fix continuation-barrier checking
Continuation-barrier checking was sometimes too strict, disallowing jumps out past a barrier (as opposed to into a barrier) that should be allowed.
This commit is contained in:
parent
fc77c91102
commit
544b7a3d53
|
@ -1475,10 +1475,12 @@
|
||||||
[exit-k #f])
|
[exit-k #f])
|
||||||
(let ([go
|
(let ([go
|
||||||
(lambda (launch)
|
(lambda (launch)
|
||||||
(let ([k (let/cc esc
|
(let ([k (call-with-continuation-barrier
|
||||||
(call-with-continuation-prompt
|
(lambda ()
|
||||||
(lambda ()
|
(let/cc esc
|
||||||
(dynamic-wind
|
(call-with-continuation-prompt
|
||||||
|
(lambda ()
|
||||||
|
(dynamic-wind
|
||||||
(lambda () (void))
|
(lambda () (void))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(with-handlers ([void (lambda (exn)
|
(with-handlers ([void (lambda (exn)
|
||||||
|
@ -1491,13 +1493,11 @@
|
||||||
(lambda () 10))
|
(lambda () 10))
|
||||||
p1))
|
p1))
|
||||||
(set! output (cons 'post output)))))
|
(set! output (cons 'post output)))))
|
||||||
p1))])
|
p1))))])
|
||||||
(call-with-continuation-barrier
|
(call-with-continuation-prompt
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(call-with-continuation-prompt
|
(exit-k (lambda () 'hi)))
|
||||||
(lambda ()
|
p1)))])
|
||||||
(exit-k (lambda () 'hi)))
|
|
||||||
p1)))))])
|
|
||||||
(err/rt-test
|
(err/rt-test
|
||||||
(go (lambda (esc) (esc 'middle)))
|
(go (lambda (esc) (esc 'middle)))
|
||||||
exn:fail:contract:continuation?)
|
exn:fail:contract:continuation?)
|
||||||
|
@ -1513,48 +1513,53 @@
|
||||||
exn:fail:contract:continuation?))
|
exn:fail:contract:continuation?))
|
||||||
(test '(post post post post) values output)))
|
(test '(post post post post) values output)))
|
||||||
|
|
||||||
;; Similar, but more checking of dropped d-ws:
|
;; Similar, but not a barrier error, because the jump
|
||||||
|
;; just escapes past a barrier instead of jumping into
|
||||||
|
;; one
|
||||||
(let ([p1 (make-continuation-prompt-tag 'p1)]
|
(let ([p1 (make-continuation-prompt-tag 'p1)]
|
||||||
[output null]
|
[output null]
|
||||||
[exit-k #f]
|
[exit-k #f]
|
||||||
[done? #f])
|
[count 3])
|
||||||
;; Capture a continuation w.r.t. the default prompt tag:
|
(let ([go
|
||||||
(call/cc
|
(lambda (launch)
|
||||||
(lambda (esc)
|
(let ([k (let/cc esc
|
||||||
(dynamic-wind
|
(call-with-continuation-prompt
|
||||||
(lambda () (void))
|
(lambda ()
|
||||||
(lambda ()
|
(dynamic-wind
|
||||||
;; Set a prompt for tag p1:
|
(lambda () (void))
|
||||||
(call-with-continuation-prompt
|
(lambda ()
|
||||||
(lambda ()
|
(with-handlers ([void (lambda (exn)
|
||||||
(dynamic-wind
|
(test #f "should not be used!" #t))])
|
||||||
(lambda () (void))
|
(launch esc)))
|
||||||
;; inside d-w, jump out:
|
(lambda ()
|
||||||
(lambda () (esc 'done))
|
((call/cc
|
||||||
(lambda ()
|
(lambda (k)
|
||||||
;; As we jump out, capture a continuation
|
(set! exit-k k)
|
||||||
;; w.r.t. p1:
|
(lambda () 10))
|
||||||
((call/cc
|
p1))
|
||||||
(lambda (k)
|
(set! output (cons 'post output)))))
|
||||||
(set! exit-k k)
|
p1))])
|
||||||
(lambda () 10))
|
(cond
|
||||||
p1))
|
[(zero? count) 'three]
|
||||||
(set! output (cons 'inner output)))))
|
[else
|
||||||
p1))
|
(set! count (sub1 count))
|
||||||
(lambda ()
|
(call-with-continuation-barrier
|
||||||
;; This post thunk is not in the
|
(lambda ()
|
||||||
;; delimited continuation captured
|
(call-with-continuation-prompt
|
||||||
;; via tag p1:
|
(lambda ()
|
||||||
(set! output (cons 'outer output))))))
|
(exit-k (lambda () 'hi)))
|
||||||
(unless done?
|
p1)))])))])
|
||||||
(set! done? #t)
|
(test 'three go (lambda (esc) (esc 'middle)))
|
||||||
;; Now invoke the delimited continuation, which must
|
(test '(post post post post) values output)
|
||||||
;; somehow continue the jump to `esc':
|
(let ([meta (call-with-continuation-prompt
|
||||||
(call-with-continuation-prompt
|
(lambda ()
|
||||||
(lambda ()
|
((call-with-composable-continuation
|
||||||
(exit-k (lambda () 10)))
|
(lambda (k) (lambda () k))))))])
|
||||||
p1))
|
(test 'three
|
||||||
(test '(inner outer inner) values output))
|
go (lambda (esc)
|
||||||
|
(meta
|
||||||
|
(lambda () (esc 'ok))))))
|
||||||
|
(test '(post post post post post) values output)))
|
||||||
|
|
||||||
;; Again, more checking of output
|
;; Again, more checking of output
|
||||||
(let ([p1 (make-continuation-prompt-tag 'p1)]
|
(let ([p1 (make-continuation-prompt-tag 'p1)]
|
||||||
|
@ -2014,14 +2019,24 @@
|
||||||
(k (lambda () 17)))
|
(k (lambda () 17)))
|
||||||
(test #t procedure? once-k)
|
(test #t procedure? once-k)
|
||||||
(test k values 17)
|
(test k values 17)
|
||||||
(err/rt-test (call-with-continuation-barrier
|
(err/rt-test (call-with-continuation-prompt
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(once-k 18)))
|
(call-with-continuation-barrier
|
||||||
exn:fail:contract:continuation?))
|
(lambda ()
|
||||||
|
(once-k 18)))))
|
||||||
|
(lambda (x)
|
||||||
|
(and (exn:fail:contract? x)
|
||||||
|
(not (exn:fail:contract:continuation? x))))))
|
||||||
|
(printf "Trying long chain under barrier...\n")
|
||||||
|
(let ([k (call-with-continuation-barrier
|
||||||
|
(lambda ()
|
||||||
|
(long-loop (lambda ()
|
||||||
|
((let/cc k (lambda () k)))))))])
|
||||||
|
(err/rt-test (k 18) exn:fail:contract:continuation?))
|
||||||
(printf "Trying long chain again...\n")
|
(printf "Trying long chain again...\n")
|
||||||
(let ([k (call-with-continuation-prompt
|
(let ([k (call-with-continuation-prompt
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(long-loop (lambda ()
|
(long-loop (lambda ()
|
||||||
((call-with-composable-continuation
|
((call-with-composable-continuation
|
||||||
(lambda (k)
|
(lambda (k)
|
||||||
(lambda () k))))))))])
|
(lambda () k))))))))])
|
||||||
|
|
|
@ -1544,7 +1544,7 @@ static Scheme_Prompt *check_barrier(Scheme_Prompt *prompt,
|
||||||
Scheme_Meta_Continuation *prompt_cont, MZ_MARK_POS_TYPE prompt_pos,
|
Scheme_Meta_Continuation *prompt_cont, MZ_MARK_POS_TYPE prompt_pos,
|
||||||
Scheme_Cont *c)
|
Scheme_Cont *c)
|
||||||
/* A continuation barrier is analogous to a dynamic-wind. A jump is
|
/* A continuation barrier is analogous to a dynamic-wind. A jump is
|
||||||
allowed if no dynamic-wind-like barriers would be executed for
|
allowed if no dynamic-wind-like pre-thunks would be executed for
|
||||||
the jump. */
|
the jump. */
|
||||||
{
|
{
|
||||||
Scheme_Prompt *barrier_prompt, *b1, *b2;
|
Scheme_Prompt *barrier_prompt, *b1, *b2;
|
||||||
|
@ -1566,8 +1566,8 @@ static Scheme_Prompt *check_barrier(Scheme_Prompt *prompt,
|
||||||
if (!b2->is_barrier)
|
if (!b2->is_barrier)
|
||||||
b2 = NULL;
|
b2 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b1 != b2) {
|
if (b2 && (b1 != b2)) {
|
||||||
scheme_raise_exn(MZEXN_FAIL_CONTRACT_CONTINUATION,
|
scheme_raise_exn(MZEXN_FAIL_CONTRACT_CONTINUATION,
|
||||||
"continuation application: attempt to cross a continuation barrier");
|
"continuation application: attempt to cross a continuation barrier");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user