summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--eval.c66
-rw-r--r--txr.16
3 files changed, 82 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 4bb3fbc9..41c1b724 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2011-12-03 Kaz Kylheku <kaz@kylheku.com>
+ * eval.c (uw_protect_s, return_s, return_from_s): New symbol
+ variables.
+ (op_unwind_protect, op_block, op_return, op_return_from):
+ New static functions.
+ (expand): Removed case for call, if, and, and or. These operators
+ evaluate all their arguments, so the code walker can treat them
+ as a function calls.
+ Added case for block and return-from.
+ (eval_init): New symbols interned. New operator functions
+ registered in op_table.
+
+ * txr.1: Blank sections added.
+
+2011-12-03 Kaz Kylheku <kaz@kylheku.com>
+
* lib.c (split_str, split_str_set): Bugfix: access beyond the end of
the input string.
diff --git a/eval.c b/eval.c
index 113f6276..3ffcfbaa 100644
--- a/eval.c
+++ b/eval.c
@@ -53,7 +53,7 @@ val eval_error_s;
val let_s, let_star_s, lambda_s, call_s;
val cond_s, if_s, and_s, or_s, defvar_s, defun_s;
val inc_s, dec_s, push_s, pop_s, gethash_s, car_s, cdr_s;
-val for_s, for_star_s, dohash_s;
+val for_s, for_star_s, dohash_s, uw_protect_s, return_s, return_from_s;
val list_s, append_s, apply_s;
val make_env(val vbindings, val fbindings, val up_env)
@@ -611,6 +611,54 @@ static val op_dohash(val form, val env)
return eval(resform, new_env, form);
}
+static val op_unwind_protect(val form, val env)
+{
+ val prot_form = second(form);
+ val cleanup_forms = rest(rest(form));
+ val result;
+
+ uw_catch_begin(nil, exsym, exvals);
+
+ result = eval(prot_form, env, prot_form);
+
+ uw_do_unwind;
+
+ uw_catch (exsym, exvals);
+
+ uw_unwind
+ eval_progn(cleanup_forms, env, cleanup_forms);
+
+ uw_catch_end;
+
+ return result;
+}
+
+static val op_block(val form, val env)
+{
+ val sym = second(form);
+ val body = rest(rest(form));
+
+ uw_block_begin (sym, result);
+ result = eval_progn(body, env, form);
+ uw_block_end;
+
+ return result;
+}
+
+static val op_return(val form, val env)
+{
+ val retval = eval(second(form), env, form);
+ uw_block_return(nil, retval);
+ abort();
+}
+
+static val op_return_from(val form, val env)
+{
+ val name = second(form);
+ val retval = eval(third(form), env, form);
+ uw_block_return(name, retval);
+ abort();
+}
static val expand_forms(val form)
{
@@ -762,12 +810,13 @@ val expand(val form)
if (body == body_ex && vars == vars_ex)
return form;
return rlcp(cons(sym, cons(vars_ex, body_ex)), form);
- } else if (sym == call_s || sym == if_s || sym == and_s || sym == or_s) {
- val body = rest(form);
+ } else if (sym == block_s || sym == return_from_s) {
+ val name = second(form);
+ val body = rest(rest(form));
val body_ex = expand_forms(body);
if (body == body_ex)
return form;
- return rlcp(cons(sym, body_ex), form);
+ return rlcp(cons(sym, cons(name, body_ex)), form);
} else if (sym == cond_s) {
val pairs = rest(form);
val pairs_ex = expand_cond_pairs(pairs);
@@ -846,6 +895,7 @@ val expand(val form)
return rlcp(cons(sym, forms_ex), form);
} else {
/* funtion call */
+ /* also handles: call, if, and, or, unwind-protect, return */
val args = rest(form);
val args_ex = expand_forms(args);
@@ -907,7 +957,6 @@ static val mappendv(val fun, val list_of_lists)
}
}
-
static void reg_fun(val sym, val fun)
{
sethash(top_fb, sym, cons(sym, fun));
@@ -942,6 +991,9 @@ void eval_init(void)
for_s = intern(lit("for"), user_package);
for_star_s = intern(lit("for*"), user_package);
dohash_s = intern(lit("dohash"), user_package);
+ uw_protect_s = intern(lit("unwind-protect"), user_package);
+ return_s = intern(lit("return"), user_package);
+ return_from_s = intern(lit("return-from"), user_package);
gethash_s = intern(lit("gethash"), user_package);
car_s = intern(lit("car"), user_package);
cdr_s = intern(lit("cdr"), user_package);
@@ -971,6 +1023,10 @@ void eval_init(void)
sethash(op_table, for_s, cptr((mem_t *) op_for));
sethash(op_table, for_star_s, cptr((mem_t *) op_for));
sethash(op_table, dohash_s, cptr((mem_t *) op_dohash));
+ sethash(op_table, uw_protect_s, cptr((mem_t *) op_unwind_protect));
+ sethash(op_table, block_s, cptr((mem_t *) op_block));
+ sethash(op_table, return_s, cptr((mem_t *) op_return));
+ sethash(op_table, return_from_s, cptr((mem_t *) op_return_from));
reg_fun(cons_s, func_n2(cons));
reg_fun(car_s, func_n1(car));
diff --git a/txr.1 b/txr.1
index 0203651e..99796e86 100644
--- a/txr.1
+++ b/txr.1
@@ -4446,6 +4446,12 @@ syntax (fun (lambda ...)) is invalid.
.SS Operator dohash
+.SS Operator unwind-protect
+
+.SS Operator block
+
+.SS Operators return, return-from
+
.SS Lisp Functions and Variables
When the first element of a compound form is a symbol denoting a function,