summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-02-03 02:07:47 -0800
committerKaz Kylheku <kaz@kylheku.com>2014-02-03 02:07:47 -0800
commit6de0cf077207362f917d8e26df4c9670a0aeb52a (patch)
tree7eec2bb8113ee38adb958aa912d02e543b55dbc6
parent5282f0ca564531363e47cac16f27eb74d963b427 (diff)
downloadtxr-6de0cf077207362f917d8e26df4c9670a0aeb52a.tar.gz
txr-6de0cf077207362f917d8e26df4c9670a0aeb52a.tar.bz2
txr-6de0cf077207362f917d8e26df4c9670a0aeb52a.zip
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.
-rw-r--r--ChangeLog16
-rw-r--r--eval.c29
-rw-r--r--txr.14
3 files changed, 26 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index b5056ac5..912e2854 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/eval.c b/eval.c
index d1f27cfd..b4644bce 100644
--- a/eval.c
+++ b/eval.c
@@ -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"),
diff --git a/txr.1 b/txr.1
index d6fc7fdd..bb2325a5 100644
--- a/txr.1
+++ b/txr.1
@@ -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))