nil 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .*.sw[a-z]
19
+ *.un~
20
+ Session.vim
21
+
22
+
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm gemset use nil
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'pry'
5
+ gem 'riot'
6
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Wuffers Lightwolf
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,96 @@
1
+ # nil
2
+
3
+ nil is a brain**** language macro language and interpreter. ## Installation
4
+
5
+ ## Macro language
6
+
7
+ nil supports a few macros that get expanded to vanilla brain**** code.
8
+
9
+ ### Numbered commands
10
+
11
+ The commands `>`, `<`, `+`, and `-` can be given a number to repeat that
12
+ command. For example:
13
+
14
+ `+5` will be expanded into `++++++`
15
+
16
+ ### Macros
17
+
18
+ Macros can be defined and referenced. However, since they are only expanded,
19
+ they cannot recurse.
20
+
21
+ Macros are defined in the form of `:sub_name{code}` and are called in the form
22
+ of `sub_name:`
23
+
24
+ Example:
25
+
26
+ :add_two{++}add_two:
27
+
28
+ will be expanded to:
29
+
30
+ ++
31
+
32
+ ### Including other files
33
+
34
+ Other files can be included in the current one. Files are included in the format
35
+ of: `.include(file.nil)`
36
+
37
+ ### Comments
38
+
39
+ Unlike regular brain**** where everything is treated as a comment, only lines
40
+ looking like such are comments:
41
+
42
+ ;this is a comment;
43
+
44
+ Comments *must* include both semicolons.
45
+
46
+ ## Interpreter
47
+
48
+ nil is also a brain**** interpreter. It does the interpreting in its own special
49
+ way, though:
50
+
51
+ 1. It uses the MacroCompiler to compile the code
52
+ 2. It translates the brain**** to Ruby code
53
+ 3. It then runs the Ruby code it generated.
54
+
55
+ The interpreter tries to be smart about the way it translates the code, for
56
+ instance:
57
+
58
+ `+++++` will be translated to:
59
+
60
+ sp += 5
61
+
62
+ instead of
63
+
64
+ sp += 1
65
+ sp += 1
66
+ sp += 1
67
+ sp += 1
68
+ sp += 1
69
+
70
+ ## Installing
71
+
72
+ Add this line to your application's Gemfile:
73
+
74
+ gem 'nil'
75
+
76
+ And then execute:
77
+
78
+ $ bundle
79
+
80
+ Or install it yourself as:
81
+
82
+ $ gem install nil
83
+
84
+ ## Usage
85
+
86
+ ```
87
+ $ nil file.nil
88
+ ```
89
+
90
+ ## Contributing
91
+
92
+ 1. Fork it
93
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
94
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
95
+ 4. Push to the branch (`git push origin my-new-feature`)
96
+ 5. Create new Pull Request
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ desc "Run tests"
7
+ task :test do
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "test"
10
+ t.pattern = "test/**/*_test.rb"
11
+ t.verbose = false
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'pp'
2
+ require 'nil/version'
3
+ require 'nil/interpreter'
4
+ require 'nil/macro'
5
+
6
+ module Nil
7
+ COMMANDS = %w(. , + - > < [ ])
8
+ end
@@ -0,0 +1,63 @@
1
+ module Nil
2
+ class Interpreter
3
+ attr_reader :compiled_ruby
4
+
5
+ def run
6
+ eval(@compiled_ruby)
7
+ end
8
+
9
+ def handle_non_multi_command(char)
10
+ case char
11
+ when '['
12
+ "while stack[sp] != 0\n"
13
+ when ']'
14
+ "end\n"
15
+ when '.'
16
+ "print stack[sp]\n"
17
+ when ','
18
+ "stack[sp] = gets[0]\n"
19
+ end
20
+ end
21
+
22
+ def handle_multi_command(command)
23
+ count = command.length
24
+ case command[0]
25
+ when '+'
26
+ "stack[sp] += #{count}\n"
27
+ when '-'
28
+ "stack[sp] -= #{count}\n"
29
+ when '>'
30
+ "sp += #{count}\n"
31
+ when '<'
32
+ "sp -= #{count}\n"
33
+ end
34
+ end
35
+
36
+ def compile(code)
37
+ @compiled_ruby = <<RB
38
+ sp = 0
39
+ stack = [0] * 10_000
40
+ RB
41
+
42
+ code.each_char do |c|
43
+ if !COMMANDS.include? c
44
+ raise SyntaxError, "Invalid characters in code."
45
+ end
46
+ end
47
+
48
+ while code != ""
49
+ multi_command = code.match(/([><\-\+])(\1*)/)
50
+
51
+ if multi_command == nil
52
+ ruby = handle_non_multi_command(code[0])
53
+ @compiled_ruby << ruby
54
+ code[0] = ""
55
+ else
56
+ @compiled_ruby << handle_multi_command(multi_command.to_s)
57
+ code.sub!(multi_command.to_s, "")
58
+ end
59
+ end
60
+ @compiled_ruby
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,68 @@
1
+ module Nil
2
+ class MacroParser
3
+ attr_accessor :original_code, :compiled_code
4
+
5
+ def initialize
6
+ # This method intentionally left blank.
7
+ end
8
+
9
+ def compile_subroutines(code)
10
+ # TODO: Throw an error when trying to define a subroutine that calls
11
+ # itself.
12
+ subroutines = {}
13
+ sub_def_regex = Regexp.new ':(?<sub-name>[a-zA-Z0-9_]+)\{(?<sub-code>[><\-\+.,A-Za-z0-9:]+)\}'
14
+ sub_call_regex = Regexp.new '([a-zA-Z0-9_]+):'
15
+ code.scan(sub_def_regex).map do |sub|
16
+ subroutines[sub[0]] = sub[1]
17
+ end
18
+
19
+ subroutines.each do |s, c|
20
+ if c =~ sub_call_regex
21
+ raise SyntaxError, "Error: Recursive subroutine."
22
+ end
23
+ end
24
+
25
+ code.gsub!(sub_call_regex) do |m|
26
+ subroutines[$1]
27
+ end
28
+
29
+ code.gsub(sub_def_regex, '')
30
+ end
31
+
32
+ def expand_included_files(code)
33
+ c = code
34
+ include_regex = Regexp.new '\.include\(([^\)]+)\)'
35
+ included_code = ""
36
+ files = c.scan(include_regex).flatten
37
+ files.each do |f|
38
+ included_code << File.open(f, 'r').read.strip
39
+ end
40
+ c.gsub!(include_regex, '')
41
+ c = included_code + c
42
+ c
43
+ end
44
+
45
+ def strip_comments(code)
46
+ code.gsub(/;(.+);/, '')
47
+ end
48
+
49
+ def parse(code)
50
+ @original_code = code
51
+
52
+ compiled_code = @original_code
53
+
54
+ compiled_code.gsub!(/\s/, '')
55
+
56
+ compiled_code = expand_included_files(compiled_code)
57
+
58
+ compiled_code = strip_comments(compiled_code)
59
+
60
+ compiled_code.gsub!(/([\+-<>])(\d+)/) do |m| # Parse the numerical commands.
61
+ $1 * $2.to_i
62
+ end
63
+
64
+ compiled_code = compile_subroutines(compiled_code)
65
+ compiled_code
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ module Nil
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nil/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Wuffers Lightwolf"]
6
+ gem.email = ["wuffers.lightwolf@me.com"]
7
+ gem.description = %q{A brain**** macro language and interpreter}
8
+ gem.summary = %q{A macro language/interpreter for brain****}
9
+ gem.homepage = "http://github.com/w-x-l/nil"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "nil"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Nil::VERSION
17
+ end
@@ -0,0 +1 @@
1
+ >>
@@ -0,0 +1,103 @@
1
+ require 'nil'
2
+ require 'riot'
3
+
4
+ Riot.pretty_dots
5
+
6
+ BOILERPLATE = <<RB
7
+ sp = 0
8
+ stack = Array.new 10_000
9
+ RB
10
+
11
+ context "Interpreter" do
12
+ setup { Nil::Interpreter.new }
13
+ asserts("invalid characters in code cause failure") { topic.compile "a++" }.raises SyntaxError
14
+ asserts("creates boilerplate code") { topic.compiled_ruby == BOILERPLATE }
15
+ asserts("handles .") { topic.compile('.') == (BOILERPLATE + "print stack[sp]\n") }
16
+ asserts("handles ,") { topic.compile(',') == (BOILERPLATE + "stack[sp] = gets[0]\n") }
17
+ asserts("handles >") { topic.compile('>') == (BOILERPLATE + "sp += 1\n") }
18
+ asserts("handles <") { topic.compile('<') == (BOILERPLATE + "sp -= 1\n") }
19
+ asserts("handles +") { topic.compile('+') == (BOILERPLATE + "stack[sp] += 1\n") }
20
+ asserts("handles -") { topic.compile('-') == (BOILERPLATE + "stack[sp] -= 1\n") }
21
+ asserts("handles [") { topic.compile('[') == (BOILERPLATE + "while stack[sp] != 0\n" ) }
22
+ asserts("handles ]") { topic.compile(']') == (BOILERPLATE + "end\n" ) }
23
+ asserts("handles multiple operators smartly") do
24
+ code = topic.compile "++++---->>>><<<<"
25
+ code == BOILERPLATE + <<CODE
26
+ stack[sp] += 4
27
+ stack[sp] -= 4
28
+ sp += 4
29
+ sp -= 4
30
+ CODE
31
+ end
32
+ end
33
+
34
+ context "MacroParser" do
35
+ setup { Nil::MacroParser.new }
36
+
37
+ context "Basics" do
38
+ asserts("that the original code equals code passed to parser") do
39
+ code = "++><>--" # Just some random stuff
40
+ topic.parse code
41
+ compiled_original_code = topic.original_code
42
+ code == compiled_original_code
43
+ end
44
+ end
45
+
46
+ context "Numbered commands" do
47
+ asserts("that numbered commands are expanded") do
48
+ code = "+5-5>5<5"
49
+ compiled_code = topic.parse code
50
+ compiled_code == "+++++----->>>>><<<<<"
51
+ end
52
+ end
53
+
54
+ context "Subroutines" do
55
+ asserts("that subroutines are expanded") do
56
+ code = ":test{++--><}++test:"
57
+ compiled_code = topic.parse code
58
+ compiled_code == "++++--><"
59
+ end
60
+
61
+ asserts("that subroutines contaning numbered commands are expanded") do
62
+ code = ":test{+5}test:"
63
+ compiled_code = topic.parse code
64
+ compiled_code == "+++++"
65
+ end
66
+
67
+ asserts("that recursive subroutines throw exceptions") { topic.parse ":sub{sub:}sub:" }.raises(SyntaxError)
68
+ end
69
+
70
+ context "Whitespace & Comments" do
71
+ asserts("that whitespace is stripped") do
72
+ code = <<CODE
73
+ ++ --++
74
+ :add{
75
+ ++
76
+ }
77
+ add:
78
+ CODE
79
+ compiled_code = topic.parse code
80
+ compiled_code == "++--++++"
81
+ end
82
+
83
+ asserts("that comments are stripped") do
84
+ code = ";this is a comment; ++--"
85
+ compiled_code = topic.parse code
86
+ compiled_code == "++--"
87
+ end
88
+ end
89
+
90
+ context "File includes" do
91
+ asserts("that other files are included") do
92
+ code = ".include(test/test.nil)--"
93
+ compiled_code = topic.parse code
94
+ compiled_code == "++--"
95
+ end
96
+
97
+ asserts("that multiple files are included correctly") do
98
+ code = ".include(test/test.nil).include(test/another.nil)--"
99
+ compiled_code = topic.parse code
100
+ compiled_code == "++>>--"
101
+ end
102
+ end
103
+ end
@@ -0,0 +1 @@
1
+ ++
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nil
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wuffers Lightwolf
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-29 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A brain**** macro language and interpreter
15
+ email:
16
+ - wuffers.lightwolf@me.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - .rvmrc
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - lib/nil.rb
28
+ - lib/nil/interpreter.rb
29
+ - lib/nil/macro.rb
30
+ - lib/nil/version.rb
31
+ - nil.gemspec
32
+ - test/another.nil
33
+ - test/nil_test.rb
34
+ - test/test.nil
35
+ homepage: http://github.com/w-x-l/nil
36
+ licenses: []
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.23
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: A macro language/interpreter for brain****
59
+ test_files:
60
+ - test/another.nil
61
+ - test/nil_test.rb
62
+ - test/test.nil