misc minor improvments to unconstrained-domain->

- add an optimization based on procedure-result-arity
 - make it generate less code
 - fix a few bugs
This commit is contained in:
Robby Findler 2016-08-29 11:19:18 -05:00
parent 56c97474b0
commit f878afb82b
2 changed files with 140 additions and 65 deletions

View File

@ -45,4 +45,27 @@
(test/pos-blame
'unconstrained-domain->7
'((contract (unconstrained-domain-> number?) (λ (#:x x) x) 'pos 'neg) #:x #f)))
'((contract (unconstrained-domain-> number?) (λ (#:x x) x) 'pos 'neg) #:x #f))
(test/spec-passed/result
'unconstrained-domain->8
'(let ([f (λ (x) 0)])
(eq? (contract (unconstrained-domain-> any/c)
f
'pos
'neg)
f))
#t)
(test/pos-blame
'unconstrained-domain->9
'((contract (unconstrained-domain-> number? number?) (λ () (values #f 0)) 'pos 'neg)))
(test/pos-blame
'unconstrained-domain->10
'((contract (unconstrained-domain-> number? number?) (λ () (values 0 #f)) 'pos 'neg)))
(test/pos-blame
'unconstrained-domain->11
'((contract (unconstrained-domain-> number? number?) (λ () 1) 'pos 'neg)))
)

View File

@ -4,32 +4,28 @@
"arrow-common.rkt"
"blame.rkt"
"guts.rkt"
"prop.rkt")
"prop.rkt"
"misc.rkt")
(provide unconstrained-domain->)
(provide (rename-out [_unconstrained-domain-> unconstrained-domain->]))
(define-syntax (unconstrained-domain-> stx)
(define-syntax (_unconstrained-domain-> stx)
(syntax-case stx ()
[(_ rngs ...)
(with-syntax ([(rngs-x ...) (generate-temporaries #'(rngs ...))]
[(proj-x ...) (generate-temporaries #'(rngs ...))]
[(p-app-x ...) (generate-temporaries #'(rngs ...))]
[(res-x ...) (generate-temporaries #'(rngs ...))])
#`(let ([rngs-x (coerce-contract 'unconstrained-domain-> rngs)] ...)
(let ([rngs-list (list rngs-x ...)]
[proj-x (get/build-late-neg-projection rngs-x)] ...)
(define (projection wrapper get-ctc)
(λ (orig-blame)
(define blame-party-info (get-blame-party-info orig-blame))
(define ctc (get-ctc))
(let ([rng-blame (blame-add-range-context orig-blame)])
(let* ([p-app-x (proj-x rng-blame)] ...)
(λ (val neg-party)
(check-is-a-procedure orig-blame neg-party val)
(define (res-checker res-x ...) (values/drop (p-app-x res-x neg-party) ...))
(define blame+neg-party (cons orig-blame neg-party))
(wrapper
(with-syntax ([(res-x ...) (generate-temporaries #'(rngs ...))]
[(p-app-x ...) (generate-temporaries #'(rngs ...))])
#`(build-unconstrained-domain->
(list rngs ...)
(λ (val blame+neg-party rngs-list blame-party-info neg-party p-app-x ...)
(define res-checker
(case-lambda
[(res-x ...) (values/drop (p-app-x res-x neg-party) ...)]
[results
(bad-number-of-results (car blame+neg-party)
val
#,(length (syntax->list #'(rngs ...)))
results
#:missing-party neg-party)]))
(make-keyword-procedure
(λ (kwds kwd-vals . args)
(with-contract-continuation-mark
@ -50,12 +46,84 @@
#'neg-party
(list #'res-checker)
(λ (s) #`(apply values #,@s args))
#'blame+neg-party))))
#'blame+neg-party)))))))]))
(define (build-unconstrained-domain-> range-maybe-contracts wrapper-proc)
(define range-contracts (coerce-contracts 'unconstrained-domain-> range-maybe-contracts))
(define chaperone? (andmap chaperone-contract? range-contracts))
(cond
[chaperone?
(make-chaperone-unconstrained-domain-> range-contracts wrapper-proc)]
[else
(make-impersonator-unconstrained-domain-> range-contracts wrapper-proc)]))
(define (unconstrained-domain->-projection ctc)
(define range-contracts (unconstrained-domain->-ranges ctc))
(define make-wrapper-proc (unconstrained-domain->-make-wrapper-proc ctc))
(define late-neg-projections (map get/build-late-neg-projection range-contracts))
(define can-check-procedure-result-arity? (andmap any/c? range-contracts))
(define desired-procedure-result-arity (length range-contracts))
(define chaperone-or-impersonate-procedure (if (chaperone-unconstrained-domain->? ctc)
chaperone-procedure
impersonate-procedure))
(λ (orig-blame)
(define blame-party-info (get-blame-party-info orig-blame))
(define range-blame (blame-add-range-context orig-blame))
(define projs (for/list ([late-neg-projection (in-list late-neg-projections)])
(late-neg-projection range-blame)))
(λ (val neg-party)
(check-is-a-procedure orig-blame neg-party val)
(define blame+neg-party (cons orig-blame neg-party))
(if (and can-check-procedure-result-arity?
(equal? desired-procedure-result-arity
(procedure-result-arity val)))
val
(chaperone-or-impersonate-procedure
val
(apply make-wrapper-proc
val
blame+neg-party
range-contracts
blame-party-info
neg-party
projs)
impersonator-prop:contracted ctc
impersonator-prop:application-mark
(cons tail-contract-key (list neg-party blame-party-info rngs-x ...))))))))
(make-unconstrained-domain-> (list rngs-x ...)
projection))))]))
(cons tail-contract-key (list* neg-party blame-party-info range-contracts)))))))
(define (unconstrained-domain->-name ud)
(apply build-compound-type-name 'unconstrained-domain->
(map contract-name (unconstrained-domain->-ranges ud))))
(define (unconstrained-domain->-first-order ud)
(λ (val)
(procedure? val)))
(define (unconstrained-domain->-stronger this that)
(and (unconstrained-domain->? that)
(pairwise-stronger-contracts? (unconstrained-domain->-ranges this)
(unconstrained-domain->-ranges that))))
(define-struct unconstrained-domain-> (ranges make-wrapper-proc)
#:property prop:custom-write custom-write-property-proc)
(define-struct (chaperone-unconstrained-domain-> unconstrained-domain->) ()
#:property
prop:chaperone-contract
(build-chaperone-contract-property
#:name unconstrained-domain->-name
#:first-order unconstrained-domain->-first-order
#:late-neg-projection unconstrained-domain->-projection
#:stronger unconstrained-domain->-stronger))
(define-struct (impersonator-unconstrained-domain-> unconstrained-domain->) ()
#:property
prop:chaperone-contract
(build-chaperone-contract-property
#:name unconstrained-domain->-name
#:first-order unconstrained-domain->-first-order
#:late-neg-projection unconstrained-domain->-projection
#:stronger unconstrained-domain->-stronger))
(define (check-is-a-procedure orig-blame neg-party val)
(unless (procedure? val)
@ -63,19 +131,3 @@
val
'(expected: "a procedure" given: "~v")
val)))
(define (make-unconstrained-domain-> ctcs late-neg-projection)
(define name
(apply build-compound-type-name 'unconstrained-domain->
(map contract-name ctcs)))
(define ctc
(if (andmap chaperone-contract? ctcs)
(make-chaperone-contract
#:name name
#:late-neg-projection (late-neg-projection chaperone-procedure (λ () ctc))
#:first-order procedure?)
(make-contract
#:name name
#:late-neg-projection (late-neg-projection impersonate-procedure (λ () ctc))
#:first-order procedure?)))
ctc)