rubylisp 0.2.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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