rubymotionlisp 0.2.2 → 1.0.0

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +129 -2
  3. data/lib/rubylisp/atom.rb +25 -6
  4. data/lib/rubylisp/boolean.rb +9 -6
  5. data/lib/rubylisp/builtins.rb +33 -0
  6. data/lib/rubylisp/character.rb +14 -275
  7. data/lib/rubylisp/class_object.rb +56 -0
  8. data/lib/rubylisp/cons_cell.rb +50 -20
  9. data/lib/rubylisp/environment.rb +27 -0
  10. data/lib/rubylisp/environment_frame.rb +24 -6
  11. data/lib/rubylisp/eof_object.rb +26 -0
  12. data/lib/rubylisp/exception.rb +61 -61
  13. data/lib/rubylisp/ext.rb +32 -6
  14. data/lib/rubylisp/ffi_new.rb +2 -1
  15. data/lib/rubylisp/ffi_send.rb +15 -5
  16. data/lib/rubylisp/frame.rb +5 -164
  17. data/lib/rubylisp/function.rb +4 -3
  18. data/lib/rubylisp/macro.rb +13 -8
  19. data/lib/rubylisp/{object.rb → native_object.rb} +0 -15
  20. data/lib/rubylisp/number.rb +5 -0
  21. data/lib/rubylisp/parser.rb +81 -52
  22. data/lib/rubylisp/port.rb +27 -0
  23. data/lib/rubylisp/prim_alist.rb +115 -0
  24. data/lib/rubylisp/prim_assignment.rb +61 -0
  25. data/lib/rubylisp/prim_character.rb +273 -0
  26. data/lib/rubylisp/{ffi_class.rb → prim_class_object.rb} +16 -69
  27. data/lib/rubylisp/prim_environment.rb +203 -0
  28. data/lib/rubylisp/prim_equivalence.rb +93 -0
  29. data/lib/rubylisp/prim_frame.rb +166 -0
  30. data/lib/rubylisp/prim_io.rb +266 -0
  31. data/lib/rubylisp/prim_list_support.rb +496 -0
  32. data/lib/rubylisp/{logical.rb → prim_logical.rb} +9 -14
  33. data/lib/rubylisp/prim_math.rb +397 -0
  34. data/lib/rubylisp/prim_native_object.rb +21 -0
  35. data/lib/rubylisp/prim_relational.rb +42 -0
  36. data/lib/rubylisp/{special_forms.rb → prim_special_forms.rb} +97 -84
  37. data/lib/rubylisp/prim_string.rb +792 -0
  38. data/lib/rubylisp/prim_system.rb +55 -0
  39. data/lib/rubylisp/prim_type_checks.rb +58 -0
  40. data/lib/rubylisp/prim_vector.rb +497 -0
  41. data/lib/rubylisp/primitive.rb +51 -6
  42. data/lib/rubylisp/string.rb +4 -803
  43. data/lib/rubylisp/symbol.rb +0 -1
  44. data/lib/rubylisp/tokenizer.rb +160 -136
  45. data/lib/rubylisp/vector.rb +10 -31
  46. data/lib/rubymotion/debug.rb +40 -0
  47. data/lib/rubymotion/require-fix.rb +1 -0
  48. data/lib/rubymotionlisp.rb +4 -0
  49. metadata +28 -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/motion_builtins.rb +0 -31
  57. data/lib/rubylisp/relational.rb +0 -46
  58. data/lib/rubylisp/system.rb +0 -20
  59. data/lib/rubylisp/testing.rb +0 -136
  60. 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,31 +0,0 @@
1
- module Lisp
2
-
3
- class Initializer
4
-
5
- def self.initialize_global_environment
6
- Lisp::EnvironmentFrame.global.bind(Symbol.named("nil"), nil)
7
- end
8
-
9
- def self.register_builtins
10
- Lisp::Equivalence.register
11
- Lisp::Math.register
12
- Lisp::Logical.register
13
- Lisp::SpecialForms.register
14
- Lisp::ListSupport.register
15
- Lisp::Relational.register
16
- Lisp::TypeChecks.register
17
- Lisp::Assignment.register
18
- Lisp::Testing.register
19
- Lisp::IO.register
20
- Lisp::AList.register
21
- Lisp::Frame.register
22
- Lisp::Character.register
23
- Lisp::String.register
24
- Lisp::NativeObject.register
25
- Lisp::ClassObject.register
26
- Lisp::System.register
27
- Lisp::Vector.register
28
- end
29
- end
30
-
31
- 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