dslisprb 0.0.4 → 0.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/CHANGELOG +14 -0
- data/Rakefile +1 -1
- data/lib/dslisprb.rb +25 -8
- data/lib/dslisprb.rb~ +27 -11
- data/spec/ast.rb +5 -1
- data/spec/ast.rb~ +10 -2
- data/spec/defun.rb +38 -0
- data/spec/defun.rb~ +38 -0
- data/spec/flowcontrol.rb~ +3 -8
- data/spec/functions.rb +4 -0
- data/spec/functions.rb~ +29 -0
- data/spec/variable.rb +8 -0
- data/spec/variable.rb~ +9 -1
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
0.0.5 Fix list processing functions when recieve nil arguments
|
2
|
+
|
3
|
+
Optional arguments for functions
|
4
|
+
|
5
|
+
Implemented reverse function
|
6
|
+
|
7
|
+
Implemented inspect function
|
8
|
+
|
9
|
+
Implemented let
|
10
|
+
|
11
|
+
Fixed parse of nested quotes
|
12
|
+
|
13
|
+
Fixed reference of variables for recursive calls
|
14
|
+
|
1
15
|
0.0.4 Implemented apply and funcall
|
2
16
|
|
3
17
|
Fix of variable assignments on lambda calla
|
data/Rakefile
CHANGED
data/lib/dslisprb.rb
CHANGED
@@ -31,8 +31,7 @@ class DsLisp
|
|
31
31
|
elsif code == :T
|
32
32
|
"true"
|
33
33
|
elsif Symbol === code
|
34
|
-
|
35
|
-
name_convert(code).to_s
|
34
|
+
"eval(\"#{name_convert(code).to_s}\")"
|
36
35
|
else
|
37
36
|
code.inspect
|
38
37
|
end
|
@@ -64,15 +63,27 @@ class DsLisp
|
|
64
63
|
"
|
65
64
|
end
|
66
65
|
|
66
|
+
def let(code)
|
67
|
+
newcode = [[:lambda, code[1].map(&:first), code[2]]] + code[1].map{|x|x[1]}
|
68
|
+
ToRuby.to_ruby(newcode)
|
69
|
+
end
|
70
|
+
|
67
71
|
def lambda(code)
|
68
|
-
arguments = code[1].map(&ToRuby.method(:name_convert)).map(&:to_s)
|
72
|
+
arguments = code[1].select{|x| x != :"&optional"}.map{|x| Array === x ? x[0] : x}.map(&ToRuby.method(:name_convert)).map(&:to_s)
|
73
|
+
x_optional = code[1].select{|x| x != :"&optional"}.map{|x|
|
74
|
+
if Array === x
|
75
|
+
ToRuby.to_ruby(x[1])
|
76
|
+
else
|
77
|
+
"nil"
|
78
|
+
end
|
79
|
+
}
|
69
80
|
|
70
81
|
@count = (@count || 0) + 1
|
71
82
|
oldargsvar = "oldargs_#{@count}"
|
72
83
|
|
73
84
|
"(lambda{|*x|
|
74
85
|
#{oldargsvar} = [ #{arguments.map{|z| "begin; #{z}; rescue; nil; end"}.join(",")} ] # save current bindings
|
75
|
-
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = x[#{i}]" }.join(";")}
|
86
|
+
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = x[#{i}] || #{x_optional[i]}" }.join(";")}
|
76
87
|
begin
|
77
88
|
aux = #{ToRuby.to_ruby(code[2])}
|
78
89
|
ensure
|
@@ -134,7 +145,7 @@ class DsLisp
|
|
134
145
|
end
|
135
146
|
|
136
147
|
if matchdata = /^\s*\'(.*)\s*$/.match(str)
|
137
|
-
[:quote, parse(matchdata[1]
|
148
|
+
[:quote, parse(matchdata[1])]
|
138
149
|
elsif matchdata = /^\s*\((.*)\)\s*$/.match(str)
|
139
150
|
inside_code = matchdata[1]
|
140
151
|
if inside_code =~ /^\s*$/
|
@@ -157,6 +168,8 @@ class DsLisp
|
|
157
168
|
else
|
158
169
|
if str =~ /^\s*\d+\s*$/
|
159
170
|
str.to_i
|
171
|
+
elsif str =~ /^\s*nil\s*$/
|
172
|
+
nil
|
160
173
|
else
|
161
174
|
str.strip.to_sym
|
162
175
|
end
|
@@ -202,8 +215,8 @@ private
|
|
202
215
|
|
203
216
|
|
204
217
|
# list selectors
|
205
|
-
_car = lambda{|x| x.first}
|
206
|
-
_cdr = lambda{|x| x[1..-1]}
|
218
|
+
_car = lambda{|x| x ? x.first : nil}
|
219
|
+
_cdr = lambda{|x| x ? x[1..-1] : nil}
|
207
220
|
_nth = lambda{|index,list| list[index-1]}
|
208
221
|
|
209
222
|
# list constructors
|
@@ -252,7 +265,11 @@ private
|
|
252
265
|
|
253
266
|
_mapcar = lambda{|function, list| list.map(&as_function.call(function))}
|
254
267
|
_apply = lambda{|function, arguments| as_function.call(function).call(*arguments) }
|
255
|
-
_funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
|
268
|
+
_funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
|
269
|
+
|
270
|
+
_reverse = :reverse.to_proc
|
271
|
+
|
272
|
+
_p = lambda{|a| p a}
|
256
273
|
end
|
257
274
|
@binding
|
258
275
|
end
|
data/lib/dslisprb.rb~
CHANGED
@@ -31,8 +31,7 @@ class DsLisp
|
|
31
31
|
elsif code == :T
|
32
32
|
"true"
|
33
33
|
elsif Symbol === code
|
34
|
-
|
35
|
-
name_convert(code).to_s
|
34
|
+
"eval(\"#{name_convert(code).to_s}\")"
|
36
35
|
else
|
37
36
|
code.inspect
|
38
37
|
end
|
@@ -64,15 +63,27 @@ class DsLisp
|
|
64
63
|
"
|
65
64
|
end
|
66
65
|
|
66
|
+
def let(code)
|
67
|
+
newcode = [[:lambda, code[1].map(&:first), code[2]]] + code[1].map{|x|x[1]}
|
68
|
+
ToRuby.to_ruby(newcode)
|
69
|
+
end
|
70
|
+
|
67
71
|
def lambda(code)
|
68
|
-
arguments = code[1].map(&ToRuby.method(:name_convert)).map(&:to_s)
|
72
|
+
arguments = code[1].select{|x| x != :"&optional"}.map{|x| Array === x ? x[0] : x}.map(&ToRuby.method(:name_convert)).map(&:to_s)
|
73
|
+
x_optional = code[1].select{|x| x != :"&optional"}.map{|x|
|
74
|
+
if Array === x
|
75
|
+
ToRuby.to_ruby(x[1])
|
76
|
+
else
|
77
|
+
"nil"
|
78
|
+
end
|
79
|
+
}
|
69
80
|
|
70
81
|
@count = (@count || 0) + 1
|
71
82
|
oldargsvar = "oldargs_#{@count}"
|
72
83
|
|
73
84
|
"(lambda{|*x|
|
74
85
|
#{oldargsvar} = [ #{arguments.map{|z| "begin; #{z}; rescue; nil; end"}.join(",")} ] # save current bindings
|
75
|
-
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = x[#{i}]" }.join(";")}
|
86
|
+
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = x[#{i}] || #{x_optional[i]}" }.join(";")}
|
76
87
|
begin
|
77
88
|
aux = #{ToRuby.to_ruby(code[2])}
|
78
89
|
ensure
|
@@ -134,7 +145,7 @@ class DsLisp
|
|
134
145
|
end
|
135
146
|
|
136
147
|
if matchdata = /^\s*\'(.*)\s*$/.match(str)
|
137
|
-
[:quote, parse(matchdata[1]
|
148
|
+
[:quote, parse(matchdata[1])]
|
138
149
|
elsif matchdata = /^\s*\((.*)\)\s*$/.match(str)
|
139
150
|
inside_code = matchdata[1]
|
140
151
|
if inside_code =~ /^\s*$/
|
@@ -157,6 +168,8 @@ class DsLisp
|
|
157
168
|
else
|
158
169
|
if str =~ /^\s*\d+\s*$/
|
159
170
|
str.to_i
|
171
|
+
elsif str =~ /^\s*nil\s*$/
|
172
|
+
nil
|
160
173
|
else
|
161
174
|
str.strip.to_sym
|
162
175
|
end
|
@@ -202,8 +215,8 @@ private
|
|
202
215
|
|
203
216
|
|
204
217
|
# list selectors
|
205
|
-
_car = lambda{|x| x.first}
|
206
|
-
_cdr = lambda{|x| x[1..-1]}
|
218
|
+
_car = lambda{|x| x? x.first : nil}
|
219
|
+
_cdr = lambda{|x| x? x[1..-1] : nil}
|
207
220
|
_nth = lambda{|index,list| list[index-1]}
|
208
221
|
|
209
222
|
# list constructors
|
@@ -237,9 +250,8 @@ private
|
|
237
250
|
as_function = lambda{|object|
|
238
251
|
if Symbol === object
|
239
252
|
eval(ToRuby.name_convert(object),@binding)
|
240
|
-
elsif
|
241
|
-
|
242
|
-
lambda{|*x| object}
|
253
|
+
elsif Array === object
|
254
|
+
evaluate(object)
|
243
255
|
else
|
244
256
|
object
|
245
257
|
end
|
@@ -253,7 +265,11 @@ private
|
|
253
265
|
|
254
266
|
_mapcar = lambda{|function, list| list.map(&as_function.call(function))}
|
255
267
|
_apply = lambda{|function, arguments| as_function.call(function).call(*arguments) }
|
256
|
-
_funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
|
268
|
+
_funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
|
269
|
+
|
270
|
+
_reverse = :reverse.to_proc
|
271
|
+
|
272
|
+
_p = lambda{|a| p a}
|
257
273
|
end
|
258
274
|
@binding
|
259
275
|
end
|
data/spec/ast.rb
CHANGED
@@ -53,11 +53,15 @@ describe DsLisp, "ds lisp" do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should parse nil" do
|
56
|
-
DsLisp.new.parse("nil").should be ==
|
56
|
+
DsLisp.new.parse("nil").should be == nil
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should parse quoted empty list" do
|
60
60
|
DsLisp.new.parse("'()").should be == [:quote, []]
|
61
61
|
end
|
62
|
+
|
63
|
+
it "should parse nested quotes" do
|
64
|
+
DsLisp.new.parse("'(car '(1 2 3))").should be == [:quote, [:car, [:quote, [1, 2, 3]]]]
|
65
|
+
end
|
62
66
|
end
|
63
67
|
|
data/spec/ast.rb~
CHANGED
@@ -53,11 +53,19 @@ describe DsLisp, "ds lisp" do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should parse nil" do
|
56
|
-
DsLisp.new.parse("nil").should be ==
|
56
|
+
DsLisp.new.parse("nil").should be == nil
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should parse quoted empty list" do
|
60
|
-
DsLisp.new.parse("'
|
60
|
+
DsLisp.new.parse("'()").should be == [:quote, []]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should parse nested quotes" do
|
64
|
+
DsLisp.new.parse("'(car '(1 2 3))").should be == [:quote, [:car, [:quote, [1, 2, 3]]]]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should ignore comments" do
|
68
|
+
DsLisp.new.parse("1").should be == 1
|
61
69
|
end
|
62
70
|
end
|
63
71
|
|
data/spec/defun.rb
CHANGED
@@ -22,6 +22,44 @@ describe DsLisp, "ds lisp defun" do
|
|
22
22
|
[:lambda_test, 1]
|
23
23
|
]).should be == 2
|
24
24
|
end
|
25
|
+
|
26
|
+
it "should allow recursive funcall" do
|
27
|
+
dslisp = DsLisp.new
|
28
|
+
dslisp.evaluate([:block,
|
29
|
+
[:defun, :a, [:x], [:if, [:>, :x, 0], [:a, [:-, :x, 1] ] ,nil]]
|
30
|
+
])
|
31
|
+
|
32
|
+
dslisp.evaluate([:a, 3])
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should allow recursive funcall between two functions" do
|
36
|
+
dslisp = DsLisp.new
|
37
|
+
dslisp.evaluate([:block,
|
38
|
+
[:defun, :a, [:x], [:if, [:>, :x, 0], [:b, [:-, :x, 1] ] ,nil]],
|
39
|
+
[:defun, :b, [:x], [:if, [:>, :x, 0], [:a, [:-, :x, 1] ] ,nil]]
|
40
|
+
])
|
41
|
+
|
42
|
+
dslisp.evaluate([:a, 3])
|
43
|
+
end
|
44
|
+
|
45
|
+
it "nil on list should be evaluated nil" do
|
46
|
+
dslisp = DsLisp.new
|
47
|
+
dslisp.evaluate("(if (car (cdr '(1 nil 3))) 2 3)").should be == dslisp.evaluate("(if nil 2 3)")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should accept optional arguments" do
|
51
|
+
dslisp = DsLisp.new
|
52
|
+
dslisp.evaluate("(defun foo (x &optional (y 4)) x)")
|
53
|
+
dslisp.evaluate("(foo 5)").should be == 5
|
54
|
+
dslisp.evaluate("(foo 6)").should be == 6
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should read optional arguments value" do
|
58
|
+
dslisp = DsLisp.new
|
59
|
+
dslisp.evaluate("(defun foo (x &optional (y 4)) y)")
|
60
|
+
dslisp.evaluate("(foo 5)").should be == 4
|
61
|
+
dslisp.evaluate("(foo 6)").should be == 4
|
62
|
+
end
|
25
63
|
end
|
26
64
|
|
27
65
|
|
data/spec/defun.rb~
CHANGED
@@ -22,6 +22,44 @@ describe DsLisp, "ds lisp defun" do
|
|
22
22
|
[:lambda_test, 1]
|
23
23
|
]).should be == 2
|
24
24
|
end
|
25
|
+
|
26
|
+
it "should allow recursive funcall" do
|
27
|
+
dslisp = DsLisp.new
|
28
|
+
dslisp.evaluate([:block,
|
29
|
+
[:defun, :a, [:x], [:if, [:>, :x, 0], [:a, [:-, :x, 1] ] ,nil]]
|
30
|
+
])
|
31
|
+
|
32
|
+
dslisp.evaluate([:a, 3])
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should allow recursive funcall between two functions" do
|
36
|
+
dslisp = DsLisp.new
|
37
|
+
dslisp.evaluate([:block,
|
38
|
+
[:defun, :a, [:x], [:if, [:>, :x, 0], [:b, [:-, :x, 1] ] ,nil]],
|
39
|
+
[:defun, :b, [:x], [:if, [:>, :x, 0], [:a, [:-, :x, 1] ] ,nil]]
|
40
|
+
])
|
41
|
+
|
42
|
+
dslisp.evaluate([:a, 3])
|
43
|
+
end
|
44
|
+
|
45
|
+
it "nil on list should be evaluated nil" do
|
46
|
+
dslisp = DsLisp.new
|
47
|
+
dslisp.evaluate("(if (car (cdr '(1 nil 3))) 2 3)").should be == dslisp.evaluate("(if nil 2 3)")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should accept optional arguments" do
|
51
|
+
dslisp = DsLisp.new
|
52
|
+
dslisp.evaluate("(defun foo (x &optional (y 4)) x)")
|
53
|
+
dslisp.evaluate("(foo 5)").should be == 5
|
54
|
+
dslisp.evaluate("(foo 6)").should be == 6
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should read optional arguments value" do
|
58
|
+
dslisp = DsLisp.new
|
59
|
+
dslisp.evaluate("(defun foo (x &optional (y 4)) x)")
|
60
|
+
dslisp.evaluate("(foo 5)").should be == 5
|
61
|
+
dslisp.evaluate("(foo 6)").should be == 6
|
62
|
+
end
|
25
63
|
end
|
26
64
|
|
27
65
|
|
data/spec/flowcontrol.rb~
CHANGED
@@ -19,15 +19,10 @@ describe DsLisp, "ds lisp flow control" do
|
|
19
19
|
|
20
20
|
it "should execute second statement of cond if the first fail" do
|
21
21
|
DsLisp.new.evaluate([:cond, [:nil, [:+, 120, 3]], [:T, [:+, 120, 5]]]).should be == 125
|
22
|
-
end
|
22
|
+
end
|
23
23
|
|
24
|
-
it "should execute
|
25
|
-
DsLisp.new.evaluate([:
|
24
|
+
it "should execute second statement of cond if the first fail" do
|
25
|
+
DsLisp.new.evaluate([:cond, [:nil, [:+, 120, 3]], [:T, [:+, 120, 5]]]).should be == 125
|
26
26
|
end
|
27
|
-
|
28
|
-
it "should return nil when first statement return false and there is no second statement" do
|
29
|
-
DsLisp.new.evaluate([:if, :nil, [:+, 110, 1]]).should be == nil
|
30
|
-
end
|
31
|
-
|
32
27
|
end
|
33
28
|
|
data/spec/functions.rb
CHANGED
@@ -32,6 +32,10 @@ describe DsLisp, "ds lisp functions" do
|
|
32
32
|
DsLisp.new.evaluate([:list, 1, 2, 3]).should be == [1,2,3]
|
33
33
|
end
|
34
34
|
|
35
|
+
it "should return nil for (cdr nil)" do
|
36
|
+
DsLisp.new.evaluate("(cdr nil)").should be == nil
|
37
|
+
end
|
38
|
+
|
35
39
|
# type recognizers
|
36
40
|
[:a, 1, [1,2,3,4], [], nil].each do |obj|
|
37
41
|
result = (obj == nil or obj == []) ? true : nil
|
data/spec/functions.rb~
CHANGED
@@ -32,6 +32,10 @@ describe DsLisp, "ds lisp functions" do
|
|
32
32
|
DsLisp.new.evaluate([:list, 1, 2, 3]).should be == [1,2,3]
|
33
33
|
end
|
34
34
|
|
35
|
+
it "should return nil for (cdr nil)" do
|
36
|
+
DsLisp.new.evaluate("(cdr nil)").should be == [2, 3]
|
37
|
+
end
|
38
|
+
|
35
39
|
# type recognizers
|
36
40
|
[:a, 1, [1,2,3,4], [], nil].each do |obj|
|
37
41
|
result = (obj == nil or obj == []) ? true : nil
|
@@ -144,6 +148,31 @@ describe DsLisp, "ds lisp functions" do
|
|
144
148
|
it "should interpret T symbol as true" do
|
145
149
|
DsLisp.new.evaluate(:T).should be == true
|
146
150
|
end
|
151
|
+
|
152
|
+
it "should execute apply with symbol function" do
|
153
|
+
DsLisp.new.evaluate("(apply 'car '((1 2 3)))").should be == 1
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should execute apply with lambda" do
|
157
|
+
DsLisp.new.evaluate("(apply (lambda (x) (car x)) '((1 2 3)))").should be == 1
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should execute apply with quoted lambda" do
|
161
|
+
DsLisp.new.evaluate("(apply '(lambda (x) (car x)) '((1 2 3)))").should be == 1
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should execute funcall with symbol function" do
|
165
|
+
DsLisp.new.evaluate("(funcall 'car '(1 2 3))").should be == 1
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should execute apply with lambda" do
|
169
|
+
DsLisp.new.evaluate("(funcall (lambda (x) (car x)) '(1 2 3))").should be == 1
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should execute apply with quoted lambda" do
|
173
|
+
DsLisp.new.evaluate("(funcall '(lambda (x) (car x)) '(1 2 3))").should be == 1
|
174
|
+
end
|
175
|
+
|
147
176
|
end
|
148
177
|
|
149
178
|
|
data/spec/variable.rb
CHANGED
@@ -4,5 +4,13 @@ describe DsLisp, "ds lisp variables" do
|
|
4
4
|
it "should evaluate variables on if" do
|
5
5
|
DsLisp.new.evaluate("((lambda (x) (if (> x 2) x 2)) 3)").should be == 3
|
6
6
|
end
|
7
|
+
|
8
|
+
it "should assign variables via let" do
|
9
|
+
DsLisp.new.evaluate("(let ((a 5)) a)").should be == 5
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should assign multiple variables via let" do
|
13
|
+
DsLisp.new.evaluate("(let ((a 5) (b 6)) (+ a b) )").should be == 11
|
14
|
+
end
|
7
15
|
end
|
8
16
|
|
data/spec/variable.rb~
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
require "dslisprb"
|
2
2
|
|
3
|
-
describe DsLisp, "ds lisp
|
3
|
+
describe DsLisp, "ds lisp variables" do
|
4
4
|
it "should evaluate variables on if" do
|
5
5
|
DsLisp.new.evaluate("((lambda (x) (if (> x 2) x 2)) 3)").should be == 3
|
6
6
|
end
|
7
|
+
|
8
|
+
it "should assign variables via let" do
|
9
|
+
DsLisp.new.evaluate("(let ((a 5)) a)").should be == 3
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should assign multiple variables via let" do
|
13
|
+
DsLisp.new.evaluate("(let ((a 5) (b 6)) (+ a b) )").should be == 11
|
14
|
+
end
|
7
15
|
end
|
8
16
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dslisprb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.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:
|
12
|
+
date: 2013-01-03 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: robertodarioseminara@gmail.com
|