On 2012-10-16 15:27:46 -0400, mflatt at racket-lang.org wrote:
> 843c722 Matthew Flatt <mflatt at racket-lang.org> 2012-10-16 15:10
> :
> | add an argument to `{chaperone,impersonate}-prompt-tag'
> |
> | The new argument gets to filter results that come from a
> | non-composable continuation that replaces one delimited
> | by a prompt using the chaperoned/impersonated prompt tag.
Thanks. One thing I noticed is that I don't think this is quite enough
to build contracts that provide full protection for `call/cc`. Let me
demonstrate with an example:
;; -----------------------------------------------
;; In this "component", we define a prompt tag
;; and install a prompt. We call `abort-k` which
;; is an unknown function imported from the other
;; component.
#lang racket
(define pt (make-continuation-prompt-tag))
(define (do-test)
(+ 1
(call-with-continuation-prompt
(lambda ()
(+ 1 (abort-k 1)))
pt)))
;; We export the prompt tag with a chaperone
;; that checks that the values we get from a
;; `call/cc` are numbers as we expect.
(define ipt
(chaperone-prompt-tag
pt
values values
(lambda (x)
(if (number? x) x
(error "wrong type")))))
;; component boundary -------------
;; In this component, we build an `abort-k`
;; that sends a string to the prompt.
;;
;; Note that it uses the chaperoned prompt tag
(define abort-k
(call-with-continuation-prompt
(lambda ()
(let ([v ; client side uses impersonation
(call/cc (lambda (k) k) ipt)])
(if (procedure? v)
v
(format "~a" v))))
ipt))
;; component boundary -------------
;; This raises an exception because the chaperone
;; on the `call/cc` side is not triggered. Only
;; the prompt side will ever trigger.
(do-test)
;; -----------------------------------------------
The summary is that I think we need to do the `call/cc`
redirection on both sides: the prompt *and* the caller of
the aborting continuation.
Cheers,
Asumu