summaryrefslogtreecommitdiffstats
path: root/unwind.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-10-24 00:57:54 -0400
committerKaz Kylheku <kaz@kylheku.com>2011-10-24 00:57:54 -0400
commit23a6fd5129b285d25faa8198e395ac91db0348c4 (patch)
tree6bad524c53ea7aed6a792cff97cfa9290c519b07 /unwind.c
parent69d40b9de060f88af224f1f27a7e020ccaabeddd (diff)
downloadtxr-23a6fd5129b285d25faa8198e395ac91db0348c4.tar.gz
txr-23a6fd5129b285d25faa8198e395ac91db0348c4.tar.bz2
txr-23a6fd5129b285d25faa8198e395ac91db0348c4.zip
Turning attention to some plumbing.
* unwind.c (uw_env_stack): New static variable. (uw_unwind_to_exit_point): Maintain correct uw_env_stack during unwinding. (uw_find_env): Just retrieve the env stack pointer; no search. (uw_push_env): Store a pointer to the previous environmental frame and just initialize the bindings to nil. No need to cons up a copy of the bindings from the previous frame. (uw_get_func): Perform a search through the environment stack. * unwind.h (struct uw_dynamic_env): New member, up_env.
Diffstat (limited to 'unwind.c')
-rw-r--r--unwind.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/unwind.c b/unwind.c
index 184fa858..143b9033 100644
--- a/unwind.c
+++ b/unwind.c
@@ -38,6 +38,7 @@
#include "unwind.h"
static uw_frame_t *uw_stack;
+static uw_frame_t *uw_env_stack;
static uw_frame_t *uw_exit_point;
static uw_frame_t toplevel_env;
@@ -72,6 +73,10 @@ static void uw_unwind_to_exit_point(void)
/* 1 means unwind only. */
longjmp(uw_stack->ca.jb, 1);
abort();
+ case UW_ENV:
+ /* Maintain consistency of unwind stack pointer */
+ uw_env_stack = uw_env_stack->ev.up_env;
+ break;
default:
break;
}
@@ -111,35 +116,33 @@ void uw_push_block(uw_frame_t *fr, val tag)
static uw_frame_t *uw_find_env(void)
{
- uw_frame_t *fr;
-
- for (fr = uw_stack; fr != 0; fr = fr->uw.up) {
- if (fr->uw.type == UW_ENV)
- break;
- }
-
- return fr ? fr : &toplevel_env;
+ return uw_env_stack ? uw_env_stack : &toplevel_env;
}
void uw_push_env(uw_frame_t *fr)
{
uw_frame_t *prev_env = uw_find_env();
fr->ev.type = UW_ENV;
-
- if (prev_env) {
- fr->ev.func_bindings = copy_alist(prev_env->ev.func_bindings);
- } else {
- fr->ev.func_bindings = nil;
- }
-
+ fr->ev.up_env = prev_env;
+ fr->ev.func_bindings = nil;
fr->ev.up = uw_stack;
uw_stack = fr;
+ uw_env_stack = fr;
}
val uw_get_func(val sym)
{
- uw_frame_t *env = uw_find_env();
- return cdr(assoc(env->ev.func_bindings, sym));
+ uw_frame_t *env;
+
+ for (env = uw_find_env(); env != 0; env = env->ev.up_env) {
+ if (env->ev.func_bindings) {
+ val found = assoc(env->ev.func_bindings, sym);
+ if (found)
+ return cdr(found);
+ }
+ }
+
+ return nil;
}
val uw_set_func(val sym, val value)
@@ -152,7 +155,11 @@ val uw_set_func(val sym, val value)
void uw_pop_frame(uw_frame_t *fr)
{
assert (fr == uw_stack);
- uw_stack = uw_stack->uw.up;
+ uw_stack = fr->uw.up;
+ if (fr->uw.type == UW_ENV) {
+ assert (fr == uw_env_stack);
+ uw_env_stack = fr->ev.up_env;
+ }
}
val uw_block_return(val tag, val result)