dslisprb 0.0.1 → 0.0.2
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 +7 -0
- data/README.rdoc +0 -2
- data/Rakefile +1 -1
- data/TODO +0 -2
- data/bin/dslisprb +1 -1
- data/lib/dslisprb.rb +90 -38
- data/lib/dslisprb.rb~ +92 -39
- data/spec/execution.rb +6 -0
- data/spec/execution.rb~ +5 -1
- data/spec/flowcontrol.rb +24 -0
- data/spec/flowcontrol.rb~ +33 -0
- data/spec/functions.rb +13 -0
- data/spec/functions.rb~ +8 -1
- metadata +4 -2
data/CHANGELOG
CHANGED
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
data/TODO
CHANGED
data/bin/dslisprb
CHANGED
data/lib/dslisprb.rb
CHANGED
@@ -29,7 +29,13 @@ class DsLisp
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
else
|
32
|
-
code
|
32
|
+
if code == :nil
|
33
|
+
nil
|
34
|
+
elsif code == :T
|
35
|
+
true
|
36
|
+
else
|
37
|
+
code.inspect
|
38
|
+
end
|
33
39
|
end
|
34
40
|
end
|
35
41
|
end
|
@@ -41,6 +47,23 @@ class DsLisp
|
|
41
47
|
code[1].inspect
|
42
48
|
end
|
43
49
|
|
50
|
+
def cond(code)
|
51
|
+
"(nil.tap {
|
52
|
+
" + code[1..-1].map{ |condition_code|
|
53
|
+
"(break (#{ToRuby.to_ruby condition_code[1]}) if (#{ToRuby.to_ruby condition_code[0]}))"
|
54
|
+
}.join(";") + "})"
|
55
|
+
end
|
56
|
+
|
57
|
+
def if(code)
|
58
|
+
"(if (#{ToRuby.to_ruby code[1]})
|
59
|
+
#{ToRuby.to_ruby code[2]}
|
60
|
+
else
|
61
|
+
#{ToRuby.to_ruby code[3]}
|
62
|
+
end
|
63
|
+
)
|
64
|
+
"
|
65
|
+
end
|
66
|
+
|
44
67
|
def lambda(code)
|
45
68
|
arguments = code[1].map(&:to_s).join(",")
|
46
69
|
"lambda{|#{arguments}| #{ToRuby.to_ruby(code[2])}}.lisp_inner_code(#{code.lisp_inspect.inspect})"
|
@@ -127,46 +150,75 @@ class DsLisp
|
|
127
150
|
if String === code
|
128
151
|
return evaluate(parse code)
|
129
152
|
end
|
130
|
-
# arithmethic
|
131
|
-
plus = lambda{|x,y| x+y}
|
132
|
-
mult = lambda{|x,y| x*y}
|
133
|
-
divide = lambda{|x,y| x/y}
|
134
|
-
minus = lambda{|x,y| x-y}
|
135
|
-
|
136
|
-
lt = lambda{|x,y| x<y || nil}
|
137
|
-
ht = lambda{|x,y| x>y || nil}
|
138
|
-
_eq = lambda{|x,y| x==y || nil}
|
139
|
-
|
140
|
-
|
141
|
-
# list selectors
|
142
|
-
_car = lambda{|x| x.first}
|
143
|
-
_cdr = lambda{|x| x[1..-1]}
|
144
|
-
_nth = lambda{|index,list| list[index-1]}
|
145
|
-
|
146
|
-
# list constructors
|
147
|
-
_cons = lambda{|element, list| [element]+list}
|
148
|
-
_append = plus
|
149
|
-
_list = lambda{|*args| args}
|
150
|
-
|
151
|
-
# recognizers
|
152
|
-
_null = lambda{|element| (element == nil or element == []) || nil}
|
153
|
-
_atom = lambda{|element| (not Array === element) || nil}
|
154
|
-
_numberp = lambda{|element| Numeric === element || nil}
|
155
|
-
_symbolp = lambda{|element| Symbol === element || nil}
|
156
|
-
_listp = lambda{|element| Array === element || nil}
|
157
|
-
_length = lambda{|list| list.size}
|
158
|
-
|
159
|
-
# nil
|
160
|
-
_nil = lambda{nil}
|
161
|
-
|
162
|
-
# boolean
|
163
|
-
_not = lambda{|a| (not a) || nil}
|
164
|
-
_and = lambda{|a,b| (a and b) || nil}
|
165
|
-
_or = lambda{|a,b| (a or b) || nil}
|
166
153
|
|
167
154
|
# generate ruby code for lisp ast
|
168
155
|
ruby_code = ToRuby.to_ruby(code)
|
169
|
-
eval(ruby_code)
|
156
|
+
eval(ruby_code, main_binding)
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def main_binding
|
162
|
+
unless @binding
|
163
|
+
@binding = binding
|
164
|
+
|
165
|
+
# arithmethic
|
166
|
+
plus = lambda{|x,y| x+y}
|
167
|
+
mult = lambda{|x,y| x*y}
|
168
|
+
divide = lambda{|x,y| x/y}
|
169
|
+
minus = lambda{|x,y| x-y}
|
170
|
+
|
171
|
+
lt = lambda{|x,y| x<y || nil}
|
172
|
+
ht = lambda{|x,y| x>y || nil}
|
173
|
+
_eq = lambda{|x,y| x==y || nil}
|
174
|
+
|
175
|
+
|
176
|
+
# list selectors
|
177
|
+
_car = lambda{|x| x.first}
|
178
|
+
_cdr = lambda{|x| x[1..-1]}
|
179
|
+
_nth = lambda{|index,list| list[index-1]}
|
180
|
+
|
181
|
+
# list constructors
|
182
|
+
_cons = lambda{|element, list| [element]+list}
|
183
|
+
_append = plus
|
184
|
+
_list = lambda{|*args| args}
|
185
|
+
|
186
|
+
# recognizers
|
187
|
+
_null = lambda{|element| (element == nil or element == []) || nil}
|
188
|
+
_atom = lambda{|element| (not Array === element) || nil}
|
189
|
+
_numberp = lambda{|element| Numeric === element || nil}
|
190
|
+
_symbolp = lambda{|element| Symbol === element || nil}
|
191
|
+
_listp = lambda{|element| Array === element || nil}
|
192
|
+
_length = lambda{|list| list.size}
|
193
|
+
|
194
|
+
# nil
|
195
|
+
_nil = lambda{nil}
|
196
|
+
|
197
|
+
# boolean
|
198
|
+
_not = lambda{|a| (not a) || nil}
|
199
|
+
_and = lambda{|a,b| (a and b) || nil}
|
200
|
+
_or = lambda{|a,b| (a or b) || nil}
|
201
|
+
|
202
|
+
|
203
|
+
as_function = lambda{|object|
|
204
|
+
if Symbol === object
|
205
|
+
eval(ToRuby.name_convert(object),@binding)
|
206
|
+
elsif not object.respond_to?(:call)
|
207
|
+
lambda{|*x| object}
|
208
|
+
else
|
209
|
+
object
|
210
|
+
end
|
211
|
+
}
|
212
|
+
|
213
|
+
_mapcan = lambda{|function, list|
|
214
|
+
list.map(&as_function.call(function)).map{|x|
|
215
|
+
x || []
|
216
|
+
}.inject(&:+)
|
217
|
+
}
|
218
|
+
|
219
|
+
_mapcar = lambda{|function, list| list.map(&as_function.call(function))}
|
220
|
+
end
|
221
|
+
@binding
|
170
222
|
end
|
171
223
|
end
|
172
224
|
|
data/lib/dslisprb.rb~
CHANGED
@@ -29,7 +29,13 @@ class DsLisp
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
else
|
32
|
-
code
|
32
|
+
if code == :nil
|
33
|
+
nil
|
34
|
+
elsif code == :T
|
35
|
+
true
|
36
|
+
else
|
37
|
+
code.inspect
|
38
|
+
end
|
33
39
|
end
|
34
40
|
end
|
35
41
|
end
|
@@ -41,6 +47,24 @@ class DsLisp
|
|
41
47
|
code[1].inspect
|
42
48
|
end
|
43
49
|
|
50
|
+
def cond(code)
|
51
|
+
"(nil.tap {
|
52
|
+
" + code[1..-1].map{ |condition_code|
|
53
|
+
"(break (#{ToRuby.to_ruby condition_code[1]}) if (#{ToRuby.to_ruby condition_code[0]}))"
|
54
|
+
}.join(";")
|
55
|
+
+ "})"
|
56
|
+
end
|
57
|
+
|
58
|
+
def if(code)
|
59
|
+
"(if (#{ToRuby.to_ruby code[1]})
|
60
|
+
#{ToRuby.to_ruby code[2]}
|
61
|
+
else
|
62
|
+
#{ToRuby.to_ruby code[3]}
|
63
|
+
end
|
64
|
+
)
|
65
|
+
"
|
66
|
+
end
|
67
|
+
|
44
68
|
def lambda(code)
|
45
69
|
arguments = code[1].map(&:to_s).join(",")
|
46
70
|
"lambda{|#{arguments}| #{ToRuby.to_ruby(code[2])}}.lisp_inner_code(#{code.lisp_inspect.inspect})"
|
@@ -90,7 +114,7 @@ class DsLisp
|
|
90
114
|
|
91
115
|
def parse(str)
|
92
116
|
if str.count("(") != str.count(")")
|
93
|
-
raise "Parentheshis count does not match, try adding parenthesis
|
117
|
+
raise "Parentheshis count does not match, try adding parenthesis at the end of string :P"
|
94
118
|
end
|
95
119
|
|
96
120
|
if matchdata = /^\s*\'(.*)\s*$/.match(str)
|
@@ -127,46 +151,75 @@ class DsLisp
|
|
127
151
|
if String === code
|
128
152
|
return evaluate(parse code)
|
129
153
|
end
|
130
|
-
# arithmethic
|
131
|
-
plus = lambda{|x,y| x+y}
|
132
|
-
mult = lambda{|x,y| x*y}
|
133
|
-
divide = lambda{|x,y| x/y}
|
134
|
-
minus = lambda{|x,y| x-y}
|
135
|
-
|
136
|
-
lt = lambda{|x,y| x<y || nil}
|
137
|
-
ht = lambda{|x,y| x>y || nil}
|
138
|
-
_eq = lambda{|x,y| x==y || nil}
|
139
|
-
|
140
|
-
|
141
|
-
# list selectors
|
142
|
-
_car = lambda{|x| x.first}
|
143
|
-
_cdr = lambda{|x| x[1..-1]}
|
144
|
-
_nth = lambda{|index,list| list[index-1]}
|
145
|
-
|
146
|
-
# list constructors
|
147
|
-
_cons = lambda{|element, list| [element]+list}
|
148
|
-
_append = plus
|
149
|
-
_list = lambda{|*args| args}
|
150
|
-
|
151
|
-
# recognizers
|
152
|
-
_null = lambda{|element| (element == nil or element == []) || nil}
|
153
|
-
_atom = lambda{|element| (not Array === element) || nil}
|
154
|
-
_numberp = lambda{|element| Numeric === element || nil}
|
155
|
-
_symbolp = lambda{|element| Symbol === element || nil}
|
156
|
-
_listp = lambda{|element| Array === element || nil}
|
157
|
-
_length = lambda{|list| list.size}
|
158
|
-
|
159
|
-
# nil
|
160
|
-
_nil = lambda{nil}
|
161
|
-
|
162
|
-
# boolean
|
163
|
-
_not = lambda{|a| (not a) || nil}
|
164
|
-
_and = lambda{|a,b| (a and b) || nil}
|
165
|
-
_or = lambda{|a,b| (a or b) || nil}
|
166
154
|
|
167
155
|
# generate ruby code for lisp ast
|
168
156
|
ruby_code = ToRuby.to_ruby(code)
|
169
|
-
eval(ruby_code)
|
157
|
+
eval(ruby_code, main_binding)
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def main_binding
|
163
|
+
unless @binding
|
164
|
+
@binding = binding
|
165
|
+
|
166
|
+
# arithmethic
|
167
|
+
plus = lambda{|x,y| x+y}
|
168
|
+
mult = lambda{|x,y| x*y}
|
169
|
+
divide = lambda{|x,y| x/y}
|
170
|
+
minus = lambda{|x,y| x-y}
|
171
|
+
|
172
|
+
lt = lambda{|x,y| x<y || nil}
|
173
|
+
ht = lambda{|x,y| x>y || nil}
|
174
|
+
_eq = lambda{|x,y| x==y || nil}
|
175
|
+
|
176
|
+
|
177
|
+
# list selectors
|
178
|
+
_car = lambda{|x| x.first}
|
179
|
+
_cdr = lambda{|x| x[1..-1]}
|
180
|
+
_nth = lambda{|index,list| list[index-1]}
|
181
|
+
|
182
|
+
# list constructors
|
183
|
+
_cons = lambda{|element, list| [element]+list}
|
184
|
+
_append = plus
|
185
|
+
_list = lambda{|*args| args}
|
186
|
+
|
187
|
+
# recognizers
|
188
|
+
_null = lambda{|element| (element == nil or element == []) || nil}
|
189
|
+
_atom = lambda{|element| (not Array === element) || nil}
|
190
|
+
_numberp = lambda{|element| Numeric === element || nil}
|
191
|
+
_symbolp = lambda{|element| Symbol === element || nil}
|
192
|
+
_listp = lambda{|element| Array === element || nil}
|
193
|
+
_length = lambda{|list| list.size}
|
194
|
+
|
195
|
+
# nil
|
196
|
+
_nil = lambda{nil}
|
197
|
+
|
198
|
+
# boolean
|
199
|
+
_not = lambda{|a| (not a) || nil}
|
200
|
+
_and = lambda{|a,b| (a and b) || nil}
|
201
|
+
_or = lambda{|a,b| (a or b) || nil}
|
202
|
+
|
203
|
+
|
204
|
+
as_function = lambda{|object|
|
205
|
+
if Symbol === object
|
206
|
+
eval(ToRuby.name_convert(object),@binding)
|
207
|
+
elsif not object.respond_to?(:call)
|
208
|
+
lambda{|*x| object}
|
209
|
+
else
|
210
|
+
object
|
211
|
+
end
|
212
|
+
}
|
213
|
+
|
214
|
+
_mapcan = lambda{|function, list|
|
215
|
+
list.map(&as_function.call(function)).map{|x|
|
216
|
+
x || []
|
217
|
+
}.inject(&:+)
|
218
|
+
}
|
219
|
+
|
220
|
+
_mapcar = lambda{|function, list| list.map(&as_function.call(function))}
|
221
|
+
end
|
222
|
+
@binding
|
170
223
|
end
|
171
224
|
end
|
172
225
|
|
data/spec/execution.rb
CHANGED
@@ -20,6 +20,12 @@ describe DsLisp, "ds lisp execution" do
|
|
20
20
|
|
21
21
|
it "should evaluate quote call to define literals" do
|
22
22
|
DsLisp.new.evaluate([:quote, [1, 2, 3]]).should be == [1, 2, 3]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should preserve variables through multiple function calls" do
|
26
|
+
dslisp = DsLisp.new
|
27
|
+
dslisp.evaluate("(defun foo (x) (+ x 1))")
|
28
|
+
dslisp.evaluate("(foo 3)").should be == 4
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
data/spec/execution.rb~
CHANGED
@@ -19,7 +19,11 @@ describe DsLisp, "ds lisp execution" do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should evaluate quote call to define literals" do
|
22
|
-
DsLisp.new.evaluate([:quote, [1, 2, 3]).should be == [1, 2, 3]
|
22
|
+
DsLisp.new.evaluate([:quote, [1, 2, 3]]).should be == [1, 2, 3]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should preserve variables through multiple function calls" do
|
26
|
+
DsLisp.new.evaluate([:quote, [1, 2, 3]]).should be == [1, 2, 3]
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
data/spec/flowcontrol.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp flow control" do
|
4
|
+
it "should execute second statement of if when first statement return true" do
|
5
|
+
DsLisp.new.evaluate([:if, :T, [:+, 110, 1], [:+, 220, 2]]).should be == 111
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should execute third statement of if when first statement return false" do
|
9
|
+
DsLisp.new.evaluate([:if, :nil, [:+, 110, 1], [:+, 220, 2]]).should be == 222
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return nil when first statement return false and there is no second statement" do
|
13
|
+
DsLisp.new.evaluate([:if, :nil, [:+, 110, 1]]).should be == nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should execute cond statement" do
|
17
|
+
DsLisp.new.evaluate([:cond, [:T, [:+, 120, 3]]]).should be == 123
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should execute second statement of cond if the first fail" do
|
21
|
+
DsLisp.new.evaluate([:cond, [:nil, [:+, 120, 3]], [:T, [:+, 120, 5]]]).should be == 125
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp flow control" do
|
4
|
+
it "should execute second statement of if when first statement return true" do
|
5
|
+
DsLisp.new.evaluate([:if, :T, [:+, 110, 1], [:+, 220, 2]]).should be == 111
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should execute third statement of if when first statement return false" do
|
9
|
+
DsLisp.new.evaluate([:if, :nil, [:+, 110, 1], [:+, 220, 2]]).should be == 222
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return nil when first statement return false and there is no second statement" do
|
13
|
+
DsLisp.new.evaluate([:if, :nil, [:+, 110, 1]]).should be == nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should execute cond statement" do
|
17
|
+
DsLisp.new.evaluate([:cond, [:T, [:+, 120, 3]]]).should be == 123
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should execute second statement of cond if the first fail" do
|
21
|
+
DsLisp.new.evaluate([:cond, [:nil, [:+, 120, 3]], [:T, [:+, 120, 5]]]).should be == 125
|
22
|
+
end
|
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
|
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
|
+
end
|
33
|
+
|
data/spec/functions.rb
CHANGED
@@ -127,6 +127,19 @@ describe DsLisp, "ds lisp functions" do
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
+
it "should execute mapcan" do
|
131
|
+
DsLisp.new.evaluate("(mapcan (lambda (x) (and (numberp x) (list x))) '(a 1 b c 3 4 d 5))").should be == [1, 3, 4, 5]
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should execute mapcar" do
|
135
|
+
DsLisp.new.evaluate("(mapcar (lambda (x) (+ x 1)) '(1 2 3 4))").should be == [2, 3, 4, 5]
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should execute mapcar with defined function" do
|
139
|
+
dslisp = DsLisp.new
|
140
|
+
dslisp.evaluate("(defun foo (x) (+ x 1))")
|
141
|
+
dslisp.evaluate("(mapcar foo '(1 2 3 4))").should be == [2, 3, 4, 5]
|
142
|
+
end
|
130
143
|
end
|
131
144
|
|
132
145
|
|
data/spec/functions.rb~
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "dslisprb"
|
2
2
|
|
3
|
-
describe DsLisp
|
3
|
+
describe DsLisp, "ds lisp functions" do
|
4
4
|
|
5
5
|
# selectors
|
6
6
|
it "should return 1 for (car (quote (1 2)))" do
|
@@ -127,6 +127,13 @@ describe DsLisp::CommonLispFunctions, "ds lisp functions" do
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
+
it "should execute mapcan" do
|
131
|
+
DsLisp.new.evaluate("(mapcan (lambda (x) (and (numberp x) (list x))) '(a 1 b c 3 4 d 5))").should be == [1, 3, 4, 5]
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should execute mapcar" do
|
135
|
+
DsLisp.new.evaluate("(mapcar (lambda (x) (+ x 1)) '(1 2 3 4))").should be == [2, 3, 4, 5]
|
136
|
+
end
|
130
137
|
end
|
131
138
|
|
132
139
|
|
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.2
|
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-05-
|
12
|
+
date: 2012-05-27 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: robertodarioseminara@gmail.com
|
@@ -20,7 +20,9 @@ extra_rdoc_files: []
|
|
20
20
|
files:
|
21
21
|
- lib/dslisprb.rb
|
22
22
|
- lib/dslisprb.rb~
|
23
|
+
- spec/flowcontrol.rb~
|
23
24
|
- spec/macro.rb
|
25
|
+
- spec/flowcontrol.rb
|
24
26
|
- spec/ast.rb
|
25
27
|
- spec/defun.rb~
|
26
28
|
- spec/execution.rb~
|