add and use late-neg projections to the contract system

These avoid one layer of currying and are more efficient, getting
about a 1.3x speed up on this program:

 #lang racket/base
(module server racket/base
  (require racket/contract/base)
  (provide
   (contract-out
    [f (-> integer? boolean? char? void?)]))
  (define (f i b c) (void)))

(require (submod "." server))

(time
  (for ([x (in-range 10000000)])
    (f 1 #t #\x)))
This commit is contained in:
Robby Findler 2015-08-31 20:30:17 -05:00
parent f09c78b5f4
commit 13964c4141
12 changed files with 570 additions and 507 deletions

View File

@ -1831,7 +1831,11 @@ accepted by the third argument to @racket[datum->syntax].
@defproc[(make-contract
[#:name name any/c 'anonymous-contract]
[#:first-order test (-> any/c any/c) (λ (x) #t)]
[#:val-first-projection
[#:late-neg-projection
late-neg-proj
(or/c #f (-> blame? (-> any/c any/c any/c)))
#f]
[#:val-first-projection
val-first-proj
(or/c #f (-> blame? (-> any/c (-> any/c any/c))))
#f]
@ -1852,6 +1856,10 @@ accepted by the third argument to @racket[datum->syntax].
@defproc[(make-chaperone-contract
[#:name name any/c 'anonymous-chaperone-contract]
[#:first-order test (-> any/c any/c) (λ (x) #t)]
[#:late-neg-projection
late-neg-proj
(or/c #f (-> blame? (-> any/c any/c any/c)))
#f]
[#:val-first-projection
val-first-proj
(or/c #f (-> blame? (-> any/c (-> any/c any/c))))
@ -1873,6 +1881,10 @@ accepted by the third argument to @racket[datum->syntax].
@defproc[(make-flat-contract
[#:name name any/c 'anonymous-flat-contract]
[#:first-order test (-> any/c any/c) (λ (x) #t)]
[#:late-neg-projection
late-neg-proj
(or/c #f (-> blame? (-> any/c any/c any/c)))
#f]
[#:val-first-projection
val-first-proj
(or/c #f (-> blame? (-> any/c (-> any/c any/c))))
@ -1893,12 +1905,6 @@ accepted by the third argument to @racket[datum->syntax].
flat-contract?]
)]{
@italic{The precise details of the
@racket[val-first-projection] argument
are subject to change. (Probably
also the default values of the @racket[project]
arguments will change.}
These functions build simple higher-order contracts, chaperone contracts, and flat contracts,
respectively. They both take the same set of three optional arguments: a name,
a first-order predicate, and a blame-tracking projection.
@ -1916,13 +1922,25 @@ by @racket[contract-first-order-passes?], and indirectly by @racket[or/c] to
determine which of multiple higher-order contracts to wrap a value with. The
default test accepts any value.
The projection @racket[proj] defines the behavior of applying the contract. It
The @racket[late-neg-proj] defines the behavior of applying the contract. If it is
supplied, it accepts a blame object that does not have a value for
the @racket[blame-negative] field. Then it must return a function that accepts
both the value that is getting the contract and the name of the blame party, in
that order. The result must either be the value (perhaps suitably wrapped
with a @tech{chaperone} or @tech{impersonator} to enforce the contract), or
signal a contract violation using @racket[raise-blame-error]. The default is
@racket[#f].
The projection @racket[proj] and @racket[val-first-proj] are older mechanisms for
defining the behavior of applying the contract. The @racket[proj] argument
is a curried function of two arguments: the first application accepts a blame
object, and the second accepts a value to protect with the contract. The
projection must either produce the value, suitably wrapped to enforce any
higher-order aspects of the contract, or signal a contract violation using
@racket[raise-blame-error]. The default projection produces an error when the
first-order test fails, and produces the value unchanged otherwise.
The @racket[val-first-proj] is like @racket[late-neg-proj], except with
an extra layer of currying.
Projections for chaperone contracts must produce a value that passes
@racket[chaperone-of?] when compared with the original, uncontracted value.
@ -2274,6 +2292,10 @@ is expected to be the blame record for the contract on the value).
get-first-order
(-> contract? (-> any/c boolean?))
(λ (c) (λ (x) #t))]
[#:late-neg-projection
late-neg-proj
(or/c #f (-> contract? (-> blame? (-> any/c any/c any/c))))
#f]
[#:val-first-projection
val-first-proj
(or/c #f (-> contract? blame? (-> any/c (-> any/c any/c))))
@ -2323,6 +2345,10 @@ is expected to be the blame record for the contract on the value).
get-first-order
(-> contract? (-> any/c boolean?))
(λ (c) (λ (x) #t))]
[#:late-neg-projection
late-neg-proj
(or/c #f (-> contract? blame? (-> any/c any/c any/c)))
#f]
[#:val-first-projection
val-first-proj
(or/c #f (-> contract? blame? (-> any/c (-> any/c any/c))))
@ -2372,6 +2398,10 @@ is expected to be the blame record for the contract on the value).
get-first-order
(-> contract? (-> any/c boolean?))
(λ (c) (λ (x) #t))]
[#:late-neg-projection
late-neg-proj
(or/c #f (-> contract? blame? (-> any/c any/c any/c)))
#f]
[#:val-first-projection
val-first-proj
(or/c #f (-> contract? blame? (-> any/c (-> any/c any/c))))

View File

@ -195,6 +195,12 @@
(λ (neg-party)
((blame-accepting-proj (blame-add-missing-party blame neg-party)) val))
(->i-mk-val-first-wrapper ctc)))))
#:late-neg-projection
(λ (ctc)
(define blame-accepting-proj (arr->i-proj ctc))
(λ (blame)
(λ (val neg-party)
((blame-accepting-proj (blame-add-missing-party blame neg-party)) val))))
#:projection arr->i-proj
#:name (λ (ctc)
(define (arg/ress->spec infos ctcs dep-ctcs skip?)

View File

@ -163,7 +163,7 @@
(list
(with-syntax ([rng-len (length rngs)])
(with-syntax ([rng-results
#'(values ((rng-ctc rng-x) neg-party)
#'(values (rng-ctc rng-x neg-party)
...)])
#'(case-lambda
[(rng-x ...)
@ -185,7 +185,7 @@
[opt-keywords (map (λ (p) (syntax-e (car p))) opt-kwds)]
[need-apply-values? (or dom-rest (not (null? opt-doms)))]
[no-rng-checking? (not rngs)])
(with-syntax ([(dom-projd-args ...) #'(((dom-ctc dom-x) neg-party) ...)]
(with-syntax ([(dom-projd-args ...) #'((dom-ctc dom-x neg-party) ...)]
[basic-params
(cond
[dom-rest
@ -197,10 +197,10 @@
[else
#'(this-param ... dom-x ... [opt-dom-x arrow:unspecified-dom] ...)])]
[opt+rest-uses
(for/fold ([i (if dom-rest #'((rest-ctc rest-x) neg-party) #'null)])
(for/fold ([i (if dom-rest #'(rest-ctc rest-x neg-party) #'null)])
([o (in-list (reverse
(syntax->list
#'(((opt-dom-ctc opt-dom-x) neg-party) ...))))]
#'((opt-dom-ctc opt-dom-x neg-party) ...))))]
[opt-dom-x (in-list (reverse (syntax->list #'(opt-dom-x ...))))])
#`(let ([r #,i])
(if (eq? arrow:unspecified-dom #,opt-dom-x) r (cons #,o r))))]
@ -214,7 +214,7 @@
[kwd-stx
(let* ([req-stxs
(map (λ (s) (λ (r) #`(cons #,s #,r)))
(syntax->list #'(((req-kwd-ctc req-kwd-x) neg-party) ...)))]
(syntax->list #'((req-kwd-ctc req-kwd-x neg-party) ...)))]
[opt-stxs
(map (λ (x c) (λ (r) #`(maybe-cons-kwd #,c #,x #,r neg-party)))
(syntax->list #'(opt-kwd-x ...))
@ -348,40 +348,42 @@
(define (maybe-cons-kwd c x r neg-party)
(if (eq? arrow:unspecified-dom x)
r
(cons ((c x) neg-party) r)))
(cons (c x neg-party) r)))
(define (->-proj chaperone-or-impersonate-procedure ctc
;; fields of the 'ctc' struct
min-arity doms kwd-infos rest pre? rngs post?
plus-one-arity-function chaperone-constructor)
(define doms-proj (map get/build-val-first-projection doms))
(define rest-proj (and rest (get/build-val-first-projection rest)))
(define rngs-proj (if rngs (map get/build-val-first-projection rngs) '()))
(define kwds-proj
(for/list ([kwd-info (in-list kwd-infos)])
(get/build-val-first-projection (kwd-info-ctc kwd-info))))
plus-one-arity-function chaperone-constructor
late-neg?)
(define optionals-length (- (length doms) min-arity))
(define mtd? #f) ;; not yet supported for the new contracts
(λ (orig-blame)
(define rng-blame (arrow:blame-add-range-context orig-blame))
(define swapped-domain (blame-add-context orig-blame "the domain of" #:swap? #t))
(define partial-doms
(for/list ([dom (in-list doms-proj)]
(define partial-doms
(for/list ([dom (in-list doms)]
[n (in-naturals 1)])
(dom (blame-add-context orig-blame
(format "the ~a argument of" (n->th n))
#:swap? #t))))
(define partial-rest (and rest-proj
(rest-proj
((get/build-late-neg-projection dom)
(blame-add-context orig-blame
(format "the ~a argument of" (n->th n))
#:swap? #t))))
(define partial-rest (and rest
((get/build-late-neg-projection rest)
(blame-add-context orig-blame "the rest argument of"
#:swap? #t))))
(define partial-ranges (map (λ (rng) (rng rng-blame)) rngs-proj))
(define partial-ranges
(if rngs
(for/list ([rng (in-list rngs)])
((get/build-late-neg-projection rng) rng-blame))
'()))
(define partial-kwds
(for/list ([kwd-proj (in-list kwds-proj)]
(for/list ([kwd-info (in-list kwd-infos)]
[kwd (in-list kwd-infos)])
(kwd-proj (blame-add-context orig-blame
(format "the ~a argument of" (kwd-info-kwd kwd))
#:swap? #t))))
((get/build-late-neg-projection (kwd-info-ctc kwd-info))
(blame-add-context orig-blame
(format "the ~a argument of" (kwd-info-kwd kwd))
#:swap? #t))))
(define man-then-opt-partial-kwds
(append (for/list ([partial-kwd (in-list partial-kwds)]
[kwd-info (in-list kwd-infos)]
@ -401,27 +403,42 @@
man-then-opt-partial-kwds
partial-ranges
(if partial-rest (list partial-rest) '())))
(λ (val)
(wrapped-extra-arg-arrow
(cond
[(do-arity-checking orig-blame val doms rest min-arity kwd-infos)
=>
values]
[else
(λ (neg-party)
(define chap/imp-func (apply chaperone-constructor orig-blame val neg-party the-args))
(if post?
(chaperone-or-impersonate-procedure
val
chap/imp-func
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party orig-blame neg-party))
(chaperone-or-impersonate-procedure
val
chap/imp-func
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party orig-blame neg-party)
impersonator-prop:application-mark (cons arrow:contract-key
;; is this right?
partial-ranges))))])
(apply plus-one-arity-function orig-blame val plus-one-constructor-args)))))
(define (successfully-got-the-right-kind-of-function val neg-party)
(define chap/imp-func (apply chaperone-constructor orig-blame val neg-party the-args))
(if post?
(chaperone-or-impersonate-procedure
val
chap/imp-func
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party orig-blame neg-party))
(chaperone-or-impersonate-procedure
val
chap/imp-func
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party orig-blame neg-party)
impersonator-prop:application-mark (cons arrow:contract-key
;; is this right?
partial-ranges))))
(cond
[late-neg?
(λ (val neg-party)
(cond
[(do-arity-checking orig-blame val doms rest min-arity kwd-infos)
=>
(λ (f)
(f neg-party))]
[else
(successfully-got-the-right-kind-of-function val neg-party)]))]
[else
(λ (val)
(wrapped-extra-arg-arrow
(cond
[(do-arity-checking orig-blame val doms rest min-arity kwd-infos)
=>
values]
[else
(λ (neg-party)
(successfully-got-the-right-kind-of-function val neg-party))])
(apply plus-one-arity-function orig-blame val plus-one-constructor-args)))])))

View File

@ -179,7 +179,7 @@
[(res-x ...) (generate-temporaries (or rngs '()))]
[(kwd-arg-x ...) (generate-temporaries mandatory-kwds)])
(define base-arg-expressions (reverse (syntax->list #'(((regb arg-x) neg-party) ...))))
(define base-arg-expressions (reverse (syntax->list #'((regb arg-x neg-party) ...))))
(define normal-arg-vars (generate-temporaries #'(arg-x ...)))
(define base-arg-vars normal-arg-vars)
@ -190,7 +190,7 @@
append
(map (λ (kwd kwd-arg-x kb)
(set! base-arg-expressions
(cons #`((#,kb #,kwd-arg-x) neg-party)
(cons #`(#,kb #,kwd-arg-x neg-party)
base-arg-expressions))
(set! base-arg-vars (cons (car (generate-temporaries (list kwd-arg-x)))
base-arg-vars))
@ -228,7 +228,7 @@
#,@(for/list ([ob (in-list (reverse ob))]
[optional-arg (in-list (reverse optional-args))])
(set! args-expressions
(cons #`((#,ob #,optional-arg) neg-party)
(cons #`(#,ob #,optional-arg neg-party)
args-expressions))
(set! args-vars
(cons (car (generate-temporaries (list optional-arg)))
@ -237,7 +237,7 @@
(define full-call
(cond
[(and first? rest)
(set! args-expressions (cons #'((restb rest-arg) neg-party) args-expressions))
(set! args-expressions (cons #'(restb rest-arg neg-party) args-expressions))
(set! args-vars (cons (car (generate-temporaries '(rest-args-arrow-contract)))
args-vars))
#`(apply #,@no-rest-call #,(car args-vars))]
@ -281,7 +281,9 @@
#'(res-x ...))))]
[else
post-check ...
(values ((rb res-x) neg-party) ...)])))]
(values
(rb res-x neg-party)
...)])))]
#`[#,the-args
pre-check ...
(let ([blame+neg-party (cons blame neg-party)])
@ -340,7 +342,7 @@
(cond
[(and (pair? mandatory-kwds)
(equal? (car mandatory-kwds) kwd))
(cons (((car kbs) kwd-arg) neg-party)
(cons ((car kbs) kwd-arg neg-party)
(loop (cdr kwds)
(cdr kwd-args)
(cdr mandatory-kwds)
@ -349,7 +351,7 @@
okbs))]
[(and (pair? optional-kwds)
(equal? (car optional-kwds) kwd))
(cons (((car okbs) kwd-arg) neg-party)
(cons ((car okbs) kwd-arg neg-party)
(loop (cdr kwds)
(cdr kwd-args)
mandatory-kwds
@ -368,9 +370,9 @@
[rbs rbs])
(cond
[(null? regular-args) '()]
[(null? rbs) ((rest-ctc regular-args) neg-party)]
[(null? rbs) (rest-ctc regular-args neg-party)]
[else
(cons (((car rbs) (car regular-args)) neg-party)
(cons ((car rbs) (car regular-args) neg-party)
(loop (cdr regular-args) (cdr rbs)))]))))
(define complete-blame (blame-add-missing-party blame neg-party))
(when pre (check-pre-cond pre blame neg-party f))
@ -385,7 +387,7 @@
values
(for/list ([result (in-list results)]
[rng (in-list rngs)])
((rng result) neg-party)))]
(rng result neg-party)))]
[else
(mk-call)]))))
@ -908,16 +910,16 @@
(define kwd-results
(for/list ([kwd (in-list kwds)]
[kwd-arg (in-list kwd-args)])
(((hash-ref kwd-table kwd) kwd-arg) neg-party)))
((hash-ref kwd-table kwd) kwd-arg neg-party)))
(define regular-arg-results
(let loop ([args args]
[projs mandatory+optional-dom-projs])
(cond
[(and (null? projs) (null? args)) '()]
[(null? projs)
((rest-proj args) neg-party)]
(rest-proj args neg-party)]
[(null? args) (error 'cant-happen::dynamic->*)]
[else (cons (((car projs) (car args)) neg-party)
[else (cons ((car projs) (car args) neg-party)
(loop (cdr args) (cdr projs)))])))
(define (result-checker . results)
(unless (= rng-len (length results))
@ -926,7 +928,7 @@
values
(for/list ([res (in-list results)]
[neg-party-proj (in-list rng-projs)])
((neg-party-proj res) neg-party))))
(neg-party-proj res neg-party))))
(define args-dealt-with
(if (null? kwds)
regular-arg-results
@ -1132,7 +1134,7 @@
#t))
(define (make-property build-X-property chaperone-or-impersonate-procedure)
(define proj
(define val-first-proj
(λ (->stct)
(->-proj chaperone-or-impersonate-procedure ->stct
(base->-min-arity ->stct)
@ -1143,14 +1145,28 @@
(base->-rngs ->stct)
(base->-post? ->stct)
(base->-plus-one-arity-function ->stct)
(base->-chaperone-constructor ->stct))))
(base->-chaperone-constructor ->stct)
#f)))
(define late-neg-proj
(λ (->stct)
(->-proj chaperone-or-impersonate-procedure ->stct
(base->-min-arity ->stct)
(base->-doms ->stct)
(base->-kwd-infos ->stct)
(base->-rest ->stct)
(base->-pre? ->stct)
(base->-rngs ->stct)
(base->-post? ->stct)
(base->-plus-one-arity-function ->stct)
(base->-chaperone-constructor ->stct)
#t)))
(parameterize ([skip-projection-wrapper? #t])
(build-X-property
#:name base->-name
#:first-order ->-first-order
#:projection
(λ (this)
(define cthis (proj this))
(define cthis (val-first-proj this))
(λ (blame)
(define cblame (cthis blame))
(λ (val)
@ -1180,7 +1196,8 @@
(not (base->-post? that))))
#:generate ->-generate
#:exercise ->-exercise
#:val-first-projection proj)))
#:val-first-projection val-first-proj
#:late-neg-projection late-neg-proj)))
(define-struct (-> base->) ()
#:property
@ -1207,11 +1224,11 @@
(λ () (f))
(case-lambda
[(rng)
(unless (void? rng)
(raise-blame-error blame #:missing-party neg-party rng
'(expected: "void?" given: "~e")
rng))
rng]
(if (void? rng)
rng
(raise-blame-error blame #:missing-party neg-party rng
'(expected: "void?" given: "~e")
rng))]
[args
(wrong-number-of-results-blame blame neg-party f args 1)]))))
(get-chaperone-constructor))))

View File

@ -51,7 +51,7 @@
(define (apply-contract c v pos neg name loc)
(let ([c (coerce-contract 'contract c)])
(check-source-location! 'contract loc)
(define cvfp (contract-val-first-projection c))
(define clnp (contract-late-neg-projection c))
(define blame
(make-blame (build-source-location loc)
name
@ -65,10 +65,10 @@
;; instead of changing the library around.
(or pos "false")
(if cvfp #f neg)
(if clnp #f neg)
#t))
(cond
[cvfp (((cvfp blame) v) neg)]
[clnp ((clnp blame) v neg)]
[else (((contract-projection c) blame) v)])))
(define-syntax (invariant-assertion stx)

View File

@ -111,18 +111,19 @@
#:name box/c-name
#:first-order box/c-first-order
#:stronger box/c-stronger
#:val-first-projection
#:late-neg-projection
(λ (ctc)
(define content-ctc (get/build-val-first-projection (base-box/c-content ctc)))
(define content-ctc (get/build-late-neg-projection (base-box/c-content ctc)))
(λ (blame)
(define box-blame (add-box-context blame))
(define val-first-proj (content-ctc box-blame))
(λ (val)
(define fail-proc (check-box/c-np ctc val blame))
(or fail-proc
(λ (neg-party)
((val-first-proj (unbox val)) neg-party)
val)))))
(define late-neg-proj (content-ctc box-blame))
(λ (val neg-party)
(define fail-proc (check-box/c-np ctc val box-blame))
(cond
[fail-proc (fail-proc neg-party)]
[else
(late-neg-proj (unbox val) neg-party)
val]))))
#:projection
(λ (ctc)
(λ (blame)
@ -148,26 +149,29 @@
impersonator-prop:contracted ctc
impersonator-prop:blame blame))))))))
(define (ho-val-first-projection chaperone/impersonate-box)
(define (ho-late-neg-projection chaperone/impersonate-box)
(λ (ctc)
(define elem-ctc (base-box/c-content ctc))
(define immutable (base-box/c-immutable ctc))
(define vfp (get/build-val-first-projection elem-ctc))
(define vfp (get/build-late-neg-projection elem-ctc))
(λ (blame)
(define box-blame (add-box-context blame))
(define pos-elem-proj (vfp box-blame))
(define neg-elem-proj (vfp (blame-swap box-blame)))
(λ (val)
(or (check-box/c-np ctc val blame)
(if (and (immutable? val) (not (chaperone? val)))
(λ (neg-party) (box-immutable ((pos-elem-proj (unbox val)) neg-party)))
(λ (neg-party)
(chaperone/impersonate-box
val
(λ (b v) ((pos-elem-proj v) neg-party))
(λ (b v) ((neg-elem-proj v) neg-party))
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party blame neg-party)))))))))
(λ (val neg-party)
(cond
[(check-box/c-np ctc val blame)
=>
(λ (f) (f neg-party))]
[else
(if (and (immutable? val) (not (chaperone? val)))
(box-immutable (pos-elem-proj (unbox val) neg-party))
(chaperone/impersonate-box
val
(λ (b v) (pos-elem-proj v neg-party))
(λ (b v) (neg-elem-proj v neg-party))
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party blame neg-party)))])))))
(define-struct (chaperone-box/c base-box/c) ()
#:property prop:custom-write custom-write-property-proc
@ -176,7 +180,7 @@
#:name box/c-name
#:first-order box/c-first-order
#:stronger box/c-stronger
#:val-first-projection (ho-val-first-projection chaperone-box)
#:late-neg-projection (ho-late-neg-projection chaperone-box)
#:projection (ho-projection chaperone-box)))
(define-struct (impersonator-box/c base-box/c) ()
@ -186,7 +190,7 @@
#:name box/c-name
#:first-order box/c-first-order
#:stronger box/c-stronger
#:val-first-projection (ho-val-first-projection impersonate-box)
#:late-neg-projection (ho-late-neg-projection impersonate-box)
#:projection (ho-projection impersonate-box)))
(define-syntax (wrap-box/c stx)

View File

@ -544,22 +544,18 @@
(predicate-contract-pred that))))
#:name (λ (ctc) (predicate-contract-name ctc))
#:first-order (λ (ctc) (predicate-contract-pred ctc))
#:val-first-projection
#:late-neg-projection
(λ (ctc)
(define p? (predicate-contract-pred ctc))
(define name (predicate-contract-name ctc))
(λ (blame)
(let ([predicate-contract-proj
(λ (v)
(if (p? v)
(λ (neg-party)
v)
(λ (neg-party)
(raise-blame-error blame v #:missing-party neg-party
'(expected: "~s" given: "~e")
name
v))))])
predicate-contract-proj)))
(λ (v neg-party)
(if (p? v)
v
(raise-blame-error blame v #:missing-party neg-party
'(expected: "~s" given: "~e")
name
v)))))
#:generate (λ (ctc)
(let ([generate (predicate-contract-generate ctc)])
(cond

View File

@ -188,7 +188,7 @@
#:name hash/c-name
#:first-order hash/c-first-order
#:stronger hash/c-stronger
#:val-first-projection
#:late-neg-projection
(λ (ctc)
(define dom-ctc (base-hash/c-dom ctc))
(define immutable (base-hash/c-immutable ctc))
@ -198,38 +198,36 @@
(blame-add-key-context blame #f)))
(define rng-proj ((contract-projection (base-hash/c-rng ctc))
(blame-add-value-context blame #f)))
(λ (val)
(λ (neg-party)
(cond
[(check-hash/c dom-ctc immutable flat? val blame neg-party)
val]
[else
(for ([(k v) (in-hash val)])
(dom-proj k)
(rng-proj v))
val])))))))
(λ (val neg-party)
(cond
[(check-hash/c dom-ctc immutable flat? val blame neg-party)
val]
[else
(for ([(k v) (in-hash val)])
(dom-proj k)
(rng-proj v))
val]))))))
(define (ho-projection chaperone-or-impersonate-hash)
(λ (ctc)
(define immutable (base-hash/c-immutable ctc))
(define dom-ctc (base-hash/c-dom ctc))
(define flat? (flat-hash/c? ctc))
(define dom-proc (get/build-val-first-projection dom-ctc))
(define rng-proc (get/build-val-first-projection (base-hash/c-rng ctc)))
(define dom-proc (get/build-late-neg-projection dom-ctc))
(define rng-proc (get/build-late-neg-projection (base-hash/c-rng ctc)))
(λ (blame)
(define pos-dom-proj (dom-proc (blame-add-key-context blame #f)))
(define neg-dom-proj (dom-proc (blame-add-key-context blame #t)))
(define pos-rng-proj (rng-proc (blame-add-value-context blame #f)))
(define neg-rng-proj (rng-proc (blame-add-value-context blame #t)))
(λ (val)
(λ (neg-party)
(cond
[(check-hash/c dom-ctc immutable flat? val blame neg-party)
val]
[else
(handle-the-hash val neg-party
pos-dom-proj neg-dom-proj (λ (v) pos-rng-proj) (λ (v) neg-rng-proj)
chaperone-or-impersonate-hash ctc blame)]))))))
(λ (val neg-party)
(cond
[(check-hash/c dom-ctc immutable flat? val blame neg-party)
val]
[else
(handle-the-hash val neg-party
pos-dom-proj neg-dom-proj (λ (v) pos-rng-proj) (λ (v) neg-rng-proj)
chaperone-or-impersonate-hash ctc blame)])))))
(define (blame-add-key-context blame swap?) (blame-add-context blame "the keys of" #:swap? swap?))
(define (blame-add-value-context blame swap?) (blame-add-context blame "the values of" #:swap? swap?))
@ -240,21 +238,21 @@
(if (immutable? val)
(for/fold ([h val]) ([(k v) (in-hash val)])
(hash-set h
((pos-dom-proj k) neg-party)
(((mk-pos-rng-proj k) v) neg-party)))
(pos-dom-proj k neg-party)
((mk-pos-rng-proj k) v neg-party)))
(chaperone-or-impersonate-hash
val
(λ (h k)
(values ((neg-dom-proj k) neg-party)
(values (neg-dom-proj k neg-party)
(λ (h k v)
(((mk-pos-rng-proj k) v) neg-party))))
((mk-pos-rng-proj k) v neg-party))))
(λ (h k v)
(values ((neg-dom-proj k) neg-party)
(((mk-neg-rng-proj k) v) neg-party)))
(values (neg-dom-proj k neg-party)
((mk-neg-rng-proj k) v neg-party)))
(λ (h k)
((neg-dom-proj k) neg-party))
(neg-dom-proj k neg-party))
(λ (h k)
((pos-dom-proj k) neg-party))
(pos-dom-proj k neg-party))
impersonator-prop:contracted ctc
impersonator-prop:blame blame)))
@ -266,7 +264,7 @@
#:name hash/c-name
#:first-order hash/c-first-order
#:stronger hash/c-stronger
#:val-first-projection (ho-projection chaperone-hash)))
#:late-neg-projection (ho-projection chaperone-hash)))
(define-struct (impersonator-hash/c base-hash/c) ()
#:omit-define-syntaxes
@ -276,7 +274,7 @@
#:name hash/c-name
#:first-order hash/c-first-order
#:stronger hash/c-stronger
#:val-first-projection (ho-projection impersonate-hash)))
#:late-neg-projection (ho-projection impersonate-hash)))
(define (hash/dc-name a-hash-dc)
@ -305,11 +303,11 @@
(define (hash/dc-stronger this that) #f)
(define ((hash/dc-val-first-projection chaperone-or-impersonate-hash) ctc)
(define ((hash/dc-late-neg-projection chaperone-or-impersonate-hash) ctc)
(define dom-ctc (base-hash/dc-dom ctc))
(define immutable (base-hash/dc-immutable ctc))
(define flat? (flat-hash/dc? ctc))
(define dom-proc (get/build-val-first-projection dom-ctc))
(define dom-proc (get/build-late-neg-projection dom-ctc))
(define dep-rng-proc (base-hash/dc-dep-rng ctc))
(λ (blame)
(define pos-dom-proj (dom-proc (blame-add-key-context blame #f)))
@ -319,18 +317,17 @@
(base-hash/dc-here ctc))))
(define pos-value-blame (blame-add-value-context blame #f))
(define neg-value-blame (blame-add-value-context blame #t))
(λ (val)
(λ (neg-party)
(cond
[(check-hash/c dom-ctc immutable flat? val blame neg-party) val]
[else
(define ((mk-rng-proj x-value-blame) key)
((get/build-val-first-projection (dep-rng-proc ((indy-dom-proj key) neg-party)))
x-value-blame))
(handle-the-hash val neg-party
pos-dom-proj neg-dom-proj
(mk-rng-proj pos-value-blame) (mk-rng-proj neg-value-blame)
chaperone-or-impersonate-hash ctc blame)])))))
(λ (val neg-party)
(cond
[(check-hash/c dom-ctc immutable flat? val blame neg-party) val]
[else
(define ((mk-rng-proj x-value-blame) key)
((get/build-late-neg-projection (dep-rng-proc (indy-dom-proj key neg-party)))
x-value-blame))
(handle-the-hash val neg-party
pos-dom-proj neg-dom-proj
(mk-rng-proj pos-value-blame) (mk-rng-proj neg-value-blame)
chaperone-or-impersonate-hash ctc blame)]))))
(struct base-hash/dc (dom dep-rng here name-info immutable))
(struct flat-hash/dc base-hash/dc ()
@ -348,7 +345,7 @@
#:name hash/dc-name
#:first-order hash/dc-first-order
#:stronger hash/dc-stronger
#:val-first-projection (hash/dc-val-first-projection chaperone-hash)))
#:late-neg-projection (hash/dc-late-neg-projection chaperone-hash)))
(struct impersonator-hash/dc base-hash/dc ()
#:property prop:custom-write custom-write-property-proc
#:property prop:contract
@ -356,7 +353,7 @@
#:name hash/dc-name
#:first-order hash/dc-first-order
#:stronger hash/dc-stronger
#:val-first-projection (hash/dc-val-first-projection impersonate-hash)))
#:late-neg-projection (hash/dc-late-neg-projection impersonate-hash)))
(define (build-hash/dc dom dep-rng here name-info immutable kind)
(unless (member kind '(flat chaperone impersonator))

View File

@ -54,7 +54,9 @@
contract-projection
contract-val-first-projection ;; might return #f (if none)
contract-late-neg-projection ;; might return #f (if none)
get/build-val-first-projection ;; builds one if necc., using contract-projection
get/build-late-neg-projection
contract-name
n->th
@ -113,22 +115,21 @@
([p (in-list (cdr projs))])
(λ (v) (p (proj v)))))))
(define (val-first-and-proj ctc)
(define mk-pos-projs (map get/build-val-first-projection (base-and/c-ctcs ctc)))
(define (late-neg-and-proj ctc)
(define mk-pos-projs (map get/build-late-neg-projection (base-and/c-ctcs ctc)))
(λ (blame)
(define projs
(define projs
(for/list ([c (in-list mk-pos-projs)]
[n (in-naturals 1)])
(c (blame-add-context blame (format "the ~a conjunct of" (n->th n))))))
(λ (val)
(λ (neg-party)
(let loop ([projs (cdr projs)]
[val (((car projs) val) neg-party)])
(cond
[(null? projs) val]
[else
(loop (cdr projs)
(((car projs) val) neg-party))]))))))
(λ (val neg-party)
(let loop ([projs (cdr projs)]
[val ((car projs) val neg-party)])
(cond
[(null? projs) val]
[else
(loop (cdr projs)
((car projs) val neg-party))])))))
(define (first-order-and-proj ctc)
(λ (blame)
@ -146,23 +147,23 @@
(define new-blame (blame-add-context blame "an and/c case of"))
((ctc1-proj new-blame) val)])])))))
(define (first-order-val-first-and-proj ctc)
(define (first-order-late-neg-and-proj ctc)
(define predicates (first-order-and/c-predicates ctc))
(define ctcs (base-and/c-ctcs ctc))
(define blame-accepters (map get/build-late-neg-projection (base-and/c-ctcs ctc)))
(λ (blame)
(λ (val)
(define new-blame (blame-add-context blame "an and/c case of"))
(define projs (map (λ (f) (f new-blame)) blame-accepters))
(λ (val neg-party)
(let loop ([predicates predicates]
[ctcs ctcs])
[projs projs])
(cond
[(null? predicates) (λ (neg-party) val)]
[(null? predicates) val]
[else
(cond
[((car predicates) val)
(loop (cdr predicates) (cdr ctcs))]
(loop (cdr predicates) (cdr projs))]
[else
(define ctc1-val-first-proj (get/build-val-first-projection (car ctcs)))
(define new-blame (blame-add-context blame "an and/c case of"))
((ctc1-val-first-proj new-blame) val)])])))))
((car projs) val neg-party)])])))))
(define (and-stronger? this that)
(and (base-and/c? that)
@ -264,7 +265,7 @@
#:property prop:flat-contract
(build-flat-contract-property
#:projection first-order-and-proj
#:val-first-projection first-order-val-first-and-proj
#:late-neg-projection first-order-late-neg-and-proj
#:name and-name
#:first-order and-first-order
#:stronger and-stronger?
@ -275,7 +276,7 @@
(parameterize ([skip-projection-wrapper? #t])
(build-chaperone-contract-property
#:projection and-proj
#:val-first-projection val-first-and-proj
#:late-neg-projection late-neg-and-proj
#:name and-name
#:first-order and-first-order
#:stronger and-stronger?
@ -285,7 +286,7 @@
#:property prop:contract
(build-contract-property
#:projection and-proj
#:val-first-projection val-first-and-proj
#:late-neg-projection late-neg-and-proj
#:name and-name
#:first-order and-first-order
#:stronger and-stronger?
@ -708,8 +709,8 @@
(elem-proj+blame x))
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) #f))))])))
(define (listof-val-first-projection ctc)
(define elem-proj (get/build-val-first-projection (listof-ctc-elem-c ctc)))
(define (listof-late-neg-projection ctc)
(define elem-proj (get/build-late-neg-projection (listof-ctc-elem-c ctc)))
(define pred? (if (pe-listof-ctc? ctc)
list?
non-empty-list?))
@ -718,49 +719,45 @@
(cond
[(flat-listof-ctc? ctc)
(if (im-listof-ctc? ctc)
(λ (val)
(λ (neg-party)
(let loop ([val val])
(cond
[(pair? val)
((elem-proj+blame (car val)) neg-party)
(loop (cdr val))]
[else
((elem-proj+blame val) neg-party)]))
val))
(λ (val)
(if (pred? val)
(λ (neg-party)
(for ([x (in-list val)])
((elem-proj+blame x) neg-party))
val)
(λ (neg-party)
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party)))))]
(λ (val neg-party)
(let loop ([val val])
(cond
[(pair? val)
(elem-proj+blame (car val) neg-party)
(loop (cdr val))]
[else
(elem-proj+blame val neg-party)]))
val)
(λ (val neg-party)
(cond
[(pred? val)
(for ([x (in-list val)])
(elem-proj+blame x neg-party))
val]
[else
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party)])))]
[else
(if (im-listof-ctc? ctc)
(λ (val)
(λ (neg-party)
(let loop ([val val])
(cond
[(pair? val)
(cons ((elem-proj+blame (car val)) neg-party)
(loop (cdr val)))]
[else
((elem-proj+blame val) neg-party)]))))
(λ (val)
(if (pred? val)
(λ (neg-party)
(for/list ([x (in-list val)])
((elem-proj+blame x) neg-party)))
(λ (neg-party)
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party)))))])))
(if (im-listof-ctc? ctc)
(λ (val neg-party)
(let loop ([val val])
(cond
[(pair? val)
(cons (elem-proj+blame (car val) neg-party)
(loop (cdr val)))]
[else
(elem-proj+blame val neg-party)])))
(λ (val neg-party)
(if (pred? val)
(for/list ([x (in-list val)])
(elem-proj+blame x neg-party))
(raise-listof-blame-error blame val (pe-listof-ctc? ctc) neg-party))))])))
(define flat-prop
(build-flat-contract-property
#:name list-name
#:first-order list-fo-check
#:projection listof-projection
#:val-first-projection listof-val-first-projection
#:late-neg-projection listof-late-neg-projection
#:generate listof-generate
#:exercise listof-exercise
#:stronger listof-stronger
@ -770,7 +767,7 @@
#:name list-name
#:first-order list-fo-check
#:projection listof-projection
#:val-first-projection listof-val-first-projection
#:late-neg-projection listof-late-neg-projection
#:generate listof-generate
#:exercise listof-exercise
#:stronger listof-stronger
@ -780,7 +777,7 @@
#:name list-name
#:first-order list-fo-check
#:projection listof-projection
#:val-first-projection listof-val-first-projection
#:late-neg-projection listof-late-neg-projection
#:generate listof-generate
#:exercise listof-exercise
#:stronger listof-stronger
@ -875,21 +872,20 @@
(define (blame-add-cdr-context blame) (blame-add-context blame "the cdr of"))
(define ((cons/c-val-first-ho-check combine) ctc)
(define ((cons/c-late-neg-ho-check combine) ctc)
(define ctc-car (the-cons/c-hd-ctc ctc))
(define ctc-cdr (the-cons/c-tl-ctc ctc))
(define car-val-first-proj (get/build-val-first-projection ctc-car))
(define cdr-val-first-proj (get/build-val-first-projection ctc-cdr))
(define car-late-neg-proj (get/build-late-neg-projection ctc-car))
(define cdr-late-neg-proj (get/build-late-neg-projection ctc-cdr))
(λ (blame)
(define car-p (car-val-first-proj (blame-add-car-context blame)))
(define cdr-p (cdr-val-first-proj (blame-add-cdr-context blame)))
(λ (v)
(λ (neg-party)
(unless (pair? v)
(raise-not-cons-blame-error blame #:missing-party neg-party v))
(combine v
((car-p (car v)) neg-party)
((cdr-p (cdr v)) neg-party))))))
(define car-p (car-late-neg-proj (blame-add-car-context blame)))
(define cdr-p (cdr-late-neg-proj (blame-add-cdr-context blame)))
(λ (v neg-party)
(unless (pair? v)
(raise-not-cons-blame-error blame #:missing-party neg-party v))
(combine v
(car-p (car v) neg-party)
(cdr-p (cdr v) neg-party)))))
(define ((cons/c-ho-check combine) ctc)
(define ctc-car (the-cons/c-hd-ctc ctc))
@ -959,7 +955,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:flat-contract
(build-flat-contract-property
#:val-first-projection (cons/c-val-first-ho-check (λ (v a d) v))
#:late-neg-projection (cons/c-late-neg-ho-check (λ (v a d) v))
#:projection (cons/c-ho-check (λ (v a d) v))
#:name cons/c-name
#:first-order cons/c-first-order
@ -971,7 +967,7 @@
#:property prop:chaperone-contract
(parameterize ([skip-projection-wrapper? #t])
(build-chaperone-contract-property
#:val-first-projection (cons/c-val-first-ho-check (λ (v a d) (cons a d)))
#:late-neg-projection (cons/c-late-neg-ho-check (λ (v a d) (cons a d)))
#:projection (cons/c-ho-check (λ (v a d) (cons a d)))
#:name cons/c-name
#:first-order cons/c-first-order
@ -982,7 +978,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:contract
(build-contract-property
#:val-first-projection (cons/c-val-first-ho-check (λ (v a d) (cons a d)))
#:late-neg-projection (cons/c-late-neg-ho-check (λ (v a d) (cons a d)))
#:projection (cons/c-ho-check (λ (v a d) (cons a d)))
#:name cons/c-name
#:first-order cons/c-first-order
@ -1001,8 +997,8 @@
[else
(impersonator-cons/c ctc-car ctc-cdr)]))
(define (cons/dc-val-first-projection ctc)
(define undep-proj (get/build-val-first-projection (the-cons/dc-undep ctc)))
(define (cons/dc-late-neg-projection ctc)
(define undep-proj (get/build-late-neg-projection (the-cons/dc-undep ctc)))
(define dep-proc (the-cons/dc-dep ctc))
(define forwards? (the-cons/dc-forwards? ctc))
(λ (blame)
@ -1013,28 +1009,26 @@
(undep-proj (blame-replace-negative
(if forwards? cdr-blame car-blame)
(the-cons/dc-here ctc))))
(λ (val)
(λ (val neg-party)
(cond
[(pair? val)
(λ (neg-party)
(define-values (orig-undep orig-dep)
(if forwards?
(values (car val) (cdr val))
(values (cdr val) (car val))))
(define new-undep ((undep-proj+blame orig-undep) neg-party))
(define new-dep-ctc (coerce-contract
'cons/dc
(dep-proc ((undep-proj+indy-blame orig-undep) neg-party))))
(define new-dep ((((get/build-val-first-projection new-dep-ctc)
(if forwards? cdr-blame car-blame))
orig-dep)
neg-party))
(define-values (orig-undep orig-dep)
(if forwards?
(cons new-undep new-dep)
(cons new-dep new-undep)))]
(values (car val) (cdr val))
(values (cdr val) (car val))))
(define new-undep (undep-proj+blame orig-undep neg-party))
(define new-dep-ctc (coerce-contract
'cons/dc
(dep-proc (undep-proj+indy-blame orig-undep neg-party))))
(define new-dep (((get/build-late-neg-projection new-dep-ctc)
(if forwards? cdr-blame car-blame))
orig-dep
neg-party))
(if forwards?
(cons new-undep new-dep)
(cons new-dep new-undep))]
[else
(λ (neg-party)
(raise-not-cons-blame-error blame val #:missing-party neg-party))]))))
(raise-not-cons-blame-error blame val #:missing-party neg-party)]))))
(define (cons/dc-name ctc)
(define info (the-cons/dc-name-info ctc))
@ -1079,7 +1073,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:flat-contract
(build-flat-contract-property
#:val-first-projection cons/dc-val-first-projection
#:late-neg-projection cons/dc-late-neg-projection
#:name cons/dc-name
#:first-order cons/dc-first-order
#:stronger cons/dc-stronger?
@ -1089,7 +1083,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:chaperone-contract
(build-chaperone-contract-property
#:val-first-projection cons/dc-val-first-projection
#:late-neg-projection cons/dc-late-neg-projection
#:name cons/dc-name
#:first-order cons/dc-first-order
#:stronger cons/dc-stronger?
@ -1099,7 +1093,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:contract
(build-contract-property
#:val-first-projection cons/dc-val-first-projection
#:late-neg-projection cons/dc-late-neg-projection
#:name cons/dc-name
#:first-order cons/dc-first-order
#:stronger cons/dc-stronger?
@ -1240,37 +1234,34 @@
#:generate list/c-generate
#:exercise list/c-exercise
#:stronger list/c-stronger
#:val-first-projection
#:late-neg-projection
(λ (c)
(λ (blame)
(λ (blame)
(define projs
(for/list ([ctc (in-list (generic-list/c-args c))]
[i (in-naturals 1)])
((get/build-val-first-projection ctc)
((get/build-late-neg-projection ctc)
(add-list-context blame i))))
(define expected-length (length (generic-list/c-args c)))
(λ (val)
(define args (generic-list/c-args c))
(define expected-length (length args))
(λ (val neg-party)
(cond
[(list? val)
(define args (generic-list/c-args c))
(define actual-length (length val))
(cond
[(= actual-length expected-length)
(λ (neg-party)
(for ([proj (in-list projs)]
[ele (in-list val)])
((proj ele) neg-party))
val)]
(for ([proj (in-list projs)]
[ele (in-list val)])
(proj ele neg-party))
val]
[else
(λ (neg-party)
(expected-a-list-of-len val actual-length expected-length blame
#:missing-party neg-party))])]
(expected-a-list-of-len val actual-length expected-length blame
#:missing-party neg-party)])]
[else
(λ (neg-party)
(raise-blame-error blame #:missing-party neg-party
val
'(expected "a list" given: "~e")
val))]))))
(raise-blame-error blame #:missing-party neg-party
val
'(expected "a list" given: "~e")
val)]))))
#:projection
(lambda (c)
(lambda (blame)
@ -1327,30 +1318,27 @@
(if (= actual 1) "" "s")
x)])))
(define (list/c-chaperone/other-val-first-projection c)
(define projs (map get/build-val-first-projection (generic-list/c-args c)))
(define (list/c-chaperone/other-late-neg-projection c)
(define projs (map get/build-late-neg-projection (generic-list/c-args c)))
(define expected (length projs))
(λ (blame)
(define p-apps (for/list ([proj (in-list projs)]
[i (in-naturals 1)])
(proj (add-list-context blame i))))
(λ (val)
(λ (val neg-party)
(cond
[(list? val)
(define actual (length val))
(cond
[(= actual expected)
(λ (neg-party)
(for/list ([item (in-list val)]
[p-app (in-list p-apps)])
((p-app item) neg-party)))]
(for/list ([item (in-list val)]
[p-app (in-list p-apps)])
(p-app item neg-party))]
[else
(λ (neg-party)
(expected-a-list-of-len val actual expected blame
#:missing-party neg-party))])]
(expected-a-list-of-len val actual expected blame
#:missing-party neg-party)])]
[else
(λ (neg-party)
(expected-a-list val blame #:missing-party neg-party))]))))
(expected-a-list val blame #:missing-party neg-party)]))))
(define (add-list-context blame i)
(blame-add-context blame (format "the ~a~a element of"
@ -1372,7 +1360,7 @@
#:exercise list/c-exercise
#:stronger list/c-stronger
#:projection list/c-chaperone/other-projection
#:val-first-projection list/c-chaperone/other-val-first-projection
#:late-neg-projection list/c-chaperone/other-late-neg-projection
#:list-contract? (λ (c) #t))))
(struct higher-order-list/c generic-list/c ()
@ -1385,7 +1373,7 @@
#:exercise list/c-exercise
#:stronger list/c-stronger
#:projection list/c-chaperone/other-projection
#:val-first-projection list/c-chaperone/other-val-first-projection
#:late-neg-projection list/c-chaperone/other-late-neg-projection
#:list-contract? (λ (c) #t)))
(struct syntax-ctc (ctc)
@ -1416,30 +1404,28 @@
[else
(promise-ctc ctc)])))
(define (promise-contract-val-first-proj ctc)
(define (promise-contract-late-neg-proj ctc)
(define chap? (chaperone-promise-ctc? ctc))
(define c/i-struct (if chap? chaperone-struct impersonate-struct))
(define c/i-procedure (if chap? chaperone-procedure impersonate-procedure))
(define ctc-proc (get/build-val-first-projection (promise-base-ctc-ctc ctc)))
(define ctc-proc (get/build-late-neg-projection (promise-base-ctc-ctc ctc)))
(λ (blame)
(define p-app (ctc-proc (blame-add-context blame "the promise from")))
(λ (val)
(λ (val neg-party)
(if (promise? val)
(λ (neg-party)
(c/i-struct
val
promise-forcer
(λ (_ proc)
(c/i-procedure
proc
(λ (promise)
(values (λ (val) ((p-app val) neg-party)) promise))))))
(λ (neg-party)
(raise-blame-error
blame #:missing-party neg-party
val
'(expected: "<promise>" given: "~e")
val))))))
(c/i-struct
val
promise-forcer
(λ (_ proc)
(c/i-procedure
proc
(λ (promise)
(values (λ (val) (p-app val neg-party)) promise)))))
(raise-blame-error
blame #:missing-party neg-party
val
'(expected: "<promise>" given: "~e")
val)))))
(define (promise-contract-name ctc)
(build-compound-type-name 'promise/c (promise-base-ctc-ctc ctc)))
@ -1455,7 +1441,7 @@
#:property prop:chaperone-contract
(build-chaperone-contract-property
#:name promise-contract-name
#:val-first-projection promise-contract-val-first-proj
#:late-neg-projection promise-contract-late-neg-proj
#:stronger promise-ctc-stronger?
#:first-order (λ (ctc) promise?)))
(struct promise-ctc promise-base-ctc ()
@ -1463,7 +1449,7 @@
#:property prop:contract
(build-contract-property
#:name promise-contract-name
#:val-first-projection promise-contract-val-first-proj
#:late-neg-projection promise-contract-late-neg-proj
#:stronger promise-ctc-stronger?
#:first-order (λ (ctc) promise?)))
@ -1509,31 +1495,29 @@
partial-pos-contract)]
[else
(raise-blame-error blame val '(expected "a parameter"))])))))
#:val-first-projection
#:late-neg-projection
(λ (ctc)
(define in-proc (contract-projection (parameter/c-in ctc)))
(define out-proc (contract-projection (parameter/c-out ctc)))
(define in-proc (get/build-late-neg-projection (parameter/c-in ctc)))
(define out-proc (get/build-late-neg-projection (parameter/c-out ctc)))
(λ (blame)
(define blame/c (blame-add-context blame "the parameter of"))
(define swapped (blame-swap blame/c))
(λ (val)
(define in-proj (in-proc (blame-swap blame/c)))
(define out-proj (out-proc blame/c))
(λ (val neg-party)
(cond
[(parameter? val)
(λ (neg-party)
(define (add-profiling f)
(λ (x)
(with-continuation-mark contract-continuation-mark-key
(cons blame neg-party)
(f x))))
(make-derived-parameter
val
;; unfortunately expensive
(add-profiling (in-proc (blame-add-missing-party swapped neg-party)))
(add-profiling (out-proc (blame-add-missing-party blame/c neg-party)))))]
(define (add-profiling f)
(λ (x)
(with-continuation-mark contract-continuation-mark-key
(cons blame/c neg-party)
(f x neg-party))))
(make-derived-parameter
val
(add-profiling in-proj)
(add-profiling out-proj))]
[else
(λ (neg-party)
(raise-blame-error blame #:missing-party neg-party
val '(expected "a parameter")))]))))
(raise-blame-error blame #:missing-party neg-party
val '(expected "a parameter"))]))))
#:name
(λ (ctc) (apply build-compound-type-name
@ -1584,7 +1568,7 @@
(define (get-any? c) any?)
(define (any? x) #t)
(define any/c-neg-party-fn (λ (val) (λ (neg-party) val)))
(define any/c-neg-party-fn (λ (val neg-party) val))
(define (random-any/c env fuel)
(define env-hash (contract-random-generate-env-hash env))
@ -1624,7 +1608,7 @@
#:property prop:flat-contract
(build-flat-contract-property
#:projection get-any-projection
#:val-first-projection (λ (ctc) (λ (blame) any/c-neg-party-fn))
#:late-neg-projection (λ (ctc) (λ (blame) any/c-neg-party-fn))
#:stronger (λ (this that) (any/c? that))
#:name (λ (ctc) 'any/c)
#:generate (λ (ctc)
@ -1648,7 +1632,7 @@
(none/c-name ctc)
val))))
(define ((((none-curried-val-first-proj ctc) blame) val) neg-party)
(define (((none-curried-late-neg-proj ctc) blame) val neg-party)
(raise-blame-error
blame #:missing-party neg-party
val
@ -1662,7 +1646,7 @@
#:property prop:flat-contract
(build-flat-contract-property
#:projection none-curried-proj
#:val-first-projection none-curried-val-first-proj
#:late-neg-projection none-curried-late-neg-proj
#:stronger (λ (this that) #t)
#:name (λ (ctc) (none/c-name ctc))
#:first-order (λ (ctc) (λ (val) #f))))
@ -1731,52 +1715,51 @@
impersonator-prop:contracted ctc
impersonator-prop:blame blame))))
(define ((prompt-tag/c-val-first-proj chaperone?) ctc)
(define ((prompt-tag/c-late-neg-proj chaperone?) ctc)
(define proxy (if chaperone? chaperone-prompt-tag impersonate-prompt-tag))
(define proc-proxy (if chaperone? chaperone-procedure impersonate-procedure))
(define ho-projs
(map get/build-val-first-projection (base-prompt-tag/c-ctcs ctc)))
(map get/build-late-neg-projection (base-prompt-tag/c-ctcs ctc)))
(define call/cc-projs
(map get/build-val-first-projection (base-prompt-tag/c-call/ccs ctc)))
(map get/build-late-neg-projection (base-prompt-tag/c-call/ccs ctc)))
(λ (blame)
(define swapped (blame-swap blame))
(define ho-neg-projs (for/list ([proj (in-list ho-projs)]) (proj swapped)))
(define ho-pos-projs (for/list ([proj (in-list ho-projs)]) (proj blame)))
(define cc-neg-projs (for/list ([proj (in-list call/cc-projs)]) (proj swapped)))
(define cc-pos-projs (for/list ([proj (in-list call/cc-projs)]) (proj blame)))
(λ (val)
(define (make-proj projs neg-party)
(λ vs
(define vs2 (for/list ([proj projs] [v vs])
((proj v) neg-party)))
(apply values vs2)))
(define (make-proj projs neg-party)
(λ vs
(apply values
(for/list ([proj (in-list projs)]
[v (in-list vs)])
(proj v neg-party)))))
(λ (val neg-party)
;; now do the actual wrapping
(cond
[(continuation-prompt-tag? val)
(λ (neg-party)
;; prompt/abort projections
(define proj1 (make-proj ho-pos-projs neg-party))
(define proj2 (make-proj ho-neg-projs neg-party))
;; call/cc projections
(define call/cc-guard (make-proj cc-pos-projs neg-party))
(define call/cc-proxy
(λ (f)
(proc-proxy
f
(λ args
(apply values (make-proj cc-neg-projs neg-party) args)))))
(proxy val
proj1 proj2
call/cc-guard call/cc-proxy
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party blame neg-party)))]
;; prompt/abort projections
(define proj1 (make-proj ho-pos-projs neg-party))
(define proj2 (make-proj ho-neg-projs neg-party))
;; call/cc projections
(define call/cc-guard (make-proj cc-pos-projs neg-party))
(define call/cc-proxy
(λ (f)
(proc-proxy
f
(λ args
(apply values (make-proj cc-neg-projs neg-party) args)))))
(proxy val
proj1 proj2
call/cc-guard call/cc-proxy
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party blame neg-party))]
[else
(λ (neg-party)
(raise-blame-error
blame #:missing-party neg-party val
'(expected: "~s" given: "~e")
(contract-name ctc)
val))]))))
(raise-blame-error
blame #:missing-party neg-party val
'(expected: "~s" given: "~e")
(contract-name ctc)
val)]))))
(define (prompt-tag/c-stronger? this that)
(and (base-prompt-tag/c? that)
@ -1794,7 +1777,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:chaperone-contract
(build-chaperone-contract-property
#:val-first-projection (prompt-tag/c-val-first-proj #t)
#:late-neg-projection (prompt-tag/c-late-neg-proj #t)
#:projection (prompt-tag/c-proj #t)
#:first-order (λ (ctc) continuation-prompt-tag?)
#:stronger prompt-tag/c-stronger?
@ -1804,7 +1787,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:contract
(build-contract-property
#:val-first-projection (prompt-tag/c-val-first-proj #f)
#:late-neg-projection (prompt-tag/c-late-neg-proj #f)
#:projection (prompt-tag/c-proj #f)
#:first-order (λ (ctc) continuation-prompt-tag?)
#:stronger prompt-tag/c-stronger?
@ -1841,31 +1824,29 @@
impersonator-prop:contracted ctc
impersonator-prop:blame blame))))
(define ((continuation-mark-key/c-val-first-proj proxy) ctc)
(define ((continuation-mark-key/c-late-neg-proj proxy) ctc)
(define ho-proj
(get/build-val-first-projection (base-continuation-mark-key/c-ctc ctc)))
(get/build-late-neg-projection (base-continuation-mark-key/c-ctc ctc)))
(λ (blame)
(define swapped (blame-swap blame))
(define proj1 (ho-proj blame))
(define proj2 (ho-proj (blame-swap blame)))
(λ (val)
(λ (val neg-party)
(cond
[(continuation-mark-key? val)
(λ (neg-party)
(proxy val
(λ (v) ((proj1 v) neg-party))
(λ (v) ((proj2 v) neg-party))
impersonator-prop:contracted ctc
impersonator-prop:blame blame))]
(proxy val
(λ (v) (proj1 v neg-party))
(λ (v) (proj2 v neg-party))
impersonator-prop:contracted ctc
impersonator-prop:blame blame)]
[else
(λ (neg-party)
(unless (contract-first-order-passes? ctc val)
(raise-blame-error
blame #:missing-party neg-party
val
'(expected: "~s" given: "~e")
(contract-name ctc)
val)))]))))
(unless (contract-first-order-passes? ctc val)
(raise-blame-error
blame #:missing-party neg-party
val
'(expected: "~s" given: "~e")
(contract-name ctc)
val))]))))
(define (continuation-mark-key/c-stronger? this that)
(and (base-continuation-mark-key/c? that)
@ -1881,7 +1862,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:chaperone-contract
(build-chaperone-contract-property
#:val-first-projection (continuation-mark-key/c-val-first-proj chaperone-continuation-mark-key)
#:late-neg-projection (continuation-mark-key/c-late-neg-proj chaperone-continuation-mark-key)
#:projection (continuation-mark-key/c-proj chaperone-continuation-mark-key)
#:first-order (λ (ctc) continuation-mark-key?)
#:stronger continuation-mark-key/c-stronger?
@ -1893,7 +1874,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:contract
(build-contract-property
#:val-first-projection (continuation-mark-key/c-val-first-proj impersonate-continuation-mark-key)
#:late-neg-projection (continuation-mark-key/c-late-neg-proj impersonate-continuation-mark-key)
#:projection (continuation-mark-key/c-proj impersonate-continuation-mark-key)
#:first-order (λ (ctc) continuation-mark-key?)
#:stronger continuation-mark-key/c-stronger?
@ -1995,30 +1976,28 @@
impersonator-prop:contracted ctc
impersonator-prop:blame blame))))
(define ((channel/c-val-first-proj proxy) ctc)
(define ((channel/c-late-neg-proj proxy) ctc)
(define ho-proj
(get/build-val-first-projection (base-channel/c-ctc ctc)))
(get/build-late-neg-projection (base-channel/c-ctc ctc)))
(λ (blame)
(define pos-proj (ho-proj blame))
(define neg-proj (ho-proj (blame-swap blame)))
(define (proj1 neg-party) (λ (ch) (values ch (λ (v) ((pos-proj v) neg-party)))))
(define (proj2 neg-party) (λ (ch v) ((neg-proj v) neg-party)))
(λ (val)
(define (proj1 neg-party) (λ (ch) (values ch (λ (v) (pos-proj v neg-party)))))
(define (proj2 neg-party) (λ (ch v) (neg-proj v neg-party)))
(λ (val neg-party)
(cond
[(channel? val)
(λ (neg-party)
(proxy val
(proj1 neg-party)
(proj2 neg-party)
impersonator-prop:contracted ctc
impersonator-prop:blame blame))]
(proxy val
(proj1 neg-party)
(proj2 neg-party)
impersonator-prop:contracted ctc
impersonator-prop:blame blame)]
[else
(λ (neg-party)
(raise-blame-error
blame #:missing-party neg-party
val '(expected: "~s" given: "~e")
(contract-name ctc)
val))]))))
(raise-blame-error
blame #:missing-party neg-party
val '(expected: "~s" given: "~e")
(contract-name ctc)
val)]))))
(define (channel/c-first-order ctc) channel?)
@ -2035,7 +2014,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:chaperone-contract
(build-chaperone-contract-property
#:val-first-projection (channel/c-val-first-proj chaperone-channel)
#:late-neg-projection (channel/c-late-neg-proj chaperone-channel)
#:projection (channel/c-proj chaperone-channel)
#:first-order channel/c-first-order
#:stronger channel/c-stronger?
@ -2046,7 +2025,7 @@
#:property prop:custom-write custom-write-property-proc
#:property prop:contract
(build-contract-property
#:val-first-projection (channel/c-val-first-proj impersonate-channel)
#:late-neg-projection (channel/c-late-neg-proj impersonate-channel)
#:projection (channel/c-proj impersonate-channel)
#:first-order channel/c-first-order
#:stronger channel/c-stronger?
@ -2086,6 +2065,9 @@
(define (contract-val-first-projection ctc)
(contract-struct-val-first-projection
(coerce-contract 'contract-projection ctc)))
(define (contract-late-neg-projection ctc)
(contract-struct-late-neg-projection
(coerce-contract 'contract-projection ctc)))
(define (get/build-val-first-projection ctc)
(or (contract-struct-val-first-projection ctc)
@ -2097,6 +2079,14 @@
((p (blame-add-missing-party blme neg-party)) val)))
(string->symbol (format "val-first: ~s" (contract-name ctc))))))))
(define (get/build-late-neg-projection ctc)
(or (contract-struct-late-neg-projection ctc)
(let ([p (contract-projection ctc)])
(λ (blme)
(procedure-rename
(λ (val neg-party)
((p (blame-add-missing-party blme neg-party)) val))
(string->symbol (format "late-neg: ~s" (contract-name ctc))))))))
(define (flat-contract predicate) (coerce-flat-contract 'flat-contract predicate))
(define (flat-named-contract name pre-contract [generate #f])

View File

@ -68,15 +68,15 @@
[(pred val) val]
[else (partial-contract val)])))))
(define (single-or/c-val-first-projection ctc)
(define c-proj (get/build-val-first-projection (single-or/c-ho-ctc ctc)))
(define (single-or/c-late-neg-projection ctc)
(define c-proj (get/build-late-neg-projection (single-or/c-ho-ctc ctc)))
(define pred (single-or/c-pred ctc))
(λ (blame)
(define p-app (c-proj (blame-add-or-context blame)))
(λ (val)
(λ (val neg-party)
(if (pred val)
(λ (neg-party) val)
(p-app val)))))
val
(p-app val neg-party)))))
(define (blame-add-or-context blame)
(blame-add-context blame "a part of the or/c of"))
@ -200,7 +200,7 @@
(parameterize ([skip-projection-wrapper? #t])
(build-chaperone-contract-property
#:projection single-or/c-projection
#:val-first-projection single-or/c-val-first-projection
#:late-neg-projection single-or/c-late-neg-projection
#:name single-or/c-name
#:first-order single-or/c-first-order
#:stronger single-or/c-stronger?
@ -215,7 +215,7 @@
#:property prop:contract
(build-contract-property
#:projection single-or/c-projection
#:val-first-projection single-or/c-val-first-projection
#:late-neg-projection single-or/c-late-neg-projection
#:name single-or/c-name
#:first-order single-or/c-first-order
#:stronger single-or/c-stronger?
@ -273,21 +273,22 @@
candidate-proc
candidate-contract)]))])))))
(define (multi-or/c-val-first-proj ctc)
(define (multi-or/c-late-neg-proj ctc)
(define ho-contracts (multi-or/c-ho-ctcs ctc))
(define c-projs (map get/build-val-first-projection ho-contracts))
(define c-projs (map get/build-late-neg-projection ho-contracts))
(define first-order-checks (map (λ (x) (contract-first-order x)) ho-contracts))
(define predicates (map flat-contract-predicate (multi-or/c-flat-ctcs ctc)))
(λ (blame)
(define blame-w-context (blame-add-or-context blame))
(λ (val)
(define c-projs+blame (map (λ (c-proj) (c-proj blame-w-context)) c-projs))
(λ (val neg-party)
(cond
[(for/or ([pred (in-list predicates)])
(pred val))
(λ (neg-party) val)]
val]
[else
(let loop ([checks first-order-checks]
[c-projs c-projs]
[c-projs c-projs+blame]
[contracts ho-contracts]
[candidate-c-proj #f]
[candidate-contract #f])
@ -295,22 +296,20 @@
[(null? checks)
(cond
[candidate-c-proj
((candidate-c-proj blame-w-context) val)]
(candidate-c-proj val neg-party)]
[else
(λ (neg-party)
(raise-blame-error blame val #:missing-party neg-party
'("none of the branches of the or/c matched" given: "~e")
val))])]
(raise-blame-error blame val #:missing-party neg-party
'("none of the branches of the or/c matched" given: "~e")
val)])]
[((car checks) val)
(if candidate-c-proj
(λ (neg-party)
(raise-blame-error blame val #:missing-party neg-party
'("two of the clauses in the or/c might both match: ~s and ~s"
given:
"~e")
(contract-name candidate-contract)
(contract-name (car contracts))
val))
(raise-blame-error blame val #:missing-party neg-party
'("two of the clauses in the or/c might both match: ~s and ~s"
given:
"~e")
(contract-name candidate-contract)
(contract-name (car contracts))
val)
(loop (cdr checks)
(cdr c-projs)
(cdr contracts)
@ -359,7 +358,7 @@
(parameterize ([skip-projection-wrapper? #t])
(build-chaperone-contract-property
#:projection multi-or/c-proj
#:val-first-projection multi-or/c-val-first-proj
#:late-neg-projection multi-or/c-late-neg-proj
#:name multi-or/c-name
#:first-order multi-or/c-first-order
#:stronger multi-or/c-stronger?
@ -374,7 +373,7 @@
#:property prop:contract
(build-contract-property
#:projection multi-or/c-proj
#:val-first-projection multi-or/c-val-first-proj
#:late-neg-projection multi-or/c-late-neg-proj
#:name multi-or/c-name
#:first-order multi-or/c-first-order
#:stronger multi-or/c-stronger?

View File

@ -10,6 +10,7 @@
contract-struct-first-order
contract-struct-projection
contract-struct-val-first-projection
contract-struct-late-neg-projection
contract-struct-stronger?
contract-struct-generate
contract-struct-exercise
@ -66,6 +67,7 @@
generate
exercise
val-first-projection
late-neg-projection
list-contract? ]
#:omit-define-syntaxes)
@ -106,6 +108,12 @@
(and get-projection
(get-projection c)))
(define (contract-struct-late-neg-projection c)
(define prop (contract-struct-property c))
(define get-projection (contract-property-late-neg-projection prop))
(and get-projection
(get-projection c)))
(define trail (make-parameter #f))
(define (contract-struct-stronger? a b)
(define prop (contract-struct-property a))
@ -255,6 +263,7 @@
#:first-order [get-first-order #f]
#:projection [get-projection #f]
#:val-first-projection [get-val-first-projection #f]
#:late-neg-projection [get-late-neg-projection #f]
#:stronger [stronger #f]
#:generate [generate (λ (ctc) (λ (fuel) #f))]
#:exercise [exercise (λ (ctc) (λ (fuel) (values void '())))]
@ -289,7 +298,8 @@
(mk get-name get-first-order
get-projection stronger
generate exercise
get-val-first-projection
get-val-first-projection
get-late-neg-projection
list-contract?)))
(define build-contract-property
@ -372,7 +382,8 @@
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-struct make-contract [ name first-order projection val-first-projection
(define-struct make-contract [ name first-order projection
val-first-projection late-neg-projection
stronger generate exercise list-contract? ]
#:omit-define-syntaxes
#:property prop:custom-write
@ -386,12 +397,14 @@
#:first-order (lambda (c) (make-contract-first-order c))
#:projection (lambda (c) (make-contract-projection c))
#:val-first-projection (lambda (c) (make-contract-val-first-projection c))
#:late-neg-projection (lambda (c) (make-contract-late-neg-projection c))
#:stronger (lambda (a b) ((make-contract-stronger a) a b))
#:generate (lambda (c) (make-contract-generate c))
#:exercise (lambda (c) (make-contract-exercise c))
#:list-contract? (λ (c) (make-contract-list-contract? c))))
(define-struct make-chaperone-contract [ name first-order projection val-first-projection
(define-struct make-chaperone-contract [ name first-order projection
val-first-projection late-neg-projection
stronger generate exercise list-contract? ]
#:omit-define-syntaxes
#:property prop:custom-write
@ -405,12 +418,14 @@
#:first-order (lambda (c) (make-chaperone-contract-first-order c))
#:projection (lambda (c) (make-chaperone-contract-projection c))
#:val-first-projection (lambda (c) (make-chaperone-contract-val-first-projection c))
#:late-neg-projection (lambda (c) (make-chaperone-contract-late-neg-projection c))
#:stronger (lambda (a b) ((make-chaperone-contract-stronger a) a b))
#:generate (lambda (c) (make-chaperone-contract-generate c))
#:exercise (lambda (c) (make-chaperone-contract-exercise c))
#:list-contract? (λ (c) (make-chaperone-contract-list-contract? c))))
(define-struct make-flat-contract [ name first-order projection val-first-projection
(define-struct make-flat-contract [ name first-order projection
val-first-projection late-neg-projection
stronger generate exercise list-contract? ]
#:omit-define-syntaxes
#:property prop:custom-write
@ -423,6 +438,7 @@
#:name (lambda (c) (make-flat-contract-name c))
#:first-order (lambda (c) (make-flat-contract-first-order c))
#:val-first-projection (λ (c) (make-flat-contract-val-first-projection c))
#:late-neg-projection (λ (c) (make-flat-contract-late-neg-projection c))
#:projection (lambda (c) (make-flat-contract-projection c))
#:stronger (lambda (a b) ((make-flat-contract-stronger a) a b))
#:generate (lambda (c) (make-flat-contract-generate c))
@ -434,6 +450,7 @@
#:first-order [first-order #f]
#:projection [projection #f]
#:val-first-projection [val-first-projection #f]
#:late-neg-projection [late-neg-projection #f]
#:stronger [stronger #f]
#:generate [generate (λ (ctc) (λ (fuel) #f))]
#:exercise [exercise (λ (ctc) (λ (fuel) (values void '())))]
@ -448,7 +465,7 @@
[stronger (or stronger as-strong?)])
(mk name first-order
projection val-first-projection
projection val-first-projection late-neg-projection
stronger
generate exercise
list-contract?)))

View File

@ -68,9 +68,9 @@
(fail val '(expected: "~s for element ~s" given: "~e") (contract-name elem-ctc) n e))))
#t)))
(define (check-val-first-vectorof c)
(define (check-late-neg-vectorof c)
(define immutable (base-vectorof-immutable c))
(λ (val blame)
(λ (val blame neg-party)
(cond
[(vector? val)
(cond
@ -78,23 +78,20 @@
(cond
[(immutable? val) #f]
[else
(λ (neg-party)
(raise-blame-error blame #:missing-party neg-party
val '(expected "an immutable vector" given: "~e") val))])]
(raise-blame-error blame #:missing-party neg-party
val '(expected "an immutable vector" given: "~e") val)])]
[(eq? immutable #f)
(cond
[(immutable? val)
(λ (neg-party)
(raise-blame-error blame #:missing-party neg-party
val '(expected "an mutable vector" given: "~e" val)))]
(raise-blame-error blame #:missing-party neg-party
val '(expected "an mutable vector" given: "~e" val))]
[else #f])]
[else #f])]
[else
(λ (neg-party)
(raise-blame-error blame #:missing-party neg-party
val
'(expected "a vector," given: "~e")
val))])))
(raise-blame-error blame #:missing-party neg-party
val
'(expected "a vector," given: "~e")
val)])))
(define (vectorof-first-order ctc)
(let ([check (check-vectorof ctc)])
@ -126,29 +123,28 @@
(build-flat-contract-property
#:name vectorof-name
#:first-order vectorof-first-order
#:val-first-projection (λ (ctc)
(define check (check-val-first-vectorof ctc))
(define vfp (get/build-val-first-projection (base-vectorof-elem ctc)))
(λ (blame)
(define ele-blame (blame-add-element-of-context blame))
(define vfp+blame (vfp ele-blame))
(λ (val)
(or (check val blame)
(λ (neg-party)
(for ([x (in-vector val)])
((vfp+blame x) neg-party))
val)))))
#:late-neg-projection (λ (ctc)
(define check (check-late-neg-vectorof ctc))
(define vfp (get/build-late-neg-projection (base-vectorof-elem ctc)))
(λ (blame)
(define ele-blame (blame-add-element-of-context blame))
(define vfp+blame (vfp ele-blame))
(λ (val neg-party)
(check val blame neg-party)
(for ([x (in-vector val)])
(vfp+blame x neg-party))
val)))
#:stronger vectorof-stronger
#:projection
(λ (ctc)
(define check (check-vectorof ctc))
(λ (blame)
(define raise-blame (λ (val . args)
(apply raise-blame-error blame val args)))
(define raise-blame (λ (val . args) (apply raise-blame-error blame val args)))
(define ele-blame (blame-add-element-of-context blame))
(λ (val)
(check val raise-blame #f)
(let* ([elem-ctc (base-vectorof-elem ctc)]
[p ((contract-projection elem-ctc) blame)])
[p ((contract-projection elem-ctc) ele-blame)])
(for ([e (in-vector val)])
(p e)))
val)))))
@ -156,7 +152,7 @@
(define (blame-add-element-of-context blame #:swap? [swap? #f])
(blame-add-context blame "an element of" #:swap? swap?))
(define (vectorof-val-first-ho-projection chaperone-or-impersonate-vector)
(define (vectorof-late-neg-ho-projection chaperone-or-impersonate-vector)
(λ (ctc)
(define elem-ctc (base-vectorof-elem ctc))
(define immutable (base-vectorof-immutable ctc))
@ -164,40 +160,34 @@
(λ (blame)
(define pos-blame (blame-add-element-of-context blame))
(define neg-blame (blame-add-element-of-context blame #:swap? #t))
(define vfp (get/build-val-first-projection elem-ctc))
(define vfp (get/build-late-neg-projection elem-ctc))
(define elem-pos-proj (vfp pos-blame))
(define elem-neg-proj (vfp neg-blame))
(define checked-ref (λ (neg-party)
(λ (vec i val)
(with-continuation-mark
contract-continuation-mark-key
(cons pos-blame neg-party)
((elem-pos-proj val) neg-party)))))
(with-continuation-mark contract-continuation-mark-key
(cons pos-blame neg-party)
(elem-pos-proj val neg-party)))))
(define checked-set (λ (neg-party)
(λ (vec i val)
(with-continuation-mark
contract-continuation-mark-key
(cons neg-blame neg-party)
((elem-neg-proj val) neg-party)))))
(with-continuation-mark contract-continuation-mark-key
(cons neg-blame neg-party)
(elem-neg-proj val neg-party)))))
(λ (val)
(let/ec k
(define (raise-blame val . args)
(k
(λ (neg-party)
(apply raise-blame-error blame #:missing-party neg-party val args))))
(check val raise-blame #f)
(λ (neg-party)
(if (and (immutable? val) (not (chaperone? val)))
(apply vector-immutable
(for/list ([e (in-vector val)])
((elem-pos-proj e) neg-party)))
(chaperone-or-impersonate-vector
val
(checked-ref neg-party)
(checked-set neg-party)
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party blame neg-party)))))))))
(λ (val neg-party)
(define (raise-blame val . args)
(apply raise-blame-error blame #:missing-party neg-party val args))
(check val raise-blame #f)
(if (and (immutable? val) (not (chaperone? val)))
(apply vector-immutable
(for/list ([e (in-vector val)])
(elem-pos-proj e neg-party)))
(chaperone-or-impersonate-vector
val
(checked-ref neg-party)
(checked-set neg-party)
impersonator-prop:contracted ctc
impersonator-prop:blame (blame-add-missing-party blame neg-party)))))))
(define-values (prop:neg-blame-party prop:neg-blame-party? prop:neg-blame-party-get)
(make-impersonator-property 'prop:neg-blame-party))
@ -242,7 +232,7 @@
#:name vectorof-name
#:first-order vectorof-first-order
#:stronger vectorof-stronger
#:val-first-projection (vectorof-val-first-ho-projection chaperone-vector)
#:late-neg-projection (vectorof-late-neg-ho-projection chaperone-vector)
#:projection (vectorof-ho-projection chaperone-vector)))
(define-struct (impersonator-vectorof base-vectorof) ()
@ -252,7 +242,7 @@
#:name vectorof-name
#:first-order vectorof-first-order
#:stronger vectorof-stronger
#:val-first-projection (vectorof-val-first-ho-projection chaperone-vector)
#:late-neg-projection (vectorof-late-neg-ho-projection chaperone-vector)
#:projection (vectorof-ho-projection impersonate-vector)))
(define-syntax (wrap-vectorof stx)