summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-02-23 21:21:17 -0800
committerKaz Kylheku <kaz@kylheku.com>2014-02-23 21:21:17 -0800
commit5cb550642ab86688e903b2221e0ccfa27d87addb (patch)
treea9fbb7efa1aa71be7da4e6212c3069a8025e81cc
parentaf2e5abd71f5a2d85137cbc524b2b942baf44e82 (diff)
downloadtxr-5cb550642ab86688e903b2221e0ccfa27d87addb.tar.gz
txr-5cb550642ab86688e903b2221e0ccfa27d87addb.tar.bz2
txr-5cb550642ab86688e903b2221e0ccfa27d87addb.zip
* eval.c (env_fbind, env_vbind): Use acons_new_c, and provide
a much more useful return value: the binding cell itself, rather than the symbol. (bind_args): Bugfix: env_vbind was still being called in one case, leading to a neglect to bind a special variable properly. (bindings_helper): Changed interface. Bugfix: in sequential binding, actually bind the successive environments so closures will behave 100% correctly. Returns a list of the actual bindings, in which special variables are not distinguished in any way. (op_let, op_for): Conform to new bindings_helper interface. Use the lexical environment that it returns instead of making a new one. (op_each): Use the environment and list of bindings out of bindings_helper. The bindings are used for stepping the lists, and that includes stepping any special vars. The lexical environment is used for evaluating the body. Thus, we need no special processing for special vars here any more.
-rw-r--r--ChangeLog19
-rw-r--r--eval.c79
2 files changed, 53 insertions, 45 deletions
diff --git a/ChangeLog b/ChangeLog
index f2f39b64..7a517753 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2014-02-23 Kaz Kylheku <kaz@kylheku.com>
+ * eval.c (env_fbind, env_vbind): Use acons_new_c, and provide
+ a much more useful return value: the binding cell itself,
+ rather than the symbol.
+ (bind_args): Bugfix: env_vbind was still being called in one case,
+ leading to a neglect to bind a special variable properly.
+ (bindings_helper): Changed interface. Bugfix: in sequential binding,
+ actually bind the successive environments so closures will behave
+ 100% correctly. Returns a list of the actual bindings, in which
+ special variables are not distinguished in any way.
+ (op_let, op_for): Conform to new bindings_helper interface. Use the
+ lexical environment that it returns instead of making a new one.
+ (op_each): Use the environment and list of bindings out of
+ bindings_helper. The bindings are used for stepping the lists,
+ and that includes stepping any special vars. The lexical environment
+ is used for evaluating the body. Thus, we need no special processing
+ for special vars here any more.
+
+2014-02-23 Kaz Kylheku <kaz@kylheku.com>
+
* eval.c (bindings_helper): This must now bind dynamic values
rather than just assign to them. Got rid of the superfluous variable
saving array. Fixed the problem in recognizing the special_s symbol (it
diff --git a/eval.c b/eval.c
index 6e16fb1b..87b4f5a6 100644
--- a/eval.c
+++ b/eval.c
@@ -106,22 +106,20 @@ val make_env(val vbindings, val fbindings, val up_env)
val env_fbind(val env, val sym, val fun)
{
+ val cell;
type_check(env, ENV);
- set(env->e.fbindings, acons_new(sym, fun, env->e.fbindings));
- return sym;
+ cell = acons_new_c(sym, 0, &env->e.fbindings);
+ rplacd(cell, fun);
+ return cell;
}
val env_vbind(val env, val sym, val obj)
{
+ val cell;
type_check(env, ENV);
- set(env->e.vbindings, acons_new(sym, obj, env->e.vbindings));
- return sym;
-}
-
-static void env_replace_vbind(val env, val bindings)
-{
- type_check(env, ENV);
- set(env->e.vbindings, bindings);
+ cell = acons_new_c(sym, 0, &env->e.vbindings);
+ rplacd(cell, obj);
+ return cell;
}
noreturn static val eval_error(val form, val fmt, ...)
@@ -343,7 +341,7 @@ static val bind_args(val env, val params, val args, val ctx_form)
if (presentsym)
env_vbind_special(new_env, presentsym, present, special_list, ctx_form);
} else {
- env_vbind(new_env, param, car(args));
+ env_vbind_special(new_env, param, car(args), special_list, ctx_form);
}
args = cdr(args);
@@ -946,12 +944,12 @@ static val op_unquote_error(val form, val env)
static val bindings_helper(val vars, val env, val sequential,
- val include_specials, val ctx_form)
+ val *env_out, val ctx_form)
{
val iter;
+ val de = if3(sequential, dyn_env, make_env(nil, nil, dyn_env));
+ val ne = if3(sequential, env, make_env(nil, nil, env));
list_collect_decl (new_bindings, ptail);
- list_collect_decl (new_dyn_bindings, ptail_d);
- val nenv = if3(sequential, make_env(nil, nil, env), env);
for (iter = vars; iter; iter = cdr(iter)) {
val item = car(iter);
@@ -959,33 +957,30 @@ static val bindings_helper(val vars, val env, val sequential,
if (consp(item)) {
var = pop(&item);
- value = eval(pop(&item), nenv, ctx_form);
+ value = eval(pop(&item), if3(sequential, ne, env), ctx_form);
} else {
var = item;
}
if (var == special_s) {
val special = car(item);
- ptail_d = list_collect(ptail_d, cons(special, value));
-
- if (sequential)
- env_replace_vbind(dyn_env, new_dyn_bindings);
-
- if (include_specials)
- ptail = list_collect (ptail, cons(special_s, var));
+ val binding = env_vbind(de, special, value);
+ ptail = list_collect (ptail, binding);
} else if (bindable(var)) {
- ptail = list_collect (ptail, cons(var, value));
-
- if (sequential)
- env_replace_vbind(nenv, new_bindings);
+ val le = if3(sequential, make_env(nil, nil, ne), ne);
+ val binding = env_vbind(le, var, value);
+ ptail = list_collect (ptail, binding);
+ ne = le;
} else {
eval_error(ctx_form, lit("~s: ~s is not a bindable symbol"),
car(ctx_form), var, nao);
}
}
- if (new_dyn_bindings)
- env_replace_vbind(dyn_env, new_dyn_bindings);
+ if (de != dyn_env)
+ dyn_env = de;
+ if (env_out)
+ *env_out = ne;
return new_bindings;
}
@@ -1005,8 +1000,9 @@ static val op_let(val form, val env)
val args = rest(form);
val vars = first(args);
val body = rest(args);
- val new_bindings = bindings_helper(vars, env, eq(let, let_star_s), nil, form);
- return eval_progn(body, make_env(new_bindings, nil, env), form);
+ val new_env;
+ (void) bindings_helper(vars, env, eq(let, let_star_s), &new_env, form);
+ return eval_progn(body, new_env, form);
}
static val op_each(val form, val env)
@@ -1021,7 +1017,8 @@ static val op_each(val form, val env)
eq(each, append_each_star_s));
val collect = or2(eq(each, collect_each_s), eq(each, collect_each_star_s));
val append = or2(eq(each, append_each_s), eq(each, append_each_star_s));
- val new_bindings = bindings_helper(vars, env, star, t, form);
+ val new_env;
+ val new_bindings = bindings_helper(vars, env, star, &new_env, form);
val lists = mapcar(cdr_f, new_bindings);
list_collect_decl (collection, ptail);
@@ -1035,23 +1032,14 @@ static val op_each(val form, val env)
{
val binding = car(biter);
val list = car(liter);
- val sym = car(binding);
if (!list)
goto out;
- if (sym == special_s) {
- val *loc = lookup_var_l(nil, cdr(binding));
- if (!loc)
- eval_error(form, lit("~s: nonexistent special var ~a"),
- car(form), sym);
- *loc = car(list);
- } else {
- rplacd(binding, car(list));
- }
+ rplacd(binding, car(list));
rplaca(liter, cdr(list));
}
{
- val res = eval_progn(body, make_env(new_bindings, nil, env), form);
+ val res = eval_progn(body, new_env, form);
if (collect)
ptail = list_collect(ptail, res);
else if (append)
@@ -1589,12 +1577,13 @@ static val op_for(val form, val env)
val cond = third(form);
val incs = fourth(form);
val forms = rest(rest(rest(rest(form))));
+ val new_env;
val new_bindings = bindings_helper(vars, env, eq(forsym, for_star_s),
- nil, form);
- val new_env = make_env(new_bindings, nil, env);
-
+ &new_env, form);
uw_block_begin (nil, result);
+ (void) new_bindings;
+
for (; cond == nil || eval(car(cond), new_env, form);
eval_progn(incs, new_env, form))
eval_progn(forms, new_env, form);