made a bunch of the contract combinators also propogate blame information

for use in check syntax
This commit is contained in:
Robby Findler 2010-07-13 05:27:09 -05:00
parent 18b8cde3e2
commit 482481fff5
2 changed files with 88 additions and 20 deletions

View File

@ -46,7 +46,11 @@
;; for opters ;; for opters
check-flat-contract check-flat-contract
check-flat-named-contract check-flat-named-contract
any) any
;; helpers for adding properties that check syntax uses
define/final-prop
define/subexpression-pos-prop)
(define-values (prop:contracted has-contract? value-contract) (define-values (prop:contracted has-contract? value-contract)
(let-values ([(prop pred get) (let-values ([(prop pred get)
@ -375,3 +379,67 @@
#:first-order (λ (ctc) (predicate-contract-pred ctc)))) #:first-order (λ (ctc) (predicate-contract-pred ctc))))
(define (build-flat-contract name pred) (make-predicate-contract name pred)) (define (build-flat-contract name pred) (make-predicate-contract name pred))
(define-syntax (define/final-prop stx)
(syntax-case stx ()
[(_ header bodies ...)
(with-syntax ([ctc (if (identifier? #'header)
#'header
(car (syntax-e #'header)))])
(with-syntax ([ctc/proc (string->symbol (format "~a/proc" (syntax-e #'ctc)))])
#'(begin
(define ctc/proc
(let ()
(define header bodies ...)
ctc))
(define-syntax (ctc stx)
(syntax-case stx ()
[x
(identifier? #'x)
(syntax-property
#'x
'racket/contract:contract
(vector (gensym 'ctc)
(list stx)
'()))]
[(_ margs (... ...))
(syntax-property
#'(ctc/proc margs (... ...))
'racket/contract:contract
(vector (gensym 'ctc)
(list (car (syntax-e stx)))
'()))])))))]))
(define-syntax (define/subexpression-pos-prop stx)
(syntax-case stx ()
[(_ header bodies ...)
(with-syntax ([ctc (if (identifier? #'header)
#'header
(car (syntax-e #'header)))])
(with-syntax ([ctc/proc (string->symbol (format "~a/proc" (syntax-e #'ctc)))])
#'(begin
(define ctc/proc
(let ()
(define header bodies ...)
ctc))
(define-syntax (ctc stx)
(syntax-case stx ()
[x
(identifier? #'x)
(syntax-property
#'x
'racket/contract:contract
(vector (gensym 'ctc)
(list stx)
'()))]
[(_ margs (... ...))
(let ([this-one (gensym 'ctc)])
(with-syntax ([(margs (... ...))
(map (λ (x) (syntax-property x 'racket/contract:rng-of this-one))
(syntax->list #'(margs (... ...))))])
(syntax-property
#'(ctc/proc margs (... ...))
'racket/contract:contract
(vector this-one
(list (car (syntax-e stx)))
'()))))])))))]))

View File

@ -86,7 +86,7 @@
[(_ ([name ctc ...] ...)) [(_ ([name ctc ...] ...))
(raise-syntax-error 'flat-rec-contract "expected at least one body expression" stx)])) (raise-syntax-error 'flat-rec-contract "expected at least one body expression" stx)]))
(define or/c (define/subexpression-pos-prop or/c
(case-lambda (case-lambda
[() (make-none/c '(or/c))] [() (make-none/c '(or/c))]
[raw-args [raw-args
@ -385,7 +385,7 @@
(define false/c #f) (define false/c #f)
(define (string-len/c n) (define/final-prop (string-len/c n)
(unless (number? n) (unless (number? n)
(error 'string-len/c "expected a number as argument, got ~e" n)) (error 'string-len/c "expected a number as argument, got ~e" n))
(flat-named-contract (flat-named-contract
@ -394,7 +394,7 @@
(and (string? x) (and (string? x)
((string-length x) . < . n))))) ((string-length x) . < . n)))))
(define (symbols . ss) (define/final-prop (symbols . ss)
(unless ((length ss) . >= . 1) (unless ((length ss) . >= . 1)
(error 'symbols "expected at least one argument")) (error 'symbols "expected at least one argument"))
(unless (andmap symbol? ss) (unless (andmap symbol? ss)
@ -409,7 +409,7 @@
(null? x) (keyword? x) (number? x) (null? x) (keyword? x) (number? x)
(void? x) (eq? x undefined))))) (void? x) (eq? x undefined)))))
(define (one-of/c . elems) (define/final-prop (one-of/c . elems)
(unless (andmap atomic-value? elems) (unless (andmap atomic-value? elems)
(error 'one-of/c "expected chars, symbols, booleans, null, keywords, numbers, void, or undefined, got ~e" (error 'one-of/c "expected chars, symbols, booleans, null, keywords, numbers, void, or undefined, got ~e"
elems)) elems))
@ -519,13 +519,13 @@
(unless (real? x) (unless (real? x)
(error 'sym "expected a real number, got ~e" x)))])) (error 'sym "expected a real number, got ~e" x)))]))
(define (=/c x) (define/final-prop (=/c x)
(check-unary-between/c '=/c x) (check-unary-between/c '=/c x)
(make-between/c x x)) (make-between/c x x))
(define (<=/c x) (define/final-prop (<=/c x)
(check-unary-between/c '<=/c x) (check-unary-between/c '<=/c x)
(make-between/c -inf.0 x)) (make-between/c -inf.0 x))
(define (>=/c x) (define/final-prop (>=/c x)
(check-unary-between/c '>=/c x) (check-unary-between/c '>=/c x)
(make-between/c x +inf.0)) (make-between/c x +inf.0))
(define (check-between/c x y) (define (check-between/c x y)
@ -533,7 +533,7 @@
(error 'between/c "expected a real number as first argument, got ~e, other arg ~e" x y)) (error 'between/c "expected a real number as first argument, got ~e, other arg ~e" x y))
(unless (real? y) (unless (real? y)
(error 'between/c "expected a real number as second argument, got ~e, other arg ~e" y x))) (error 'between/c "expected a real number as second argument, got ~e, other arg ~e" y x)))
(define (between/c x y) (define/final-prop (between/c x y)
(check-between/c x y) (check-between/c x y)
(make-between/c x y)) (make-between/c x y))
@ -682,7 +682,7 @@
(exact? x) (exact? x)
(x . >= . 0))))) (x . >= . 0)))))
(define (integer-in start end) (define/final-prop (integer-in start end)
(unless (and (integer? start) (unless (and (integer? start)
(exact? start) (exact? start)
(integer? end) (integer? end)
@ -695,7 +695,7 @@
(exact? x) (exact? x)
(<= start x end))))) (<= start x end)))))
(define (real-in start end) (define/final-prop (real-in start end)
(unless (and (real? start) (unless (and (real? start)
(real? end)) (real? end))
(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))
@ -705,7 +705,7 @@
(and (real? x) (and (real? x)
(<= start x end))))) (<= start x end)))))
(define (not/c f) (define/final-prop (not/c f)
(let* ([ctc (coerce-flat-contract 'not/c f)] (let* ([ctc (coerce-flat-contract 'not/c f)]
[pred (flat-contract-predicate ctc)]) [pred (flat-contract-predicate ctc)])
(build-flat-contract (build-flat-contract
@ -760,7 +760,7 @@
(define non-empty-listof (define non-empty-listof
(*-immutableof non-empty-list? for-each map andmap non-empty-list non-empty-listof)) (*-immutableof non-empty-list? for-each map andmap non-empty-list non-empty-listof))
(define (immutable-vector? val) (and (immutable? val) (vector? val))) (define/final-prop (immutable-vector? val) (and (immutable? val) (vector? val)))
(define vector-immutableof (define vector-immutableof
(*-immutableof immutable-vector? (*-immutableof immutable-vector?
@ -770,7 +770,7 @@
immutable-vector immutable-vector
vector-immutableof)) vector-immutableof))
(define (vectorof p) (define/subexpression-pos-prop (vectorof p)
(let* ([ctc (coerce-flat-contract 'vectorof p)] (let* ([ctc (coerce-flat-contract 'vectorof p)]
[pred (flat-contract-predicate ctc)]) [pred (flat-contract-predicate ctc)])
(build-flat-contract (build-flat-contract
@ -779,7 +779,7 @@
(and (vector? v) (and (vector? v)
(andmap pred (vector->list v))))))) (andmap pred (vector->list v)))))))
(define (vector/c . args) (define/subexpression-pos-prop (vector/c . args)
(let* ([ctcs (coerce-flat-contracts 'vector/c args)] (let* ([ctcs (coerce-flat-contracts 'vector/c args)]
[largs (length args)] [largs (length args)]
[procs (map flat-contract-predicate ctcs)]) [procs (map flat-contract-predicate ctcs)])
@ -792,7 +792,7 @@
procs procs
(vector->list v))))))) (vector->list v)))))))
(define (box/c pred) (define/final-prop (box/c pred)
(let* ([ctc (coerce-flat-contract 'box/c pred)] (let* ([ctc (coerce-flat-contract 'box/c pred)]
[p? (flat-contract-predicate ctc)]) [p? (flat-contract-predicate ctc)])
(build-flat-contract (build-flat-contract
@ -1030,7 +1030,7 @@
(syntax-case stx (cons/c) (syntax-case stx (cons/c)
[(_ hdp tlp) (opt/cons-ctc #'hdp #'tlp)])) [(_ hdp tlp) (opt/cons-ctc #'hdp #'tlp)]))
(define (list/c . args) (define/subexpression-pos-prop (list/c . args)
(let* ([args (coerce-contracts 'list/c args)]) (let* ([args (coerce-contracts 'list/c args)])
(if (andmap flat-contract? args) (if (andmap flat-contract? args)
(flat-list/c args) (flat-list/c args)
@ -1101,7 +1101,7 @@
(for/list ([arg/c (in-list args)] [v (in-list x)]) (for/list ([arg/c (in-list args)] [v (in-list x)])
(((contract-projection arg/c) b) v)))))))) (((contract-projection arg/c) b) v))))))))
(define (syntax/c ctc-in) (define/subexpression-pos-prop (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)
@ -1110,7 +1110,7 @@
(and (syntax? val) (and (syntax? val)
(pred (syntax-e val)))))))) (pred (syntax-e val))))))))
(define promise/c (define/subexpression-pos-prop promise/c
(λ (ctc-in) (λ (ctc-in)
(let* ([ctc (coerce-contract 'promise/c ctc-in)] (let* ([ctc (coerce-contract 'promise/c ctc-in)]
[ctc-proc (contract-projection ctc)]) [ctc-proc (contract-projection ctc)])
@ -1197,7 +1197,7 @@
(raise-syntax-error 'struct/c "expected a struct identifier" stx (syntax struct-name))])) (raise-syntax-error 'struct/c "expected a struct identifier" stx (syntax struct-name))]))
(define (parameter/c x) (define/subexpression-pos-prop (parameter/c x)
(make-parameter/c (coerce-contract 'parameter/c x))) (make-parameter/c (coerce-contract 'parameter/c x)))
(define-struct parameter/c (ctc) (define-struct parameter/c (ctc)