diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 1681 |
1 files changed, 1200 insertions, 481 deletions
@@ -47,18 +47,130 @@ #define I_SYM(x) (CAR((x)-1L)) #define I_VAL(x) (CDR((x)-1L)) -#ifdef MACRO -# define ATOMP(x) (5==(5 & (int)CAR(x))) -# define EVALCELLCAR(x,env) (ATOMP(CAR(x))?evalatomcar(x,env):ceval(CAR(x),env)) +#define ATOMP(x) (5==(5 & (int)CAR(x))) +#define EVALCELLCAR(x) (ATOMP(CAR(x))?evalatomcar(x):ceval_1(CAR(x))) + +/* Environment frames are initially allocated in a small cache ("ecache"). + This cache is subject to copying gc, cells in it may be moved to the + general purpose Scheme heap by a call to any routine that allocates cells + in the cache. + + Global variables scm_env and scm_env_tmp are used as software + registers: scm_env is the current lexical environment, scm_env_tmp + is used for protecting environment frames under construction and not + yet linked into the environment. + + In order to protect environments from garbage collection, a stack of + environments (scm_estk) is maintained. scm_env and scm_env_tmp may + be pushed on or popped off the stack using the macros ENV_PUSH and + ENV_POP. + + It is not safe to pass objects that may allocated in the ecache as + arguments to C functions, or to return them from C functions, since + such objects may be moved by the ecache gc. Ecache gc may happen + anywhere interrupts are not deferred, because some interrupt + handlers may evaluate Scheme code and then return. + + Interrupts may be deferred with DEFER_INTS_EGC: This will prevent + interrupts until an ALLOW_INTS or ALLOW_INTS_EGC, which may happen + any time Scheme code is evaluated. It is not necessary to strictly + nest DEFER_INTS_EGC and ALLOW_INTS_EGC since ALLOW_INTS_EGC is + called in ceval_1 before any subrs are called. + + Instead of using the C stack and deferring interrupts, objects which + might have been allocated in the ecache may be passed using the + global variables scm_env_tmp and scm_env. + + If the CDR of a cell that might be allocated in the regular heap is + made to point to a cell allocated in the cache, then the first cell + must be recorded as a gc root, using the macro EGC_ROOT. There is + no provision for allowing the CAR of a regular cell to point to a + cache cell. */ + +#ifdef NO_ENV_CACHE +# define scm_env_cons(a,b) {scm_env_tmp=cons((a),(b));} +# define scm_env_cons2(a,b,c) {scm_env_tmp=cons2((a),(b),(c));} +# define scm_env_cons_tmp(a) {scm_env_tmp=cons((a),scm_env_tmp);} +# define EXTEND_ENV(names) {scm_env=acons((names),scm_env_tmp,scm_env);} #else -# define EVALCELLCAR(x, env) SYMBOLP(CAR(x))?*lookupcar(x, env):ceval(CAR(x), env) +# define EXTEND_ENV scm_extend_env +#endif + +SCM scm_env = EOL, scm_env_tmp = UNSPECIFIED; +long tc16_env; /* Type code for environments passed to macro + transformers. */ +SCM nconc2copy P((SCM x)); +SCM copy_list P((SCM x)); +SCM rename_ident P((SCM id, SCM env)); +SCM eqv P((SCM x, SCM y)); +void scm_dynthrow P((CONTINUATION *cont, SCM val)); +void scm_egc P((void)); +void scm_estk_grow P((sizet inc)); +void scm_estk_shrink P((void)); +int badargsp P((SCM proc, SCM args)); + +static SCM ceval_1 P((SCM x)); +static SCM evalatomcar P((SCM x)); +static SCM evalcar P((SCM x)); +static SCM id2sym P((SCM id)); +static SCM iqq P((SCM form)); +static SCM m_body P((SCM op, SCM xorig, char *what)); +static SCM m_iqq P((SCM form, int depth, SCM env)); +static SCM m_letrec1 P((SCM op, SCM imm, SCM xorig, SCM env)); +static SCM macroexp1 P((SCM x, int check)); +static SCM unmemocar P((SCM x)); +static SCM wrapenv P((void)); +static SCM *id_denote P((SCM var)); +static int prinenv P((SCM exp, SCM port, int writing)); +static int prinid P((SCM exp, SCM port, int writing)); +static int prinmacro P((SCM exp, SCM port, int writing)); +static int prinprom P((SCM exp, SCM port, int writing)); +static void bodycheck P((SCM xorig, SCM *bodyloc, char *what)); +static void unpaint P((SCM *p)); +#ifdef CAREFUL_INTS +static void debug_env_warn P((char *fnam, long line, char *what)); +#endif + +/* Flush global variable state to estk. */ +#define ENV_SAVE {scm_estk_ptr[0]=scm_env; scm_estk_ptr[1]=scm_env_tmp;} + +/* Make global variable state consistent with estk. */ +#define ENV_RESTORE {scm_env=scm_estk_ptr[0]; scm_env_tmp=scm_estk_ptr[1];} + +#define ENV_PUSH {DEFER_INTS_EGC; ENV_SAVE;\ + if (INUM0==scm_estk_ptr[SCM_ESTK_FRLEN]) scm_estk_grow(20);\ + else scm_estk_ptr += SCM_ESTK_FRLEN;} + +#define ENV_POP {DEFER_INTS_EGC;\ + if (INUM0==scm_estk_ptr[-SCM_ESTK_FRLEN]) scm_estk_shrink();\ + else scm_estk_ptr -= SCM_ESTK_FRLEN; ENV_RESTORE;} + +#ifdef NO_ENV_CACHE +# define EGC_ROOT(x) /**/ +#else +# ifdef CAREFUL_INTS +# define EGC_ROOT(x) {if (!ints_disabled) \ + debug_env_warn(__FILE__,__LINE__,"EGC_ROOT"); \ + scm_egc_roots[--scm_egc_root_index] = (x); \ + if (0==scm_egc_root_index) scm_egc();} +# else +# define EGC_ROOT(x) {scm_egc_roots[--scm_egc_root_index] = (x);\ + if (0==scm_egc_root_index) scm_egc();} +# endif #endif -#define EVALIMP(x, env) (ILOCP(x)?*ilookup((x), env):x) -#define EVALCAR(x, env) (NCELLP(CAR(x))?(IMP(CAR(x))?EVALIMP(CAR(x), env):\ - I_VAL(CAR(x))):EVALCELLCAR(x, env)) -#define EXTEND_ENV acons +#define ENV_MAY_POP(p, guard) if (p>0 && !(guard)) {ENV_POP; p=-1;} +#define ENV_MAY_PUSH(p) if (p<=0) {ENV_PUSH; p=1;} +#define SIDEVAL_1(x) if NIMP(x) ceval_1(x) +#ifdef CAUTIOUS +# define TRACE(x) scm_estk_ptr[2]=(x) +#else +# define TRACE(x) /**/ +#endif +#define EVALIMP(x) (ILOCP(x)?*ilookup(x):x) +#define EVALCAR(x) (NCELLP(CAR(x))?(IMP(CAR(x))?EVALIMP(CAR(x)):\ + I_VAL(CAR(x))):EVALCELLCAR(x)) long tc16_macro; /* Type code for macros */ #define MACROP(x) (tc16_macro==TYP16(x)) @@ -75,26 +187,148 @@ static char s_escaped[] = "escaped synthetic identifier"; # define ENV_MARK BOOL_T #else # define IDENTP SYMBOLP +# define M_IDENTP(x) (0) #endif -SCM *ilookup(iloc, env) - SCM iloc, env; +/* #define SCM_PROFILE */ +#ifdef SCM_PROFILE +long eval_cases[128]; +long eval_cases_other[NUM_ISYMS]; +long ilookup_cases[10][10][2]; /* frame, dist, icdrp */ +long eval_clo_cases[5][4]; /* actual args, required args */ +SCM scm_profile(resetp) + SCM resetp; +{ + SCM ev = make_uve(sizeof(eval_cases)/sizeof(long), MAKINUM(-1)); + SCM evo = make_uve(sizeof(eval_cases_other)/sizeof(long), MAKINUM(-1)); + SCM il = dims2ura(cons2(MAKINUM(10), MAKINUM(10), cons(MAKINUM(2), EOL)), + MAKINUM(-1), EOL); + SCM evc = dims2ura(cons2(MAKINUM(5), MAKINUM(4), EOL), MAKINUM(-1), EOL); + long *v = (long *)VELTS(ev); + int i; + for (i = 0; i < sizeof(eval_cases)/sizeof(long); i++) + v[i] = eval_cases[i]; + v = (long *)VELTS(evo); + for (i = 0; i < sizeof(eval_cases_other)/sizeof(long); i++) + v[i] = eval_cases_other[i]; + v = (long *)VELTS(ARRAY_V(il)); + for (i = 0; i < sizeof(ilookup_cases)/sizeof(long); i++) + v[i] = ((long *)ilookup_cases)[i]; + v = (long *)VELTS(ARRAY_V(evc)); + for (i = 0; i < sizeof(eval_clo_cases)/sizeof(long); i++) + v[i] = ((long *)eval_clo_cases)[i]; + if (! UNBNDP(resetp)) { + for (i = 0; i < sizeof(eval_cases)/sizeof(long); i++) + eval_cases[i] = 0; + for (i = 0; i < sizeof(eval_cases_other)/sizeof(long); i++) + eval_cases_other[i] = 0; + for (i = 0; i < sizeof(ilookup_cases)/sizeof(long); i++) + ((long *)ilookup_cases)[i] = 0; + for (i = 0; i < sizeof(eval_clo_cases)/sizeof(long); i++) + ((long *)eval_clo_cases)[i] = 0; + } + return cons2(ev, evo, cons2(il, evc, EOL)); +} +#endif + +#ifdef CAREFUL_INTS +# undef CAR +# define CAR(x) (*debug_env_car((x), __FILE__, __LINE__)) +# undef CDR +# define CDR(x) (*debug_env_cdr((x), __FILE__, __LINE__)) +/* Inhibit warnings for ARGC, is not changed by egc. */ +# undef ARGC +# define ARGC(x) ((6L & (((cell *)(SCM2PTR(x)))->cdr))>>1) +#include <signal.h> +SCM test_ints(x) + SCM x; +{ + static int cnt = 100; + if (0==--cnt) { + cnt = 100; + DEFER_INTS; + scm_egc(); + ALLOW_INTS; + /* l_raise(MAKINUM(SIGALRM)); */ + } + return x; +} +int ecache_p(x) + SCM x; +{ + register CELLPTR ptr; + if NCELLP(x) return 0; + ptr = (CELLPTR)SCM2PTR(x); + if (PTR_LE(scm_ecache, ptr) + && PTR_GT(scm_ecache+scm_ecache_len, ptr)) + return !0; + return 0; +} +static void debug_env_warn(fnam, line, what) + char *fnam; + long line; + char *what; +{ + lputs(fnam, cur_errp); + lputc(':', cur_errp); + intprint(line, 10, cur_errp); + lputs(": unprotected ", cur_errp); + lputs(what, cur_errp); + lputs(" of ecache value\n", cur_errp); +} +SCM *debug_env_car(x, fnam, line) + SCM x; + char *fnam; + long line; +{ + SCM *ret; + if (!ints_disabled && ecache_p(x)) + debug_env_warn(fnam, line, "CAR"); + ret = &(((cell *)(SCM2PTR(x)))->car); + if (!ints_disabled && NIMP(*ret) && ecache_p(*ret)) + debug_env_warn(fnam, line, "CAR"); + return ret; +} +SCM *debug_env_cdr(x, fnam, line) + SCM x; + char *fnam; + long line; +{ + SCM *ret; + if (!ints_disabled && ecache_p(x)) + debug_env_warn(fnam, line, "CDR"); + ret = &(((cell *)(SCM2PTR(x)))->cdr); + if (!ints_disabled && NIMP(*ret) && ecache_p(*ret)) + debug_env_warn(fnam, line, "CAR"); + return ret; +} +#endif /* CAREFUL_INTS */ + +SCM *ilookup(iloc) + SCM iloc; { register int ir = IFRAME(iloc); - register SCM er = env; + register SCM er; +#ifdef SCM_PROFILE + ilookup_cases[ir<10 ? ir : 9] + [IDIST(iloc)<10 ? IDIST(iloc) : 9][ICDRP(iloc)?1:0]++; +#endif + DEFER_INTS_EGC; + er = scm_env; for(;0 != ir;--ir) er = CDR(er); er = CAR(er); for(ir = IDIST(iloc);0 != ir;--ir) er = CDR(er); if ICDRP(iloc) return &CDR(er); return &CAR(CDR(er)); } - -SCM *farlookup(farloc, env) - SCM farloc, env; +SCM *farlookup(farloc) + SCM farloc; { register int ir; - register SCM er = env; + register SCM er; SCM x = CDR(farloc); + DEFER_INTS_EGC; + er = scm_env; for (ir = INUM(CAR(x)); 0 != ir; --ir) er = CDR(er); er = CAR(er); for (ir = INUM(CDR(x)); 0 != ir; --ir) er = CDR(er); @@ -102,15 +336,23 @@ SCM *farlookup(farloc, env) return &CAR(CDR(er)); } -SCM *lookupcar(vloc, genv) - SCM vloc, genv; +static char s_badkey[] = "Use of keyword as variable", + s_unbnd[] = "unbound variable: ", s_wtap[] = "Wrong type to apply: "; +/* check is logical OR of LOOKUP_UNDEFP and LOOKUP_MACROP */ +#define LOOKUP_UNDEFP 1 +#define LOOKUP_MACROP 2 +SCM *lookupcar(vloc, check) + SCM vloc; + int check; { - SCM env = genv; + SCM env; register SCM *al, fl, var = CAR(vloc); register unsigned int idist, iframe = 0; #ifdef MACRO SCM mark = IDENT_MARK(var); #endif + DEFER_INTS_EGC; + env = scm_env; for(; NIMP(env); env = CDR(env)) { idist = 0; al = &CAR(env); @@ -123,6 +365,14 @@ SCM *lookupcar(vloc, genv) #endif if NCONSP(fl) if (fl==var) { +#ifndef RECKLESS + if ((check & LOOKUP_UNDEFP) + && UNBNDP(CDR(*al))) { env = EOL; goto errout; } +# ifdef MACRO + if ((check & LOOKUP_MACROP) + && (NIMP(CDR(*al)) && MACROP(CDR(*al)))) goto badkey; +# endif +#endif #ifndef TEST_FARLOC if (iframe < 4096 && idist < (1L<<(LONG_BIT-20))) CAR(vloc) = MAKILOC(iframe, idist) + ICDR; @@ -135,7 +385,12 @@ SCM *lookupcar(vloc, genv) al = &CDR(*al); if (CAR(fl)==var) { #ifndef RECKLESS /* letrec inits to UNDEFINED */ - if UNBNDP(CAR(*al)) {env = EOL; goto errout;} + if ((check & LOOKUP_UNDEFP) + && UNBNDP(CAR(*al))) {env = EOL; goto errout;} +# ifdef MACRO + if ((check & LOOKUP_MACROP) + && NIMP(CAR(*al)) && MACROP(CAR(*al))) goto badkey; +# endif #endif #ifndef TEST_FARLOC if (iframe < 4096 && idist < (1L<<(LONG_BIT-20))) @@ -157,24 +412,33 @@ SCM *lookupcar(vloc, genv) #endif var = sym2vcell(var); #ifndef RECKLESS - if (NNULLP(env) || UNBNDP(CDR(var))) { + if (NNULLP(env) || ((check & LOOKUP_UNDEFP) && UNBNDP(CDR(var)))) { var = CAR(var); errout: - everr(vloc, genv, var, + everr(vloc, wrapenv() /*scm_env*/, var, # ifdef MACRO M_IDENTP(var) ? s_escaped : # endif - (NULLP(env) ? "unbound variable: " : "damaged environment"), ""); + (NULLP(env) ? s_unbnd : "damaged environment"), ""); + } +# ifdef MACRO + if ((check & LOOKUP_MACROP) && NIMP(CDR(var)) && MACROP(CDR(var))) { + var = CAR(var); + badkey: everr(vloc, wrapenv()/*scm_env*/, var, s_badkey, ""); } +# endif #endif CAR(vloc) = var + 1; return &CDR(var); } -static SCM unmemocar(form, env) - SCM form, env; +static SCM unmemocar(form) + SCM form; { + SCM env; register int ir; + DEFER_INTS_EGC; + env = scm_env; if IMP(form) return form; if (1==TYP3(form)) CAR(form) = I_SYM(CAR(form)); @@ -187,47 +451,44 @@ static SCM unmemocar(form, env) return form; } -#ifdef MACRO /* CAR(x) is known to be a cell but not a cons */ -static char s_badkey[] = "Use of keyword as variable"; -static SCM evalatomcar(x, env) - SCM x, env; +static SCM evalatomcar(x) + SCM x; { SCM r; switch TYP7(CAR(x)) { default: - everr(x, env, CAR(x), "Cannot evaluate: ", ""); + everr(x, wrapenv() /*scm_env*/, CAR(x), "Cannot evaluate: ", ""); case tcs_symbols: lookup: - r = *lookupcar(x, env); -# ifndef RECKLESS - if (NIMP(r) && MACROP(r)) { - x = cons(CAR(x), CDR(x)); - unmemocar(x, env); - everr(x, env, CAR(x), s_badkey, ""); - } -# endif - return r; + return *lookupcar(x, LOOKUP_UNDEFP|LOOKUP_MACROP); case tc7_vector: +#ifndef RECKLESS + if (2 <= verbose) warn("unquoted ", s_vector); +#endif + r = cons2(IM_QUOTE, CAR(x), EOL); + CAR(x) = r; + return CAR(CDR(r)); + case tc7_smob: +#ifdef MACRO + if M_IDENTP(CAR(x)) goto lookup; +#endif + /* fall through */ case tc7_string: case tc7_bvect: case tc7_ivect: case tc7_uvect: case tc7_fvect: case tc7_dvect: case tc7_cvect: return CAR(x); - case tc7_smob: - if M_IDENTP(CAR(x)) goto lookup; - return CAR(x); } } -#endif /* def MACRO */ -SCM eval_args(l, env) - SCM l, env; +SCM eval_args(l) + SCM l; { SCM res = EOL, *lloc = &res; while NIMP(l) { - *lloc = cons(EVALCAR(l, env), EOL); - lloc = &CDR(*lloc); - l = CDR(l); + *lloc = cons(EVALCAR(l), EOL); + lloc = &CDR(*lloc); + l = CDR(l); } return res; } @@ -240,21 +501,21 @@ static char s_test[] = "bad test"; static char s_body[] = "bad body"; static char s_bindings[] = "bad bindings"; static char s_variable[] = "bad variable"; +static char s_bad_else_clause[] = "bad ELSE clause"; static char s_clauses[] = "bad or missing clauses"; static char s_formals[] = "bad formals"; #define ASSYNT(_cond, _arg, _pos, _subr) if(!(_cond))wta(_arg, (char *)_pos, _subr); -SCM i_dot, i_quote, i_quasiquote, i_lambda, - i_let, i_arrow, i_else, i_unquote, i_uq_splicing, i_apply; +SCM i_dot, i_quote, i_quasiquote, i_lambda, i_define, + i_let, i_arrow, i_else, i_unquote, i_uq_splicing; #define ASRTSYNTAX(cond_, msg_) if(!(cond_))wta(xorig, (msg_), what); #ifdef MACRO -SCM rename_ident P((SCM id, SCM env)); -# define TOPDENOTE_EQ(sym, x, env) ((sym)==ident2sym(x) && TOPLEVELP(x,env)) -# define TOPLEVELP(x,env) (0==id_denote(x,env)) +# define TOPDENOTE_EQ(sym, x, env) ((sym)==id2sym(x) && TOPLEVELP(x,env)) +# define TOPLEVELP(x,env) (0==id_denote(x)) # define TOPRENAME(v) (renamed_ident(v, BOOL_F)) -static SCM ident2sym(id) +static SCM id2sym(id) SCM id; { if NIMP(id) @@ -263,11 +524,13 @@ static SCM ident2sym(id) return id; } -static SCM *id_denote(var, env) - SCM var, env; +static SCM *id_denote(var) + SCM var; { register SCM *al, fl; - SCM mark = IDENT_MARK(var); + SCM env, mark = IDENT_MARK(var); + DEFER_INTS_EGC; + env = scm_env; for(;NIMP(env); env = CDR(env)) { al = &CAR(env); for(fl = CAR(*al);NIMP(fl);fl = CDR(fl)) { @@ -294,6 +557,12 @@ static void unpaint(p) if NIMP(CAR(x)) unpaint(&CAR(x)); p = &CDR(*p); } + else if VECTORP(x) { + sizet i = LENGTH(x); + if (0==i) return; + while (i-- > 1) unpaint(&(VELTS(x)[i])); + p = VELTS(x); + } else { while M_IDENTP(x) *p = x = IDENT_PARENT(x); return; @@ -313,16 +582,33 @@ static void bodycheck(xorig, bodyloc, what) ASRTSYNTAX(ilength(*bodyloc) >= 1, s_expression); } +static SCM m_body(op, xorig, what) + SCM op, xorig; + char *what; +{ + ASRTSYNTAX(ilength(xorig) >= 1, s_expression); + /* Don't add another ISYM if one is present already. */ + if ISYMP(CAR(xorig)) return xorig; + /* Retain possible doc string. */ + if (IMP(CAR(xorig)) || NCONSP(CAR(xorig))) { + if NNULLP(CDR(xorig)) + return cons(CAR(xorig), m_body(op, CDR(xorig), what)); + return xorig; + } + return cons2(op, CAR(xorig), CDR(xorig)); +} + SCM m_quote(xorig, env) SCM xorig, env; { + SCM x = copytree(CDR(xorig)); ASSYNT(ilength(CDR(xorig))==1, xorig, s_expression, s_quote); #ifdef MACRO DEFER_INTS; - unpaint(&CAR(CDR(xorig))); + unpaint(&CAR(x)); ALLOW_INTS; #endif - return cons(IM_QUOTE, CDR(xorig)); + return cons(IM_QUOTE, x); } SCM m_begin(xorig, env) @@ -368,32 +654,47 @@ SCM m_or(xorig, env) else return BOOL_F; } +#ifdef INUMS_ONLY +# define memv memq +#endif SCM m_case(xorig, env) SCM xorig, env; { - SCM proc, x = CDR(xorig); + SCM clause, cdrx = copy_list(CDR(xorig)), x = cdrx; +#ifndef RECKLESS + SCM s, keys = EOL; +#endif ASSYNT(ilength(x) >= 2, xorig, s_clauses, s_case); while(NIMP(x = CDR(x))) { - proc = CAR(x); - ASSYNT(ilength(proc) >= 2, xorig, s_clauses, s_case); - if TOPDENOTE_EQ(i_else, CAR(proc), env) - CAR(proc) = IM_ELSE; + clause = CAR(x); + ASSYNT(ilength(clause) >= 2, xorig, s_clauses, s_case); + if TOPDENOTE_EQ(i_else, CAR(clause), env) { + ASSYNT(NULLP(CDR(x)), xorig, s_bad_else_clause, s_case); + CAR(x) = cons(IM_ELSE, CDR(clause)); + } else { - ASSYNT(ilength(CAR(proc)) >= 0, xorig, s_clauses, s_case); + ASSYNT(ilength(CAR(clause)) >= 0, xorig, s_clauses, s_case); #ifdef MACRO + clause = cons(copy_list(CAR(clause)), CDR(clause)); DEFER_INTS; - unpaint(&CAR(proc)); + unpaint(&CAR(clause)); ALLOW_INTS; + CAR(x) = clause; #endif +#ifndef RECKLESS + for (s = CAR(clause); NIMP(s); s = CDR(s)) + ASSYNT(FALSEP(memv(CAR(s),keys)), xorig, "duplicate key value", s_case); + keys = append(cons2(CAR(clause), keys, EOL)); +#endif } } - return cons(IM_CASE, CDR(xorig)); + return cons(IM_CASE, cdrx); } SCM m_cond(xorig, env) SCM xorig, env; { - SCM arg1, x = CDR(xorig); + SCM arg1, cdrx = copy_list(CDR(xorig)), x = cdrx; int len = ilength(x); ASSYNT(len >= 1, xorig, s_clauses, s_cond); while(NIMP(x)) { @@ -401,26 +702,30 @@ SCM m_cond(xorig, env) len = ilength(arg1); ASSYNT(len >= 1, xorig, s_clauses, s_cond); if TOPDENOTE_EQ(i_else, CAR(arg1), env) { - ASSYNT(NULLP(CDR(x)) && len >= 2, xorig, "bad ELSE clause", s_cond); - CAR(arg1) = BOOL_T; + ASSYNT(NULLP(CDR(x)) && len >= 2, xorig, s_bad_else_clause, s_cond); + CAR(x) = cons(BOOL_T, CDR(arg1)); } - arg1 = CDR(arg1); - if (len >= 2 && TOPDENOTE_EQ(i_arrow, CAR(arg1), env)) { - ASSYNT(3==len && NIMP(CAR(CDR(arg1))), xorig, "bad recipient", s_cond); - CAR(arg1) = IM_ARROW; + else { + arg1 = CDR(arg1); + if (len >= 2 && TOPDENOTE_EQ(i_arrow, CAR(arg1), env)) { + ASSYNT(3==len && NIMP(CAR(CDR(arg1))), xorig, "bad recipient", s_cond); + CAR(x) = cons2(CAR(CAR(x)), IM_ARROW, CDR(arg1)); + } } x = CDR(x); } - return cons(IM_COND, CDR(xorig)); + return cons(IM_COND, cdrx); } SCM m_lambda(xorig, env) SCM xorig, env; { SCM proc, x = CDR(xorig); + int argc = 0; /* Number of required args */ if (ilength(x) < 2) goto badforms; proc = CAR(x); if NULLP(proc) goto memlambda; + if (IM_LET==proc) goto memlambda; /* named let */ if IMP(proc) goto badforms; if IDENTP(proc) goto memlambda; if NCONSP(proc) goto badforms; @@ -430,12 +735,13 @@ SCM m_lambda(xorig, env) else goto memlambda; if (!(NIMP(CAR(proc)) && IDENTP(CAR(proc)))) goto badforms; proc = CDR(proc); + argc++; } - if NNULLP(proc) + if (NNULLP(proc) && (IM_LET != proc)) /* IM_LET inserted by named let. */ badforms: wta(xorig, s_formals, s_lambda); memlambda: - bodycheck(xorig, &CDR(x), s_lambda); - return cons(IM_LAMBDA, CDR(xorig)); + return cons2(ISYMSETVAL(IM_LAMBDA, argc), CAR(x), + m_body(IM_LAMBDA, CDR(x), s_lambda)); } SCM m_letstar(xorig, env) SCM xorig, env; @@ -454,8 +760,7 @@ SCM m_letstar(xorig, env) proc = CDR(proc); } x = cons(vars, CDR(x)); - bodycheck(xorig, &CDR(x), s_letstar); - return cons(IM_LETSTAR, x); + return cons2(IM_LETSTAR, CAR(x), m_body(IM_LETSTAR, CDR(x), s_letstar)); } /* DO gets the most radically altered syntax @@ -475,7 +780,7 @@ SCM m_do(xorig, env) SCM xorig, env; { SCM x = CDR(xorig), arg1, proc; - SCM vars = EOL, inits = EOL, steps = EOL; + SCM vars = IM_DO, inits = EOL, steps = EOL; SCM *initloc = &inits, *steploc = &steps; int len = ilength(x); ASSYNT(len >= 2, xorig, s_test, s_do); @@ -505,16 +810,16 @@ SCM m_do(xorig, env) } /* evalcar is small version of inline EVALCAR when we don't care about speed */ -static SCM evalcar(x, env) - SCM x, env; +static SCM evalcar(x) + SCM x; { - return EVALCAR(x, env); + return EVALCAR(x); } /* Here are acros which return values rather than code. */ -static SCM iqq(form, env) - SCM form, env; +static SCM iqq(form) + SCM form; { SCM tmp; if IMP(form) return form; @@ -523,15 +828,15 @@ static SCM iqq(form, env) SCM *data = VELTS(form); tmp = EOL; for(;--i >= 0;) tmp = cons(data[i], tmp); - return vector(iqq(tmp, env)); + return vector(iqq(tmp)); } if NCONSP(form) return form; tmp = CAR(form); if (IM_UNQUOTE==tmp) - return evalcar(CDR(form), env); + return evalcar(CDR(form)); if (NIMP(tmp) && IM_UQ_SPLICING==CAR(tmp)) - return append(cons2(evalcar(CDR(tmp),env), iqq(CDR(form),env), EOL)); - return cons(iqq(CAR(form),env), iqq(CDR(form),env)); + return append(cons2(evalcar(CDR(tmp)), iqq(CDR(form)), EOL)); + return cons(iqq(CAR(form)), iqq(CDR(form))); } static SCM m_iqq(form, depth, env) @@ -545,9 +850,7 @@ static SCM m_iqq(form, depth, env) long i = LENGTH(form); SCM *data = VELTS(form); tmp = EOL; - ALLOW_INTS; for(;--i >= 0;) tmp = cons(data[i], tmp); - DEFER_INTS; tmp = m_iqq(tmp, depth, env); for(i = 0; i < LENGTH(form); i++) { data[i] = CAR(tmp); @@ -603,9 +906,7 @@ SCM m_quasiquote(xorig, env) { SCM x = CDR(xorig); ASSYNT(ilength(x)==1, xorig, s_expression, s_quasiquote); - DEFER_INTS; - x = m_iqq(x, 1, env); - ALLOW_INTS; + x = m_iqq(copytree(x), 1, env); return cons(IM_QUASIQUOTE, x); } @@ -616,7 +917,6 @@ SCM m_delay(xorig, env) return cons2(IM_DELAY, EOL, CDR(xorig)); } -extern int verbose; SCM m_define(x, env) SCM x, env; { @@ -630,8 +930,12 @@ SCM m_define(x, env) } ASSYNT(NIMP(proc) && IDENTP(proc), arg1, s_variable, s_define); ASSYNT(1==ilength(x), arg1, s_expression, s_define); + if (NIMP(env) && tc16_env==CAR(env)) { + DEFER_INTS_EGC; + env = CDR(env); + } if NULLP(env) { - x = evalcar(x,env); + x = evalcar(x); #ifdef MACRO while M_IDENTP(proc) { ASSYNT(IMP(IDENT_MARK(proc)), proc, s_escaped, s_define); @@ -640,7 +944,8 @@ SCM m_define(x, env) #endif arg1 = sym2vcell(proc); #ifndef RECKLESS - if (NIMP(CDR(arg1)) && + if (2 <= verbose && + NIMP(CDR(arg1)) && (proc == ((SCM) SNAME(MACROP(CDR(arg1)) ? CDR(CDR(arg1)) : CDR(arg1)))) && (CDR(arg1) != x)) @@ -656,21 +961,25 @@ SCM m_define(x, env) return UNSPECIFIED; #endif } - return cons2(IM_DEFINE, cons(proc,CAR(CAR(env))), x); + return cons2(IM_DEFINE, proc, x); + /* return cons2(IM_DEFINE, cons(proc,CAR(CAR(env))), x); */ } /* end of acros */ -SCM m_letrec(xorig, env) - SCM xorig, env; +static SCM m_letrec1(op, imm, xorig, env) + SCM op, imm, xorig, env; { SCM cdrx = CDR(xorig); /* locally mutable version of form */ char *what = CHARS(CAR(xorig)); SCM x = cdrx, proc, arg1; /* structure traversers */ - SCM vars = EOL, inits = EOL, *initloc = &inits; + SCM vars = imm, inits = EOL, *initloc = &inits; - ASRTSYNTAX(ilength(x) >= 2, s_body); + /* ASRTSYNTAX(ilength(x) >= 2, s_body); */ proc = CAR(x); - if NULLP(proc) return m_letstar(xorig, env); /* null binding, let* faster */ +#if 0 + if NULLP(proc) /* null binding, let* faster */ + return m_letstar(cons2(CAR(xorig), EOL, m_body(imm, CDR(x), what)), env); +#endif ASRTSYNTAX(ilength(proc) >= 1, s_bindings); do { /* vars list reversed here, inits reversed at evaluation */ @@ -681,9 +990,19 @@ SCM m_letrec(xorig, env) *initloc = cons(CAR(CDR(arg1)), EOL); initloc = &CDR(*initloc); } while NIMP(proc = CDR(proc)); - cdrx = cons2(vars, inits, CDR(x)); - bodycheck(xorig, &CDR(CDR(cdrx)), what); - return cons(IM_LETREC, cdrx); + return cons2(op, vars, cons(inits, m_body(imm, CDR(x), what))); +} + +SCM m_letrec(xorig, env) + SCM xorig, env; +{ + SCM x = CDR(xorig); + ASSYNT(ilength(x) >= 2, xorig, s_body, s_letrec); + if NULLP(CAR(x)) /* null binding, let* faster */ + return m_letstar(cons2(CAR(xorig), EOL, + m_body(IM_LETREC, CDR(x), s_letrec)), + env); + return m_letrec1(IM_LETREC, IM_LETREC, xorig, env); } SCM m_let(xorig, env) @@ -691,17 +1010,18 @@ SCM m_let(xorig, env) { SCM cdrx = CDR(xorig); /* locally mutable version of form */ SCM x = cdrx, proc, arg1, name; /* structure traversers */ - SCM vars = EOL, inits = EOL, *varloc = &vars, *initloc = &inits; + SCM vars = IM_LET, inits = EOL, *varloc = &vars, *initloc = &inits; ASSYNT(ilength(x) >= 2, xorig, s_body, s_let); proc = CAR(x); - if (NULLP(proc) + if (NULLP(proc) /* null or single binding, let* is faster */ || (NIMP(proc) && CONSP(proc) && NIMP(CAR(proc)) && CONSP(CAR(proc)) && NULLP(CDR(proc)))) - return m_letstar(xorig, env); /* null or single binding, let* is faster */ + return m_letstar(cons2(CAR(xorig), proc, m_body(IM_LET, CDR(x), s_let)), + env); ASSYNT(NIMP(proc), xorig, s_bindings, s_let); if CONSP(proc) /* plain let, proc is <bindings> */ - return cons(IM_LET, CDR(m_letrec(xorig, env))); + return m_letrec1(IM_LET, IM_LET, xorig, env); if (!IDENTP(proc)) wta(xorig, s_bindings, s_let); /* bad let */ name = proc; /* named let, build equiv letrec */ x = CDR(x); @@ -712,19 +1032,16 @@ SCM m_let(xorig, env) arg1 = CAR(proc); ASSYNT(2==ilength(arg1), xorig, s_bindings, s_let); ASSYNT(NIMP(CAR(arg1)) && IDENTP(CAR(arg1)), xorig, s_variable, s_let); - *varloc = cons(CAR(arg1), EOL); + *varloc = cons(CAR(arg1), IM_LET); varloc = &CDR(*varloc); *initloc = cons(CAR(CDR(arg1)), EOL); initloc = &CDR(*initloc); proc = CDR(proc); } - return - m_letrec(cons2(i_let, - cons(cons2(name, - cons2(TOPRENAME(i_lambda), vars, CDR(x)), EOL), - EOL), - acons(name, inits, EOL)), /* body */ - env); + proc = cons2(TOPRENAME(i_lambda), vars, m_body(IM_LET, CDR(x), s_let)); + proc = cons2(i_let, cons(cons2(name, proc, EOL), EOL), + acons(name, inits, EOL)); + return m_letrec1(IM_LETREC, IM_LET, proc, env); } #define s_atapply (ISYMCHARS(IM_APPLY)+1) @@ -736,19 +1053,154 @@ SCM m_apply(xorig, env) return cons(IM_APPLY, CDR(xorig)); } -#define s_atcall_cc (ISYMCHARS(IM_CONT)+1) +SCM m_expand_body(xorig) + SCM xorig; +{ + SCM form, x = CDR(xorig), defs = EOL; + char *what = ISYMCHARS(CAR(xorig)) + 2; + while NIMP(x) { + form = CAR(x); + if (IMP(form) || NCONSP(form)) break; + if IMP(CAR(form)) break; + if (! IDENTP(CAR(form))) break; + form = macroexp1(cons(CAR(form), CDR(form)), 0); + if (IM_DEFINE==CAR(form)) { + defs = cons(CDR(form), defs); + x = CDR(x); + } + else if NIMP(defs) { + break; + } + else if (IM_BEGIN==CAR(form)) { + x = append(cons2(CDR(form), CDR(x), EOL)); + } + else { + x = cons(form, CDR(x)); + break; + } + } + ASSYNT(NIMP(x), CDR(xorig), s_body, what); + if NIMP(defs) + x = cons(m_letrec1(IM_LETREC, IM_DEFINE, cons2(i_define, defs, x), + wrapenv()) + , EOL); + DEFER_INTS; + CAR(xorig) = CAR(x); + CDR(xorig) = CDR(x); + ALLOW_INTS; + return xorig; +} -SCM m_cont(xorig, env) - SCM xorig, env; +static SCM macroexp1(x, check) + SCM x; + int check; { - ASSYNT(ilength(CDR(xorig))==1, xorig, s_expression, s_atcall_cc); - return cons(IM_CONT, CDR(xorig)); + SCM res, proc; + int argc; + ASRTGO(IDENTP(CAR(x)), badfun); + macro_tail: + proc = *lookupcar(x, 0); + if (NIMP(proc) && MACROP(proc)) { + unmemocar(x); + res = apply(CDR(proc), cons2(x, wrapenv(), EOL), EOL); + switch ((int)(CAR(proc)>>16) & 0x7f) { + case 2: /* mmacro */ + if (ilength(res) <= 0) + res = cons2(IM_BEGIN, res, EOL); + DEFER_INTS; + CAR(x) = CAR(res); + CDR(x) = CDR(res); + ALLOW_INTS; + break; + case 1: /* macro */ + x = NIMP(res) ? res : cons2(IM_BEGIN, res, EOL); + break; + case 0: /* acro */ + return cons2(IM_QUOTE, res, EOL); + } + if (NIMP(CAR(x)) && IDENTP(CAR(x))) goto macro_tail; +#ifndef RECKLESS + if (check && IM_DEFINE==CAR(x)) + everr(x, wrapenv() /*scm_env*/, i_define, "Bad placement", ""); +#endif + return x; + } + else if (!check) { + unmemocar(x); + return x; + } +#ifdef RECKLESS + return x; +#else + ASRTGO(NIMP(proc), badfun); + argc = ilength(CDR(x)); +# ifdef CCLO + cclo_tail: +# endif + switch TYP7(proc) { + default: + badfun: + unmemocar(x); + everr(x, wrapenv(), UNBNDP(proc) ? CAR(x) : proc, + UNBNDP(proc) ? s_unbnd : s_wtap, ""); + case tc7_lsubr: + case tc7_rpsubr: + case tc7_asubr: + return x; + case tc7_subr_0: + ASRTGO(0==argc, wrongnumargs); + return x; + case tc7_contin: + case tc7_subr_1: + case tc7_cxr: + ASRTGO(1==argc, wrongnumargs); + return x; + case tc7_subr_2: + ASRTGO(2==argc, wrongnumargs); + return x; + case tc7_subr_3: + ASRTGO(3==argc, wrongnumargs); + return x; + case tc7_subr_1o: + ASRTGO(0==argc || 1==argc, wrongnumargs); + return x; + case tc7_subr_2o: + ASRTGO(1==argc || 2==argc, wrongnumargs); + return x; + case tc7_lsubr_2: + ASRTGO(2<=argc, wrongnumargs); + return x; + case tc7_specfun: + switch TYP16(proc) { + case tc16_apply: + ASRTGO(2<=argc, wrongnumargs); + return x; + case tc16_call_cc: + ASRTGO(1==argc, wrongnumargs); + return x; +# ifdef CCLO + case tc16_cclo: + proc = CCLO_SUBR(proc); + argc++; + goto cclo_tail; +# endif + } + case tcs_closures: + if (badargsp(proc, CDR(x))) { + wrongnumargs: + unmemocar(x); + everr(x, wrapenv()/*scm_env*/, proc, (char *)WNA, ""); + } + return x; + } +#endif /* ndef RECKLESS */ } #ifndef RECKLESS -int badargsp(formals, args) - SCM formals, args; +int badargsp(proc, args) + SCM proc, args; { + SCM formals = CAR(CODE(proc)); while NIMP(formals) { if NCONSP(formals) return 0; if IMP(args) return 1; @@ -760,59 +1212,93 @@ int badargsp(formals, args) #endif char s_map[] = "map", s_for_each[] = "for-each", s_eval[] = "eval"; -SCM eqv P((SCM x, SCM y)); -#ifdef CAUTIOUS -static char s_bottom[] = "stacktrace bottommed out"; -#endif +char s_call_cc[] = "call-with-current-continuation"; /* s_apply[] = "apply"; */ + +static SCM wrapenv() +{ + register SCM z; + NEWCELL(z); + DEFER_INTS_EGC; + CDR(z) = scm_env; + CAR(z) = tc16_env; + EGC_ROOT(z); + return z; +} SCM ceval(x, env) SCM x, env; { + DEFER_INTS_EGC; + ENV_PUSH; + scm_env = env; + TRACE(x); + x = ceval_1(x); + ENV_POP; + ALLOW_INTS_EGC; + return x; +} + +static SCM ceval_1(x) + SCM x; +{ union {SCM *lloc; SCM arg1;} t; - SCM proc, arg2; + SCM proc, arg2, arg3; + int envpp = 0; /* 1 means an environment has been pushed in this + invocation of ceval_1, -1 means pushed and then popped. */ CHECK_STACK; loop: POLL; + TRACE(x); +#ifdef SCM_PROFILE + eval_cases[TYP7(x)]++; +#endif switch TYP7(x) { case tcs_symbols: /* only happens when called at top level */ - x = cons(x, UNDEFINED); - goto retval; + x = *lookupcar(cons(x, UNDEFINED), LOOKUP_UNDEFP); + goto retx; case (127 & IM_AND): x = CDR(x); t.arg1 = x; while(NNULLP(t.arg1 = CDR(t.arg1))) - if FALSEP(EVALCAR(x, env)) return BOOL_F; + if (FALSEP(EVALCAR(x))) {x = BOOL_F; goto retx;} else x = t.arg1; goto carloop; - cdrtcdrxbegin: -#ifdef CAUTIOUS - ASSERT(NIMP(stacktrace), EOL, s_bottom, s_eval); - stacktrace = CDR(stacktrace); -#endif cdrxbegin: case (127 & IM_BEGIN): x = CDR(x); begin: t.arg1 = x; while(NNULLP(t.arg1 = CDR(t.arg1))) { - SIDEVAL(CAR(x), env); + if IMP(CAR(x)) { + if ISYMP(CAR(x)) { + x = m_expand_body(x); + goto begin; + } + } + else + ceval_1(CAR(x)); x = t.arg1; } carloop: /* eval car of last form in list */ if NCELLP(CAR(x)) { x = CAR(x); - return IMP(x)?EVALIMP(x, env):I_VAL(x); + x = IMP(x) ? EVALIMP(x) : I_VAL(x); + goto retx; } - if IDENTP(CAR(x)) { - retval: - return *lookupcar(x, env); + + if ATOMP(CAR(x)) { + x = evalatomcar(x); + retx: + ENV_MAY_POP(envpp, 0); + ALLOW_INTS_EGC; + return x; } x = CAR(x); goto loop; /* tail recurse */ case (127 & IM_CASE): x = CDR(x); - t.arg1 = EVALCAR(x, env); + t.arg1 = EVALCAR(x); #ifndef INUMS_ONLY arg2 = (SCM)(IMP(t.arg1) || !NUMP(t.arg1)); #endif @@ -835,331 +1321,312 @@ SCM ceval(x, env) proc = CDR(proc); } } + retunspec: + ENV_MAY_POP(envpp, 0); + ALLOW_INTS_EGC; return UNSPECIFIED; case (127 & IM_COND): while(NIMP(x = CDR(x))) { proc = CAR(x); - t.arg1 = EVALCAR(proc, env); + t.arg1 = EVALCAR(proc); if NFALSEP(t.arg1) { x = CDR(proc); - if NULLP(x) return t.arg1; + if NULLP(x) { + x = t.arg1; + goto retx; + } if (IM_ARROW != CAR(x)) goto begin; proc = CDR(x); - proc = EVALCAR(proc, env); + proc = EVALCAR(proc); ASRTGO(NIMP(proc), badfun); -#ifdef CAUTIOUS - if CLOSUREP(proc) goto checkargs1; -#endif goto evap1; } } - return UNSPECIFIED; + goto retunspec; case (127 & IM_DO): + ENV_MAY_PUSH(envpp); x = CDR(x); proc = CAR(CDR(x)); /* inits */ - t.arg1 = EOL; /* values */ + scm_env_tmp = EOL; /* values */ while NIMP(proc) { - t.arg1 = cons(EVALCAR(proc, env), t.arg1); + scm_env_cons_tmp(EVALCAR(proc)); proc = CDR(proc); } - env = EXTEND_ENV(CAR(x), t.arg1, env); + EXTEND_ENV(CAR(x)); x = CDR(CDR(x)); - while (proc = CAR(x), FALSEP(EVALCAR(proc, env))) { + while (proc = CAR(x), FALSEP(EVALCAR(proc))) { for(proc = CAR(CDR(x));NIMP(proc);proc = CDR(proc)) { t.arg1 = CAR(proc); /* body */ - SIDEVAL(t.arg1, env); + SIDEVAL_1(t.arg1); } - for(t.arg1 = EOL, proc = CDR(CDR(x)); NIMP(proc); proc = CDR(proc)) - t.arg1 = cons(EVALCAR(proc, env), t.arg1); /* steps */ - env = EXTEND_ENV(CAR(CAR(env)), t.arg1, CDR(env)); + scm_env_tmp = EOL; + for(proc = CDR(CDR(x)); NIMP(proc); proc = CDR(proc)) { + scm_env_cons_tmp(EVALCAR(proc)); /* steps */ + } + DEFER_INTS_EGC; + t.arg1 = CAR(CAR(scm_env)); + scm_env = CDR(scm_env); + EXTEND_ENV(t.arg1); } x = CDR(proc); - if NULLP(x) return UNSPECIFIED; + if NULLP(x) goto retunspec; goto begin; case (127 & IM_IF): x = CDR(x); - if NFALSEP(EVALCAR(x, env)) x = CDR(x); - else if IMP(x = CDR(CDR(x))) return UNSPECIFIED; + if NFALSEP(EVALCAR(x)) x = CDR(x); + else if IMP(x = CDR(CDR(x))) goto retunspec; goto carloop; case (127 & IM_LET): + ENV_MAY_PUSH(envpp); x = CDR(x); proc = CAR(CDR(x)); - t.arg1 = EOL; + scm_env_tmp = EOL; do { - t.arg1 = cons(EVALCAR(proc, env), t.arg1); + scm_env_cons_tmp(EVALCAR(proc)); } while NIMP(proc = CDR(proc)); - env = EXTEND_ENV(CAR(x), t.arg1, env); + EXTEND_ENV(CAR(x)); x = CDR(x); goto cdrxbegin; case (127 & IM_LETREC): + ENV_MAY_PUSH(envpp); x = CDR(x); - env = EXTEND_ENV(CAR(x), undefineds, env); + scm_env_tmp = undefineds; + EXTEND_ENV(CAR(x)); x = CDR(x); proc = CAR(x); - t.arg1 = EOL; + scm_env_tmp = EOL; do { - t.arg1 = cons(EVALCAR(proc, env), t.arg1); + scm_env_cons_tmp(EVALCAR(proc)); } while NIMP(proc = CDR(proc)); - CDR(CAR(env)) = t.arg1; + EGC_ROOT(CAR(scm_env)); + CDR(CAR(scm_env)) = scm_env_tmp; + scm_env_tmp = EOL; goto cdrxbegin; case (127 & IM_LETSTAR): + ENV_MAY_PUSH(envpp); x = CDR(x); proc = CAR(x); if IMP(proc) { - env = EXTEND_ENV(EOL, EOL, env); + scm_env_tmp = EOL; + EXTEND_ENV(EOL); goto cdrxbegin; } do { t.arg1 = CAR(proc); proc = CDR(proc); - env = EXTEND_ENV(t.arg1, EVALCAR(proc, env), env); + scm_env_tmp = EVALCAR(proc); + EXTEND_ENV(t.arg1); } while NIMP(proc = CDR(proc)); goto cdrxbegin; case (127 & IM_OR): x = CDR(x); t.arg1 = x; while(NNULLP(t.arg1 = CDR(t.arg1))) { - x = EVALCAR(x, env); - if NFALSEP(x) return x; + x = EVALCAR(x); + if NFALSEP(x) goto retx; x = t.arg1; } goto carloop; case (127 & IM_LAMBDA): - return closure(CDR(x), env); + x = closure(CDR(x), ISYMVAL(CAR(x))); + goto retx; case (127 & IM_QUOTE): - return CAR(CDR(x)); + x = CAR(CDR(x)); + goto retx; case (127 & IM_SET): x = CDR(x); + arg2 = EVALCAR(CDR(x)); proc = CAR(x); switch (7 & (int)proc) { case 0: if CONSP(proc) - t.lloc = farlookup(proc,env); - else { - t.lloc = lookupcar(x,env); -#ifdef MACRO -# ifndef RECKLESS - if (NIMP(*t.lloc) && MACROP(*t.lloc)) { - unmemocar(x,env); - everr(x, env, CAR(x), s_badkey, s_set); - } -# endif -#endif - } + *farlookup(proc) = arg2; + else + *lookupcar(x, LOOKUP_UNDEFP|LOOKUP_MACROP) = arg2; break; case 1: - t.lloc = &I_VAL(proc); + I_VAL(proc) = arg2; break; case 4: - t.lloc = ilookup(proc, env); + *ilookup(proc) = arg2; break; } - x = CDR(x); - *t.lloc = EVALCAR(x, env); #ifdef SICP - return *t.lloc; -#else - return UNSPECIFIED; + x = arg2; + goto retx; #endif + goto retunspec; case (127 & IM_DEFINE): /* only for internal defines */ + goto badfun; +#if 0 x = CDR(x); proc = CAR(x); x = CDR(x); - x = evalcar(x, env); - env = CAR(env); - DEFER_INTS; - CAR(env) = proc; - CDR(env) = cons(x, CDR(env)); - ALLOW_INTS; - return UNSPECIFIED; + x = evalcar(x); + DEFER_INTS_EGC; + scm_env_tmp = CDR(CAR(scm_env)); + scm_env_cons_tmp(x); + EGC_ROOT(CAR(scm_env)); + /* DEFER_INTS; */ + CAR(CAR(scm_env)) = proc; + CDR(CAR(scm_env)) = scm_env_tmp; + /* ALLOW_INTS; */ + goto retunspec; +#endif /* new syntactic forms go here. */ case (127 & MAKISYM(0)): proc = CAR(x); ASRTGO(ISYMP(proc), badfun); +#ifdef SCM_PROFILE + eval_cases_other[ISYMNUM(proc)]++; +#endif switch ISYMNUM(proc) { case (ISYMNUM(IM_APPLY)): proc = CDR(x); - proc = EVALCAR(proc, env); + proc = EVALCAR(proc); ASRTGO(NIMP(proc), badfun); + t.arg1 = CDR(CDR(x)); + t.arg1 = EVALCAR(t.arg1); if (CLOSUREP(proc)) { - t.arg1 = CDR(CDR(x)); - t.arg1 = EVALCAR(t.arg1, env); + ENV_MAY_PUSH(envpp); + scm_env_tmp = t.arg1; #ifndef RECKLESS - if (badargsp(CAR(CODE(proc)), t.arg1)) goto wrongnumargs; -#endif - env = EXTEND_ENV(CAR(CODE(proc)), t.arg1, ENV(proc)); - x = CODE(proc); - goto cdrxbegin; - } - proc = i_apply; - goto evapply; - case (ISYMNUM(IM_CONT)): - t.arg1 = scm_make_cont(); - if ((proc = setjump(CONT(t.arg1)->jmpbuf))) -#ifdef SHORT_INT - return (SCM)thrown_value; + goto clo_checked; #else - return (SCM)proc; + goto clo_unchecked; #endif - proc = CDR(x); - proc = evalcar(proc, env); - ASRTGO(NIMP(proc), badfun); -#ifdef CAUTIOUS - if CLOSUREP(proc) { - checkargs1: - stacktrace = cons(x, stacktrace); - /* Check that argument list of proc can match 1 arg. */ - arg2 = CAR(CODE(proc)); - ASRTGO(NIMP(arg2), wrongnumargs); - if NCONSP(arg2) goto evap1; - arg2 = CDR(arg2); - ASRTGO(NULLP(arg2) || NCONSP(arg2), wrongnumargs); } -#endif - goto evap1; + x = apply(proc, t.arg1, EOL); + goto retx; case (ISYMNUM(IM_DELAY)): - return makprom(closure(CDR(x), env)); + x = makprom(closure(CDR(x), 0)); + goto retx; case (ISYMNUM(IM_QUASIQUOTE)): - return iqq(CAR(CDR(x)), env); + ALLOW_INTS_EGC; + x = iqq(CAR(CDR(x))); + goto retx; case (ISYMNUM(IM_FARLOC_CAR)): case (ISYMNUM(IM_FARLOC_CDR)): - return *farlookup(x, env); + x = *farlookup(x); + goto retx; default: goto badfun; } default: proc = x; badfun: - everr(x, env, proc, "Wrong type to apply: ", ""); + everr(x, wrapenv() /*scm_env*/, proc, s_wtap, ""); case tc7_vector: case tc7_bvect: case tc7_ivect: case tc7_uvect: case tc7_fvect: case tc7_dvect: case tc7_cvect: case tc7_string: case tc7_smob: -#ifdef MACRO - if M_IDENTP(x) { - x = cons(x, UNDEFINED); - goto retval; - } -#endif - return x; + goto retx; case (127 & ILOC00): - proc = *ilookup(CAR(x), env); - ASRTGO(NIMP(proc), badfun); -#ifndef RECKLESS -# ifdef CAUTIOUS - goto checkargs; -# endif -#endif + proc = *ilookup(CAR(x)); break; case tcs_cons_gloc: proc = I_VAL(CAR(x)); - ASRTGO(NIMP(proc), badfun); -#ifndef RECKLESS -# ifdef CAUTIOUS - goto checkargs; -# endif -#endif break; case tcs_cons_nimcar: - if IDENTP(CAR(x)) { - proc = *lookupcar(x, env); - if IMP(proc) {unmemocar(x, env); goto badfun;} - if MACROP(proc) { - unmemocar(x, env); - t.arg1 = apply(CDR(proc), x, cons(env, listofnull)); - switch ((int)(CAR(proc)>>16)) { - case 2: /* mmacro */ - if (ilength(t.arg1) <= 0) - t.arg1 = cons2(IM_BEGIN, t.arg1, EOL); - DEFER_INTS; - CAR(x) = CAR(t.arg1); - CDR(x) = CDR(t.arg1); - ALLOW_INTS; - goto loop; - case 1: /* macro */ - if NIMP(x = t.arg1) goto loop; - case 0: /* acro */ - return t.arg1; - } - } + if ATOMP(CAR(x)) { + x = macroexp1(x, !0); + goto loop; } - else proc = ceval(CAR(x), env); - ASRTGO(NIMP(proc), badfun); -#ifndef RECKLESS -# ifdef CAUTIOUS - checkargs: -# endif + proc = ceval_1(CAR(x)); /* At this point proc is the evaluated procedure from the function position and x has the form which is being evaluated. */ - if CLOSUREP(proc) { -# ifdef CAUTIOUS - stacktrace = cons(x, stacktrace); -# endif - arg2 = CAR(CODE(proc)); - t.arg1 = CDR(x); - while NIMP(arg2) { - if NCONSP(arg2) { - goto evapply; + } + ASRTGO(NIMP(proc), badfun); + *scm_estk_ptr = scm_env; /* For error reporting at wrongnumargs. */ + if NULLP(CDR(x)) { + evap0: + ENV_MAY_POP(envpp, CLOSUREP(proc)); + ALLOW_INTS_EGC; + switch TYP7(proc) { /* no arguments given */ + case tc7_subr_0: + return SUBRF(proc)(); + case tc7_subr_1o: + return SUBRF(proc) (UNDEFINED); + case tc7_lsubr: + return SUBRF(proc)(EOL); + case tc7_rpsubr: + return BOOL_T; + case tc7_asubr: + return SUBRF(proc)(UNDEFINED, UNDEFINED); + case tcs_closures: + DEFER_INTS_EGC; + ENV_MAY_PUSH(envpp); + scm_env_tmp = EOL; +#ifdef SCM_PROFILE + eval_clo_cases[0][0]++; +#endif +#ifdef CAUTIOUS + if (0!=ARGC(proc)) { + clo_checked: + DEFER_INTS_EGC; + t.arg1 = CAR(CODE(proc)); + arg2 = scm_env_tmp; + while NIMP(t.arg1) { + if NCONSP(t.arg1) goto clo_unchecked; + if IMP(arg2) goto umwrongnumargs; + t.arg1 = CDR(t.arg1); + arg2 = CDR(arg2); } - if IMP(t.arg1) goto umwrongnumargs; - arg2 = CDR(arg2); - t.arg1 = CDR(t.arg1); + if NNULLP(arg2) goto umwrongnumargs; } - if NNULLP(t.arg1) goto umwrongnumargs; - } +#else /* def CAUTIOUS */ + clo_checked: #endif - } - evapply: - if NULLP(CDR(x)) switch TYP7(proc) { /* no arguments given */ - case tc7_subr_0: - return SUBRF(proc)(); - case tc7_subr_1o: - return SUBRF(proc) (UNDEFINED); - case tc7_lsubr: - return SUBRF(proc)(EOL); - case tc7_rpsubr: - return BOOL_T; - case tc7_asubr: - return SUBRF(proc)(UNDEFINED, UNDEFINED); + clo_unchecked: + x = CODE(proc); + scm_env = ENV(proc); + EXTEND_ENV(CAR(x)); + goto cdrxbegin; + case tc7_specfun: #ifdef CCLO - case tc7_cclo: - t.arg1 = proc; - proc = CCLO_SUBR(proc); - goto evap1; + if (tc16_cclo==TYP16(proc)) { + t.arg1 = proc; + proc = CCLO_SUBR(proc); + goto evap1; + } #endif - case tcs_closures: - x = CODE(proc); - env = EXTEND_ENV(CAR(x), EOL, ENV(proc)); - goto cdrtcdrxbegin; - case tc7_contin: - case tc7_subr_1: - case tc7_subr_2: - case tc7_subr_2o: - case tc7_cxr: - case tc7_subr_3: - case tc7_lsubr_2: - umwrongnumargs: - unmemocar(x, env); - wrongnumargs: - everr(x, env, proc, (char *)WNA, ""); - default: - goto badfun; + case tc7_contin: + case tc7_subr_1: + case tc7_subr_2: + case tc7_subr_2o: + case tc7_cxr: + case tc7_subr_3: + case tc7_lsubr_2: + umwrongnumargs: + unmemocar(x); + wrongnumargs: + if (envpp < 0) { + scm_estk_ptr += SCM_ESTK_FRLEN; + scm_env = *scm_estk_ptr; + } + everr(x, wrapenv()/*scm_env*/, proc, (char *)WNA, ""); + default: + goto badfun; + } } x = CDR(x); #ifdef CAUTIOUS if (IMP(x)) goto wrongnumargs; #endif - t.arg1 = EVALCAR(x, env); + t.arg1 = EVALCAR(x); x = CDR(x); - if NULLP(x) -evap1: switch TYP7(proc) { /* have one argument in t.arg1 */ - case tc7_subr_2o: - return SUBRF(proc)(t.arg1, UNDEFINED); - case tc7_subr_1: - case tc7_subr_1o: - return SUBRF(proc)(t.arg1); - case tc7_cxr: + if NULLP(x) { +evap1: + ENV_MAY_POP(envpp, CLOSUREP(proc)); + ALLOW_INTS_EGC; + switch TYP7(proc) { /* have one argument in t.arg1 */ + case tc7_subr_2o: + return SUBRF(proc)(t.arg1, UNDEFINED); + case tc7_subr_1: + case tc7_subr_1o: + return SUBRF(proc)(t.arg1); + case tc7_cxr: #ifdef FLOATS if SUBRF(proc) { if INUMP(t.arg1) @@ -1191,109 +1658,214 @@ evap1: switch TYP7(proc) { /* have one argument in t.arg1 */ return SUBRF(proc)(t.arg1, UNDEFINED); case tc7_lsubr: return SUBRF(proc)(cons(t.arg1, EOL)); -#ifdef CCLO - case tc7_cclo: - arg2 = t.arg1; - t.arg1 = proc; - proc = CCLO_SUBR(proc); - goto evap2; + case tcs_closures: + ENV_MAY_PUSH(envpp); +#ifdef SCM_PROFILE + eval_clo_cases[1][ARGC(proc)]++; #endif - case tcs_closures: - x = CODE(proc); - env = EXTEND_ENV(CAR(x), cons(t.arg1, EOL), ENV(proc)); - goto cdrtcdrxbegin; - case tc7_contin: - scm_dynthrow(CONT(proc), t.arg1); - case tc7_subr_2: - case tc7_subr_0: - case tc7_subr_3: - case tc7_lsubr_2: - goto wrongnumargs; - default: - goto badfun; - } -#ifdef CAUTIOUS - if (IMP(x)) goto wrongnumargs; + if (1==ARGC(proc)) { + scm_env_cons(t.arg1, EOL); + goto clo_unchecked; + } + else { + scm_env_tmp = cons(t.arg1, EOL); + goto clo_checked; + } + case tc7_contin: + scm_dynthrow(CONT(proc), t.arg1); + case tc7_specfun: + switch TYP16(proc) { + case tc16_call_cc: + proc = t.arg1; + DEFER_INTS_EGC; + t.arg1 = scm_make_cont(); + EGC_ROOT(t.arg1); + if ((x = setjump(CONT(t.arg1)->jmpbuf))) { +#ifdef SHORT_INT + x = (SCM)thrown_value; #endif - { /* have two or more arguments */ - arg2 = EVALCAR(x, env); - x = CDR(x); - if NULLP(x) + goto retx; + } + ASRTGO(NIMP(proc), badfun); + goto evap1; #ifdef CCLO - evap2: + case tc16_cclo: + arg2 = t.arg1; + t.arg1 = proc; + proc = CCLO_SUBR(proc); + goto evap2; #endif - switch TYP7(proc) { /* have two arguments */ + } case tc7_subr_2: - case tc7_subr_2o: - return SUBRF(proc)(t.arg1, arg2); - case tc7_lsubr: - return SUBRF(proc)(cons2(t.arg1, arg2, EOL)); - case tc7_lsubr_2: - return SUBRF(proc)(t.arg1, arg2, EOL); - case tc7_rpsubr: - case tc7_asubr: - return SUBRF(proc)(t.arg1, arg2); -#ifdef CCLO - cclon: case tc7_cclo: - return apply(CCLO_SUBR(proc), proc, - cons2(t.arg1, arg2, cons(eval_args(x, env), EOL))); -/* case tc7_cclo: - x = cons(arg2, eval_args(x, env)); - arg2 = t.arg1; - t.arg1 = proc; - proc = CCLO_SUBR(proc); - goto evap3; */ -#endif case tc7_subr_0: - case tc7_cxr: - case tc7_subr_1o: - case tc7_subr_1: case tc7_subr_3: - case tc7_contin: + case tc7_lsubr_2: goto wrongnumargs; default: goto badfun; - case tcs_closures: - env = EXTEND_ENV(CAR(CODE(proc)), cons2(t.arg1, arg2, EOL), ENV(proc)); - x = CODE(proc); - goto cdrtcdrxbegin; } - switch TYP7(proc) { /* have 3 or more arguments */ - case tc7_subr_3: - ASRTGO(NULLP(CDR(x)), wrongnumargs); - return SUBRF(proc)(t.arg1, arg2, EVALCAR(x, env)); - case tc7_asubr: -/* t.arg1 = SUBRF(proc)(t.arg1, arg2); - while NIMP(x) { - t.arg1 = SUBRF(proc)(t.arg1, EVALCAR(x, env)); - x = CDR(x); + } +#ifdef CAUTIOUS + if (IMP(x)) goto wrongnumargs; +#endif + { /* have two or more arguments */ + arg2 = EVALCAR(x); + x = CDR(x); + if NULLP(x) { /* have two arguments */ + evap2: + ENV_MAY_POP(envpp, CLOSUREP(proc)); + ALLOW_INTS_EGC; + switch TYP7(proc) { + case tc7_subr_2: + case tc7_subr_2o: + return SUBRF(proc)(t.arg1, arg2); + case tc7_lsubr: + return SUBRF(proc)(cons2(t.arg1, arg2, EOL)); + case tc7_lsubr_2: + return SUBRF(proc)(t.arg1, arg2, EOL); + case tc7_rpsubr: + case tc7_asubr: + return SUBRF(proc)(t.arg1, arg2); + case tc7_specfun: + switch TYP16(proc) { + case tc16_apply: + proc = t.arg1; + if NULLP(arg2) goto evap0; + if (IMP(arg2) || NCONSP(arg2)) { + x = arg2; + badlst: wta(x, (char *)ARGn, s_apply); + } + t.arg1 = CAR(arg2); + x = CDR(arg2); + apply3: + if NULLP(x) goto evap1; + ASRTGO(NIMP(x) && CONSP(x), badlst); + arg2 = CAR(x); + x = CDR(x); + apply4: + if NULLP(x) goto evap2; + ASRTGO(NIMP(x) && CONSP(x), badlst); + arg3 = CAR(x); + ASRTGO(0 <= ilength(x), badlst); + x = copy_list(CDR(x)); + goto evap3; +#ifdef CCLO + case tc16_cclo: cclon: + return apply(CCLO_SUBR(proc), + cons2(proc, t.arg1, cons(arg2, x)), EOL); + /* arg3 = arg2; + arg2 = t.arg1; + t.arg1 = proc; + proc = CCLO_SUBR(proc); + goto evap3; */ +#endif + } + case tc7_subr_0: + case tc7_cxr: + case tc7_subr_1o: + case tc7_subr_1: + case tc7_subr_3: + case tc7_contin: + goto wrongnumargs; + default: + goto badfun; + case tcs_closures: + ENV_MAY_PUSH(envpp); +#ifdef SCM_PROFILE + eval_clo_cases[2][ARGC(proc)]++; +#endif + switch ARGC(proc) { + case 2: + scm_env_cons2(t.arg1, arg2, EOL); + goto clo_unchecked; + case 1: + scm_env_cons(t.arg1, cons(arg2, EOL)); + goto clo_checked; + case 0: + case 3: /* Error, will be caught at clo_checked: */ + scm_env_tmp = cons2(t.arg1, arg2, EOL); + goto clo_checked; + } } - return t.arg1; */ - case tc7_rpsubr: - return apply(proc, t.arg1, acons(arg2, eval_args(x, env), EOL)); - case tc7_lsubr_2: - return SUBRF(proc)(t.arg1, arg2, eval_args(x, env)); - case tc7_lsubr: - return SUBRF(proc)(cons2(t.arg1, arg2, eval_args(x, env))); + } + { /* have 3 or more arguments */ + arg3 = EVALCAR(x); + x = CDR(x); + if NIMP(x) x = eval_args(x); + evap3: + ENV_MAY_POP(envpp, CLOSUREP(proc)); + ALLOW_INTS_EGC; + switch TYP7(proc) { + case tc7_subr_3: + ASRTGO(NULLP(x), wrongnumargs); + return SUBRF(proc)(t.arg1, arg2, arg3); + case tc7_asubr: + /* t.arg1 = SUBRF(proc)(t.arg1, arg2); + while NIMP(x) { + t.arg1 = SUBRF(proc)(t.arg1, EVALCAR(x, env)); + x = CDR(x); + } + return t.arg1; */ + case tc7_rpsubr: + return apply(proc, cons2(t.arg1, arg2, cons(arg3, x)), EOL); + case tc7_lsubr_2: + return SUBRF(proc)(t.arg1, arg2, cons(arg3, x)); + case tc7_lsubr: + return SUBRF(proc)(cons2(t.arg1, arg2, cons(arg3, x))); + case tcs_closures: + ENV_MAY_PUSH(envpp); +#ifdef SCM_PROFILE + eval_clo_cases[IMP(x)?3:4][ARGC(proc)]++; +#endif + switch ARGC(proc) { + case 3: + scm_env_cons2(arg2, arg3, x); + scm_env_cons_tmp(t.arg1); + goto clo_checked; + case 2: + scm_env_cons2(t.arg1, arg2, cons(arg3, x)); + goto clo_checked; + case 1: + scm_env_cons(t.arg1, cons2(arg2, arg3, x)); + goto clo_checked; + case 0: + scm_env_tmp = cons2(t.arg1, arg2, cons(arg3, x)); + goto clo_checked; + } + case tc7_specfun: + switch TYP16(proc) { + case tc16_apply: + proc = t.arg1; + t.arg1 = arg2; + if IMP(x) { + x = arg3; + goto apply3; + } + arg2 = arg3; + if IMP(CDR(x)) { + x = CAR(x); + goto apply4; + } + arg3 = CAR(x); + x = nconc2copy(CDR(x)); + goto evap3; #ifdef CCLO - case tc7_cclo: goto cclon; + case tc16_cclo: + x = cons(arg3, x); + goto cclon; #endif - case tcs_closures: - env = EXTEND_ENV(CAR(CODE(proc)), - cons2(t.arg1, arg2, eval_args(x, env)), - ENV(proc)); - x = CODE(proc); - goto cdrtcdrxbegin; - case tc7_subr_2: - case tc7_subr_1o: - case tc7_subr_2o: - case tc7_subr_0: - case tc7_cxr: - case tc7_subr_1: - case tc7_contin: - goto wrongnumargs; - default: - goto badfun; + } + case tc7_subr_2: + case tc7_subr_1o: + case tc7_subr_2o: + case tc7_subr_0: + case tc7_cxr: + case tc7_subr_1: + case tc7_contin: + goto wrongnumargs; + default: + goto badfun; + } } } } @@ -1305,9 +1877,7 @@ SCM procedurep(obj) case tcs_closures: case tc7_contin: case tcs_subrs: -#ifdef CCLO - case tc7_cclo: -#endif + case tc7_specfun: return BOOL_T; } return BOOL_F; @@ -1331,19 +1901,18 @@ SCM l_proc_doc(proc) return BOOL_F; /* case tcs_subrs: -#ifdef CCLO - case tc7_cclo: -#endif + case tc7_specfun: */ } } /* This code is for apply. it is destructive on multiple args. This will only screw you if you do (apply apply '( ... )) */ -SCM nconc2last(lst) +/* Copy last (list) argument, so SET! in a closure can't mutate it. */ +SCM nconc2copy(lst) SCM lst; { - SCM *lloc = &lst; + SCM last, *lloc = &lst; #ifdef CAUTIOUS ASSERT(ilength(lst) >= 1, lst, WNA, s_apply); #endif @@ -1351,14 +1920,30 @@ SCM nconc2last(lst) #ifdef CAUTIOUS ASSERT(ilength(CAR(*lloc)) >= 0, lst, ARGn, s_apply); #endif - *lloc = CAR(*lloc); + last = CAR(*lloc); + *lloc = EOL; + for(; NIMP(last); last=CDR(last)) { + *lloc = cons(CAR(last), EOL); + lloc = &CDR(*lloc); + } return lst; } - - +/* Shallow copy */ +SCM copy_list(lst) + SCM lst; +{ + SCM res, *lloc = &res; + res = EOL; + for(; NIMP(lst); lst = CDR(lst)) { + *lloc = cons(CAR(lst), EOL); + lloc = &CDR(*lloc); + } + return res; +} SCM apply(proc, arg1, args) SCM proc, arg1, args; { + apply_tail: ASRTGO(NIMP(proc), badproc); if NULLP(args) if NULLP(arg1) arg1 = UNDEFINED; @@ -1368,15 +1953,17 @@ SCM apply(proc, arg1, args) } else { /* ASRTGO(NIMP(args) && CONSP(args), wrongnumargs); */ - args = nconc2last(args); + args = nconc2copy(args); } -#ifdef CCLO - tail: -#endif + cc_tail: + ALLOW_INTS_EGC; switch TYP7(proc) { case tc7_subr_2o: - args = NULLP(args)?UNDEFINED:CAR(args); - return SUBRF(proc)(arg1, args); + if NULLP(args) { + args = UNDEFINED; + return SUBRF(proc)(arg1, args); + } + /* Fall through */ case tc7_subr_2: ASRTGO(NIMP(args) && NULLP(CDR(args)), wrongnumargs); args = CAR(args); @@ -1416,6 +2003,8 @@ SCM apply(proc, arg1, args) return arg1; } case tc7_subr_3: + ASRTGO(NIMP(args) && NIMP(CDR(args)) && NULLP(CDR(CDR(args))), + wrongnumargs); return SUBRF(proc)(arg1, CAR(args), CAR(CDR(args))); case tc7_lsubr: return SUBRF(proc)(UNBNDP(arg1) ? EOL : cons(arg1, args)); @@ -1442,22 +2031,54 @@ SCM apply(proc, arg1, args) case tcs_closures: arg1 = (UNBNDP(arg1) ? EOL : cons(arg1, args)); #ifndef RECKLESS - if (badargsp(CAR(CODE(proc)), arg1)) goto wrongnumargs; + if (badargsp(proc, arg1)) goto wrongnumargs; #endif - args = EXTEND_ENV(CAR(CODE(proc)), arg1, ENV(proc)); + DEFER_INTS_EGC; + ENV_PUSH; + TRACE(proc); + scm_env_tmp = arg1; + scm_env = ENV(proc); + EXTEND_ENV(CAR(CODE(proc))); proc = CODE(proc); - while NNULLP(proc = CDR(proc)) arg1 = EVALCAR(proc, args); + arg1 = ceval_1(cons(IM_BEGIN, CDR(proc))); + /* while NNULLP(proc = CDR(proc)) arg1 = EVALCAR(proc); */ + ENV_POP; return arg1; case tc7_contin: ASRTGO(NULLP(args), wrongnumargs); scm_dynthrow(CONT(proc), arg1); + case tc7_specfun: + switch TYP16(proc) { + case tc16_apply: + ASRTGO(!UNBNDP(arg1), wrongnumargs); + proc = arg1; + arg1 = args; + args = EOL; + goto apply_tail; + case tc16_call_cc: + ASRTGO(NULLP(args), wrongnumargs); + proc = arg1; + ASRTGO(NIMP(proc), badproc); + DEFER_INTS_EGC; + arg1 = scm_make_cont(); + EGC_ROOT(arg1); + if ((args = setjump(CONT(arg1)->jmpbuf))) { +#ifdef SHORT_INT + args = (SCM)thrown_value; +#endif + return args; + } + args = EOL; + goto cc_tail; #ifdef CCLO - case tc7_cclo: - args = (UNBNDP(arg1) ? EOL : cons(arg1, args)); - arg1 = proc; - proc = CCLO_SUBR(proc); - goto tail; + case tc16_cclo: + args = (UNBNDP(arg1) ? EOL : cons(arg1, args)); + arg1 = proc; + proc = CCLO_SUBR(proc); + goto cc_tail; #endif + } + goto badproc; wrongnumargs: wta(proc, (char *)WNA, s_apply); default: @@ -1472,7 +2093,8 @@ SCM map(proc, arg1, args) { long i; SCM res = EOL, *pres = &res; - SCM *ve = &args; /* Keep args from being optimized away. */ + SCM *ve; + scm_protect_temp(&args); /* Keep args from being optimized away. */ if NULLP(arg1) return res; ASSERT(NIMP(arg1), arg1, ARG2, s_map); if NULLP(args) { @@ -1504,8 +2126,9 @@ SCM map(proc, arg1, args) SCM for_each(proc, arg1, args) SCM proc, arg1, args; { - SCM *ve = &args; /* Keep args from being optimized away. */ + SCM *ve; long i; + scm_protect_temp(&args); /* Keep args from being optimized away. */ if NULLP(arg1) return UNSPECIFIED; ASSERT(NIMP(arg1), arg1, ARG2, s_for_each); if NULLP(args) { @@ -1529,13 +2152,24 @@ SCM for_each(proc, arg1, args) } } -SCM closure(code, env) - SCM code, env; +/* The number of required arguments up to 3 is encoded in the cdr of the + closure. This information is used to make sure that rest args are not + allocated in the environment cache. */ +SCM closure(code, argc) + SCM code; + int argc; { register SCM z; + if (argc > 3) argc = 3; NEWCELL(z); SETCODE(z, code); - ENV(z) = env; + DEFER_INTS_EGC; + if (IMP(scm_env)) + CDR(z) = argc<<1; + else { + CDR(z) = scm_env | (argc<<1); + EGC_ROOT(z); + } return z; } @@ -1600,6 +2234,17 @@ static int prinmacro(exp, port, writing) lputc('>', port); return !0; } +static int prinenv(exp, port, writing) + SCM exp; + SCM port; + int writing; +{ + lputs("#<environment ", port); + intprint((long)exp, -16, port); + /* iprin1(CDR(exp), port, writing); */ + lputc('>', port); + return !0; +} #ifdef MACRO static int prinid(exp, port, writing) SCM exp; @@ -1611,7 +2256,7 @@ static int prinid(exp, port, writing) lputs("#<identifier ", port); iprin1(s, port, writing); lputc(':', port); - intprint((long)exp, 16, port); + intprint((long)exp, -16, port); lputc('>', port); return !0; } @@ -1664,7 +2309,7 @@ SCM definedp(x, env) { SCM proc = CAR(x = CDR(x)); #ifdef MACRO - proc = ident2sym(proc); + proc = id2sym(proc); #endif return (ISYMP(proc) || (NIMP(proc) && IDENTP(proc) @@ -1684,7 +2329,8 @@ static char s_ident_eqp[] = "identifier-equal?"; SCM ident_eqp(id1, id2, env) SCM id1, id2, env; { - SCM s1 = id1, s2 = id2; + SCM s1 = id1, s2 = id2, ret; + # ifndef RECKLESS if IMP(id1) badarg1: wta(id1, (char *)ARG1, s_ident_eqp); @@ -1697,8 +2343,21 @@ SCM ident_eqp(id1, id2, env) ASRTGO(SYMBOLP(s1), badarg1); ASRTGO(SYMBOLP(s2), badarg2); if (s1 != s2) return BOOL_F; - if (id_denote(id1, env)==id_denote(id2, env)) return BOOL_T; - return BOOL_F; + DEFER_INTS_EGC; + ENV_PUSH; + scm_env = (NIMP(env) && tc16_env==CAR(env)) ? CDR(env) : env; + ret = (id_denote(id1)==id_denote(id2)) ? BOOL_T : BOOL_F; + ENV_POP; + return ret; +} + +static char s_ident2sym[] = "identifier->symbol"; +SCM ident2sym(id) + SCM id; +{ + id = id2sym(id); + ASSERT(NIMP(id) && SYMBOLP(id), id, ARG1, s_ident2sym); + return id; } static char s_renamed_ident[] = "renamed-identifier"; @@ -1707,6 +2366,11 @@ SCM renamed_ident(id, env) { SCM z; ASSERT(NIMP(id) && IDENTP(id), id, ARG1, s_renamed_ident); + if NIMP(env) { + ASSERT(tc16_env==CAR(env), env, ARG2, s_renamed_ident); + DEFER_INTS_EGC; + env = CDR(env); + } NEWCELL(z); if IMP(env) { CAR(z) = tc16_ident; @@ -1736,15 +2400,18 @@ SCM m_syn_quote(xorig, env) SCM m_atlet_syntax(xorig, env) SCM xorig, env; { - if (IMP(env) || CONSP(CAR(CAR(env)))) - return m_let(xorig, env); - else { - SCM mark = renamed_ident(i_mark, BOOL_F); - return m_letstar(cons2(i_let, - cons(cons2(mark, BOOL_F, EOL), EOL), - acons(TOPRENAME(i_let), CDR(xorig), EOL)), - env); - } + SCM mark; + DEFER_INTS_EGC; + if (tc16_env==CAR(env)) + env = CDR(env); + if NULLP(env) return m_let(xorig, env); + mark = CAR(CAR(env)); + if (NIMP(mark) && CONSP(mark)) return m_let(xorig, env); + mark = renamed_ident(i_mark, BOOL_F); + return m_letstar(cons2(i_let, + cons(cons2(mark, BOOL_F, EOL), EOL), + acons(TOPRENAME(i_let), CDR(xorig), EOL)), + env); } static char s_the_macro[] = "the-macro"; @@ -1754,14 +2421,46 @@ SCM m_the_macro(xorig, env) SCM x = CDR(xorig); ASSYNT(1==ilength(x), xorig, s_expression, s_the_macro); if (NIMP(CAR(x)) && IDENTP(CAR(x))) - x = *lookupcar(x, env); + x = *lookupcar(x, LOOKUP_UNDEFP); else - x = evalcar(x, env); + x = evalcar(x); ASSYNT(NIMP(x) && MACROP(x), xorig, ARG1, s_the_macro); return cons2(IM_QUOTE, x, EOL); } #endif +static char s_env2tree[] = "environment->tree"; +SCM env2tree(env) + SCM env; +{ + SCM ans, a, *lloc; + if NULLP(env) return env; + ASSERT(NIMP(env) && tc16_env==CAR(env), env, ARG1, s_env2tree); + DEFER_INTS_EGC; + if IMP(CDR(env)) return env; + ENV_PUSH; + scm_env = CDR(env); + ans = a = cons(UNSPECIFIED, UNSPECIFIED); + while (!0) { + scm_env_tmp = CAR(scm_env); + lloc = &CAR(a); + while (NIMP(scm_env_tmp) && CONSP(scm_env_tmp)) { + *lloc = cons(CAR(scm_env_tmp), CDR(scm_env_tmp)); + lloc = &CDR(*lloc); + DEFER_INTS_EGC; + scm_env_tmp = CDR(scm_env_tmp); + } + scm_env = CDR(scm_env); + if IMP(scm_env) { + CDR(a) = scm_env; + break; + } + a = (CDR(a) = cons(UNSPECIFIED, UNSPECIFIED)); + } + ENV_POP; + ALLOW_INTS_EGC; + return ans; +} static iproc subr1s[] = { {"@copy-tree", copytree}, @@ -1771,9 +2470,11 @@ static iproc subr1s[] = { {"procedure->syntax", makacro}, {"procedure->macro", makmacro}, {"procedure->memoizing-macro", makmmacro}, - {"apply:nconc-to-last", nconc2last}, + {"apply:nconc-to-last", nconc2copy}, + {s_env2tree, env2tree}, #ifdef MACRO {s_identp, identp}, + {s_ident2sym, ident2sym}, #endif {0, 0}}; @@ -1785,6 +2486,7 @@ static iproc lsubr2s[] = { static smobfuns promsmob = {markcdr, free0, prinprom}; static smobfuns macrosmob = {markcdr, free0, prinmacro}; +static smobfuns envsmob = {markcdr, free0, prinenv}; #ifdef MACRO static smobfuns idsmob = {markcdr, free0, prinid}; #endif @@ -1805,14 +2507,31 @@ SCM make_synt(name, macroizer, fcn) CDR(symcell) = macroizer(z); return CAR(symcell); } - +SCM make_specfun(name, typ) + char *name; + int typ; +{ + SCM symcell = sysintern(name, UNDEFINED); + register SCM z; + NEWCELL(z); + CAR(z) = (long)typ; + CDR(z) = CAR(symcell); + CDR(symcell) = z; + return z; +} void init_eval() { tc16_promise = newsmob(&promsmob); tc16_macro = newsmob(¯osmob); + tc16_env = newsmob(&envsmob); init_iprocs(subr1s, tc7_subr_1); init_iprocs(lsubr2s, tc7_lsubr_2); - i_apply = make_subr(s_apply, tc7_lsubr_2, apply); +#ifdef SCM_PROFILE + make_subr("scm:profile", tc7_subr_1o, scm_profile); +#endif + make_specfun(s_apply, tc16_apply); + make_specfun(s_call_cc, tc16_call_cc); + i_dot = CAR(sysintern(".", UNDEFINED)); i_arrow = CAR(sysintern("=>", UNDEFINED)); i_else = CAR(sysintern("else", UNDEFINED)); @@ -1821,7 +2540,7 @@ void init_eval() /* acros */ i_quasiquote = make_synt(s_quasiquote, makmmacro, m_quasiquote); - make_synt(s_define, makmmacro, m_define); + i_define = make_synt(s_define, makmmacro, m_define); make_synt(s_delay, makmmacro, m_delay); make_synt("defined?", makacro, definedp); /* end of acros */ @@ -1840,7 +2559,7 @@ void init_eval() i_quote = make_synt(s_quote, makmmacro, m_quote); make_synt(s_set, makmmacro, m_set); make_synt(s_atapply, makmmacro, m_apply); - make_synt(s_atcall_cc, makmmacro, m_cont); + /* make_synt(s_atcall_cc, makmmacro, m_cont); */ #ifdef MACRO tc16_ident = newsmob(&idsmob); |