add the ability to make chaperone contracts to ->i

This commit is contained in:
Robby Findler 2015-12-18 20:41:31 -06:00
parent 962a72dfda
commit 506c9be0cd
3 changed files with 247 additions and 162 deletions

View File

@ -2,7 +2,7 @@
(require "test-util.rkt") (require "test-util.rkt")
(parameterize ([current-contract-namespace (parameterize ([current-contract-namespace
(make-basic-contract-namespace)]) (make-basic-contract-namespace 'racket/contract/parametric)])
(define exn:fail:contract:blame? (contract-eval 'exn:fail:contract:blame?)) (define exn:fail:contract:blame? (contract-eval 'exn:fail:contract:blame?))
(test/no-error '(->i ([x integer?]) ([y integer?]) any)) (test/no-error '(->i ([x integer?]) ([y integer?]) any))
@ -1397,4 +1397,31 @@
1)) 1))
;; this used to cause a runtime error in the code that parses ->i ;; this used to cause a runtime error in the code that parses ->i
(test/no-error '(->i ([x () any/c] [y (x) any/c]) any))) (test/no-error '(->i ([x () any/c] [y (x) any/c]) any))
(test/spec-passed/result
'really-chaperones.1
'(let ([f (λ () 1)])
(chaperone-of?
(contract (->i #:chaperone () any) f 'pos 'neg)
f))
#t)
(test/spec-passed/result
'really-chaperones.2
'(let ([f (λ () 1)])
(chaperone-of?
(contract (->i () [_ (new-∀/c)]) f 'pos 'neg)
f))
#f)
(test/spec-passed/result
'really-chaperones.3
'(with-handlers ([exn:fail?
(λ (x)
(regexp-match? #rx"^->i:.*chaperone" (exn-message x)))])
((contract (->i #:chaperone ([x integer?] [y (x) (new-∀/c)]) any)
(λ (x y) x)
'pos 'neg) 1 2)
"didn't raise an error")
#t))

View File

@ -20,12 +20,13 @@ code does the parsing and validation of the syntax.
|# |#
;; istx-is-chaperone-contract? : boolean?
;; args : (listof arg?) ;; args : (listof arg?)
;; rst : (or/c #f arg/res?) ;; rst : (or/c #f arg/res?)
;; pre : (listof pre/post?) ;; pre : (listof pre/post?)
;; ress : (or/c #f (listof eres?) (listof lres?)) ;; ress : (or/c #f (listof eres?) (listof lres?))
;; post : (listof pre/post?) ;; post : (listof pre/post?)
(struct istx (args rst pre ress post) #:transparent) (struct istx (is-chaperone-contract? args rst pre ress post) #:transparent)
;; NOTE: the ress field may contain a mixture of eres and lres structs ;; NOTE: the ress field may contain a mixture of eres and lres structs
;; but only temporarily; in that case, a syntax error ;; but only temporarily; in that case, a syntax error
;; is signaled and the istx struct is not used afterwards ;; is signaled and the istx struct is not used afterwards
@ -59,11 +60,13 @@ code does the parsing and validation of the syntax.
(define (parse-->i stx) (define (parse-->i stx)
(if (identifier? stx) (if (identifier? stx)
(raise-syntax-error #f "expected ->i to follow an open parenthesis" stx) (raise-syntax-error #f "expected ->i to follow an open parenthesis" stx)
(let-values ([(raw-mandatory-doms raw-optional-doms (let-values ([(is-chaperone-contract?
id/rest-id pre-cond range post-cond) raw-mandatory-doms raw-optional-doms
id/rest-id pre-cond range post-cond)
(pull-out-pieces stx)]) (pull-out-pieces stx)])
(let ([candidate (let ([candidate
(istx (append (parse-doms stx #f raw-mandatory-doms) (istx is-chaperone-contract?
(append (parse-doms stx #f raw-mandatory-doms)
(parse-doms stx #t raw-optional-doms)) (parse-doms stx #t raw-optional-doms))
id/rest-id id/rest-id
pre-cond pre-cond
@ -393,12 +396,26 @@ code does the parsing and validation of the syntax.
;; pull-out-pieces : ;; pull-out-pieces :
;; stx -> (values raw-mandatory-doms raw-optional-doms id/rest-id pre-cond range post-cond) ;; stx -> (values raw-mandatory-doms raw-optional-doms id/rest-id pre-cond range post-cond)
(define (pull-out-pieces stx) (define (pull-out-pieces stx)
(let*-values ([(raw-mandatory-doms leftover) (let*-values ([(is-chaperone-contract? leftover)
(syntax-case stx () (syntax-case stx ()
[(_ (raw-mandatory-doms ...) . leftover) [(_ #:chaperone . leftover)
(values #t #'leftover)]
[(_ . leftover)
(let ([lst (syntax->list stx)])
(when (null? (cdr lst))
(raise-syntax-error #f "expected a sequence of mandatory domain elements"
stx))
(when (keyword? (syntax-e (cadr lst)))
(raise-syntax-error #f "unknown keyword"
stx
(cadr lst)))
(values #f #'leftover))])]
[(raw-mandatory-doms leftover)
(syntax-case leftover ()
[((raw-mandatory-doms ...) . leftover)
(values (syntax->list #'(raw-mandatory-doms ...)) (values (syntax->list #'(raw-mandatory-doms ...))
#'leftover)] #'leftover)]
[(_ a . leftover) [(a . leftover)
(raise-syntax-error #f (raise-syntax-error #f
"expected a sequence of mandatory domain elements" "expected a sequence of mandatory domain elements"
stx #'a)] stx #'a)]
@ -604,7 +621,9 @@ code does the parsing and validation of the syntax.
(values (reverse post-conds) leftover)]))]) (values (reverse post-conds) leftover)]))])
(syntax-case leftover () (syntax-case leftover ()
[() [()
(values raw-mandatory-doms raw-optional-doms id/rest-id pre-conds range post-conds)] (values is-chaperone-contract?
raw-mandatory-doms raw-optional-doms id/rest-id pre-conds
range post-conds)]
[(a . b) [(a . b)
(raise-syntax-error #f "bad syntax" stx #'a)] (raise-syntax-error #f "bad syntax" stx #'a)]
[_ [_

View File

@ -27,7 +27,7 @@
(provide (rename-out [->i/m ->i])) (provide (rename-out [->i/m ->i]))
(define (build-??-args ctc blame) (define (build-??-args c-or-i-procedure ctc blame)
(define arg-ctc-projs (map (λ (x) (contract-projection (->i-arg-contract x))) (->i-arg-ctcs ctc))) (define arg-ctc-projs (map (λ (x) (contract-projection (->i-arg-contract x))) (->i-arg-ctcs ctc)))
(define indy-arg-ctc-projs (map (λ (x) (contract-projection (cdr x))) (define indy-arg-ctc-projs (map (λ (x) (contract-projection (cdr x)))
(->i-indy-arg-ctcs ctc))) (->i-indy-arg-ctcs ctc)))
@ -81,7 +81,8 @@
[rng-pr (in-list (->i-indy-rng-ctcs ctc))]) [rng-pr (in-list (->i-indy-rng-ctcs ctc))])
(rng-proj (blame-add-context indy-rng-blame (format "the ~a result of" (rng-proj (blame-add-context indy-rng-blame (format "the ~a result of"
(car rng-pr)))))) (car rng-pr))))))
(list* (λ (val mtd?) (list* c-or-i-procedure
(λ (val mtd?)
(if has-rest (if has-rest
(check-procedure/more val mtd? (check-procedure/more val mtd?
(->i-mandatory-args ctc) (->i-mandatory-args ctc)
@ -104,10 +105,10 @@
partial-indy-rngs))) partial-indy-rngs)))
(define arr->i-proj (define arr->i-proj
(λ (ctc) (λ (ctc c-or-i-procedure)
(define func (->i-mk-wrapper ctc)) (define func (->i-mk-wrapper ctc))
(λ (blame) (λ (blame)
(define ???-args (build-??-args ctc blame)) (define ???-args (build-??-args c-or-i-procedure ctc blame))
(apply func ???-args)))) (apply func ???-args))))
@ -183,140 +184,160 @@
pre/post-procs pre/post-procs
mandatory-args opt-args mandatory-kwds opt-kwds rest mandatory-args opt-args mandatory-kwds opt-kwds rest
mtd? here mk-wrapper mk-val-first-wrapper name-info) mtd? here mk-wrapper mk-val-first-wrapper name-info)
#:property prop:custom-write custom-write-property-proc #:property prop:custom-write custom-write-property-proc)
#:property prop:contract
(build-contract-property (define (mk-prop chaperone?)
#:val-first-projection (define c-or-i-procedure (if chaperone? chaperone-procedure impersonate-procedure))
(λ (ctc) ((if chaperone? build-chaperone-contract-property build-contract-property)
(define blame-accepting-proj (arr->i-proj ctc)) #:val-first-projection
(λ (blame) (λ (ctc)
(λ (val) (define blame-accepting-proj (arr->i-proj ctc c-or-i-procedure))
(wrapped-extra-arg-arrow (λ (blame)
(λ (neg-party) (λ (val)
((blame-accepting-proj (blame-add-missing-party blame neg-party)) val)) (wrapped-extra-arg-arrow
(->i-mk-val-first-wrapper ctc))))) (λ (neg-party)
#:late-neg-projection ((blame-accepting-proj (blame-add-missing-party blame neg-party)) val))
(λ (ctc) (->i-mk-val-first-wrapper ctc)))))
(define blame-accepting-proj (arr->i-proj ctc)) #:late-neg-projection
(λ (blame) (λ (ctc)
(λ (val neg-party) (define blame-accepting-proj (arr->i-proj ctc c-or-i-procedure))
((blame-accepting-proj (blame-add-missing-party blame neg-party)) val)))) (λ (blame)
#:projection arr->i-proj (λ (val neg-party)
#:name (λ (ctc) ((blame-accepting-proj (blame-add-missing-party blame neg-party)) val))))
(define (arg/ress->spec infos ctcs dep-ctcs skip?) #:projection (λ (ctc) (arr->i-proj ctc c-or-i-procedure))
(let loop ([infos infos] #:name (λ (ctc)
[ctcs ctcs] (define (arg/ress->spec infos ctcs dep-ctcs skip?)
[dep-ctcs dep-ctcs]) (let loop ([infos infos]
(cond [ctcs ctcs]
[(null? infos) '()] [dep-ctcs dep-ctcs])
[else (cond
(let* ([info (car infos)] [(null? infos) '()]
[dep/nodep (list-ref info 0)] [else
[var (list-ref info 1)] (let* ([info (car infos)]
[vars (list-ref info 2)] [dep/nodep (list-ref info 0)]
[kwd (list-ref info 3)]) [var (list-ref info 1)]
(case dep/nodep [vars (list-ref info 2)]
[(nodep) [kwd (list-ref info 3)])
(if (skip? info) (case dep/nodep
(loop (cdr infos) (cdr ctcs) dep-ctcs) [(nodep)
`(,@(if kwd (if (skip? info)
(list kwd) (loop (cdr infos) (cdr ctcs) dep-ctcs)
(list)) `(,@(if kwd
[,var ,(contract-name (car ctcs))] (list kwd)
. (list))
,(loop (cdr infos) (cdr ctcs) dep-ctcs)))] [,var ,(contract-name (car ctcs))]
[(dep) .
(define body-src (list-ref info 5)) ,(loop (cdr infos) (cdr ctcs) dep-ctcs)))]
(if (skip? info) [(dep)
(loop (cdr infos) ctcs (cdr dep-ctcs)) (define body-src (list-ref info 5))
`(,@(if kwd (if (skip? info)
(list kwd) (loop (cdr infos) ctcs (cdr dep-ctcs))
(list)) `(,@(if kwd
[,var ,vars ,body-src] (list kwd)
. (list))
,(loop (cdr infos) ctcs (cdr dep-ctcs))))]))]))) [,var ,vars ,body-src]
(let* ([name-info (->i-name-info ctc)] .
[args-info (vector-ref name-info 0)] ,(loop (cdr infos) ctcs (cdr dep-ctcs))))]))])))
[rest-info (vector-ref name-info 1)] (let* ([name-info (->i-name-info ctc)]
[pre-infos (vector-ref name-info 2)] [args-info (vector-ref name-info 0)]
[rng-info (vector-ref name-info 3)] [rest-info (vector-ref name-info 1)]
[post-infos (vector-ref name-info 4)]) [pre-infos (vector-ref name-info 2)]
`(->i ,(arg/ress->spec args-info [rng-info (vector-ref name-info 3)]
(map ->i-arg-contract (->i-arg-ctcs ctc)) [post-infos (vector-ref name-info 4)])
(->i-arg-dep-ctcs ctc) `(->i ,(arg/ress->spec args-info
(λ (x) (list-ref x 4))) (map ->i-arg-contract (->i-arg-ctcs ctc))
,@(let ([rests (arg/ress->spec args-info (->i-arg-dep-ctcs ctc)
(map ->i-arg-contract (->i-arg-ctcs ctc)) (λ (x) (list-ref x 4)))
(->i-arg-dep-ctcs ctc) ,@(let ([rests (arg/ress->spec args-info
(λ (x) (not (list-ref x 4))))]) (map ->i-arg-contract (->i-arg-ctcs ctc))
(if (null? rests) (->i-arg-dep-ctcs ctc)
'() (λ (x) (not (list-ref x 4))))])
(list rests))) (if (null? rests)
,@(if rest-info '()
(case (car rest-info) (list rests)))
[(nodep) `(#:rest ,@(if rest-info
[,(list-ref rest-info 1) (case (car rest-info)
,(contract-name [(nodep) `(#:rest
(car [,(list-ref rest-info 1)
(reverse ,(contract-name
(map ->i-arg-contract (->i-arg-ctcs ctc)))))])] (car
[(dep) `(#:rest [,(list-ref rest-info 1) (reverse
,(list-ref rest-info 2) (map ->i-arg-contract (->i-arg-ctcs ctc)))))])]
,(list-ref rest-info 3)])]) [(dep) `(#:rest [,(list-ref rest-info 1)
'()) ,(list-ref rest-info 2)
,@(apply ,(list-ref rest-info 3)])])
append '())
(for/list ([pre-info pre-infos]) ,@(apply
(define ids (list-ref pre-info 0)) append
(define name (list-ref pre-info 1)) (for/list ([pre-info pre-infos])
(define code (list-ref pre-info 2)) (define ids (list-ref pre-info 0))
(cond (define name (list-ref pre-info 1))
[(string? name) (define code (list-ref pre-info 2))
`(#:pre/name ,ids ,name ,code)] (cond
[(equal? name 'bool) [(string? name)
`(#:pre ,ids ,code)] `(#:pre/name ,ids ,name ,code)]
[(equal? name 'desc) [(equal? name 'bool)
`(#:pre/desc ,ids ,code)]))) `(#:pre ,ids ,code)]
,(cond [(equal? name 'desc)
[(not rng-info) `(#:pre/desc ,ids ,code)])))
'any] ,(cond
[else [(not rng-info)
(let ([infos (arg/ress->spec rng-info 'any]
(map cdr (->i-rng-ctcs ctc)) [else
(->i-rng-dep-ctcs ctc) (let ([infos (arg/ress->spec rng-info
(λ (x) #f))]) (map cdr (->i-rng-ctcs ctc))
(cond (->i-rng-dep-ctcs ctc)
[(or (null? infos) (not (null? (cdr infos)))) (λ (x) #f))])
`(values ,@infos)] (cond
[else [(or (null? infos) (not (null? (cdr infos))))
(car infos)]))]) `(values ,@infos)]
,@(apply [else
append (car infos)]))])
(for/list ([post-info post-infos]) ,@(apply
(define ids (list-ref post-info 0)) append
(define name (list-ref post-info 1)) (for/list ([post-info post-infos])
(define code (list-ref post-info 2)) (define ids (list-ref post-info 0))
(cond (define name (list-ref post-info 1))
[(string? name) (define code (list-ref post-info 2))
`(#:post/name ,ids ,name ,code)] (cond
[(equal? name 'bool) [(string? name)
`(#:post ,ids ,code)] `(#:post/name ,ids ,name ,code)]
[(equal? name 'desc) [(equal? name 'bool)
`(#:post/desc ,ids ,code)])))))) `(#:post ,ids ,code)]
#:first-order [(equal? name 'desc)
(λ (ctc) `(#:post/desc ,ids ,code)]))))))
(let ([has-rest (->i-rest ctc)] #:first-order
[mtd? (->i-mtd? ctc)] (λ (ctc)
[mand-args (->i-mandatory-args ctc)] (let ([has-rest (->i-rest ctc)]
[opt-args (->i-opt-args ctc)] [mtd? (->i-mtd? ctc)]
[mand-kwds (->i-mandatory-kwds ctc)] [mand-args (->i-mandatory-args ctc)]
[opt-kwds (->i-opt-kwds ctc)]) [opt-args (->i-opt-args ctc)]
(λ (val) [mand-kwds (->i-mandatory-kwds ctc)]
(if has-rest [opt-kwds (->i-opt-kwds ctc)])
(check-procedure/more val mtd? mand-args mand-kwds opt-kwds #f #f) (λ (val)
(check-procedure val mtd? mand-args opt-args mand-kwds opt-kwds #f #f))))) (if has-rest
#:exercise exercise->i (check-procedure/more val mtd? mand-args mand-kwds opt-kwds #f #f)
#:stronger (λ (this that) (eq? this that)))) ;; WRONG (check-procedure val mtd? mand-args opt-args mand-kwds opt-kwds #f #f)))))
#:exercise exercise->i
#:stronger (λ (this that) (eq? this that)))) ;; WRONG
(struct chaperone->i ->i () #:property prop:chaperone-contract (mk-prop #t))
(struct impersonator->i ->i () #:property prop:contract (mk-prop #f))
(define (make-->i is-chaperone-contract? blame-info
arg-ctcs arg-dep-ctcs indy-arg-ctcs
rng-ctcs rng-dep-ctcs indy-rng-ctcs
pre/post-procs
mandatory-args opt-args mandatory-kwds opt-kwds rest
mtd? here mk-wrapper mk-val-first-wrapper name-info)
(define maker (if is-chaperone-contract? chaperone->i impersonator->i))
(maker blame-info
arg-ctcs arg-dep-ctcs indy-arg-ctcs
rng-ctcs rng-dep-ctcs indy-rng-ctcs
pre/post-procs
mandatory-args opt-args mandatory-kwds opt-kwds rest
mtd? here mk-wrapper mk-val-first-wrapper name-info))
;; find-ordering : (listof arg) -> (values (listof arg) (listof number)) ;; find-ordering : (listof arg) -> (values (listof arg) (listof number))
;; sorts the arguments according to the dependency order. ;; sorts the arguments according to the dependency order.
@ -655,7 +676,7 @@ evaluted left-to-right.)
;; adds nested lets that bind the wrapper-args and the indy-arg/res-vars to projected values, ;; adds nested lets that bind the wrapper-args and the indy-arg/res-vars to projected values,
;; with 'body' in the body of the let also handles adding code to check to see if unsupplied ;; with 'body' in the body of the let also handles adding code to check to see if unsupplied
;; args are present (skipping the contract check, if so) ;; args are present (skipping the contract check, if so)
(define-for-syntax (add-wrapper-let body swapped-blame? neg-calls? (define-for-syntax (add-wrapper-let body is-chaperone-contract? swapped-blame? neg-calls?
ordered-arg/reses indicies ordered-arg/reses indicies
arg/res-proj-vars indy-arg/res-proj-vars arg/res-proj-vars indy-arg/res-proj-vars
wrapper-arg/ress indy-arg/res-vars wrapper-arg/ress indy-arg/res-vars
@ -706,11 +727,12 @@ evaluted left-to-right.)
wrapper-arg wrapper-arg
(cond (cond
[(and (eres? an-arg/res) (arg/res-vars an-arg/res)) [(and (eres? an-arg/res) (arg/res-vars an-arg/res))
#`(un-dep #,(eres-eid an-arg/res) #`(#,(if is-chaperone-contract? #'un-dep/chaperone #'un-dep)
#,wrapper-arg #,(eres-eid an-arg/res)
#,(build-blame-identifier #f #,wrapper-arg
swapped-blame? #,(build-blame-identifier #f
(arg/res-var an-arg/res)))] swapped-blame?
(arg/res-var an-arg/res)))]
[(arg/res-vars an-arg/res) [(arg/res-vars an-arg/res)
#`(#,arg/res-proj-var #`(#,arg/res-proj-var
#,@(map (λ (var) (arg/res-to-indy-var indy-arg-vars #,@(map (λ (var) (arg/res-to-indy-var indy-arg-vars
@ -789,6 +811,7 @@ evaluted left-to-right.)
#,(add-wrapper-let #,(add-wrapper-let
(add-post-cond an-istx indy-arg-vars ordered-args indy-res-vars ordered-ress (add-post-cond an-istx indy-arg-vars ordered-args indy-res-vars ordered-ress
#`(values #,@(vector->list wrapper-ress))) #`(values #,@(vector->list wrapper-ress)))
(istx-is-chaperone-contract? an-istx)
#f #f #f #f
ordered-ress res-indices ordered-ress res-indices
res-proj-vars indy-res-proj-vars res-proj-vars indy-res-proj-vars
@ -868,6 +891,7 @@ evaluted left-to-right.)
(istx-rst an-istx) (istx-rst an-istx)
wrapper-args wrapper-args
this-param))) this-param)))
(istx-is-chaperone-contract? an-istx)
#t #f #t #f
ordered-args arg-indices ordered-args arg-indices
arg-proj-vars indy-arg-proj-vars arg-proj-vars indy-arg-proj-vars
@ -879,7 +903,7 @@ evaluted left-to-right.)
#`(λ #,wrapper-proc-arglist #`(λ #,wrapper-proc-arglist
(λ (val) (λ (val)
(chk val #,(and (syntax-parameter-value #'making-a-method) #t)) (chk val #,(and (syntax-parameter-value #'making-a-method) #t))
(impersonate-procedure (c-or-i-procedure
val val
(let ([arg-checker (let ([arg-checker
(λ #,(args/vars->arglist an-istx wrapper-args this-param) (λ #,(args/vars->arglist an-istx wrapper-args this-param)
@ -954,7 +978,7 @@ evaluted left-to-right.)
'())))) '()))))
(define wrapper-proc-arglist (define wrapper-proc-arglist
#`(chk ctc blame swapped-blame #,@(map car blame-ids) #`(c-or-i-procedure chk ctc blame swapped-blame #,@(map car blame-ids)
;; the pre- and post-condition procs ;; the pre- and post-condition procs
#,@(for/list ([pres (istx-pre an-istx)] #,@(for/list ([pres (istx-pre an-istx)]
@ -1037,6 +1061,7 @@ evaluted left-to-right.)
(istx-rst an-istx) (istx-rst an-istx)
wrapper-args wrapper-args
this-param) this-param)
(istx-is-chaperone-contract? an-istx)
#t #t #t #t
ordered-args arg-indices ordered-args arg-indices
arg-proj-vars indy-arg-proj-vars arg-proj-vars indy-arg-proj-vars
@ -1059,8 +1084,17 @@ evaluted left-to-right.)
#`(f #,@argument-list))) #`(f #,@argument-list)))
(begin-encourage-inline (begin-encourage-inline
(define (un-dep ctc obj blame) (define (un-dep/chaperone orig-ctc obj blame)
(let ([ctc (coerce-contract '->i ctc)]) (let ([ctc (coerce-contract '->i orig-ctc)])
(unless (chaperone-contract? ctc)
(raise-argument-error '->i
"chaperone-contract?"
orig-ctc))
(((contract-projection ctc) blame) obj))))
(begin-encourage-inline
(define (un-dep orig-ctc obj blame)
(let ([ctc (coerce-contract '->i orig-ctc)])
(((contract-projection ctc) blame) obj)))) (((contract-projection ctc) blame) obj))))
(define-for-syntax (mk-used-indy-vars an-istx) (define-for-syntax (mk-used-indy-vars an-istx)
@ -1161,10 +1195,13 @@ evaluted left-to-right.)
an-id arg/ress-to-look-in)) an-id arg/ress-to-look-in))
ans)) ans))
(define is-chaperone-contract? (istx-is-chaperone-contract? an-istx))
#`(let ([arg-exp-xs (coerce-contract '->i arg-exps)] ... #`(let ([arg-exp-xs (coerce-contract '->i arg-exps)] ...
[res-exp-xs (coerce-contract '->i res-exps)] ...) [res-exp-xs (coerce-contract '->i res-exps)] ...)
#,(syntax-property #,(syntax-property
#`(->i #`(make-->i
#,is-chaperone-contract?
;; the information needed to make the blame records and their new contexts ;; the information needed to make the blame records and their new contexts
'#,blame-ids '#,blame-ids
;; all of the non-dependent argument contracts ;; all of the non-dependent argument contracts
@ -1185,7 +1222,8 @@ evaluted left-to-right.)
#,@(arg/res-vars arg) #,@(arg/res-vars arg)
;; this used to use opt/direct, but ;; this used to use opt/direct, but
;; opt/direct duplicates code (bad!) ;; opt/direct duplicates code (bad!)
(un-dep #,ctc-stx val blame)))) (#,(if is-chaperone-contract? #'un-dep/chaperone #'un-dep)
#,ctc-stx val blame))))
;; then the non-dependent argument contracts that are themselves dependend on ;; then the non-dependent argument contracts that are themselves dependend on
(list #,@(filter values (list #,@(filter values
(map (λ (arg/res indy-id) (map (λ (arg/res indy-id)
@ -1225,7 +1263,8 @@ evaluted left-to-right.)
;; this used to use opt/direct, but ;; this used to use opt/direct, but
;; opt/direct duplicates code (bad!) ;; opt/direct duplicates code (bad!)
#,@(arg/res-vars arg) #,@(arg/res-vars arg)
(un-dep #,arg-stx val blame))))) (#,(if is-chaperone-contract? #'un-dep/chaperone #'un-dep)
#,arg-stx val blame)))))
#''()) #''())
#,(if (istx-ress an-istx) #,(if (istx-ress an-istx)
#`(list #,@(filter values #`(list #,@(filter values