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.
- checksums.yaml +4 -4
- data/README.md +129 -2
- data/lib/rubylisp/atom.rb +25 -6
- data/lib/rubylisp/boolean.rb +9 -6
- data/lib/rubylisp/builtins.rb +33 -0
- data/lib/rubylisp/character.rb +14 -275
- data/lib/rubylisp/class_object.rb +56 -0
- data/lib/rubylisp/cons_cell.rb +50 -20
- data/lib/rubylisp/environment.rb +27 -0
- data/lib/rubylisp/environment_frame.rb +24 -6
- data/lib/rubylisp/eof_object.rb +26 -0
- data/lib/rubylisp/exception.rb +61 -61
- data/lib/rubylisp/ext.rb +32 -6
- data/lib/rubylisp/ffi_new.rb +2 -1
- data/lib/rubylisp/ffi_send.rb +15 -5
- data/lib/rubylisp/frame.rb +5 -164
- data/lib/rubylisp/function.rb +4 -3
- data/lib/rubylisp/macro.rb +13 -8
- data/lib/rubylisp/{object.rb → native_object.rb} +0 -15
- data/lib/rubylisp/number.rb +5 -0
- data/lib/rubylisp/parser.rb +81 -52
- data/lib/rubylisp/port.rb +27 -0
- data/lib/rubylisp/prim_alist.rb +115 -0
- data/lib/rubylisp/prim_assignment.rb +61 -0
- data/lib/rubylisp/prim_character.rb +273 -0
- data/lib/rubylisp/{ffi_class.rb → prim_class_object.rb} +16 -69
- data/lib/rubylisp/prim_environment.rb +203 -0
- data/lib/rubylisp/prim_equivalence.rb +93 -0
- data/lib/rubylisp/prim_frame.rb +166 -0
- data/lib/rubylisp/prim_io.rb +266 -0
- data/lib/rubylisp/prim_list_support.rb +496 -0
- data/lib/rubylisp/{logical.rb → prim_logical.rb} +9 -14
- data/lib/rubylisp/prim_math.rb +397 -0
- data/lib/rubylisp/prim_native_object.rb +21 -0
- data/lib/rubylisp/prim_relational.rb +42 -0
- data/lib/rubylisp/{special_forms.rb → prim_special_forms.rb} +97 -84
- data/lib/rubylisp/prim_string.rb +792 -0
- data/lib/rubylisp/prim_system.rb +55 -0
- data/lib/rubylisp/prim_type_checks.rb +58 -0
- data/lib/rubylisp/prim_vector.rb +497 -0
- data/lib/rubylisp/primitive.rb +51 -6
- data/lib/rubylisp/string.rb +4 -803
- data/lib/rubylisp/symbol.rb +0 -1
- data/lib/rubylisp/tokenizer.rb +160 -136
- data/lib/rubylisp/vector.rb +10 -31
- data/lib/rubymotion/debug.rb +40 -0
- data/lib/rubymotion/require-fix.rb +1 -0
- data/lib/rubymotionlisp.rb +4 -0
- metadata +28 -17
- data/lib/rubylisp/alist.rb +0 -230
- data/lib/rubylisp/assignment.rb +0 -65
- data/lib/rubylisp/equivalence.rb +0 -118
- data/lib/rubylisp/io.rb +0 -74
- data/lib/rubylisp/list_support.rb +0 -526
- data/lib/rubylisp/math.rb +0 -405
- data/lib/rubylisp/motion_builtins.rb +0 -31
- data/lib/rubylisp/relational.rb +0 -46
- data/lib/rubylisp/system.rb +0 -20
- data/lib/rubylisp/testing.rb +0 -136
- 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
|
data/lib/rubylisp/relational.rb
DELETED
@@ -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
|
data/lib/rubylisp/system.rb
DELETED
@@ -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
|
data/lib/rubylisp/testing.rb
DELETED
@@ -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
|