summaryrefslogtreecommitdiffstats
path: root/unwind.h
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-10-25 20:48:39 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-10-25 20:48:39 -0700
commit596f3633c74f5dbd90768355e389ffadfbf2e89f (patch)
treeff52b9d41fb9988eb5e4301a312a777ce76e690b /unwind.h
parentbde25e195a88a78c12d3cdac820bcfdc8a01bbca (diff)
downloadtxr-596f3633c74f5dbd90768355e389ffadfbf2e89f.tar.gz
txr-596f3633c74f5dbd90768355e389ffadfbf2e89f.tar.bz2
txr-596f3633c74f5dbd90768355e389ffadfbf2e89f.zip
TXR gets delimited continuations.
* unwind.c (sys_cont_s): New symbol variable. (uw_pop_block): New function, supporting uw_block_end macro. Special logic is needed for popping blocks now, because a block can be a captured stub at the top of a continuation, which must not be popped in the regular manner. (struct cont): New struct type. (cont_destroy, cont_mark): New static functions. (cont_ops): New static structure. (revive_cont, capture_cont): New static functions. (uw_capture_cont): New functions. (uw_init): Initialize sys_cont_s. Register sys:capture-cont intrinsic. * unwind.h (enum uw_frtype): New enum member UW_CAPTURED_BLOCK. When a block is captured as a stub copy of the prompt block of a delimited continuation, its type is changed from UW_BLOCK to this new type. This does two things: it makes the block invisible to block-related code that does nothing with continuations (code that looks for UW_BLOCK and ignores anything else). Secondly, there is some special handling related to UW_CAPTURED_BLOCK frames. (uw_pop_block, uw_capture_cont): Declared. (uw_block_begin): New local pointer uw_rslt introduced which helps communicate the result variable over to the uw_block_end macro (so we don't have to add a variable argument to the latter). (uw_block_end): Use uw_pop_block instead of uw_pop_frame. * txr.1: Documented delimited continuations.
Diffstat (limited to 'unwind.h')
-rw-r--r--unwind.h11
1 files changed, 7 insertions, 4 deletions
diff --git a/unwind.h b/unwind.h
index 97d1026a..d6753da4 100644
--- a/unwind.h
+++ b/unwind.h
@@ -32,7 +32,7 @@
typedef union uw_frame uw_frame_t;
typedef enum uw_frtype {
- UW_BLOCK, UW_ENV, UW_CATCH, UW_HANDLE, UW_DBG
+ UW_BLOCK, UW_CAPTURED_BLOCK, UW_ENV, UW_CATCH, UW_HANDLE, UW_DBG
} uw_frtype_t;
struct uw_common {
@@ -123,12 +123,14 @@ void uw_push_debug(uw_frame_t *, val func, struct args *,
val ub_p_a_pairs, val env, val data,
val line, val chr);
void uw_pop_frame(uw_frame_t *);
+void uw_pop_block(uw_frame_t *, val *pret);
void uw_pop_until(uw_frame_t *);
uw_frame_t *uw_current_frame(void);
uw_frame_t *uw_current_exit_point(void);
val uw_get_frames(void);
val uw_find_frame(val extype, val frtype);
val uw_invoke_catch(val catch_frame, val sym, struct args *);
+val uw_capture_cont(val tag, val ctx);
void uw_init(void);
void uw_late_init(void);
@@ -147,15 +149,16 @@ noreturn val type_mismatch(val, ...);
obj_t *RESULTVAR = nil; \
do { \
uw_frame_t uw_blk; \
+ obj_t **uw_rslt = &RESULTVAR; \
uw_push_block(&uw_blk, TAG); \
if (extended_setjmp(uw_blk.bl.jb)) { \
RESULTVAR = uw_blk.bl.result; \
} else { \
do { } while (0)
-#define uw_block_end \
- } \
- uw_pop_frame(&uw_blk); \
+#define uw_block_end \
+ } \
+ uw_pop_block(&uw_blk, uw_rslt); \
} while (0)
#define uw_env_begin \