add continuation-mark-set->iterator

Support continuation-mark inspection proportional to the amount that
needs to be inspected, instead of having to build a list of length
propotional to the size of a continuation.

In Racket CS, use iteration to improve exception-handling chaining.
Traditional Racket already used similar functonality internally.
This commit is contained in:
Matthew Flatt 2019-11-10 14:35:10 -06:00
parent 8aef27ccf5
commit 5eb04dfa9e
11 changed files with 332 additions and 130 deletions

View File

@ -12,7 +12,7 @@
(define collection 'multi) (define collection 'multi)
(define version "7.5.0.6") (define version "7.5.0.7")
(define deps `("racket-lib" (define deps `("racket-lib"
["racket" #:version ,version])) ["racket" #:version ,version]))

View File

@ -0,0 +1,40 @@
#lang racket/base
(require racket/include)
(include "config.rktl")
'----------------------------------------
'exn
(time
(for/fold ([v #f]) ([i (in-range Q)])
(with-handlers ([(lambda (x) #t) (lambda (x) 'caught)])
(raise 'exn))))
'exn-deep
(time
(let loop ([n 1000])
(if (zero? n)
(for/fold ([v #f]) ([i (in-range Q)])
(with-handlers ([(lambda (x) #t) (lambda (x) 'caught)])
(raise 'exn)))
(with-continuation-mark
'key 'val
(values (loop (sub1 n)))))))
;; Runs a chain of 1000 handlers
'exn-chain
(time
(for/fold ([v #f]) ([i (in-range (quotient Q 100))])
(let/ec esc
(call-with-exception-handler
(lambda (exn) (esc 'done))
(lambda ()
(let loop ([n 1000])
(if (zero? n)
(raise 'exn)
(call-with-exception-handler
(lambda (exn) exn)
(lambda ()
(values (loop (sub1 n))))))))))))

View File

@ -85,7 +85,9 @@ Returns a newly-created list containing the marks for @racket[key-v]
in @racket[mark-set], which is a set of marks returned by in @racket[mark-set], which is a set of marks returned by
@racket[current-continuation-marks]. The result list is truncated at @racket[current-continuation-marks]. The result list is truncated at
the first point, if any, where continuation frames were originally the first point, if any, where continuation frames were originally
separated by a prompt tagged with @racket[prompt-tag].} separated by a prompt tagged with @racket[prompt-tag]. Producing the result
takes time proportional to the size of the continuation reflected by
@racket[mark-set].}
@defproc*[([(make-continuation-mark-key) continuation-mark-key?] @defproc*[([(make-continuation-mark-key) continuation-mark-key?]
[(make-continuation-mark-key [sym symbol?]) continuation-mark-key?])]{ [(make-continuation-mark-key [sym symbol?]) continuation-mark-key?])]{
@ -114,7 +116,30 @@ particular vector position is the value for the corresponding key in
@racket[key-list]. Values for multiple keys appear in a single vector @racket[key-list]. Values for multiple keys appear in a single vector
only when the marks are for the same continuation frame in only when the marks are for the same continuation frame in
@racket[mark-set]. The @racket[none-v] argument is used for vector @racket[mark-set]. The @racket[none-v] argument is used for vector
elements to indicate the lack of a value.} elements to indicate the lack of a value. Producing the result
takes time proportional to the size of the continuation reflected by
@racket[mark-set] times the length of @racket[key-list].}
@defproc[(continuation-mark-set->iterator
[mark-set continuation-mark-set?]
[key-list (listof any/c)]
[none-v any/c #f]
[prompt-tag continuation-prompt-tag? (default-continuation-prompt-tag)])
(-> (values (or/c vector? #f) procedure?))]{
Like @racket[continuation-mark-set->list*], but instead of returning a
list of values, returns a functional iterator in the form of a
procedure that returns one element of the would-be list and a new
iterator function for the rest of the would-be list. An iterator
procedure returns @racket[#f] instead of a vector when no more
elements are available; in that case, the returned iterator
procedure is like the called one, producing no further values.
The time required for each step is proportional to the length of
@racket[key-list] times the size of the segment of the continuation
reflected by @racket[mark-set] between frames that have keys in
@racket[key-list].
@history[#:added "7.5.0.7"]}
@defproc[(continuation-mark-set-first @defproc[(continuation-mark-set-first
[mark-set (or/c continuation-mark-set? #f)] [mark-set (or/c continuation-mark-set? #f)]
@ -125,10 +150,12 @@ elements to indicate the lack of a value.}
Returns the first element of the list that would be returned by Returns the first element of the list that would be returned by
@racket[(continuation-mark-set->list (or mark-set @racket[(continuation-mark-set->list (or mark-set
(current-continuation-marks prompt-tag)) key-v prompt-tag)], or (current-continuation-marks prompt-tag)) key-v prompt-tag)], or
@racket[none-v] if the result would be the empty list. Typically, this @racket[none-v] if the result would be the empty list. The result
is produced in (amortized) constant time. Typically, this
result can be computed more quickly using result can be computed more quickly using
@racket[continuation-mark-set-first] than using @racket[continuation-mark-set-first] than using
@racket[continuation-mark-set->list].} @racket[continuation-mark-set->list] or by using
@racket[continuation-mark-set->iterator] and iterating just once.}
@defproc[(call-with-immediate-continuation-mark @defproc[(call-with-immediate-continuation-mark
[key-v any/c] [key-v any/c]

View File

@ -73,6 +73,23 @@
x x
x))))) x)))))
(wcm-test '(#(no 12) #(10 no))
(lambda ()
(with-continuation-mark 'key1 10
(let ([x (with-continuation-mark 'key2 12
(let loop ([iter (continuation-mark-set->iterator (current-continuation-marks) '(key1 key2) 'no)])
(let-values ([(vec next) (iter)])
(if (not vec)
(let*-values ([(false next-again) (next)]
[(false2 next-again-again) (next-again)])
(test #f values false)
(test #f values false2)
null)
(cons vec (loop next))))))])
(if (void? x)
x
x)))))
(wcm-test '(11) (lambda () (wcm-test '(11) (lambda ()
(with-continuation-mark 'key 10 (with-continuation-mark 'key 10
(with-continuation-mark 'key 11 (with-continuation-mark 'key 11
@ -101,7 +118,7 @@
(with-continuation-mark 'key 10 (extract-current-continuation-marks 'key)) (with-continuation-mark 'key 10 (extract-current-continuation-marks 'key))
(extract-current-continuation-marks 'key))))) (extract-current-continuation-marks 'key)))))
(require (prefix-in unit: scheme/unit)) (require (prefix-in unit: racket/unit))
;; ;; Hide keywords from scheme/unit.rkt: ;; ;; Hide keywords from scheme/unit.rkt:
(define import #f) (define import #f)
@ -995,6 +1012,14 @@
(current-continuation-marks) (current-continuation-marks)
(list mark)))) (list mark))))
(define (do-test-iterate mark val)
(with-continuation-mark mark val
(let ([iter (continuation-mark-set->iterator (current-continuation-marks)
(list mark))])
(let loop ([iter iter])
(let-values ([(v iter) (iter)])
(if v (cons v (loop iter)) null))))))
(define (do-test/first mark val) (define (do-test/first mark val)
(with-continuation-mark mark val (with-continuation-mark mark val
(continuation-mark-set-first (current-continuation-marks) mark))) (continuation-mark-set-first (current-continuation-marks) mark)))
@ -1006,10 +1031,12 @@
(wcm-test '(12) (lambda () (do-test imp-mark 5))) (wcm-test '(12) (lambda () (do-test imp-mark 5)))
(wcm-test '(#(12)) (lambda () (do-test* imp-mark 5))) (wcm-test '(#(12)) (lambda () (do-test* imp-mark 5)))
(wcm-test '(#(12)) (lambda () (do-test-iterate imp-mark 5)))
(wcm-test 12 (lambda () (do-test/first imp-mark 5))) (wcm-test 12 (lambda () (do-test/first imp-mark 5)))
(wcm-test 12 (lambda () (do-test/immediate imp-mark 5))) (wcm-test 12 (lambda () (do-test/immediate imp-mark 5)))
(wcm-test '(5) (lambda () (do-test cha-mark 5))) (wcm-test '(5) (lambda () (do-test cha-mark 5)))
(wcm-test '(#(5)) (lambda () (do-test* cha-mark 5))) (wcm-test '(#(5)) (lambda () (do-test* cha-mark 5)))
(wcm-test '(#(5)) (lambda () (do-test-iterate cha-mark 5)))
(wcm-test 5 (lambda () (do-test/first cha-mark 5))) (wcm-test 5 (lambda () (do-test/first cha-mark 5)))
(wcm-test 5 (lambda () (do-test/immediate cha-mark 5))) (wcm-test 5 (lambda () (do-test/immediate cha-mark 5)))
(err/rt-test (do-test cha-mark #t) exn:fail?) (err/rt-test (do-test cha-mark #t) exn:fail?)

View File

@ -187,6 +187,7 @@
[cons (known-procedure/pure 4)] [cons (known-procedure/pure 4)]
[continuation-mark-key? (known-procedure/pure/folding 2)] [continuation-mark-key? (known-procedure/pure/folding 2)]
[continuation-mark-set->context (known-procedure/no-prompt 2)] [continuation-mark-set->context (known-procedure/no-prompt 2)]
[continuation-mark-set->iterator (known-procedure/no-prompt 28)]
[continuation-mark-set->list (known-procedure/no-prompt 12)] [continuation-mark-set->list (known-procedure/no-prompt 12)]
[continuation-mark-set->list* (known-procedure/no-prompt 28)] [continuation-mark-set->list* (known-procedure/no-prompt 28)]
[continuation-mark-set-first (known-procedure/no-prompt 28)] [continuation-mark-set-first (known-procedure/no-prompt 28)]

View File

@ -37,6 +37,7 @@
continuation-mark-set-first continuation-mark-set-first
continuation-mark-set->list continuation-mark-set->list
continuation-mark-set->list* continuation-mark-set->list*
continuation-mark-set->iterator
continuation-mark-set->context continuation-mark-set->context
current-continuation-marks current-continuation-marks
(rename [continuation-marks rumble:continuation-marks]) ; wrapped at threads layer (rename [continuation-marks rumble:continuation-marks]) ; wrapped at threads layer

View File

@ -1366,6 +1366,26 @@
[(marks keys) (continuation-mark-set->list* marks keys #f the-default-continuation-prompt-tag)] [(marks keys) (continuation-mark-set->list* marks keys #f the-default-continuation-prompt-tag)]
[(marks keys none-v) (continuation-mark-set->list* marks keys none-v the-default-continuation-prompt-tag)] [(marks keys none-v) (continuation-mark-set->list* marks keys none-v the-default-continuation-prompt-tag)]
[(marks keys none-v prompt-tag) [(marks keys none-v prompt-tag)
((do-continuation-mark-set->list* who #f marks keys none-v prompt-tag))]))
(define/who continuation-mark-set->iterator
(case-lambda
[(marks keys) (continuation-mark-set->iterator marks keys #f the-default-continuation-prompt-tag)]
[(marks keys none-v) (continuation-mark-set->iterator marks keys none-v the-default-continuation-prompt-tag)]
[(marks keys none-v prompt-tag)
(let ([next (do-continuation-mark-set->list* who #t marks keys none-v prompt-tag)])
;; Each `next` call returns `null` when no more values are
;; available, otherwise a vector and a new next
(lambda ()
(let loop ([next next])
(call-with-values next
(case-lambda
[(done)
(values #f (lambda () (loop (lambda () null))))]
[(v new-next)
(values v (lambda () (loop new-next)))])))))]))
(define (do-continuation-mark-set->list* who iterator? marks keys none-v prompt-tag)
(check who continuation-mark-set? :or-false marks) (check who continuation-mark-set? :or-false marks)
(check who list? keys) (check who list? keys)
(check who continuation-prompt-tag? prompt-tag) (check who continuation-prompt-tag? prompt-tag)
@ -1373,8 +1393,9 @@
(let ([prompt-tag (strip-impersonator prompt-tag)]) (let ([prompt-tag (strip-impersonator prompt-tag)])
(let-values ([(all-keys all-wrappers) (let-values ([(all-keys all-wrappers)
(map/2-values (lambda (k) (map/2-values (lambda (k)
(extract-continuation-mark-key-and-wrapper 'continuation-mark-set->list* k)) (extract-continuation-mark-key-and-wrapper who k))
keys)]) keys)])
(lambda ()
(let* ([n (length all-keys)] (let* ([n (length all-keys)]
[tmp (#%make-vector n)]) [tmp (#%make-vector n)])
(let chain-loop ([mark-chain (or (and marks (let chain-loop ([mark-chain (or (and marks
@ -1400,7 +1421,9 @@
[(null? keys) [(null? keys)
(if found? (if found?
(let ([vec (vector-copy tmp)]) (let ([vec (vector-copy tmp)])
(cons vec (loop (cdr marks)))) (if iterator?
(values vec (lambda () (loop (cdr marks))))
(cons vec (loop (cdr marks)))))
(loop (cdr marks)))] (loop (cdr marks)))]
[else [else
(let ([v (extract-mark-from-frame* t (car keys) none (car wrappers))]) (let ([v (extract-mark-from-frame* t (car keys) none (car wrappers))])
@ -1410,7 +1433,7 @@
(key-loop (cdr keys) (cdr wrappers) (add1 i) found?)] (key-loop (cdr keys) (cdr wrappers) (add1 i) found?)]
[else [else
(vector-set! tmp i v) (vector-set! tmp i v)
(key-loop (cdr keys) (cdr wrappers) (add1 i) #t)]))])))]))]))])))))])) (key-loop (cdr keys) (cdr wrappers) (add1 i) #t)]))])))]))]))])))))))
(define/who (continuation-mark-set->context marks) (define/who (continuation-mark-set->context marks)
(check who continuation-mark-set? marks) (check who continuation-mark-set? marks)

View File

@ -10,8 +10,9 @@
(do-raise v))])) (do-raise v))]))
(define (do-raise v) (define (do-raise v)
(let ([hs (continuation-mark-set->list (current-continuation-marks/no-trace) (let ([get-next-h (continuation-mark-set->iterator (current-continuation-marks/no-trace)
exception-handler-key (list exception-handler-key)
#f
the-root-continuation-prompt-tag)] the-root-continuation-prompt-tag)]
[init-v (condition->exn v)]) [init-v (condition->exn v)])
(let ([call-with-nested-handler (let ([call-with-nested-handler
@ -20,20 +21,20 @@
(make-nested-exception-handler "exception handler" init-v) (make-nested-exception-handler "exception handler" init-v)
(lambda () (lambda ()
(call-with-break-disabled thunk))))]) (call-with-break-disabled thunk))))])
(let loop ([hs hs] [v init-v]) (let loop ([get-next-h get-next-h] [v init-v])
(let-values ([(hv get-next-h) (get-next-h)])
(cond (cond
[(null? hs) [(not hv)
(call-with-nested-handler (call-with-nested-handler
(lambda () (|#%app| (|#%app| uncaught-exception-handler) v))) (lambda () (|#%app| (|#%app| uncaught-exception-handler) v)))
;; Use `nested-exception-handler` if the uncaught-exception ;; Use `nested-exception-handler` if the uncaught-exception
;; handler doesn't escape: ;; handler doesn't escape:
((make-nested-exception-handler #f v) #f)] ((make-nested-exception-handler #f v) #f)]
[else [else
(let ([h (car hs)] (let ([h (vector-ref hv 0)])
[hs (cdr hs)])
(let ([new-v (call-with-nested-handler (let ([new-v (call-with-nested-handler
(lambda () (|#%app| h v)))]) (lambda () (|#%app| h v)))])
(loop hs new-v)))]))))) (loop get-next-h new-v)))]))))))
;; ---------------------------------------- ;; ----------------------------------------

View File

@ -106,6 +106,7 @@ static Scheme_Object *cont_marks (int argc, Scheme_Object *argv[]);
static Scheme_Object *cc_marks_p (int argc, Scheme_Object *argv[]); static Scheme_Object *cc_marks_p (int argc, Scheme_Object *argv[]);
static Scheme_Object *extract_cc_marks (int argc, Scheme_Object *argv[]); static Scheme_Object *extract_cc_marks (int argc, Scheme_Object *argv[]);
static Scheme_Object *extract_cc_markses (int argc, Scheme_Object *argv[]); static Scheme_Object *extract_cc_markses (int argc, Scheme_Object *argv[]);
static Scheme_Object *extract_cc_iterator (int argc, Scheme_Object *argv[]);
static Scheme_Object *extract_cc_proc_marks (int argc, Scheme_Object *argv[]); static Scheme_Object *extract_cc_proc_marks (int argc, Scheme_Object *argv[]);
static Scheme_Object *extract_one_cc_mark (int argc, Scheme_Object *argv[]); static Scheme_Object *extract_one_cc_mark (int argc, Scheme_Object *argv[]);
static Scheme_Object *call_with_immediate_cc_mark (int argc, Scheme_Object *argv[]); static Scheme_Object *call_with_immediate_cc_mark (int argc, Scheme_Object *argv[]);
@ -415,6 +416,12 @@ scheme_init_fun (Scheme_Startup_Env *env)
2, 4), 2, 4),
env); env);
scheme_addto_prim_instance("continuation-mark-set->iterator",
scheme_make_prim_w_arity(extract_cc_iterator,
"continuation-mark-set->iterator",
2, 4),
env);
o = scheme_make_prim_w_arity(extract_one_cc_mark, o = scheme_make_prim_w_arity(extract_one_cc_mark,
"continuation-mark-set-first", "continuation-mark-set-first",
2, 4); 2, 4);
@ -8137,59 +8144,23 @@ extract_cc_marks(int argc, Scheme_Object *argv[])
} }
static Scheme_Object * static Scheme_Object *
extract_cc_markses(int argc, Scheme_Object *argv[]) iterate_cc_markses(const char *who,
Scheme_Object *prompt_tag, Scheme_Object *none,
intptr_t len, Scheme_Object **keys,
Scheme_Cont_Mark_Chain **_chain)
{ {
Scheme_Cont_Mark_Chain *chain; Scheme_Cont_Mark_Chain *chain = *_chain;
Scheme_Object *first = scheme_null, *last = NULL; intptr_t last_pos, i;
Scheme_Object *pr, **keys, *vals, *none, *prompt_tag; Scheme_Object *vals = NULL;
int len, i;
intptr_t last_pos;
if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_cont_mark_set_type)) {
scheme_wrong_contract("continuation-mark-set->list*", "continuation-mark-set?", 0, argc, argv);
return NULL;
}
len = scheme_proper_list_length(argv[1]);
if (len < 0) {
scheme_wrong_contract("continuation-mark-set->list*", "list?", 1, argc, argv);
return NULL;
}
if (argc > 2)
none = argv[2];
else
none = scheme_false;
if (argc > 3) {
if (!SAME_TYPE(scheme_prompt_tag_type, SCHEME_TYPE(argv[3]))) {
if (SCHEME_NP_CHAPERONEP(argv[3])
&& SCHEME_PROMPT_TAGP(SCHEME_CHAPERONE_VAL(argv[3])))
prompt_tag = SCHEME_CHAPERONE_VAL(argv[3]);
else {
scheme_wrong_contract("continuation-mark-set->list*", "continuation-prompt-tag?",
3, argc, argv);
return NULL;
}
} else
prompt_tag = argv[3];
} else
prompt_tag = scheme_default_prompt_tag;
keys = MALLOC_N(Scheme_Object *, len);
for (pr = argv[1], i = 0; SCHEME_PAIRP(pr); pr = SCHEME_CDR(pr), i++) {
keys[i] = SCHEME_CAR(pr);
if ((keys[i] == scheme_parameterization_key)
|| (keys[i] == scheme_break_enabled_key)
|| (keys[i] == scheme_exn_handler_key)) {
scheme_signal_error("continuation-mark-set->list: secret key leaked!");
return NULL;
}
}
prompt_tag = SCHEME_PTR_VAL(prompt_tag); prompt_tag = SCHEME_PTR_VAL(prompt_tag);
chain = ((Scheme_Cont_Mark_Set *)argv[0])->chain;
last_pos = -1;
while (chain) { while (chain) {
if (vals && (last_pos != chain->pos)) {
*_chain = chain;
return vals;
}
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int is_chaperoned = 0; int is_chaperoned = 0;
Scheme_Object *orig_key, *val; Scheme_Object *orig_key, *val;
@ -8206,19 +8177,12 @@ extract_cc_markses(int argc, Scheme_Object *argv[])
if (SAME_OBJ(chain->key, keys[i])) { if (SAME_OBJ(chain->key, keys[i])) {
intptr_t pos; intptr_t pos;
pos = (intptr_t)chain->pos; pos = (intptr_t)chain->pos;
if (pos != last_pos) { if (!vals) {
vals = scheme_make_vector(len, none); vals = scheme_make_vector(len, none);
last_pos = pos; last_pos = pos;
pr = scheme_make_pair(vals, scheme_null); }
if (last)
SCHEME_CDR(last) = pr;
else
first = pr;
last = pr;
} else
vals = SCHEME_CAR(last);
if (is_chaperoned) { if (is_chaperoned) {
val = scheme_chaperone_do_continuation_mark("continuation-mark-set->list*", val = scheme_chaperone_do_continuation_mark(who,
1, orig_key, chain->val); 1, orig_key, chain->val);
SCHEME_VEC_ELS(vals)[i] = val; SCHEME_VEC_ELS(vals)[i] = val;
} else } else
@ -8232,8 +8196,126 @@ extract_cc_markses(int argc, Scheme_Object *argv[])
chain = chain->next; chain = chain->next;
} }
*_chain = NULL;
return vals;
}
static Scheme_Object *iterate_step(void *data, int argc, Scheme_Object *argv[])
{
Scheme_Cont_Mark_Chain *chain = ((void **)data)[0];
void **clos = ((void **)data)[1], **new_state;
Scheme_Object *vals, *a[2];
Scheme_Object *prompt_tag = ((Scheme_Object **)clos)[0];
Scheme_Object **keys = ((Scheme_Object ***)clos)[1];
intptr_t len = SCHEME_INT_VAL(((Scheme_Object **)clos)[2]);
Scheme_Object *none = ((Scheme_Object **)clos)[3];
if (!chain) {
a[0] = scheme_false;
new_state = data;
} else {
vals = iterate_cc_markses("mark-list*-iterator", prompt_tag, none, len, keys, &chain);
if (!vals)
a[0] = scheme_false;
else
a[0] = vals;
new_state = MALLOC_N(void*, 2);
new_state[0] = chain;
new_state[1] = clos;
}
a[1] = scheme_make_closed_prim_w_arity(iterate_step, new_state, "mark-list*-iterator", 0, 0);
return scheme_values(2, a);
}
static Scheme_Object *
do_extract_cc_markses(const char *who, int argc, Scheme_Object *argv[], int iterator)
{
Scheme_Cont_Mark_Chain *chain;
Scheme_Object *first = scheme_null, *last = NULL;
Scheme_Object *pr, **keys, *vals, *none, *prompt_tag;
intptr_t len, i;
if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_cont_mark_set_type)) {
scheme_wrong_contract(who, "continuation-mark-set?", 0, argc, argv);
return NULL;
}
len = scheme_proper_list_length(argv[1]);
if (len < 0) {
scheme_wrong_contract(who, "list?", 1, argc, argv);
return NULL;
}
if (argc > 2)
none = argv[2];
else
none = scheme_false;
if (argc > 3) {
if (!SAME_TYPE(scheme_prompt_tag_type, SCHEME_TYPE(argv[3]))) {
if (SCHEME_NP_CHAPERONEP(argv[3])
&& SCHEME_PROMPT_TAGP(SCHEME_CHAPERONE_VAL(argv[3])))
prompt_tag = SCHEME_CHAPERONE_VAL(argv[3]);
else {
scheme_wrong_contract(who, "continuation-prompt-tag?",
3, argc, argv);
return NULL;
}
} else
prompt_tag = argv[3];
} else
prompt_tag = scheme_default_prompt_tag;
keys = MALLOC_N(Scheme_Object *, len);
for (pr = argv[1], i = 0; SCHEME_PAIRP(pr); pr = SCHEME_CDR(pr), i++) {
keys[i] = SCHEME_CAR(pr);
if ((keys[i] == scheme_parameterization_key)
|| (keys[i] == scheme_break_enabled_key)) {
scheme_signal_error("%s: misuse of primitive key", who);
return NULL;
}
}
chain = ((Scheme_Cont_Mark_Set *)argv[0])->chain;
if (iterator) {
void **clos, **state;
clos = MALLOC_N(void*, 4);
clos[0] = prompt_tag;
clos[1] = keys;
clos[2] = scheme_make_integer(len);
clos[3] = none;
state = MALLOC_N(void*, 2);
state[0] = chain;
state[1] = clos;
return scheme_make_closed_prim_w_arity(iterate_step, state, "mark-list*-iterator", 0, 0);
} else {
while (chain) {
vals = iterate_cc_markses(who, prompt_tag, none, len, keys, &chain);
if (vals) {
pr = scheme_make_pair(vals, scheme_null);
if (last)
SCHEME_CDR(last) = pr;
else
first = pr;
last = pr;
}
}
return first; return first;
} }
}
static Scheme_Object *
extract_cc_markses(int argc, Scheme_Object *argv[])
{
return do_extract_cc_markses("continuation-mark-set->list*", argc, argv, 0);
}
static Scheme_Object *
extract_cc_iterator(int argc, Scheme_Object *argv[])
{
return do_extract_cc_markses("continuation-mark-set->iterator", argc, argv, 1);
}
Scheme_Object * Scheme_Object *
scheme_get_stack_trace(Scheme_Object *mark_set) scheme_get_stack_trace(Scheme_Object *mark_set)

View File

@ -14,7 +14,7 @@
#define USE_COMPILED_STARTUP 1 #define USE_COMPILED_STARTUP 1
#define EXPECTED_PRIM_COUNT 1458 #define EXPECTED_PRIM_COUNT 1459
#ifdef MZSCHEME_SOMETHING_OMITTED #ifdef MZSCHEME_SOMETHING_OMITTED
# undef USE_COMPILED_STARTUP # undef USE_COMPILED_STARTUP

View File

@ -16,7 +16,7 @@
#define MZSCHEME_VERSION_X 7 #define MZSCHEME_VERSION_X 7
#define MZSCHEME_VERSION_Y 5 #define MZSCHEME_VERSION_Y 5
#define MZSCHEME_VERSION_Z 0 #define MZSCHEME_VERSION_Z 0
#define MZSCHEME_VERSION_W 6 #define MZSCHEME_VERSION_W 7
/* A level of indirection makes `#` work as needed: */ /* A level of indirection makes `#` work as needed: */
#define AS_a_STR_HELPER(x) #x #define AS_a_STR_HELPER(x) #x