Skip to content

Commit cc03165

Browse files
committed
Using SRFI-226 implementation of shift/reset
Adding control/prompt Adding composable continuation inspection
1 parent 4e5f137 commit cc03165

File tree

5 files changed

+145
-54
lines changed

5 files changed

+145
-54
lines changed

lib/sagittarius/continuations.scm

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -37,62 +37,52 @@
3737
call/delim-cc
3838
call-with-delimited-current-continuation
3939

40-
continuation? continuation-prompt-available?
40+
continuation? composable-continuation?
41+
continuation-prompt-available?
4142

4243
default-continuation-prompt-tag
4344
make-continuation-prompt-tag continuation-prompt-tag?
44-
shift reset)
45+
shift reset
46+
prompt control)
4547
(import (except (core) call/cc call-with-current-continuation)
4648
(core macro)
4749
(sagittarius))
4850

49-
;; (define (call/cc proc :optional (tag (default-continuation-prompt-tag)))
50-
;; (call-with-composable-continuation
51-
;; (lambda (ck)
52-
;; (define (k . args)
53-
;; (abort-current-continuation tag (lambda () (apply ck args))))
54-
;; (proc k))
55-
;; tag))
56-
;; (define call-with-current-continuation call/cc)
57-
58-
(define (abort-current-continuation/keep-prompt tag thunk)
59-
((call-with-continuation-prompt
60-
(lambda ()
61-
((call-with-delimited-current-continuation
62-
(lambda (k) (lambda () k))
63-
tag)))
64-
tag)
65-
thunk))
66-
67-
(define (make-call-with-shift abort-cc inserted-handler)
68-
(define (call-with-shift f :optional (tag (default-continuation-prompt-tag)))
69-
(call-with-composable-continuation
70-
(lambda (k)
71-
(abort-cc
72-
tag
73-
(lambda ()
74-
(f (lambda vals
75-
(call-with-continuation-prompt
76-
(lambda () (apply k vals))
77-
tag
78-
inserted-handler))))))))
79-
call-with-shift)
80-
81-
(define call-with-shift
82-
(make-call-with-shift abort-current-continuation/keep-prompt #f))
51+
;; From SRFI-226 implementation
52+
(define-syntax reset
53+
(lambda (x)
54+
(syntax-case x ()
55+
[(reset e1 e2 ...)
56+
#'(call-with-continuation-prompt
57+
(lambda ()
58+
e1 e2 ...))])))
8359

8460
(define-syntax shift
8561
(lambda (x)
8662
(syntax-case x ()
87-
((_ id expr0 expr ...)
88-
(identifier? #'id)
89-
#'(call-with-shift (lambda (id) expr0 expr ...))))))
63+
[(shift k e1 e2 ...)
64+
#'(call-with-composable-continuation
65+
(lambda (c)
66+
(define k (lambda args (reset (apply c args))))
67+
(abort-current-continuation (default-continuation-prompt-tag)
68+
(lambda () e1 e2 ...))))])))
9069

91-
(define-syntax reset
70+
(define-syntax prompt
9271
(lambda (x)
9372
(syntax-case x ()
94-
((_ expr0 expr ...)
73+
[(prompt e1 e2 ...)
9574
#'(call-with-continuation-prompt
96-
(lambda () expr0 expr ...))))))
75+
(lambda () e1 e2 ...)
76+
(default-continuation-prompt-tag)
77+
(lambda (thunk) (thunk)))])))
78+
79+
(define-syntax control
80+
(lambda (x)
81+
(syntax-case x ()
82+
[(control k e1 e2 ...)
83+
#'(call-with-composable-continuation
84+
(lambda (k)
85+
(abort-current-continuation (default-continuation-prompt-tag)
86+
(lambda () e1 e2 ...))))])))
9787

9888
)

src/lib_sagittarius.stub

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,8 @@
18561856
(define-c-proc %call/delim-cc (proc::<procedure> tag) :no-export
18571857
Sg_VMCallDelimitedCC)
18581858
(define-c-proc continuation? (o) ::<boolean> :no-side-effect Sg_ContinuationP)
1859+
(define-c-proc composable-continuation? (o) ::<boolean> :no-side-effect
1860+
Sg_ComposableContinuationP)
18591861
(define-c-proc continuation-prompt-available? (tag :optional (cont #f))
18601862
::<boolean> :no-side-effect
18611863
Sg_ContinuationPromptAvailableP)

src/sagittarius/private/vm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ SG_EXTERN SgObject Sg_VMCallComp(SgObject proc, SgObject tag);
417417
SG_EXTERN SgObject Sg_VMCallDelimitedCC(SgObject proc, SgObject tag);
418418
SG_EXTERN SgObject Sg_VMAbortCC(SgObject tag, SgObject args);
419419
SG_EXTERN int Sg_ContinuationP(SgObject o);
420+
SG_EXTERN int Sg_ComposableContinuationP(SgObject o);
420421
SG_EXTERN int Sg_ContinuationPromptAvailableP(SgObject tag, SgObject cont);
421422
SG_EXTERN SgVM* Sg_VM(); /* get vm */
422423
SG_EXTERN int Sg_SetCurrentVM(SgVM *vm);

src/vm.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,25 +1859,41 @@ int Sg_ContinuationP(SgObject o)
18591859
return SG_SUBRP(o) && SG_EQ(SG_PROCEDURE_NAME(o), sym_continuation);
18601860
}
18611861

1862+
int Sg_ComposableContinuationP(SgObject o)
1863+
{
1864+
return Sg_ContinuationP(o) &&
1865+
((SgContinuation *)SG_CAR(SG_SUBR_DATA(o)))->type == SG_COMPOSABLE_CONTINUATION;
1866+
}
1867+
18621868
int Sg_ContinuationPromptAvailableP(SgObject tag, SgObject k)
18631869
{
18641870
SgContFrame *cont = NULL;
18651871
SgPrompt *boundary = NULL;
18661872
SgVM *vm = theVM;
1873+
int type = SG_FULL_CONTINUATION;
18671874
if (SG_FALSEP(k)) {
18681875
cont = vm->cont;
18691876
} else if (Sg_ContinuationP(k)) {
18701877
SgContinuation *c = (SgContinuation *)SG_CAR(SG_SUBR_DATA(k));
18711878
boundary = (SgPrompt *)SG_CDR(SG_SUBR_DATA(k));
18721879
cont = c->cont;
1880+
type = c->type;
18731881
} else {
18741882
Sg_Error(UC("continuation or #f is required but got %S"), k);
18751883
}
18761884
while (!bottom_cont_frame_p(vm, cont)) {
18771885
if (PROMPT_FRAME_MARK_P(cont)) {
1878-
if (((SgPrompt *)cont->pc)->tag == tag) return TRUE;
1879-
if ((SgPrompt *)cont->pc == boundary) return FALSE;
1880-
1886+
SgPrompt *p = (SgPrompt *)cont->pc;
1887+
/* a bit weird, but Racket and SRFI-226 seems like this */
1888+
if (type == SG_COMPOSABLE_CONTINUATION) {
1889+
/* composable, excludes boundary */
1890+
if (p == boundary) return FALSE;
1891+
if (p->tag == tag) return TRUE;
1892+
} else {
1893+
/* delimited, includes boundary */
1894+
if (p->tag == tag) return TRUE;
1895+
if (p == boundary) return FALSE;
1896+
}
18811897
}
18821898
cont = cont->prev;
18831899
}

test/tests/sagittarius/continuations.scm

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,22 @@
55
(test-begin "Continuations")
66

77
(test-assert "continuation? (call/cc)"
8-
(continuation? (call/cc (lambda (k) k))))
8+
(continuation? (call/cc values)))
99
(test-assert "continuation? (call/comp)"
10-
(continuation?
11-
(call/prompt
12-
(lambda ()
13-
(call/comp (lambda (k) k))))))
10+
(continuation? (call/prompt (lambda () (call/comp values)))))
1411
(test-assert "continuation? (call/delimited-cc)"
15-
(continuation?
16-
(call/prompt
17-
(lambda ()
18-
(call/delim-cc (lambda (k) k))))))
12+
(continuation? (call/prompt (lambda () (call/delim-cc values)))))
1913

2014
(test-assert "continuation? (symbol)" (not (continuation? 'a)))
2115
(test-assert "continuation? (symbol)" (not (continuation? (lambda args args))))
2216

17+
(test-assert (not (composable-continuation? (call/cc values))))
18+
(test-assert (not (composable-continuation?
19+
(call/prompt (lambda () (call/delim-cc values))))))
20+
21+
(test-assert (composable-continuation?
22+
(call/prompt (lambda () (call/comp values)))))
23+
2324
(test-assert (continuation-prompt-tag? (default-continuation-prompt-tag)))
2425
(test-assert (continuation-prompt-tag? (make-continuation-prompt-tag)))
2526

@@ -158,4 +159,85 @@
158159
(test-equal "(post mid pre)" (e))
159160
(test-equal '(mid pre post mid pre) v)))
160161

162+
;; From SRFI-226
163+
164+
(test-equal 4 (+ 1 (reset 3)))
165+
(test-equal 5 (+ 1 (reset (* 2 (shift k 4)))))
166+
(test-equal 9 (+ 1 (reset (* 2 (shift k (k 4))))))
167+
(test-equal 17 (+ 1 (reset (* 2 (shift k (k (k 4)))))))
168+
(test-equal 25 (+ 1 (reset (* 2 (shift k1 (* 3 (shift k2 (k1 (k2 4)))))))))
169+
170+
(let ()
171+
(define call-with-non-composable-continuation call/delim-cc)
172+
(test-equal 990
173+
(let ([tag (make-continuation-prompt-tag)])
174+
(* 2
175+
(call-with-continuation-prompt
176+
(lambda ()
177+
(* 3
178+
(call-with-non-composable-continuation
179+
(lambda (k)
180+
(* 5
181+
(call-with-continuation-prompt
182+
(lambda ()
183+
(* 7 (k 11)))
184+
tag)))
185+
tag)))
186+
tag)))))
187+
188+
(test-equal 6930
189+
(let ([tag (make-continuation-prompt-tag)])
190+
(* 2
191+
(call-with-continuation-prompt
192+
(lambda ()
193+
(* 3
194+
(call-with-composable-continuation
195+
(lambda (k)
196+
(* 5
197+
(call-with-continuation-prompt
198+
(lambda ()
199+
(* 7 (k 11)))
200+
tag)))
201+
tag)))
202+
tag))))
203+
204+
(test-equal 7 (prompt (+ 2 (control k (k 5)))))
205+
(test-equal 5 (prompt (+ 2 (control k 5))))
206+
(test-equal 12 (prompt (+ 5 (prompt (+ 2 (control k1 (+ 1 (control k2 (k2 6)))))))))
207+
(test-equal 8 (prompt (+ 5 (prompt (+ 2 (control k1 (+ 1 (control k2 (k1 6)))))))))
208+
(test-equal 18 (prompt
209+
(+ 12 (prompt (+ 5 (prompt (+ 2 (control k1 (control k2 (control k3 (k3 6)))))))))))
210+
211+
(define-syntax let/prompt
212+
(syntax-rules ()
213+
((_ ((var val) ...) body ...)
214+
(let/prompt (default-continuation-prompt-tag) ((var val) ...) body ...))
215+
((_ tag ((var val) ...) body ...)
216+
(call-with-continuation-prompt
217+
(lambda ()
218+
(let ((var val) ...) body ...))
219+
tag))))
220+
221+
(let/prompt ()
222+
(define call-with-non-composable-continuation call/delim-cc)
223+
(define tag (make-continuation-prompt-tag))
224+
(call-with-continuation-prompt
225+
(lambda ()
226+
(test-assert
227+
(continuation-prompt-available? tag
228+
(call-with-non-composable-continuation values))))
229+
tag)
230+
(call-with-continuation-prompt
231+
(lambda ()
232+
(test-assert
233+
(continuation-prompt-available? tag
234+
(call-with-non-composable-continuation values tag))))
235+
tag)
236+
(call-with-continuation-prompt
237+
(lambda ()
238+
(test-assert
239+
(not (continuation-prompt-available? tag
240+
(call-with-composable-continuation values tag)))))
241+
tag))
242+
161243
(test-end)

0 commit comments

Comments
 (0)