dslisprb 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -0
- data/Rakefile +1 -1
- data/bin/dslisprb +27 -7
- data/lib/dslisprb.rb +16 -6
- data/lib/dslisprb.rb~ +21 -4
- data/spec/functions.rb +25 -0
- data/spec/functions.rb~ +1 -1
- data/spec/stack.rb +38 -0
- data/spec/stack.rb~ +39 -1
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
0.0.4 Implemented apply and funcall
|
2
|
+
|
3
|
+
Fix of variable assignments on lambda calla
|
4
|
+
|
5
|
+
Load of source files from console and multiline functions allowing line breaks
|
6
|
+
|
1
7
|
0.0.3 fixed interpretation of special nil and T symbols
|
2
8
|
|
3
9
|
implemented autocompletion of lisp variable names on dslisp console
|
data/Rakefile
CHANGED
data/bin/dslisprb
CHANGED
@@ -24,23 +24,43 @@ if ARGV[0]
|
|
24
24
|
else
|
25
25
|
# repl
|
26
26
|
require 'readline'
|
27
|
-
print "enter lisp commands
|
27
|
+
print "enter lisp commands and see the output
|
28
|
+
enter quit to exit
|
29
|
+
enter load to execute a source file. Example: load test.lisp
|
30
|
+
|
31
|
+
Tip: use tab key to autocomplete variable/function names
|
32
|
+
"
|
33
|
+
|
28
34
|
|
29
35
|
stty_save = `stty -g`.chomp
|
30
36
|
trap('INT') { system('stty', stty_save); exit }
|
31
37
|
|
32
38
|
Readline.completion_append_character = " "
|
33
39
|
Readline.completion_proc = proc do |s|
|
34
|
-
dslisp.variables.grep( /^#{Regexp.escape(s)}/ )
|
40
|
+
(dslisp.variables + ["quit", "load"]).grep( /^#{Regexp.escape(s)}/ )
|
35
41
|
end
|
36
42
|
|
37
|
-
|
38
|
-
if cmd == "quit"
|
39
|
-
exit
|
40
|
-
end
|
43
|
+
accumulated = ""
|
41
44
|
|
45
|
+
while cmd = Readline.readline(accumulated == "" ? '> ' : '?> ', true)
|
42
46
|
begin
|
43
|
-
|
47
|
+
if cmd.split.first == "quit"
|
48
|
+
exit
|
49
|
+
elsif cmd.split.first == "load"
|
50
|
+
filename = cmd.split[1]
|
51
|
+
print dslisp.evaluate(File.open(filename).read.gsub("\n"," ")).lisp_inspect,"\n"
|
52
|
+
else
|
53
|
+
accumulated = accumulated + " " + cmd
|
54
|
+
if accumulated.count('(') - accumulated.count(')') == 0
|
55
|
+
begin
|
56
|
+
print dslisp.evaluate(accumulated.gsub("\n"," ")).lisp_inspect,"\n"
|
57
|
+
ensure
|
58
|
+
accumulated = ""
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
rescue SystemExit => e
|
63
|
+
raise e
|
44
64
|
rescue Exception => e
|
45
65
|
p e
|
46
66
|
print e.backtrace.join("\n"),"\n"
|
data/lib/dslisprb.rb
CHANGED
@@ -66,13 +66,17 @@ class DsLisp
|
|
66
66
|
|
67
67
|
def lambda(code)
|
68
68
|
arguments = code[1].map(&ToRuby.method(:name_convert)).map(&:to_s)
|
69
|
-
|
70
|
-
|
69
|
+
|
70
|
+
@count = (@count || 0) + 1
|
71
|
+
oldargsvar = "oldargs_#{@count}"
|
72
|
+
|
73
|
+
"(lambda{|*x|
|
74
|
+
#{oldargsvar} = [ #{arguments.map{|z| "begin; #{z}; rescue; nil; end"}.join(",")} ] # save current bindings
|
71
75
|
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = x[#{i}]" }.join(";")}
|
72
76
|
begin
|
73
77
|
aux = #{ToRuby.to_ruby(code[2])}
|
74
78
|
ensure
|
75
|
-
#{arguments.
|
79
|
+
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = #{oldargsvar}[#{i}]" }.join(";")}
|
76
80
|
end
|
77
81
|
aux
|
78
82
|
}.lisp_inner_code(#{code.lisp_inspect.inspect}))"
|
@@ -121,6 +125,10 @@ class DsLisp
|
|
121
125
|
end
|
122
126
|
|
123
127
|
def parse(str)
|
128
|
+
if str =~ /^\s*$/
|
129
|
+
return :nil
|
130
|
+
end
|
131
|
+
|
124
132
|
if str.count("(") != str.count(")")
|
125
133
|
raise "Parentheshis count does not match, try adding parenthesis at the end of string :P"
|
126
134
|
end
|
@@ -199,7 +207,7 @@ private
|
|
199
207
|
_nth = lambda{|index,list| list[index-1]}
|
200
208
|
|
201
209
|
# list constructors
|
202
|
-
_cons = lambda{|element, list| [element]+list}
|
210
|
+
_cons = lambda{|element, list| [element]+list.to_a}
|
203
211
|
_append = plus
|
204
212
|
_list = lambda{|*args| args}
|
205
213
|
|
@@ -229,8 +237,8 @@ private
|
|
229
237
|
as_function = lambda{|object|
|
230
238
|
if Symbol === object
|
231
239
|
eval(ToRuby.name_convert(object),@binding)
|
232
|
-
elsif
|
233
|
-
|
240
|
+
elsif Array === object
|
241
|
+
evaluate(object)
|
234
242
|
else
|
235
243
|
object
|
236
244
|
end
|
@@ -243,6 +251,8 @@ private
|
|
243
251
|
}
|
244
252
|
|
245
253
|
_mapcar = lambda{|function, list| list.map(&as_function.call(function))}
|
254
|
+
_apply = lambda{|function, arguments| as_function.call(function).call(*arguments) }
|
255
|
+
_funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
|
246
256
|
end
|
247
257
|
@binding
|
248
258
|
end
|
data/lib/dslisprb.rb~
CHANGED
@@ -66,13 +66,17 @@ class DsLisp
|
|
66
66
|
|
67
67
|
def lambda(code)
|
68
68
|
arguments = code[1].map(&ToRuby.method(:name_convert)).map(&:to_s)
|
69
|
-
|
70
|
-
|
69
|
+
|
70
|
+
@count = (@count || 0) + 1
|
71
|
+
oldargsvar = "oldargs_#{@count}"
|
72
|
+
|
73
|
+
"(lambda{|*x|
|
74
|
+
#{oldargsvar} = [ #{arguments.map{|z| "begin; #{z}; rescue; nil; end"}.join(",")} ] # save current bindings
|
71
75
|
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = x[#{i}]" }.join(";")}
|
72
76
|
begin
|
73
77
|
aux = #{ToRuby.to_ruby(code[2])}
|
74
78
|
ensure
|
75
|
-
#{arguments.
|
79
|
+
#{(0..arguments.size-1).map{|i| "#{arguments[i]} = #{oldargsvar}[#{i}]" }.join(";")}
|
76
80
|
end
|
77
81
|
aux
|
78
82
|
}.lisp_inner_code(#{code.lisp_inspect.inspect}))"
|
@@ -121,6 +125,10 @@ class DsLisp
|
|
121
125
|
end
|
122
126
|
|
123
127
|
def parse(str)
|
128
|
+
if str =~ /^\s*$/
|
129
|
+
return :nil
|
130
|
+
end
|
131
|
+
|
124
132
|
if str.count("(") != str.count(")")
|
125
133
|
raise "Parentheshis count does not match, try adding parenthesis at the end of string :P"
|
126
134
|
end
|
@@ -199,7 +207,7 @@ private
|
|
199
207
|
_nth = lambda{|index,list| list[index-1]}
|
200
208
|
|
201
209
|
# list constructors
|
202
|
-
_cons = lambda{|element, list| [element]+list}
|
210
|
+
_cons = lambda{|element, list| [element]+list.to_a}
|
203
211
|
_append = plus
|
204
212
|
_list = lambda{|*args| args}
|
205
213
|
|
@@ -230,6 +238,7 @@ private
|
|
230
238
|
if Symbol === object
|
231
239
|
eval(ToRuby.name_convert(object),@binding)
|
232
240
|
elsif not object.respond_to?(:call)
|
241
|
+
_funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
|
233
242
|
lambda{|*x| object}
|
234
243
|
else
|
235
244
|
object
|
@@ -243,6 +252,8 @@ private
|
|
243
252
|
}
|
244
253
|
|
245
254
|
_mapcar = lambda{|function, list| list.map(&as_function.call(function))}
|
255
|
+
_apply = lambda{|function, arguments| as_function.call(function).call(*arguments) }
|
256
|
+
_funcall = lambda{|function, *arguments| as_function.call(function).call(*arguments) }
|
246
257
|
end
|
247
258
|
@binding
|
248
259
|
end
|
@@ -260,6 +271,12 @@ class Symbol
|
|
260
271
|
end
|
261
272
|
end
|
262
273
|
|
274
|
+
class TrueClass
|
275
|
+
def lisp_inspect
|
276
|
+
"T"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
263
280
|
class Array
|
264
281
|
def lisp_inspect
|
265
282
|
"(" + map(&:lisp_inspect).join(" ") + ")"
|
data/spec/functions.rb
CHANGED
@@ -144,6 +144,31 @@ describe DsLisp, "ds lisp functions" do
|
|
144
144
|
it "should interpret T symbol as true" do
|
145
145
|
DsLisp.new.evaluate(:T).should be == true
|
146
146
|
end
|
147
|
+
|
148
|
+
it "should execute apply with symbol function" do
|
149
|
+
DsLisp.new.evaluate("(apply 'car '((1 2 3)))").should be == 1
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should execute apply with lambda" do
|
153
|
+
DsLisp.new.evaluate("(apply (lambda (x) (car x)) '((1 2 3)))").should be == 1
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should execute apply with quoted lambda" do
|
157
|
+
DsLisp.new.evaluate("(apply '(lambda (x) (car x)) '((1 2 3)))").should be == 1
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should execute funcall with symbol function" do
|
161
|
+
DsLisp.new.evaluate("(funcall 'car '(1 2 3))").should be == 1
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should execute apply with lambda" do
|
165
|
+
DsLisp.new.evaluate("(funcall (lambda (x) (car x)) '(1 2 3))").should be == 1
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should execute apply with quoted lambda" do
|
169
|
+
DsLisp.new.evaluate("(funcall '(lambda (x) (car x)) '(1 2 3))").should be == 1
|
170
|
+
end
|
171
|
+
|
147
172
|
end
|
148
173
|
|
149
174
|
|
data/spec/functions.rb~
CHANGED
data/spec/stack.rb
CHANGED
@@ -10,5 +10,43 @@ describe DsLisp, "ds lisp stack" do
|
|
10
10
|
dslisp.evaluate("(set foo2 (lambda (x) (foo1 4)))")
|
11
11
|
dslisp.evaluate("(foo2 3)").should be == 7
|
12
12
|
end
|
13
|
+
|
14
|
+
it "should restore variable f when assigned to list" do
|
15
|
+
|
16
|
+
dslisp = DsLisp.new
|
17
|
+
|
18
|
+
dslisp.evaluate("(defun b (f x)
|
19
|
+
(mapcar
|
20
|
+
(lambda (a)
|
21
|
+
(a x)
|
22
|
+
)
|
23
|
+
|
24
|
+
f
|
25
|
+
)
|
26
|
+
) ".gsub("\n"," "))
|
27
|
+
|
28
|
+
dslisp.evaluate("(set f 100)")
|
29
|
+
dslisp.evaluate("(b (list car cdr) '(1 2 3))")
|
30
|
+
dslisp.evaluate("f").should be == 100
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should restore variable f when assigned to list when assignment occurs before defun" do
|
34
|
+
|
35
|
+
dslisp = DsLisp.new
|
36
|
+
|
37
|
+
dslisp.evaluate("(set f 100)")
|
38
|
+
dslisp.evaluate("(defun b (f x)
|
39
|
+
(mapcar
|
40
|
+
(lambda (a)
|
41
|
+
1
|
42
|
+
)
|
43
|
+
|
44
|
+
f
|
45
|
+
)
|
46
|
+
) ".gsub("\n"," "))
|
47
|
+
|
48
|
+
dslisp.evaluate("(b '(list car) '(1 2 3))")
|
49
|
+
dslisp.evaluate("f").should be == 100
|
50
|
+
end
|
13
51
|
end
|
14
52
|
|
data/spec/stack.rb~
CHANGED
@@ -8,7 +8,45 @@ describe DsLisp, "ds lisp stack" do
|
|
8
8
|
dslisp.evaluate("(set x 100)")
|
9
9
|
dslisp.evaluate("(set foo1 (lambda (z) (+ x z)))")
|
10
10
|
dslisp.evaluate("(set foo2 (lambda (x) (foo1 4)))")
|
11
|
-
dslisp.
|
11
|
+
dslisp.evaluate("(foo2 3)").should be == 7
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should restore variable f when assigned to list" do
|
15
|
+
|
16
|
+
dslisp = DsLisp.new
|
17
|
+
|
18
|
+
dslisp.evaluate("(defun b (f x)
|
19
|
+
(mapcar
|
20
|
+
(lambda (a)
|
21
|
+
(a x)
|
22
|
+
)
|
23
|
+
|
24
|
+
f
|
25
|
+
)
|
26
|
+
) ".gsub("\n"," "))
|
27
|
+
|
28
|
+
dslisp.evaluate("(set f 100)")
|
29
|
+
dslisp.evaluate("(b (list car cdr) '(1 2 3))")
|
30
|
+
dslisp.evaluate("f").should be == 100
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should restore variable f when assigned to list when assignment occurs before defun" do
|
34
|
+
|
35
|
+
dslisp = DsLisp.new
|
36
|
+
|
37
|
+
dslisp.evaluate("(set f 100)")
|
38
|
+
dslisp.evaluate("(defun b (f x)
|
39
|
+
(mapcar
|
40
|
+
(lambda (a)
|
41
|
+
1
|
42
|
+
)
|
43
|
+
|
44
|
+
f
|
45
|
+
)
|
46
|
+
) ".gsub("\n"," "))
|
47
|
+
|
48
|
+
dslisp.evaluate("(b '() '(1 2 3))")
|
49
|
+
dslisp.evaluate("f").should be == 100
|
12
50
|
end
|
13
51
|
end
|
14
52
|
|
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.4
|
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-
|
12
|
+
date: 2012-06-02 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: robertodarioseminara@gmail.com
|