summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/txr/stdlib/yield.tl27
-rw-r--r--txr.162
-rw-r--r--unwind.c18
-rw-r--r--unwind.h2
4 files changed, 50 insertions, 59 deletions
diff --git a/share/txr/stdlib/yield.tl b/share/txr/stdlib/yield.tl
index 3b58ace2..43fa57ee 100644
--- a/share/txr/stdlib/yield.tl
+++ b/share/txr/stdlib/yield.tl
@@ -38,12 +38,6 @@
(lambda (cont)
(call cont 'sys:cont-poison))))
-(defun sys:yield-impl (name fun ctx-form)
- (let ((cont (sys:capture-cont name ctx-form)))
- (if (car cont)
- (call fun cont)
- (cdr cont))))
-
(defmacro obtain (. body)
(let ((arg (gensym "arg")))
^(sys:obtain-impl (lambda (,arg)
@@ -55,20 +49,17 @@
(defmacro yield-from (:form ctx-form name form)
(let ((cont-sym (gensym)))
- ^(sys:yield-impl ',name
- (lambda (,cont-sym)
- (sys:abscond-from ,name
- (new (sys:yld-item
- ,form (cdr ,cont-sym)))))
- ',ctx-form)))
+ ^(sys:capture-cont ',name
+ (lambda (,cont-sym)
+ (sys:abscond-from ,name
+ (new (sys:yld-item
+ ,form ,cont-sym))))
+ ',ctx-form)))
(defmacro yield (form)
^(yield-from nil ,form))
(defmacro suspend (:form form name var . body)
- (with-gensyms (cap val)
- ^(tree-bind (,cap . ,val) (sys:capture-cont ',name ',form)
- (if ,cap
- (let ((,var ,val))
- (sys:abscond-from ,name ,*body))
- ,val))))
+ ^(sys:capture-cont ',name (lambda (,var)
+ (sys:abscond-from ,name ,*body))
+ ',form))
diff --git a/txr.1 b/txr.1
index cb08499e..9a16104e 100644
--- a/txr.1
+++ b/txr.1
@@ -27568,14 +27568,17 @@ as the closure body terminates.
.coNP Function @ sys:capture-cont
.synb
-.mets (sys:capture-cont < name <> [ context-form ])
+.mets (sys:capture-cont < name < receive-fun <> [ context-form ])
.syne
.desc
The
.code sys:capture-cont
function captures a continuation, and also serves as the resume point
for the resulting continuation. Which of these two situations is the
-case (capture or resumption) is distinguished by the return value.
+case (capture or resumption) is distinguished by the use of the
+.meta receive-fun
+argument, which must be a function capable of being called with one
+argument.
A block named
.meta name
@@ -27594,33 +27597,29 @@ uses its own name.
The
.code sys:capture-cont
-function returns a cons cell. The
-.code car
-field of the cell distinguishes the capture and resume situations.
-If the
-.code car
-is the object
-.codn t ,
-then it indicates capture, and in this case, the
-.code cdr
-field contains the continuation function. When the continuation
-function is called, the
+function captures a continuation, represented as a function.
+It immediately calls
+.metn receive-fun ,
+passing it it the continuation function as an argument.
+If
+.meta receive-fun
+returns normally, then
.code sys:capture-cont
-function appears to return again. This time the
-.code car
-of the returned cell is
-.code nil
-indicating that the
-.code cdr
-field holds the argument value which was passed to the continuation
-function.
+returns whatever value
+.meta receive-fun
+returns.
-The invoked continuation function will terminate when the resumed context
-terminates. If that context terminates normally (by returning from the
-delimiting block named by
-.metn name ),
-then the result value of that block will appear as the return value
-of the continuation function.
+When the continuation function is called (thereby resuming the captured
+continuation), inside that resumed continuation,
+.code sys:capture-cont
+function appears to return. Its return value is the argument
+which was passed to the continuation function. The continuation function
+appears suspended while the resumed continuation executes.
+If the resumed continuation context terminates normally (by terminating
+the continuation's delimiting block named by
+.metn name )
+the continuation function terminates, and yields the value which emerged
+from the terminated block.
If the symbol
.code sys:cont-poison
@@ -27661,12 +27660,9 @@ operator.
.cblk
(defmacro suspend (:form form name var . body)
- (with-gensyms (cap val)
- ^(tree-bind (,cap . ,val) (sys:capture-cont ',name ',form)
- (if ,cap
- (let ((,var ,val))
- (sys:abscond-from ,name ,*body))
- ,val))))
+ ^(sys:capture-cont ',name (lambda (,var)
+ (sys:abscond-from ,name ,*body))
+ ',form))
.cble
.coNP Operator @ sys:abscond-from
diff --git a/unwind.c b/unwind.c
index f72839f0..a3f63038 100644
--- a/unwind.c
+++ b/unwind.c
@@ -754,7 +754,7 @@ static val revive_cont(val dc, val arg)
bug_unless (uw_stack->uw.type == UW_BLOCK);
- uw_stack->bl.result = cons(nil, arg);
+ uw_stack->bl.result = arg;
uw_exit_point = if3(arg == sys_cont_poison_s, &uw_blk, uw_stack);
uw_unwind_to_exit_point();
abort();
@@ -767,8 +767,9 @@ static val revive_cont(val dc, val arg)
}
}
-static val capture_cont(val tag, uw_frame_t *block)
+static val capture_cont(val tag, val fun, uw_frame_t *block)
{
+ volatile val cont_obj = nil;
uw_block_begin (nil, result);
bug_unless (uw_stack < block);
@@ -792,19 +793,22 @@ static val capture_cont(val tag, uw_frame_t *block)
blcopy->uw.up = 0;
blcopy->uw.type = UW_CAPTURED_BLOCK;
- result = cobj(coerce(mem_t *, cont), sys_cont_s, &cont_ops);
+ cont_obj = cobj(coerce(mem_t *, cont), sys_cont_s, &cont_ops);
cont->tag = tag;
- result = cons(t, func_f1(result, revive_cont));
+ result = nil;
}
uw_block_end;
+ if (cont_obj)
+ result = funcall1(fun, func_f1(cont_obj, revive_cont));
+
return result;
}
-val uw_capture_cont(val tag, val ctx_form)
+val uw_capture_cont(val tag, val fun, val ctx_form)
{
uw_frame_t *fr;
@@ -825,7 +829,7 @@ val uw_capture_cont(val tag, val ctx_form)
abort();
}
- return capture_cont(tag, fr);
+ return capture_cont(tag, fun, fr);
}
void uw_init(void)
@@ -874,5 +878,5 @@ void uw_late_init(void)
reg_fun(intern(lit("invoke-catch"), user_package),
func_n2v(uw_invoke_catch));
reg_fun(sys_capture_cont_s = intern(lit("capture-cont"), system_package),
- func_n2o(uw_capture_cont, 1));
+ func_n3o(uw_capture_cont, 2));
}
diff --git a/unwind.h b/unwind.h
index bcf8d185..5fccabc0 100644
--- a/unwind.h
+++ b/unwind.h
@@ -125,7 +125,7 @@ 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_form);
+val uw_capture_cont(val tag, val fun, val ctx_form);
void uw_init(void);
void uw_late_init(void);