Skip to content

Commit 126258f

Browse files
authored
Merge pull request #335 from ktakashi/feature/continuation-mark
Feature/continuation mark
2 parents b6de535 + 4f6651b commit 126258f

File tree

5 files changed

+642
-6
lines changed

5 files changed

+642
-6
lines changed

lib/sagittarius/continuations.scm

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,113 @@
4545
continuation? composable-continuation?
4646
continuation-prompt-available?
4747

48+
with-continuation-mark with-continuation-marks
49+
continuation-mark-set?
50+
continuation-mark-set->list continuation-mark-set->list*
51+
current-continuation-marks
52+
continuation-mark-set-first
53+
call-with-immediate-continuation-mark
54+
55+
make-continuation-mark-key continuation-mark-key?
56+
4857
default-continuation-prompt-tag
4958
make-continuation-prompt-tag continuation-prompt-tag?
5059
shift reset
5160
prompt control)
5261
(import (except (core) call/cc call-with-current-continuation)
5362
(core macro)
63+
(core record)
5464
(core conditions)
5565
(sagittarius))
5666

67+
(define-syntax with-continuation-mark
68+
(lambda (x)
69+
(syntax-case x ()
70+
((_ k v expr ...)
71+
#'(call/cm (vector (cons k v)) (lambda () expr ...))))))
72+
(define-syntax with-continuation-marks
73+
(lambda (x)
74+
(syntax-case x ()
75+
((_ ((k v) ...) expr ...)
76+
#'(call/cm (vector (cons k v) ...) (lambda () expr ...))))))
77+
78+
(define (continuation-mark-set->list mark-set key
79+
:optional (prompt-tag (default-continuation-prompt-tag)))
80+
;; If mark-set is #f, use current-continuation-marks
81+
(let* ((ms (or mark-set (current-continuation-marks prompt-tag)))
82+
(frames (vector-ref ms 1)))
83+
(let loop ((frames frames) (result '()))
84+
(if (null? frames)
85+
(reverse! result)
86+
(let* ((frame (car frames))
87+
(entry (assq key frame)))
88+
(if entry
89+
(loop (cdr frames) (cons (cdr entry) result))
90+
(loop (cdr frames) result)))))))
91+
92+
(define (continuation-mark-set->list* mark-set keys
93+
:optional (default #f) (prompt-tag (default-continuation-prompt-tag)))
94+
;; Helper function to check if any key in keys has an entry in frame
95+
(define (has-any-key? frame keys)
96+
(let loop ((ks keys))
97+
(cond ((null? ks) #f)
98+
((assq (car ks) frame) #t)
99+
(else (loop (cdr ks))))))
100+
;; If mark-set is #f, use current-continuation-marks
101+
(let* ((ms (or mark-set (current-continuation-marks prompt-tag)))
102+
(frames (vector-ref ms 1))
103+
(key-count (length keys)))
104+
(let loop ((frames frames) (result '()))
105+
(if (null? frames)
106+
(reverse result)
107+
(let* ((frame (car frames))
108+
;; Check if this frame has any of our keys
109+
(has-key? (has-any-key? frame keys)))
110+
(if has-key?
111+
(let ((vec (make-vector key-count default)))
112+
;; Fill in values for each key
113+
(let key-loop ((ks keys) (i 0))
114+
(if (null? ks)
115+
(loop (cdr frames) (cons vec result))
116+
(let ((entry (assq (car ks) frame)))
117+
(when entry
118+
(vector-set! vec i (cdr entry)))
119+
(key-loop (cdr ks) (+ i 1))))))
120+
(loop (cdr frames) result)))))))
121+
122+
(define (continuation-mark-set-first mark-set key
123+
:optional (default #f) (prompt-tag (default-continuation-prompt-tag)))
124+
;; If mark-set is #f, use current-continuation-marks
125+
(let* ((ms (or mark-set (current-continuation-marks prompt-tag)))
126+
(frames (vector-ref ms 1)))
127+
(let loop ((frames frames))
128+
(if (null? frames)
129+
default
130+
(let* ((frame (car frames))
131+
(entry (assq key frame)))
132+
(if entry
133+
(cdr entry)
134+
(loop (cdr frames))))))))
135+
136+
(define (continuation-mark-set->iterator . arg*)
137+
(let f ((ls (apply continuation-mark-set->list* arg*)))
138+
(lambda ()
139+
(if (null? ls)
140+
(values #f
141+
(lambda ()
142+
(apply assertion-violation
143+
'continuation-mark-set->iterator
144+
"attempt to iterate past the end"
145+
arg*)))
146+
(values (car ls) (f (cdr ls)))))))
147+
148+
(define-record-type continuation-mark-key
149+
(nongenerative) (sealed #t) (opaque #f)
150+
(fields (mutable name))
151+
(protocol
152+
(lambda (p)
153+
(lambda (:optional ((name (or symbol? #f)) #f)) (p name)))))
154+
57155
;; From SRFI-226 implementation
58156
(define-syntax reset
59157
(lambda (x)

src/lib_sagittarius.stub

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,18 @@
18691869
(:optional (name::<symbol> (Sg_Gensym NULL)))
18701870
Sg_MakeContinuationPromptTag)
18711871

1872+
(define-c-proc call/cm (entries::<vector> thunk::<procedure>) Sg_VMCallCM)
1873+
(define-c-proc continuation-mark-set? (o) ::<boolean> :no-side-effect
1874+
Sg_ContinuationMarkSetP)
1875+
(define-c-proc %cm (k tag) :no-side-effect :no-export
1876+
Sg_ContinuationMarks)
1877+
(define-c-proc %ccm (tag) :no-side-effect :no-export
1878+
Sg_CurrentContinuationMarks)
1879+
1880+
(define-c-proc call-with-immediate-continuation-mark
1881+
(key proc::<procedure> :optional (default #f))
1882+
Sg_VMCallImmediateCM)
1883+
18721884
(define default-continuation-prompt-tag
18731885
(let ((tag (make-continuation-prompt-tag (gensym "default"))))
18741886
(lambda () tag)))
@@ -1892,6 +1904,13 @@
18921904
(default-continuation-prompt-tag)))
18931905
(%call/delim-cc proc tag))
18941906

1907+
(define (continuation-marks k
1908+
:optional (tag (default-continuation-prompt-tag)))
1909+
(%cm k tag))
1910+
(define (current-continuation-marks
1911+
:optional (tag (default-continuation-prompt-tag)))
1912+
(%ccm tag))
1913+
18951914
(define call/prompt call-with-continuation-prompt)
18961915
(define abort/cc abort-current-continuation)
18971916
(define call/comp call-with-composable-continuation)

src/sagittarius/private/vm.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ typedef enum {
108108
SG_DELIMIETED_CONTINUATION
109109
} SgContType;
110110

111+
typedef struct SgContMarksRec SgContMarks;
112+
111113
typedef struct SgContinucationRec
112114
{
113115
struct SgContinucationRec * prev;
@@ -120,6 +122,7 @@ typedef struct SgContinucationRec
120122
int errorReporting;
121123
int rewindBefore;
122124
SgContType type;
125+
SgContMarks *marks;
123126
} SgContinuation;
124127

125128
#define SG_CONTINUATION(obj) ((SgContinuation*)obj)
@@ -228,6 +231,18 @@ typedef struct SgPromptNodeRec
228231
struct SgPromptNodeRec *next;
229232
} SgPromptNode;
230233

234+
typedef struct SgMarkEntryRec {
235+
SgObject key;
236+
SgObject value;
237+
struct SgMarkEntryRec *next;
238+
} SgMarkEntry;
239+
240+
struct SgContMarksRec {
241+
SgContFrame *frame;
242+
SgMarkEntry *entries;
243+
struct SgContMarksRec *prev;
244+
};
245+
231246
struct SgVMRec
232247
{
233248
SG_HEADER;
@@ -252,6 +267,7 @@ struct SgVMRec
252267
SgObject *fp; /* frame pointer */
253268
SgObject *sp; /* stack pointer */
254269
SgContFrame *cont; /* saved continuation frame */
270+
SgContMarks *marks; /* continuation marks */
255271
SgPromptNode *prompts; /* prompt chain, this is the top */
256272
/* values buffer */
257273
int valuesCount;
@@ -429,13 +445,21 @@ SG_EXTERN SgObject Sg_VMCallCP(SgObject proc, SgObject tag,
429445
SgObject handler, SgObject args);
430446
/* call-with-continuation-barrier */
431447
SG_EXTERN SgObject Sg_VMCallCB(SgObject thunk);
448+
/* call-with-continuation-mark */
449+
SG_EXTERN SgObject Sg_VMCallCM(SgObject entries, SgObject thunk);
450+
/* call-with-immediate-continuation-mark */
451+
SG_EXTERN SgObject Sg_VMCallImmediateCM(SgObject key, SgObject proc,
452+
SgObject fallback);
432453
SG_EXTERN SgObject Sg_VMCallComp(SgObject proc, SgObject tag);
433454
SG_EXTERN SgObject Sg_VMCallDelimitedCC(SgObject proc, SgObject tag);
434455
SG_EXTERN SgObject Sg_VMAbortCC(SgObject tag, SgObject args);
435456
SG_EXTERN SgObject Sg_MakeContinuationPromptTag(SgObject name);
436457
SG_EXTERN int Sg_ContinuationP(SgObject o);
437458
SG_EXTERN int Sg_ComposableContinuationP(SgObject o);
438459
SG_EXTERN int Sg_ContinuationPromptAvailableP(SgObject tag, SgObject cont);
460+
SG_EXTERN int Sg_ContinuationMarkSetP(SgObject o);
461+
SG_EXTERN SgObject Sg_ContinuationMarks(SgObject k, SgObject promptTag);
462+
SG_EXTERN SgObject Sg_CurrentContinuationMarks(SgObject promptTag);
439463
SG_EXTERN SgVM* Sg_VM(); /* get vm */
440464
SG_EXTERN int Sg_SetCurrentVM(SgVM *vm);
441465
SG_EXTERN int Sg_AttachVM(SgVM *vm);

0 commit comments

Comments
 (0)