summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-07-17 06:12:10 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-07-17 06:12:10 -0700
commite7c14e74668d15f0403c868847779d795d167c8a (patch)
tree998039c1f4e5be608390b2048a33deb13bcdebcc /eval.c
parentd879eb7226e928e41c45c1702ed3685e0b8e1757 (diff)
downloadtxr-e7c14e74668d15f0403c868847779d795d167c8a.tar.gz
txr-e7c14e74668d15f0403c868847779d795d167c8a.tar.bz2
txr-e7c14e74668d15f0403c868847779d795d167c8a.zip
eval: handle top-level incrementally.
Like in some other Lisp dialects, evaluation of top-level forms should deal with forms like: (progn (defmacro a () 42) (a)) where the (a) will correctly reference the macro earlier in the progn. * eval.c (eval_only_s, compile_only_s): New symbol variables. (expand_eval): New static function, based on previous code of eval_intrinsic. (eval_intrinsic): Rewritten to perform incremental macroexpand, similarly to compile-file, and recurse. If a form, after macro-expansion, is a progn, eval-only or compile-only, then its constituents are individually evaluated through expand_eval as separate forms: each one is fully expanded and evaluated before the next one is processed. If the form isn't a progn, eval-only or compile-only, then it is treated as a single expansion and evaluation. (eval_init): Initialize new symbol variables and use their values in registering their respective operators.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/eval.c b/eval.c
index 7199272b..50c6fbc7 100644
--- a/eval.c
+++ b/eval.c
@@ -102,6 +102,7 @@ val defsymacro_s, symacrolet_s, prof_s, switch_s;
val fbind_s, lbind_s, flet_s, labels_s;
val load_path_s, load_recursive_s;
val load_time_s, load_time_lit_s;
+val eval_only_s, compile_only_s;
val special_s, unbound_s;
val whole_k, form_k, symacro_k;
@@ -1378,7 +1379,7 @@ val funcall_interp(val interp_fun, struct args *args)
return ret;
}
-val eval_intrinsic(val form, val env)
+static val expand_eval(val form, val env)
{
val lfe_save = last_form_evaled;
val lfx_save = last_form_expanded;
@@ -1392,6 +1393,30 @@ val eval_intrinsic(val form, val env)
return ret;
}
+static val macroexpand(val form, val menv);
+
+val eval_intrinsic(val form, val env)
+{
+ val form_ex = macroexpand(form, env);
+ val op;
+
+ if (consp(form_ex) &&
+ ((op = car(form_ex)) == progn_s || op == eval_only_s ||
+ op == compile_only_s))
+ {
+ val res = nil, next = cdr(form_ex);
+
+ while (next) {
+ res = expand_eval(car(next), env);
+ next = cdr(next);
+ }
+
+ return res;
+ }
+
+ return expand_eval(form_ex, env);
+}
+
val eval_intrinsic_noerr(val form, val env, val *error_p)
{
val result = nil;
@@ -6064,6 +6089,8 @@ void eval_init(void)
load_recursive_s = intern(lit("*load-recursive*"), system_package);
load_time_s = intern(lit("load-time"), user_package);
load_time_lit_s = intern(lit("load-time-lit"), system_package);
+ eval_only_s = intern(lit("eval-only"), user_package);
+ compile_only_s = intern(lit("compile-only"), user_package);
qquote_init();
@@ -6119,8 +6146,8 @@ void eval_init(void)
reg_op(prof_s, op_prof);
reg_op(switch_s, op_switch);
reg_op(intern(lit("upenv"), system_package), op_upenv);
- reg_op(intern(lit("compile-only"), user_package), op_progn);
- reg_op(intern(lit("eval-only"), user_package), op_progn);
+ reg_op(compile_only_s, op_progn);
+ reg_op(eval_only_s, op_progn);
reg_op(load_time_lit_s, op_load_time_lit);
reg_mac(defvar_s, func_n2(me_def_variable));