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 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