Add prompt tag contracts using control proxies
This commit is contained in:
parent
d527426cac
commit
1cce922d97
|
@ -35,6 +35,8 @@
|
|||
none/c
|
||||
make-none/c
|
||||
|
||||
prompt/c
|
||||
|
||||
chaperone-contract?
|
||||
impersonator-contract?
|
||||
flat-contract?
|
||||
|
@ -943,6 +945,55 @@
|
|||
|
||||
(define/final-prop none/c (make-none/c 'none/c))
|
||||
|
||||
;; prompt/c
|
||||
(define/subexpression-pos-prop (prompt/c ctc-arg)
|
||||
(define ctc (coerce-contract 'prompt/c ctc-arg))
|
||||
(cond [(chaperone-contract? ctc) (chaperone-prompt/c ctc)]
|
||||
[else (impersonator-prompt/c ctc)]))
|
||||
|
||||
(define (prompt/c-name ctc)
|
||||
(build-compound-type-name 'prompt/c (base-prompt/c-ctc ctc)))
|
||||
|
||||
(define ((prompt/c-proj proxy) ctc)
|
||||
(define ho-proj (contract-projection (base-prompt/c-ctc ctc)))
|
||||
(λ (blame)
|
||||
(define proj1 (ho-proj blame))
|
||||
(define proj2 (ho-proj (blame-swap blame)))
|
||||
(λ (val)
|
||||
(unless (contract-first-order-passes? ctc val)
|
||||
(raise-blame-error
|
||||
blame val
|
||||
'(expected: "~s," given: "~e")
|
||||
(contract-name ctc)
|
||||
val))
|
||||
(proxy val proj1 proj2))))
|
||||
|
||||
(define ((prompt/c-first-order ctc) v)
|
||||
(continuation-prompt-tag? v))
|
||||
|
||||
(define (prompt/c-stronger? this that)
|
||||
(and (base-prompt/c? that)
|
||||
(contract-stronger? (base-prompt/c-ctc this)
|
||||
(base-prompt/c-ctc that))))
|
||||
|
||||
(define-struct base-prompt/c (ctc))
|
||||
|
||||
(define-struct (chaperone-prompt/c base-prompt/c) ()
|
||||
#:property prop:chaperone-contract
|
||||
(build-chaperone-contract-property
|
||||
#:projection (prompt/c-proj chaperone-prompt-tag)
|
||||
#:first-order prompt/c-first-order
|
||||
#:stronger prompt/c-stronger?
|
||||
#:name prompt/c-name))
|
||||
|
||||
(define-struct (impersonator-prompt/c base-prompt/c) ()
|
||||
#:property prop:contract
|
||||
(build-contract-property
|
||||
#:projection (prompt/c-proj impersonate-prompt-tag)
|
||||
#:first-order prompt/c-first-order
|
||||
#:stronger prompt/c-stronger?
|
||||
#:name prompt/c-name))
|
||||
|
||||
|
||||
(define (flat-contract-predicate x)
|
||||
(contract-struct-first-order
|
||||
|
|
|
@ -4044,6 +4044,106 @@
|
|||
(for ([(k v) (in-hash h)])
|
||||
(hash-ref k v))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; prompt/c
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(test/spec-passed
|
||||
'prompt/c-fo-1
|
||||
'(contract (prompt/c string?)
|
||||
(make-continuation-prompt-tag)
|
||||
'pos 'neg))
|
||||
|
||||
(test/pos-blame
|
||||
'prompt/c-fo-2
|
||||
'(contract (prompt/c string?) 5 'pos 'neg))
|
||||
|
||||
(test/spec-passed
|
||||
'prompt/c-ho-1
|
||||
'(let ([pt (contract (prompt/c number?)
|
||||
(make-continuation-prompt-tag)
|
||||
'pos
|
||||
'neg)])
|
||||
(call-with-continuation-prompt
|
||||
(λ () (abort-current-continuation pt 3))
|
||||
pt
|
||||
(λ (x) (+ x 1)))))
|
||||
|
||||
(test/neg-blame
|
||||
'prompt/c-ho-2
|
||||
'(let ([pt (contract (prompt/c string?)
|
||||
(make-continuation-prompt-tag)
|
||||
'pos
|
||||
'neg)])
|
||||
(call-with-continuation-prompt
|
||||
(λ () (abort-current-continuation pt 3))
|
||||
pt
|
||||
(λ (x) (+ x 1)))))
|
||||
|
||||
(test/neg-blame
|
||||
'prompt/c-ho-3
|
||||
'(let ([pt (contract (prompt/c (-> string? number?))
|
||||
(make-continuation-prompt-tag)
|
||||
'pos
|
||||
'neg)])
|
||||
(call-with-continuation-prompt
|
||||
(λ () (abort-current-continuation pt (λ (x) 5)))
|
||||
pt
|
||||
(λ (x) (x 8)))))
|
||||
|
||||
(test/neg-blame
|
||||
'prompt/c-ho-4
|
||||
'(let ([pt (contract (prompt/c (-> string? number?))
|
||||
(make-continuation-prompt-tag)
|
||||
'pos
|
||||
'neg)])
|
||||
(call-with-continuation-prompt
|
||||
(λ () (abort-current-continuation pt (λ (x) "bad")))
|
||||
pt
|
||||
(λ (x) (x "potato")))))
|
||||
|
||||
(test/pos-blame
|
||||
'prompt/c-ho-5
|
||||
'(let* ([pt (make-continuation-prompt-tag)]
|
||||
[do-prompt (contract
|
||||
(-> (-> (prompt/c (-> number? number?))
|
||||
any)
|
||||
number?)
|
||||
(λ (f) (call-with-continuation-prompt
|
||||
(λ () (f pt))
|
||||
pt
|
||||
(λ (f) (f "bad"))))
|
||||
'pos
|
||||
'neg)])
|
||||
(do-prompt (λ (pt)
|
||||
(abort-current-continuation pt (λ (v) (+ v 1)))))))
|
||||
|
||||
(test/spec-failed
|
||||
'prompt/c-ho-5
|
||||
'(let* ([pt (make-continuation-prompt-tag)]
|
||||
[do-prompt (contract
|
||||
(-> (-> (prompt/c (-> number? number?))
|
||||
any)
|
||||
number?)
|
||||
(λ (f) (call-with-continuation-prompt
|
||||
(λ () (f pt))
|
||||
pt
|
||||
(λ (f) (f 0))))
|
||||
'A
|
||||
'B)]
|
||||
[do-prompt2 (contract
|
||||
(-> (-> (prompt/c (-> string? number?))
|
||||
any)
|
||||
number?)
|
||||
do-prompt
|
||||
'B
|
||||
'C)])
|
||||
(do-prompt2
|
||||
(λ (pt) (abort-current-continuation pt (λ (v) (+ v 1))))))
|
||||
"B")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; make-contract
|
||||
|
|
Loading…
Reference in New Issue
Block a user