nydp 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.zeiger.yml +28 -0
- data/lib/lisp/core-000.nydp +1 -1
- data/lib/lisp/core-015-documentation.nydp +6 -9
- data/lib/lisp/core-017-builtin-dox.nydp +33 -0
- data/lib/lisp/core-025-warnings.nydp +15 -0
- data/lib/lisp/core-030-syntax.nydp +38 -2
- data/lib/lisp/core-035-flow-control.nydp +2 -2
- data/lib/lisp/core-037-list-utils.nydp +7 -5
- data/lib/lisp/core-040-utils.nydp +15 -4
- data/lib/lisp/core-043-list-utils.nydp +1 -0
- data/lib/lisp/core-045-dox-utils.nydp +6 -0
- data/lib/lisp/core-050-test-runner.nydp +9 -9
- data/lib/lisp/core-070-prefix-list.nydp +2 -2
- data/lib/lisp/core-090-hook.nydp +24 -0
- data/lib/lisp/core-100-utils.nydp +38 -10
- data/lib/lisp/tests/ampersand-syntax-examples.nydp +26 -0
- data/lib/lisp/tests/boot-tests.nydp +1 -1
- data/lib/lisp/tests/collect-tests.nydp +4 -0
- data/lib/lisp/tests/destructuring-examples.nydp +18 -1
- data/lib/lisp/tests/fill-bucket-examples.nydp +46 -2
- data/lib/lisp/tests/floor-examples.nydp +58 -0
- data/lib/lisp/tests/k-examples.nydp +5 -0
- data/lib/lisp/tests/power-examples.nydp +16 -0
- data/lib/lisp/tests/string-tests.nydp +8 -0
- data/lib/lisp/tests/syntax-tests.nydp +6 -0
- data/lib/lisp/tests/zip-examples.nydp +16 -0
- data/lib/nydp.rb +6 -2
- data/lib/nydp/assignment.rb +1 -2
- data/lib/nydp/builtin/ensuring.rb +1 -2
- data/lib/nydp/builtin/greater_than.rb +2 -2
- data/lib/nydp/builtin/handle_error.rb +1 -2
- data/lib/nydp/builtin/less_than.rb +2 -2
- data/lib/nydp/builtin/math_ceiling.rb +7 -0
- data/lib/nydp/builtin/math_floor.rb +7 -0
- data/lib/nydp/builtin/math_power.rb +7 -0
- data/lib/nydp/builtin/math_round.rb +7 -0
- data/lib/nydp/builtin/parse.rb +2 -2
- data/lib/nydp/builtin/parse_in_string.rb +3 -3
- data/lib/nydp/builtin/pre_compile.rb +0 -1
- data/lib/nydp/compiler.rb +1 -1
- data/lib/nydp/cond.rb +3 -6
- data/lib/nydp/context_symbol.rb +40 -32
- data/lib/nydp/core.rb +8 -2
- data/lib/nydp/function_invocation.rb +3 -5
- data/lib/nydp/image_store.rb +21 -0
- data/lib/nydp/interpreted_function.rb +8 -12
- data/lib/nydp/lexical_context_builder.rb +19 -35
- data/lib/nydp/pair.rb +2 -1
- data/lib/nydp/parser.rb +4 -0
- data/lib/nydp/plugin.rb +15 -8
- data/lib/nydp/runner.rb +3 -3
- data/lib/nydp/symbol.rb +3 -1
- data/lib/nydp/symbol_lookup.rb +2 -2
- data/lib/nydp/truth.rb +2 -2
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp/vm.rb +47 -27
- data/spec/date_spec.rb +2 -2
- data/spec/embedded_spec.rb +16 -16
- data/spec/error_spec.rb +1 -1
- data/spec/nydp_spec.rb +13 -4
- data/spec/parser_spec.rb +63 -16
- data/spec/spec_helper.rb +1 -2
- data/spec/string_atom_spec.rb +2 -2
- data/spec/symbol_spec.rb +2 -2
- data/spec/tokeniser_spec.rb +101 -0
- metadata +16 -2
data/lib/nydp/truth.rb
CHANGED
@@ -17,8 +17,8 @@ module Nydp
|
|
17
17
|
def car ; self ; end
|
18
18
|
def cdr ; self ; end
|
19
19
|
def size ; 0 ; end
|
20
|
-
def is? other ;
|
21
|
-
def isnt? other ;
|
20
|
+
def is? other ; self == other ; end
|
21
|
+
def isnt? other ; self != other ; end
|
22
22
|
def to_s ; "" ; end
|
23
23
|
def + other ; other ; end
|
24
24
|
def copy ; self ; end
|
data/lib/nydp/version.rb
CHANGED
data/lib/nydp/vm.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Nydp
|
2
2
|
class VM
|
3
|
+
NIL = Nydp::NIL
|
3
4
|
include Helper
|
4
|
-
attr_accessor :instructions, :args, :contexts, :current_context, :locals, :unhandled_error, :last_error, :ns
|
5
|
+
attr_accessor :instructions, :args, :contexts, :current_context, :locals, :unhandled_error, :last_error, :ns, :thisi
|
5
6
|
|
6
7
|
module Finally ; end
|
7
8
|
module HandleError ; end
|
@@ -14,36 +15,56 @@ module Nydp
|
|
14
15
|
@ns = ns
|
15
16
|
end
|
16
17
|
|
17
|
-
def r2n obj
|
18
|
-
|
18
|
+
def r2n obj ; super obj, @ns ; end
|
19
|
+
|
20
|
+
def push_instructions ii, ctx
|
21
|
+
if @current_instructions && NIL != @current_instructions
|
22
|
+
@instructions.push @current_instructions
|
23
|
+
@contexts.push @current_context
|
24
|
+
end
|
25
|
+
|
26
|
+
@current_instructions = ii
|
27
|
+
@current_context = ctx
|
28
|
+
end
|
29
|
+
|
30
|
+
def push_ctx_instructions ii
|
31
|
+
if @current_instructions && NIL != @current_instructions
|
32
|
+
@instructions.push @current_instructions
|
33
|
+
@contexts.push @current_context
|
34
|
+
end
|
35
|
+
|
36
|
+
@current_instructions = ii
|
19
37
|
end
|
20
38
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
39
|
+
def thread_with_expr expr
|
40
|
+
@current_instructions = expr
|
41
|
+
thread
|
42
|
+
end
|
43
|
+
|
44
|
+
def thread
|
45
|
+
while @current_instructions
|
24
46
|
begin
|
25
|
-
|
26
|
-
|
27
|
-
|
47
|
+
if NIL == @current_instructions
|
48
|
+
@current_instructions = @instructions.pop
|
49
|
+
@current_context = @contexts.pop
|
28
50
|
else
|
29
|
-
|
30
|
-
|
51
|
+
now = @current_instructions.car
|
52
|
+
@current_instructions = @current_instructions.cdr
|
53
|
+
now.execute(self)
|
31
54
|
end
|
32
|
-
|
55
|
+
|
33
56
|
rescue StandardError => e
|
34
57
|
handle_error e
|
35
58
|
end
|
36
59
|
end
|
37
|
-
raise_unhandled_error
|
38
|
-
args.pop
|
39
|
-
end
|
40
60
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
self.unhandled_error = nil
|
61
|
+
if @unhandled_error
|
62
|
+
e = @unhandled_error
|
63
|
+
@unhandled_error = nil
|
45
64
|
raise e
|
46
65
|
end
|
66
|
+
|
67
|
+
args.pop
|
47
68
|
end
|
48
69
|
|
49
70
|
def handle_error ex
|
@@ -52,19 +73,18 @@ module Nydp
|
|
52
73
|
protecti = []
|
53
74
|
protectc = []
|
54
75
|
|
55
|
-
while (instructions.length > 0) && !(instructions.last.car.is_a? HandleError)
|
56
|
-
if instructions.last.car.is_a? Finally
|
57
|
-
protecti << instructions.last
|
58
|
-
protectc << contexts.last
|
76
|
+
while (@instructions.length > 0) && !(@instructions.last.car.is_a? HandleError)
|
77
|
+
if @instructions.last.car.is_a? Finally
|
78
|
+
protecti << @instructions.last
|
79
|
+
protectc << @contexts.last
|
59
80
|
end
|
60
81
|
|
61
|
-
instructions.pop
|
62
|
-
contexts.pop
|
82
|
+
@instructions.pop
|
83
|
+
@contexts.pop
|
63
84
|
end
|
64
85
|
|
65
86
|
while protecti.length > 0
|
66
|
-
|
67
|
-
contexts.push protectc.pop
|
87
|
+
push_instructions protecti.pop, protectc.pop
|
68
88
|
end
|
69
89
|
end
|
70
90
|
|
data/spec/date_spec.rb
CHANGED
@@ -60,7 +60,7 @@ describe Nydp::Date do
|
|
60
60
|
|
61
61
|
f.invoke vm, pair_list([d1, d0])
|
62
62
|
|
63
|
-
expect(vm.args.pop).to eq
|
63
|
+
expect(vm.args.pop).to eq d0
|
64
64
|
end
|
65
65
|
|
66
66
|
it "compares with nil" do
|
@@ -86,7 +86,7 @@ describe Nydp::Date do
|
|
86
86
|
|
87
87
|
f.invoke vm, pair_list([d0, d1])
|
88
88
|
|
89
|
-
expect(vm.args.pop).to eq
|
89
|
+
expect(vm.args.pop).to eq d1
|
90
90
|
end
|
91
91
|
|
92
92
|
it "works with builtin less-than when false" do
|
data/spec/embedded_spec.rb
CHANGED
@@ -19,40 +19,40 @@ describe Nydp::Parser do
|
|
19
19
|
let(:cocosyn) { Nydp::Symbol.mk :"colon-colon-syntax", ns }
|
20
20
|
let(:colosyn) { Nydp::Symbol.mk :"colon-syntax", ns }
|
21
21
|
|
22
|
-
def parse_string txt
|
22
|
+
def parse_string txt
|
23
23
|
reader = Nydp::StringReader.new txt
|
24
|
-
Nydp
|
24
|
+
Nydp.new_parser(ns).embedded(Nydp.new_tokeniser(reader))
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should parse empty string" do
|
28
|
-
expected = pair_list([sym('string-pieces'), Nydp::StringFragmentCloseToken.new('','
|
29
|
-
actual = parse_string "
|
28
|
+
expected = pair_list([sym('string-pieces'), Nydp::StringFragmentCloseToken.new('','')])
|
29
|
+
actual = parse_string ""
|
30
30
|
expect(actual).to eq Nydp::StringAtom.new ''
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should parse external text" do
|
34
|
-
actual = parse_string "a fluffy bunny!"
|
35
|
-
expect(actual) .to eq Nydp::StringAtom.new "a fluffy bunny"
|
36
|
-
expect(actual.inspect).to eq '"a fluffy bunny"'
|
34
|
+
actual = parse_string "a fluffy bunny!"
|
35
|
+
expect(actual) .to eq Nydp::StringAtom.new "a fluffy bunny!"
|
36
|
+
expect(actual.inspect).to eq '"a fluffy bunny!"'
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should parse a string delimited by eof" do
|
40
40
|
expected = pair_list([sym('string-pieces'), Nydp::StringFragmentCloseToken.new('a fluffy bunny!','a fluffy bunny!')])
|
41
|
-
actual = parse_string "a fluffy bunny!"
|
41
|
+
actual = parse_string "a fluffy bunny!"
|
42
42
|
expect(actual) .to eq Nydp::StringAtom.new "a fluffy bunny!"
|
43
43
|
expect(actual.inspect).to eq '"a fluffy bunny!"'
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should parse a string with embedded code, delimited by eof" do
|
47
47
|
x1 = sym('string-pieces')
|
48
|
-
x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','
|
48
|
+
x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','a fluffy bunny! ~')
|
49
49
|
x2 = Nydp::StringAtom.new(x2.string, x2)
|
50
50
|
x3 = sym('expr')
|
51
51
|
x4 = Nydp::StringFragmentCloseToken.new(' a purple cow!',' a purple cow!')
|
52
52
|
x4 = Nydp::StringAtom.new(x4.string, x4)
|
53
53
|
|
54
54
|
expected = pair_list([x1,x2,x3,x4])
|
55
|
-
actual = parse_string "a fluffy bunny! ~expr a purple cow!"
|
55
|
+
actual = parse_string "a fluffy bunny! ~expr a purple cow!"
|
56
56
|
expect(actual).to eq expected
|
57
57
|
end
|
58
58
|
|
@@ -63,14 +63,14 @@ describe Nydp::Parser do
|
|
63
63
|
n4 = sym(:zop)
|
64
64
|
|
65
65
|
x1 = sym('string-pieces')
|
66
|
-
x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','
|
66
|
+
x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','a fluffy bunny! ~')
|
67
67
|
x2 = Nydp::StringAtom.new(x2.string, x2)
|
68
68
|
x3 = pair_list [n1, n2, n3, n4]
|
69
69
|
x4 = Nydp::StringFragmentCloseToken.new(' a purple cow!',' a purple cow!')
|
70
70
|
x4 = Nydp::StringAtom.new(x4.string, x4)
|
71
71
|
|
72
72
|
expected = pair_list([x1,x2,x3,x4])
|
73
|
-
actual = parse_string
|
73
|
+
actual = parse_string 'a fluffy bunny! ~(foo bar "an embedded bunny :)" zop) a purple cow!'
|
74
74
|
expect(actual).to eq expected
|
75
75
|
end
|
76
76
|
|
@@ -79,7 +79,7 @@ describe Nydp::Parser do
|
|
79
79
|
e2 = sym(:bunny)
|
80
80
|
|
81
81
|
s1 = sym('string-pieces')
|
82
|
-
s2 = Nydp::StringFragmentToken.new('a rather ','
|
82
|
+
s2 = Nydp::StringFragmentToken.new('a rather ','a rather ~')
|
83
83
|
s2 = Nydp::StringAtom.new(s2.string, s2)
|
84
84
|
s3 = pair_list [e1, e2]
|
85
85
|
s4 = Nydp::StringFragmentCloseToken.new(' bunny :)',' bunny :)"')
|
@@ -91,19 +91,19 @@ describe Nydp::Parser do
|
|
91
91
|
n4 = sym(:zop)
|
92
92
|
|
93
93
|
x1 = sym('string-pieces')
|
94
|
-
x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','
|
94
|
+
x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','a fluffy bunny! ~')
|
95
95
|
x2 = Nydp::StringAtom.new(x2.string, x2)
|
96
96
|
x3 = pair_list [n1, n2, n3, n4]
|
97
97
|
x4 = Nydp::StringFragmentCloseToken.new(' a purple cow!',' a purple cow!')
|
98
98
|
x4 = Nydp::StringAtom.new(x4.string, x4)
|
99
99
|
|
100
100
|
expected = pair_list([x1,x2,x3,x4])
|
101
|
-
actual = parse_string "a fluffy bunny! ~(foo bar \"a rather ~(describe bunny) bunny :)\" zop) a purple cow!"
|
101
|
+
actual = parse_string "a fluffy bunny! ~(foo bar \"a rather ~(describe bunny) bunny :)\" zop) a purple cow!"
|
102
102
|
expect(actual).to eq expected
|
103
103
|
end
|
104
104
|
|
105
105
|
it "parses a string that looks like html with little bits of embedded code in it" do
|
106
|
-
parsed = parse_string "<div id='item_~{id}'><label>~{data-label-1}</label> ~{data-content-1}</div>"
|
106
|
+
parsed = parse_string "<div id='item_~{id}'><label>~{data-label-1}</label> ~{data-content-1}</div>"
|
107
107
|
expect(parsed.inspect).to eq '(string-pieces "<div id=\'item_" (brace-list id) "\'><label>" (brace-list data-label-1) "</label> " (brace-list data-content-1) "</div>")'
|
108
108
|
end
|
109
109
|
end
|
data/spec/error_spec.rb
CHANGED
@@ -21,7 +21,7 @@ describe Nydp::VM do
|
|
21
21
|
expect(error).to be_a Nydp::Error
|
22
22
|
expect(error.message).to eq "failed to eval dflkjdgjeirgjeoi"
|
23
23
|
|
24
|
-
expect(error.cause).to be_a Nydp::
|
24
|
+
expect(error.cause).to be_a Nydp::Symbol::Unbound
|
25
25
|
expect(error.cause.message).to eq "unbound symbol: dflkjdgjeirgjeoi"
|
26
26
|
|
27
27
|
expect(vm.unhandled_error).to eq nil
|
data/spec/nydp_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Nydp do
|
4
|
-
let(:parser) { Nydp
|
4
|
+
let(:parser) { Nydp.new_parser(ns) }
|
5
5
|
let(:vm) { Nydp::VM.new(ns) }
|
6
6
|
|
7
7
|
def run txt
|
@@ -9,6 +9,10 @@ describe Nydp do
|
|
9
9
|
Nydp.eval_src ns, txt
|
10
10
|
end
|
11
11
|
|
12
|
+
it "invokes a zero-arg function" do
|
13
|
+
expect(run('(to-string)').to_s).to eq ""
|
14
|
+
end
|
15
|
+
|
12
16
|
it "should make a symbol from a string" do
|
13
17
|
expect(run '(sym "the-family")').to eq sym(:"the-family")
|
14
18
|
end
|
@@ -47,8 +51,8 @@ describe Nydp do
|
|
47
51
|
|
48
52
|
it "should compare integers" do
|
49
53
|
expect(run "(> 13 17)").to eq Nydp::NIL
|
50
|
-
expect(run "(> 29 23)").to eq
|
51
|
-
expect(run "(< 13 17)").to eq
|
54
|
+
expect(run "(> 29 23)").to eq 23
|
55
|
+
expect(run "(< 13 17)").to eq 17
|
52
56
|
expect(run "(< 29 23)").to eq Nydp::NIL
|
53
57
|
end
|
54
58
|
|
@@ -80,7 +84,12 @@ describe Nydp do
|
|
80
84
|
end
|
81
85
|
|
82
86
|
it "should recurse without consuming extra memory" do
|
83
|
-
program = "(assign f1 (fn (x acc)
|
87
|
+
program = "(assign f1 (fn (x acc)
|
88
|
+
(cond (< x 1)
|
89
|
+
(vm-info)
|
90
|
+
(f1 (- x 1)
|
91
|
+
(+ x acc)))))
|
92
|
+
(f1 1000 0)"
|
84
93
|
expected = parse "((contexts . 0) (instructions . 0) (args . 0))"
|
85
94
|
expect(run program).to eq expected
|
86
95
|
end
|
data/spec/parser_spec.rb
CHANGED
@@ -19,25 +19,14 @@ describe Nydp::Parser do
|
|
19
19
|
let(:dotsyn) { Nydp::Symbol.mk :"dot-syntax", ns }
|
20
20
|
let(:cocosyn) { Nydp::Symbol.mk :"colon-colon-syntax", ns }
|
21
21
|
let(:colosyn) { Nydp::Symbol.mk :"colon-syntax", ns }
|
22
|
+
let(:string_pieces) { Nydp::Symbol.mk :"string-pieces", ns }
|
22
23
|
|
23
24
|
it "should return a stream of tokens" do
|
24
25
|
reader = Nydp::StringReader.new ""
|
25
|
-
t = Nydp
|
26
|
+
t = Nydp.new_tokeniser reader
|
26
27
|
expect(t.next_token).to eq nil
|
27
28
|
end
|
28
29
|
|
29
|
-
it "should return another stream of tokens" do
|
30
|
-
reader = Nydp::StringReader.new "(a b c 1 2 3)"
|
31
|
-
t = Nydp::Tokeniser.new reader
|
32
|
-
tt = []
|
33
|
-
tok = t.next_token
|
34
|
-
while tok
|
35
|
-
tt << tok
|
36
|
-
tok = t.next_token
|
37
|
-
end
|
38
|
-
expect(tt).to eq [[:left_paren, ""], [:symbol, "a"], [:symbol, "b"], [:symbol, "c"], [:number, 1.0], [:number, 2.0], [:number, 3.0], [:right_paren]]
|
39
|
-
end
|
40
|
-
|
41
30
|
it "should parse an empty expression" do
|
42
31
|
expect(parse "").to be_nil
|
43
32
|
end
|
@@ -75,8 +64,11 @@ describe Nydp::Parser do
|
|
75
64
|
expect(parse "(1 2 3 . 4)").to eq pair_list([1, 2, 3], 4)
|
76
65
|
end
|
77
66
|
|
67
|
+
it "should parse an improper list containing symbols" do
|
68
|
+
expect(parse "(foo foo . bar)").to eq pair_list([foo, foo], bar)
|
69
|
+
end
|
70
|
+
|
78
71
|
it "should parse a string" do
|
79
|
-
s1 = sym 'string-pieces'
|
80
72
|
s2 = Nydp::StringFragmentCloseToken.new "hello there", '"hello there"'
|
81
73
|
|
82
74
|
x1 = 1
|
@@ -101,7 +93,6 @@ describe Nydp::Parser do
|
|
101
93
|
end
|
102
94
|
|
103
95
|
it "should not get confused by embedded lisp in a string" do
|
104
|
-
s1 = sym 'string-pieces'
|
105
96
|
s2 = Nydp::StringFragmentCloseToken.new "hello (1 2 3) there", '"hello (1 2 3) there"'
|
106
97
|
|
107
98
|
x1 = 1
|
@@ -114,7 +105,6 @@ describe Nydp::Parser do
|
|
114
105
|
end
|
115
106
|
|
116
107
|
it "should handle escaped quotes inside a string" do
|
117
|
-
s1 = sym 'string-pieces'
|
118
108
|
s2 = Nydp::StringFragmentCloseToken.new "hello there \"jimmy\"", '"hello there \"jimmy\""'
|
119
109
|
|
120
110
|
x1 = 1
|
@@ -255,6 +245,37 @@ describe Nydp::Parser do
|
|
255
245
|
expect(parse "(a b (c) d)").to eq pair_list([a, b, pair_list([c]), d])
|
256
246
|
end
|
257
247
|
|
248
|
+
it "parses a simple string" do
|
249
|
+
expect(parse '"foo"').to eq Nydp::StringAtom.new("foo")
|
250
|
+
end
|
251
|
+
|
252
|
+
it "parses a string with a simple interpolation" do
|
253
|
+
str = Nydp::StringAtom.new("foo ")
|
254
|
+
empty = Nydp::StringAtom.new("")
|
255
|
+
expect(parse '"foo ~foo"').to eq pair_list([string_pieces, str, foo, empty])
|
256
|
+
end
|
257
|
+
|
258
|
+
it "parses a string with a more complex interpolation" do
|
259
|
+
strf = Nydp::StringAtom.new("foo ")
|
260
|
+
strb = Nydp::StringAtom.new(" bar")
|
261
|
+
expect(parse '"foo ~(foo bar) bar"').to eq pair_list([string_pieces, strf, pair_list([foo, bar]), strb])
|
262
|
+
end
|
263
|
+
|
264
|
+
it "parses a string with an interpolation containing a nested interpolation" do
|
265
|
+
strf = Nydp::StringAtom.new("foo ")
|
266
|
+
strb = Nydp::StringAtom.new(" bar")
|
267
|
+
|
268
|
+
nested = pair_list [string_pieces, strf, foo, strb]
|
269
|
+
expr = pair_list [foo, nested, bar]
|
270
|
+
|
271
|
+
expect(parse '"foo ~(foo "foo ~foo bar" bar) bar"').to eq pair_list([string_pieces, strf, expr, strb])
|
272
|
+
end
|
273
|
+
|
274
|
+
it "parses a string with only an interpolation" do
|
275
|
+
empty = Nydp::StringAtom.new("")
|
276
|
+
expect(parse '"~foo"').to eq pair_list([string_pieces, empty, foo, empty])
|
277
|
+
end
|
278
|
+
|
258
279
|
it "should even parse comments" do
|
259
280
|
txt = "(def foo (bar)
|
260
281
|
; here's a comment
|
@@ -267,4 +288,30 @@ describe Nydp::Parser do
|
|
267
288
|
expr = pair_list([fdef, foo, fbar, c1, fzab])
|
268
289
|
expect(parse txt).to eq expr
|
269
290
|
end
|
291
|
+
|
292
|
+
it "parses an expression with whitespace before closing paren" do
|
293
|
+
txt = <<NYDP
|
294
|
+
(def plugin-end (name) (assign this-plugin nil ) (chapter-end))
|
295
|
+
NYDP
|
296
|
+
expect(parse(txt).to_a.inspect).to eq "[def, plugin-end, (name), (assign this-plugin nil), (chapter-end)]"
|
297
|
+
end
|
298
|
+
|
299
|
+
it "parses a more complete expression" do
|
300
|
+
txt = <<NYDP
|
301
|
+
(mac def (name args . body)
|
302
|
+
; define a new function in the global namespace
|
303
|
+
(chapter nydp-core)
|
304
|
+
(define-def-expr name args (filter-forms (build-def-hash (hash)) body)))
|
305
|
+
NYDP
|
306
|
+
parsed = parse(txt).to_a
|
307
|
+
expect(parsed[0]).to eq sym("mac")
|
308
|
+
expect(parsed[1]).to eq sym("def")
|
309
|
+
args = parsed[2].to_a
|
310
|
+
expect(args[0]).to eq sym("name")
|
311
|
+
expect(args[1]).to eq sym("args")
|
312
|
+
expect(args[2]).to be_nil
|
313
|
+
expect(parsed[2].cdr.cdr).to eq sym("body")
|
314
|
+
expect(parsed[3].to_a).to eq [sym("comment"), Nydp::StringAtom.new("define a new function in the global namespace")]
|
315
|
+
expect(parsed[4].to_a).to eq [sym("chapter"), sym("nydp-core")]
|
316
|
+
end
|
270
317
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,8 +7,7 @@ module SpecHelper
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def parse txt
|
10
|
-
|
11
|
-
Nydp::Parser.new(ns).expression(Nydp::Tokeniser.new reader)
|
10
|
+
Nydp.new_parser(ns).expression(Nydp.new_tokeniser Nydp::StringReader.new(txt))
|
12
11
|
end
|
13
12
|
|
14
13
|
def pair_list xs, last=Nydp::NIL
|
data/spec/string_atom_spec.rb
CHANGED
@@ -32,7 +32,7 @@ describe Nydp::StringAtom do
|
|
32
32
|
|
33
33
|
f.invoke vm, pair_list([foo, bar])
|
34
34
|
|
35
|
-
expect(vm.args.pop).to eq
|
35
|
+
expect(vm.args.pop).to eq bar
|
36
36
|
end
|
37
37
|
|
38
38
|
it "works with builtin greater-than when false" do
|
@@ -48,7 +48,7 @@ describe Nydp::StringAtom do
|
|
48
48
|
|
49
49
|
f.invoke vm, pair_list([bar, foo])
|
50
50
|
|
51
|
-
expect(vm.args.pop).to eq
|
51
|
+
expect(vm.args.pop).to eq foo
|
52
52
|
end
|
53
53
|
|
54
54
|
it "works with builtin less-than when false" do
|