extended or/c to support multiple higher-order contracts

svn: r3606
This commit is contained in:
Robby Findler 2006-07-06 02:08:12 +00:00
parent 8fa40a972a
commit 79ae279b79
7 changed files with 778 additions and 286 deletions

View File

@ -9,5 +9,7 @@
(all-from "private/contract-ds.ss") (all-from "private/contract-ds.ss")
(all-from "private/contract-arrow.ss") (all-from "private/contract-arrow.ss")
(all-from-except "private/contract-guts.ss" (all-from-except "private/contract-guts.ss"
build-compound-type-name) build-compound-type-name
first-order-prop
first-order-get)
(all-from "private/contract.ss"))) (all-from "private/contract.ss")))

View File

@ -32,10 +32,10 @@
(raise-syntax-error 'any "Use any out of an arrow contract" stx)) (raise-syntax-error 'any "Use any out of an arrow contract" stx))
;; FIXME: need to pass in the name of the contract combinator. ;; FIXME: need to pass in the name of the contract combinator.
(define (build--> doms doms-rest rngs rng-any? func) (define (build--> name doms doms-rest rngs rng-any? func)
(let ([doms/c (map (λ (dom) (coerce-contract -> dom)) doms)] (let ([doms/c (map (λ (dom) (coerce-contract name dom)) doms)]
[rngs/c (map (λ (rng) (coerce-contract -> rng)) rngs)] [rngs/c (map (λ (rng) (coerce-contract name rng)) rngs)]
[doms-rest/c (and doms-rest (coerce-contract -> doms-rest))]) [doms-rest/c (and doms-rest (coerce-contract name doms-rest))])
(make--> rng-any? doms/c doms-rest/c rngs/c func))) (make--> rng-any? doms/c doms-rest/c rngs/c func)))
(define-struct/prop -> (rng-any? doms dom-rest rngs func) (define-struct/prop -> (rng-any? doms dom-rest rngs func)
@ -79,6 +79,16 @@
(->-dom-rest ctc) (->-dom-rest ctc)
(->-rng-any? ctc) (->-rng-any? ctc)
(->-rngs ctc)))) (->-rngs ctc))))
(first-order-prop
(λ (ctc)
(let ([l (length (->-doms ctc))])
(if (->-dom-rest ctc)
(λ (x)
(and (procedure? x)
(procedure-accepts-and-more? x l)))
(λ (x)
(and (procedure? x)
(procedure-arity-includes? x l)))))))
(stronger-prop (stronger-prop
(λ (this that) (λ (this that)
(and (->? that) (and (->? that)
@ -137,7 +147,8 @@
(chk val) (chk val)
inner-lambda)))]) inner-lambda)))])
(values (values
(syntax (build--> (list dom-ctcs ...) (syntax (build--> '->
(list dom-ctcs ...)
#f #f
(list rng-ctcs ...) (list rng-ctcs ...)
use-any? use-any?
@ -213,7 +224,8 @@
(lambda (val) (lambda (val)
(chk val) (chk val)
inner-lambda)))]) inner-lambda)))])
(values (syntax (build--> (list doms ...) (values (syntax (build--> '->*
(list doms ...)
rst rst
(list rngs ...) (list rngs ...)
#f #f
@ -238,7 +250,8 @@
(lambda (val) (lambda (val)
(chk val) (chk val)
inner-lambda)))]) inner-lambda)))])
(values (syntax (build--> (list doms ...) (values (syntax (build--> '->*
(list doms ...)
rst rst
(list any/c) (list any/c)
#t #t
@ -246,6 +259,9 @@
inner-args/body inner-args/body
(syntax (dom-x ... rst-x)))))))]))) (syntax (dom-x ... rst-x)))))))])))
(define empty-case-lambda/c
(flat-named-contract '(case->)
(λ (x) (and (procedure? x) (null? (procedure-arity x))))))
(define-syntax-set (->/real ->*/real ->d ->d* ->r ->pp ->pp-rest case-> object-contract opt-> opt->*) (define-syntax-set (->/real ->*/real ->d ->d* ->r ->pp ->pp-rest case-> object-contract opt-> opt->*)
@ -278,7 +294,10 @@
;; syntax ;; syntax
;; -> (syntax -> syntax) ;; -> (syntax -> syntax)
(define (make-/proc method-proc? /h stx) (define (make-/proc method-proc? /h stx)
(let-values ([(arguments-check build-pos-proj build-neg-proj check-val pos-wrapper neg-wrapper) (/h method-proc? stx)]) (let-values ([(arguments-check build-pos-proj build-neg-proj
check-val first-order-check
pos-wrapper neg-wrapper)
(/h method-proc? stx)])
(let ([outer-args (syntax (val blame src-info orig-str name-id))]) (let ([outer-args (syntax (val blame src-info orig-str name-id))])
(with-syntax ([inner-check (check-val outer-args)] (with-syntax ([inner-check (check-val outer-args)]
[(val blame src-info orig-str name-id) outer-args] [(val blame src-info orig-str name-id) outer-args]
@ -302,7 +321,8 @@
(lambda (val) (lambda (val)
inner-neg-lambda))]) inner-neg-lambda))])
(with-syntax ([pos-proj-code (build-pos-proj outer-args inner-pos-lambda-w/err-check)] (with-syntax ([pos-proj-code (build-pos-proj outer-args inner-pos-lambda-w/err-check)]
[neg-proj-code (build-neg-proj outer-args inner-neg-lambda)]) [neg-proj-code (build-neg-proj outer-args inner-neg-lambda)]
[first-order-check first-order-check])
(arguments-check (arguments-check
outer-args outer-args
(syntax/loc stx (syntax/loc stx
@ -311,16 +331,22 @@
(lambda (blame src-info orig-str) (lambda (blame src-info orig-str)
pos-proj-code) pos-proj-code)
(lambda (blame src-info orig-str) (lambda (blame src-info orig-str)
neg-proj-code))))))))))) neg-proj-code)
first-order-check))))))))))
(define (make-case->/proc method-proc? stx inferred-name-stx) (define (make-case->/proc method-proc? stx inferred-name-stx)
(syntax-case stx () (syntax-case stx ()
;; if there are no cases, this contract should only accept the "empty" case-lambda.
[(_) (syntax empty-case-lambda/c)]
;; if there is only a single case, just skip it. ;; if there is only a single case, just skip it.
[(_ case) (syntax case)] [(_ case) (syntax case)]
[(_ cases ...) [(_ cases ...)
(let-values ([(arguments-check build-pos-projs build-neg-projs check-val pos-wrapper neg-wrapper) (let-values ([(arguments-check build-pos-projs build-neg-projs
check-val first-order-check
pos-wrapper neg-wrapper)
(case->/h method-proc? stx (syntax->list (syntax (cases ...))))]) (case->/h method-proc? stx (syntax->list (syntax (cases ...))))])
(let ([outer-args (syntax (val blame src-info orig-str name-id))]) (let ([outer-args (syntax (val blame src-info orig-str name-id))])
(with-syntax ([(inner-check ...) (check-val outer-args)] (with-syntax ([(inner-check ...) (check-val outer-args)]
@ -342,7 +368,8 @@
inner-pos-lambda))] inner-pos-lambda))]
[inner-neg-lambda (syntax (lambda (val) inner-neg-lambda))]) [inner-neg-lambda (syntax (lambda (val) inner-neg-lambda))])
(with-syntax ([pos-proj-code (build-pos-projs outer-args inner-pos-lambda-w/err-check)] (with-syntax ([pos-proj-code (build-pos-projs outer-args inner-pos-lambda-w/err-check)]
[neg-proj-code (build-neg-projs outer-args inner-neg-lambda)]) [neg-proj-code (build-neg-projs outer-args inner-neg-lambda)]
[first-order-check first-order-check])
(arguments-check (arguments-check
outer-args outer-args
(syntax/loc stx (syntax/loc stx
@ -351,7 +378,8 @@
(lambda (blame src-info orig-str) (lambda (blame src-info orig-str)
pos-proj-code) pos-proj-code)
(lambda (blame src-info orig-str) (lambda (blame src-info orig-str)
neg-proj-code))))))))))])) neg-proj-code)
first-order-check)))))))))]))
(define (make-opt->/proc method-proc? stx) (define (make-opt->/proc method-proc? stx)
(syntax-case stx (any) (syntax-case stx (any)
@ -506,14 +534,19 @@
(lambda (x y) y) (lambda (x y) y)
(lambda (x y) y) (lambda (x y) y)
(lambda (args) (syntax ())) (lambda (args) (syntax ()))
(syntax (lambda (x) #t))
(lambda (args) (syntax ())) (lambda (args) (syntax ()))
(lambda (args) (syntax ())))] (lambda (args) (syntax ())))]
[else [else
(let ([/h (select/h (car cases) 'case-> orig-stx)] (let ([/h (select/h (car cases) 'case-> orig-stx)]
[new-id (car (generate-temporaries (syntax (case->name-id))))]) [new-id (car (generate-temporaries (syntax (case->name-id))))])
(let-values ([(arguments-checks build-pos-projs build-neg-projs check-vals pos-wrappers neg-wrappers) (let-values ([(arguments-checks build-pos-projs build-neg-projs
check-vals first-order-checks
pos-wrappers neg-wrappers)
(loop (cdr cases) (cons new-id name-ids))] (loop (cdr cases) (cons new-id name-ids))]
[(arguments-check build-pos-proj build-neg-proj check-val pos-wrapper neg-wrapper) [(arguments-check build-pos-proj build-neg-proj
check-val first-order-check
pos-wrapper neg-wrapper)
(/h method-proc? (car cases))]) (/h method-proc? (car cases))])
(values (values
(lambda (outer-args x) (lambda (outer-args x)
@ -530,6 +563,9 @@
(with-syntax ([checks (check-vals args)] (with-syntax ([checks (check-vals args)]
[check (check-val args)]) [check (check-val args)])
(syntax (check . checks)))) (syntax (check . checks))))
(with-syntax ([checks first-order-checks]
[check first-order-check])
(syntax (lambda (x) (and (checks x) (check x)))))
(lambda (args) (lambda (args)
(with-syntax ([case (pos-wrapper args)] (with-syntax ([case (pos-wrapper args)]
[cases (pos-wrappers args)]) [cases (pos-wrappers args)])
@ -820,7 +856,7 @@
(syntax (syntax
(let ([method-ctc-var method-ctc-stx] (let ([method-ctc-var method-ctc-stx]
... ...
[field-ctc-var (coerce-contract object-contract field-ctc-stx)] [field-ctc-var (coerce-contract 'object-contract field-ctc-stx)]
...) ...)
(let ([method-pos-var (contract-pos-proc method-ctc-var)] (let ([method-pos-var (contract-pos-proc method-ctc-var)]
... ...
@ -877,7 +913,8 @@
val val
(method/app-var (vector-ref vtable (hash-table-get method-ht 'method-name))) ... (method/app-var (vector-ref vtable (hash-table-get method-ht 'method-name))) ...
(field/app-var (get-field field-name val)) ... (field/app-var (get-field field-name val)) ...
)))))))))))))])) ))))))
#f)))))))]))
;; ensure-no-duplicates : syntax (listof syntax[identifier]) -> void ;; ensure-no-duplicates : syntax (listof syntax[identifier]) -> void
(define (ensure-no-duplicates stx form-name names) (define (ensure-no-duplicates stx form-name names)
@ -933,6 +970,9 @@
;; - [check-val] ;; - [check-val]
;; code that does error checking on the contract'd value itself ;; code that does error checking on the contract'd value itself
;; (is it a function of the right arity?) ;; (is it a function of the right arity?)
;; - [first-order-check]
;; predicate function that does the first order check and returns a boolean
;; (is it a function of the right arity?)
;; - [pos-wrapper] ;; - [pos-wrapper]
;; a piece of syntax that has the arguments to the wrapper ;; a piece of syntax that has the arguments to the wrapper
;; and the body of the wrapper. ;; and the body of the wrapper.
@ -982,7 +1022,7 @@
(with-syntax ([body body] (with-syntax ([body body]
[(val blame src-info orig-str name-id) outer-args]) [(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(let ([dom-contract-x (coerce-contract -> dom)] ...) (let ([dom-contract-x (coerce-contract '-> dom)] ...)
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] ...) [dom-neg-x (contract-neg-proc dom-contract-x)] ...)
@ -1009,7 +1049,7 @@
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(check-procedure val dom-length src-info blame orig-str)))) (check-procedure val dom-length src-info blame orig-str))))
(syntax (check-procedure? dom-length))
wrap wrap
wrap))] wrap))]
[(values rng ...) [(values rng ...)
@ -1034,9 +1074,9 @@
(with-syntax ([body body] (with-syntax ([body body]
[(val blame src-info orig-str name-id) outer-args]) [(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(let ([dom-contract-x (coerce-contract -> dom)] (let ([dom-contract-x (coerce-contract '-> dom)]
... ...
[rng-contract-x (coerce-contract -> rng)] ...) [rng-contract-x (coerce-contract '-> rng)] ...)
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] [dom-neg-x (contract-neg-proc dom-contract-x)]
@ -1075,7 +1115,7 @@
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(check-procedure val dom-length src-info blame orig-str)))) (check-procedure val dom-length src-info blame orig-str))))
(syntax (check-procedure? dom-length))
wrap wrap
wrap)))] wrap)))]
[rng [rng
@ -1097,9 +1137,9 @@
(with-syntax ([body body] (with-syntax ([body body]
[(val blame src-info orig-str name-id) outer-args]) [(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(let ([dom-contract-x (coerce-contract -> dom)] (let ([dom-contract-x (coerce-contract '-> dom)]
... ...
[rng-contract-x (coerce-contract -> rng)]) [rng-contract-x (coerce-contract '-> rng)])
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] [dom-neg-x (contract-neg-proc dom-contract-x)]
@ -1133,7 +1173,7 @@
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(check-procedure val dom-length src-info blame orig-str)))) (check-procedure val dom-length src-info blame orig-str))))
(syntax (check-procedure? dom-length))
wrap wrap
wrap)))])))])) wrap)))])))]))
@ -1188,9 +1228,10 @@
(syntax (dom-contract-x ...)))) (syntax (dom-contract-x ...))))
(syntax (dom-contract-x ...)))]) (syntax (dom-contract-x ...)))])
(syntax (syntax
(let ([dom-contract-x (coerce-contract ->* dom)] ... (let ([dom-contract-x (coerce-contract '->* dom)]
[dom-rest-contract-x (coerce-contract ->* rest)] ...
[rng-contract-x (coerce-contract ->* rng)] ...) [dom-rest-contract-x (coerce-contract '->* rest)]
[rng-contract-x (coerce-contract '->* rng)] ...)
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] [dom-neg-x (contract-neg-proc dom-contract-x)]
@ -1234,7 +1275,7 @@
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(check-procedure/more val dom-length src-info blame orig-str)))) (check-procedure/more val dom-length src-info blame orig-str))))
(syntax (check-procedure/more? dom-length))
wrap wrap
wrap)))] wrap)))]
[(_ (dom ...) rest any) [(_ (dom ...) rest any)
@ -1273,9 +1314,9 @@
(syntax (dom-contract-x ...)))) (syntax (dom-contract-x ...))))
(syntax (dom-contract-x ...)))]) (syntax (dom-contract-x ...)))])
(syntax (syntax
(let ([dom-contract-x (coerce-contract ->* dom)] (let ([dom-contract-x (coerce-contract '->* dom)]
... ...
[dom-rest-contract-x (coerce-contract ->* rest)]) [dom-rest-contract-x (coerce-contract '->* rest)])
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] [dom-neg-x (contract-neg-proc dom-contract-x)]
@ -1312,6 +1353,7 @@
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(check-procedure/more val dom-length src-info blame orig-str)))) (check-procedure/more val dom-length src-info blame orig-str))))
(syntax (check-procedure/more? dom-length))
wrap wrap
wrap)))])) wrap)))]))
@ -1338,7 +1380,7 @@
(syntax (dom-contract-x ...)))) (syntax (dom-contract-x ...))))
(syntax (dom-contract-x ...)))]) (syntax (dom-contract-x ...)))])
(syntax (syntax
(let ([dom-contract-x (coerce-contract ->d dom)] ...) (let ([dom-contract-x (coerce-contract '->d dom)] ...)
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] ... [dom-neg-x (contract-neg-proc dom-contract-x)] ...
@ -1368,6 +1410,8 @@
(syntax (syntax
(check-procedure val arity src-info blame orig-str)))) (check-procedure val arity src-info blame orig-str))))
(syntax (check-procedure? arity))
;; pos ;; pos
(lambda (outer-args) (lambda (outer-args)
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
@ -1375,7 +1419,7 @@
((arg-x ...) ((arg-x ...)
(let ([arg-x (dom-projection-x arg-x)] ...) (let ([arg-x (dom-projection-x arg-x)] ...)
(let ([rng-contract (rng-x arg-x ...)]) (let ([rng-contract (rng-x arg-x ...)])
(((contract-pos-proc (coerce-contract ->d rng-contract)) (((contract-pos-proc (coerce-contract '->d rng-contract))
blame blame
src-info src-info
orig-str) orig-str)
@ -1388,7 +1432,7 @@
((arg-x ...) ((arg-x ...)
(let ([arg-x (dom-projection-x arg-x)] ...) (let ([arg-x (dom-projection-x arg-x)] ...)
(let ([rng-contract (rng-x arg-x ...)]) (let ([rng-contract (rng-x arg-x ...)])
(((contract-neg-proc (coerce-contract ->d rng-contract)) (((contract-neg-proc (coerce-contract '->d rng-contract))
blame blame
src-info src-info
orig-str) orig-str)
@ -1423,7 +1467,7 @@
(apply (apply
values values
(map (lambda (rng-contract result) (map (lambda (rng-contract result)
(((extract-proc (coerce-contract ->d* rng-contract)) (((extract-proc (coerce-contract '->d* rng-contract))
blame blame
src-info src-info
orig-str) orig-str)
@ -1441,7 +1485,7 @@
(syntax (dom-contract-x ...)))) (syntax (dom-contract-x ...))))
(syntax (dom-contract-x ...)))]) (syntax (dom-contract-x ...)))])
(syntax (syntax
(let ([dom-contract-x (coerce-contract ->d* dom)] ...) (let ([dom-contract-x (coerce-contract '->d* dom)] ...)
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] ... [dom-neg-x (contract-neg-proc dom-contract-x)] ...
@ -1473,7 +1517,7 @@
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(check-procedure val dom-length src-info blame orig-str)))) (check-procedure val dom-length src-info blame orig-str))))
(syntax (check-procedure? dom-length))
(mk-wrap (syntax contract-pos-proc)) (mk-wrap (syntax contract-pos-proc))
(mk-wrap (syntax contract-neg-proc)))))] (mk-wrap (syntax contract-neg-proc)))))]
[(_ (dom ...) rest rng-mk) [(_ (dom ...) rest rng-mk)
@ -1510,7 +1554,7 @@
(apply (apply
values values
(map (lambda (rng-contract result) (map (lambda (rng-contract result)
(((extract-proj (coerce-contract ->d* rng-contract)) (((extract-proj (coerce-contract '->d* rng-contract))
blame blame
src-info src-info
orig-str) orig-str)
@ -1528,9 +1572,9 @@
(syntax (dom-contract-x ...)))) (syntax (dom-contract-x ...))))
(syntax (dom-contract-x ...)))]) (syntax (dom-contract-x ...)))])
(syntax (syntax
(let ([dom-contract-x (coerce-contract ->d* dom)] (let ([dom-contract-x (coerce-contract '->d* dom)]
... ...
[dom-rest-contract-x (coerce-contract ->d* rest)]) [dom-rest-contract-x (coerce-contract '->d* rest)])
(let ([dom-pos-x (contract-pos-proc dom-contract-x)] (let ([dom-pos-x (contract-pos-proc dom-contract-x)]
... ...
[dom-neg-x (contract-neg-proc dom-contract-x)] ... [dom-neg-x (contract-neg-proc dom-contract-x)] ...
@ -1569,6 +1613,7 @@
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
(syntax (syntax
(check-procedure/more val arity src-info blame orig-str)))) (check-procedure/more val arity src-info blame orig-str))))
(syntax (check-procedure/more? arity))
(mk-wrap (syntax contract-pos-proc)) (mk-wrap (syntax contract-pos-proc))
(mk-wrap (syntax contract-neg-proc)))))])) (mk-wrap (syntax contract-neg-proc)))))]))
@ -1633,6 +1678,9 @@
(syntax (syntax
(begin (begin
(check-procedure/kind val arity 'kind-of-thing src-info blame orig-str))))) (check-procedure/kind val arity 'kind-of-thing src-info blame orig-str)))))
(syntax (check-procedure? arity))
;; pos ;; pos
(lambda (outer-args) (lambda (outer-args)
(with-syntax ([(val blame src-info orig-str name-id) outer-args]) (with-syntax ([(val blame src-info orig-str name-id) outer-args])
@ -1640,7 +1688,7 @@
[(any) [(any)
(syntax (syntax
((x ...) ((x ...)
(let ([dom-id ((contract-neg-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-neg-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
...) ...)
(val (dom-id x) ...))))] (val (dom-id x) ...))))]
[((values (rng-ids rng-ctc) ...) post-expr) [((values (rng-ids rng-ctc) ...) post-expr)
@ -1650,11 +1698,11 @@
(syntax (syntax
((x ...) ((x ...)
(begin (begin
(let ([dom-id ((contract-neg-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-neg-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
...) ...)
(let-values ([(rng-ids ...) (val (dom-id x) ...)]) (let-values ([(rng-ids ...) (val (dom-id x) ...)])
(check-post-expr->pp/h val post-expr src-info blame orig-str) (check-post-expr->pp/h val post-expr src-info blame orig-str)
(let ([rng-ids-x ((contract-pos-proc (coerce-contract stx-name rng-ctc)) (let ([rng-ids-x ((contract-pos-proc (coerce-contract 'stx-name rng-ctc))
blame src-info orig-str)] ...) blame src-info orig-str)] ...)
(values (rng-ids-x rng-ids) ...))))))))] (values (rng-ids-x rng-ids) ...))))))))]
[((values (rng-ids rng-ctc) ...) post-expr) [((values (rng-ids rng-ctc) ...) post-expr)
@ -1671,9 +1719,9 @@
[(rng res-id post-expr) [(rng res-id post-expr)
(syntax (syntax
((x ...) ((x ...)
(let ([dom-id ((contract-neg-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-neg-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rng-id ((contract-pos-proc (coerce-contract stx-name rng)) blame src-info orig-str)]) [rng-id ((contract-pos-proc (coerce-contract 'stx-name rng)) blame src-info orig-str)])
(let ([res-id (rng-id (val (dom-id x) ...))]) (let ([res-id (rng-id (val (dom-id x) ...))])
(check-post-expr->pp/h val post-expr src-info blame orig-str) (check-post-expr->pp/h val post-expr src-info blame orig-str)
res-id))))] res-id))))]
@ -1689,7 +1737,7 @@
((x ...) ((x ...)
(begin (begin
(check-pre-expr->pp/h val pre-expr src-info blame orig-str) (check-pre-expr->pp/h val pre-expr src-info blame orig-str)
(let ([dom-id ((contract-pos-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-pos-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
...) ...)
(val (dom-id x) ...)))))] (val (dom-id x) ...)))))]
[((values (rng-ids rng-ctc) ...) post-expr) [((values (rng-ids rng-ctc) ...) post-expr)
@ -1700,10 +1748,10 @@
((x ...) ((x ...)
(begin (begin
(check-pre-expr->pp/h val pre-expr src-info blame orig-str) (check-pre-expr->pp/h val pre-expr src-info blame orig-str)
(let ([dom-id ((contract-pos-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-pos-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
...) ...)
(let-values ([(rng-ids ...) (val (dom-id x) ...)]) (let-values ([(rng-ids ...) (val (dom-id x) ...)])
(let ([rng-ids-x ((contract-neg-proc (coerce-contract stx-name rng-ctc)) (let ([rng-ids-x ((contract-neg-proc (coerce-contract 'stx-name rng-ctc))
blame src-info orig-str)] ...) blame src-info orig-str)] ...)
(values (rng-ids-x rng-ids) ...))))))))] (values (rng-ids-x rng-ids) ...))))))))]
[((values (rng-ids rng-ctc) ...) post-expr) [((values (rng-ids rng-ctc) ...) post-expr)
@ -1722,9 +1770,9 @@
((x ...) ((x ...)
(begin (begin
(check-pre-expr->pp/h val pre-expr src-info blame orig-str) (check-pre-expr->pp/h val pre-expr src-info blame orig-str)
(let ([dom-id ((contract-pos-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-pos-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rng-id ((contract-neg-proc (coerce-contract stx-name rng)) blame src-info orig-str)]) [rng-id ((contract-neg-proc (coerce-contract 'stx-name rng)) blame src-info orig-str)])
(rng-id (val (dom-id x) ...))))))] (rng-id (val (dom-id x) ...))))))]
[_ [_
(raise-syntax-error name "unknown result specification" stx (syntax result-stuff))]))))))] (raise-syntax-error name "unknown result specification" stx (syntax result-stuff))]))))))]
@ -1785,6 +1833,7 @@
(syntax (syntax
(begin (begin
(check-procedure/more/kind val arity 'kind-of-thing src-info blame orig-str))))) (check-procedure/more/kind val arity 'kind-of-thing src-info blame orig-str)))))
(syntax (check-procedure/more? arity))
;; pos ;; pos
(lambda (outer-args) (lambda (outer-args)
@ -1793,9 +1842,9 @@
[(any) [(any)
(syntax (syntax
((x ... . rest-x) ((x ... . rest-x)
(let ([dom-id ((contract-neg-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-neg-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rest-id ((contract-neg-proc (coerce-contract stx-name rest-dom)) blame src-info orig-str)]) [rest-id ((contract-neg-proc (coerce-contract 'stx-name rest-dom)) blame src-info orig-str)])
(apply val (dom-id x) ... (rest-id rest-x)))))] (apply val (dom-id x) ... (rest-id rest-x)))))]
[(any . x) [(any . x)
(raise-syntax-error name "cannot have anything after any" stx (syntax result-stuff))] (raise-syntax-error name "cannot have anything after any" stx (syntax result-stuff))]
@ -1805,12 +1854,12 @@
(with-syntax ([(rng-ids-x ...) (generate-temporaries (syntax (rng-ids ...)))]) (with-syntax ([(rng-ids-x ...) (generate-temporaries (syntax (rng-ids ...)))])
(syntax (syntax
((x ... . rest-x) ((x ... . rest-x)
(let ([dom-id ((contract-neg-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-neg-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rest-id ((contract-neg-proc (coerce-contract stx-name rest-dom)) blame src-info orig-str)]) [rest-id ((contract-neg-proc (coerce-contract 'stx-name rest-dom)) blame src-info orig-str)])
(let-values ([(rng-ids ...) (apply val (dom-id x) ... (rest-id rest-x))]) (let-values ([(rng-ids ...) (apply val (dom-id x) ... (rest-id rest-x))])
(check-post-expr->pp/h val post-expr src-info blame orig-str) (check-post-expr->pp/h val post-expr src-info blame orig-str)
(let ([rng-ids-x ((contract-pos-proc (coerce-contract stx-name rng-ctc)) (let ([rng-ids-x ((contract-pos-proc (coerce-contract 'stx-name rng-ctc))
blame src-info orig-str)] ...) blame src-info orig-str)] ...)
(values (rng-ids-x rng-ids) ...)))))))] (values (rng-ids-x rng-ids) ...)))))))]
[((values (rng-ids rng-ctc) ...) . whatever) [((values (rng-ids rng-ctc) ...) . whatever)
@ -1832,10 +1881,10 @@
(identifier? (syntax res-id)) (identifier? (syntax res-id))
(syntax (syntax
((x ... . rest-x) ((x ... . rest-x)
(let ([dom-id ((contract-neg-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-neg-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rest-id ((contract-neg-proc (coerce-contract stx-name rest-dom)) blame src-info orig-str)] [rest-id ((contract-neg-proc (coerce-contract 'stx-name rest-dom)) blame src-info orig-str)]
[rng-id ((contract-pos-proc (coerce-contract stx-name rng)) blame src-info orig-str)]) [rng-id ((contract-pos-proc (coerce-contract 'stx-name rng)) blame src-info orig-str)])
(let ([res-id (rng-id (apply val (dom-id x) ... (rest-id rest-x)))]) (let ([res-id (rng-id (apply val (dom-id x) ... (rest-id rest-x)))])
(check-post-expr->pp/h val post-expr src-info blame orig-str) (check-post-expr->pp/h val post-expr src-info blame orig-str)
res-id))))] res-id))))]
@ -1854,9 +1903,9 @@
((x ... . rest-x) ((x ... . rest-x)
(begin (begin
(check-pre-expr->pp/h val pre-expr src-info blame orig-str) (check-pre-expr->pp/h val pre-expr src-info blame orig-str)
(let ([dom-id ((contract-pos-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-pos-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rest-id ((contract-pos-proc (coerce-contract stx-name rest-dom)) blame src-info orig-str)]) [rest-id ((contract-pos-proc (coerce-contract 'stx-name rest-dom)) blame src-info orig-str)])
(apply val (dom-id x) ... (rest-id rest-x))))))] (apply val (dom-id x) ... (rest-id rest-x))))))]
[(any . x) [(any . x)
(raise-syntax-error name "cannot have anything after any" stx (syntax result-stuff))] (raise-syntax-error name "cannot have anything after any" stx (syntax result-stuff))]
@ -1868,11 +1917,11 @@
((x ... . rest-x) ((x ... . rest-x)
(begin (begin
(check-pre-expr->pp/h val pre-expr src-info blame orig-str) (check-pre-expr->pp/h val pre-expr src-info blame orig-str)
(let ([dom-id ((contract-pos-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-pos-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rest-id ((contract-pos-proc (coerce-contract stx-name rest-dom)) blame src-info orig-str)]) [rest-id ((contract-pos-proc (coerce-contract 'stx-name rest-dom)) blame src-info orig-str)])
(let-values ([(rng-ids ...) (apply val (dom-id x) ... (rest-id rest-x))]) (let-values ([(rng-ids ...) (apply val (dom-id x) ... (rest-id rest-x))])
(let ([rng-ids-x ((contract-neg-proc (coerce-contract stx-name rng-ctc)) (let ([rng-ids-x ((contract-neg-proc (coerce-contract 'stx-name rng-ctc))
blame src-info orig-str)] ...) blame src-info orig-str)] ...)
(values (rng-ids-x rng-ids) ...))))))))] (values (rng-ids-x rng-ids) ...))))))))]
[((values (rng-ids rng-ctc) ...) . whatever) [((values (rng-ids rng-ctc) ...) . whatever)
@ -1896,10 +1945,10 @@
((x ... . rest-x) ((x ... . rest-x)
(begin (begin
(check-pre-expr->pp/h val pre-expr src-info blame orig-str) (check-pre-expr->pp/h val pre-expr src-info blame orig-str)
(let ([dom-id ((contract-pos-proc (coerce-contract stx-name dom)) blame src-info orig-str)] (let ([dom-id ((contract-pos-proc (coerce-contract 'stx-name dom)) blame src-info orig-str)]
... ...
[rest-id ((contract-pos-proc (coerce-contract stx-name rest-dom)) blame src-info orig-str)] [rest-id ((contract-pos-proc (coerce-contract 'stx-name rest-dom)) blame src-info orig-str)]
[rng-id ((contract-neg-proc (coerce-contract stx-name rng)) blame src-info orig-str)]) [rng-id ((contract-neg-proc (coerce-contract 'stx-name rng)) blame src-info orig-str)])
(rng-id (apply val (dom-id x) ... (rest-id rest-x)))))))] (rng-id (apply val (dom-id x) ... (rest-id rest-x)))))))]
[(rng res-id post-expr) [(rng res-id post-expr)
(not (identifier? (syntax res-id))) (not (identifier? (syntax res-id)))
@ -2054,6 +2103,14 @@
"expected a procedure that accepts ~a arguments, given: ~e" "expected a procedure that accepts ~a arguments, given: ~e"
dom-length dom-length
val))) val)))
(define ((check-procedure? arity) val)
(and (procedure? val)
(procedure-arity-includes? val arity)))
(define ((check-procedure/more? arity) val)
(and (procedure? val)
(procedure-accepts-and-more? val arity)))
(define (check-procedure/kind val arity kind-of-thing src-info blame orig-str) (define (check-procedure/kind val arity kind-of-thing src-info blame orig-str)
(unless (procedure? val) (unless (procedure? val)

View File

@ -67,7 +67,7 @@ which are then called when the contract's fields are explored
(syntax (x ...)) (syntax (x ...))
field-names) field-names)
#,(defeat-inlining #,(defeat-inlining
#`(#,coerce-contract #,name ctc-exp)))]) #`(#,coerce-contract '#,name ctc-exp)))])
(loop (cdr clauses) (loop (cdr clauses)
(cdr ac-ids) (cdr ac-ids)
(cons (car ac-ids) prior-ac-ids) (cons (car ac-ids) prior-ac-ids)
@ -84,7 +84,7 @@ which are then called when the contract's fields are explored
(loop (cdr clauses) (loop (cdr clauses)
(cdr ac-ids) (cdr ac-ids)
(cons (car ac-ids) prior-ac-ids) (cons (car ac-ids) prior-ac-ids)
(cons #`(#,coerce-contract #,name ctc-exp) maker-args))] (cons #`(#,coerce-contract '#,name ctc-exp) maker-args))]
[(id ctc-exp) [(id ctc-exp)
(raise-syntax-error name "expected identifier" stx (syntax id))]))])))) (raise-syntax-error name "expected identifier" stx (syntax id))]))]))))

View File

@ -193,7 +193,7 @@ it around flattened out.
#f])) #f]))
(define (struct/c ctc-x ...) (define (struct/c ctc-x ...)
(let ([ctc-x (coerce-contract struct/c ctc-x)] ...) (let ([ctc-x (coerce-contract 'struct/c ctc-x)] ...)
(contract-maker ctc-x ...))) (contract-maker ctc-x ...)))
(define (selectors x) (burrow-in x 'selectors selector-indicies)) ... (define (selectors x) (burrow-in x 'selectors selector-indicies)) ...
@ -233,6 +233,7 @@ it around flattened out.
(list (cons pos-proj-prop lazy-contract-pos-proj) (list (cons pos-proj-prop lazy-contract-pos-proj)
(cons neg-proj-prop lazy-contract-neg-proj) (cons neg-proj-prop lazy-contract-neg-proj)
(cons name-prop lazy-contract-name) (cons name-prop lazy-contract-name)
(cons first-order-prop (λ (ctc) predicate))
(cons stronger-prop stronger-lazy-contract?)))))))])) (cons stronger-prop stronger-lazy-contract?)))))))]))
(define-struct contract/info (contract pos neg src-info orig-str)) (define-struct contract/info (contract pos neg src-info orig-str))

View File

@ -8,7 +8,6 @@
(provide raise-contract-error (provide raise-contract-error
contract-violation->string contract-violation->string
coerce-contract coerce-contract
coerce/select-contract
flat-contract/predicate? flat-contract/predicate?
flat-contract? flat-contract?
@ -20,6 +19,8 @@
and/c and/c
any/c any/c
none/c
make-none/c
contract? contract?
contract-name contract-name
@ -32,6 +33,8 @@
define-struct/prop define-struct/prop
contract-stronger? contract-stronger?
contract-first-order-passes?
proj-pred? proj-get proj-pred? proj-get
pos-proj-prop pos-proj-pred? pos-proj-get pos-proj-prop pos-proj-pred? pos-proj-get
@ -40,7 +43,10 @@
stronger-prop stronger-pred? stronger-get stronger-prop stronger-pred? stronger-get
flat-prop flat-pred? flat-get flat-prop flat-pred? flat-get
any-curried-proj any-curried-proj
flat-pos-proj) flat-pos-proj
first-order-prop
first-order-get)
;; define-struct/prop is a define-struct-like macro that ;; define-struct/prop is a define-struct-like macro that
@ -94,12 +100,26 @@
(make-struct-type-property 'contract-stronger-than)) (make-struct-type-property 'contract-stronger-than))
(define-values (flat-prop flat-pred? flat-get) (define-values (flat-prop flat-pred? flat-get)
(make-struct-type-property 'contract-flat)) (make-struct-type-property 'contract-flat))
(define-values (first-order-prop first-order-pred? first-order-get)
(make-struct-type-property 'contract-first-order))
(define-values (pos-proj-prop pos-proj-pred? pos-proj-get) (define-values (pos-proj-prop pos-proj-pred? pos-proj-get)
(make-struct-type-property 'contract-positive-projection)) (make-struct-type-property 'contract-positive-projection))
(define-values (neg-proj-prop neg-proj-pred? neg-proj-get) (define-values (neg-proj-prop neg-proj-pred? neg-proj-get)
(make-struct-type-property 'contract-negative-projection)) (make-struct-type-property 'contract-negative-projection))
(define (contract-first-order-passes? c v)
(cond
[(first-order-pred? c) (((first-order-get c) c) v)]
[(and (procedure? c)
(procedure-arity-includes? c 1))
;; flat contract as a predicate
(c v)]
[(flat-pred? c) (((flat-get c) c) v)]
[else (error 'contract-first-order-passes?
"expected a contract as first argument, got ~e, other arg ~e" c v)]))
(define (proj-get ctc) (define (proj-get ctc)
(cond (cond
[(proj-pred? ctc) [(proj-pred? ctc)
@ -120,40 +140,16 @@
;; indicates if one contract is stronger (ie, likes fewer values) than another ;; indicates if one contract is stronger (ie, likes fewer values) than another
;; this is not a total order. ;; this is not a total order.
(define (contract-stronger? a b) (define (contract-stronger? a b)
(let ([a-ctc (coerce-contract contract-stronger? a)] (let ([a-ctc (coerce-contract 'contract-stronger? a)]
[b-ctc (coerce-contract contract-stronger? b)]) [b-ctc (coerce-contract 'contract-stronger? b)])
((stronger-get a-ctc) a-ctc b-ctc))) ((stronger-get a-ctc) a-ctc b-ctc)))
;; coerce/select-contract : id (union contract? procedure-arity-1) -> contract-proc
;; contract-proc = sym sym stx -> alpha -> alpha
;; returns the procedure for the contract after extracting it from the
;; struct. Coerces the argument to a flat contract if it is procedure, but first.
(define-syntax (coerce/select-contract stx)
(syntax-case stx ()
[(_ name val)
(syntax (coerce/select-contract/proc 'name val))]))
(define (coerce/select-contract/proc name x)
(cond
[(contract? x)
(contract-proc x)]
[(and (procedure? x) (procedure-arity-includes? x 1))
(contract-proc (flat-contract x))]
[else
(error name
"expected contract or procedure of arity 1, got ~e"
x)]))
;; coerce-contract : id (union contract? procedure-arity-1) -> contract ;; coerce-contract : id (union contract? procedure-arity-1) -> contract
;; contract-proc = sym sym stx -> alpha -> alpha ;; contract-proc = sym sym stx -> alpha -> alpha
;; returns the procedure for the contract after extracting it from the ;; returns the procedure for the contract after extracting it from the
;; struct. Coerces the argument to a flat contract if it is procedure, but first. ;; struct. Coerces the argument to a flat contract if it is procedure, but first.
(define-syntax (coerce-contract stx) (define (coerce-contract name x)
(syntax-case stx ()
[(_ name val)
(syntax (coerce-contract/proc 'name val))]))
(define (coerce-contract/proc name x)
(cond (cond
[(contract? x) x] [(contract? x) x]
[(and (procedure? x) (procedure-arity-includes? x 1)) [(and (procedure? x) (procedure-arity-includes? x 1))
@ -307,10 +303,12 @@
(define-values (make-flat-contract (define-values (make-flat-contract
make-pair-proj-contract) make-pair-proj-contract)
(let () (let ()
(define-struct/prop pair-proj-contract (the-name pos-proc neg-proc) (define-struct/prop pair-proj-contract (the-name pos-proc neg-proc first-order-proc)
((pos-proj-prop (λ (ctc) (pair-proj-contract-pos-proc ctc))) ((pos-proj-prop (λ (ctc) (pair-proj-contract-pos-proc ctc)))
(neg-proj-prop (λ (ctc) (pair-proj-contract-neg-proc ctc))) (neg-proj-prop (λ (ctc) (pair-proj-contract-neg-proc ctc)))
(name-prop (λ (ctc) (pair-proj-contract-the-name ctc))) (name-prop (λ (ctc) (pair-proj-contract-the-name ctc)))
(first-order-prop (λ (ctc) (or (pair-proj-contract-first-order-proc ctc)
(λ (x) #t))))
(stronger-prop (λ (this that) (stronger-prop (λ (this that)
(and (pair-proj-contract? that) (and (pair-proj-contract? that)
(procedure-closure-contents-eq? (procedure-closure-contents-eq?
@ -375,7 +373,38 @@
(let ([mk-sub-name (contract-name sub)]) (let ([mk-sub-name (contract-name sub)])
`(,mk-sub-name ,@(loop (cdr subs))))] `(,mk-sub-name ,@(loop (cdr subs))))]
[else `(,sub ,@(loop (cdr subs)))]))]))) [else `(,sub ,@(loop (cdr subs)))]))])))
(define (make-and-proj proj-get)
(λ (ctc)
(let ([mk-pos-projs (map (λ (x) ((proj-get x) x)) (and/c-ctcs ctc))])
(lambda (pos src-info orig-str)
(let ([projs (map (λ (c) (c pos src-info orig-str)) mk-pos-projs)])
(let loop ([projs (cdr projs)]
[proj (car projs)])
(cond
[(null? projs) proj]
[else (loop (cdr projs)
(let ([f (car projs)])
(λ (v) (proj (f v)))))])))))))
(define-struct/prop and/c (ctcs)
((pos-proj-prop (make-and-proj pos-proj-get))
(neg-proj-prop (make-and-proj neg-proj-get))
(name-prop (λ (ctc) (apply build-compound-type-name 'and/c (and/c-ctcs ctc))))
(first-order-prop (λ (ctc)
(let ([tests (map (λ (x) ((first-order-get x) x)) (and/c-ctcs ctc))])
(λ (x)
(andmap (λ (f) (f x)) tests)))))
(stronger-prop
(λ (this that)
(and (and/c? that)
(let ([this-ctcs (and/c-ctcs this)]
[that-ctcs (and/c-ctcs that)])
(and (= (length this-ctcs) (length that-ctcs))
(andmap contract-stronger?
this-ctcs
that-ctcs))))))))
(define (and/c . fs) (define (and/c . fs)
(for-each (for-each
(lambda (x) (lambda (x)
@ -405,43 +434,41 @@
(cdr preds)))]))]) (cdr preds)))]))])
(flat-named-contract (apply build-compound-type-name 'and/c contracts) pred))] (flat-named-contract (apply build-compound-type-name 'and/c contracts) pred))]
[else [else
(let* ([contracts (map (lambda (x) (if (contract? x) x (flat-contract x))) fs)] (let ([contracts (map (lambda (x) (if (contract? x) x (flat-contract x))) fs)])
[pos-contract/procs (map contract-pos-proc contracts)] (make-and/c contracts))]))
[neg-contract/procs (map contract-neg-proc contracts)])
(make-pair-proj-contract
(apply build-compound-type-name 'and/c contracts)
(lambda (blame src-info orig-str)
(let ([partial-contracts (map (lambda (contract/proc) (contract/proc blame src-info orig-str))
pos-contract/procs)])
(let loop ([ctct (car partial-contracts)]
[rest (cdr partial-contracts)])
(cond
[(null? rest) ctct]
[else
(let ([fst (car rest)])
(loop (lambda (x) (fst (ctct x)))
(cdr rest)))]))))
(lambda (blame src-info orig-str)
(let ([partial-contracts (map (lambda (contract/proc) (contract/proc blame src-info orig-str))
neg-contract/procs)])
(let loop ([ctct (car partial-contracts)]
[rest (cdr partial-contracts)])
(cond
[(null? rest) ctct]
[else
(let ([fst (car rest)])
(loop (lambda (x) (fst (ctct x)))
(cdr rest)))]))))))]))
(define-struct/prop any/c () (define-struct/prop any/c ()
((pos-proj-prop any-curried-proj) ((pos-proj-prop any-curried-proj)
(neg-proj-prop any-curried-proj) (neg-proj-prop any-curried-proj)
(stronger-prop (λ (this that) (any/c? that))) (stronger-prop (λ (this that) (any/c? that)))
(name-prop (λ (ctc) 'any/c)) (name-prop (λ (ctc) 'any/c))
(first-order-prop (λ (ctc) (λ (val) #t)))
(flat-prop (λ (ctc) (λ (x) #t))))) (flat-prop (λ (ctc) (λ (x) #t)))))
(define any/c (make-any/c)) (define any/c (make-any/c))
(define (none-curried-proj ctc)
(λ (pos src-info orig-str)
(λ (val)
(raise-contract-error
val
src-info
pos
orig-str
"~s accepts no values, given: ~e"
(none/c-name ctc)
val))))
(define-struct/prop none/c (name)
((pos-proj-prop none-curried-proj)
(neg-proj-prop none-curried-proj)
(stronger-prop (λ (this that) #t))
(name-prop (λ (ctc) (none/c-name ctc)))
(first-order-prop (λ (ctc) (λ (val) #f)))
(flat-prop (λ (ctc) (λ (x) #f)))))
(define none/c (make-none/c 'none/c))
(define (flat-contract/predicate? pred) (define (flat-contract/predicate? pred)
(or (flat-contract? pred) (or (flat-contract? pred)
(and (procedure? pred) (and (procedure? pred)

View File

@ -53,7 +53,7 @@ add struct contracts for immutable structs?
(define-for-syntax (make-define/contract-transformer contract-id id) (define-for-syntax (make-define/contract-transformer contract-id id)
(make-set!-transformer (make-set!-transformer
(lambda (stx) (λ (stx)
(with-syntax ([neg-blame-str (or (a:build-src-loc-string stx) "")] (with-syntax ([neg-blame-str (or (a:build-src-loc-string stx) "")]
[contract-id contract-id] [contract-id contract-id]
[id id]) [id id])
@ -83,7 +83,7 @@ add struct contracts for immutable structs?
(define-for-syntax (make-provide/contract-transformer contract-id id pos-module-source) (define-for-syntax (make-provide/contract-transformer contract-id id pos-module-source)
(make-set!-transformer (make-set!-transformer
(lambda (stx) (λ (stx)
(with-syntax ([neg-stx (datum->syntax-object stx 'here)] (with-syntax ([neg-stx (datum->syntax-object stx 'here)]
[contract-id contract-id] [contract-id contract-id]
[id id] [id id]
@ -215,7 +215,7 @@ add struct contracts for immutable structs?
provide-stx provide-stx
(syntax name))] (syntax name))]
[(struct name (fields ...)) [(struct name (fields ...))
(for-each (lambda (field) (for-each (λ (field)
(syntax-case field () (syntax-case field ()
[(x y) [(x y)
(identifier? (syntax x)) (identifier? (syntax x))
@ -272,8 +272,8 @@ add struct contracts for immutable structs?
[(a b) (syntax a)] [(a b) (syntax a)]
[else struct-name-position])] [else struct-name-position])]
[super-id (syntax-case struct-name-position () [super-id (syntax-case struct-name-position ()
[(a b) (syntax b)] [(a b) (syntax b)]
[else #t])] [else #t])]
[struct-info (extract-struct-info struct-name-position)] [struct-info (extract-struct-info struct-name-position)]
[constructor-id (list-ref struct-info 1)] [constructor-id (list-ref struct-info 1)]
[predicate-id (list-ref struct-info 2)] [predicate-id (list-ref struct-info 2)]
@ -291,7 +291,7 @@ add struct contracts for immutable structs?
provide-stx provide-stx
struct-name)] struct-name)]
[else (length fields)]))))] [else (length fields)]))))]
[field-contract-ids (map (lambda (field-name) [field-contract-ids (map (λ (field-name)
(a:mangle-id provide-stx (a:mangle-id provide-stx
"provide/contract-field-contract" "provide/contract-field-contract"
field-name field-name
@ -305,22 +305,28 @@ add struct contracts for immutable structs?
"struct:" "struct:"
(symbol->string (syntax-e struct-name)))))] (symbol->string (syntax-e struct-name)))))]
[-struct:struct-name
(datum->syntax-object
struct-name
(string->symbol
(string-append
"-struct:"
(symbol->string (syntax-e struct-name)))))]
[is-new-id?
[is-new-id? (λ (index)
(λ (index) (or (not parent-struct-count)
(or (not parent-struct-count) (parent-struct-count . <= . index)))])
(parent-struct-count . <= . index)))])
(let ([unknown-info (let ([unknown-info
(lambda (what names) (λ (what names)
(raise-syntax-error (raise-syntax-error
'provide/contract 'provide/contract
(format "cannot determine ~a, found ~s" what names) (format "cannot determine ~a, found ~s" what names)
provide-stx provide-stx
struct-name))] struct-name))]
[is-id-ok? [is-id-ok?
(lambda (id i) (λ (id i)
(if (or (not parent-struct-count) (if (or (not parent-struct-count)
(parent-struct-count . <= . i)) (parent-struct-count . <= . i))
id id
@ -330,13 +336,13 @@ add struct contracts for immutable structs?
(unless predicate-id (unknown-info "predicate" predicate-id)) (unless predicate-id (unknown-info "predicate" predicate-id))
(unless (andmap/count is-id-ok? selector-ids) (unless (andmap/count is-id-ok? selector-ids)
(unknown-info "selectors" (unknown-info "selectors"
(map (lambda (x) (if (syntax? x) (map (λ (x) (if (syntax? x)
(syntax-object->datum x) (syntax-object->datum x)
x)) x))
selector-ids))) selector-ids)))
(unless (andmap/count is-id-ok? mutator-ids) (unless (andmap/count is-id-ok? mutator-ids)
(unknown-info "mutators" (unknown-info "mutators"
(map (lambda (x) (if (syntax? x) (map (λ (x) (if (syntax? x)
(syntax-object->datum x) (syntax-object->datum x)
x)) x))
mutator-ids)))) mutator-ids))))
@ -360,8 +366,8 @@ add struct contracts for immutable structs?
(with-syntax ([((selector-codes selector-new-names) ...) (with-syntax ([((selector-codes selector-new-names) ...)
(filter (filter
(lambda (x) x) (λ (x) x)
(map/count (lambda (selector-id field-contract-id index) (map/count (λ (selector-id field-contract-id index)
(if (is-new-id? index) (if (is-new-id? index)
(code-for-one-id/new-name (code-for-one-id/new-name
stx stx
@ -376,16 +382,16 @@ add struct contracts for immutable structs?
[(rev-selector-old-names ...) [(rev-selector-old-names ...)
(reverse (reverse
(filter (filter
(lambda (x) x) (λ (x) x)
(map/count (lambda (selector-id index) (map/count (λ (selector-id index)
(if (not (is-new-id? index)) (if (not (is-new-id? index))
selector-id selector-id
#f)) #f))
selector-ids)))] selector-ids)))]
[((mutator-codes mutator-new-names) ...) [((mutator-codes mutator-new-names) ...)
(filter (filter
(lambda (x) x) (λ (x) x)
(map/count (lambda (mutator-id field-contract-id index) (map/count (λ (mutator-id field-contract-id index)
(if (is-new-id? index) (if (is-new-id? index)
(code-for-one-id/new-name stx (code-for-one-id/new-name stx
mutator-id mutator-id
@ -399,8 +405,8 @@ add struct contracts for immutable structs?
[(rev-mutator-old-names ...) [(rev-mutator-old-names ...)
(reverse (reverse
(filter (filter
(lambda (x) x) (λ (x) x)
(map/count (lambda (mutator-id index) (map/count (λ (mutator-id index)
(if (not (is-new-id? index)) (if (not (is-new-id? index))
mutator-id mutator-id
#f)) #f))
@ -424,7 +430,7 @@ add struct contracts for immutable structs?
"provide/contract-struct-expandsion-info-id" "provide/contract-struct-expandsion-info-id"
struct-name)] struct-name)]
[struct-name struct-name] [struct-name struct-name]
[struct:struct-name struct:struct-name] [-struct:struct-name -struct:struct-name]
[super-id (if (boolean? super-id) [super-id (if (boolean? super-id)
super-id super-id
(with-syntax ([super-id super-id]) (with-syntax ([super-id super-id])
@ -432,7 +438,7 @@ add struct contracts for immutable structs?
(syntax (begin (syntax (begin
(provide (rename id-rename struct-name)) (provide (rename id-rename struct-name))
(define-syntax id-rename (define-syntax id-rename
(list-immutable ((syntax-local-certifier) #'struct:struct-name) (list-immutable ((syntax-local-certifier) #'-struct:struct-name)
((syntax-local-certifier) #'constructor-new-name) ((syntax-local-certifier) #'constructor-new-name)
((syntax-local-certifier) #'predicate-new-name) ((syntax-local-certifier) #'predicate-new-name)
(list-immutable ((syntax-local-certifier) #'rev-selector-new-names) ... (list-immutable ((syntax-local-certifier) #'rev-selector-new-names) ...
@ -440,7 +446,10 @@ add struct contracts for immutable structs?
(list-immutable ((syntax-local-certifier) #'rev-mutator-new-names) ... (list-immutable ((syntax-local-certifier) #'rev-mutator-new-names) ...
((syntax-local-certifier) #'rev-mutator-old-names) ...) ((syntax-local-certifier) #'rev-mutator-old-names) ...)
super-id)))))] super-id)))))]
[struct:struct-name struct:struct-name]) [struct:struct-name struct:struct-name]
[-struct:struct-name -struct:struct-name]
[struct-name struct-name]
[(selector-ids ...) selector-ids])
(syntax/loc stx (syntax/loc stx
(begin (begin
struct-code struct-code
@ -449,7 +458,23 @@ add struct contracts for immutable structs?
mutator-codes ... mutator-codes ...
predicate-code predicate-code
constructor-code constructor-code
(provide struct:struct-name)))))))) (define -struct:struct-name
(let-values ([(struct:struct-name _make _pred _get _set)
(make-struct-type 'struct-name
struct:struct-name
0 ;; init
0 ;; auto
#f ;; auto-v
'() ;; props
#f ;; inspector
#f ;; proc-spec
'
() ;; immutable-k-list
(λ (selector-ids ... ignore)
(values (-contract field-contract-ids selector-ids 'guess1 'guess2)
...)))])
struct:struct-name))
(provide (rename -struct:struct-name struct:struct-name)))))))))
;; map/count : (X Y int -> Z) (listof X) (listof Y) -> (listof Z) ;; map/count : (X Y int -> Z) (listof X) (listof Y) -> (listof Z)
#; #;
@ -491,7 +516,7 @@ add struct contracts for immutable structs?
[(a b) [(a b)
(syntax-local-value (syntax-local-value
(syntax b) (syntax b)
(lambda () (λ ()
(raise-syntax-error 'provide/contract (raise-syntax-error 'provide/contract
"expected a struct name" "expected a struct name"
provide-stx provide-stx
@ -505,7 +530,7 @@ add struct contracts for immutable structs?
[_ stx])]) [_ stx])])
(syntax-local-value (syntax-local-value
id id
(lambda () (λ ()
(raise-syntax-error 'provide/contract (raise-syntax-error 'provide/contract
"expected a struct name" "expected a struct name"
provide-stx provide-stx
@ -519,14 +544,14 @@ add struct contracts for immutable structs?
(field-contract-ids (field-contract-ids
... ...
. -> . . -> .
(let ([predicate-id (lambda (x) (predicate-id x))]) predicate-id))))) (let ([predicate-id (λ (x) (predicate-id x))]) predicate-id)))))
;; build-selector-contract : syntax syntax -> syntax ;; build-selector-contract : syntax syntax -> syntax
;; constructs the contract for a selector ;; constructs the contract for a selector
(define (build-selector-contract struct-name predicate-id field-contract-id) (define (build-selector-contract struct-name predicate-id field-contract-id)
(with-syntax ([field-contract-id field-contract-id] (with-syntax ([field-contract-id field-contract-id]
[predicate-id predicate-id]) [predicate-id predicate-id])
(syntax ((let ([predicate-id (lambda (x) (predicate-id x))]) predicate-id) (syntax ((let ([predicate-id (λ (x) (predicate-id x))]) predicate-id)
. -> . . -> .
field-contract-id)))) field-contract-id))))
@ -535,7 +560,7 @@ add struct contracts for immutable structs?
(define (build-mutator-contract struct-name predicate-id field-contract-id) (define (build-mutator-contract struct-name predicate-id field-contract-id)
(with-syntax ([field-contract-id field-contract-id] (with-syntax ([field-contract-id field-contract-id]
[predicate-id predicate-id]) [predicate-id predicate-id])
(syntax ((let ([predicate-id (lambda (x) (predicate-id x))]) predicate-id) (syntax ((let ([predicate-id (λ (x) (predicate-id x))]) predicate-id)
field-contract-id field-contract-id
. -> . . -> .
void?)))) void?))))
@ -696,7 +721,8 @@ add struct contracts for immutable structs?
(λ (blame src str) (λ (blame src str)
(let ([proc (contract-neg-proc arg)]) (let ([proc (contract-neg-proc arg)])
(λ (val) (λ (val)
((proc blame src str) val))))))])) ((proc blame src str) val))))
#f))]))
(define (check-contract ctc) (define (check-contract ctc)
(unless (contract? ctc) (unless (contract? ctc)
@ -751,15 +777,15 @@ add struct contracts for immutable structs?
(with-syntax ([(ctc-id ...) (generate-temporaries (syntax (ctc ...)))] (with-syntax ([(ctc-id ...) (generate-temporaries (syntax (ctc ...)))]
[(pred-id ...) (generate-temporaries (syntax (ctc ...)))]) [(pred-id ...) (generate-temporaries (syntax (ctc ...)))])
(syntax (syntax
(let* ([pred (lambda (x) (error 'flat-rec-contract "applied too soon"))] (let* ([pred (λ (x) (error 'flat-rec-contract "applied too soon"))]
[name (flat-contract (let ([name (lambda (x) (pred x))]) name))]) [name (flat-contract (let ([name (λ (x) (pred x))]) name))])
(let ([ctc-id (coerce-contract flat-rec-contract ctc)] ...) (let ([ctc-id (coerce-contract 'flat-rec-contract ctc)] ...)
(unless (flat-contract? ctc-id) (unless (flat-contract? ctc-id)
(error 'flat-rec-contract "expected flat contracts as arguments, got ~e" ctc-id)) (error 'flat-rec-contract "expected flat contracts as arguments, got ~e" ctc-id))
... ...
(set! pred (set! pred
(let ([pred-id (flat-contract-predicate ctc-id)] ...) (let ([pred-id (flat-contract-predicate ctc-id)] ...)
(lambda (x) (λ (x)
(or (pred-id x) ...)))) (or (pred-id x) ...))))
name))))] name))))]
[(_ name ctc ...) [(_ name ctc ...)
@ -775,9 +801,9 @@ add struct contracts for immutable structs?
[((pred-arm-id ...) ...) (map generate-temporaries [((pred-arm-id ...) ...) (map generate-temporaries
(syntax->list (syntax ((ctc ...) ...))))]) (syntax->list (syntax ((ctc ...) ...))))])
(syntax (syntax
(let* ([pred-id (lambda (x) (error 'flat-murec-contract "applied too soon"))] ... (let* ([pred-id (λ (x) (error 'flat-murec-contract "applied too soon"))] ...
[name (flat-contract (let ([name (lambda (x) (pred-id x))]) name))] ...) [name (flat-contract (let ([name (λ (x) (pred-id x))]) name))] ...)
(let-values ([(ctc-id ...) (values (coerce-contract flat-rec-contract ctc) ...)] ...) (let-values ([(ctc-id ...) (values (coerce-contract 'flat-rec-contract ctc) ...)] ...)
(begin (begin
(void) (void)
(unless (flat-contract? ctc-id) (unless (flat-contract? ctc-id)
@ -785,12 +811,12 @@ add struct contracts for immutable structs?
...) ... ...) ...
(set! pred-id (set! pred-id
(let ([pred-arm-id (flat-contract-predicate ctc-id)] ...) (let ([pred-arm-id (flat-contract-predicate ctc-id)] ...)
(lambda (x) (λ (x)
(or (pred-arm-id x) ...)))) ... (or (pred-arm-id x) ...)))) ...
body1 body1
body ...))))] body ...))))]
[(_ ([name ctc ...] ...) body1 body ...) [(_ ([name ctc ...] ...) body1 body ...)
(for-each (lambda (name) (for-each (λ (name)
(unless (identifier? name) (unless (identifier? name)
(raise-syntax-error 'flat-rec-contract (raise-syntax-error 'flat-rec-contract
"expected an identifier" stx name))) "expected an identifier" stx name)))
@ -815,51 +841,53 @@ add struct contracts for immutable structs?
[(_ args ...) (syntax (or/c args ...))] [(_ args ...) (syntax (or/c args ...))]
[id (syntax or/c)]))) [id (syntax or/c)])))
(define (or/c . args) (define or/c
(for-each (case-lambda
(lambda (x) [() (make-none/c '(or/c))]
(unless (or (contract? x) [args
(and (procedure? x) (for-each
(procedure-arity-includes? x 1))) (λ (x)
(error 'or/c "expected procedures of arity 1 or contracts, given: ~e" x))) (unless (or (contract? x)
args) (and (procedure? x)
(let-values ([(contract fc/predicates) (procedure-arity-includes? x 1)))
(let loop ([contract #f] (error 'or/c "expected procedures of arity 1 or contracts, given: ~e" x)))
[fc/predicates null] args)
[args args]) (let-values ([(ho-contracts fc/predicates)
(cond (let loop ([ho-contracts '()]
[(null? args) (values contract (reverse fc/predicates))] [fc/predicates null]
[else [args args])
(let ([arg (car args)]) (cond
(cond [(null? args) (values ho-contracts (reverse fc/predicates))]
[(or (flat-contract? arg) [else
(not (contract? arg))) (let ([arg (car args)])
(loop contract (cons arg fc/predicates) (cdr args))] (cond
[contract [(and (contract? arg)
(error 'or/c "expected at most one non-flat contract, given ~e and ~e" (not (flat-contract? arg)))
contract (loop (cons arg ho-contracts) fc/predicates (cdr args))]
arg)] [else
[else (loop arg fc/predicates (cdr args))]))]))]) (loop ho-contracts (cons arg fc/predicates) (cdr args))]))]))])
(let ([flat-contracts (map (lambda (x) (if (flat-contract? x) (let ([flat-contracts (map (λ (x) (if (flat-contract? x)
x x
(flat-contract x))) (flat-contract x)))
fc/predicates)]) fc/predicates)])
(cond (cond
[contract [(null? ho-contracts)
(make-or/c flat-contracts contract)] (make-flat-or/c flat-contracts)]
[else [(null? (cdr ho-contracts))
(make-flat-or/c flat-contracts)])))) (make-or/c flat-contracts (car ho-contracts))]
[else
(make-multi-or/c flat-contracts ho-contracts)])))]))
(define-struct/prop or/c (flat-ctcs ho-ctc) (define-struct/prop or/c (flat-ctcs ho-ctc)
((pos-proj-prop (λ (ctc) ((pos-proj-prop (λ (ctc)
(let ([c-proc ((pos-proj-get (or/c-ho-ctc ctc)) (or/c-ho-ctc ctc))] (let ([c-proc ((pos-proj-get (or/c-ho-ctc ctc)) (or/c-ho-ctc ctc))]
[predicates (map (λ (x) ((flat-get x) x)) [predicates (map (λ (x) ((flat-get x) x))
(or/c-flat-ctcs ctc))]) (or/c-flat-ctcs ctc))])
(lambda (pos src-info orig-str) (λ (pos src-info orig-str)
(let ([partial-contract (c-proc pos src-info orig-str)]) (let ([partial-contract (c-proc pos src-info orig-str)])
(lambda (val) (λ (val)
(cond (cond
[(ormap (lambda (pred) (pred val)) predicates) [(ormap (λ (pred) (pred val)) predicates)
val] val]
[else [else
(partial-contract val)]))))))) (partial-contract val)])))))))
@ -868,11 +896,11 @@ add struct contracts for immutable structs?
(let ([c-proc ((neg-proj-get (or/c-ho-ctc ctc)) (or/c-ho-ctc ctc))] (let ([c-proc ((neg-proj-get (or/c-ho-ctc ctc)) (or/c-ho-ctc ctc))]
[predicates (map (λ (x) ((flat-get x) x)) [predicates (map (λ (x) ((flat-get x) x))
(or/c-flat-ctcs ctc))]) (or/c-flat-ctcs ctc))])
(lambda (pos src-info orig-str) (λ (pos src-info orig-str)
(let ([partial-contract (c-proc pos src-info orig-str)]) (let ([partial-contract (c-proc pos src-info orig-str)])
(lambda (val) (λ (val)
(cond (cond
[(ormap (lambda (pred) (pred val)) predicates) [(ormap (λ (pred) (pred val)) predicates)
val] val]
[else [else
(partial-contract val)]))))))) (partial-contract val)])))))))
@ -881,18 +909,101 @@ add struct contracts for immutable structs?
(apply build-compound-type-name (apply build-compound-type-name
'or/c 'or/c
(or/c-ho-ctc ctc) (or/c-ho-ctc ctc)
(or/c-flat-ctcs ctc)))) (or/c-flat-ctcs ctc))))
(first-order-prop
(λ (ctc)
(let ([flats (map (λ (x) ((flat-get x) x)) (or/c-flat-ctcs ctc))]
[ho ((first-order-get (or/c-ho-ctc ctc)) (or/c-ho-ctc ctc))])
(λ (x)
(or (ho x)
(ormap (λ (f) (f x)) flats))))))
(stronger-prop (stronger-prop
(λ (this that) (λ (this that)
(and (or/c? that) (and (or/c? that)
(and (contract-stronger? (or/c-ho-ctc this) (or/c-ho-ctc that))
(contract-stronger? (or/c-ho-ctc this) (or/c-ho-ctc that)) (let ([this-ctcs (or/c-flat-ctcs this)]
(let ([this-ctcs (or/c-flat-ctcs this)] [that-ctcs (or/c-flat-ctcs that)])
[that-ctcs (or/c-flat-ctcs that)]) (and (= (length this-ctcs) (length that-ctcs))
(and (= (length this-ctcs) (length that-ctcs)) (andmap contract-stronger?
(andmap contract-stronger? this-ctcs
this-ctcs that-ctcs))))))))
that-ctcs)))))))))
(define (make-multi-or/c-proj pos-proj-get)
(λ (ctc)
(let* ([ho-contracts (multi-or/c-ho-ctcs ctc)]
[c-procs (map (λ (x) ((pos-proj-get x) x)) ho-contracts)]
[first-order-checks (map (λ (x) ((first-order-get x) x)) ho-contracts)]
[predicates (map (λ (x) ((flat-get x) x))
(multi-or/c-flat-ctcs ctc))])
(λ (pos src-info orig-str)
(let ([partial-contracts (map (λ (c-proc) (c-proc pos src-info orig-str)) c-procs)])
(λ (val)
(cond
[(ormap (λ (pred) (pred val)) predicates)
val]
[else
(let loop ([checks first-order-checks]
[procs partial-contracts]
[contracts ho-contracts]
[candidate-proc #f]
[candidate-contract #f])
(cond
[(null? checks)
(if candidate-proc
(candidate-proc val)
(raise-contract-error val src-info pos orig-str
"none of the branches of the or/c matched"))]
[((car checks) val)
(if candidate-proc
(error 'or/c "two arguments, ~s and ~s, might both match ~s"
(contract-name candidate-contract)
(contract-name (car contracts))
val)
(loop (cdr checks)
(cdr procs)
(cdr contracts)
(car procs)
(car contracts)))]
[else
(loop (cdr checks)
(cdr procs)
(cdr contracts)
candidate-proc
candidate-contract)]))])))))))
(define-struct/prop multi-or/c (flat-ctcs ho-ctcs)
((pos-proj-prop (make-multi-or/c-proj pos-proj-get))
(neg-proj-prop (make-multi-or/c-proj neg-proj-get))
(name-prop (λ (ctc)
(apply build-compound-type-name
'or/c
(append
(multi-or/c-ho-ctcs ctc)
(multi-or/c-flat-ctcs ctc)))))
(first-order-prop
(λ (ctc)
(let ([flats (map (λ (x) ((flat-get x) x)) (multi-or/c-flat-ctcs ctc))]
[hos (map (λ (x) ((first-order-get x) x)) (multi-or/c-ho-ctcs ctc))])
(λ (x)
(or (ormap (λ (f) (f x)) hos)
(ormap (λ (f) (f x)) flats))))))
(stronger-prop
(λ (this that)
(and (multi-or/c? that)
(let ([this-ctcs (multi-or/c-ho-ctcs this)]
[that-ctcs (multi-or/c-ho-ctcs that)])
(and (= (length this-ctcs) (length that-ctcs))
(andmap contract-stronger?
this-ctcs
that-ctcs)))
(let ([this-ctcs (multi-or/c-flat-ctcs this)]
[that-ctcs (multi-or/c-flat-ctcs that)])
(and (= (length this-ctcs) (length that-ctcs))
(andmap contract-stronger?
this-ctcs
that-ctcs))))))))
(define-struct/prop flat-or/c (flat-ctcs) (define-struct/prop flat-or/c (flat-ctcs)
((pos-proj-prop flat-pos-proj) ((pos-proj-prop flat-pos-proj)
@ -919,14 +1030,14 @@ add struct contracts for immutable structs?
(define false/c (define false/c
(flat-named-contract (flat-named-contract
'false/c 'false/c
(lambda (x) (not x)))) (λ (x) (not x))))
(define (string/len n) (define (string/len n)
(unless (number? n) (unless (number? n)
(error 'string/len "expected a number as argument, got ~e" n)) (error 'string/len "expected a number as argument, got ~e" n))
(flat-named-contract (flat-named-contract
`(string/len ,n) `(string/len ,n)
(lambda (x) (λ (x)
(and (string? x) (and (string? x)
((string-length x) . < . n))))) ((string-length x) . < . n)))))
@ -935,7 +1046,7 @@ add struct contracts for immutable structs?
(error 'symbols "expected at least one argument")) (error 'symbols "expected at least one argument"))
(unless (andmap symbol? ss) (unless (andmap symbol? ss)
(error 'symbols "expected symbols as arguments, given: ~a" (error 'symbols "expected symbols as arguments, given: ~a"
(apply string-append (map (lambda (x) (format "~e " x)) ss)))) (apply string-append (map (λ (x) (format "~e " x)) ss))))
(make-one-of/c ss)) (make-one-of/c ss))
(define atomic-value? (define atomic-value?
@ -979,7 +1090,7 @@ add struct contracts for immutable structs?
(define printable/c (define printable/c
(flat-named-contract (flat-named-contract
'printable/c 'printable/c
(lambda (x) (λ (x)
(let printable? ([x x]) (let printable? ([x x])
(or (symbol? x) (or (symbol? x)
(string? x) (string? x)
@ -1027,16 +1138,16 @@ add struct contracts for immutable structs?
(define (</c x) (define (</c x)
(flat-named-contract (flat-named-contract
`(</c ,x) `(</c ,x)
(lambda (y) (and (number? y) (< y x))))) (λ (y) (and (number? y) (< y x)))))
(define (>/c x) (define (>/c x)
(flat-named-contract (flat-named-contract
`(>/c ,x) `(>/c ,x)
(lambda (y) (and (number? y) (> y x))))) (λ (y) (and (number? y) (> y x)))))
(define natural-number/c (define natural-number/c
(flat-named-contract (flat-named-contract
'natural-number/c 'natural-number/c
(lambda (x) (λ (x)
(and (number? x) (and (number? x)
(integer? x) (integer? x)
(x . >= . 0))))) (x . >= . 0)))))
@ -1047,7 +1158,7 @@ add struct contracts for immutable structs?
(error 'integer-in "expected two integers as arguments, got ~e and ~e" start end)) (error 'integer-in "expected two integers as arguments, got ~e and ~e" start end))
(flat-named-contract (flat-named-contract
`(integer-in ,start ,end) `(integer-in ,start ,end)
(lambda (x) (λ (x)
(and (integer? x) (and (integer? x)
(<= start x end))))) (<= start x end)))))
@ -1059,7 +1170,7 @@ add struct contracts for immutable structs?
(error 'integer-in "expected two exact integers as arguments, got ~e and ~e" start end)) (error 'integer-in "expected two exact integers as arguments, got ~e and ~e" start end))
(flat-named-contract (flat-named-contract
`(exact-integer-in ,start ,end) `(exact-integer-in ,start ,end)
(lambda (x) (λ (x)
(and (integer? x) (and (integer? x)
(exact? x) (exact? x)
(<= start x end))))) (<= start x end)))))
@ -1070,7 +1181,7 @@ add struct contracts for immutable structs?
(error 'real-in "expected two real numbers as arguments, got ~e and ~e" start end)) (error 'real-in "expected two real numbers as arguments, got ~e and ~e" start end))
(flat-named-contract (flat-named-contract
`(real-in ,start ,end) `(real-in ,start ,end)
(lambda (x) (λ (x)
(and (real? x) (and (real? x)
(<= start x end))))) (<= start x end)))))
@ -1079,34 +1190,34 @@ add struct contracts for immutable structs?
(error 'not/c "expected a procedure of arity 1 or <flat-named-contract>, given: ~e" f)) (error 'not/c "expected a procedure of arity 1 or <flat-named-contract>, given: ~e" f))
(build-flat-contract (build-flat-contract
(build-compound-type-name 'not/c (proc/ctc->ctc f)) (build-compound-type-name 'not/c (proc/ctc->ctc f))
(lambda (x) (not (test-proc/flat-contract f x))))) (λ (x) (not (test-proc/flat-contract f x)))))
(define (listof p) (define (listof p)
(unless (flat-contract/predicate? p) (unless (flat-contract/predicate? p)
(error 'listof "expected a flat contract or procedure of arity 1 as argument, got: ~e" p)) (error 'listof "expected a flat contract or procedure of arity 1 as argument, got: ~e" p))
(build-flat-contract (build-flat-contract
(build-compound-type-name 'listof (proc/ctc->ctc p)) (build-compound-type-name 'listof (proc/ctc->ctc p))
(lambda (v) (λ (v)
(and (list? v) (and (list? v)
(andmap (lambda (ele) (test-proc/flat-contract p ele)) (andmap (λ (ele) (test-proc/flat-contract p ele))
v))))) v)))))
(define-syntax (*-immutableof stx) (define-syntax (*-immutableof stx)
(syntax-case stx () (syntax-case stx ()
[(_ predicate? fill type-name name) [(_ predicate? fill type-name name)
(identifier? (syntax predicate?))
(syntax (syntax
(let ([predicate?-name predicate?] (let ([fill-name fill])
[fill-name fill]) (λ (input)
(lambda (input) (let* ([ctc (coerce-contract 'name input)]
(let* ([ctc (coerce-contract name input)]
[p-proj (contract-pos-proc ctc)] [p-proj (contract-pos-proc ctc)]
[n-proj (contract-neg-proc ctc)]) [n-proj (contract-neg-proc ctc)])
(make-pair-proj-contract (make-pair-proj-contract
(build-compound-type-name 'name ctc) (build-compound-type-name 'name ctc)
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([p-app (p-proj blame src-info orig-str)]) (let ([p-app (p-proj blame src-info orig-str)])
(lambda (val) (λ (val)
(unless (predicate?-name val) (unless (predicate? val)
(raise-contract-error (raise-contract-error
val val
src-info src-info
@ -1116,10 +1227,11 @@ add struct contracts for immutable structs?
'type-name 'type-name
val)) val))
(fill-name p-app val)))) (fill-name p-app val))))
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([n-app (n-proj blame src-info orig-str)]) (let ([n-app (n-proj blame src-info orig-str)])
(lambda (val) (λ (val)
(fill-name n-app val)))))))))])) (fill-name n-app val))))
predicate?)))))]))
(define (map-immutable f lst) (define (map-immutable f lst)
(let loop ([lst lst]) (let loop ([lst lst])
@ -1129,20 +1241,21 @@ add struct contracts for immutable structs?
(loop (cdr lst)))] (loop (cdr lst)))]
[(null? lst) null]))) [(null? lst) null])))
(define (immutable-list? lst) (define (immutable-list? val)
(cond (let loop ([v val])
[(and (pair? lst) (or (and (pair? v)
(immutable? lst)) (immutable? v)
(immutable-list? (cdr lst))] (loop (cdr v)))
[(null? lst) #t] (null? v))))
[else #f]))
(define list-immutableof (define list-immutableof
(*-immutableof immutable-list? map-immutable immutable-list list-immutableof)) (*-immutableof immutable-list? map-immutable immutable-list list-immutableof))
(define (immutable-vector? val) (and (immutable? val) (vector? val)))
(define vector-immutableof (define vector-immutableof
(*-immutableof (lambda (x) (and (vector? x) (immutable? x))) (*-immutableof immutable-vector?
(lambda (f v) (apply vector-immutable (map f (vector->list v)))) (λ (f v) (apply vector-immutable (map f (vector->list v))))
immutable-vector immutable-vector
vector-immutableof)) vector-immutableof))
@ -1151,9 +1264,9 @@ add struct contracts for immutable structs?
(error 'vectorof "expected a flat contract or procedure of arity 1 as argument, got: ~e" p)) (error 'vectorof "expected a flat contract or procedure of arity 1 as argument, got: ~e" p))
(build-flat-contract (build-flat-contract
(build-compound-type-name 'vectorof (proc/ctc->ctc p)) (build-compound-type-name 'vectorof (proc/ctc->ctc p))
(lambda (v) (λ (v)
(and (vector? v) (and (vector? v)
(andmap (lambda (ele) (test-proc/flat-contract p ele)) (andmap (λ (ele) (test-proc/flat-contract p ele))
(vector->list v)))))) (vector->list v))))))
(define (vector/c . args) (define (vector/c . args)
@ -1169,7 +1282,7 @@ add struct contracts for immutable structs?
(let ([largs (length args)]) (let ([largs (length args)])
(build-flat-contract (build-flat-contract
(apply build-compound-type-name 'vector/c (map proc/ctc->ctc args)) (apply build-compound-type-name 'vector/c (map proc/ctc->ctc args))
(lambda (v) (λ (v)
(and (vector? v) (and (vector? v)
(= (vector-length v) largs) (= (vector-length v) largs)
(andmap test-proc/flat-contract (andmap test-proc/flat-contract
@ -1181,7 +1294,7 @@ add struct contracts for immutable structs?
(error 'box/c "expected a flat contract or a procedure of arity 1, got: ~e" pred)) (error 'box/c "expected a flat contract or a procedure of arity 1, got: ~e" pred))
(build-flat-contract (build-flat-contract
(build-compound-type-name 'box/c (proc/ctc->ctc pred)) (build-compound-type-name 'box/c (proc/ctc->ctc pred))
(lambda (x) (λ (x)
(and (box? x) (and (box? x)
(test-proc/flat-contract pred (unbox x)))))) (test-proc/flat-contract pred (unbox x))))))
@ -1191,7 +1304,7 @@ add struct contracts for immutable structs?
(error 'cons/c "expected two flat contracts or procedures of arity 1, got: ~e and ~e" hdp tlp)) (error 'cons/c "expected two flat contracts or procedures of arity 1, got: ~e and ~e" hdp tlp))
(build-flat-contract (build-flat-contract
(build-compound-type-name 'cons/c (proc/ctc->ctc hdp) (proc/ctc->ctc tlp)) (build-compound-type-name 'cons/c (proc/ctc->ctc hdp) (proc/ctc->ctc tlp))
(lambda (x) (λ (x)
(and (pair? x) (and (pair? x)
(test-proc/flat-contract hdp (car x)) (test-proc/flat-contract hdp (car x))
(test-proc/flat-contract tlp (cdr x)))))) (test-proc/flat-contract tlp (cdr x))))))
@ -1210,16 +1323,16 @@ add struct contracts for immutable structs?
(let ([predicate?-name predicate?] (let ([predicate?-name predicate?]
[constructor-name constructor] [constructor-name constructor]
[selector-names selectors] ...) [selector-names selectors] ...)
(lambda (params ...) (λ (params ...)
(let ([ctc-x (coerce-contract name params)] ...) (let ([ctc-x (coerce-contract 'name params)] ...)
(let ([pos-procs (contract-pos-proc ctc-x)] (let ([pos-procs (contract-pos-proc ctc-x)]
... ...
[neg-procs (contract-neg-proc ctc-x)] ...) [neg-procs (contract-neg-proc ctc-x)] ...)
(make-pair-proj-contract (make-pair-proj-contract
(build-compound-type-name 'name (proc/ctc->ctc params) ...) (build-compound-type-name 'name (proc/ctc->ctc params) ...)
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([p-apps (pos-procs blame src-info orig-str)] ...) (let ([p-apps (pos-procs blame src-info orig-str)] ...)
(lambda (v) (λ (v)
(if (and (immutable? v) (if (and (immutable? v)
(predicate?-name v)) (predicate?-name v))
(constructor-name (p-apps (selector-names v)) ...) (constructor-name (p-apps (selector-names v)) ...)
@ -1231,26 +1344,27 @@ add struct contracts for immutable structs?
"expected <~a>, given: ~e" "expected <~a>, given: ~e"
'type-name 'type-name
v))))) v)))))
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([p-apps (neg-procs blame src-info orig-str)] ...) (let ([p-apps (neg-procs blame src-info orig-str)] ...)
(lambda (v) (λ (v)
(constructor-name (p-apps (selector-names v)) ...)))))))))))] (constructor-name (p-apps (selector-names v)) ...))))
#f)))))))]
[(_ predicate? constructor (arb? selector) correct-size type-name name) [(_ predicate? constructor (arb? selector) correct-size type-name name)
(eq? #t (syntax-object->datum (syntax arb?))) (eq? #t (syntax-object->datum (syntax arb?)))
(syntax (syntax
(let ([predicate?-name predicate?] (let ([predicate?-name predicate?]
[constructor-name constructor] [constructor-name constructor]
[selector-name selector]) [selector-name selector])
(lambda params (λ params
(let ([ctcs (map (lambda (param) (coerce-contract name param)) params)]) (let ([ctcs (map (λ (param) (coerce-contract 'name param)) params)])
(let ([pos-procs (map contract-pos-proc ctcs)] (let ([pos-procs (map contract-pos-proc ctcs)]
[neg-procs (map contract-neg-proc ctcs)]) [neg-procs (map contract-neg-proc ctcs)])
(make-pair-proj-contract (make-pair-proj-contract
(apply build-compound-type-name 'name (map proc/ctc->ctc params)) (apply build-compound-type-name 'name (map proc/ctc->ctc params))
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([p-apps (map (lambda (proc) (proc blame src-info orig-str)) pos-procs)] (let ([p-apps (map (λ (proc) (proc blame src-info orig-str)) pos-procs)]
[count (length params)]) [count (length params)])
(lambda (v) (λ (v)
(if (and (immutable? v) (if (and (immutable? v)
(predicate?-name v) (predicate?-name v)
(correct-size count v)) (correct-size count v))
@ -1270,9 +1384,9 @@ add struct contracts for immutable structs?
"expected <~a>, given: ~e" "expected <~a>, given: ~e"
'type-name 'type-name
v))))) v)))))
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([p-apps (map (lambda (proc) (proc blame src-info orig-str)) neg-procs)]) (let ([p-apps (map (λ (proc) (proc blame src-info orig-str)) neg-procs)])
(lambda (v) (λ (v)
(apply constructor-name (apply constructor-name
(let loop ([p-apps p-apps] (let loop ([p-apps p-apps]
[i 0]) [i 0])
@ -1280,14 +1394,15 @@ add struct contracts for immutable structs?
[(null? p-apps) null] [(null? p-apps) null]
[else (let ([p-app (car p-apps)]) [else (let ([p-app (car p-apps)])
(cons (p-app (selector-name v i)) (cons (p-app (selector-name v i))
(loop (cdr p-apps) (+ i 1))))]))))))))))))])) (loop (cdr p-apps) (+ i 1))))]))))))
#f))))))]))
(define cons-immutable/c (*-immutable/c pair? cons-immutable (#f car cdr) immutable-cons cons-immutable/c)) (define cons-immutable/c (*-immutable/c pair? cons-immutable (#f car cdr) immutable-cons cons-immutable/c))
(define box-immutable/c (*-immutable/c box? box-immutable (#f unbox) immutable-box box-immutable/c)) (define box-immutable/c (*-immutable/c box? box-immutable (#f unbox) immutable-box box-immutable/c))
(define vector-immutable/c (*-immutable/c vector? (define vector-immutable/c (*-immutable/c vector?
vector-immutable vector-immutable
(#t (lambda (v i) (vector-ref v i))) (#t (λ (v i) (vector-ref v i)))
(lambda (n v) (= n (vector-length v))) (λ (n v) (= n (vector-length v)))
immutable-vector immutable-vector
vector-immutable/c)) vector-immutable/c))
@ -1307,7 +1422,7 @@ add struct contracts for immutable structs?
[else (cons/c (car args) (loop (cdr args)))]))) [else (cons/c (car args) (loop (cdr args)))])))
(define (list-immutable/c . args) (define (list-immutable/c . args)
(unless (andmap (lambda (x) (or (contract? x) (unless (andmap (λ (x) (or (contract? x)
(and (procedure? x) (and (procedure? x)
(procedure-arity-includes? x 1)))) (procedure-arity-includes? x 1))))
args) args)
@ -1325,24 +1440,24 @@ add struct contracts for immutable structs?
[else (cons-immutable/c (car args) (loop (cdr args)))]))) [else (cons-immutable/c (car args) (loop (cdr args)))])))
(define (syntax/c ctc-in) (define (syntax/c ctc-in)
(let ([ctc (coerce-contract syntax/c ctc-in)]) (let ([ctc (coerce-contract 'syntax/c ctc-in)])
(build-flat-contract (build-flat-contract
(build-compound-type-name 'syntax/c ctc) (build-compound-type-name 'syntax/c ctc)
(let ([pred (flat-contract-predicate ctc)]) (let ([pred (flat-contract-predicate ctc)])
(lambda (val) (λ (val)
(and (syntax? val) (and (syntax? val)
(pred (syntax-e val)))))))) (pred (syntax-e val))))))))
(define promise/c (define promise/c
(lambda (ctc-in) (λ (ctc-in)
(let* ([ctc (coerce-contract promise/c ctc-in)] (let* ([ctc (coerce-contract 'promise/c ctc-in)]
[pos-ctc-proc (contract-pos-proc ctc)] [pos-ctc-proc (contract-pos-proc ctc)]
[neg-ctc-proc (contract-neg-proc ctc)]) [neg-ctc-proc (contract-neg-proc ctc)])
(make-pair-proj-contract (make-pair-proj-contract
(build-compound-type-name 'promise/c ctc) (build-compound-type-name 'promise/c ctc)
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([p-app (pos-ctc-proc blame src-info orig-str)]) (let ([p-app (pos-ctc-proc blame src-info orig-str)])
(lambda (val) (λ (val)
(unless (promise? val) (unless (promise? val)
(raise-contract-error (raise-contract-error
val val
@ -1353,10 +1468,11 @@ add struct contracts for immutable structs?
"expected <promise>, given: ~e" "expected <promise>, given: ~e"
val)) val))
(delay (p-app (force val)))))) (delay (p-app (force val))))))
(lambda (blame src-info orig-str) (λ (blame src-info orig-str)
(let ([p-app (neg-ctc-proc blame src-info orig-str)]) (let ([p-app (neg-ctc-proc blame src-info orig-str)])
(lambda (val) (λ (val)
(delay (p-app (force val)))))))))) (delay (p-app (force val))))))
promise?))))
#| #|
as with copy-struct in struct.ss, this first begin0 as with copy-struct in struct.ss, this first begin0
@ -1372,7 +1488,7 @@ add struct contracts for immutable structs?
(syntax-case stx () (syntax-case stx ()
[(_ struct-name args ...) [(_ struct-name args ...)
(and (identifier? (syntax struct-name)) (and (identifier? (syntax struct-name))
(syntax-local-value (syntax struct-name) (lambda () #f))) (syntax-local-value (syntax struct-name) (λ () #f)))
(with-syntax ([(ctc-x ...) (generate-temporaries (syntax (args ...)))] (with-syntax ([(ctc-x ...) (generate-temporaries (syntax (args ...)))]
[(ctc-name-x ...) (generate-temporaries (syntax (args ...)))] [(ctc-name-x ...) (generate-temporaries (syntax (args ...)))]
[(ctc-pred-x ...) (generate-temporaries (syntax (args ...)))] [(ctc-pred-x ...) (generate-temporaries (syntax (args ...)))]
@ -1392,7 +1508,7 @@ add struct contracts for immutable structs?
(syntax-local-value (syntax struct-name))]) (syntax-local-value (syntax struct-name))])
(with-syntax ([(selector-id ...) (reverse (syntax->list (syntax (rev-selector-id ...))))]) (with-syntax ([(selector-id ...) (reverse (syntax->list (syntax (rev-selector-id ...))))])
(syntax (syntax
(let ([ctc-x (coerce-contract struct/c args)] ...) (let ([ctc-x (coerce-contract 'struct/c args)] ...)
(unless predicate-id (unless predicate-id
(error 'struct/c "could not determine predicate for ~s" 'struct-name)) (error 'struct/c "could not determine predicate for ~s" 'struct-name))

View File

@ -128,6 +128,9 @@
(test/no-error '(listof any/c)) (test/no-error '(listof any/c))
(test/no-error '(listof (lambda (x) #t))) (test/no-error '(listof (lambda (x) #t)))
(test/spec-passed/result 'any/c '(contract any/c 1 'pos 'neg) 1)
(test/pos-blame 'none/c '(contract none/c 1 'pos 'neg))
(test/spec-passed (test/spec-passed
'contract-arrow-star0a 'contract-arrow-star0a
'(contract (->* (integer?) (integer?)) '(contract (->* (integer?) (integer?))
@ -1134,6 +1137,34 @@
'neg) 'neg)
1)) 1))
(test/pos-blame
'contract-case->0a
'(contract (case->)
(lambda (x) x)
'pos
'neg))
(test/pos-blame
'contract-case->0b
'(contract (case->)
(lambda () 1)
'pos
'neg))
(test/pos-blame
'contract-case->0c
'(contract (case->)
1
'pos
'neg))
(test/spec-passed
'contract-case->0d
'(contract (case->)
(case-lambda)
'pos
'neg))
(test/pos-blame (test/pos-blame
'contract-case->1 'contract-case->1
'(contract (case-> (integer? integer? . -> . integer?) (integer? . -> . integer?)) '(contract (case-> (integer? integer? . -> . integer?) (integer? . -> . integer?))
@ -1335,6 +1366,47 @@
#f) #f)
#f) #f)
(test/spec-passed/result
'or/c9
'((contract (or/c (-> string?) (-> integer? integer?))
(λ () "x")
'pos
'neg))
"x")
(test/spec-passed/result
'or/c10
'((contract (or/c (-> string?) (-> integer? integer?))
(λ (x) x)
'pos
'neg)
1)
1)
(test/pos-blame
'or/c11
'(contract (or/c (-> string?) (-> integer? integer?))
1
'pos
'neg))
(test/pos-blame
'or/c12
'((contract (or/c (-> string?) (-> integer? integer?))
1
'pos
'neg)
'x))
(test 1 'or/c-not-error-early
(begin (or/c (-> integer? integer?) (-> boolean? boolean?))
1))
(error-test #'(contract (or/c (-> integer? integer?) (-> boolean? boolean?))
(λ (x) x)
'pos
'neg)
exn:fail?)
(test (test
'(1 2) '(1 2)
'or/c-ordering 'or/c-ordering
@ -1365,6 +1437,20 @@
'neg) 'neg)
x)) x))
(test
(reverse '(1 3 4 2))
'ho-and/c-ordering
(let ([x '()])
((contract (and/c (-> (lambda (y) (set! x (cons 1 x)) #t)
(lambda (y) (set! x (cons 2 x)) #t))
(-> (lambda (y) (set! x (cons 3 x)) #t)
(lambda (y) (set! x (cons 4 x)) #t)))
(λ (x) x)
'pos
'neg)
1)
x))
(test/spec-passed (test/spec-passed
'define/contract1 'define/contract1
'(let () '(let ()
@ -3964,6 +4050,7 @@
(-> integer? integer? integer?)) (-> integer? integer? integer?))
(case-> (->r ((x number?) (y boolean?) (z pair?)) number?) (case-> (->r ((x number?) (y boolean?) (z pair?)) number?)
(-> integer? integer? integer?))) (-> integer? integer? integer?)))
(test-name '(case->) (case->))
(test-name '(case-> (-> integer? integer?) (-> integer? integer? integer?)) (test-name '(case-> (-> integer? integer?) (-> integer? integer? integer?))
(case-> (-> integer? integer?) (-> integer? integer? integer?))) (case-> (-> integer? integer?) (-> integer? integer? integer?)))
@ -4151,6 +4238,28 @@
(test #f contract-stronger? (symbols 'z 'x 'y) (symbols 'x 'y)) (test #f contract-stronger? (symbols 'z 'x 'y) (symbols 'x 'y))
(test #t contract-stronger? (one-of/c (expt 2 100)) (one-of/c (expt 2 100) 12)) (test #t contract-stronger? (one-of/c (expt 2 100)) (one-of/c (expt 2 100) 12))
(test #t contract-stronger?
(or/c (-> (>=/c 3) (>=/c 3)) (-> string?))
(or/c (-> (>=/c 4) (>=/c 3)) (-> string?)))
(test #f contract-stronger?
(or/c (-> string?) (-> integer? integer?))
(or/c (-> string?) (-> any/c integer?)))
(test #f contract-stronger?
(or/c (-> string?) (-> any/c integer?))
(or/c (-> string?) (-> integer? integer?)))
(test #t contract-stronger?
(or/c (-> string?) (-> integer? integer?) integer? boolean?)
(or/c (-> string?) (-> integer? integer?) integer? boolean?))
(test #f contract-stronger?
(or/c (-> string?) (-> integer? integer?) integer? char?)
(or/c (-> string?) (-> integer? integer?) integer? boolean?))
(test #f contract-stronger?
(or/c (-> string?) (-> integer? integer?) integer?)
(or/c (-> string?) (-> integer? integer?) integer? boolean?))
(test #f contract-stronger?
(or/c (-> string?) (-> integer? integer?) integer?)
(or/c (-> integer? integer?) integer?))
(let () (let ()
(define-contract-struct couple (hd tl)) (define-contract-struct couple (hd tl))
(define (non-zero? x) (not (zero? x))) (define (non-zero? x) (not (zero? x)))
@ -4194,5 +4303,185 @@
(test #t contract-stronger? (sorted-list/less-than 4) (sorted-list/less-than 5)) (test #t contract-stronger? (sorted-list/less-than 4) (sorted-list/less-than 5))
(test #f contract-stronger? (sorted-list/less-than 5) (sorted-list/less-than 4))) (test #f contract-stronger? (sorted-list/less-than 5) (sorted-list/less-than 4)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; first-order tests
;;
(test #t contract-first-order-passes? (flat-contract integer?) 1)
(test #f contract-first-order-passes? (flat-contract integer?) 'x)
(test #t contract-first-order-passes? (flat-contract boolean?) #t)
(test #f contract-first-order-passes? (flat-contract boolean?) 'x)
(test #t contract-first-order-passes? any/c 1)
(test #t contract-first-order-passes? any/c #t)
(test #t contract-first-order-passes? (-> integer? integer?) (λ (x) #t))
(test #f contract-first-order-passes? (-> integer? integer?) (λ (x y) #t))
(test #f contract-first-order-passes? (-> integer? integer?) 'x)
(test #t contract-first-order-passes? (-> integer? boolean? integer?) (λ (x y) #t))
(test #f contract-first-order-passes? (-> integer? boolean? integer?) (λ (x) #t))
(test #f contract-first-order-passes? (-> integer? boolean? integer?) (λ (x y z) #t))
(test #t contract-first-order-passes? (->* (integer?) boolean? (char? any/c)) (λ (x . y) #f))
(test #f contract-first-order-passes? (->* (integer?) boolean? (char? any/c)) (λ (x y . z) #f))
(test #f contract-first-order-passes? (->* (integer?) boolean? (char? any/c)) (λ (x) #f))
(test #t contract-first-order-passes? (->* (integer?) boolean? (char? any/c)) (λ x #f))
(test #t contract-first-order-passes? (->d integer? boolean? (lambda (x y) char?)) (λ (x y) x))
(test #f contract-first-order-passes? (->d integer? boolean? (lambda (x y) char?)) (λ (x) x))
(test #f contract-first-order-passes? (->d integer? boolean? (lambda (x y) char?)) (λ (x y z) x))
(test #t contract-first-order-passes? (list-immutableof integer?) (list-immutable 1))
(test #f contract-first-order-passes? (list-immutableof integer?) (list 1))
(test #f contract-first-order-passes? (list-immutableof integer?) #f)
(test #t contract-first-order-passes? (vector-immutableof integer?) (vector->immutable-vector (vector 1)))
(test #f contract-first-order-passes? (vector-immutableof integer?) 'x)
(test #f contract-first-order-passes? (vector-immutableof integer?) '())
(test #t contract-first-order-passes? (promise/c integer?) (delay 1))
(test #f contract-first-order-passes? (promise/c integer?) 1)
(test #t contract-first-order-passes? (->d* (integer? boolean?) (lambda (x y) char?)) (λ (x y) #t))
(test #f contract-first-order-passes? (->d* (integer? boolean?) (lambda (x y) char?)) (λ (x) #t))
(test #f contract-first-order-passes? (->d* (integer? boolean?) (lambda (x y) char?)) (λ (x y z) #t))
(test #t contract-first-order-passes?
(->d* (integer? boolean?) any/c (lambda (x y . z) char?))
(λ (x y . z) z))
(test #t contract-first-order-passes?
(->d* (integer? boolean?) any/c (lambda (x y . z) char?))
(λ (y . z) z))
(test #t contract-first-order-passes?
(->d* (integer? boolean?) any/c (lambda (x y . z) char?))
(λ z z))
(test #f contract-first-order-passes?
(->d* (integer? boolean?) any/c (lambda (x y . z) char?))
(λ (x y z . w) 1))
(test #f contract-first-order-passes?
(->d* (integer? boolean?) any/c (lambda (x y . z) char?))
(λ (x y) 1))
(test #t contract-first-order-passes? (->r ((x number?)) number?) (λ (x) 1))
(test #f contract-first-order-passes? (->r ((x number?)) number?) (λ (x y) 1))
(test #f contract-first-order-passes? (->r ((x number?)) number?) (λ () 1))
(test #t contract-first-order-passes? (->r ((x number?)) number?) (λ args 1))
(test #t contract-first-order-passes? (->pp ((x number?)) #t number? blech #t) (λ (x) 1))
(test #f contract-first-order-passes? (->pp ((x number?)) #t number? blech #t) (λ () 1))
(test #t contract-first-order-passes? (->pp ((x number?)) #t number? blech #t) (λ (x . y) 1))
(test #f contract-first-order-passes?
(case-> (-> integer? integer?)
(-> integer? integer? integer?))
(λ () 1))
(test #f contract-first-order-passes?
(case-> (-> integer? integer?)
(-> integer? integer? integer?))
(λ (x) 1))
(test #f contract-first-order-passes?
(case-> (-> integer? integer?)
(-> integer? integer? integer?))
(λ (x y) 1))
(test #f contract-first-order-passes?
(case->)
1)
(test #t contract-first-order-passes?
(case->)
(case-lambda))
(test #t contract-first-order-passes?
(case-> (-> integer? integer?)
(-> integer? integer? integer?))
(case-lambda [(x) x] [(x y) x]))
(test #t contract-first-order-passes?
(case-> (-> integer? integer?)
(-> integer? integer? integer?))
(case-lambda [() 1] [(x) x] [(x y) x]))
(test #t contract-first-order-passes?
(case-> (-> integer? integer?)
(-> integer? integer? integer?))
(case-lambda [() 1] [(x) x] [(x y) x] [(x y z) x]))
(test #t contract-first-order-passes? (and/c (-> positive? positive?) (-> integer? integer?)) (λ (x) x))
(test #t contract-first-order-passes? (and/c (-> positive? positive?) (-> integer? integer?)) values)
(test #f contract-first-order-passes? (and/c (-> integer?) (-> integer? integer?)) (λ (x) x))
(test #t contract-first-order-passes?
(cons-immutable/c boolean? (-> integer? integer?))
(list*-immutable #t (λ (x) x)))
(test #t contract-first-order-passes?
(cons-immutable/c boolean? (-> integer? integer?))
(list*-immutable 1 2))
(test #f contract-first-order-passes? (flat-rec-contract the-name) 1)
(test #t contract-first-order-passes?
(object-contract (m (-> integer? integer?)))
(new object%))
(test #t contract-first-order-passes?
(object-contract (m (-> integer? integer?)))
1)
(let ()
(define-contract-struct couple (hd tl))
(test #t contract-first-order-passes?
(couple/c any/c any/c)
(make-couple 1 2))
(test #f contract-first-order-passes?
(couple/c any/c any/c)
2)
(test #t contract-first-order-passes?
(couple/dc [hd any/c] [tl any/c])
(make-couple 1 2))
(test #f contract-first-order-passes?
(couple/dc [hd any/c] [tl any/c])
1)
(test #t contract-first-order-passes?
(couple/dc [hd any/c] [tl (hd) any/c])
(make-couple 1 2))
(test #f contract-first-order-passes?
(couple/dc [hd any/c] [tl (hd) any/c])
1))
(test #t contract-first-order-passes? (or/c (-> (>=/c 5) (>=/c 5)) boolean?) #t)
(test #t contract-first-order-passes? (or/c (-> (>=/c 5) (>=/c 5)) boolean?) (λ (x) x))
(test #f contract-first-order-passes? (or/c (-> (>=/c 5) (>=/c 5)) boolean?) 'x)
(test #t contract-first-order-passes?
(or/c (-> integer? integer? integer?)
(-> integer? integer?))
(λ (x) x))
(test #t contract-first-order-passes?
(or/c (-> integer? integer? integer?)
(-> integer? integer?))
(λ (x y) x))
(test #f contract-first-order-passes?
(or/c (-> integer? integer? integer?)
(-> integer? integer?))
(λ () x))
(test #f contract-first-order-passes?
(or/c (-> integer? integer? integer?)
(-> integer? integer?))
1)
(test-name '(or/c) (or/c))
(test-name '(or/c integer? gt0?) (or/c integer? (let ([gt0? (lambda (x) (> x 0))]) gt0?)))
(test-name '(or/c integer? boolean?)
(or/c (flat-contract integer?)
(flat-contract boolean?)))
(test-name '(or/c (-> (>=/c 5) (>=/c 5)) boolean?)
(or/c (-> (>=/c 5) (>=/c 5)) boolean?))
(test-name '(or/c (-> (>=/c 5) (>=/c 5)) boolean?)
(or/c boolean? (-> (>=/c 5) (>=/c 5))))
)) ))
(report-errs) (report-errs)