diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-10-28 20:18:20 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-10-28 20:18:20 -0700 |
commit | a5ef086fc33cfbfce7b03bad291efa28acf739b2 (patch) | |
tree | b6658f3ecbc98054217f72a166b02bfdb0b029e0 /unwind.c | |
parent | 67af4be97a2ea8700a841feb893a1f1747987843 (diff) | |
download | txr-a5ef086fc33cfbfce7b03bad291efa28acf739b2.tar.gz txr-a5ef086fc33cfbfce7b03bad291efa28acf739b2.tar.bz2 txr-a5ef086fc33cfbfce7b03bad291efa28acf739b2.zip |
Implementing sys:abscond-from operator.
* eval.c (sys_abscond_from_s): New symbol variable.
(op_abscond_from): New static function.
(do_expand): Handle abscond-from like return-from.
(eval_init): Initialize sys_abscond_from_s and
register sys:abscond-from operator.
* share/txr/stdlib/yield.tl (yield-from): Use
sys:abscond-from instead of return-from, to avoid
tearing down the continuation's resources that it may
need when restarted.
* txr.1: Documented sys:abscond-from and added
a mention to the Delimited Continuations introduction.
* unwind.c (uw_abscond_to_exit_point): New static function.
(uw_block_abscond): New function.
* unwind.h (uw_block_abscond): Declared.
Diffstat (limited to 'unwind.c')
-rw-r--r-- | unwind.c | 47 |
1 files changed, 47 insertions, 0 deletions
@@ -114,6 +114,34 @@ static void uw_unwind_to_exit_point(void) } } +static void uw_abscond_to_exit_point(void) +{ + assert (uw_exit_point); + + for (; uw_stack && uw_stack != uw_exit_point; uw_stack = uw_stack->uw.up) { + switch (uw_stack->uw.type) { + case UW_ENV: + uw_env_stack = uw_env_stack->ev.up_env; + break; + default: + break; + } + } + + if (!uw_stack) + abort(); + + uw_exit_point = 0; + + switch (uw_stack->uw.type) { + case UW_BLOCK: + extended_longjmp(uw_stack->bl.jb, 1); + abort(); + default: + abort(); + } +} + void uw_push_block(uw_frame_t *fr, val tag) { memset(fr, 0, sizeof *fr); @@ -356,6 +384,25 @@ val uw_block_return_proto(val tag, val result, val protocol) abort(); } +val uw_block_abscond(val tag, val result) +{ + uw_frame_t *ex; + + for (ex = uw_stack; ex != 0; ex = ex->uw.up) { + if (ex->uw.type == UW_BLOCK && ex->bl.tag == tag) + break; + } + + if (ex == 0) + return nil; + + ex->bl.result = result; + ex->bl.protocol = nil; + uw_exit_point = ex; + uw_abscond_to_exit_point(); + abort(); +} + void uw_push_catch(uw_frame_t *fr, val matches) { memset(fr, 0, sizeof *fr); |