dslisprb 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -7,7 +7,7 @@ require "rspec/core/rake_task"
7
7
 
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'dslisprb'
10
- s.version = '0.0.4'
10
+ s.version = '0.0.5'
11
11
  s.author = 'Dario Seminara'
12
12
  s.email = 'robertodarioseminara@gmail.com'
13
13
  s.platform = Gem::Platform::RUBY
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
- # "(local_variables.include?(#{name_convert(code)}) ? #{name_convert(code)} : nil)"
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].sub("'",""))]
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
- # "(local_variables.include?(#{name_convert(code)}) ? #{name_convert(code)} : nil)"
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].sub("'",""))]
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 not object.respond_to?(:call)
241
- _funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
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 == :nil
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 == :nil
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("'[]").should be == [:quote, []]
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 third statement of if when first statement return false" do
25
- DsLisp.new.evaluate([:if, :nil, [:+, 110, 1], [:+, 220, 2]]).should be == 222
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 execution" do
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
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: 2012-06-02 00:00:00.000000000Z
12
+ date: 2013-01-03 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: robertodarioseminara@gmail.com