diff --git a/libguile/ChangeLog b/libguile/ChangeLog index 71bc04bf6..4dfb9932b 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,3 +1,12 @@ +1998-04-12 Mikael Djurfeldt + + * eval.c (SCM_CEVAL, SCM_APPLY): In SCM_IM_APPLY and in the + procedure apply: Copy argument lists before pushing them unto the + environment so that the environment won't get mutated due to + manipulation of procedure arguments. This should perhaps be + regarded as a temporary solution until someone finds a more + efficient one. (Thanks to Maciej Stachowiak.) + 1998-04-10 Mikael Djurfeldt * script.c (scm_compile_shell_switches): Use "guile" as default diff --git a/libguile/eval.c b/libguile/eval.c index f8dbff3ab..0bdc33c41 100644 --- a/libguile/eval.c +++ b/libguile/eval.c @@ -1922,6 +1922,7 @@ dispatch: SCM_ASRTGO (SCM_NIMP (proc), badfun); if (SCM_CLOSUREP (proc)) { + SCM argl, tl; PREP_APPLY (proc, SCM_EOL); t.arg1 = SCM_CDR (SCM_CDR (x)); t.arg1 = EVALCAR (t.arg1, env); @@ -1932,7 +1933,23 @@ dispatch: if (scm_badargsp (SCM_CAR (SCM_CODE (proc)), t.arg1)) goto wrongnumargs; #endif - env = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)), t.arg1, SCM_ENV (proc)); + /* Copy argument list */ + if (SCM_IMP (t.arg1)) + argl = t.arg1; + else + { + argl = tl = scm_cons (SCM_CAR (t.arg1), SCM_UNSPECIFIED); + while (SCM_NIMP (t.arg1 = SCM_CDR (t.arg1)) + && SCM_CONSP (t.arg1)) + { + SCM_SETCDR (tl, scm_cons (SCM_CAR (t.arg1), + SCM_UNSPECIFIED)); + tl = SCM_CDR (tl); + } + SCM_SETCDR (tl, t.arg1); + } + + env = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)), argl, SCM_ENV (proc)); x = SCM_CODE (proc); goto cdrxbegin; } @@ -2883,7 +2900,24 @@ tail: if (scm_badargsp (SCM_CAR (SCM_CODE (proc)), arg1)) goto wrongnumargs; #endif - args = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)), arg1, SCM_ENV (proc)); + + /* Copy argument list */ + if (SCM_IMP (arg1)) + args = arg1; + else + { + SCM tl = args = scm_cons (SCM_CAR (arg1), SCM_UNSPECIFIED); + while (SCM_NIMP (arg1 = SCM_CDR (arg1)) + && SCM_CONSP (arg1)) + { + SCM_SETCDR (tl, scm_cons (SCM_CAR (arg1), + SCM_UNSPECIFIED)); + tl = SCM_CDR (tl); + } + SCM_SETCDR (tl, arg1); + } + + args = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)), args, SCM_ENV (proc)); proc = SCM_CODE (proc); while (SCM_NNULLP (proc = SCM_CDR (proc))) arg1 = EVALCAR (proc, args);