rubylisp 0.2.1 → 1.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +129 -2
  3. data/bin/rubylisp +87 -12
  4. data/lib/rubylisp/atom.rb +25 -6
  5. data/lib/rubylisp/boolean.rb +9 -6
  6. data/lib/rubylisp/builtins.rb +19 -18
  7. data/lib/rubylisp/character.rb +14 -275
  8. data/lib/rubylisp/class_object.rb +56 -0
  9. data/lib/rubylisp/cons_cell.rb +56 -25
  10. data/lib/rubylisp/debug.rb +15 -19
  11. data/lib/rubylisp/environment.rb +27 -0
  12. data/lib/rubylisp/environment_frame.rb +31 -6
  13. data/lib/rubylisp/eof_object.rb +26 -0
  14. data/lib/rubylisp/exception.rb +61 -61
  15. data/lib/rubylisp/ext.rb +32 -6
  16. data/lib/rubylisp/ffi_new.rb +2 -1
  17. data/lib/rubylisp/ffi_send.rb +15 -5
  18. data/lib/rubylisp/frame.rb +5 -164
  19. data/lib/rubylisp/function.rb +4 -3
  20. data/lib/rubylisp/macro.rb +13 -8
  21. data/lib/rubylisp/{object.rb → native_object.rb} +0 -15
  22. data/lib/rubylisp/number.rb +5 -0
  23. data/lib/rubylisp/parser.rb +81 -52
  24. data/lib/rubylisp/port.rb +27 -0
  25. data/lib/rubylisp/prim_alist.rb +115 -0
  26. data/lib/rubylisp/prim_assignment.rb +61 -0
  27. data/lib/rubylisp/prim_character.rb +273 -0
  28. data/lib/rubylisp/{ffi_class.rb → prim_class_object.rb} +16 -69
  29. data/lib/rubylisp/prim_environment.rb +203 -0
  30. data/lib/rubylisp/prim_equivalence.rb +93 -0
  31. data/lib/rubylisp/prim_frame.rb +166 -0
  32. data/lib/rubylisp/prim_io.rb +266 -0
  33. data/lib/rubylisp/prim_list_support.rb +496 -0
  34. data/lib/rubylisp/{logical.rb → prim_logical.rb} +9 -14
  35. data/lib/rubylisp/prim_math.rb +397 -0
  36. data/lib/rubylisp/prim_native_object.rb +21 -0
  37. data/lib/rubylisp/prim_relational.rb +42 -0
  38. data/lib/rubylisp/{special_forms.rb → prim_special_forms.rb} +98 -85
  39. data/lib/rubylisp/prim_string.rb +792 -0
  40. data/lib/rubylisp/prim_system.rb +55 -0
  41. data/lib/rubylisp/prim_type_checks.rb +58 -0
  42. data/lib/rubylisp/prim_vector.rb +497 -0
  43. data/lib/rubylisp/primitive.rb +51 -6
  44. data/lib/rubylisp/string.rb +4 -803
  45. data/lib/rubylisp/symbol.rb +0 -1
  46. data/lib/rubylisp/tokenizer.rb +161 -137
  47. data/lib/rubylisp/vector.rb +10 -31
  48. data/lib/rubylisp.rb +1 -0
  49. metadata +46 -17
  50. data/lib/rubylisp/alist.rb +0 -230
  51. data/lib/rubylisp/assignment.rb +0 -65
  52. data/lib/rubylisp/equivalence.rb +0 -118
  53. data/lib/rubylisp/io.rb +0 -74
  54. data/lib/rubylisp/list_support.rb +0 -526
  55. data/lib/rubylisp/math.rb +0 -405
  56. data/lib/rubylisp/relational.rb +0 -46
  57. data/lib/rubylisp/system.rb +0 -20
  58. data/lib/rubylisp/testing.rb +0 -136
  59. data/lib/rubylisp/type_checks.rb +0 -60
@@ -3,278 +3,6 @@ module Lisp
3
3
 
4
4
  class Character < Atom
5
5
 
6
- def self.register
7
- Primitive.register("char->name", "(char->name char)\n\nReturns a string corresponding to the printed representation of char. This is the character or character-name component of the external representation.") do |args, env|
8
- Lisp::Character::char_name_impl(args, env)
9
- end
10
-
11
- Primitive.register("name->char", "(name->char string)\n\nConverts a string that names a character into the character specified. If string does not name any character, name->char signals an error.") do |args, env|
12
- Lisp::Character::name_char_impl(args, env)
13
- end
14
-
15
- Primitive.register("char=?", "(char=? char1 char2)\n\nReturn whether char1 and char2 are the same") do |args, env|
16
- Lisp::Character::char_eq_impl(args, env)
17
- end
18
-
19
- Primitive.register("char<?", "(char<? char1 char2)\n\nReturn whether char1 is less than char2") do |args, env|
20
- Lisp::Character::char_lt_impl(args, env)
21
- end
22
-
23
- Primitive.register("char>?", "(char>? char1 char2)\n\nReturn whether char1 is greater than char2") do |args, env|
24
- Lisp::Character::char_gt_impl(args, env)
25
- end
26
-
27
- Primitive.register("char<=?", "(char<=? char1 char2)\n\nReturn whether char1 is less than or equal to char2") do |args, env|
28
- Lisp::Character::char_lteq_impl(args, env)
29
- end
30
-
31
- Primitive.register("char>=?", "(char>=? char1 char2)\n\nReturn whether char1 is greater than or equal to char2") do |args, env|
32
- Lisp::Character::char_gteq_impl(args, env)
33
- end
34
-
35
- Primitive.register("char-ci=?", "(char=? char1 char2)\n\nReturn whether char1 is equal to char2, ignoring case") do |args, env|
36
- Lisp::Character::char_ci_eq_impl(args, env)
37
- end
38
-
39
- Primitive.register("char-ci<?", "(char=? char1 char2)\n\nReturn whether char1 is less than char2, ignoring case") do |args, env|
40
- Lisp::Character::char_ci_lt_impl(args, env)
41
- end
42
-
43
- Primitive.register("char-ci>?", "(char=? char1 char2)\n\nReturn whether char1 is greater than char2, ignoring case") do |args, env|
44
- Lisp::Character::char_ci_gt_impl(args, env)
45
- end
46
-
47
- Primitive.register("char-ci<=?", "(char=? char1 char2)\n\nReturn whether char1 is less than or equal to char2, ignoring case") do |args, env|
48
- Lisp::Character::char_ci_lteq_impl(args, env)
49
- end
50
-
51
- Primitive.register("char-ci>=?", "(char=? char1 char2)\n\nReturn whether char1 is greater than orequal to char2, ignoring case") do |args, env|
52
- Lisp::Character::char_ci_gteq_impl(args, env)
53
- end
54
-
55
- Primitive.register("char?", "(char? sexpr)\n\nReturns #t if object is a character; otherwise returns #f.") do |args, env|
56
- Lisp::Character::charp_impl(args, env)
57
- end
58
-
59
- Primitive.register("char-upcase", "(char-upcase char)\n\nReturns the uppercase equivalent of char if char is a letter; otherwise returns char. These procedures return a character char2 such that (char-ci=? char char2).") do |args, env|
60
- Lisp::Character::char_upcase_impl(args, env)
61
- end
62
-
63
- Primitive.register("char-downcase", "(char-downcase char)\n\nReturns the lowercase equivalent of char if char is a letter; otherwise returns char. These procedures return a character char2 such that (char-ci=? char char2).") do |args, env|
64
- Lisp::Character::char_downcase_impl(args, env)
65
- end
66
-
67
- Primitive.register("char->digit", "(char->digit char [radix])\n\nIf char is a character representing a digit in the given radix, returns the corresponding integer value. If you specify radix (which must be an integer between 2 and 36 inclusive), the conversion is done in that base, otherwise it is done in base 10. If char doesn’t represent a digit in base radix, char->digit returns #f.\n\nNote that this procedure is insensitive to the alphabetic case of char.") do |args, env|
68
- Lisp::Character::char_digit_impl(args, env)
69
- end
70
-
71
- Primitive.register("digit->char", "(digit->char digit [radix])\n\nReturns a character that represents digit in the radix given by radix. Radix must be an exact integer between 2 and 36 (inclusive), and defaults to 10. Digit, which must be a non-negative integer, should be less than radix; if digit is greater than or equal to radix, digit->char returns #f.") do |args, env|
72
- Lisp::Character::digit_char_impl(args, env)
73
- end
74
-
75
- Primitive.register("char->integer", "(char->integer char)\n\nchar->integer returns the character code representation for char.") do |args, env|
76
- Lisp::Character::char_int_impl(args, env)
77
- end
78
-
79
- Primitive.register("integer->char", "(integer->char k)\n\ninteger->char returns the character whose character code representation is k.") do |args, env|
80
- Lisp::Character::int_char_impl(args, env)
81
- end
82
- end
83
-
84
-
85
- def self.find_character_for_chr(ch)
86
- @@character_constants.each_value {|v| return v if v.value == ch}
87
- return @@character_constants[ch] = Lisp::Character.new(ch)
88
- end
89
-
90
-
91
- def self.find_character_for_name(n)
92
- return @@character_constants[n] if @@character_constants.has_key?(n)
93
- if n.length == 1
94
- ch = self.new(n[0])
95
- return @@character_constants[n] = ch
96
- end
97
- nil
98
- end
99
-
100
-
101
- def self.char_name_impl(args, env)
102
- return Lisp::Debug.process_error("char->name requires a single argument, found #{args.length}", env) unless args.length == 1
103
- char = args.car.evaluate(env)
104
- return Lisp::Debug.process_error("char->name requires a character argument", env) unless char.character?
105
- kv = @@character_constants.rassoc(char)
106
- return Lisp::String.with_value(kv[0]) unless kv.nil?
107
- return Lisp::Debug.process_error("char->name was passed an invalid character", env)
108
- end
109
-
110
-
111
- def self.name_char_impl(args, env)
112
- return Lisp::Debug.process_error("name->char requires a single argument, found #{args.length}", env) unless args.length == 1
113
- name = args.car.evaluate(env)
114
- return Lisp::Debug.process_error("name->char requires a string argument", env) unless name.string?
115
- ch = find_character_for_name(name.value)
116
- return ch unless ch.nil?
117
- return Lisp::Debug.process_error("There is no character with the name #{name}", env)
118
- end
119
-
120
-
121
- def self.get_one_character_arg(func, args, env)
122
- return Lisp::Debug.process_error("#{func} requires a character argument, found no args", env) unless args.length >= 1
123
- char1 = args.car.evaluate(env)
124
- return Lisp::Debug.process_error("#{func} requires a character argument, found #{char1}", env) unless char1.character?
125
- return char1
126
- end
127
-
128
-
129
- def self.get_two_character_args(func, args, env)
130
- return Lisp::Debug.process_error("#{func} requires two arguments, found
131
- ##{args.length}", env) unless args.length == 2
132
- char1 = args.car.evaluate(env)
133
- return Lisp::Debug.process_error("#{func} requires character arguments, found #{char1}", env) unless char1.character?
134
- char2 = args.cadr.evaluate(env)
135
- return Lisp::Debug.process_error("#{func} requires character arguments, found #{char2}", env) unless char2.character?
136
- return [char1, char2]
137
- end
138
-
139
-
140
- def self.char_eq_impl(args, env)
141
- char1, char2 = get_two_character_args("char=?", args, env)
142
- Lisp::Boolean.with_value(char1.value == char2.value)
143
- end
144
-
145
-
146
- def self.char_lt_impl(args, env)
147
- char1, char2 = get_two_character_args("char<?", args, env)
148
- Lisp::Boolean.with_value(char1.value < char2.value)
149
- end
150
-
151
-
152
- def self.char_gt_impl(args, env)
153
- char1, char2 = get_two_character_args("char>?", args, env)
154
- Lisp::Boolean.with_value(char1.value > char2.value)
155
- end
156
-
157
-
158
- def self.char_lteq_impl(args, env)
159
- char1, char2 = get_two_character_args("char<=?", args, env)
160
- Lisp::Boolean.with_value(char1.value <= char2.value)
161
- end
162
-
163
-
164
- def self.char_gteq_impl(args, env)
165
- char1, char2 = get_two_character_args("char>=?", args, env)
166
- Lisp::Boolean.with_value(char1.value >= char2.value)
167
- end
168
-
169
-
170
- def self.char_ci_eq_impl(args, env)
171
- char1, char2 = get_two_character_args("char-ci=?", args, env)
172
- Lisp::Boolean.with_value(char1.value.downcase == char2.value.downcase)
173
- end
174
-
175
-
176
- def self.char_ci_lt_impl(args, env)
177
- char1, char2 = get_two_character_args("char-ci<?", args, env)
178
- Lisp::Boolean.with_value(char1.value.downcase < char2.value.downcase)
179
- end
180
-
181
-
182
- def self.char_ci_gt_impl(args, env)
183
- char1, char2 = get_two_character_args("char-ci>?", args, env)
184
- Lisp::Boolean.with_value(char1.value.downcase > char2.value.downcase)
185
- end
186
-
187
-
188
- def self.char_ci_lteq_impl(args, env)
189
- char1, char2 = get_two_character_args("char-ci<=?", args, env)
190
- Lisp::Boolean.with_value(char1.value.downcase <= char2.value.downcase)
191
- end
192
-
193
-
194
- def self.char_ci_gteq_impl(args, env)
195
- char1, char2 = get_two_character_args("char-ci>=?", args, env)
196
- Lisp::Boolean.with_value(char1.value.downcase >= char2.value.downcase)
197
- end
198
-
199
-
200
- def self.charp_impl(args, env)
201
- return Lisp::Debug.process_error("char->name requires a single argument, found #{args.length}", env) unless args.length == 1
202
- char = args.car.evaluate(env)
203
- Lisp::Boolean.with_value(char.character?)
204
- end
205
-
206
-
207
- def self.char_upcase_impl(args, env)
208
- char = get_one_character_arg("char->digit", args, env)
209
- find_character_for_chr(char.value.upcase)
210
- end
211
-
212
-
213
- def self.char_downcase_impl(args, env)
214
- char = get_one_character_arg("char->digit", args, env)
215
- find_character_for_chr(char.value.downcase)
216
- end
217
-
218
-
219
- def self.char_digit_impl(args, env)
220
- char = get_one_character_arg("char->digit", args, env)
221
- base = if args.length == 1
222
- 10
223
- else
224
- b = args.cadr.evaluate(env)
225
- return Lisp::Debug.process_error("Base for char->digit has to be an integer", env) unless b.integer?
226
- return Lisp::Debug.process_error("Base for char->digit has to be between 2 and 36", env) unless b.value >=2 && b.value <= 36
227
- b.value
228
- end
229
- ch = char.value.upcase
230
- value = case ch
231
- when /[0-9]/
232
- ch[0].ord - 48
233
- when /[A-Z]/
234
- 10 + ch[0].ord - 65
235
- else
236
- -1
237
- end
238
- if value == -1
239
- Lisp::FALSE
240
- elsif value >= base
241
- Lisp::FALSE
242
- else
243
- Lisp::Number.with_value(value)
244
- end
245
- end
246
-
247
-
248
- def self.digit_char_impl(args, env)
249
- d = args.car.evaluate(env)
250
- return Lisp::Debug.process_error("Digit value for digit->char has to be an integer", env) unless d.integer?
251
- base = if args.length == 1
252
- 10
253
- else
254
- b = args.cadr.evaluate(env)
255
- return Lisp::Debug.process_error("Base for char->digit has to be an integer", env) unless b.integer?
256
- return Lisp::Debug.process_error("Base for char->digit has to be between 2 and 36", env) unless b.value >=2 && b.value <= 36
257
- b.value
258
- end
259
- val = d.value
260
- return Lisp::FALSE if val < 0 || val >= base
261
- find_character_for_chr((((val < 10) ? 48 : 55) + val).chr)
262
- end
263
-
264
-
265
- def self.char_int_impl(args, env)
266
- char = get_one_character_arg("char->int", args, env)
267
- Lisp::Number.with_value(char.value.ord)
268
- end
269
-
270
-
271
- def self.int_char_impl(args, env)
272
- i = args.car.evaluate(env)
273
- return Lisp::Debug.process_error("Integer value for int->char has to be an integer", env) unless i.integer?
274
- find_character_for_chr(i.value.chr)
275
- end
276
-
277
-
278
6
  def initialize(n)
279
7
  @value = n
280
8
  end
@@ -289,6 +17,12 @@ module Lisp
289
17
  true
290
18
  end
291
19
 
20
+
21
+ def eqv?(other)
22
+ return false unless other.character?
23
+ @value == other.value
24
+ end
25
+
292
26
 
293
27
  def type
294
28
  :character
@@ -363,9 +97,14 @@ module Lisp
363
97
  @@character_constants["DEL"] = Lisp::Character.new("\x7F")
364
98
 
365
99
 
100
+ def self.character_constants()
101
+ @@character_constants
102
+ end
103
+
104
+
366
105
  def self.with_value(n)
367
106
  if n.length == 1
368
- ch = find_character_for_chr(n[0])
107
+ ch = Lisp::PrimCharacter.find_character_for_chr(n[0])
369
108
  return ch unless ch.nil?
370
109
  ch = self.new(n[0])
371
110
  @@character_constants[n] = ch
@@ -373,9 +112,9 @@ module Lisp
373
112
  elsif @@character_constants.has_key?(n)
374
113
  @@character_constants[n]
375
114
  elsif n[0..1] == "U+"
376
- find_character_for_chr(n[2..-1].to_i(16).chr)
115
+ Lisp::PrimCharacter.find_character_for_chr(n[2..-1].to_i(16).chr)
377
116
  else
378
- return Lisp::Debug.process_error("Invalid character name: #{n}", env)
117
+ return Lisp::Debug.process_error("Invalid character name: #{n}", Lisp::EnvironmentFrame.global)
379
118
  end
380
119
  end
381
120
 
@@ -0,0 +1,56 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Lisp
3
+
4
+ class ClassObject < Atom
5
+
6
+ def self.new_instance
7
+ self.new(@value.alloc.init)
8
+ end
9
+
10
+
11
+ def self.with_class(c)
12
+ self.new(c)
13
+ end
14
+
15
+
16
+ def initialize(c)
17
+ @value = c
18
+ end
19
+
20
+
21
+ def with_value(&block)
22
+ block.call(@value)
23
+ end
24
+
25
+
26
+ def class?
27
+ true
28
+ end
29
+
30
+
31
+ def type
32
+ :class
33
+ end
34
+
35
+
36
+ def native_type
37
+ @value.class
38
+ end
39
+
40
+
41
+ def to_s
42
+ "<a class: #{@value.name}>"
43
+ end
44
+
45
+
46
+ def true?
47
+ @value != nil
48
+ end
49
+
50
+
51
+ def false?
52
+ @value == nil
53
+ end
54
+
55
+ end
56
+ end
@@ -5,6 +5,7 @@ module Lisp
5
5
  attr_reader :car, :cdr
6
6
 
7
7
  def self.cons(a=nil, b=nil)
8
+ b = nil if b.pair? && b.empty?
8
9
  ConsCell.new(a, b)
9
10
  end
10
11
 
@@ -31,8 +32,9 @@ module Lisp
31
32
 
32
33
 
33
34
  def set_nth!(n, d)
35
+ return nil if empty?
34
36
  c = self
35
- (n-1).times {|i| c = c.cdr}
37
+ n.times {|i| c = c.cdr}
36
38
  c.set_car!(d)
37
39
  end
38
40
 
@@ -93,10 +95,6 @@ module Lisp
93
95
  true
94
96
  end
95
97
 
96
- def alist?
97
- false
98
- end
99
-
100
98
  def frame?
101
99
  false
102
100
  end
@@ -104,10 +102,21 @@ module Lisp
104
102
  def vector?
105
103
  false
106
104
  end
105
+
106
+ def eq?(other)
107
+ return true if empty? && (other.nil? || (other.pair? && other.empty?))
108
+ other.pair? && self == other
109
+ end
110
+
111
+ def eqv?(other)
112
+ return true if empty? && (other.nil? || (other.pair? && other.empty?))
113
+ other.pair? && self == other
114
+ end
107
115
 
108
- def eq?(sexpr)
109
- return false unless sexpr.pair?
110
- (@car == sexpr.car || @car.eq?(sexpr.car)) && (@cdr == sexpr.cdr || @cdr.eq?(sexpr.cdr))
116
+ def equal?(other)
117
+ return true if empty? && (other.nil? || (other.pair? && other.empty?))
118
+ return false unless other.pair?
119
+ @car.equal?(other.car) && @cdr.equal?(other.cdr)
111
120
  end
112
121
 
113
122
  def type
@@ -124,7 +133,7 @@ module Lisp
124
133
  return "()" if self.empty?
125
134
  return "'#{@cdr.car.to_s}" if @car.symbol? && @car.name == "quote"
126
135
  return "{#{@cdr.to_s_helper}}" if @car.symbol? && @car.name == "make-frame"
127
- return "[#{@cdr.to_s_helper}]" if @car.symbol? && @car.name == "make-vector"
136
+ return "#(#{@cdr.to_s_helper})" if @car.symbol? && @car.name == "make-vector"
128
137
  return "(#{@car.to_s} . #{@cdr.to_s})" if !@cdr.nil? && !@cdr.pair?
129
138
  return "(#{self.to_s_helper})"
130
139
  end
@@ -137,22 +146,24 @@ module Lisp
137
146
  return "()" if self.empty?
138
147
  return "'#{@cdr.car.print_string}" if @car.symbol? && @car.name == "quote"
139
148
  return "{#{@cdr.print_string_helper}}" if @car.symbol? && @car.name == "make-frame"
140
- return "[#{@cdr.print_string_helper}]" if @car.symbol? && @car.name == "make-vector"
149
+ return "#(#{@cdr.print_string_helper})" if @car.symbol? && @car.name == "make-vector"
141
150
  return "(#{@car.print_string} . #{@cdr.print_string})" if !@cdr.nil? && !@cdr.pair?
142
151
  return "(#{self.print_string_helper})"
143
152
  end
144
153
 
145
154
  def to_a
146
155
  a = []
156
+ return a if empty?
147
157
  c = self
148
158
  until c.nil?
149
- a << c.car()
159
+ a << c.car
150
160
  c = c.cdr
151
161
  end
152
162
  a
153
163
  end
154
164
 
155
165
  def each &block
166
+ return if empty?
156
167
  c = self
157
168
  if self.length > 0
158
169
  until c.nil?
@@ -163,11 +174,11 @@ module Lisp
163
174
  end
164
175
 
165
176
  def self.array_to_list(cells, tail=nil)
166
- return tail if cells.empty?
177
+ return cons() if cells.empty? && tail.nil?
167
178
  head = ConsCell.new
168
179
  last_cell = head
169
- cells.each do |d|
170
- new_cell = self.cons(d, nil)
180
+ (0...cells.length).each do |i|
181
+ new_cell = self.cons(cells[i], nil)
171
182
  last_cell.set_cdr!(new_cell)
172
183
  last_cell = new_cell
173
184
  end
@@ -176,11 +187,12 @@ module Lisp
176
187
  end
177
188
 
178
189
  def traverse(path)
179
- return self if path.empty?
180
- next_cell = (path[0] == ?a) ? @car : @cdr
181
- return next_cell if path.length == 1
182
- return nil if next_cell.nil? || !next_cell.pair?
183
- next_cell.traverse(path[1..-1])
190
+ next_cell = self
191
+ path.chars.each do |p|
192
+ return nil if next_cell.nil? || !next_cell.pair?
193
+ next_cell = ((p == ?a) ? next_cell.car : next_cell.cdr)
194
+ end
195
+ next_cell
184
196
  end
185
197
 
186
198
  def method_missing(name, *args, &block)
@@ -193,13 +205,13 @@ module Lisp
193
205
 
194
206
  def nth(n)
195
207
  c = self
196
- (n-1).times {|i| c = c.cdr}
208
+ n.times {|i| c = c.cdr}
197
209
  c.car
198
210
  end
199
211
 
200
212
  def nth_tail(n)
201
213
  c = self
202
- (n-1).times {|i| c = c.cdr}
214
+ n.times {|i| c = c.cdr}
203
215
  c
204
216
  end
205
217
 
@@ -225,6 +237,7 @@ module Lisp
225
237
  Lisp::Debug.debug_repl(env)
226
238
  end
227
239
  end
240
+
228
241
  result = func.apply_to(@cdr, env)
229
242
  env.current_code.shift() if !Lisp::Debug.eval_in_debug_repl && Lisp::Debug.interactive
230
243
  Lisp::Debug.log_result(result, env)
@@ -236,8 +249,8 @@ module Lisp
236
249
  return self if empty?
237
250
  sexpr = if @car.symbol?
238
251
  key = @car
239
- frame = nth(2)
240
- value = nth(3)
252
+ frame = nth(1)
253
+ value = nth(2)
241
254
 
242
255
  s = key.name
243
256
  if s.end_with?(":")
@@ -246,6 +259,10 @@ module Lisp
246
259
  ConsCell.array_to_list([Symbol.named("set-slot!"), frame, Symbol.named(s[0..-2]), value])
247
260
  elsif s.end_with?(":?")
248
261
  ConsCell.array_to_list([Symbol.named("has-slot?"), frame, Symbol.named(s[0..-2])])
262
+ elsif s.end_with?(":>")
263
+ ConsCell.array_to_list([Symbol.named("send"), frame, Symbol.named(s[0..-2])] << self.cdddr)
264
+ elsif s.end_with?(":^")
265
+ ConsCell.array_to_list([Symbol.named("send-super"), frame, Symbol.named(s[0..-2])] << self.cdddr)
249
266
  else
250
267
  self
251
268
  end
@@ -256,6 +273,7 @@ module Lisp
256
273
  end
257
274
 
258
275
  def evaluate_each(env)
276
+ return nil if empty?
259
277
  result = @car.evaluate(env)
260
278
  return result if @cdr.nil?
261
279
  @cdr.evaluate_each(env)
@@ -287,9 +305,22 @@ module Lisp
287
305
  c
288
306
  end
289
307
 
308
+ def print_ary(a)
309
+ (0...a.length).map {|i| puts (a[i].nil? ? "nil" : a[i])}
310
+ end
311
+
290
312
  def flatten
291
- ary = to_a.collect {|s| s.list? ? s.to_a : s}
292
- ConsCell.array_to_list(ary.flatten)
313
+ ary = []
314
+ to_a.each do |s|
315
+ if s.nil?
316
+ ary << nil
317
+ elsif s.list?
318
+ s.to_a.each {|e| ary << e}
319
+ else
320
+ ary << s
321
+ end
322
+ end
323
+ ConsCell.array_to_list(ary)
293
324
  end
294
325
 
295
326
 
@@ -18,28 +18,26 @@ module Lisp
18
18
  self.on_entry = Set.new
19
19
  self.single_step = false
20
20
  self.interactive = false
21
-
22
- Primitive.register("debug-trace") {|args, env| Lisp::Debug::debug_trace_impl(args, env) }
23
- Primitive.register("debug-on-error") {|args, env| Lisp::Debug::debug_on_error_impl(args, env) }
24
- Primitive.register("debug-on-entry") {|args, env| Lisp::Debug::debug_on_entry_impl(args, env) }
25
- Primitive.register("add-debug-on-entry") {|args, env| Lisp::Debug::add_debug_on_entry_impl(args, env) }
26
- Primitive.register("remove-debug-on-entry") {|args, env| Lisp::Debug::remove_debug_on_entry_impl(args, env) }
27
- Primitive.register("debug") {|args, env| Lisp::Debug::debug_impl(args, env) }
28
- Primitive.register("dump") {|args, env| Lisp::Debug::dump_imp2l(args, env) }
21
+
22
+ Primitive.register("debug-trace", "1") {|args, env| Lisp::Debug::debug_trace_impl(args, env) }
23
+ Primitive.register("debug-on-error", "1") {|args, env| Lisp::Debug::debug_on_error_impl(args, env) }
24
+ Primitive.register("debug-on-entry", "0") {|args, env| Lisp::Debug::debug_on_entry_impl(args, env) }
25
+ Primitive.register("add-debug-on-entry", "1") {|args, env| Lisp::Debug::add_debug_on_entry_impl(args, env) }
26
+ Primitive.register("remove-debug-on-entry", "1") {|args, env| Lisp::Debug::remove_debug_on_entry_impl(args, env) }
27
+ Primitive.register("debug", "0") {|args, env| Lisp::Debug::debug_impl(args, env) }
28
+ Primitive.register("dump", "0") {|args, env| Lisp::Debug::dump_imp2l(args, env) }
29
29
  end
30
-
30
+
31
31
 
32
32
  def self.debug_trace_impl(args, env)
33
- return Lisp::Debug.process_error("debug-trace requires 1 argument", env) unless args.length == 1
34
- flag = args.car.evaluate(env)
33
+ flag = args.car
35
34
  return Lisp::Debug.process_error("the argument to debug-trace has to be a boolean", env) unless flag.boolean?
36
35
  self.trace = flag.value
37
36
  flag
38
37
  end
39
38
 
40
39
  def self.debug_on_error_impl(args, env)
41
- return Lisp::Debug.process_error("debug-on-error requires 1 argument", env) unless args.length == 1
42
- flag = args.car.evaluate(env)
40
+ flag = args.car
43
41
  return Lisp::Debug.process_error("the argument to debug-on-error has to be a boolean", env) unless flag.boolean?
44
42
  self.on_error = flag.value
45
43
  flag
@@ -50,8 +48,7 @@ module Lisp
50
48
  end
51
49
 
52
50
  def self.add_debug_on_entry_impl(args, env)
53
- return Lisp::Debug.process_error("add-debug-on-error requires 1 argument", env) unless args.length == 1
54
- f = args.car.evaluate(env)
51
+ f = args.car
55
52
  return Lisp::Debug.process_error("the argument to add-debug-on-error has to be a function", env) unless f.function? || f.primitive?
56
53
 
57
54
  self.on_entry.add(f.name)
@@ -59,8 +56,7 @@ module Lisp
59
56
  end
60
57
 
61
58
  def self.remove_debug_on_entry_impl(args, env)
62
- return Lisp::Debug.process_error("remove-debug-on-error requires 1 argument", env) unless args.length == 1
63
- f = args.car.evaluate(env)
59
+ f = args.car
64
60
  return Lisp::Debug.process_error("the argument to remove-debug-on-error has to be a function", env) unless f.function?
65
61
 
66
62
  self.on_entry.remove(f.name)
@@ -232,7 +228,7 @@ module Lisp
232
228
  puts(" #{result.to_s}")
233
229
  end
234
230
  end
235
-
236
-
231
+
237
232
  end
233
+
238
234
  end
@@ -0,0 +1,27 @@
1
+ module Lisp
2
+
3
+ class Environment < Atom
4
+
5
+ def self.with_value(e)
6
+ self.new(e)
7
+ end
8
+
9
+ def initialize(e)
10
+ @value = e
11
+ end
12
+
13
+ def environment?
14
+ true
15
+ end
16
+
17
+ def equal?(other)
18
+ other.environment? && @value == other.value
19
+ end
20
+
21
+ def type
22
+ :environment
23
+ end
24
+
25
+ end
26
+
27
+ end