summaryrefslogtreecommitdiffstats
path: root/unwind.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-07-31 17:32:19 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-07-31 17:37:25 -0700
commit2f5e7a5b96039b7a00543b4056bab7ec85c8db4b (patch)
treef6aeb8eb6cb4ee3fad726348fdd27ae2e43ec885 /unwind.c
parentc7edf3a752bc2522589246ff64f5a00fb96315d6 (diff)
downloadtxr-2f5e7a5b96039b7a00543b4056bab7ec85c8db4b.tar.gz
txr-2f5e7a5b96039b7a00543b4056bab7ec85c8db4b.tar.bz2
txr-2f5e7a5b96039b7a00543b4056bab7ec85c8db4b.zip
txr-014 2009-10-05txr-014
Diffstat (limited to 'unwind.c')
-rw-r--r--unwind.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/unwind.c b/unwind.c
index c573c16d..eb1490d4 100644
--- a/unwind.c
+++ b/unwind.c
@@ -30,10 +30,12 @@
#include <setjmp.h>
#include <dirent.h>
#include "lib.h"
+#include "gc.h"
#include "unwind.h"
static uw_frame_t *uw_stack;
static uw_frame_t *uw_exit_point;
+static uw_frame_t toplevel_env;
static void uw_unwind_to_exit_point()
{
@@ -49,9 +51,16 @@ static void uw_unwind_to_exit_point()
case UW_BLOCK:
longjmp(uw_stack->bl.jb, 1);
break;
+ case UW_ENV: /* env frame cannot be exit point */
+ abort();
+ default:
+ abort();
}
+}
- abort();
+void uw_init(void)
+{
+ protect(&toplevel_env.ev.func_bindings, 0);
}
void uw_push_block(uw_frame_t *fr, obj_t *tag)
@@ -63,6 +72,46 @@ void uw_push_block(uw_frame_t *fr, obj_t *tag)
uw_stack = fr;
}
+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;
+}
+
+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 = uw_stack;
+ uw_stack = fr;
+}
+
+obj_t *uw_get_func(obj_t *sym)
+{
+ uw_frame_t *env = uw_find_env();
+ return cdr(assoc(env->ev.func_bindings, sym));
+}
+
+obj_t *uw_set_func(obj_t *sym, obj_t *value)
+{
+ uw_frame_t *env = uw_find_env();
+ env->ev.func_bindings = acons_new(env->ev.func_bindings, sym, value);
+ return value;
+}
+
void uw_pop_frame(uw_frame_t *fr)
{
assert (fr == uw_stack);