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 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
@@ -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.3'
10
+ s.version = '0.0.4'
11
11
  s.author = 'Dario Seminara'
12
12
  s.email = 'robertodarioseminara@gmail.com'
13
13
  s.platform = Gem::Platform::RUBY
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 or quit to exit\n"
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
- while cmd = Readline.readline('> ', true)
38
- if cmd == "quit"
39
- exit
40
- end
43
+ accumulated = ""
41
44
 
45
+ while cmd = Readline.readline(accumulated == "" ? '> ' : '?> ', true)
42
46
  begin
43
- print dslisp.evaluate(cmd).lisp_inspect,"\n"
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
- "(#{arguments.join(",")} = #{code[1].map{"nil"}.join(",")} ;lambda{|*x|
70
- oldargs = [ #{arguments.join(",")} ] # save current bindings
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.join(",")} = oldargs # restore bindings
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 not object.respond_to?(:call)
233
- lambda{|*x| object}
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
- "(#{arguments.join(",")} = #{code[1].map{"nil"}.join(",")} ;lambda{|*x|
70
- oldargs = [ #{arguments.join(",")} ] # save current bindings
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.join(",")} = oldargs # restore bindings
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
@@ -142,7 +142,7 @@ describe DsLisp, "ds lisp functions" do
142
142
  end
143
143
 
144
144
  it "should interpret T symbol as true" do
145
- DsLisp.new.evaluate(:T).should be == nil
145
+ DsLisp.new.evaluate(:T).should be == true
146
146
  end
147
147
  end
148
148
 
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.evluaate("(foo2 3)").should be == 7
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.3
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-05-30 00:00:00.000000000Z
12
+ date: 2012-06-02 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: robertodarioseminara@gmail.com