nil 1.0.4 → 1.0.5
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.
- data/README.md +13 -2
- data/TODO.md +0 -4
- data/lib/nil/interpreter.rb +19 -2
- data/lib/nil/macro.rb +10 -2
- data/lib/nil/version.rb +1 -1
- data/test/nil_test.rb +36 -12
- metadata +2 -2
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# nil
|
2
2
|
|
3
|
-
nil is a brain**** language macro language and interpreter.
|
3
|
+
nil is a brain**** language macro language and interpreter.
|
4
4
|
|
5
5
|
## Macro language
|
6
6
|
|
@@ -43,6 +43,17 @@ looking like such are comments:
|
|
43
43
|
|
44
44
|
Comments *must* include both semicolons.
|
45
45
|
|
46
|
+
### Modes
|
47
|
+
|
48
|
+
The original brain**** specification calls for buffers to be output as ASCII
|
49
|
+
text. However, sometimes outputting numbers is more useful. Nil allows modes to
|
50
|
+
be set. In the nil code, the line:
|
51
|
+
|
52
|
+
.mode(mode)
|
53
|
+
|
54
|
+
Will be used to set the mode. The `mode` can either be `num` or `ascii`. The
|
55
|
+
default mode is `ascii`.
|
56
|
+
|
46
57
|
## Interpreter
|
47
58
|
|
48
59
|
nil is also a brain**** interpreter. It does the interpreting in its own special
|
@@ -97,7 +108,7 @@ interpreter.compile code
|
|
97
108
|
interpreter.run
|
98
109
|
```
|
99
110
|
|
100
|
-
|
111
|
+
Run `nil -h` for command line tool usage.
|
101
112
|
|
102
113
|
## Contributing
|
103
114
|
|
data/TODO.md
CHANGED
data/lib/nil/interpreter.rb
CHANGED
@@ -2,10 +2,22 @@ module Nil
|
|
2
2
|
class Interpreter
|
3
3
|
attr_reader :compiled_ruby
|
4
4
|
|
5
|
+
def self.mode=(x)
|
6
|
+
@@mode = x
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.mode
|
10
|
+
@@mode
|
11
|
+
end
|
12
|
+
|
5
13
|
def run
|
6
14
|
eval(@compiled_ruby)
|
7
15
|
end
|
8
16
|
|
17
|
+
def initialize
|
18
|
+
@@mode = 'ascii'
|
19
|
+
end
|
20
|
+
|
9
21
|
def handle_command(command, count)
|
10
22
|
case command[0]
|
11
23
|
when '+'
|
@@ -21,13 +33,18 @@ module Nil
|
|
21
33
|
when ']'
|
22
34
|
"end\n"
|
23
35
|
when '.'
|
24
|
-
|
36
|
+
if @@mode == 'num'
|
37
|
+
"puts stack[sp]\n"
|
38
|
+
else
|
39
|
+
"puts stack[sp].chr\n"
|
40
|
+
end
|
25
41
|
when ','
|
26
42
|
"stack[sp] = gets[0]\n"
|
27
43
|
end
|
28
44
|
end
|
29
45
|
|
30
|
-
def compile(code)
|
46
|
+
def compile(code, mode)
|
47
|
+
@@mode = mode
|
31
48
|
@compiled_ruby = <<RB
|
32
49
|
sp = 0
|
33
50
|
stack = [0] * 10_000
|
data/lib/nil/macro.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module Nil
|
2
2
|
class MacroParser
|
3
|
-
attr_accessor :original_code, :compiled_code
|
3
|
+
attr_accessor :original_code, :compiled_code, :mode
|
4
4
|
|
5
5
|
def initialize
|
6
|
-
# This method intentionally left blank.
|
7
6
|
end
|
8
7
|
|
9
8
|
def compile_subroutines(code)
|
@@ -27,6 +26,13 @@ module Nil
|
|
27
26
|
code.gsub(sub_def_regex, '')
|
28
27
|
end
|
29
28
|
|
29
|
+
def interpret_mode_definition(code)
|
30
|
+
code.match /\.mode\((ascii|num)\)/i do |m|
|
31
|
+
$1 == 'num' ? Nil::Interpreter.mode = 'num' : Nil::Interpreter.mode = 'ascii'
|
32
|
+
end
|
33
|
+
code.gsub(/\.mode\((ascii|num)\)/i, '')
|
34
|
+
end
|
35
|
+
|
30
36
|
def expand_included_files(code)
|
31
37
|
c = code
|
32
38
|
include_regex = Regexp.new '\.include\(([^\)]+)\)'
|
@@ -51,6 +57,8 @@ module Nil
|
|
51
57
|
|
52
58
|
compiled_code.gsub!(/\s/, '')
|
53
59
|
|
60
|
+
compiled_code = interpret_mode_definition(compiled_code)
|
61
|
+
|
54
62
|
compiled_code = expand_included_files(compiled_code)
|
55
63
|
|
56
64
|
compiled_code = strip_comments(compiled_code)
|
data/lib/nil/version.rb
CHANGED
data/test/nil_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'nil'
|
2
2
|
require 'riot'
|
3
3
|
|
4
|
-
|
4
|
+
Riot.pretty_dots
|
5
5
|
|
6
6
|
BOILERPLATE = <<RB
|
7
7
|
sp = 0
|
@@ -10,19 +10,23 @@ RB
|
|
10
10
|
|
11
11
|
context "Interpreter" do
|
12
12
|
setup { Nil::Interpreter.new }
|
13
|
-
|
13
|
+
|
14
|
+
asserts("invalid characters in code cause failure") { topic.compile "a++", 'num' }.raises SyntaxError
|
15
|
+
|
14
16
|
asserts("creates boilerplate code") { topic.compiled_ruby == BOILERPLATE }
|
15
|
-
|
16
|
-
asserts("handles
|
17
|
-
asserts("handles
|
18
|
-
asserts("handles
|
19
|
-
asserts("handles
|
20
|
-
asserts("handles
|
21
|
-
asserts("handles
|
22
|
-
asserts("handles
|
17
|
+
|
18
|
+
asserts("handles . in numerical mode") { topic.compile('.', 'num') == (BOILERPLATE + "puts stack[sp]\n") }
|
19
|
+
asserts("handles . in ascii mode") { topic.compile('.', 'ascii') == (BOILERPLATE + "puts stack[sp].chr\n") }
|
20
|
+
asserts("handles ,") { topic.compile(',', 'num') == (BOILERPLATE + "stack[sp] = gets[0]\n") }
|
21
|
+
asserts("handles >") { topic.compile('>', 'num') == (BOILERPLATE + "sp += 1\n") }
|
22
|
+
asserts("handles <") { topic.compile('<', 'num') == (BOILERPLATE + "sp -= 1\n") }
|
23
|
+
asserts("handles +") { topic.compile('+', 'num') == (BOILERPLATE + "stack[sp] += 1\n") }
|
24
|
+
asserts("handles -") { topic.compile('-', 'num') == (BOILERPLATE + "stack[sp] -= 1\n") }
|
25
|
+
asserts("handles [") { topic.compile('[', 'num') == (BOILERPLATE + "while stack[sp] != 0\n" ) }
|
26
|
+
asserts("handles ]") { topic.compile(']', 'num') == (BOILERPLATE + "end\n" ) }
|
23
27
|
|
24
28
|
asserts("handles multiple operators smartly") do
|
25
|
-
code = topic.compile "++++---->>>><<<<"
|
29
|
+
code = topic.compile "++++---->>>><<<<", 'num'
|
26
30
|
code == BOILERPLATE + <<CODE
|
27
31
|
stack[sp] += 4
|
28
32
|
stack[sp] -= 4
|
@@ -33,7 +37,7 @@ CODE
|
|
33
37
|
|
34
38
|
asserts("handles multiple printing statements") do
|
35
39
|
code = "++++.>+++."
|
36
|
-
code = topic.compile(code)
|
40
|
+
code = topic.compile(code, 'num')
|
37
41
|
code == BOILERPLATE + <<CODE
|
38
42
|
stack[sp] += 4
|
39
43
|
puts stack[sp]
|
@@ -71,6 +75,26 @@ context "MacroParser" do
|
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
78
|
+
context "Modes" do
|
79
|
+
asserts("that numerical mode is correctly set") do
|
80
|
+
code = ".mode(num)"
|
81
|
+
compiled = topic.parse code
|
82
|
+
Nil::Interpreter.mode == 'num'
|
83
|
+
end
|
84
|
+
|
85
|
+
asserts("that ascii mode is correctly set") do
|
86
|
+
code = ".mode(ascii)"
|
87
|
+
compiled = topic.parse code
|
88
|
+
Nil::Interpreter.mode == 'ascii'
|
89
|
+
end
|
90
|
+
|
91
|
+
asserts("that ascii mode is set by default") do
|
92
|
+
code = "+"
|
93
|
+
compiled = topic.parse code
|
94
|
+
Nil::Interpreter.mode == 'ascii'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
74
98
|
context "Subroutines" do
|
75
99
|
asserts("that subroutines are expanded") do
|
76
100
|
code = ":test{++--><}++test:"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: trollop
|