123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776 |
- /* eval1.c Copyright (C) 1989-96 Codemist Ltd */
- /*
- * Interpreter (part 1).
- */
- /* Signature: 47f1cfe1 31-May-1997 */
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
- #include "machine.h"
- #include "tags.h"
- #include "cslerror.h"
- #include "externs.h"
- #include "entries.h"
- #ifdef TIMEOUT
- #include "timeout.h"
- #endif
- Lisp_Object nreverse(Lisp_Object a)
- {
- Lisp_Object nil = C_nil;
- Lisp_Object b = nil;
- while (consp(a))
- { Lisp_Object c = a;
- a = qcdr(a);
- qcdr(c) = b;
- b = c;
- }
- return b;
- }
- /*
- * Environments are represented as association lists, and have to cope
- * with several sorts of things. The items in an environment can be
- * in one of the following forms:
- *
- * (a) (symbol . value) normal lexical variable binding
- * (b) (symbol . ~magic~) given symbol is (locally) special
- * (c) (0 . tag) (block tag ...) marker
- * (d) (1 . (tag ...)) (tagbody ... tag ...) marker
- * (e) (2 . <anything>) case (c) or (d) but now invalidated
- * (f) (def . symbol) (flet ...) or (macrolet ...) binding,
- * where the def is non-atomic.
- *
- * Format for def in case (f)
- *
- * (1) (funarg env bvl ...) flet and labels
- * (2) (bvl ...) macrolet
- * Note that 'funarg is not valid as a bvl
- * and indeed in this case bvl is a list
- */
- /*
- * In CSL mode flet, macrolet and local declarations are not supported.
- */
- Lisp_Object Ceval(Lisp_Object u, Lisp_Object env)
- {
- Lisp_Object nil = C_nil;
- #ifdef COMMON
- int t;
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__)) return aerror("deep stack in eval");
- #endif
- restart:
- t = (int)u & TAG_BITS;
- /*
- * The first case considered is of symbols - lexical and special bindings
- * have to be sorted out.
- */
- if (t == TAG_SYMBOL)
- {
- Header h = qheader(u);
- if (h & SYM_SPECIAL_VAR)
- { Lisp_Object v = qvalue(u);
- if (v == unset_var) return error(1, err_unset_var, u);
- else return onevalue(v);
- }
- else
- {
- while (env != nil)
- { Lisp_Object p = qcar(env);
- if (qcar(p) == u)
- { Lisp_Object v =qcdr(p);
- /*
- * If a variable is lexically bound to the value work_symbol that means
- * that the symbol has been (lexically) declared to be special, so its
- * value cell should be inspected.
- */
- if (v == work_symbol)
- { v = qvalue(u);
- if (v == unset_var) return error(1, err_unset_var, u);
- }
- return onevalue(v);
- }
- env = qcdr(env);
- }
- #ifdef ARTHURS_ORIGINAL_INTERPRETATION
- return error(1, err_unbound_lexical, u);
- #else
- { Lisp_Object v = qvalue(u);
- if (v == unset_var) return error(1, err_unset_var, u);
- else return onevalue(v);
- }
- #endif
- }
- }
- /*
- * Things that are neither symbols nor lists evaluate to themselves,
- * e.g. numbers and vectors.
- */
- else if (t != TAG_CONS) return onevalue(u);
- else
- #endif /* COMMON */
- {
- /*
- * The final case is that of a list (fn ...), and one case that has to
- * be checked is if fn is lexically bound.
- */
- Lisp_Object fn, args;
- #ifdef COMMON
- /*
- * The test for nil here is because although nil is a symbol the tagging
- * structure tested here marks it as a list.
- */
- if (u == nil) return onevalue(nil);
- #endif
- stackcheck2(0, u, env);
- fn = qcar(u);
- args = qcdr(u);
- #ifdef COMMON
- /*
- * Local function bindings must be looked for first.
- */
- { Lisp_Object p;
- for (p=env; p!=nil; p=qcdr(p))
- { Lisp_Object w = qcar(p);
- /*
- * The form (<list> . sym) is used in an environment to indicate a local
- * binding of a function, either as a regular function or as a macro
- * (i.e. flet or macrolet). The structure of the list distinguishes
- * between these two cases.
- */
- if (qcdr(w) == fn && is_cons(w = qcar(w)) && w!=nil)
- {
- p = qcar(w);
- if (p == funarg) /* ordinary function */
- { fn = w; /* (funarg ...) is OK to apply */
- goto ordinary_function;
- }
- /*
- * Here it is a local macro. Observe that the macroexpansion is done
- * with respect to an empty environment. Macros that are defined at the same
- * time may seem to be mutually recursive but there is a sense in which they
- * are not (as well as a sense in which they are) - self and cross references
- * only happen AFTER an expansion and can not happen during one.
- */
- push2(u, env);
- w = cons(lambda, w);
- nil = C_nil;
- if (!exception_pending())
- p = Lfuncalln(nil, 4, qvalue(macroexpand_hook),
- w, u, nil);
- pop2(env, u);
- nil = C_nil;
- if (exception_pending())
- { flip_exception();
- if ((exit_reason & UNWIND_ERROR) != 0)
- { err_printf("\nMacroexpanding: ");
- loop_print_error(u);
- nil = C_nil;
- if (exception_pending()) flip_exception();
- }
- flip_exception();
- return nil;
- }
- u = p;
- goto restart;
- }
- }
- }
- #endif
- if (is_symbol(fn))
- {
- /*
- * Special forms and macros are checked for next. Special forms
- * take precedence over macros.
- */
- Header h = qheader(fn);
- if (h & SYM_SPECIAL_FORM)
- { Lisp_Object v;
- #ifdef DEBUG
- if (qfn1(fn) == NULL)
- { term_printf("Illegal special form\n");
- my_exit(EXIT_FAILURE);
- }
- #endif
- v = ((Special_Form *)qfn1(fn))(args, env);
- return v;
- }
- else if (h & SYM_MACRO)
- {
- push2(u, env);
- /*
- * the environment passed to macroexpand should only be needed to cope
- * with macrolet, I think. Since I use just one datastructure for the
- * whole environment I also pass along lexical bindings etc, but I hope that
- * they will never be accessed. I do not think that macrolet is important
- * enough to call for complication and slow-down in the interpreter this
- * way - but then I am not exactly what you would call a Common Lisp Fan!
- */
- fn = macroexpand(u, env);
- pop2(env, u);
- nil = C_nil;
- if (exception_pending())
- { flip_exception();
- if ((exit_reason & UNWIND_ERROR) != 0)
- { err_printf("\nMacroexpanding: ");
- loop_print_error(u);
- nil = C_nil;
- if (exception_pending()) flip_exception();
- }
- flip_exception();
- return nil;
- }
- return eval(fn, env);
- }
- }
- /*
- * Otherwise we have a regular function call. I prepare the args and
- * call APPLY.
- */
- #ifdef COMMON
- ordinary_function:
- #endif
- { int nargs = 0;
- Lisp_Object *save_stack = stack;
- /*
- * Args are built up on the stack here...
- */
- while (consp(args))
- { Lisp_Object w;
- push3(fn, args, env);
- w = qcar(args);
- w = eval(w, env);
- pop3(env, args, fn);
- /*
- * nil having its mark bit set indicates that a special sort of exit
- * is in progress. Multiple values can be ignored in this case.
- */
- nil = C_nil;
- if (exception_pending())
- { flip_exception();
- stack = save_stack;
- if ((exit_reason & UNWIND_ERROR) != 0)
- { err_printf("\nEvaluating: ");
- loop_print_error(qcar(args));
- nil = C_nil;
- if (exception_pending()) flip_exception();
- }
- flip_exception();
- return nil;
- }
- push(w); /* args build up on the Lisp stack */
- nargs++;
- args = qcdr(args);
- }
- /*
- * I pass the environment down to apply() because it will be used if the
- * function was a simple lambda expression. If the function is a symbol
- * or a closure, env will be irrelevant. The arguments are on the Lisp
- * stack, and it is the responsibility of apply() to pop them.
- */
- return apply(fn, nargs, env, fn);
- }
- }
- }
- #ifdef COMMON
- /*
- * Keyword arguments are not supported in CSL mode - but &optional
- * and &rest and &aux will be (at least for now). Removal of
- * support for keywords will save a little space and an even smaller
- * amount of time.
- */
- static bool check_no_unwanted_keys(Lisp_Object restarg, Lisp_Object ok_keys)
- /*
- * verify that there were no unwanted keys in the actual arg list
- */
- {
- Lisp_Object nil = C_nil;
- bool odd_key_found = NO;
- while (restarg!=nil)
- { Lisp_Object k = qcar(restarg);
- Lisp_Object w;
- for (w=ok_keys; w!=nil; w=qcdr(w))
- if (k == qcar(w)) goto is_ok;
- odd_key_found = YES;
- is_ok:
- restarg = qcdr(restarg);
- if (restarg==nil) return YES; /* odd length list */
- if (k == allow_key_key && qcar(restarg) != nil) return NO; /* OK */
- restarg = qcdr(restarg);
- }
- return odd_key_found;
- }
- static bool check_keyargs_even(Lisp_Object restarg)
- /*
- * check that list is even length with alternate items symbols in
- * the keyword package.
- */
- {
- Lisp_Object nil = C_nil;
- while (restarg!=nil)
- { Lisp_Object q = qcar(restarg);
- if (!is_symbol(q) || qpackage(q) != qvalue(keyword_package)) return YES;
- restarg = qcdr(restarg);
- if (restarg==nil) return YES; /* Odd length is wrong */
- restarg = qcdr(restarg);
- }
- return NO; /* OK */
- }
- static Lisp_Object keywordify(Lisp_Object v)
- {
- /*
- * arg is a non-nil symbol. Should nil be permitted - I think not
- * since there seems too much chance of confusion.
- */
- Lisp_Object nil, name = get_pname(v);
- errexit();
- return Lintern_2(nil, name, qvalue(keyword_package));
- }
- static Lisp_Object key_lookup(Lisp_Object keyname, Lisp_Object args)
- {
- Lisp_Object nil = C_nil;
- while (args!=nil)
- { Lisp_Object next = qcdr(args);
- if (next==nil) return nil;
- if (qcar(args) == keyname) return next;
- else args = qcdr(next);
- }
- return nil;
- }
- #endif
- Lisp_Object apply_lambda(Lisp_Object def, int nargs,
- Lisp_Object env, Lisp_Object name)
- /*
- * Here def is a lambda expression (sans the initial lambda) that is to
- * be applied. Much horrible messing about is needed so that I can cope
- * with &optional and &rest args (including initialisers and supplied-p
- * variables, also &key, &allow-other-keys and &aux). Note the need to find
- * any special declarations at the head of the body of the lambda-form.
- * Must pop (nargs) items from the stack at exit.
- */
- {
- /*
- * lambda-lists are parsed using a finite state engine with the
- * following states, plus an exit state.
- */
- #define STATE_NULL 0 /* at start and during regular args */
- #define STATE_OPT 1 /* after &optional */
- #define STATE_OPT1 2 /* after &optional + at least one var */
- #define STATE_REST 3 /* immediately after &rest */
- #define STATE_REST1 4 /* after &rest vv */
- #ifdef COMMON
- #define STATE_KEY 5 /* &key with no &rest */
- #define STATE_ALLOW 6 /* &allow-other-keys */
- #endif
- #define STATE_AUX 7 /* &aux */
- Lisp_Object nil = C_nil;
- int opt_rest_state = STATE_NULL;
- Lisp_Object *next_arg;
- int args_left = nargs;
- Lisp_Object w;
- if (!consp(def))
- { popv(nargs);
- return onevalue(nil); /* Should never happen */
- }
- stackcheck3(0, def, env, name);
- w = qcar(def);
- next_arg = &stack[1-nargs]; /* Points to arg1 */
- push4(w, /* bvl */
- qcdr(def), /* body */
- env, name);
- /*
- * Here I need to macroexpand the first few items in body and
- * look for declare/special items. I will only bother with SPECIAL decls.
- * Note that args have been pushed onto the stack first to avoid corruption
- * while the interpreter performs macroexpansion. This is the sort of place
- * where I feel that Common Lisp has built in causes of inefficiency.
- * Well oh well!!! The Common Lisp standardisation group thought so too,
- * and have now indicated that DECLARE forms can not be hidden away as
- * the result of macros, so some of this is unnecessary.
- */
- push5(nil, nil, /* local_decs, ok_keys */
- nil, nil, nil); /* restarg, specenv, val1 */
- push5(nil, nil, /* arg, v1 */
- nil, nil, nil); /* v, p, w */
- /*
- * On computers which have unsigned offsets in indexed memory reference
- * instructions the negative indexes off the stack suggested here might
- * be more expensive than I would like - maybe on such machines the stack
- * pointer should be kept offset by 64 bytes (say). Doing so in general
- * would be to the disadvantage of machines with auto-index address modes
- * that might be used when pushing/popping single items on the stack.
- */
- #define w stack[0]
- #define p stack[-1]
- #define v stack[-2]
- #define v1 stack[-3]
- #define arg stack[-4]
- #define val1 stack[-5]
- #define specenv stack[-6]
- #define restarg stack[-7]
- #ifdef COMMON
- #define ok_keys stack[-8]
- #define local_decs stack[-9]
- #endif
- #define name stack[-10]
- #define env stack[-11]
- #define body stack[-12]
- #define bvl stack[-13]
- #define arg1 stack[-14]
- #define stack_used ((int)(nargs + 14))
- #ifdef COMMON
- for (;;)
- { if (!consp(body)) break;
- p = macroexpand(qcar(body), env);
- nil = C_nil;
- if (exception_pending())
- { Lisp_Object qname = name;
- popv(stack_used);
- return qname;
- }
- body = qcdr(body);
- if (!consp(p))
- { if (stringp(p) && consp(body)) continue;
- body = cons(p, body);
- break;
- }
- if (qcar(p) != declare_symbol)
- { body = cons(p, body);
- break;
- }
- for (v = qcdr(v); consp(v); v = qcdr(v))
- { v1 = qcar(v);
- if (!consp(v1) || qcar(v1) != special_symbol) continue;
- /* here v1 says (special ...) */
- for (v1=qcdr(v1); consp(v1); v1 = qcdr(v1))
- { local_decs = cons(qcar(v1), local_decs);
- if (exception_pending()) break;
- }
- }
- }
- nil = C_nil;
- if (exception_pending())
- { Lisp_Object qname = name;
- popv(stack_used);
- return qname;
- }
- #endif
- /*
- * Parse the BVL
- */
- for (p = bvl; consp(p); p=qcdr(p))
- { v = qcar(p);
- v1 = nil;
- arg = nil;
- val1 = nil;
- /*
- * I can break from this switch statement with v a variable to bind
- * and arg the value to bind to it, also v1 (if not nil) is a second
- * variable to be bound (a supplied-p value) and val1 the value to bind it to.
- * If I see &rest or &key the remaining actual args get collected into
- * restarg, which takes the place of arg in some respects.
- */
- switch (opt_rest_state)
- {
- case STATE_NULL:
- if (v == opt_key)
- { opt_rest_state = STATE_OPT;
- continue;
- }
- #define BAD1(msg) { error(0, msg); goto unwind_special_bindings; }
- #define BAD2(msg, a) { error(1, msg, a); goto unwind_special_bindings; }
- #define collect_rest_arg() \
- while (args_left-- != 0) \
- { if (!exception_pending()) \
- restarg = cons(next_arg[args_left], restarg); \
- nil = C_nil; \
- }
- if (v == rest_key)
- { collect_rest_arg();
- if (exception_pending()) goto unwind_special_bindings;
- opt_rest_state = STATE_REST;
- continue;
- }
- #ifdef COMMON
- if (v == key_key)
- { collect_rest_arg();
- if (exception_pending()) goto unwind_special_bindings;
- if (check_keyargs_even(restarg)) BAD2(err_bad_keyargs, restarg);
- opt_rest_state = STATE_KEY;
- continue;
- }
- if (v == aux_key)
- { if (args_left != 0) BAD1(err_excess_args);
- opt_rest_state = STATE_AUX;
- continue;
- }
- if (v == allow_other_keys) BAD2(err_bad_bvl, v);
- #endif
- if (args_left == 0) BAD1(err_insufficient_args);
- arg = *next_arg++;
- args_left--;
- v1 = nil; /* no suppliedp mess here, I'm glad to say */
- break;
- case STATE_OPT:
- if (v == opt_key
- || v == rest_key
- #ifdef COMMON
- || v == key_key
- || v == allow_other_keys
- || v == aux_key
- #endif
- ) BAD2(err_bad_bvl, v);
- /*
- * Here v may be a simple variable, or a list (var init suppliedp)
- */
- opt_rest_state = STATE_OPT1;
- process_optional_parameter:
- if (args_left != 0)
- { arg = *next_arg++;
- args_left--;
- val1 = lisp_true;
- }
- else
- { arg = nil;
- val1 = nil;
- }
- v1 = nil;
- if (!consp(v)) break; /* Simple case */
- { w = qcdr(v);
- v = qcar(v);
- if (!consp(w)) break; /* (var) */
- if (val1 == nil) /* use the init form */
- { arg = qcar(w);
- arg = eval(arg, env);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- }
- w = qcdr(w);
- if (consp(w)) v1 = qcar(w); /* suppliedp name */
- break;
- }
- case STATE_OPT1:
- if (v == rest_key)
- { collect_rest_arg();
- if (exception_pending()) goto unwind_special_bindings;
- opt_rest_state = STATE_REST;
- continue;
- }
- #ifdef COMMON
- if (v == key_key)
- { collect_rest_arg();
- if (exception_pending()) goto unwind_special_bindings;
- if (check_keyargs_even(restarg)) BAD2(err_bad_keyargs, restarg);
- opt_rest_state = STATE_KEY;
- continue;
- }
- if (v == aux_key)
- { if (args_left != 0) BAD1(err_excess_args);
- opt_rest_state = STATE_AUX;
- continue;
- }
- #endif
- if (v == opt_key
- #ifdef COMMON
- || v == allow_other_keys
- #endif
- ) BAD2(err_bad_bvl, v);
- goto process_optional_parameter;
- case STATE_REST:
- if (v == opt_key
- || v == rest_key
- #ifdef COMMON
- || v == key_key
- || v == allow_other_keys
- || v == aux_key
- #endif
- ) BAD2(err_bad_bvl, v);
- opt_rest_state = STATE_REST1;
- arg = restarg;
- break;
- case STATE_REST1:
- #ifdef COMMON
- if (v == key_key)
- { if (check_keyargs_even(restarg)) BAD2(err_bad_keyargs, restarg);
- opt_rest_state = STATE_KEY;
- continue;
- }
- if (v == aux_key)
- {
- opt_rest_state = STATE_AUX;
- continue;
- }
- #endif
- BAD2(err_bad_bvl, rest_key);
- #ifdef COMMON
- case STATE_KEY:
- if (v == allow_other_keys)
- { opt_rest_state = STATE_ALLOW;
- continue;
- }
- if (v == aux_key)
- { if (check_no_unwanted_keys(restarg, ok_keys))
- BAD2(err_bad_keyargs, restarg);
- opt_rest_state = STATE_AUX;
- continue;
- }
- if (v == opt_key || v == rest_key || v == key_key)
- BAD2(err_bad_bvl, v);
- process_keyword_parameter:
- /*
- * v needs to expand to ((:kv v) init svar) in effect here.
- */
- { Lisp_Object keyname = nil;
- w = nil;
- if (!consp(v))
- { if (!is_symbol(v)) BAD2(err_bad_bvl, v);
- keyname = keywordify(v);
- }
- else
- { w = qcdr(v);
- v = qcar(v);
- if (!consp(v))
- { if (!is_symbol(v)) BAD2(err_bad_bvl, v);
- keyname = keywordify(v);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- }
- else
- { keyname = qcar(v);
- if (!is_symbol(keyname)) BAD2(err_bad_bvl, v);
- keyname = keywordify(keyname);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- v = qcdr(v);
- if (consp(v)) v = qcar(v);
- else BAD2(err_bad_bvl, v);
- }
- }
- ok_keys = cons(keyname, ok_keys);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- arg = key_lookup(qcar(ok_keys), restarg);
- if (arg == nil) val1 = nil;
- else
- { arg = qcar(arg);
- val1 = lisp_true;
- }
- v1 = nil;
- if (!consp(w)) break; /* (var) */
- if (val1 == nil) /* use the init form */
- { arg = qcar(w);
- arg = eval(arg, env);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- }
- w = qcdr(w);
- if (consp(w)) v1 = qcar(w); /* suppliedp name */
- break;
- }
- case STATE_ALLOW:
- if (v == aux_key)
- { opt_rest_state = STATE_AUX;
- continue;
- }
- if (v == opt_key || v == rest_key || v == key_key ||
- v == allow_other_keys) BAD2(err_bad_bvl, v);
- goto process_keyword_parameter;
- case STATE_AUX:
- if (v == opt_key || v == rest_key ||
- v == key_key || v == allow_other_keys ||
- v == aux_key) BAD2(err_bad_bvl, v);
- if (consp(v))
- { w = qcdr(v);
- v = qcar(v);
- if (consp(w))
- { arg = qcar(w);
- arg = eval(arg, env);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- }
- }
- else arg = nil;
- v1 = nil;
- break;
- #endif
- }
- /*
- * This is where I get when I have one or two vars to bind.
- */
- #ifndef COMMON
- /*
- * CSL mode does not have to mess about looking for local special bindings
- * and so is MUCH shorter and neater. I always shallow bind
- */
- #define instate_binding(var, val, local_decs1, lab) \
- { if (!is_symbol(var)) BAD2(err_bad_bvl, var); \
- w = acons(var, qvalue(var), specenv); \
- nil = C_nil; \
- if (exception_pending()) goto unwind_special_bindings; \
- specenv = w; \
- qvalue(var) = val; \
- }
- #else
- #define instate_binding(var, val, local_decs1, lab) \
- { Header h; \
- if (!is_symbol(var)) BAD2(err_bad_bvl, var); \
- h = qheader(var); \
- if ((h & SYM_SPECIAL_VAR) != 0) \
- { w = acons(var, qvalue(var), specenv); \
- nil = C_nil; \
- if (exception_pending()) goto unwind_special_bindings; \
- specenv = w; \
- qvalue(var) = val; \
- } \
- else \
- { for (w = local_decs1; w!=nil; w = qcdr(w)) \
- { if (qcar(w) == var) \
- { qcar(w) = fixnum_of_int(0);/* decl is used up */\
- w = acons(var, work_symbol, env); \
- nil = C_nil; \
- if (exception_pending()) \
- goto unwind_special_bindings; \
- env = w; \
- w = acons(var, qvalue(var), specenv); \
- nil = C_nil; \
- if (exception_pending()) \
- goto unwind_special_bindings; \
- specenv = w; \
- qvalue(var) = val; \
- goto lab; \
- } \
- } \
- w = acons(var, val, env); \
- nil = C_nil; \
- if (exception_pending()) goto unwind_special_bindings; \
- env = w; \
- lab: ; \
- } \
- }
- #endif
- #ifdef COMMON
- /*
- * Must check about local special declarations here...
- */
- #endif
- instate_binding(v, arg, local_decs, label1);
- if (v1 != nil) instate_binding(v1, val1, local_decs, label2);
- } /* End of for loop that scans BVL */
- #ifdef COMMON
- /*
- * As well as local special declarations that have applied to bindings here
- * there can be some that apply just to variable references within the body.
- */
- while (local_decs!=nil)
- { Lisp_Object q = qcar(local_decs);
- local_decs=qcdr(local_decs);
- if (!is_symbol(q)) continue;
- w = acons(q, work_symbol, env);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- env = w;
- }
- #endif
- switch (opt_rest_state)
- {
- case STATE_NULL:
- case STATE_OPT1: /* Ensure there had not been too many args */
- if (args_left != 0) BAD1(err_excess_args);
- break;
- case STATE_OPT: /* error if bvl finishes here */
- case STATE_REST:
- BAD2(err_bad_bvl, opt_rest_state == STATE_OPT ? opt_key : rest_key);
- #ifdef COMMON
- case STATE_KEY: /* ensure only valid keys were given */
- if (check_no_unwanted_keys(restarg, ok_keys))
- BAD2(err_bad_keyargs, restarg);
- break;
- #endif
- default:
- /* in the following cases all is known to be well
- case STATE_REST1:
- case STATE_ALLOW:
- case STATE_AUX:
- */
- break;
- }
- /*
- * Now all the argument bindings have been performed - it remains to
- * process the body of the lambda-expression.
- */
- if (specenv == nil)
- { Lisp_Object bodyx = body, envx = env;
- Lisp_Object qname = name;
- popv(stack_used);
- push(qname);
- bodyx = progn_fn(bodyx, envx);
- pop(qname);
- nil = C_nil;
- if (exception_pending()) return qname;
- return bodyx;
- }
- { body = progn_fn(body, env);
- nil = C_nil;
- if (exception_pending()) goto unwind_special_bindings;
- while (specenv != nil)
- {
- Lisp_Object bv = qcar(specenv);
- qvalue(qcar(bv)) = qcdr(bv);
- specenv = qcdr(specenv);
- }
- { Lisp_Object bodyx = body;
- popv(stack_used);
- /*
- * note that exit_count has not been disturbed since I called progn_fn,
- * so the numbert of values that will be returned remains correctly
- * established (in Common Lisp mode where it is needed.
- */
- return bodyx;
- }
- }
- unwind_special_bindings:
- /*
- * I gete here ONLY if nil has its mark bit set, which means that (for
- * one reason or another) I am having to unwind the stack, restoring
- * special bindings as I go.
- */
- nil = C_nil;
- flip_exception();
- while (specenv != nil)
- { Lisp_Object bv = qcar(specenv);
- qvalue(qcar(bv)) = qcdr(bv);
- specenv = qcdr(specenv);
- }
- flip_exception();
- { Lisp_Object qname = name;
- popv(stack_used);
- return qname;
- }
- #undef w
- #undef p
- #undef v
- #undef v1
- #undef arg
- #undef val1
- #undef specenv
- #undef restarg
- #undef ok_keys
- #undef local_decs
- #undef name
- #undef env
- #undef body
- #undef bvl
- #undef stack_used
- }
- Lisp_Object Leval(Lisp_Object nil, Lisp_Object a)
- {
- return eval(a, nil); /* Multiple values may be returned */
- }
- Lisp_Object Levlis(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object r;
- stackcheck1(0, a);
- r = nil;
- while (consp(a))
- { push2(qcdr(a), r);
- a = qcar(a);
- a = eval(a, nil);
- errexitn(2);
- pop(r);
- r = cons(a, r);
- pop(a);
- errexit();
- }
- return onevalue(nreverse(r));
- }
- Lisp_Object MS_CDECL Lapply_n(Lisp_Object nil, int nargs, ...)
- {
- va_list a;
- int i;
- Lisp_Object *stack_save = stack, last, fn;
- if (nargs == 0) return aerror("apply");
- if (nargs > 1)
- { va_start(a, nargs);
- fn = va_arg(a, Lisp_Object);
- push_args_1(a, nargs);
- pop(last);
- i = nargs-2;
- while (consp(last))
- { push(qcar(last));
- last = qcdr(last);
- i++;
- }
- }
- else i = 0;
- stackcheck1(stack-stack_save, fn);
- return apply(fn, i, nil, fn);
- }
- Lisp_Object Lapply_1(Lisp_Object nil, Lisp_Object fn)
- {
- return Lapply_n(nil, 1, fn);
- }
- Lisp_Object Lapply_2(Lisp_Object nil, Lisp_Object fn, Lisp_Object a1)
- {
- return Lapply_n(nil, 2, fn, a1);
- }
- Lisp_Object Lapply0(Lisp_Object nil, Lisp_Object fn)
- {
- if (is_symbol(fn)) return (*qfnn(fn))(qenv(fn), 0);
- stackcheck1(0, fn);
- return apply(fn, 0, C_nil, fn);
- }
- Lisp_Object Lapply1(Lisp_Object nil, Lisp_Object fn, Lisp_Object a)
- {
- if (is_symbol(fn)) return (*qfn1(fn))(qenv(fn), a);
- push(a);
- stackcheck1(1, fn);
- return apply(fn, 1, C_nil, fn);
- }
- Lisp_Object MS_CDECL Lapply2(Lisp_Object nil, int nargs, ...)
- {
- va_list aa;
- Lisp_Object fn, a, b;
- argcheck(nargs, 3, "apply2");
- va_start(aa, nargs);
- fn = va_arg(aa, Lisp_Object);
- a = va_arg(aa, Lisp_Object);
- b = va_arg(aa, Lisp_Object);
- va_end(aa);
- if (is_symbol(fn)) return (*qfn2(fn))(qenv(fn), a, b);
- push2(a, b);
- stackcheck1(2, fn);
- return apply(fn, 2, C_nil, fn);
- }
- Lisp_Object MS_CDECL Lapply3(Lisp_Object nil, int nargs, ...)
- {
- va_list aa;
- Lisp_Object fn, a, b, c;
- argcheck(nargs, 4, "apply3");
- va_start(aa, nargs);
- fn = va_arg(aa, Lisp_Object);
- a = va_arg(aa, Lisp_Object);
- b = va_arg(aa, Lisp_Object);
- c = va_arg(aa, Lisp_Object);
- va_end(aa);
- if (is_symbol(fn)) return (*qfnn(fn))(qenv(fn), 3, a, b, c);
- push3(a, b, c);
- stackcheck1(3, fn);
- return apply(fn, 3, C_nil, fn);
- }
- Lisp_Object Lfuncall1(Lisp_Object nil, Lisp_Object fn)
- {
- if (is_symbol(fn)) return (*qfnn(fn))(qenv(fn), 0);
- stackcheck1(0, fn);
- return apply(fn, 0, nil, fn);
- }
- Lisp_Object Lfuncall2(Lisp_Object nil, Lisp_Object fn, Lisp_Object a1)
- {
- if (is_symbol(fn)) return (*qfn1(fn))(qenv(fn), a1);
- push(a1);
- stackcheck1(1, fn);
- return apply(fn, 1, nil, fn);
- }
- static Lisp_Object MS_CDECL Lfuncalln_sub(Lisp_Object nil, int nargs, va_list a)
- {
- Lisp_Object *stack_save = stack, fn;
- fn = va_arg(a, Lisp_Object);
- push_args_1(a, nargs);
- stackcheck1(stack-stack_save, fn);
- return apply(fn, nargs-1, nil, fn);
- }
- Lisp_Object MS_CDECL Lfuncalln(Lisp_Object nil, int nargs, ...)
- {
- va_list a;
- Lisp_Object fn, a1, a2, a3, a4;
- va_start(a, nargs);
- switch (nargs)
- {
- case 0: return aerror("funcall");
- case 1: /* cases 1 and 2 should go through Lfuncall1,2 not here */
- case 2: return aerror("funcall wrong call");
- case 3: fn = va_arg(a, Lisp_Object);
- a1 = va_arg(a, Lisp_Object);
- a2 = va_arg(a, Lisp_Object);
- if (is_symbol(fn)) return (*qfn2(fn))(qenv(fn), a1, a2);
- push2(a1, a2);
- return apply(fn, 2, nil, fn);
- case 4: fn = va_arg(a, Lisp_Object);
- a1 = va_arg(a, Lisp_Object);
- a2 = va_arg(a, Lisp_Object);
- a3 = va_arg(a, Lisp_Object);
- if (is_symbol(fn)) return (*qfnn(fn))(qenv(fn), 3, a1, a2, a3);
- push3(a1, a2, a3);
- return apply(fn, 3, nil, fn);
- case 5: fn = va_arg(a, Lisp_Object);
- a1 = va_arg(a, Lisp_Object);
- a2 = va_arg(a, Lisp_Object);
- a3 = va_arg(a, Lisp_Object);
- a4 = va_arg(a, Lisp_Object);
- if (is_symbol(fn)) return (*qfnn(fn))(qenv(fn), 4, a1, a2, a3, a4);
- push4(a1, a2, a3, a4);
- return apply(fn, 4, nil, fn);
- default:
- return Lfuncalln_sub(nil, nargs, a);
- }
- }
- #ifdef COMMON
- Lisp_Object MS_CDECL Lvalues(Lisp_Object nil, int nargs, ...)
- {
- va_list a;
- Lisp_Object *p = &mv_2, w;
- int i;
- /*
- * Because multiple-values get passed back in static storage there is
- * a fixed upper limit to how many I can handle - truncate here to allow
- * for that.
- */
- if (nargs > 50) nargs = 50;
- if (nargs == 0) return nvalues(nil, 0);
- va_start(a, nargs);
- push_args(a, nargs);
- for (i=1; i<nargs; i++)
- { pop(w);
- p[nargs-i-1] = w;
- }
- pop(w);
- return nvalues(w, nargs);
- }
- Lisp_Object Lvalues_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- return Lvalues(nil, 2, a, b);
- }
- Lisp_Object Lvalues_1(Lisp_Object nil, Lisp_Object a)
- {
- return Lvalues(nil, 1, a);
- }
- Lisp_Object mv_call_fn(Lisp_Object args, Lisp_Object env)
- /*
- * here with the rest of the interpreter rather than in specforms.c
- */
- {
- Lisp_Object nil = C_nil;
- Lisp_Object fn, *stack_save = stack;
- int i=0, j=0;
- if (!consp(args)) return nil; /* (multiple-value-call) => nil */
- stackcheck2(0, args, env);
- push2(args, env);
- fn = qcar(args);
- fn = eval(fn, env);
- pop2(env, args);
- errexit();
- args = qcdr(args);
- while (consp(args))
- { Lisp_Object r1;
- push2(args, env);
- r1 = qcar(args);
- r1 = eval(r1, env);
- nil = C_nil;
- if (exception_pending())
- { stack = stack_save;
- return nil;
- }
- /*
- * It is critical here that push does not check for stack overflow and
- * thus can not call the garbage collector, or otherwise lead to calculation
- * that could possibly clobber the multiple results that I am working with
- * here.
- */
- pop2(env, args);
- push(r1);
- i++;
- for (j = 2; j<=exit_count; j++)
- { push((&work_0)[j]);
- i++;
- }
- args = qcdr(args);
- }
- stackcheck2(stack-stack_save, fn, env);
- return apply(fn, i, env, fn);
- }
- #endif
- Lisp_Object interpreted1(Lisp_Object def, Lisp_Object a1)
- {
- Lisp_Object nil = C_nil;
- push(a1);
- stackcheck1(1, def);
- return apply_lambda(def, 1, nil, def);
- }
- Lisp_Object interpreted2(Lisp_Object def, Lisp_Object a1, Lisp_Object a2)
- {
- Lisp_Object nil = C_nil;
- push2(a1, a2);
- stackcheck1(2, def);
- return apply_lambda(def, 2, nil, def);
- }
- Lisp_Object MS_CDECL interpretedn(Lisp_Object def, int nargs, ...)
- {
- /*
- * The messing about here is to get the (unknown number of) args
- * into a nice neat vector so that they can be indexed into. If I knew
- * that the args were in consecutive locations on the stack I could
- * probably save a copying operation.
- */
- Lisp_Object nil = C_nil;
- Lisp_Object *stack_save = stack;
- va_list a;
- if (nargs != 0)
- { va_start(a, nargs);
- push_args(a, nargs);
- }
- stackcheck1(stack-stack_save, def);
- return apply_lambda(def, nargs, nil, def);
- }
- Lisp_Object funarged1(Lisp_Object def, Lisp_Object a1)
- {
- Lisp_Object nil = C_nil;
- push(a1);
- stackcheck1(1, def);
- return apply_lambda(qcdr(def), 1, qcar(def), qcdr(def));
- }
- Lisp_Object funarged2(Lisp_Object def, Lisp_Object a1, Lisp_Object a2)
- {
- Lisp_Object nil = C_nil;
- push2(a1, a2);
- stackcheck1(2, def);
- return apply_lambda(qcdr(def), 2, qcar(def), qcdr(def));
- }
- Lisp_Object MS_CDECL funargedn(Lisp_Object def, int nargs, ...)
- {
- Lisp_Object nil = C_nil;
- Lisp_Object *stack_save = stack;
- va_list a;
- if (nargs != 0)
- { va_start(a, nargs);
- push_args(a, nargs);
- }
- stackcheck1(stack-stack_save, def);
- return apply_lambda(qcdr(def), nargs, qcar(def), qcdr(def));
- }
- /*
- * Now some execution-doubling versions...
- */
- Lisp_Object double_interpreted1(Lisp_Object def, Lisp_Object a1)
- {
- Lisp_Object nil = C_nil;
- push(a1);
- stackcheck1(1, def);
- return apply_lambda(def, 1, nil, def);
- }
- Lisp_Object double_interpreted2(Lisp_Object def, Lisp_Object a1, Lisp_Object a2)
- {
- Lisp_Object nil = C_nil;
- push2(a1, a2);
- stackcheck1(2, def);
- return apply_lambda(def, 2, nil, def);
- }
- Lisp_Object MS_CDECL double_interpretedn(Lisp_Object def, int nargs, ...)
- {
- /*
- * The messing about here is to get the (unknown number of) args
- * into a nice neat vector so that they can be indexed into. If I knew
- * that the args were in consecutive locations on the stack I could
- * probably save a copying operation.
- */
- Lisp_Object nil = C_nil;
- Lisp_Object *stack_save = stack;
- va_list a;
- if (nargs != 0)
- { va_start(a, nargs);
- push_args(a, nargs);
- }
- stackcheck1(stack-stack_save, def);
- return apply_lambda(def, nargs, nil, def);
- }
- Lisp_Object double_funarged1(Lisp_Object def, Lisp_Object a1)
- {
- Lisp_Object nil = C_nil;
- push(a1);
- stackcheck1(1, def);
- return apply_lambda(qcdr(def), 1, qcar(def), qcdr(def));
- }
- Lisp_Object double_funarged2(Lisp_Object def, Lisp_Object a1, Lisp_Object a2)
- {
- Lisp_Object nil = C_nil;
- push2(a1, a2);
- stackcheck1(2, def);
- return apply_lambda(qcdr(def), 2, qcar(def), qcdr(def));
- }
- Lisp_Object MS_CDECL double_funargedn(Lisp_Object def, int nargs, ...)
- {
- Lisp_Object nil = C_nil;
- Lisp_Object *stack_save = stack;
- va_list a;
- if (nargs != 0)
- { va_start(a, nargs);
- push_args(a, nargs);
- }
- stackcheck1(stack-stack_save, def);
- return apply_lambda(qcdr(def), nargs, qcar(def), qcdr(def));
- }
- int trace_depth = 0;
- static void trace_entering(char *s)
- {
- int i;
- for (i=0; i<trace_depth; i++) trace_printf(" ");
- trace_printf(s);
- trace_depth++;
- }
- static void trace_exiting(char *s)
- {
- int i;
- trace_depth--;
- trace_printf(s);
- }
- Lisp_Object traceinterpreted1(Lisp_Object def, Lisp_Object a1)
- /*
- * Like interpreted() but the definition has the fn name consed on the front
- */
- {
- Lisp_Object nil = C_nil, r;
- push(a1);
- stackcheck1(1, def);
- freshline_trace();
- trace_entering("Entering ");
- loop_print_trace(qcar(def));
- trace_printf(" (1 arg)\n");
- trace_printf("Arg1: ");
- loop_print_trace(stack[0]);
- trace_printf("\n");
- r = apply_lambda(qcdr(def), 1, nil, def);
- errexit();
- push(r);
- trace_printf("Value = ");
- loop_print_trace(r);
- trace_exiting("\n");
- pop(r);
- return r;
- }
- Lisp_Object traceinterpreted2(Lisp_Object def, Lisp_Object a1, Lisp_Object a2)
- /*
- * Like interpreted() but the definition has the fn name consed on the front
- */
- {
- Lisp_Object nil = C_nil, r;
- int i;
- push2(a1, a2);
- stackcheck1(2, def);
- freshline_trace();
- trace_entering("Entering ");
- loop_print_trace(qcar(def));
- trace_printf(" (2 args)\n");
- for (i=1; i<=2; i++)
- { trace_printf("Arg%d: ", i);
- loop_print_trace(stack[i-2]);
- trace_printf("\n");
- }
- r = apply_lambda(qcdr(def), 2, nil, def);
- errexit();
- push(r);
- trace_printf("Value = ");
- loop_print_trace(r);
- trace_exiting("\n");
- pop(r);
- return r;
- }
- Lisp_Object MS_CDECL traceinterpretedn(Lisp_Object def, int nargs, ...)
- /*
- * Like interpreted() but the definition has the fn name consed on the front
- */
- {
- int i;
- Lisp_Object nil = C_nil, r;
- Lisp_Object *stack_save = stack;
- va_list a;
- if (nargs != 0)
- { va_start(a, nargs);
- push_args(a, nargs);
- }
- stackcheck1(stack-stack_save, def);
- freshline_trace();
- trace_entering("Entering ");
- loop_print_trace(qcar(def));
- trace_printf(" (%d args)\n", nargs);
- for (i=1; i<=nargs; i++)
- { trace_printf("Arg%d: ", i);
- loop_print_trace(stack[i-nargs]);
- trace_printf("\n");
- }
- r = apply_lambda(qcdr(def), nargs, nil, def);
- errexit();
- push(r);
- trace_printf("Value = ");
- loop_print_trace(r);
- trace_exiting("\n");
- pop(r);
- return r;
- }
- Lisp_Object tracefunarged1(Lisp_Object def, Lisp_Object a1)
- /*
- * Like funarged() but with some printing
- */
- {
- Lisp_Object nil = C_nil, r;
- push(a1);
- stackcheck1(1, def);
- freshline_trace();
- trace_entering("Entering funarg ");
- loop_print_trace(qcar(def));
- trace_printf(" (1 arg)\n");
- def = qcdr(def);
- r = apply_lambda(qcdr(def), 1, qcar(def), qcdr(def));
- errexit();
- push(r);
- trace_printf("Value = ");
- loop_print_trace(r);
- trace_exiting("\n");
- pop(r);
- return r;
- }
- Lisp_Object tracefunarged2(Lisp_Object def, Lisp_Object a1, Lisp_Object a2)
- /*
- * Like funarged() but with some printing
- */
- {
- Lisp_Object nil = C_nil, r;
- push2(a1, a2);
- stackcheck1(2, def);
- freshline_trace();
- trace_entering("Entering funarg ");
- loop_print_trace(qcar(def));
- trace_printf(" (2 args)\n");
- def = qcdr(def);
- r = apply_lambda(qcdr(def), 2, qcar(def), qcdr(def));
- errexit();
- push(r);
- trace_printf("Value = ");
- loop_print_trace(r);
- trace_exiting("\n");
- pop(r);
- return r;
- }
- Lisp_Object MS_CDECL tracefunargedn(Lisp_Object def, int nargs, ...)
- /*
- * Like funarged() but with some printing
- */
- {
- Lisp_Object nil = C_nil, r;
- Lisp_Object *stack_save = stack;
- va_list a;
- if (nargs != 0)
- { va_start(a, nargs);
- push_args(a, nargs);
- }
- stackcheck1(stack-stack_save, def);
- freshline_trace();
- trace_entering("Entering funarg ");
- loop_print_trace(qcar(def));
- trace_printf(" (%d args)\n", nargs);
- def = qcdr(def);
- r = apply_lambda(qcdr(def), nargs, qcar(def), qcdr(def));
- errexit();
- push(r);
- trace_printf("Value = ");
- loop_print_trace(r);
- trace_exiting("\n");
- pop(r);
- return r;
- }
- static Lisp_Object macroexpand_1(Lisp_Object form, Lisp_Object env)
- { /* The environment here seems only necessary for macrolet */
- Lisp_Object done;
- Lisp_Object f, nil;
- nil = C_nil;
- stackcheck2(0, form, env);
- done = nil;
- if (consp(form))
- { f = qcar(form);
- #ifdef COMMON
- /*
- * look for local macro definitions
- */
- { Lisp_Object p;
- for (p=env; p!=nil; p=qcdr(p))
- { Lisp_Object w = qcar(p);
- if (qcdr(w) == f && is_cons(w = qcar(w)) && w!=nil)
- {
- p = qcar(w);
- if (p == funarg) /* ordinary function */
- { mv_2 = nil;
- return nvalues(form, 2);
- }
- push2(form, done);
- w = cons(lambda, w);
- errexitn(1);
- p = Lfuncalln(nil, 4, qvalue(macroexpand_hook),
- w, stack[-1], nil);
- pop2(done, form);
- nil = C_nil;
- if (exception_pending())
- { flip_exception();
- if ((exit_reason & UNWIND_ERROR) != 0)
- { err_printf("\nMacroexpanding: ");
- loop_print_error(form);
- nil = C_nil;
- if (exception_pending()) flip_exception();
- }
- flip_exception();
- return nil;
- }
- mv_2 = lisp_true;
- return nvalues(p, 2);
- }
- }
- }
- /*
- * If there is no local macro definition I need to look for a global one
- */
- #endif
- if (symbolp(f) && (qheader(f) & SYM_MACRO) != 0)
- {
- done = qvalue(macroexpand_hook);
- if (done == unset_var)
- return error(1, err_macroex_hook, macroexpand_hook);
- push3(form, env, done);
- f = cons(lambda, qenv(f));
- pop3(done, env, form);
- nil = C_nil;
- if (!exception_pending())
- {
- #ifndef COMMON
- /* CSL does not pass an environment down here, so does not demand &opt arg */
- form = Lfuncalln(nil, 3, done, f, form);
- #else
- form = Lfuncalln(nil, 4, done, f, form, env);
- #endif
- nil = C_nil;
- }
- if (exception_pending()) return nil;
- done = lisp_true;
- }
- }
- mv_2 = done;
- return nvalues(form, 2); /* Multiple values handed back */
- }
- Lisp_Object macroexpand(Lisp_Object form, Lisp_Object env)
- { /* The environment here seems only necessary for macrolet */
- Lisp_Object done, nil;
- nil = C_nil;
- stackcheck2(0, form, env);
- done = nil;
- for (;;)
- { push2(env, done);
- form = macroexpand_1(form, env);
- pop2(done, env);
- errexit();
- if (mv_2 == nil) break;
- done = lisp_true;
- }
- mv_2 = done;
- return nvalues(form, 2); /* Multiple values handed back */
- }
- Lisp_Object Lmacroexpand(Lisp_Object nil, Lisp_Object a)
- {
- return macroexpand(a, nil);
- }
- #ifdef COMMON
- Lisp_Object Lmacroexpand_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- return macroexpand(a, b);
- }
- #endif
- Lisp_Object Lmacroexpand_1(Lisp_Object nil, Lisp_Object a)
- {
- return macroexpand_1(a, nil);
- }
- #ifdef COMMON
- Lisp_Object Lmacroexpand_1_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- return macroexpand_1(a, b);
- }
- #endif
- /*
- * To make something autoloadable I should set the environment cell to
- * (name-of-self module-name-1 module-name-2 ...)
- * and when invoked the function will do a load-module on each of the
- * modules specified and then re-attempt to call. Loading the
- * modules is expected to establish a proper definition for the
- * function involved.
- */
- Lisp_Object autoload1(Lisp_Object fname, Lisp_Object a1)
- {
- Lisp_Object nil = C_nil;
- push2(a1, qcar(fname));
- set_fns(qcar(fname), undefined1, undefined2, undefinedn);
- qenv(qcar(fname)) = qcar(fname);
- fname = qcdr(fname);
- while (consp(fname))
- { push(qcdr(fname));
- Lload_module(nil, qcar(fname));
- errexitn(3);
- pop(fname);
- }
- pop(fname);
- return apply(fname, 1, nil, fname);
- }
- Lisp_Object autoload2(Lisp_Object fname, Lisp_Object a1, Lisp_Object a2)
- {
- Lisp_Object nil = C_nil;
- push3(a1, a2, qcar(fname));
- set_fns(qcar(fname), undefined1, undefined2, undefinedn);
- qenv(qcar(fname)) = qcar(fname);
- fname = qcdr(fname);
- while (consp(fname))
- { push(qcdr(fname));
- Lload_module(nil, qcar(fname));
- errexitn(4);
- pop(fname);
- }
- pop(fname);
- return apply(fname, 2, nil, fname);
- }
- Lisp_Object MS_CDECL autoloadn(Lisp_Object fname, int nargs, ...)
- {
- Lisp_Object nil = C_nil;
- va_list a;
- va_start(a, nargs);
- push_args(a, nargs);
- push(qcar(fname));
- set_fns(qcar(fname), undefined1, undefined2, undefinedn);
- qenv(qcar(fname)) = qcar(fname);
- fname = qcdr(fname);
- while (consp(fname))
- { push(qcdr(fname));
- Lload_module(nil, qcar(fname));
- errexitn(nargs+2);
- pop(fname);
- }
- pop(fname);
- return apply(fname, nargs, nil, fname);
- }
- Lisp_Object undefined1(Lisp_Object fname, Lisp_Object a1)
- {
- /*
- * It would be perfectly possible to grab and save the args here, and retry
- * the function call after error has patched things up. Again
- * this entrypoint is for compiled code calling something that is undefined,
- * and so no lexical environment is needed.
- */
- CSL_IGNORE(a1);
- return error(1, err_undefined_function_1, fname);
- }
- Lisp_Object undefined2(Lisp_Object fname, Lisp_Object a1, Lisp_Object a2)
- {
- CSL_IGNORE(a1);
- CSL_IGNORE(a2);
- return error(1, err_undefined_function_2, fname);
- }
- Lisp_Object MS_CDECL undefinedn(Lisp_Object fname, int nargs, ...)
- {
- CSL_IGNORE(nargs);
- return error(1, err_undefined_function_n, fname);
- }
- /*
- * The next few functions allow me to create variants on things! The
- * entrypoint fX_as_Y goes in the function cell of a symbol, and the name
- * of a function with Y arguments goes in is environment cell. The result will
- * be a function that accepts X arguments and discards all but the first Y of
- * them, then chains to the other function. The purpose is to support goo
- * compilation of things like
- * (de funny_equal (a b c) (equal a b))
- */
- Lisp_Object MS_CDECL f0_as_0(Lisp_Object env, int nargs, ...)
- {
- if (nargs != 0) return aerror1("wrong number of args (0->0)", env);
- return (*qfnn(env))(qenv(env), 0);
- }
- Lisp_Object f1_as_0(Lisp_Object env, Lisp_Object a)
- {
- return (*qfnn(env))(qenv(env), 0);
- }
- Lisp_Object f2_as_0(Lisp_Object env, Lisp_Object a, Lisp_Object b)
- {
- return (*qfnn(env))(qenv(env), 0);
- }
- Lisp_Object MS_CDECL f3_as_0(Lisp_Object env, int nargs, ...)
- {
- if (nargs != 3) return aerror1("wrong number of args (3->0)", env);
- return (*qfnn(env))(qenv(env), 0);
- }
- Lisp_Object f1_as_1(Lisp_Object env, Lisp_Object a)
- {
- return (*qfn1(env))(qenv(env), a);
- }
- Lisp_Object f2_as_1(Lisp_Object env, Lisp_Object a, Lisp_Object b)
- {
- return (*qfn1(env))(qenv(env), a);
- }
- Lisp_Object MS_CDECL f3_as_1(Lisp_Object env, int nargs, ...)
- {
- va_list a;
- Lisp_Object a1;
- if (nargs != 3) return aerror1("wrong number of args (3->1)", env);
- va_start(a, nargs);
- a1 = va_arg(a, Lisp_Object);
- va_end(a);
- return (*qfn1(env))(qenv(env), a1);
- }
- Lisp_Object f2_as_2(Lisp_Object env, Lisp_Object a, Lisp_Object b)
- {
- return (*qfn2(env))(qenv(env), a, b);
- }
- Lisp_Object MS_CDECL f3_as_2(Lisp_Object env, int nargs, ...)
- {
- va_list a;
- Lisp_Object a1, a2;
- if (nargs != 3) return aerror1("wrong number of args (3->2)", env);
- va_start(a, nargs);
- a1 = va_arg(a, Lisp_Object);
- a2 = va_arg(a, Lisp_Object);
- va_end(a);
- return (*qfn2(env))(qenv(env), a1, a2);
- }
- Lisp_Object MS_CDECL f3_as_3(Lisp_Object env, int nargs, ...)
- {
- va_list a;
- Lisp_Object a1, a2, a3;
- if (nargs != 3) return aerror1("wrong number of args (3->3)", env);
- va_start(a, nargs);
- a1 = va_arg(a, Lisp_Object);
- a2 = va_arg(a, Lisp_Object);
- a3 = va_arg(a, Lisp_Object);
- va_end(a);
- return (*qfnn(env))(qenv(env), 3, a1, a2, a3);
- }
- setup_type const eval1_setup[] =
- {
- {"bytecounts", wrong_no_na, wrong_no_nb, bytecounts},
- {"apply", Lapply_1, Lapply_2, Lapply_n},
- {"apply0", Lapply0, too_many_1, wrong_no_1},
- {"apply1", too_few_2, Lapply1, wrong_no_2},
- {"apply2", wrong_no_na, wrong_no_nb, Lapply2},
- {"apply3", wrong_no_na, wrong_no_nb, Lapply3},
- {"evlis", Levlis, too_many_1, wrong_no_1},
- {"funcall", Lfuncall1, Lfuncall2, Lfuncalln},
- {"funcall*", Lfuncall1, Lfuncall2, Lfuncalln},
- #ifdef COMMON
- {"values", Lvalues_1, Lvalues_2, Lvalues},
- {"macroexpand", Lmacroexpand, Lmacroexpand_2, wrong_no_1},
- {"macroexpand-1", Lmacroexpand_1, Lmacroexpand_1_2, wrong_no_1},
- #else
- {"macroexpand", Lmacroexpand, too_many_1, wrong_no_1},
- {"macroexpand-1", Lmacroexpand_1, too_many_1, wrong_no_1},
- #endif
- {NULL, 0, 0, 0}
- };
- /* end of eval1.c */
|