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
data/lib/rubylisp/math.rb DELETED
@@ -1,405 +0,0 @@
1
- module Lisp
2
-
3
- class Math
4
-
5
- def self.register
6
- self.bind("PI", ::Math::PI)
7
- self.bind("E", ::Math::E)
8
-
9
- Primitive.register("+", "(+ number...)\n\nAdds a series of numbers.") do |args, env|
10
- Lisp::Math.add_impl(args, env)
11
- end
12
-
13
- Primitive.register("-", "(- number...)\n\nSequentially subtracts a sequence of numbers.\nAs expected, a unary form of - is available as well.") do |args, env|
14
- Lisp::Math.subtract_impl(args, env)
15
- end
16
-
17
- Primitive.register("*", "(* number...)\n\nMultiplies a series of numbers.") do |args, env|
18
- Lisp::Math.multiply_impl(args, env)
19
- end
20
-
21
- Primitive.register("/", "(/ number...)\n\nSequentially divides a sequence of numbers.") do |args, env|
22
- Lisp::Math.quotient_impl(args, env)
23
- end
24
-
25
- Primitive.register("%", "(% number number)\n\nReturns the remainder of the division of two numbers. NOTE: modulus only works for integers.") do |args, env|
26
- Lisp::Math.remainder_impl(args, env)
27
- end
28
-
29
- Primitive.register("modulo", "(modulo number number)\n\nReturns the remainder of the division of two numbers. NOTE: modulus only works for integers.") do |args, env|
30
- Lisp::Math.remainder_impl(args, env)
31
- end
32
-
33
- Primitive.register("even?", "(even? number)\n\nReturns whether the argument is even.") do |args, env|
34
- Lisp::Math.even_impl(args, env)
35
- end
36
-
37
- Primitive.register("odd?", "(odd? number)\n\nReturns whether the argument is odd.") do |args, env|
38
- Lisp::Math.odd_impl(args, env)
39
- end
40
-
41
- Primitive.register("zero?", "(zero? _number_)\n\nReturns whether the argument is zero.") do |args, env|
42
- Lisp::Math.zero_impl(args, env)
43
- end
44
-
45
- Primitive.register("positive?", "(positive? _number_)\n\nReturns whether the argument is positive.") do |args, env|
46
- Lisp::Math.positive_impl(args, env)
47
- end
48
-
49
- Primitive.register("negative?", "(negative? _number_)\n\nReturns whether the argument is negative.") do |args, env|
50
- Lisp::Math.negative_impl(args, env)
51
- end
52
-
53
- Primitive.register("interval", "(interval _lo_ _hi_)\n\nCreates a list of numbers from `lo` to `hi`, inclusive.") do |args, env|
54
- Lisp::Math.interval_impl(args, env)
55
- end
56
-
57
- Primitive.register("truncate", "(truncate number)\n\nReturns the integer value of number. If it is an integer, it is simply returned. However, if it is a float the integer part is returned.") do |args, env|
58
- Lisp::Math.truncate_impl(args, env)
59
- end
60
-
61
- Primitive.register("round", "(round number)\n\nIf number is an integer, it is simply returned. However, if it is a float the closest integer is returned.") do |args, env|
62
- Lisp::Math.round_impl(args, env)
63
- end
64
-
65
- Primitive.register("ceiling", "(ceiling _number_)\n\nIf `number` is an integer, it is simply returned. However, if it is a float the smallest integer greater than or equal to `number` is returned.") do |args, env|
66
- Lisp::Math.ceiling_impl(args, env)
67
- end
68
-
69
- Primitive.register("floor", "(floor _number_)\n\nIf `number` is an integer, it is simply returned. However, if it is a float the
70
- largest integer less than or equal to `number` is returned.") do |args, env|
71
- Lisp::Math.floor_impl(args, env)
72
- end
73
-
74
- Primitive.register("random", "(random)\n\nReturns a pseudo-random floating point number between 0.0 and 1.0, including 0.0 and excluding 1.0.\n\n(random n)\n\nReturns a pseudo-random integer greater than or equal to 0 and less than n.") do |args, env|
75
- Lisp::Math.random_impl(args, env)
76
- end
77
-
78
- Primitive.register("float", "(float number)\n\nReturns the floating point value of number. If it is a float, it is simply returned. However, if it is an integer it is converted to float and returned.") do |args, env|
79
- Lisp::Math.float_impl(args, env)
80
- end
81
-
82
- Primitive.register("integer", "(integer number)\n\nReturns the integer value of number. If it is an integer, it is simply returned. However, if it is a float the integer part is returned. This is the same as tuncate.") do |args, env|
83
- Lisp::Math.integer_impl(args, env)
84
- end
85
-
86
- Primitive.register("sqrt", "(sqrt _number_)\n\nReturns the square root of `number'.") do |args, env|
87
- Lisp::Math.sqrt_impl(args, env)
88
- end
89
-
90
- Primitive.register("min", "(min _number_...)\n\nReturns the smallest of all the `number` arguments.") do |args, env|
91
- Lisp::Math.min_impl(args, env)
92
- end
93
-
94
- Primitive.register("max", "(max _number_...)\n\nReturns the largest of all the `number` arguments.") do |args, env|
95
- Lisp::Math.max_impl(args, env)
96
- end
97
-
98
- Primitive.register("abs", "(abs _number_)\n\nReturns the absolute value of `number'.") do |args, env|
99
- Lisp::Math.abs_impl(args, env)
100
- end
101
-
102
- Primitive.register("sin", "(sin _number_)\n\nReturns the sine of `number'.") do |args, env|
103
- Lisp::Math.sin_impl(args, env)
104
- end
105
-
106
- Primitive.register("cos", " (cos _number_)\n\nReturns the cosine of `number'.") do |args, env|
107
- Lisp::Math.cos_impl(args, env)
108
- end
109
-
110
- Primitive.register("tan", "(tan _number_)\n\nReturns the tangent of `number'.") do |args, env|
111
- Lisp::Math.tan_impl(args, env)
112
- end
113
-
114
-
115
- end
116
-
117
-
118
- def self.bind(name, number)
119
- EnvironmentFrame.global.bind(Symbol.named(name), Number.with_value(number))
120
- end
121
-
122
- def self.add_impl(args, env)
123
- return Lisp::Debug.process_error("add needs at least 1 argument", env) if args.empty?
124
-
125
- acc = 0
126
- c = args
127
- while !c.nil?
128
- n = c.car.evaluate(env)
129
- return Lisp::Debug.process_error("add needs number arguments but was given a #{n.type}: #{n}", env) unless n.type == :number
130
- acc += n.value
131
- c = c.cdr
132
- end
133
-
134
- Number.with_value(acc)
135
- end
136
-
137
-
138
- def self.subtract_impl(args, env)
139
- return Lisp::Debug.process_error("subtract needs at least 1 argument", env) if args.empty?
140
-
141
- return Number.with_value(-1 * args.car.evaluate(env).value) if args.length == 1
142
-
143
- first = args.car.evaluate(env)
144
- return Lisp::Debug.process_error("subtract needs number arguments, but received #{first}", env) unless first.type == :number
145
- acc = first.value
146
- c = args.cdr
147
- while !c.nil?
148
- n = c.car.evaluate(env)
149
- return Lisp::Debug.process_error("subtract needs number arguments, but received #{n}", env) unless n.type == :number
150
- acc -= n.value
151
- c = c.cdr
152
- end
153
-
154
- Number.with_value(acc)
155
- end
156
-
157
-
158
- def self.multiply_impl(args, env)
159
- return Lisp::Debug.process_error("multiply needs at least 1 argument", env) if args.empty?
160
-
161
- acc = 1
162
- c = args
163
- while !c.nil?
164
- n = c.car.evaluate(env)
165
- return Lisp::Debug.process_error("multiply needs number arguments, but received #{n}", env) unless n.type == :number
166
- acc *= n.value
167
- c = c.cdr
168
- end
169
-
170
- Number.with_value(acc)
171
- end
172
-
173
-
174
- def self.quotient_impl(args, env)
175
- return Lisp::Debug.process_error("quotient needs at least 1 argument", env) if args.empty?
176
-
177
- first = args.car.evaluate(env)
178
- return Lisp::Debug.process_error("quotient needs number arguments, but received #{first}", env) unless first.type == :number
179
- return first if args.length == 1
180
- acc = first.value
181
- c = args.cdr
182
- while !c.nil?
183
- n = c.car.evaluate(env)
184
- return Lisp::Debug.process_error("quotient needs number arguments, but received #{n}", env) unless n.type == :number
185
- return Lisp::Debug.process_error("divide by zero", env) if n.value == 0
186
- acc /= n.value
187
- c = c.cdr
188
- end
189
-
190
- Number.with_value(acc)
191
- end
192
-
193
-
194
- def self.remainder_impl(args, env)
195
- return Lisp::Debug.process_error("remainder needs at least 1 argument", env) if args.empty?
196
-
197
- first = args.car.evaluate(env)
198
- return Lisp::Debug.process_error("remainder needs number arguments, but received #{first}", env) unless first.type == :number
199
- return first if args.length == 1
200
- acc = first.value
201
- c = args.cdr
202
- while !c.nil?
203
- n = c.car.evaluate(env)
204
- return Lisp::Debug.process_error("remainder needs number arguments, but received #{n}", env) unless n.type == :number
205
- return Lisp::Debug.process_error("divide by zero", env) if n.value == 0
206
- acc %= n.value
207
- c = c.cdr
208
- end
209
-
210
- Number.with_value(acc)
211
- end
212
-
213
- def self.truncate_impl(args, env)
214
- return Lisp::Debug.process_error("truncate needs 1 argument, but received #{args.length}", env) if args.length != 1
215
- arg = args.car.evaluate(env)
216
- return Lisp::Debug.process_error("truncate needs a number argument, but received #{arg}", env) unless arg.type == :number
217
- Number.with_value(arg.value.truncate)
218
- end
219
-
220
-
221
- def self.round_impl(args, env)
222
- return Lisp::Debug.process_error("round needs 1 argument, but received #{args.length}", env) if args.length != 1
223
- arg = args.car.evaluate(env)
224
- return Lisp::Debug.process_error("round needs a number argument, but received #{arg}", env) unless arg.type == :number
225
- num = arg.value
226
- int = num.to_i
227
- Number.with_value(if (num - int).abs == 0.5
228
- if int.even?
229
- int
230
- else
231
- int + (int < 0 ? -1 : 1)
232
- end
233
- else
234
- arg.value.round
235
- end)
236
- end
237
-
238
-
239
- def self.ceiling_impl(args, env)
240
- return Lisp::Debug.process_error("ceiling needs 1 argument, but received #{args.length}", env) if args.length != 1
241
- arg = args.car.evaluate(env)
242
- return Lisp::Debug.process_error("ceiling needs a number argument, but received #{arg}", env) unless arg.type == :number
243
- Number.with_value(arg.value.ceil)
244
- end
245
-
246
-
247
- def self.floor_impl(args, env)
248
- return Lisp::Debug.process_error("floor needs 1 argument, but received #{args.length}", env) if args.length != 1
249
- arg = args.car.evaluate(env)
250
- return Lisp::Debug.process_error("floor needs a number argument, but received #{arg}", env) unless arg.type == :number
251
- Number.with_value(arg.value.floor)
252
- end
253
-
254
-
255
- def self.even_impl(args, env)
256
- return Lisp::Debug.process_error("even? needs 1 argument, but received #{args.length}", env) if args.length != 1
257
- arg = args.car.evaluate(env)
258
- return Lisp::Debug.process_error("even? needs a number argument, but received #{arg}", env) unless arg.type == :number
259
- Boolean.with_value(arg.value.even?)
260
- end
261
-
262
-
263
- def self.odd_impl(args, env)
264
- return Lisp::Debug.process_error("odd? needs 1 argument, but received #{args.length}", env) if args.length != 1
265
- arg = args.car.evaluate(env)
266
- return Lisp::Debug.process_error("odd? needs a number argument, but received #{arg}", env) unless arg.type == :number
267
- Boolean.with_value(arg.value.odd?)
268
- end
269
-
270
-
271
- def self.zero_impl(args, env)
272
- return Lisp::Debug.process_error("zero? needs 1 argument, but received #{args.length}", env) if args.length != 1
273
- arg = args.car.evaluate(env)
274
- return Lisp::Debug.process_error("zero? needs a number argument, but received #{arg}", env) unless arg.type == :number
275
- Boolean.with_value(arg.value.zero?)
276
- end
277
-
278
-
279
- def self.positive_impl(args, env)
280
- return Lisp::Debug.process_error("positive? needs 1 argument, but received #{args.length}", env) if args.length != 1
281
- arg = args.car.evaluate(env)
282
- return Lisp::Debug.process_error("positive? needs a number argument, but received #{arg}", env) unless arg.type == :number
283
- Boolean.with_value(arg.value > 0)
284
- end
285
-
286
-
287
- def self.negative_impl(args, env)
288
- return Lisp::Debug.process_error("negative? needs 1 argument, but received #{args.length}", env) if args.length != 1
289
- arg = args.car.evaluate(env)
290
- return Lisp::Debug.process_error("negative? needs a number argument, but received #{arg}", env) unless arg.type == :number
291
- Boolean.with_value(arg.value < 0)
292
- end
293
-
294
-
295
- def self.interval_impl(args, env)
296
- return Lisp::Debug.process_error("interval needs 2 arguments, but received #{args.length}", env) if args.length != 2
297
- initial = args.car.evaluate(env)
298
- return Lisp::Debug.process_error("interval needs number arguments, but received #{initial}", env) unless initial.type == :number
299
- final = args.cadr.evaluate(env)
300
- return Lisp::Debug.process_error("interval needs number arguments, but received #{final}", env) unless final.type == :number
301
- return Lisp::Debug.process_error("interval's arguments need to be in natural order", env) unless initial.value <= final.value
302
- Lisp::ConsCell.array_to_list((initial.value..final.value).to_a.map {|n| Number.with_value(n)})
303
- end
304
-
305
-
306
- def self.random_impl(args, env)
307
- arg = args.car.evaluate(env)
308
- return Lisp::Debug.process_error("random needs a number argument, but received #{arg}", env) unless arg.nil? || arg.type == :number
309
- Number.with_value(arg.nil? ? rand() : rand(arg.value))
310
- end
311
-
312
-
313
- def self.float_impl(args, env)
314
- return Lisp::Debug.process_error("float needs 1 argument, but received #{args.length}", env) if args.length != 1
315
- arg = args.car.evaluate(env)
316
- return Lisp::Debug.process_error("float needs a numeric or string argument, but received #{arg}", env) unless arg.number? || arg.string?
317
- Number.with_value(arg.value.to_f)
318
- end
319
-
320
-
321
- def self.integer_impl(args, env)
322
- return Lisp::Debug.process_error("integer needs 1 argument, but received #{args.length}", env) if args.length != 1
323
- arg = args.car.evaluate(env)
324
- return Lisp::Debug.process_error("integer needs a numeric or string argument, but received #{arg}", env) unless arg.number? || arg.string?
325
- Number.with_value(arg.value.to_i)
326
- end
327
-
328
-
329
- def self.abs_impl(args, env)
330
- return Lisp::Debug.process_error("abs needs 1 argument, but received #{args.length}", env) if args.length != 1
331
- arg = args.car.evaluate(env)
332
- return Lisp::Debug.process_error("abs needs a numeric argument, but received #{arg}", env) unless arg.number?
333
- Number.with_value(arg.value.abs)
334
- end
335
-
336
-
337
- def self.sqrt_impl(args, env)
338
- return Lisp::Debug.process_error("sqrt needs 1 argument, but received #{args.length}", env) if args.length != 1
339
- arg = args.car.evaluate(env)
340
- return Lisp::Debug.process_error("sqrt needs a numeric argument, but received #{arg}", env) unless arg.number?
341
- Number.with_value(::Math.sqrt(arg.value).round(5))
342
- end
343
-
344
-
345
- def self.min_impl(args, env)
346
- return Lisp::Debug.process_error("min needs at least 1 argument", env) if args.length == 0
347
-
348
- initial = args.car.evaluate(env)
349
- return Lisp::Debug.process_error("min requires numeric arguments, but received #{initial}", env) unless initial.type ==:number
350
- acc = initial.value
351
- c = args.cdr
352
- while !c.nil?
353
- n = c.car.evaluate(env)
354
- return Lisp::Debug.process_error("min needs number arguments, but received #{n}", env) unless n.type == :number
355
- acc = n.value if n.value < acc
356
- c = c.cdr
357
- end
358
-
359
- Number.with_value(acc)
360
- end
361
-
362
-
363
- def self.max_impl(args, env)
364
- return Lisp::Debug.process_error("max needs at least 1 argumenta", env) if args.length == 0
365
- initial = args.car.evaluate(env)
366
- return Lisp::Debug.process_error("max requires numeric arguments, but received #{initial}", env) unless initial.type ==:number
367
- acc = initial.value
368
- c = args.cdr
369
- while !c.nil?
370
- n = c.car.evaluate(env)
371
- return Lisp::Debug.process_error("max needs number arguments, but received #{n}", env) unless n.type == :number
372
- acc = n.value if n.value > acc
373
- c = c.cdr
374
- end
375
-
376
- Number.with_value(acc)
377
- end
378
-
379
-
380
- def self.sin_impl(args, env)
381
- return Lisp::Debug.process_error("sin needs 1 argument, but received #{args.length}", env) if args.length != 1
382
- arg = args.car.evaluate(env)
383
- return Lisp::Debug.process_error("sin needs a numeric argument, but received #{arg}", env) unless arg.number?
384
- Number.with_value(::Math.sin(arg.value).round(5))
385
- end
386
-
387
-
388
- def self.cos_impl(args, env)
389
- return Lisp::Debug.process_error("cos needs 1 argument, but received #{args.length}", env) if args.length != 1
390
- arg = args.car.evaluate(env)
391
- return Lisp::Debug.process_error("cos needs a numeric argument, but received #{arg}", env) unless arg.number?
392
- Number.with_value(::Math.cos(arg.value).round(5))
393
- end
394
-
395
-
396
- def self.tan_impl(args, env)
397
- return Lisp::Debug.process_error("tan needs 1 argument, but received #{args.length}", env) if args.length != 1
398
- arg = args.car.evaluate(env)
399
- return Lisp::Debug.process_error("tan needs a numeric argument, but received #{arg}", env) unless arg.number?
400
- Number.with_value(::Math.tan(arg.value).round(5))
401
- end
402
-
403
-
404
- end
405
- end
@@ -1,46 +0,0 @@
1
- module Lisp
2
-
3
- class Relational
4
-
5
- def self.register
6
- Primitive.register("<", "(< number number)\n\nReturns whether the first argument is less than the second argument.") do |args, env|
7
- Lisp::Relational::lt_impl(args, env)
8
- end
9
-
10
- Primitive.register(">", "(> number number)\n\nReturns whether the first argument is greater than the second argument.") do |args, env|
11
- Lisp::Relational::gt_impl(args, env)
12
- end
13
-
14
- Primitive.register("<=", "(<= number number)\n\nReturns whether the first argument is less than or equal to the second argument.") do |args, env|
15
- Lisp::Relational::lteq_impl(args, env)
16
- end
17
-
18
- Primitive.register(">=", "(>= number number)\n\nReturns whether the first argument is greater than or equal to the second argument.") do |args, env|
19
- Lisp::Relational::gteq_impl(args, env)
20
- end
21
- end
22
-
23
-
24
- def self.lt_impl(args, env)
25
- return Lisp::Debug.process_error("< needs at least 2 arguments", env) unless args.length > 1
26
- return Lisp::Boolean.with_value(args.car.evaluate(env).value < args.cadr.evaluate(env).value)
27
- end
28
-
29
- def self.gt_impl(args, env)
30
- return Lisp::Debug.process_error("> needs at least 2 arguments", env) unless args.length > 1
31
- return Lisp::Boolean.with_value(args.car.evaluate(env).value > args.cadr.evaluate(env).value)
32
- end
33
-
34
- def self.lteq_impl(args, env)
35
- return Lisp::Debug.process_error("<= needs at least 2 arguments", env) unless args.length > 1
36
- return Lisp::Boolean.with_value(args.car.evaluate(env).value <= args.cadr.evaluate(env).value)
37
- end
38
-
39
- def self.gteq_impl(args, env)
40
- return Lisp::Debug.process_error(">= needs at least 2 arguments", env) unless args.length > 1
41
- return Lisp::Boolean.with_value(args.car.evaluate(env).value >= args.cadr.evaluate(env).value)
42
- end
43
-
44
-
45
- end
46
- end
@@ -1,20 +0,0 @@
1
- module Lisp
2
-
3
- class System
4
-
5
- def self.register
6
- Primitive.register("sleep") {|args, env| Lisp::System.sleep_impl(args, env) }
7
- Primitive.register("quit") {|args, env| exit() }
8
- end
9
-
10
-
11
- def self.sleep_impl(args, env)
12
- return Lisp::Debug.process_error("sleep needs 1 argument", env) if args.length != 1
13
- arg = args.car.evaluate(env)
14
- return Lisp::Debug.process_error("sleep needs a numeric argument", env) unless arg.number?
15
- sleep(arg.value)
16
- end
17
-
18
-
19
- end
20
- end
@@ -1,136 +0,0 @@
1
- module Lisp
2
-
3
- class Testing
4
-
5
-
6
- def self.register
7
- Primitive.register("describe") {|args, env| Lisp::Testing::describe_impl(args, env) }
8
- Primitive.register("check") {|args, env| Lisp::Testing::check_impl(args, env) }
9
- Primitive.register("check!") {|args, env| Lisp::Testing::check_not_impl(args, env) }
10
- Primitive.register("check*") {|args, env| Lisp::Testing::check_star_impl(args, env) }
11
- end
12
-
13
- def self.describe_impl(args, env)
14
- return Lisp::Debug.process_error("First arg to describe must be a string or symbol", env) if !args.car.symbol? && !args.car.string?
15
- return if args.cdr.nil?
16
- puts
17
- puts " #{args.car.to_s}"
18
- args.cdr.each do |clause|
19
- clause.evaluate(env)
20
- end
21
- end
22
-
23
- def self.do_comparison(c1, c2)
24
- return Lisp::TRUE if c1.nil? && c2.nil?
25
- return Lisp::FALSE if c1.nil? || c2.nil?
26
- Lisp::Boolean.with_value(c1.eq?(c2))
27
- end
28
-
29
- def self.eval_check(code, c1, c2, inverted)
30
- check_result = self.do_comparison(c1, c2)
31
- passed = inverted ? check_result.negate : check_result
32
-
33
- if passed.true?
34
- @@number_of_passes += 1
35
- puts "ok"
36
- else
37
- @@number_of_fails += 1
38
- message = "failed: #{code.print_string} is #{c1.print_string}, expected #{inverted ? 'not ' : ''}#{c2.print_string}"
39
- puts message
40
- @@failure_messages << message
41
- end
42
- end
43
-
44
-
45
- def self.unary_check(name,sexpr, env, inverted)
46
- print " (#{name} #{sexpr.print_string}) - "
47
- c1 = sexpr.evaluate(env)
48
- self.eval_check(sexpr, c1, inverted ? Lisp::FALSE : Lisp::TRUE, false)
49
- end
50
-
51
-
52
- def self.binary_check(name, sexpr_1, sexpr_2, env, inverted)
53
- print " (#{name} "
54
- print "#{sexpr_1.print_string} "
55
- print "#{sexpr_2.print_string}) - "
56
- c1 = sexpr_1.evaluate(env)
57
- c2 = sexpr_2.evaluate(env)
58
- self.eval_check(sexpr_1, c1, c2, inverted)
59
- end
60
-
61
-
62
- def self.check_impl(args, env, inverted=false)
63
- @@number_of_tests += 1
64
- name = inverted ? "check!" : "check"
65
- Lisp::Boolean.with_value(case (args.length)
66
- when 1
67
- self.unary_check(name, args.car, env, inverted)
68
- when 2
69
- self.binary_check(name, args.car, args.cadr, env, inverted)
70
- else
71
- return Lisp::Debug.process_error("check takes 1 or 2 arguments, received #{args.length}", env)
72
- end)
73
- end
74
-
75
-
76
- def self.check_not_impl(args, env)
77
- self.check_impl(args, env, true)
78
- end
79
-
80
-
81
- def self.check_star_impl(args, env)
82
- return Lisp::Debug.process_error("check* needs 2 arguments, received #{args.length}", env) if args.length != 2
83
- @@number_of_tests += 1
84
- print " (check* #{args.car.print_string} #{args.cadr.print_string}) - "
85
-
86
- c1 = args.car.evaluate(env)
87
- c2 = args.cadr
88
- self.eval_check(args.car, c1, c2, false)
89
- end
90
-
91
- def self.init
92
- @@number_of_tests = 0
93
- @@number_of_fails = 0
94
- @@number_of_passes = 0
95
- @@number_of_errors = 0
96
- @@failure_messages = []
97
- @@error_messages = []
98
- end
99
-
100
- def self.dump_messages(header, messages)
101
- return if messages.empty?
102
- puts " #{header}:"
103
- messages.each do |message|
104
- puts " #{message}"
105
- end
106
- puts ""
107
- end
108
-
109
- def self.print_test_results
110
- puts ""
111
- puts " Done."
112
- puts ""
113
-
114
- dump_messages("Errors", @@error_messages)
115
- dump_messages("Failures", @@failure_messages)
116
-
117
- puts " #{@@number_of_tests} Lisp tests"
118
- puts " #{@@number_of_passes} passes, #{@@number_of_fails} fails, #{@@number_of_errors} errors"
119
- end
120
-
121
- def self.run_tests
122
- register
123
- init
124
- Dir[File.dirname(__FILE__) + '/../../lisptest/*_test.lsp'].each do |test_filename|
125
- puts "\nLoading #{test_filename}"
126
- File.open(test_filename) do |f|
127
- code_string = f.read()
128
- Parser.new.parse_and_eval_all(code_string)
129
- end
130
- end
131
- print_test_results
132
- @@number_of_errors == 0 && @@number_of_fails == 0
133
- end
134
-
135
- end
136
- end
@@ -1,60 +0,0 @@
1
- module Lisp
2
-
3
- class TypeChecks
4
-
5
- def self.register
6
- Primitive.register("list?") {|args, env| Lisp::TypeChecks::typep_impl("list?", :pair, args, env) }
7
- Primitive.register("pair?") {|args, env| Lisp::TypeChecks::typep_impl("pair?", :pair, args, env) }
8
- Primitive.register("symbol?") {|args, env| Lisp::TypeChecks::typep_impl("symbol?", :symbol, args, env) }
9
- Primitive.register("number?") {|args, env| Lisp::TypeChecks::typep_impl("number?", :number, args, env) }
10
- Primitive.register("integer?") {|args, env| Lisp::TypeChecks::integerp_impl(args, env) }
11
- Primitive.register("float?") {|args, env| Lisp::TypeChecks::floatp_impl(args, env) }
12
- Primitive.register("function?") {|args, env| Lisp::TypeChecks::functionp_impl(args, env) }
13
-
14
- Primitive.register("nil?") {|args, env| Lisp::TypeChecks::nilp_impl(args, env) }
15
- Primitive.register("null?") {|args, env| Lisp::TypeChecks::nilp_impl(args, env) }
16
- Primitive.register("not-nil?") {|args, env| Lisp::TypeChecks::not_nilp_impl(args, env) }
17
- Primitive.register("not-null?") {|args, env| Lisp::TypeChecks::not_nilp_impl(args, env) }
18
- end
19
-
20
-
21
- def self.typep_impl(name, sym, args, env)
22
- return Lisp::Debug.process_error("#{name} needs 1 argument", env) unless args.length == 1
23
- return Lisp::Boolean.with_value(args.car.evaluate(env).type == sym)
24
- end
25
-
26
-
27
- def self.integerp_impl(args, env)
28
- return Lisp::Debug.process_error("integer? needs 1 argument", env) unless args.length == 1
29
- val = args.car.evaluate(env)
30
- return Lisp::Boolean.with_value(val.type == :number && val.integer?)
31
- end
32
-
33
-
34
- def self.floatp_impl(args, env)
35
- return Lisp::Debug.process_error("float? needs 1 argument", env) unless args.length == 1
36
- val = args.car.evaluate(env)
37
- return Lisp::Boolean.with_value(val.type == :number && val.float?)
38
- end
39
-
40
-
41
- def self.functionp_impl(args, env)
42
- return Lisp::Debug.process_error("function? needs 1 argument", env) unless args.length == 1
43
- val = args.car.evaluate(env)
44
- return Lisp::Boolean.with_value(val.type == :function || val.type == :primitive)
45
- end
46
-
47
-
48
- def self.nilp_impl(args, env)
49
- return Lisp::Debug.process_error("nil? needs 1 argument", env) unless args.length == 1
50
- return Lisp::Boolean.with_value(args.car.evaluate(env).nil?)
51
- end
52
-
53
-
54
- def self.not_nilp_impl(args, env)
55
- return Lisp::Debug.process_error("not-nil? needs 1 argument", env) unless args.length == 1
56
- return Lisp::Boolean.with_value(!args.car.evaluate(env).nil?)
57
- end
58
-
59
- end
60
- end