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