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
@@ -0,0 +1,397 @@
1
+ module Lisp
2
+
3
+ class PrimMath
4
+
5
+ def self.register
6
+ self.bind("PI", ::Math::PI)
7
+ self.bind("E", ::Math::E)
8
+
9
+ Primitive.register("+", ">=1", "(+ number...)\n\nAdds a series of numbers.") do |args, env|
10
+ Lisp::PrimMath.add_impl(args, env)
11
+ end
12
+
13
+ Primitive.register("-", ">=1", "(- number...)\n\nSequentially subtracts a sequence of numbers.\nAs expected, a unary form of - is available as well.") do |args, env|
14
+ Lisp::PrimMath.subtract_impl(args, env)
15
+ end
16
+
17
+ Primitive.register("*", ">=1", "(* number...)\n\nMultiplies a series of numbers.") do |args, env|
18
+ Lisp::PrimMath.multiply_impl(args, env)
19
+ end
20
+
21
+ Primitive.register("/", ">=1", "(/ number...)\n\nSequentially divides a sequence of numbers.") do |args, env|
22
+ Lisp::PrimMath.quotient_impl(args, env)
23
+ end
24
+
25
+ Primitive.register("%", "1|2", "(% number number)\n\nReturns the remainder of the division of two numbers. NOTE: modulus only works for integers.") do |args, env|
26
+ Lisp::PrimMath.remainder_impl(args, env)
27
+ end
28
+
29
+ Primitive.register("modulo", "1|2", "(modulo number number)\n\nReturns the remainder of the division of two numbers. NOTE: modulus only works for integers.") do |args, env|
30
+ Lisp::PrimMath.remainder_impl(args, env)
31
+ end
32
+
33
+ Primitive.register("even?", "1", "(even? number)\n\nReturns whether the argument is even.") do |args, env|
34
+ Lisp::PrimMath.even_impl(args, env)
35
+ end
36
+
37
+ Primitive.register("odd?", "1", "(odd? number)\n\nReturns whether the argument is odd.") do |args, env|
38
+ Lisp::PrimMath.odd_impl(args, env)
39
+ end
40
+
41
+ Primitive.register("zero?", "1", "(zero? number)\n\nReturns whether the argument is zero.") do |args, env|
42
+ Lisp::PrimMath.zero_impl(args, env)
43
+ end
44
+
45
+ Primitive.register("positive?", "1", "(positive? number)\n\nReturns whether the argument is positive.") do |args, env|
46
+ Lisp::PrimMath.positive_impl(args, env)
47
+ end
48
+
49
+ Primitive.register("negative?", "1", "(negative? number)\n\nReturns whether the argument is negative.") do |args, env|
50
+ Lisp::PrimMath.negative_impl(args, env)
51
+ end
52
+
53
+ Primitive.register("interval", "2", "(interval lo hi)\n\nCreates a list of numbers from `lo` to `hi`, inclusive.") do |args, env|
54
+ Lisp::PrimMath.interval_impl(args, env)
55
+ end
56
+
57
+ Primitive.register("truncate", "1", "(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::PrimMath.truncate_impl(args, env)
59
+ end
60
+
61
+ Primitive.register("round", "1", "(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::PrimMath.round_impl(args, env)
63
+ end
64
+
65
+ Primitive.register("ceiling", "1", "(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::PrimMath.ceiling_impl(args, env)
67
+ end
68
+
69
+ Primitive.register("floor", "1", "(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::PrimMath.floor_impl(args, env)
72
+ end
73
+
74
+ Primitive.register("random", "0|1", "(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::PrimMath.random_impl(args, env)
76
+ end
77
+
78
+ Primitive.register("float", "1", "(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::PrimMath.float_impl(args, env)
80
+ end
81
+
82
+ Primitive.register("integer", "1", "(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::PrimMath.integer_impl(args, env)
84
+ end
85
+
86
+ Primitive.register("sqrt", "1", "(sqrt number)\n\nReturns the square root of `number'.") do |args, env|
87
+ Lisp::PrimMath.sqrt_impl(args, env)
88
+ end
89
+
90
+ Primitive.register("min", ">=1", "(min number...)\n\nReturns the smallest of all the `number` arguments.") do |args, env|
91
+ Lisp::PrimMath.min_impl(args, env)
92
+ end
93
+
94
+ Primitive.register("max", ">=1", "(max number...)\n\nReturns the largest of all the `number` arguments.") do |args, env|
95
+ Lisp::PrimMath.max_impl(args, env)
96
+ end
97
+
98
+ Primitive.register("abs", "1", "(abs number)\n\nReturns the absolute value of `number'.") do |args, env|
99
+ Lisp::PrimMath.abs_impl(args, env)
100
+ end
101
+
102
+ Primitive.register("sin", "1", "(sin number)\n\nReturns the sine of `number'.") do |args, env|
103
+ Lisp::PrimMath.sin_impl(args, env)
104
+ end
105
+
106
+ Primitive.register("cos", "1", "(cos number)\n\nReturns the cosine of `number'.") do |args, env|
107
+ Lisp::PrimMath.cos_impl(args, env)
108
+ end
109
+
110
+ Primitive.register("tan", "1", "(tan number)\n\nReturns the tangent of `number'.") do |args, env|
111
+ Lisp::PrimMath.tan_impl(args, env)
112
+ end
113
+
114
+ Primitive.register("pred", "1", "(pred number)\n\nReturns one less than `number'.") do |args, env|
115
+ Lisp::PrimMath.pred_impl(args, env)
116
+ end
117
+
118
+ Primitive.register("succ", "1", "(succ number)\n\nReturns one more than `number'.") do |args, env|
119
+ Lisp::PrimMath.succ_impl(args, env)
120
+ end
121
+
122
+
123
+ end
124
+
125
+
126
+ def self.bind(name, number)
127
+ EnvironmentFrame.global.bind(Symbol.named(name), Number.with_value(number))
128
+ end
129
+
130
+ def self.add_impl(args, env)
131
+ acc = 0
132
+ c = args
133
+ while !c.nil?
134
+ n = c.car
135
+ return Lisp::Debug.process_error("add needs number arguments but was given a #{n.type}: #{n}", env) unless n.type == :number
136
+ acc += n.value
137
+ c = c.cdr
138
+ end
139
+
140
+ Number.with_value(acc)
141
+ end
142
+
143
+
144
+ def self.subtract_impl(args, env)
145
+ return Number.with_value(-1 * args.car.value) if args.length == 1
146
+
147
+ first = args.car
148
+ return Lisp::Debug.process_error("subtract needs number arguments, but received #{first}", env) unless first.number?
149
+ acc = first.value
150
+ c = args.cdr
151
+ while !c.nil?
152
+ n = c.car
153
+ return Lisp::Debug.process_error("subtract needs number arguments, but received #{n}", env) unless n.number?
154
+ acc -= n.value
155
+ c = c.cdr
156
+ end
157
+
158
+ Number.with_value(acc)
159
+ end
160
+
161
+
162
+ def self.multiply_impl(args, env)
163
+ acc = 1
164
+ c = args
165
+ while !c.nil?
166
+ n = c.car
167
+ return Lisp::Debug.process_error("multiply needs number arguments, but received #{n}", env) unless n.number?
168
+ acc *= n.value
169
+ c = c.cdr
170
+ end
171
+
172
+ Number.with_value(acc)
173
+ end
174
+
175
+
176
+ def self.quotient_impl(args, env)
177
+ first = args.car
178
+ return Lisp::Debug.process_error("quotient needs number arguments, but received #{first}", env) unless first.number?
179
+ return first if args.length == 1
180
+ acc = first.value
181
+ c = args.cdr
182
+ while !c.nil?
183
+ n = c.car
184
+ return Lisp::Debug.process_error("quotient needs number arguments, but received #{n}", env) unless n.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
+ first = args.car
196
+ return Lisp::Debug.process_error("remainder needs number arguments, but received #{first}", env) unless first.number?
197
+ return first if args.length == 1
198
+ acc = first.value
199
+ c = args.cdr
200
+ while !c.nil?
201
+ n = c.car
202
+ return Lisp::Debug.process_error("remainder needs number arguments, but received #{n}", env) unless n.number?
203
+ return Lisp::Debug.process_error("divide by zero", env) if n.value == 0
204
+ acc %= n.value
205
+ c = c.cdr
206
+ end
207
+
208
+ Number.with_value(acc)
209
+ end
210
+
211
+ def self.truncate_impl(args, env)
212
+ arg = args.car
213
+ return Lisp::Debug.process_error("truncate needs a number argument, but received #{arg}", env) unless arg.number?
214
+ Number.with_value(arg.value.truncate)
215
+ end
216
+
217
+
218
+ def self.round_impl(args, env)
219
+ arg = args.car
220
+ return Lisp::Debug.process_error("round needs a number argument, but received #{arg}", env) unless arg.number?
221
+ num = arg.value
222
+ int = num.to_i
223
+ Number.with_value(if (num - int).abs == 0.5
224
+ if int.even?
225
+ int
226
+ else
227
+ int + (int < 0 ? -1 : 1)
228
+ end
229
+ else
230
+ arg.value.round
231
+ end)
232
+ end
233
+
234
+
235
+ def self.ceiling_impl(args, env)
236
+ arg = args.car
237
+ return Lisp::Debug.process_error("ceiling needs a number argument, but received #{arg}", env) unless arg.number?
238
+ Number.with_value(arg.value.ceil)
239
+ end
240
+
241
+
242
+ def self.floor_impl(args, env)
243
+ arg = args.car
244
+ return Lisp::Debug.process_error("floor needs a number argument, but received #{arg}", env) unless arg.number?
245
+ Number.with_value(arg.value.floor)
246
+ end
247
+
248
+
249
+ def self.even_impl(args, env)
250
+ arg = args.car
251
+ return Lisp::Debug.process_error("even? needs a number argument, but received #{arg}", env) unless arg.number?
252
+ Boolean.with_value(arg.value.even?)
253
+ end
254
+
255
+
256
+ def self.odd_impl(args, env)
257
+ arg = args.car
258
+ return Lisp::Debug.process_error("odd? needs a number argument, but received #{arg}", env) unless arg.number?
259
+ Boolean.with_value(arg.value.odd?)
260
+ end
261
+
262
+
263
+ def self.zero_impl(args, env)
264
+ arg = args.car
265
+ return Lisp::Debug.process_error("zero? needs a number argument, but received #{arg}", env) unless arg.number?
266
+ Boolean.with_value(arg.value.zero?)
267
+ end
268
+
269
+
270
+ def self.positive_impl(args, env)
271
+ arg = args.car
272
+ return Lisp::Debug.process_error("positive? needs a number argument, but received #{arg}", env) unless arg.number?
273
+ Boolean.with_value(arg.value > 0)
274
+ end
275
+
276
+
277
+ def self.negative_impl(args, env)
278
+ arg = args.car
279
+ return Lisp::Debug.process_error("negative? needs a number argument, but received #{arg}", env) unless arg.number?
280
+ Boolean.with_value(arg.value < 0)
281
+ end
282
+
283
+
284
+ def self.interval_impl(args, env)
285
+ initial = args.car
286
+ return Lisp::Debug.process_error("interval needs number arguments, but received #{initial}", env) unless initial.number?
287
+ final = args.cadr
288
+ return Lisp::Debug.process_error("interval needs number arguments, but received #{final}", env) unless final.number?
289
+ return Lisp::Debug.process_error("interval's arguments need to be in natural order", env) unless initial.value <= final.value
290
+ Lisp::ConsCell.array_to_list((initial.value..final.value).to_a.map {|n| Number.with_value(n)})
291
+ end
292
+
293
+
294
+ def self.random_impl(args, env)
295
+ arg = args.car
296
+ return Lisp::Debug.process_error("random needs a number argument, but received #{arg}", env) unless arg.nil? || arg.number?
297
+ Number.with_value(arg.nil? ? rand() : rand(arg.value))
298
+ end
299
+
300
+
301
+ def self.float_impl(args, env)
302
+ arg = args.car
303
+ return Lisp::Debug.process_error("float needs a numeric or string argument, but received #{arg}", env) unless arg.number? || arg.string?
304
+ Number.with_value(arg.value.to_f)
305
+ end
306
+
307
+
308
+ def self.integer_impl(args, env)
309
+ arg = args.car
310
+ return Lisp::Debug.process_error("integer needs a numeric or string argument, but received #{arg}", env) unless arg.number? || arg.string?
311
+ Number.with_value(arg.value.to_i)
312
+ end
313
+
314
+
315
+ def self.abs_impl(args, env)
316
+ arg = args.car
317
+ return Lisp::Debug.process_error("abs needs a numeric argument, but received #{arg}", env) unless arg.number?
318
+ Number.with_value(arg.value.abs)
319
+ end
320
+
321
+
322
+ def self.sqrt_impl(args, env)
323
+ arg = args.car
324
+ return Lisp::Debug.process_error("sqrt needs a numeric argument, but received #{arg}", env) unless arg.number?
325
+ Number.with_value(::Math.sqrt(arg.value).round(5))
326
+ end
327
+
328
+
329
+ def self.min_impl(args, env)
330
+ initial = args.car
331
+ return Lisp::Debug.process_error("min requires numeric arguments, but received #{initial}", env) unless initial.number?
332
+ acc = initial.value
333
+ c = args.cdr
334
+ while !c.nil?
335
+ n = c.car
336
+ return Lisp::Debug.process_error("min needs number arguments, but received #{n}", env) unless n.number?
337
+ acc = n.value if n.value < acc
338
+ c = c.cdr
339
+ end
340
+
341
+ Number.with_value(acc)
342
+ end
343
+
344
+
345
+ def self.max_impl(args, env)
346
+ initial = args.car
347
+ return Lisp::Debug.process_error("max requires numeric arguments, but received #{initial}", env) unless initial.number?
348
+ acc = initial.value
349
+ c = args.cdr
350
+ while !c.nil?
351
+ n = c.car
352
+ return Lisp::Debug.process_error("max needs number arguments, but received #{n}", env) unless n.number?
353
+ acc = n.value if n.value > acc
354
+ c = c.cdr
355
+ end
356
+
357
+ Number.with_value(acc)
358
+ end
359
+
360
+
361
+ def self.sin_impl(args, env)
362
+ arg = args.car
363
+ return Lisp::Debug.process_error("sin needs a numeric argument, but received #{arg}", env) unless arg.number?
364
+ Number.with_value(::Math.sin(arg.value).round(5))
365
+ end
366
+
367
+
368
+ def self.cos_impl(args, env)
369
+ arg = args.car
370
+ return Lisp::Debug.process_error("cos needs a numeric argument, but received #{arg}", env) unless arg.number?
371
+ Number.with_value(::Math.cos(arg.value).round(5))
372
+ end
373
+
374
+
375
+ def self.tan_impl(args, env)
376
+ arg = args.car
377
+ return Lisp::Debug.process_error("tan needs a numeric argument, but received #{arg}", env) unless arg.number?
378
+ Number.with_value(::Math.tan(arg.value).round(5))
379
+ end
380
+
381
+
382
+ def self.pred_impl(args, env)
383
+ arg = args.car
384
+ return Lisp::Debug.process_error("pred needs a numeric argument, but received #{arg}", env) unless arg.number?
385
+ Number.with_value(arg.value - 1)
386
+ end
387
+
388
+
389
+ def self.succ_impl(args, env)
390
+ arg = args.car
391
+ return Lisp::Debug.process_error("succ needs a numeric argument, but received #{arg}", env) unless arg.number?
392
+ Number.with_value(arg.value + 1)
393
+ end
394
+
395
+
396
+ end
397
+ end
@@ -0,0 +1,21 @@
1
+ module Lisp
2
+
3
+ class PrimNativeObject
4
+
5
+ def self.register
6
+ Primitive.register("wrap-object", "1") {|args, env| Lisp::NativeObject::wrap_impl(args, env) }
7
+ end
8
+
9
+ def self.wrap_impl(args, env)
10
+ raw_val = args.car.evaluate(env)
11
+ val = if raw_val.list?
12
+ raw_val.to_a
13
+ else
14
+ raw_val
15
+ end
16
+ NativeObject.with_value(val)
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,42 @@
1
+ module Lisp
2
+
3
+ class PrimRelational
4
+
5
+ def self.register
6
+ Primitive.register("<", "2", "(< number number)\n\nReturns whether the first argument is less than the second argument.") do |args, env|
7
+ Lisp::PrimRelational::lt_impl(args, env)
8
+ end
9
+
10
+ Primitive.register(">", "2", "(> number number)\n\nReturns whether the first argument is greater than the second argument.") do |args, env|
11
+ Lisp::PrimRelational::gt_impl(args, env)
12
+ end
13
+
14
+ Primitive.register("<=", "2", "(<= number number)\n\nReturns whether the first argument is less than or equal to the second argument.") do |args, env|
15
+ Lisp::PrimRelational::lteq_impl(args, env)
16
+ end
17
+
18
+ Primitive.register(">=", "2", "(>= number number)\n\nReturns whether the first argument is greater than or equal to the second argument.") do |args, env|
19
+ Lisp::PrimRelational::gteq_impl(args, env)
20
+ end
21
+ end
22
+
23
+
24
+ def self.lt_impl(args, env)
25
+ return Lisp::Boolean.with_value(args.car.value < args.cadr.value)
26
+ end
27
+
28
+ def self.gt_impl(args, env)
29
+ return Lisp::Boolean.with_value(args.car.value > args.cadr.value)
30
+ end
31
+
32
+ def self.lteq_impl(args, env)
33
+ return Lisp::Boolean.with_value(args.car.value <= args.cadr.value)
34
+ end
35
+
36
+ def self.gteq_impl(args, env)
37
+ return Lisp::Boolean.with_value(args.car.value >= args.cadr.value)
38
+ end
39
+
40
+
41
+ end
42
+ end