diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | eval.c | 29 | ||||
-rw-r--r-- | txr.1 | 4 |
3 files changed, 26 insertions, 23 deletions
@@ -1,5 +1,21 @@ 2014-02-03 Kaz Kylheku <kaz@kylheku.com> + Tighten up environment visibility semantics of default argument + init forms, while streamlining the implementation. + + * eval.c (bind_args): Get rid of opt_init_parm array hack; + turns out we already have a useful function for extending an + environment object, namely env_vbind: hitherto unused! We now make a + blank environment upfront and extend it destructively with env_vbind. + Except that after evaluating an init form, we create a new environment: + this is in case a lexical closure was made by the init form, in which + event we don't want to be destructively manipulating the environment + any more. + + * txr.1: Clarified. + +2014-02-03 Kaz Kylheku <kaz@kylheku.com> + * eval.c (eval_init): Fix incorrect registration of list_star_intrinsic, diagnosed by compiler. @@ -220,11 +220,8 @@ static val lookup_sym_lisp1(val env, val sym) static val bind_args(val env, val params, val args, val ctx_form) { - val opt_init_parm[32]; - val *oi_parm = &opt_init_parm[0], *oi_end = &opt_init_parm[32], *oi_iter; - val new_bindings = nil; + val new_env = make_env(nil, nil, env); val optargs = nil; - val new_env; for (; args && consp(params); args = cdr(args), params = cdr(params)) { val param = car(params); @@ -246,11 +243,11 @@ static val bind_args(val env, val params, val args, val ctx_form) eval_error(ctx_form, lit("~a: ~s is not a bindable symbol"), car(ctx_form), param, nao); - new_bindings = acons(param, car(args), new_bindings); + env_vbind(new_env, param, car(args)); } if (bindable(params)) { - new_bindings = acons(params, args, new_bindings); + env_vbind(new_env, params, args); } else if (consp(params)) { if (car(params) == colon_k) { if (optargs) @@ -265,19 +262,16 @@ static val bind_args(val env, val params, val args, val ctx_form) if (param == colon_k) goto twocol; if (consp(param)) { - if (oi_parm == oi_end) - eval_error(ctx_form, - lit("~s: too many optional args with initializers"), - car(ctx_form), nao); - new_bindings = acons(car(param), car(cdr(param)), new_bindings); - *oi_parm++ = car(new_bindings); + val initval = eval(car(cdr(param)), new_env, ctx_form); + new_env = make_env(nil, nil, new_env); + env_vbind(new_env, car(param), initval); } else { - new_bindings = acons(param, nil, new_bindings); + env_vbind(new_env, param, nil); } params = cdr(params); } if (bindable(params)) - new_bindings = acons(params, args, new_bindings); + env_vbind(new_env, params, nil); } else if (params) { eval_error(ctx_form, lit("~a: ~s is not a bindable sybol"), car(ctx_form), params, nao); @@ -285,13 +279,6 @@ static val bind_args(val env, val params, val args, val ctx_form) eval_error(ctx_form, lit("~s: too many arguments"), car(ctx_form), nao); } - new_env = make_env(new_bindings, nil, env); - - for (oi_iter = &opt_init_parm[0]; oi_iter < oi_parm; oi_iter++) { - val initval = eval(cdr(*oi_iter), new_env, ctx_form); - rplacd(*oi_iter, initval); - } - return new_env; twocol: eval_error(ctx_form, lit("~a: multiple colons in parameter list"), @@ -5977,8 +5977,8 @@ In this situation, if the call does not specify a value for the parameter, then the parameter takes on the value of the expression <expr>. The initializer expressions are evaluated an environment in which -all of the parameters are visible, which extends the environment in -which the lambda was constructed. For instance: +all of the previous parameters are visible, in addition to the surrounding +environment of the lambda. For instance: (let ((default 0)) (lambda (str : (end (length str)) (counter default)) |