1 // eval1.cpp Copyright (C) 1989-2021 Codemist
2
3 //
4 // Interpreter (part 1).
5 //
6
7 /**************************************************************************
8 * Copyright (C) 2021, Codemist. A C Norman *
9 * *
10 * Redistribution and use in source and binary forms, with or without *
11 * modification, are permitted provided that the following conditions are *
12 * met: *
13 * *
14 * * Redistributions of source code must retain the relevant *
15 * copyright notice, this list of conditions and the following *
16 * disclaimer. *
17 * * Redistributions in binary form must reproduce the above *
18 * copyright notice, this list of conditions and the following *
19 * disclaimer in the documentation and/or other materials provided *
20 * with the distribution. *
21 * *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
26 * COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
31 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
32 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
33 * DAMAGE. *
34 *************************************************************************/
35
36 // $Id: eval1.cpp 5739 2021-03-16 22:57:25Z arthurcnorman $
37
38 #include "headers.h"
39
nreverse(LispObject a)40 LispObject nreverse(LispObject a)
41 { LispObject b = nil;
42 while (consp(a))
43 { LispObject c = a;
44 a = cdr(a);
45 write_barrier(cdraddr(c), b);
46 b = c;
47 }
48 return b;
49 }
50
51 // Environments are represented as association lists, and have to cope
52 // with several sorts of things. The items in an environment can be
53 // in one of the following forms:
54 //
55 // (a) (symbol . value) normal lexical variable binding
56 // (b) (symbol . ~magic~) given symbol is (locally) special
57 // (c) (0 . tag) (block tag ...) marker
58 // (d) (1 . (tag ...)) (tagbody ... tag ...) marker
59 // (e) (2 . <anything>) case (c) or (d) but now invalidated
60 // (f) (def . symbol) (flet ...) or (macrolet ...) binding,
61 // where the def is non-atomic.
62 //
63 // Format for def in case (f)
64 //
65 // (1) (funarg env bvl ...) flet and labels for local function
66 // (2) (bvl ...) macrolet
67 // Note that 'funarg is not valid as a bvl
68 // and indeed in this case bvl is a list
69 // and can never be an atom.
70
eval(LispObject u,LispObject env)71 LispObject eval(LispObject u, LispObject env)
72 { STACK_SANITY;
73 assert (env == nil || consp(env));
74 #ifdef DEBUG
75 if (is_exception(u) || is_exception(env)) my_abort("exception value not trapped");
76 #endif // DEBUG
77 #ifdef CHECK_STACK
78 if (check_stack("@" __FILE__,__LINE__)) return aerror("deep stack in eval");
79 #endif
80 restart:
81 int t = static_cast<int>(u) & TAG_BITS;
82 // The first case considered is of symbols - lexical and special bindings
83 // have to be allowed for.
84 if (t == TAG_SYMBOL)
85 { Header h = qheader(u);
86 debug_record_symbol(u);
87 // I detect FLUID and GLOBAL variables because each of those situation is
88 // marked with a big in the symbol header. Both bits are set to mark
89 // a KEYWORD. In all such cases the value is in the symbol's value cell.
90 // If the symbol was fluid or global its value cell should have been
91 // initialized when it got declared, so I will not cgeck for "unset_var"
92 // again here.
93 if ((h & SYM_KEYWORD_VAR) != 0) return onevalue(qvalue(u));
94 // If a symbol is not global or fluid then it ought to be bound locally,
95 // ir mentioned in the environment. This can include as a special case it
96 // being subject to a local declaration that it is global! This is
97 // "deep binding".
98 else
99 { while (env != nil)
100 { LispObject p = car(env);
101 if (car(p) == u)
102 { LispObject v =cdr(p);
103 // If a variable is lexically bound to the value work_symbol that means
104 // that the symbol has been (lexically) declared to be special, so its
105 // value cell should be inspected.
106 if (v == work_symbol)
107 { v = qvalue(u);
108 // I will trigger the "unset variable" message if a variable is declared
109 // locally global but did not have a global value set.
110 if (v == unset_var) return error(1, err_unset_var, u);
111 }
112 return onevalue(v);
113 }
114 env = cdr(env);
115 }
116 // If a symbol has not been declared FLUID or GLOBAL and is not lovally
117 // bound then if I was feeling really cautious I would raise an error
118 // explaining that it should not be accessed. But that feels MEAN, and
119 // so I will treat it as if it had been made locally global. I COULD force
120 // it to be globally fluid here. There is a balance that has to be struck
121 // between error detection and convenience for the informal user!
122 { LispObject v = qvalue(u);
123 if (v == unset_var) return error(1, err_unset_var, u);
124 else return onevalue(v);
125 }
126 }
127 }
128 // Things that are neither symbols nor lists evaluate to themselves,
129 // e.g. numbers, characters, string and vectors. The special test for nil
130 // here is a throw-back to times when NIL was tagged as if a CONS. That
131 // happened in Common Lisp mode so that (car nil) and (cdr nil) could
132 // both yield nil without there needing to be any special treatment.
133 // My forward looking idea is that NIL will always be tagged as a symbol
134 // but in Common Lisp mode every CAR or CDR access will be checked for
135 // validity, and in the error case a special check for (CAR NIL) or
136 // (CDR NIL) will be made... In Standard Lisp mode there is no special
137 // issue to worry about here.
138 else if (t != TAG_CONS || u == nil) return onevalue(u);
139 else
140 {
141 // The final case is that of a list (fn ...), and one case that has to
142 // be checked is if fn is lexically bound.
143 LispObject fn, args;
144 stackcheck(u, env);
145 errexit();
146 fn = car(u);
147 args = cdr(u);
148 // Local function bindings must be looked for first. Well Standard Lisp
149 // does not have local function bindings, but Common Lisp does - hence the
150 // extra "fun" here.
151 { LispObject p;
152 if (is_symbol(fn)) // can only be a local function if atomic.
153 for (p=env; p!=nil; p=cdr(p))
154 { LispObject w = car(p);
155 // The form (<list> . sym) is used in an environment to indicate a local
156 // binding of a function, either as a regular function or as a macro
157 // (i.e. flet or macrolet). The structure of the list distinguishes
158 // between these two cases.
159 if (cdr(w) == fn && is_cons(w = car(w)) && w!=nil)
160 { p = car(w);
161 // p will now be (funarg env bvl ...body...) for a simple local
162 // function definition, or (bvl ...body...) with the bvl non-atomic
163 // for a local macro introduced using MACROLET.
164 if (p == funarg) // ordinary function
165 { fn = w; // (funarg ...) is OK to apply
166 goto ordinary_function;
167 }
168 // Here it is a local macro. Observe that the macroexpansion is done
169 // with respect to an empty environment. Macros that are defined at the same
170 // time may seem to be mutually recursive but there is a sense in which they
171 // are not (as well as a sense in which they are) - self and cross references
172 // only happen AFTER an expansion and can not happen during one.
173 Save save(u, env);
174 on_backtrace(
175 w = cons(lambda, w);
176 errexit();
177 p = apply(qvalue(macroexpand_hook),
178 list3(w, u, nil),
179 nil,
180 macroexpand_hook),
181 // now the error handler
182 save.restore(u, env);
183 if (SHOW_FNAME)
184 { err_printf("\nMacroexpanding: ");
185 loop_print_error(u);
186 });
187 save.restore(u, env);
188 u = p;
189 goto restart;
190 }
191 }
192 }
193 // Here I have dropped out from the search for a local definition of the
194 // function, so a global interpretation is needed.
195 if (is_symbol(fn))
196 {
197 // Special forms and (global) macros are checked for next. Special forms
198 // take precedence over macros.
199 Header h = qheader(fn);
200 debug_record_symbol(fn);
201 if (h & SYM_SPECIAL_FORM)
202 { STACK_SANITY1(u);
203 assert(qfn1(fn) != nullptr);
204 return (*qfn1(fn))(args, env);
205 }
206 else if (h & SYM_MACRO)
207 { STACK_SANITY;
208 Save save(u, env);
209 // the environment passed to macroexpand should only be needed to cope
210 // with macrolet, I think. Since I use just one datastructure for the
211 // whole environment I also pass along lexical bindings etc, but I hope that
212 // they will never be accessed. I do not think that macrolet is important
213 // enough to call for complication and slow-down in the interpreter this
214 // way - but then I am not exactly what you would call a Common Lisp Fan!
215 debug_record("About to expand a macro");
216 on_backtrace(
217 fn = macroexpand(u, env);
218 debug_record("macro expanded"),
219 // now the error handler
220 save.restore(u, env);
221 if (SHOW_FNAME)
222 { err_printf("\nMacroexpanding: ");
223 loop_print_error(u);
224 });
225 save.restore(u, env);
226 return eval(fn, env);
227 }
228 }
229 // Otherwise we have a regular function call. I prepare the args and
230 // call APPLY. In the Lisp 1.5 manual there was a call to EVLIS here.
231 // I want the same sort of effect, but will avoid any recursion as I
232 // evaluate all the arguments!
233 ordinary_function:
234 // Here I might reasonably unwind the process of evaluating arguments
235 // so that if I have at most 3 and if the function is a symbol I do
236 // things rather directly.
237 LispObject eargs = nil;
238 if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
239 { if (args == nil) return (*qfn0(fn))(fn);
240 LispObject a1 = car(args);
241 { Save save(fn, args, env);
242 on_backtrace(a1 = eval(a1, env),
243 save.restore(fn, args, env);
244 if (SHOW_ARGS)
245 { err_printf("\nEvaluating: ");
246 loop_print_error(car(args));
247 });
248 save.restore(fn, args, env);
249 }
250 args = cdr(args);
251 if (args == nil) return (*qfn1(fn))(fn, a1);
252 LispObject a2 = car(args);
253 { Save save(fn, args, env, a1);
254 on_backtrace(
255 a2 = eval(a2, env),
256 save.restore(fn, args, env, a1);
257 if (SHOW_ARGS)
258 { err_printf("\nEvaluating: ");
259 loop_print_error(car(args));
260 });
261 save.restore(fn, args, env, a1);
262 }
263 args = cdr(args);
264 if (args == nil) return (*qfn2(fn))(fn, a1, a2);
265 LispObject a3 = car(args);
266 { Save save(fn, args, env, a1, a2);
267 on_backtrace(
268 a3 = eval(a3, env),
269 save.restore(fn, args, env, a1, a2);
270 if (SHOW_ARGS)
271 { err_printf("\nEvaluating: ");
272 loop_print_error(car(args));
273 });
274 save.restore(fn, args, env, a1, a2);
275 }
276 args = cdr(args);
277 if (args == nil) return (*qfn3(fn))(fn, a1, a2, a3);
278 Save save(fn, env, args);
279 eargs = list3(a3, a2, a1);
280 errexit();
281 save.restore(fn, env, args);
282 }
283 // I have evaluated the first 3 args if the function was a symbol, so
284 // now I process the rest.
285 { STACK_SANITY1(u);
286 while (consp(args))
287 { LispObject w;
288 Save save(fn, args, env, eargs);
289 w = car(args);
290 on_backtrace(
291 w = eval(w, env),
292 // Now the error handler
293 save.restore(fn, args, env, eargs);;
294 if (SHOW_ARGS)
295 { err_printf("\nEvaluating: ");
296 loop_print_error(car(args));
297 });
298 save.restore(fn, args, env, eargs);
299 Save save1(fn, args, env);
300 eargs = cons(w, eargs);
301 errexit();
302 save1.restore(fn, args, env);
303 args = cdr(args);
304 }
305 eargs = nreverse(eargs);
306 // I pass the environment down to apply() because it will be used if the
307 // function was a simple lambda expression. If the function is a symbol
308 // or a closure, env will be irrelevant. The arguments are in a list.
309 return apply(fn, eargs, env, current_function);
310 }
311 }
312 }
313
314 // I am moving to a situation where the intepreter support &optional,
315 // &rest and keyword arguments and all the odd generality that Common Lisp
316 // introduces. This slows down the interpreter.
317
check_no_unwanted_keys(LispObject restarg,LispObject ok_keys)318 static bool check_no_unwanted_keys(LispObject restarg,
319 LispObject ok_keys)
320 // verify that there were no unwanted keys in the actual arg list
321 { bool odd_key_found = false;
322 while (restarg!=nil)
323 { LispObject k = car(restarg);
324 LispObject w;
325 for (w=ok_keys; w!=nil; w=cdr(w))
326 if (k == car(w)) goto is_ok;
327 odd_key_found = true;
328 is_ok:
329 restarg = cdr(restarg);
330 if (restarg==nil) return true; // odd length list
331 if (k == allow_key_key && car(restarg) != nil) return false; // OK
332 restarg = cdr(restarg);
333 }
334 return odd_key_found;
335 }
336
check_keyargs_even(LispObject restarg)337 static bool check_keyargs_even(LispObject restarg)
338 // check that list is even length with alternate items symbols in
339 // the keyword package. Return true in BAD case.
340 { while (restarg!=nil)
341 { LispObject q = car(restarg);
342 if (!is_symbol(q) || qpackage(q) != qvalue(keyword_package))
343 return true;
344 restarg = cdr(restarg);
345 if (restarg==nil) return true; // Odd length is wrong
346 restarg = cdr(restarg);
347 }
348 return false; // OK
349 }
350
keywordify(LispObject v)351 static LispObject keywordify(LispObject v)
352 { LispObject name = get_pname(v);
353 #ifdef COMMON
354 return Lintern_2(nil, name, qvalue(keyword_package));
355 #else
356 // For Standard Lisp I will force a ":" as the first character of the
357 // name, and than tag it as a "keyword".
358 if (basic_celt(name, 0) != ':')
359 { v = Lexplode(nil, v);
360 errexit();
361 v = list2star(fixnum_of_int('!'), fixnum_of_int(':'), v);
362 errexit();
363 v = Lcompress(nil, v);
364 errexit();
365 }
366 Lmake_keyword(nil, v);
367 return v;
368 #endif
369 }
370
key_lookup(LispObject keyname,LispObject args)371 static LispObject key_lookup(LispObject keyname, LispObject args)
372 { while (args!=nil)
373 { LispObject next = cdr(args);
374 if (next==nil) return nil;
375 if (car(args) == keyname) return next;
376 else args = cdr(next);
377 }
378 return nil;
379 }
380
381
382
instate_binding(LispObject var,LispObject val,LispObject local_decs1,LispObject & env,LispObject & specenv,LispObject & w)383 inline LispObject instate_binding(LispObject var, LispObject val,
384 LispObject local_decs1,
385 LispObject &env, LispObject &specenv,
386 LispObject &w)
387 { Header h;
388 // Complain if the varianble that somebody is attempting to bind seems bad.
389 if (!is_symbol(var) || (qheader(var) & SYM_GLOBAL_VAR)!=0)
390 return error(1, err_bad_bvl, var);
391 h = qheader(var);
392 // Special variables have their old value saved in the association list
393 // specenv, and then get updated.
394 if ((h & SYM_SPECIAL_VAR) != 0)
395 {
396 // Wow messy. var and val need to be made GC safe across the call to acons,
397 // but it would not be valid to use push and pop because the name "specenv"
398 // expands to a rerefence relative to the top of the stack.
399 specenv = acons_no_gc(var, qvalue(var), specenv);
400 setvalue(var, val);
401 cons_gc_test(nil);
402 errexit();
403 }
404 else
405 {
406 // If something is not globally special it may still have been locally
407 // declared special, so I scan the environment. I clobber local declarations
408 // when I use them so that they do not get applied multiple times.
409 for (w = local_decs1; w!=nil; w = cdr(w))
410 { if (car(w) == var)
411 { setcar(w, fixnum_of_int(0)); // decl is used up
412 env = acons(var, work_symbol, env);
413 errexit();
414 specenv = acons_no_gc(var, qvalue(var), specenv);
415 setvalue(var, val);
416 cons_gc_test(nil);
417 errexit();
418 }
419 }
420 // Finally simple lexical bindings use deep binding.
421 env = acons(var, val, env);
422 }
423 return nil;
424 }
425
426 // arglist is in fact a value on the Lisp stack.
427
next_arg(LispObject & arglist)428 inline LispObject next_arg(LispObject &arglist)
429 { LispObject r = car(arglist);
430 arglist = cdr(arglist);
431 return r;
432 }
433
apply_lambda(LispObject def,LispObject args,LispObject env1,LispObject name1)434 LispObject apply_lambda(LispObject def, LispObject args,
435 LispObject env1, LispObject name1)
436 // Here def is a lambda expression (sans the initial lambda) that is to
437 // be applied. Much horrible messing about is needed so that I can cope
438 // with &optional and &rest args (including initialisers and supplied-p
439 // variables, also &key, &allow-other-keys and &aux). Note the need to find
440 // any special declarations at the head of the body of the lambda-form.
441 // Much of the reall mess here is because I am supporting features that
442 // Common Lisp introduced but that my use of Lisp does not actually use!
443 //
444 // The final argument "name1" may be used in backtrces of otherwise for
445 // debugging: when you are calling an interpreted function it may be the
446 // name of that function and if you are applying a free-standing lambda
447 // expression it may be the whole expression. At present it is not used.
448 {
449 // lambda-lists are parsed using a finite state engine with the
450 // following states, plus an exit state.
451 #define STATE_NULL 0 // at start and during regular args
452 #define STATE_OPT 1 // after &optional
453 #define STATE_OPT1 2 // after &optional + at least one var
454 #define STATE_REST 3 // immediately after &rest
455 #define STATE_REST1 4 // after &rest vv
456 #define STATE_KEY 5 // &key with no &rest
457 #define STATE_ALLOW 6 // &allow-other-keys
458 #define STATE_AUX 7 // &aux
459 int opt_rest_state = STATE_NULL;
460 int args_left = 0;
461 for (LispObject u=args; u!=nil; u=cdr(u)) args_left++;
462 LispObject w1;
463 if (!consp(def)) return onevalue(nil); // Should never happen
464 stackcheck(def, args, env1, name1);
465 w1 = car(def);
466 // The next fragment is horrible but is here because at present I have a
467 // precise garbage collector and all the values set up here need to act
468 // as list-bases.
469 RealSave save(args, // arglist
470 w1, // bvl
471 cdr(def), // body
472 env1,
473 name1,
474 PushCount(10));
475 LispObject &arglist = save.val(1);
476 LispObject &bvl = save.val(2);
477 LispObject &body = save.val(3);
478 LispObject &env = save.val(4);
479 // LispObject &name = save.val(5); // not used at present!
480 LispObject &local_decs = save.val(6);
481 LispObject &ok_keys = save.val(7);
482 LispObject &restarg = save.val(8);
483 LispObject &specenv = save.val(9);
484 LispObject &val1 = save.val(10);
485 LispObject &arg = save.val(11);
486 LispObject &v1 = save.val(12);
487 LispObject &v = save.val(13);
488 LispObject &p = save.val(14);
489 LispObject &w = save.val(15);
490 for (;;)
491 { if (!consp(body)) break;
492 // I used to macroexpand things here in case a macro might expand into
493 // a DECLARE expression, but versions of the Common Lisp specification later
494 // than the one I originally looked at say that DECLARE may only appear
495 // directly and manifestly, so I can avoid that extra step.
496 p = car(body);
497 body = cdr(body);
498 if (!consp(p))
499 { if (stringp(p) &&
500 consp(body)) continue; // string is comment here.
501 body = cons(p, body); // other atoms get stuck back on body.
502 break;
503 }
504 if (car(p) != declare_symbol)
505 { body = cons(p, body); // something other than a "declare".
506 errexit();
507 break;
508 }
509 // I have found a body that was initially something like
510 // ("string" "string" (declare ...) ...)
511 // and I have discarded the strings and here p is the part that starts
512 // with the symbol DECLARE.
513 for (v = cdr(p); consp(v); v = cdr(v))
514 { v1 = car(v);
515 // scan looking for (SPECIAL ...)
516 if (!consp(v1) || car(v1) != special_symbol) continue;
517 // here v1 says (special ...)
518 for (v1=cdr(v1); consp(v1); v1 = cdr(v1))
519 { local_decs = cons(car(v1), local_decs);
520 errexit();
521 }
522 }
523 // I keep going so that several DECLARE expressions one after the other will
524 // be supported. Note that the way I have coded this allows strings interleaved
525 // amongst the DECLARE expressions. I think that is not supposed to be
526 // permitted.
527 }
528 // Next parse the BVL
529 TRY
530 for (p = bvl; consp(p); p=cdr(p))
531 { v = car(p);
532 v1 = nil;
533 arg = nil;
534 val1 = nil;
535 // I can break from this switch statement with v a variable to bind
536 // and arg the value to bind to it, also v1 (if not nil) is a second
537 // variable to be bound (a supplied-p value) and val1 the value to bind it to.
538 // If I see &rest or &key the remaining actual args get collected into
539 // restarg, which takes the place of arg in some respects.
540 switch (opt_rest_state)
541 { case STATE_NULL:
542 if (v == opt_key)
543 { opt_rest_state = STATE_OPT;
544 continue;
545 }
546 if (v == rest_key)
547 { restarg = arglist;
548 opt_rest_state = STATE_REST;
549 continue;
550 }
551 if (v == key_key)
552 { restarg = arglist;
553 if (check_keyargs_even(restarg)) return error(1, err_bad_keyargs, restarg);
554 opt_rest_state = STATE_KEY;
555 continue;
556 }
557 if (v == aux_key)
558 { if (args_left != 0) return error(0, err_excess_args);
559 opt_rest_state = STATE_AUX;
560 continue;
561 }
562 if (v == allow_other_keys) return error(1, err_bad_bvl, v);
563 if (args_left == 0) return error(0, err_insufficient_args);
564 arg = next_arg(arglist); // the simple case!
565 args_left--;
566 v1 = nil; // no suppliedp mess here, I'm glad to say
567 break;
568
569 case STATE_OPT:
570 if (v == opt_key
571 || v == rest_key
572 || v == key_key
573 || v == allow_other_keys
574 || v == aux_key
575 ) return error(1, err_bad_bvl, v);
576 // Here v may be a simple variable, or a list (var init suppliedp)
577 opt_rest_state = STATE_OPT1;
578 process_optional_parameter:
579 if (args_left != 0)
580 { arg = next_arg(arglist); // Arg available for optional
581 args_left--;
582 val1 = lisp_true;
583 }
584 else
585 { arg = nil;
586 val1 = nil;
587 }
588 v1 = nil;
589 if (!consp(v)) break; // Simple case
590 { w = cdr(v);
591 v = car(v);
592 if (!consp(w)) break; // (var)
593 if (val1 == nil) // use the init form
594 { arg = car(w);
595 arg = eval(arg, env);
596 errexit();
597 }
598 w = cdr(w);
599 if (consp(w)) v1 = car(w); // suppliedp name
600 break;
601 }
602
603 case STATE_OPT1:
604 if (v == rest_key)
605 { restarg = arglist;
606 opt_rest_state = STATE_REST;
607 continue;
608 }
609 if (v == key_key)
610 { restarg = arglist;
611 if (check_keyargs_even(restarg)) return error(1, err_bad_keyargs, restarg);
612 opt_rest_state = STATE_KEY;
613 continue;
614 }
615 if (v == aux_key)
616 { if (args_left != 0) return error(0, err_excess_args);
617 opt_rest_state = STATE_AUX;
618 continue;
619 }
620 if (v == opt_key ||
621 v == allow_other_keys) return error(1, err_bad_bvl, v);
622 goto process_optional_parameter;
623
624 case STATE_REST:
625 if (v == opt_key
626 || v == rest_key
627 || v == key_key
628 || v == allow_other_keys
629 || v == aux_key
630 ) error(1, err_bad_bvl, v);
631 opt_rest_state = STATE_REST1;
632 arg = restarg;
633 break;
634
635 case STATE_REST1:
636 if (v == key_key)
637 { if (check_keyargs_even(restarg)) return error(1, err_bad_keyargs,
638 restarg);
639 opt_rest_state = STATE_KEY;
640 continue;
641 }
642 if (v == aux_key)
643 { opt_rest_state = STATE_AUX;
644 continue;
645 }
646 return error(1, err_bad_bvl, rest_key);
647
648 case STATE_KEY:
649 if (v == allow_other_keys)
650 { opt_rest_state = STATE_ALLOW;
651 continue;
652 }
653 if (v == aux_key)
654 { if (check_no_unwanted_keys(restarg, ok_keys))
655 return error(1, err_bad_keyargs, restarg);
656 opt_rest_state = STATE_AUX;
657 continue;
658 }
659 if (v == opt_key || v == rest_key || v == key_key)
660 return error(1, err_bad_bvl, v);
661 process_keyword_parameter:
662 // v needs to expand to ((:kv v) init svar) in effect here.
663 { LispObject keyname = nil;
664 w = nil;
665 if (!consp(v))
666 { if (!is_symbol(v) || v==nil || v==lisp_true)
667 return error(1, err_bad_bvl, v);
668 keyname = keywordify(v);
669 errexit();
670 }
671 else
672 { w = cdr(v);
673 v = car(v);
674 if (!consp(v))
675 { if (!is_symbol(v) || v==nil || v==lisp_true)
676 return error(1, err_bad_bvl, v);
677 keyname = keywordify(v);
678 errexit();
679 }
680 else
681 { keyname = car(v);
682 if (!is_symbol(keyname) || v==nil || v ==lisp_true)
683 return error(1, err_bad_bvl, v);
684 keyname = keywordify(keyname);
685 errexit();
686 v = cdr(v);
687 if (consp(v)) v = car(v);
688 else return error(1, err_bad_bvl, v);
689 }
690 }
691 ok_keys = cons(keyname, ok_keys);
692 arg = key_lookup(car(ok_keys), restarg);
693 errexit();
694 if (arg == nil) val1 = nil;
695 else
696 { arg = car(arg);
697 val1 = lisp_true;
698 }
699 v1 = nil;
700 if (!consp(w)) break; // (var)
701 if (val1 == nil) // use the init form
702 { arg = car(w);
703 arg = eval(arg, env);
704 errexit();
705 }
706 w = cdr(w);
707 if (consp(w)) v1 = car(w); // suppliedp name
708 break;
709 }
710
711 case STATE_ALLOW:
712 if (v == aux_key)
713 { opt_rest_state = STATE_AUX;
714 continue;
715 }
716 if (v == opt_key || v == rest_key || v == key_key ||
717 v == allow_other_keys) return error(1, err_bad_bvl, v);
718 goto process_keyword_parameter;
719
720 case STATE_AUX:
721 if (v == opt_key || v == rest_key ||
722 v == key_key || v == allow_other_keys ||
723 v == aux_key) return error(1, err_bad_bvl, v);
724 if (consp(v))
725 { w = cdr(v);
726 v = car(v);
727 if (consp(w))
728 { arg = car(w);
729 arg = eval(arg, env);
730 errexit();
731 }
732 }
733 else arg = nil;
734 v1 = nil;
735 break;
736 }
737 instate_binding(v, arg, local_decs, env, specenv, w);
738 errexit();
739 if (v1 != nil)
740 { instate_binding(v1, val1, local_decs, env, specenv, w);
741 errexit();
742 }
743 } // End of for loop that scans BVL
744
745 // As well as local special declarations that have applied to bindings here
746 // there can be some that apply just to variable references within the body.
747 while (local_decs!=nil)
748 { LispObject q = car(local_decs);
749 local_decs=cdr(local_decs);
750 if (!is_symbol(q)) continue;
751 env = acons(q, work_symbol, env);
752 errexit();
753 }
754
755 switch (opt_rest_state)
756 { case STATE_NULL:
757 case STATE_OPT1: // Ensure there had not been too many args
758 if (args_left != 0) return error(0, err_excess_args);
759 break;
760
761 case STATE_OPT: // error if bvl finishes here
762 case STATE_REST:
763 return error(1, err_bad_bvl,
764 opt_rest_state == STATE_OPT ? opt_key : rest_key);
765
766 case STATE_KEY: // ensure only valid keys were given
767 if (check_no_unwanted_keys(restarg, ok_keys))
768 return error(1, err_bad_keyargs, restarg);
769 break;
770
771 default:
772 //case STATE_REST1:
773 //case STATE_ALLOW:
774 //case STATE_AUX:
775 break;
776 }
777
778 // Now all the argument bindings have been performed - it remains to
779 // process the body of the lambda-expression.
780 { exit_count = 1;
781 def = progn_fn(body, env);
782 errexit();
783 while (specenv != nil)
784 { LispObject bv = car(specenv);
785 setvalue(car(bv), cdr(bv));
786 specenv = cdr(specenv);
787 }
788 }
789 CATCH(LispException)
790 // On any exception raised above I will need to restore any fluid bindings
791 // that have been made.
792 while (specenv != nil)
793 { LispObject bv = car(specenv);
794 setvalue(car(bv), cdr(bv));
795 specenv = cdr(specenv);
796 }
797 RETHROW;
798 END_CATCH;
799 // note that exit_count has not been disturbed since I called progn_fn,
800 // so the number of values that will be returned remains correctly
801 // established.
802 return def;
803 }
804
Leval(LispObject env,LispObject a)805 LispObject Leval(LispObject env, LispObject a)
806 { save_current_function saver(eval_symbol);
807 return eval(a, nil); // Multiple values may be returned
808 }
809
Levlis(LispObject env,LispObject a)810 LispObject Levlis(LispObject env, LispObject a)
811 { STACK_SANITY;
812 save_current_function saver(eval_symbol);
813 LispObject r;
814 stackcheck(a);
815 errexit();
816 r = nil;
817 while (consp(a))
818 { { Save save(a);
819 LispObject a1;
820 { Save save1(r);
821 a1 = car(a);
822 a1 = eval(a1, nil);
823 errexit();
824 save1.restore(r);
825 }
826 r = cons(a1, r);
827 errexit();
828 save.restore(a);
829 }
830 a = cdr(a);
831 }
832 return onevalue(nreverse(r));
833 }
834
835 // The Lisp-level APPLY functions could potentially confuse. What we have is
836 //
837 // (APPLY fn a1 a2 .. an)
838 // The simple form of this is just (APPLY fn a1) where a1 is a list of
839 // all the arguments to be passed,. All the cases where more arguments are
840 // given behave rather like
841 // (APPLY fn (LIST* a1 a2 ... an)).
842 // In my C code here these cases are Lapply_1, Lapply_2 etc.
843
Lapply_4up(LispObject env,LispObject fn,LispObject a1,LispObject a2,LispObject a3up)844 LispObject Lapply_4up(LispObject env, LispObject fn, LispObject a1,
845 LispObject a2, LispObject a3up)
846 { STACK_SANITY;
847 save_current_function saver(apply_symbol);
848 // Here I have something like
849 // (APPLY fn a1 a2 (a3 a4 a5up))
850 // where a5up will be a list (a5 a6 ...).
851 a3up = Lreverse(nil, a3up);
852 errexit();
853 a3up = nreverse2(cdr(a3up), car(a3up));
854 // I have just flattened out the final argument.
855 { Save save(fn);
856 a1 = list2star(a1, a2, a3up);
857 save.restore(fn);
858 }
859 errexit();
860 return apply(fn, a1, nil, apply_symbol);
861 }
862
863 // This may look odd at first sight, but what is happening is that the
864 // basic case is (APPLY f arglist) where arglist is a list of arguments.
865 // As a concession (APPLY f) is treated as if it had been (APPLY f nil), ie
866 // no arguments are passed. For more arguments (APPLY f a1 a2 .. rest)
867 // treates all but the final argument as being individual actual arguments,
868 // and the last one passed is a list of extras.
869
Lapply_1(LispObject env,LispObject fn)870 LispObject Lapply_1(LispObject env, LispObject fn)
871 { save_current_function saver(apply_symbol);
872 return apply(fn, nil, nil, apply_symbol);
873 }
874
Lapply_2(LispObject env,LispObject fn,LispObject a1)875 LispObject Lapply_2(LispObject env, LispObject fn, LispObject a1)
876 { save_current_function saver(apply_symbol);
877 return apply(fn, a1, nil, apply_symbol);
878 }
879
Lapply_3(LispObject env,LispObject fn,LispObject a1,LispObject a2)880 LispObject Lapply_3(LispObject env, LispObject fn, LispObject a1,
881 LispObject a2)
882 { save_current_function saver(apply_symbol);
883 { Save save(fn);
884 a1 = cons(a1, a2);
885 save.restore(fn);
886 }
887 errexit();
888 return apply(fn, a1, nil, apply_symbol);
889 }
890
891 // Next I have (APPLY0 fn), (APPLY1 fn a1), (APPLY2 fr a1 a2) where the
892 // name of the function indicates the number of arguments to be involved.
893
Lapply0(LispObject env,LispObject fn)894 LispObject Lapply0(LispObject env, LispObject fn)
895 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
896 return (*qfn0(fn))(fn);
897 return Lapply_2(env, fn, nil);
898 }
899
Lapply1(LispObject env,LispObject fn,LispObject a1)900 LispObject Lapply1(LispObject env, LispObject fn, LispObject a1)
901 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
902 return (*qfn1(fn))(fn, a1);
903 Save save(fn, env);
904 a1 = ncons(a1);
905 errexit();
906 save.restore(fn, env);
907 return Lapply_2(env, fn, a1);
908 }
909
Lapply2(LispObject env,LispObject fn,LispObject a1,LispObject a2)910 LispObject Lapply2(LispObject env, LispObject fn,
911 LispObject a1, LispObject a2)
912 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
913 return (*qfn2(fn))(fn, a1, a2);
914 { Save save(env, fn);
915 a1 = list2(a1, a2);
916 save.restore(env, fn);
917 }
918 errexit();
919 return Lapply_2(env, fn, a1);
920 }
921
Lapply3(LispObject env,LispObject fn,LispObject a1,LispObject a2,LispObject a3up)922 LispObject Lapply3(LispObject env, LispObject fn,
923 LispObject a1, LispObject a2, LispObject a3up)
924 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
925 { LispObject a3 = arg4("apply3", a3up);
926 return (*qfn3(fn))(fn, a1, a2, a3);
927 }
928 LispObject a3 = arg4("apply3", a3up);
929 { Save save(env, fn);
930 a1 = list3(a1, a2, a3);
931 save.restore(env, fn);
932 }
933 errexit();
934 return Lapply_2(env, fn, a1);
935 }
936
937 // Finally I can have (FUNCALL fn a1 ...) which behaves like
938 // APPLY0, APPLY1,... for few arguments and continues passing more
939 // of its own arguments to the called function.
940
Lfuncall_1(LispObject env,LispObject fn)941 LispObject Lfuncall_1(LispObject env, LispObject fn)
942 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
943 return (*qfn0(fn))(fn);
944 return Lapply_2(env, fn, nil);
945 }
946
Lfuncall_2(LispObject env,LispObject fn,LispObject a1)947 LispObject Lfuncall_2(LispObject env, LispObject fn, LispObject a1)
948 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
949 return (*qfn1(fn))(fn, a1);
950 { Save save(env, fn);
951 a1 = ncons(a1);
952 save.restore(env, fn);
953 }
954 errexit();
955 return Lapply_2(env, fn, a1);
956 }
957
Lfuncall_3(LispObject env,LispObject fn,LispObject a1,LispObject a2)958 LispObject Lfuncall_3(LispObject env, LispObject fn,
959 LispObject a1, LispObject a2)
960 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
961 return (*qfn2(fn))(fn, a1, a2);
962 { Save save(env, fn);
963 a1 = list2(a1, a2);
964 save.restore(env, fn);
965 }
966 errexit();
967 return Lapply_2(env, fn, a1);
968 }
969
Lfuncall_4up(LispObject env,LispObject fn,LispObject a1,LispObject a2,LispObject a3up)970 LispObject Lfuncall_4up(LispObject env, LispObject fn,
971 LispObject a1, LispObject a2, LispObject a3up)
972 { if (is_symbol(fn) && (qheader(fn) & SYM_TRACED) == 0)
973 { if (cdr(a3up) == nil) return (*qfn3(fn))(fn, a1, a2, car(a3up));
974 else return (*qfn4up(fn))(fn, a1, a2, car(a3up), cdr(a3up));
975 }
976 { Save save(env, fn);
977 a1 = list2star(a1, a2, a3up);
978 save.restore(env, fn);
979 }
980 errexit();
981 return Lapply_2(env, fn, a1);
982 }
983
984 // My initial implementation of multiple values insists that every function
985 // set a value-count on exit. That is onerous and puts a cost almost
986 // everywhere. I want to move to a model where before entering a function the
987 // value-count variable is set to 1, and the function only changes it if it
988 // needs to. In the interpreter that will be easy I believe. For the compiler
989 // it will mean that after any call to an unknown function (or one liable to
990 // return multiple values) the count variable is reset on the path to any
991 // and before a call to any other function that could possibly (directly or
992 // indirectly) rely on how many values were in play. The most naive version
993 // of that would involve resetting the count to 1 after any call to anything
994 // unknown. If I go that way it will be in the future.
995 // Well the scheme indicated above favours leaf procedures and so is
996 // liable to clean up the C++-coded kernel a fair deal. But it looks to
997 // me as if for non-leaf things it is less help.
998
Lvalues_4up(LispObject env,LispObject a1,LispObject a2,LispObject a3,LispObject a4up)999 LispObject Lvalues_4up(LispObject env, LispObject a1, LispObject a2,
1000 LispObject a3, LispObject a4up)
1001 { mv_2 = a2;
1002 mv_3 = a3;
1003 // Because multiple-values get passed back in static storage there is
1004 // a fixed upper limit to how many I can handle - truncate here to allow
1005 // for that.
1006 int n = 3;
1007 for (int i=4; i<=50; i++)
1008 { if (a4up == nil) break;
1009 workbase[i] = car(a4up);
1010 a4up = cdr(a4up);
1011 n++;
1012 }
1013 return nvalues(a1, n);
1014 }
1015
Lvalues_3(LispObject env,LispObject a,LispObject b,LispObject c)1016 LispObject Lvalues_3(LispObject env, LispObject a, LispObject b,
1017 LispObject c)
1018 { mv_2 = b;
1019 mv_3 = c;
1020 return nvalues(a, 3);
1021 }
1022
Lvalues_2(LispObject env,LispObject a,LispObject b)1023 LispObject Lvalues_2(LispObject env, LispObject a, LispObject b)
1024 { mv_2 = b;
1025 return nvalues(a, 2);
1026 }
1027
Lvalues_1(LispObject env,LispObject a)1028 LispObject Lvalues_1(LispObject env, LispObject a)
1029 { return onevalue(a);
1030 }
1031
Lvalues_0(LispObject env)1032 LispObject Lvalues_0(LispObject env)
1033 { return nvalues(nil, 0);
1034 }
1035
mv_call_fn(LispObject args,LispObject env)1036 LispObject mv_call_fn(LispObject args, LispObject env)
1037 // Here with the rest of the interpreter rather than with other
1038 // special forms because this is so closely related to APPLY.
1039 // (MULTIPLE-VALUE-CALL 'fn (values a1 a2)
1040 // (values a3 a4 a5) a6 (values a7 a8))
1041 // (for example) is rather like
1042 // (FUNCALL 'fn a1 a2 a3 a4 a5 a6 a7 a8)
1043 { STACK_SANITY;
1044 save_current_function saver(mv_call_symbol);
1045 if (!consp(args)) return nil; // (multiple-value-call) => nil
1046 stackcheck(args, env);
1047 LispObject fn;
1048 { Save save(args, env);
1049 fn = car(args);
1050 fn = eval(fn, env);
1051 save.restore(args, env);
1052 }
1053 errexit();
1054 args = cdr(args);
1055 Save save1(fn);
1056 LispObject xargs = nil; // for list of eventual args
1057 while (consp(args))
1058 { LispObject r1;
1059 { RealSave save(args, env, xargs);
1060 // LispObject &arg1 = save.val(1);
1061 // LispObject &env1 = save.val(2);
1062 LispObject &xargs1 = save.val(3);
1063 r1 = car(args);
1064 exit_count = 1;
1065 r1 = eval(r1, env);
1066 errexit();
1067 if (exit_count != 0) xargs1 = cons(r1, xargs1);
1068 for (unsigned int i=2; i<=exit_count; i++)
1069 { xargs1 = cons((&work_0)[i], xargs1);
1070 errexit();
1071 }
1072 save.restore(args, env, xargs);
1073 }
1074 args = cdr(args);
1075 }
1076 save1.restore(fn);
1077 return apply(fn, xargs, env, mv_call_symbol);
1078 }
1079
interpreted_0(LispObject def)1080 LispObject interpreted_0(LispObject def)
1081 { STACK_SANITY;
1082 save_current_function saver(def);
1083 stackcheck(def);
1084 errexit();
1085 return apply_lambda(qenv(def), nil, nil, def);
1086 }
1087
interpreted_1(LispObject def,LispObject a1)1088 LispObject interpreted_1(LispObject def, LispObject a1)
1089 { STACK_SANITY;
1090 save_current_function saver(def);
1091 stackcheck(def, a1);
1092 errexit();
1093 { Save save(def);
1094 a1 = ncons(a1);
1095 save.restore(def);
1096 }
1097 errexit();
1098 return apply_lambda(qenv(def), a1, nil, def);
1099 }
1100
interpreted_2(LispObject def,LispObject a1,LispObject a2)1101 LispObject interpreted_2(LispObject def, LispObject a1, LispObject a2)
1102 { STACK_SANITY;
1103 save_current_function saver(def);
1104 stackcheck(def, a1, a2);
1105 errexit();
1106 { Save save(def);
1107 a1 = list2(a1, a2);
1108 save.restore(def);
1109 }
1110 errexit();
1111 return apply_lambda(qenv(def), a1, nil, def);
1112 }
1113
interpreted_3(LispObject def,LispObject a1,LispObject a2,LispObject a3)1114 LispObject interpreted_3(LispObject def, LispObject a1, LispObject a2,
1115 LispObject a3)
1116 { STACK_SANITY;
1117 save_current_function saver(def);
1118 stackcheck(def, a1, a2, a3);
1119 errexit();
1120 { Save save(def);
1121 a1 = list3(a1, a2, a3);
1122 save.restore(def);
1123 }
1124 errexit();
1125 return apply_lambda(qenv(def), a1, nil, def);
1126 }
1127
interpreted_4up(LispObject def,LispObject a1,LispObject a2,LispObject a3,LispObject a4up)1128 LispObject interpreted_4up(LispObject def, LispObject a1,
1129 LispObject a2,
1130 LispObject a3, LispObject a4up)
1131 { STACK_SANITY;
1132 save_current_function saver(def);
1133 stackcheck(a1, a2, a3, a4up);
1134 errexit();
1135 { Save save(def);
1136 a1 = list3star(a1, a2, a3, a4up);
1137 save.restore(def);
1138 }
1139 errexit();
1140 return apply_lambda(qenv(def), a1, nil, def);
1141 }
1142
funarged_0(LispObject def)1143 LispObject funarged_0(LispObject def)
1144 { STACK_SANITY;
1145 save_current_function saver(def);
1146 stackcheck(def);
1147 errexit();
1148 def = qenv(def);
1149 return apply_lambda(cdr(def), nil, car(def), cdr(def));
1150 }
1151
funarged_1(LispObject def,LispObject a1)1152 LispObject funarged_1(LispObject def, LispObject a1)
1153 { STACK_SANITY;
1154 save_current_function saver(def);
1155 stackcheck(def, a1);
1156 errexit();
1157 def = qenv(def);
1158 { Save save(def);
1159 a1 = ncons(a1);
1160 save.restore(def);
1161 }
1162 errexit();
1163 return apply_lambda(cdr(def), a1, car(def), cdr(def));
1164 }
1165
funarged_2(LispObject def,LispObject a1,LispObject a2)1166 LispObject funarged_2(LispObject def, LispObject a1, LispObject a2)
1167 { STACK_SANITY;
1168 save_current_function saver(def);
1169 stackcheck(def, a1, a2);
1170 errexit();
1171 def = qenv(def);
1172 { Save save(def);
1173 a1 = list2(a1, a2);
1174 save.restore(def);
1175 }
1176 errexit();
1177 return apply_lambda(cdr(def), a1, car(def), cdr(def));
1178 }
1179
funarged_3(LispObject def,LispObject a1,LispObject a2,LispObject a3)1180 LispObject funarged_3(LispObject def, LispObject a1, LispObject a2,
1181 LispObject a3)
1182 { STACK_SANITY;
1183 save_current_function saver(def);
1184 stackcheck(def, a1, a2, a3);
1185 errexit();
1186 def = qenv(def);
1187 { Save save(def);
1188 a1 = list3(a1, a2, a3);
1189 save.restore(def);
1190 }
1191 errexit();
1192 return apply_lambda(cdr(def), a1, car(def), cdr(def));
1193 }
1194
funarged_4up(LispObject def,LispObject a1,LispObject a2,LispObject a3,LispObject a4up)1195 LispObject funarged_4up(LispObject def, LispObject a1, LispObject a2,
1196 LispObject a3, LispObject a4up)
1197 { STACK_SANITY;
1198 save_current_function saver(def);
1199 def = qenv(def);
1200 stackcheck(a1, a2, a3, a4up);
1201 errexit();
1202 { Save save(def);
1203 a1 = list3star(a1, a2, a3, a4up);
1204 save.restore(def);
1205 }
1206 errexit();
1207 return apply_lambda(cdr(def), a1, car(def), cdr(def));
1208 }
1209
macroexpand_1(LispObject form,LispObject env)1210 static LispObject macroexpand_1(LispObject form, LispObject env)
1211 { // The environment here seems only necessary for macrolet
1212 STACK_SANITY;
1213 LispObject done;
1214 LispObject f;
1215 stackcheck(form, env);
1216 errexit();
1217 done = nil;
1218 if (consp(form))
1219 { f = car(form);
1220 // look for local macro definitions
1221 { LispObject p;
1222 for (p=env; p!=nil; p=cdr(p))
1223 { LispObject w = car(p);
1224 if (cdr(w) == f && is_cons(w = car(w)) && w!=nil)
1225 { p = car(w);
1226 if (p == funarg) // ordinary function
1227 { mv_2 = nil;
1228 return nvalues(form, 2);
1229 }
1230 { RealSave save(form, done);
1231 { RealSave save1(env);
1232 w = cons(lambda, w);
1233 errexit();
1234 w = list3(w, save.val(1), nil);
1235 save1.restore(env);
1236 }
1237 errexit();
1238 on_backtrace(
1239 p = apply(qvalue(macroexpand_hook),
1240 w,
1241 env,
1242 macroexpand_hook),
1243 // Now the error handler
1244 if (SHOW_FNAME)
1245 { err_printf("\nMacroexpanding: ");
1246 loop_print_error(save.val(1));
1247 });
1248 save.restore(form, done);
1249 }
1250 mv_2 = lisp_true;
1251 return nvalues(p, 2);
1252 }
1253 }
1254 }
1255 // If there is no local macro definition I need to look for a global one
1256 if (symbolp(f) && (qheader(f) & SYM_MACRO) != 0)
1257 { done = qvalue(macroexpand_hook);
1258 if (done == unset_var)
1259 return error(1, err_macroex_hook, macroexpand_hook);
1260 { Save save(form, env, done);
1261 f = cons(lambda, qenv(f));
1262 save.restore(form, env, done);
1263 }
1264 errexit();
1265 { Save save(done, env);
1266 f = list3(f, form, env);
1267 save.restore(done, env);
1268 }
1269 errexit();
1270 form = apply(done,
1271 f,
1272 env,
1273 macroexpand_hook);
1274 errexit();
1275 done = lisp_true;
1276 }
1277 }
1278 mv_2 = done;
1279 return nvalues(form, 2); // Multiple values handed back
1280 }
1281
macroexpand(LispObject form,LispObject env)1282 LispObject macroexpand(LispObject form, LispObject env)
1283 { // The environment here seems only necessary for macrolet
1284 STACK_SANITY;
1285 LispObject done;
1286 stackcheck(form, env);
1287 errexit();
1288 done = nil;
1289 for (;;)
1290 { { Save save(env, done);
1291 form = macroexpand_1(form, env);
1292 save.restore(env, done);
1293 }
1294 errexit();
1295 if (mv_2 == nil) break;
1296 done = lisp_true;
1297 }
1298 mv_2 = done;
1299 return nvalues(form, 2); // Multiple values handed back
1300 }
1301
Lmacroexpand(LispObject env,LispObject a)1302 LispObject Lmacroexpand(LispObject env, LispObject a)
1303 { return macroexpand(a, nil);
1304 }
1305
Lmacroexpand_2(LispObject,LispObject a,LispObject b)1306 LispObject Lmacroexpand_2(LispObject, LispObject a, LispObject b)
1307 { return macroexpand(a, b);
1308 }
1309
Lmacroexpand_1(LispObject env,LispObject a)1310 LispObject Lmacroexpand_1(LispObject env, LispObject a)
1311 { return macroexpand_1(a, nil);
1312 }
1313
Lmacroexpand_1_2(LispObject,LispObject a,LispObject b)1314 LispObject Lmacroexpand_1_2(LispObject, LispObject a, LispObject b)
1315 { return macroexpand_1(a, b);
1316 }
1317
1318 // To make something autoloadable I should set the environment cell to
1319 // (name-of-self module-name-1 module-name-2 ...)
1320 // and when invoked the function will do a load-module on each of the
1321 // modules specified and then re-attempt to call. Loading the
1322 // modules is expected to establish a proper definition for the
1323 // function involved.
1324
autoload_0(LispObject fname)1325 LispObject autoload_0(LispObject fname)
1326 { STACK_SANITY;
1327 fname = qenv(fname);
1328 { Save save(fname);
1329 set_fns(car(fname), undefined_0, undefined_1, undefined_2,
1330 undefined_3, undefined_4up);
1331 setenv(car(fname), car(fname));
1332 LispObject fname1 = cdr(fname);
1333 while (consp(fname1))
1334 { { Save save1(fname1);
1335 Lload_module(nil, car(fname1));
1336 save1.restore(fname1);
1337 }
1338 errexit();
1339 fname1 = cdr(fname1);
1340 }
1341 save.restore(fname);
1342 }
1343 return apply(car(fname), nil, nil, autoload_symbol);
1344 }
1345
autoload_1(LispObject fname,LispObject a1)1346 LispObject autoload_1(LispObject fname, LispObject a1)
1347 { STACK_SANITY;
1348 fname = qenv(fname);
1349 { Save save(fname);
1350 { Save save1(a1);
1351 set_fns(car(fname), undefined_0, undefined_1, undefined_2,
1352 undefined_3, undefined_4up);
1353 setenv(car(fname), car(fname));
1354 LispObject fname1 = cdr(fname);
1355 while (consp(fname1))
1356 { { Save save2(fname1);
1357 Lload_module(nil, car(fname1));
1358 errexit();
1359 save2.restore(fname1);
1360 }
1361 fname1 = cdr(fname1);
1362 }
1363 save1.restore(a1);
1364 }
1365 a1 = ncons(a1);
1366 errexit();
1367 save.restore(fname);
1368 }
1369 return apply(car(fname), a1, nil, autoload_symbol);
1370 }
1371
autoload_2(LispObject fname,LispObject a1,LispObject a2)1372 LispObject autoload_2(LispObject fname, LispObject a1, LispObject a2)
1373 { STACK_SANITY;
1374 fname = qenv(fname);
1375 { Save save(fname);
1376 { Save save1(a1, a2);
1377 set_fns(car(fname), undefined_0, undefined_1, undefined_2,
1378 undefined_3, undefined_4up);
1379 setenv(car(fname), car(fname));
1380 LispObject fname1 = cdr(fname);
1381 while (consp(fname1))
1382 { { Save save2(fname1);
1383 Lload_module(nil, car(fname1));
1384 save2.restore(fname1);
1385 }
1386 errexit();
1387 fname1 = cdr(fname1);
1388 }
1389 save1.restore(a1, a2);
1390 }
1391 a1 = list2(a1, a2);
1392 errexit();
1393 save.restore(fname);
1394 }
1395 errexit();
1396 return apply(car(fname), a1, nil, autoload_symbol);
1397 }
1398
autoload_3(LispObject fname,LispObject a1,LispObject a2,LispObject a3)1399 LispObject autoload_3(LispObject fname, LispObject a1, LispObject a2,
1400 LispObject a3)
1401 { STACK_SANITY;
1402 fname = qenv(fname);
1403 { Save save(fname);
1404 { Save save1(a1, a2, a3);
1405 set_fns(car(fname), undefined_0, undefined_1, undefined_2,
1406 undefined_3, undefined_4up);
1407 setenv(car(fname), car(fname));
1408 LispObject fname1 = cdr(fname);
1409 while (consp(fname1))
1410 { { Save save2(fname1);
1411 Lload_module(nil, car(fname1));
1412 errexit();
1413 save2.restore(fname1);
1414 }
1415 fname1 = cdr(fname1);
1416 }
1417 save1.restore(a1, a2, a3);
1418 }
1419 a1 = list3(a1, a2, a3);
1420 errexit();
1421 save.restore(fname);
1422 }
1423 return apply(car(fname), a1, nil, autoload_symbol);
1424 }
1425
autoload_4up(LispObject fname,LispObject a1,LispObject a2,LispObject a3,LispObject a4up)1426 LispObject autoload_4up(LispObject fname, LispObject a1,
1427 LispObject a2,
1428 LispObject a3, LispObject a4up)
1429 { STACK_SANITY;
1430 fname = qenv(fname);
1431 { Save save(fname);
1432 { Save save1(a1, a2, a3, a4up);
1433 set_fns(car(fname), undefined_0, undefined_1, undefined_2,
1434 undefined_3, undefined_4up);
1435 setenv(car(fname), car(fname));
1436 LispObject fname1 = cdr(fname);
1437 while (consp(fname1))
1438 { { Save save2(fname1);
1439 Lload_module(nil, car(fname1));
1440 save2.restore(fname);
1441 }
1442 fname1 = cdr(fname1);
1443 }
1444 save1.restore(a1, a2, a3, a4up);
1445 }
1446 a1 = list3star(a1, a2, a3, a4up);
1447 save.restore(fname);
1448 }
1449 return apply(car(fname), a1, nil, autoload_symbol);
1450 }
1451
undefined_0(LispObject fname)1452 LispObject undefined_0(LispObject fname)
1453 { return error(1, err_undefined_function_0, fname);
1454 }
1455
undefined_1(LispObject fname,LispObject)1456 LispObject undefined_1(LispObject fname, LispObject)
1457 {
1458 // It would be perfectly possible to grab and save the args here, and retry
1459 // the function call after error has patched things up. Again
1460 // this entrypoint is for compiled code calling something that is undefined,
1461 // and so no lexical environment is needed.
1462 return error(1, err_undefined_function_1, fname);
1463 }
1464
undefined_2(LispObject fname,LispObject,LispObject)1465 LispObject undefined_2(LispObject fname, LispObject, LispObject)
1466 { return error(1, err_undefined_function_2, fname);
1467 }
1468
undefined_3(LispObject fname,LispObject,LispObject,LispObject)1469 LispObject undefined_3(LispObject fname, LispObject, LispObject,
1470 LispObject)
1471 { return error(1, err_undefined_function_3, fname);
1472 }
1473
undefined_4up(LispObject fname,LispObject,LispObject,LispObject,LispObject)1474 LispObject undefined_4up(LispObject fname,
1475 LispObject, LispObject, LispObject, LispObject)
1476 { return error(1, err_undefined_function_4up, fname);
1477 }
1478
1479 // The next few functions allow me to create variants on things! The
1480 // entrypoint fX_as_Y goes in the function cell of a symbol, and the name
1481 // of a function with Y arguments goes in is environment cell. The result will
1482 // be a function that accepts X arguments and discards all but the first Y of
1483 // them, then chains to the other function. The purpose is to support good
1484 // compilation of things like
1485 // (de funny_equal (a b c) (equal a b))
1486
f0_as_0(LispObject env)1487 LispObject f0_as_0(LispObject env)
1488 { env = qenv(env);
1489 debug_record_symbol(env);
1490 return (*qfn0(env))(env);
1491 }
1492
f1_as_0(LispObject env,LispObject)1493 LispObject f1_as_0(LispObject env, LispObject)
1494 { env = qenv(env);
1495 debug_record_symbol(env);
1496 return (*qfn0(env))(env);
1497 }
1498
f2_as_0(LispObject env,LispObject,LispObject)1499 LispObject f2_as_0(LispObject env, LispObject, LispObject)
1500 { env = qenv(env);
1501 debug_record_symbol(env);
1502 return (*qfn0(env))(env);
1503 }
1504
f3_as_0(LispObject env,LispObject,LispObject,LispObject)1505 LispObject f3_as_0(LispObject env, LispObject, LispObject, LispObject)
1506 { env = qenv(env);
1507 debug_record_symbol(env);
1508 return (*qfn0(env))(env);
1509 }
1510
f1_as_1(LispObject env,LispObject a)1511 LispObject f1_as_1(LispObject env, LispObject a)
1512 { env = qenv(env);
1513 debug_record_symbol(env);
1514 return (*qfn1(env))(env, a);
1515 }
1516
f2_as_1(LispObject env,LispObject a,LispObject)1517 LispObject f2_as_1(LispObject env, LispObject a, LispObject)
1518 { env = qenv(env);
1519 debug_record_symbol(env);
1520 return (*qfn1(env))(env, a);
1521 }
1522
f3_as_1(LispObject env,LispObject a1,LispObject,LispObject)1523 LispObject f3_as_1(LispObject env, LispObject a1, LispObject,
1524 LispObject)
1525 { env = qenv(env);
1526 debug_record_symbol(env);
1527 return (*qfn1(env))(env, a1);
1528 }
1529
f2_as_2(LispObject env,LispObject a,LispObject b)1530 LispObject f2_as_2(LispObject env, LispObject a, LispObject b)
1531 { env = qenv(env);
1532 debug_record_symbol(env);
1533 return (*qfn2(env))(env, a, b);
1534 }
1535
f3_as_2(LispObject env,LispObject a1,LispObject a2,LispObject)1536 LispObject f3_as_2(LispObject env, LispObject a1, LispObject a2,
1537 LispObject)
1538 { env = qenv(env);
1539 debug_record_symbol(env);
1540 return (*qfn2(env))(env, a1, a2);
1541 }
1542
f3_as_3(LispObject env,LispObject a1,LispObject a2,LispObject a3)1543 LispObject f3_as_3(LispObject env, LispObject a1, LispObject a2,
1544 LispObject a3)
1545 { env = qenv(env);
1546 debug_record_symbol(env);
1547 return (*qfn3(env))(env, a1, a2, a3);
1548 }
1549
1550 // The next function is EXPERIMENTAL and is only available if there is
1551 // a "fork" function available. It is probably only even partially useful
1552 // if the operating system and libraries used implement that using a
1553 // "copy on write" strategy. This is the case with Linux, and I believe it to
1554 // be so in MacOSX. But Windows does not provide that sort of functionality
1555 // comfortably, so this stuff will not be available there. Observe that I
1556 // make fairly extreme use of the autoconf detection stuff to try to avoid
1557 // trying this where it might not make sense!
1558
1559 // Expected behaviour
1560 // (parallel f a)
1561 // runs two tasks, one of which is f(a, nil), the other is f(a, t).
1562 // when the first of those tasks completes the other is killed.
1563 // The result is a pair (fg . val)
1564 // If fg > 0 it is 1 or 2 to indicate which of the two calls
1565 // "won". In that case the value is the result returned by the
1566 // call, but NOTE that it has been in effect through print/read, and
1567 // so gensym identity and structure sharing will have been lost.
1568 // If fg < 0 then the true result was computed, but its printed
1569 // representation was longer than around 2K characters. The absolute
1570 // value of fg again indicates which task won, but the value is now
1571 // a string consisting of the first segment of characters in a printed
1572 // representation of the result. If creating parallel processes
1573 // fails or if the first task to finish does so by failing then this
1574 // call will report an error.
1575 // While it may be legal to use nested instaces of parallel to get
1576 // extra concurrency the memory demands that will result could be
1577 // severe. The overhead associated with starting and finishing a
1578 // task may also be significant, and so this is only liable to make
1579 // sense on a multi-cpu system for sub-tasks that are fairly demanding.
1580 // Note that the longer running task will be cancelled and no output
1581 // from it will be available at all.
1582 // Tasks run this way should probably avoid all input and output
1583 // operations.
1584 //
1585 // If the computer on which CSL has been built does not support "fork"
1586 // and the shared memory operations required here the parallel function
1587 // will just always report an error.
1588 //
1589 // While this code is in development it may genatate a certain amount
1590 // of unwanted trace or logging information.
1591
1592 #if defined HAVE_UNISTD_H && \
1593 defined HAVE_SYS_TYPES_H && \
1594 defined HAVE_SYS_STAT_H && \
1595 defined HAVE_SYS_WAIT_H && \
1596 defined HAVE_SIGNAL_H && \
1597 defined HAVE_SYS_SHM_H && \
1598 defined HAVE_SYS_IPC_H && \
1599 defined HAVE_FORK && \
1600 defined HAVE_WAIT && \
1601 defined HAVE_WAITPID && \
1602 defined HAVE_SHMGET && \
1603 defined HAVE_SHMAT && \
1604 defined HAVE_SHMDT && \
1605 defined HAVE_SHMCTL
1606
1607 #include <sys/types.h>
1608 #include <sys/stat.h>
1609 #include <unistd.h>
1610 #include <sys/wait.h>
1611 #include <sys/shm.h>
1612 #include <sys/ipc.h>
1613 #include <errno.h>
1614
1615 #define PARSIZE 65536
1616
write_result(LispObject env,LispObject r,char * shared)1617 static LispObject write_result(LispObject env, LispObject r, char *shared)
1618 {
1619 // This converts an arbitrary result into a string so I can pass it back.
1620 int32_t i, len, ok = 1;
1621 // Cyclic and re-entrant structures could lead to failure here, and
1622 // uninterned symbols (eg gensyms) will not be coped with very well. But
1623 // SIMPLE data types should all be safe.
1624 if_error(r = Lexplode(nil, r),
1625 // Error handler
1626 std::strcpy(shared, "Failed");
1627 my_exit());
1628 if_error(r = Llist_to_string(nil, r),
1629 // Error handler
1630 std::strcpy(shared, "Failed");
1631 my_exit());
1632 len = length_of_byteheader(vechdr(r)) - CELL;
1633 // If the displayed form ou the output was too long I just truncate it
1634 // at present. A more agressive attitude would be to count that as a form
1635 // of failure. As an intermediate step I use the first character in my
1636 // buffer as an "overflow flag" and leave a blank in it if all is well.
1637 if (len > PARSIZE-2)
1638 { len=PARSIZE-2;
1639 ok = 0;
1640 }
1641 shared[0] = ok ? ' ' : '#';
1642 for (i=0; i<len; i++) shared[i+1] = celt(r, i);
1643 shared[len+1] = 0;
1644 return nil;
1645 }
1646
Lparallel(LispObject env,LispObject a,LispObject b)1647 LispObject Lparallel(LispObject env, LispObject a, LispObject b)
1648 { STACK_SANITY;
1649 pid_t pid1, pid2, pidx, pidy;
1650 // Create an identifier for a private shared segment of memory of size
1651 // 2*PARSIZE. This will be used for passing a result from the sub-task
1652 // to the main one. Give up if such a segment can not be allocated.
1653 int status, segid = shmget(IPC_PRIVATE, (size_t)(2*PARSIZE),
1654 IPC_CREAT | S_IRUSR | S_IWUSR);
1655 char *shared, *w;
1656 int overflow;
1657 LispObject r;
1658 if (segid == -1) return aerror("Unable to allocate a shared segment");
1659 // Attach to the shared segment to obtain a memory address via which it can be
1660 // accessed. Again raise an error if this fails.
1661 shared = reinterpret_cast<char *>(shmat(segid, nullptr, 0));
1662 if (shared == reinterpret_cast<char *>(-1))
1663 return aerror("Unable to attach to shared segment");
1664 // the shared segment is set up to contain null strings in the two places
1665 // where it might be used to hold return values.
1666 shared[0] = shared[PARSIZE] = 0;
1667 // Split off a clone of the current process that can be used to do the
1668 // first evaluation. If this succeeds call a(b, nil) in it. Note that
1669 // processes created via "fork" inherit shared memory segments from their
1670 // parent.
1671 pid1 = fork();
1672 if (pid1 < 0) // Task not created, must tidy up.
1673 { shmdt(shared);
1674 shmctl(segid, IPC_RMID, 0);
1675 return aerror("Fork 1 failed");
1676 }
1677 else if (pid1 == 0)
1678 { // TASK 1 created OK
1679 LispObject r1 = nil;
1680 if_error(r1 = Lapply2(nil, a, b, nil),
1681 // If the evaluation failed I will exit indicating a failure.
1682 std::strcpy(shared, "Failed");
1683 my_exit());
1684 // Write result from first task into the first half of the shared memory block.
1685 write_result(nil, r1, shared);
1686 // Exiting from the sub-task would in fact detach from the shared data
1687 // segment, but I do the detaching explictly to feel tidy.
1688 shmdt(shared);
1689 return Lstop1(nil, fixnum_of_int(0));
1690 }
1691 else
1692 {
1693 // This is the continuation of the main process. Create a second task in
1694 // much the same way.
1695 pid2 = fork();
1696 if (pid2 < 0) // If task 2 can not be created then kill task 1
1697 { kill(pid1, SIGKILL);
1698 waitpid(pid1, &status, 0);
1699 shmdt(shared);
1700 shmctl(segid, IPC_RMID, 0);
1701 return aerror("Fork 2 failed");
1702 }
1703 else if (pid2 == 0)
1704 { // TASK 2
1705 LispObject r2 = nil;
1706 if_error(r2 = Lapply2(nil, a, b, lisp_true),
1707 // Error handler
1708 std::strcpy(shared, "Failed");
1709 my_exit());
1710 write_result(nil, r2, shared+PARSIZE);
1711 shmdt(shared);
1712 return Lstop1(nil, fixnum_of_int(0));
1713 }
1714 else
1715 {
1716 // Wait for whichever of the two sub-tasks finishes first. Then kill the
1717 // other one, and return the result left by the winner.
1718 pidx = wait(&status);
1719 // term_printf("First signal was from task %d\n", pidx);
1720 if (!WIFEXITED(status) ||
1721 WEXITSTATUS(status) != 0)
1722 {
1723 // If the first task to complete in fact failed rather than exited cleanly
1724 // I will count it as an overall failure and cancel everything. This
1725 // covers aborting (in which case WIFEXITED will return false) or
1726 // exiting cleanly but with a non-zero return code.
1727 kill(pid1, SIGKILL);
1728 kill(pid2, SIGKILL);
1729 waitpid(pid1, &status, 0);
1730 waitpid(pid2, &status, 0);
1731 shmdt(shared);
1732 shmctl(segid, IPC_RMID, 0);
1733 return aerror("Task did not exit cleanly");
1734 }
1735 if (pidx == pid1)
1736 { w = shared;
1737 pidy = pid2;
1738 overflow = 1;
1739 }
1740 else
1741 { w = shared+PARSIZE;
1742 pidy = pid1;
1743 overflow = 2;
1744 }
1745 kill(pidy, SIGKILL); // Kill alternate task
1746 waitpid(pidy, &status, 0);
1747 // If the first character of the buffer is a blank then there was no
1748 // overflow and all is well.
1749 if (w[0] == ' ') r = read_from_vector(w + 1);
1750 else
1751 { overflow = -overflow;
1752 r = make_string(w + 1);
1753 }
1754 // Need to tidy up the shared segment at the end.
1755 shmdt(shared);
1756 shmctl(segid, IPC_RMID, 0);
1757 r = cons(fixnum_of_int(overflow), r);
1758 return onevalue(r);
1759 }
1760 }
1761 }
1762
1763 #else
1764
Lparallel(LispObject env,LispObject a,LispObject b)1765 LispObject Lparallel(LispObject env, LispObject a, LispObject b)
1766 { return aerror("parallel not supported on this platform");
1767 }
1768
1769 #endif
1770
Lsleep(LispObject env,LispObject a)1771 LispObject Lsleep(LispObject env, LispObject a)
1772 { int n;
1773 if (is_fixnum(a)) n = int_of_fixnum(a);
1774 else n = 1;
1775 std::this_thread::sleep_for(std::chrono::milliseconds(n));
1776 return onevalue(nil);
1777 }
1778
1779 // This is intended for use when debugging!
1780 // (show-stack m n) displays stack locations from m to n (inclusive)
1781 // where the top item on the stack has number 0.
1782 // (show-stack n) is equivalent to (show-stack 0 n)
1783 // (show-stack) is equivalent to (show-stack 0 0), ie it shows just the
1784 // top item on the stack.
1785 // If m > n then this just reports stack depth.
1786 // This will refuse to handle arguments larger than 100.
1787
Lshow_stack_2(LispObject env,LispObject a1,LispObject a2)1788 LispObject Lshow_stack_2(LispObject env, LispObject a1, LispObject a2)
1789 { int m = 0, n = 0;
1790 if (is_fixnum(a1))
1791 { m = int_of_fixnum(a1);
1792 if (m < 0 || m > 100) m = 0;
1793 }
1794 if (is_fixnum(a2))
1795 { n = int_of_fixnum(a2);
1796 if (n > 100) n = m+10;
1797 }
1798 term_printf("Stack depth %d\n", static_cast<int>(stack-stackBase));
1799 for (int i=m; i<=n; i++)
1800 { term_printf("%d: ", i);
1801 prin_to_terminal(stack[-i]);
1802 term_printf("\n");
1803 errexit();
1804 }
1805 return onevalue(nil);
1806 }
1807
Lshow_stack_1(LispObject env,LispObject a1)1808 LispObject Lshow_stack_1(LispObject env, LispObject a1)
1809 { return Lshow_stack_2(env, fixnum_of_int(0), a1);
1810 }
1811
Lshow_stack_0(LispObject env)1812 LispObject Lshow_stack_0(LispObject env)
1813 { return Lshow_stack_2(env, fixnum_of_int(0), fixnum_of_int(0));
1814 }
1815
1816 setup_type const eval1_setup[] =
1817 { {"bytecounts", Lbytecounts_0, Lbytecounts_1, G2Wother, G3Wother, G4Wother},
1818 {"idapply", G0Wother, Lapply_1, Lapply_2, Lapply_3, Lapply_4up},
1819 DEF_1("eval", Leval),
1820 {"apply", G0Wother, Lapply_1, Lapply_2, Lapply_3, Lapply_4up},
1821 DEF_1("apply0", Lapply0),
1822 DEF_2("apply1", Lapply1),
1823 DEF_3("apply2", Lapply2),
1824 DEF_4up("apply3", Lapply3),
1825 DEF_1("evlis", Levlis),
1826 {"funcall", G0Wother, Lfuncall_1, Lfuncall_2, Lfuncall_3, Lfuncall_4up},
1827 {"funcall*", G0Wother, Lfuncall_1, Lfuncall_2, Lfuncall_3, Lfuncall_4up},
1828 DEF_2("parallel", Lparallel),
1829 DEF_1("sleep", Lsleep),
1830 {"values", Lvalues_0, Lvalues_1, Lvalues_2, Lvalues_3, Lvalues_4up},
1831 {"macroexpand", G0Wother, Lmacroexpand, Lmacroexpand_2, G3W1, G4W1},
1832 {"macroexpand-1", G0Wother, Lmacroexpand_1, Lmacroexpand_2, G3Wother, G4Wother},
1833 {"show-stack", Lshow_stack_0, Lshow_stack_1, Lshow_stack_2, G3Wother, G4Wother},
1834 {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}
1835 };
1836
1837 // end of eval1.cpp
1838