rubymotionlisp 0.2.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,128 +1,140 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
module Lisp
|
3
3
|
|
4
|
-
class
|
4
|
+
class PrimSpecialForms
|
5
5
|
|
6
6
|
def self.register
|
7
|
-
Primitive.register("cond",
|
7
|
+
Primitive.register("cond", "*",
|
8
8
|
"(cond (predicate sexpr...)... [(else sexpr...)])\n\nEach predicate is evaluated in order until one results in true value. The expressions associated with this predicate are then evaluated in order, and the result of the `cond` is the result of the last evaluation. If all predicates evaluate to false values, the value of `cond` in indeterminate. If, however, the final predicate is the symbol `else` the expressions associated with it are evaluated, and the value of `cond` is the value of the last evaluation.",
|
9
9
|
true) do |args, env|
|
10
|
-
Lisp::
|
10
|
+
Lisp::PrimSpecialForms::cond_impl(args, env)
|
11
11
|
end
|
12
12
|
|
13
|
-
Primitive.register("case",
|
13
|
+
Primitive.register("case", ">=1",
|
14
14
|
"(case target-sexpr ((value...) sexpr...)... [(else sexpr...)])\n\n`case` chooses code to evaluate based on the value of the target `sexpr`. Each condition clause is a list of possible values. A clause is selected if the target value is in it’s list of possible values. Any number of expressions can be associated with each target value.",
|
15
15
|
true) do |args, env|
|
16
|
-
Lisp::
|
16
|
+
Lisp::PrimSpecialForms::case_impl(args, env)
|
17
17
|
end
|
18
18
|
|
19
|
-
Primitive.register("if",
|
19
|
+
Primitive.register("if", "2|3",
|
20
20
|
"(if condition true-clause)\n(if condition true-clause false-clause)\n\n`if` has two forms, one that conditionally evaluates a single `sexpr` (see `begin` which provides a way to use multiple `sexprs` in this context) and one that chooses an `sexpr` to evaluate based on the value of the condition.\n\nIn the single action version, `nil` is the value of the form when the conditions evaluates to `false`. Note that it is preferable to use `when` (see below) instead of this form of `if`.",
|
21
21
|
true) do |args, env|
|
22
|
-
Lisp::
|
22
|
+
Lisp::PrimSpecialForms::if_impl(args, env)
|
23
23
|
end
|
24
24
|
|
25
|
-
Primitive.register("when",
|
25
|
+
Primitive.register("when", ">=2",
|
26
26
|
"(when condition sexpr...)\n\nIff the condition evaluates to logically true, the `sexprs` are evaluated and the result of the last one is the result of the form, otherwise nil is the result.",
|
27
27
|
true) do |args, env|
|
28
|
-
Lisp::
|
28
|
+
Lisp::PrimSpecialForms::when_impl(args, env)
|
29
29
|
end
|
30
30
|
|
31
|
-
Primitive.register("unless",
|
31
|
+
Primitive.register("unless", ">=2",
|
32
32
|
"(unless condition sexpr...)\n\nIff the condition evaluates to logically false, the `sexprs` are evaluated and the result of the last one is the result of the form, otherwise nil is the result. This is the same functionally as `(when (not condition) sexpr...)` but is simpler and can be clearer.",
|
33
33
|
true) do |args, env|
|
34
|
-
Lisp::
|
34
|
+
Lisp::PrimSpecialForms::unless_impl(args, env)
|
35
35
|
end
|
36
36
|
|
37
|
-
Primitive.register("lambda",
|
38
|
-
"(lambda (param...) sexpr...)\n\nCreates an anonymous function. This can then be used in a function call.\n\n ((lambda (x)\n (+ x x))\n 5) ⇒ 10\n\nFunctions can be named (i.e. bound to a symbol) and later referred to by using define
|
37
|
+
Primitive.register("lambda", ">=1",
|
38
|
+
"(lambda ([param...]) sexpr...)\n\nCreates an anonymous function. This can then be used in a function call.\n\n ((lambda (x)\n (+ x x))\n 5) ⇒ 10\n\nFunctions can be named (i.e. bound to a symbol) and later referred to by using define:\n\n (define foo (lambda (x)\n (+ x x)))\n (foo 5) ⇒ 10\n\n`lambda` creates a local environment at the point of it’s evaluation. This environment is attached to the resulting function, and any binding or symbol lookup starts in this local environment.",
|
39
39
|
true) do |args, env|
|
40
|
-
Lisp::
|
40
|
+
Lisp::PrimSpecialForms::lambda_impl(args, env)
|
41
41
|
end
|
42
42
|
|
43
|
-
Primitive.register("define",
|
43
|
+
Primitive.register("define", ">=2",
|
44
44
|
"(define symbol value)\n\nEvaluates the value expression and binds it to the symbol, returning the value.",
|
45
45
|
true) do |args, env|
|
46
|
-
Lisp::
|
46
|
+
Lisp::PrimSpecialForms::define_impl(args, env)
|
47
47
|
end
|
48
48
|
|
49
|
-
Primitive.register("
|
50
|
-
"(defun (symbol param...) doc-string sexpr...)\n\nCreate a named function:\n\n`symbol` specifies the name (how you reference the function)\n\n`param...` parameters of the function, these are bound to the respective arguments when the function is called.\n\n`doc-string` is an optional documentation string.\n\n`sexpr...` the sequence of expressions that are evaluated in order when the function is called. The final evaluation result becomes the value of evaluation of the function.",
|
51
|
-
true) do |args, env|
|
52
|
-
Lisp::SpecialForms::defun_impl(args, env)
|
53
|
-
end
|
54
|
-
|
55
|
-
Primitive.register("defmacro",
|
49
|
+
Primitive.register("defmacro", "2|3",
|
56
50
|
"(defmacro (symbol param...) sexpr)\n\nCreate a named macro:\n\n`symbol` specifies the name (how you reference the macro)\n\n`param...` parameters of the macro, these are bound to the respective arguments when the macro is invoked. **NOTE** that the arguments to a macro invokation are **not** evaluated, but are passed as is to the macro to do with as it wishes.\n\n`sexpr` the template expression that is processed when the macro is invoked. The result of evaluating the processed template expression becomes the value of the macro's invocation.",
|
57
51
|
true) do |args, env|
|
58
|
-
Lisp::
|
52
|
+
Lisp::PrimSpecialForms::defmacro_impl(args, env)
|
59
53
|
end
|
60
54
|
|
61
|
-
Primitive.register("let",
|
55
|
+
Primitive.register("let", "*",
|
62
56
|
"(let ((name value)...) sexpr...)\n\nCreate a local scope and bindings for evaluating a body of code. The first argument is a list of bindings. Each binding is a raw symbol (doesn’t get evaluated) that is the name to be bound, and a value (which is evaluated). These bindings are added to a scope that is local to the let. The body is evaluated in this local scope. The value of the `let` is the last evaluation result. Bindings values are evaluated in the environment where the `let` is defined, and so are independant.",
|
63
57
|
true) do |args, env|
|
64
|
-
Lisp::
|
58
|
+
Lisp::PrimSpecialForms::let_impl(args, env)
|
65
59
|
end
|
66
60
|
|
67
|
-
Primitive.register("let*",
|
61
|
+
Primitive.register("let*", "*",
|
68
62
|
"(let* ((name value)...) sexpr...)\n\nCreate a local scope and bindings for evaluating a body of code. The first argument is a list of bindings. Each binding is a raw symbol (doesn’t get evaluated) that is the name to be bound, and a value (which is evaluated). Each binding’s value is evaluated in the context of the local scope. I.e. bindings cascade. The body is evaluated in this local scope. The value of the `let*` is the last evaluation result.",
|
69
63
|
true) do |args, env|
|
70
|
-
Lisp::
|
64
|
+
Lisp::PrimSpecialForms::letstar_impl(args, env)
|
71
65
|
end
|
72
66
|
|
73
|
-
Primitive.register("begin",
|
67
|
+
Primitive.register("begin", ">=1",
|
74
68
|
"(begin sexpr...)\n\nEvaluates the each `sexpr` in order, returning the result of the last one evaluated. Used in a context that allows a single `sexpr` but you need multiple.",
|
75
69
|
true) do |args, env|
|
76
|
-
Lisp::
|
70
|
+
Lisp::PrimSpecialForms::begin_impl(args, env)
|
77
71
|
end
|
78
72
|
|
79
|
-
Primitive.register("do",
|
73
|
+
Primitive.register("do", ">=2",
|
80
74
|
"(do ((name initial next)...) ((test sexpr...)) sexpr...)\n\nThis is a general purpose iteration construct. There are three sections:\n\nbindings\nThis is similar to `let` in that it defines names that can be used in the remainder of the scope of the `do`. Like `let` it is a list of lists, each starting with the binding name followed by the initial value of the binding. The difference is that this is followed by an expression that is evaluated at the beginning of each subsequent pass through the loop, and whose result is used as a new binding of the name.\n\ntermination\nThis is a list whose first element is an expression which is evaluated before each pass through the loop (after rebinding the variables). If it evaluates to a truthy value, the remaining expressions are evaluated in turn. The result of the final one is used as the value of the `do`.\n\nbody\nThis is a sequence of expressions that are evaluated in order each time though the loop. This section can be empty.",
|
81
75
|
true) do |args, env|
|
82
|
-
Lisp::
|
76
|
+
Lisp::PrimSpecialForms::do_impl(args, env)
|
83
77
|
end
|
84
78
|
|
85
|
-
Primitive.register("eval",
|
79
|
+
Primitive.register("eval", "1",
|
86
80
|
"(eval sexpr)\n\nEvaluate `sexpr`.",
|
87
81
|
true) do |args, env|
|
88
|
-
Lisp::
|
82
|
+
Lisp::PrimSpecialForms::eval_impl(args, env)
|
89
83
|
end
|
90
84
|
|
91
|
-
Primitive.register("apply",
|
85
|
+
Primitive.register("apply", ">=2",
|
92
86
|
"(apply function sexpr...)\n\nApply the function that results from evaluating `function` to the argument list resulting from evaluating each `sexpr`. Each initial `sexpr` can evaluate to any type of object, but the final one (and there must be at least one `sexpr`) must evaluate to a list.",
|
93
87
|
true) do |args, env|
|
94
|
-
Lisp::
|
88
|
+
Lisp::PrimSpecialForms::apply_impl(args, env)
|
95
89
|
end
|
96
90
|
|
97
|
-
Primitive.register("=>",
|
91
|
+
Primitive.register("=>", ">=2",
|
98
92
|
"(=> value sexpr|symbol...)\n\nThis creates a cascade.\n\n`value` (evaluated once at the beginning) is used as the initial argument to **each** function, and they are independent and do not pass results one to another. `value` is the result of the form.\n\nSince this is implemented by syntactic modification, a `lambda` form **cannot** be used here as an `sexpr`.",
|
99
93
|
true) do |args, env|
|
100
|
-
Lisp::
|
94
|
+
Lisp::PrimSpecialForms::tap_impl(args, env)
|
101
95
|
end
|
102
96
|
|
103
|
-
Primitive.register("->",
|
97
|
+
Primitive.register("->", ">=2",
|
104
98
|
"(-> value sexpr|symbol...)\n\nThis creates a function chain. `value` (evaluated first) is used as the first argument to the first `sexpr`. The result of each `sexpr` is used as the first argument of the next, and the result of the final `sexpr` is the value of the `->` form. If a `sexpr` would take a single argument (which would be provided by the `value` or the result of the previous `sexpr`, just the function name can be used. Since this is implemented by syntactic modification, a `lambda` form cannot be used here as an `sexpr`.\n\nThe form `(-> 0 a b c)` is equivalent to `(c (b (a 0)))`.",
|
105
99
|
true) do |args, env|
|
106
|
-
Lisp::
|
100
|
+
Lisp::PrimSpecialForms::chain_impl(args, env)
|
107
101
|
end
|
108
102
|
|
109
|
-
Primitive.register("quote", "
|
110
|
-
|
111
|
-
|
103
|
+
Primitive.register("quote", "1",
|
104
|
+
"(quote _expr_)\n\nSurpresses evaluation of the expression.\n\n (quote (+ 1 2)) ⇒ (+ 1 2)\n\nThere is a shortcut for quote that uses the single quote:\n\n '(+ 1 2) ⇒ (+ 1 2)",
|
105
|
+
true) do |args, env|
|
106
|
+
Lisp::PrimSpecialForms::quote_impl(args, env)
|
107
|
+
end
|
112
108
|
|
113
|
-
Primitive.register("quasiquote", "
|
114
|
-
|
115
|
-
|
109
|
+
Primitive.register("quasiquote", "1",
|
110
|
+
"(quasiquote _sexpr_)\n\nThis defines a template expression that can be filled in by unquote and unquote-splicing. The backquote character can be used as a shorthand for quasiquote: `sexpr.",
|
111
|
+
true) do |args, env|
|
112
|
+
Lisp::PrimSpecialForms::quasiquote_impl(args, env)
|
113
|
+
end
|
116
114
|
|
117
|
-
Primitive.register("gensym", "
|
118
|
-
used as the initial part of the symbol, otherwise GENSYM is used. gensym is
|
119
|
-
|
120
|
-
|
121
|
-
|
115
|
+
Primitive.register("gensym", "0|1",
|
116
|
+
"(gensym)\n(gensym _prefix_)\n\nThis creates a unique symbol. If you provide the optional prefix string it is used as the initial part of the symbol, otherwise GENSYM is used. gensym is useful in macros when you need a unique name for something.",
|
117
|
+
true) do |args, env|
|
118
|
+
Lisp::PrimSpecialForms::gensym_impl(args, env)
|
119
|
+
end
|
122
120
|
|
123
|
-
Primitive.register("expand", "
|
124
|
-
|
125
|
-
|
121
|
+
Primitive.register("expand", ">=1",
|
122
|
+
"(expand _symbol_ _sexpr_...)\n\nExpands the macro named by symbol, passing the evaluated sequence of sexpr as arguments.\n\nNOTE: whereas invoking the macro (in the same way you invoke a function) expands and evaluates, expand (as you would expect) only expands the macro, resulting in the expanded template sexpr. This can then be evaluated as desired.",
|
123
|
+
true) do |args, env|
|
124
|
+
Lisp::PrimSpecialForms::expand_impl(args, env)
|
125
|
+
end
|
126
|
+
|
127
|
+
Primitive.register("doc-string", "1",
|
128
|
+
"(doc-string _symbol_)\n\Prints the documentation associated with the form, function, or macro named by symbol.",
|
129
|
+
true) do |args, env|
|
130
|
+
Lisp::PrimSpecialForms::doc_string_impl(args, env)
|
131
|
+
end
|
132
|
+
|
133
|
+
Primitive.register("definition", "1",
|
134
|
+
"(definition _symbol_)\n\Prints the code associated with the function or macro named by symbol.",
|
135
|
+
true) do |args, env|
|
136
|
+
Lisp::PrimSpecialForms::definition_impl(args, env)
|
137
|
+
end
|
126
138
|
|
127
139
|
@@SYMBOL_COUNT = 0
|
128
140
|
end
|
@@ -169,7 +181,6 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
169
181
|
|
170
182
|
|
171
183
|
def self.if_impl(args, env)
|
172
|
-
return Lisp::Debug.process_error("IF requires a condition, true action, and possibly an else action", env) unless args.length == 2 || args.length == 3
|
173
184
|
condition = args.car.evaluate(env)
|
174
185
|
if condition.true?
|
175
186
|
args.cadr.evaluate(env)
|
@@ -182,7 +193,6 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
182
193
|
|
183
194
|
|
184
195
|
def self.when_impl(args, env)
|
185
|
-
return Lisp::Debug.process_error("WHEN requires a condition and sexprs to evaluate.", env) unless args.length >= 2
|
186
196
|
condition = args.car.evaluate(env)
|
187
197
|
return args.cdr.evaluate_each(env) if condition.true?
|
188
198
|
nil
|
@@ -190,7 +200,6 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
190
200
|
|
191
201
|
|
192
202
|
def self.unless_impl(args, env)
|
193
|
-
return Lisp::Debug.process_error("UNLESS requires a condition and sexprs to evaluate.", env) unless args.length >= 2
|
194
203
|
condition = args.car.evaluate(env)
|
195
204
|
return args.cdr.evaluate_each(env) unless condition.true?
|
196
205
|
nil
|
@@ -200,7 +209,7 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
200
209
|
def self.lambda_impl(args, env)
|
201
210
|
arguments = args.car
|
202
211
|
body = args.cdr
|
203
|
-
Lisp::Function.new("
|
212
|
+
Lisp::Function.new("anonymous_function", arguments.empty? ? nil : arguments, "", body, env)
|
204
213
|
end
|
205
214
|
|
206
215
|
|
@@ -208,7 +217,7 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
208
217
|
return Lisp::Debug.process_error("Variable names must be literal symbols.", env) unless definition.symbol?
|
209
218
|
|
210
219
|
ev = value.evaluate(env)
|
211
|
-
|
220
|
+
env.bind_locally(definition, ev)
|
212
221
|
ev
|
213
222
|
end
|
214
223
|
|
@@ -228,13 +237,6 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
228
237
|
end
|
229
238
|
|
230
239
|
|
231
|
-
def self.defun_impl(args, env)
|
232
|
-
definition = args.car
|
233
|
-
return Lisp::Debug.process_error("Function definition must specify name and parameters in a list", env) unless definition.list?
|
234
|
-
define_function(definition, args.cdr, env)
|
235
|
-
end
|
236
|
-
|
237
|
-
|
238
240
|
def self.define_impl(args, env)
|
239
241
|
definition = args.car
|
240
242
|
if definition.list?
|
@@ -247,12 +249,11 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
247
249
|
|
248
250
|
|
249
251
|
def self.defmacro_impl(args, env)
|
250
|
-
return Lisp::Debug.process_error("defmacro requires 2 or 3 arguments: a name and argument list, and a template expression.", env) unless args.length == 2 || args.length == 3
|
251
252
|
definition = args.car
|
252
253
|
return Lisp::Debug.process_error("defmacro requires macro name and args in a list as it's first argument.", env) if definition.nil? || !definition.list?
|
253
254
|
name = definition.car
|
254
255
|
arguments = definition.cdr
|
255
|
-
doc =
|
256
|
+
doc = ""
|
256
257
|
if args.cadr.string?
|
257
258
|
doc = args.cadr
|
258
259
|
body = args.caddr
|
@@ -275,13 +276,27 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
275
276
|
"GENSYM"
|
276
277
|
else
|
277
278
|
return Lisp::Debug.process_error("gensym's argument must be a string", env) unless args.car.string?
|
278
|
-
args.car.to_s
|
279
|
+
args.car.evaluate(env).to_s
|
279
280
|
end
|
280
281
|
sym = Lisp::Symbol.named("#{prefix}-#{@@SYMBOL_COUNT}")
|
281
282
|
@@SYMBOL_COUNT += 1
|
282
283
|
sym
|
283
284
|
end
|
284
285
|
|
286
|
+
|
287
|
+
def self.doc_string_impl(args, env)
|
288
|
+
thing = args.car.evaluate(env)
|
289
|
+
return Lisp::Debug.process_error("doc-string expects a form, macro, or function as its argument", env) unless thing.macro? || thing.function? || thing.primitive?
|
290
|
+
puts thing.doc
|
291
|
+
end
|
292
|
+
|
293
|
+
|
294
|
+
def self.definition_impl(args, env)
|
295
|
+
thing = args.car.evaluate(env)
|
296
|
+
return Lisp::Debug.process_error("definition expects a macro or function as its argument", env) unless thing.macro? || thing.function?
|
297
|
+
puts thing.body.print_string
|
298
|
+
end
|
299
|
+
|
285
300
|
|
286
301
|
def self.expand_impl(args, env)
|
287
302
|
macro = args.car.evaluate(env)
|
@@ -291,7 +306,9 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
291
306
|
|
292
307
|
|
293
308
|
def self.process_quasiquoted(sexpr, level, env)
|
294
|
-
if
|
309
|
+
if sexpr.nil?
|
310
|
+
ConsCell.new
|
311
|
+
elsif !sexpr.list?
|
295
312
|
ConsCell.cons(sexpr)
|
296
313
|
elsif sexpr.car.symbol? && sexpr.car.name == "quasiquote"
|
297
314
|
ConsCell.cons(ConsCell.cons(Symbol.named("quasiquote"), process_quasiquoted(sexpr.cadr, level + 1, env)))
|
@@ -308,7 +325,8 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
308
325
|
ConsCell.cons(ConsCell.cons(Symbol.named("unquote-splicing"), process_quasiquoted(sexpr.cadr, level - 1, env)))
|
309
326
|
end
|
310
327
|
else
|
311
|
-
|
328
|
+
processed_sexpr = sexpr.to_a.map {|e| process_quasiquoted(e, level, env)}
|
329
|
+
l = ConsCell.array_to_list(processed_sexpr).flatten
|
312
330
|
ConsCell.cons(l)
|
313
331
|
end
|
314
332
|
end
|
@@ -333,7 +351,7 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
333
351
|
def self.let_impl(args, env)
|
334
352
|
bindings = args.car || Lisp::ConsCell.new
|
335
353
|
return Lisp::Debug.process_error("let requires a list of bindings as it's firest argument", env) unless bindings.list?
|
336
|
-
local_frame = EnvironmentFrame.extending(env)
|
354
|
+
local_frame = EnvironmentFrame.extending(env, "let")
|
337
355
|
local_frame.previous = env
|
338
356
|
do_let_bindings(bindings, env, local_frame)
|
339
357
|
args.cdr.evaluate_each(local_frame)
|
@@ -343,7 +361,7 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
343
361
|
def self.letstar_impl(args, env)
|
344
362
|
bindings = args.car || Lisp::ConsCell.new
|
345
363
|
return Lisp::Debug.process_error("let requires a list of bindings as it's firest argument", env) unless bindings.list?
|
346
|
-
local_frame = EnvironmentFrame.extending(env)
|
364
|
+
local_frame = EnvironmentFrame.extending(env, "let*")
|
347
365
|
do_let_bindings(bindings, local_frame, local_frame)
|
348
366
|
args.cdr.evaluate_each(local_frame)
|
349
367
|
end
|
@@ -355,14 +373,13 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
355
373
|
|
356
374
|
|
357
375
|
def self.do_impl(args, env)
|
358
|
-
return Lisp::Debug.process_error("Do requires at least a list of bindings and a test clause", env) if args.length < 2
|
359
376
|
bindings = args.car
|
360
377
|
return Lisp::Debug.process_error("Do requires a list of bindings as it's first argument", env) unless bindings.list?
|
361
378
|
test_clause = args.cadr
|
362
379
|
return Lisp::Debug.process_error("Do requires a list of termination condition and result expressions as it's second argument", env) unless test_clause.list?
|
363
380
|
body = args.cddr
|
364
381
|
|
365
|
-
local_frame = EnvironmentFrame.extending(env)
|
382
|
+
local_frame = EnvironmentFrame.extending(env, "do")
|
366
383
|
local_frame.previous = env
|
367
384
|
|
368
385
|
bindings.each do |binding|
|
@@ -393,7 +410,6 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
393
410
|
|
394
411
|
|
395
412
|
def self.eval_impl(args, env)
|
396
|
-
return Lisp::Debug.process_error("eval expects a single argument, received #{args.length}.", env) if args.length != 1
|
397
413
|
arg = args.car.evaluate(env)
|
398
414
|
return Lisp::Debug.process_error("eval expect a list argument, received a #{arg.type}.", env) unless arg.list?
|
399
415
|
arg.evaluate(env)
|
@@ -402,20 +418,18 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
402
418
|
|
403
419
|
def self.apply_impl(args, env)
|
404
420
|
func = args.car.evaluate(env)
|
405
|
-
return Lisp::Debug.process_error("
|
421
|
+
return Lisp::Debug.process_error("apply required the first qrgument to be a function but it was #{args.car.to_s}.", env) unless func.primitive? || func.function?
|
406
422
|
|
407
423
|
a = args.cdr.to_a.collect {|sexpr| sexpr.evaluate(env)}
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
end
|
424
|
+
|
425
|
+
return Lisp::Debug.process_error("Apply required the last argument to bea list but it was #{a[-1].to_s}.", env) unless a[-1].list?
|
426
|
+
|
427
|
+
arg_list = Lisp::ConsCell.array_to_list(a[0..-2], a[-1])
|
413
428
|
func.apply_to(arg_list, env)
|
414
429
|
end
|
415
430
|
|
416
431
|
|
417
432
|
def self.chain_impl(args, env)
|
418
|
-
return Lisp::Debug.process_error("-> requires at the very least an initial value.", env) unless args.length > 0
|
419
433
|
value = args.car.evaluate(env)
|
420
434
|
cell = args.cdr
|
421
435
|
while !cell.nil?
|
@@ -434,7 +448,6 @@ useful in macros when you need a unique name for something.") do |args, env|
|
|
434
448
|
|
435
449
|
|
436
450
|
def self.tap_impl(args, env)
|
437
|
-
return Lisp::Debug.process_error("tap requires at the very least an initial value.", env) unless args.length > 0
|
438
451
|
value = args.car.evaluate(env)
|
439
452
|
cell = args.cdr
|
440
453
|
while !cell.nil?
|