..
original commit: d14cfb79aa467931c0d1e79d828b2b7f338e3d6f
This commit is contained in:
parent
9aa0fb6739
commit
87e852a921
|
@ -142,10 +142,12 @@
|
|||
|
||||
;; flat-named-contract = (make-flat-named-contract string (any -> boolean))
|
||||
;; this holds flat contracts that have names for error reporting
|
||||
(define-struct flat-named-contract (type-name predicate))
|
||||
(define-struct flat-named-contract (type-name predicate) (make-inspector)) (print-struct #t)
|
||||
|
||||
(provide (rename build-flat-named-contract flat-named-contract)
|
||||
flat-named-contract-type-name
|
||||
flat-named-contract-predicate)
|
||||
|
||||
(define build-flat-named-contract
|
||||
(let ([flat-named-contract
|
||||
(lambda (name contract)
|
||||
|
@ -693,24 +695,36 @@
|
|||
pos
|
||||
neg
|
||||
"~agiven: ~e~a"
|
||||
(predicate->type-name contract)
|
||||
(predicate->expected-msg contract)
|
||||
val
|
||||
(if extra-message
|
||||
extra-message
|
||||
"")))]))
|
||||
|
||||
;; predicate->type-name : function -> string
|
||||
;; predicate->expected-msg : function -> string
|
||||
;; if the function has a name and the name ends
|
||||
;; with a question mark, turn it into a mzscheme
|
||||
;; style type name
|
||||
(define (predicate->expected-msg pred)
|
||||
(let ([name (predicate->type-name)])
|
||||
(if name
|
||||
(format "expected type <~a>, " name)
|
||||
"")))
|
||||
|
||||
;; predicate->type-name : pred -> (union #f string)
|
||||
(define (predicate->type-name pred)
|
||||
(let* ([name (object-name pred)])
|
||||
(if name
|
||||
(let ([m (regexp-match "(.*)\\?" (symbol->string name))])
|
||||
(if m
|
||||
(format "expected type <~a>, " (cadr m))
|
||||
""))
|
||||
"")))
|
||||
(and name
|
||||
(let ([m (regexp-match "(.*)\\?" (symbol->string name))])
|
||||
(and m
|
||||
(cadr m))))))
|
||||
|
||||
;; flat-contract->type-name : flat-contract -> string
|
||||
(define (flat-contract->type-name fc)
|
||||
(cond
|
||||
[(flat-named-contract? fc) (flat-named-contract-type-name fc)]
|
||||
[else (or (predicate->type-name fc)
|
||||
"unknown type")]))
|
||||
|
||||
(provide union)
|
||||
(define (union . args)
|
||||
|
@ -732,19 +746,27 @@
|
|||
(unless (or (null? contracts)
|
||||
(null? (cdr contracts)))
|
||||
(error 'union "expected at most one function contract, given: ~e" args))
|
||||
(make-contract
|
||||
(lambda (val pos neg src-info)
|
||||
(cond
|
||||
[(ormap (lambda (proc)
|
||||
(if (flat-named-contract? proc)
|
||||
((flat-named-contract-predicate proc) val)
|
||||
(proc val)))
|
||||
procs)
|
||||
val]
|
||||
[(null? contracts)
|
||||
(raise-contract-error src-info pos neg "union failed, given: ~e" val)]
|
||||
[(null? (cdr contracts))
|
||||
((contract-f (car contracts)) val pos neg src-info)])))))
|
||||
(cond
|
||||
[(null? contracts)
|
||||
(make-flat-named-contract
|
||||
(apply build-compound-type-name "union" procs)
|
||||
(lambda (x)
|
||||
(ormap (lambda (proc) (test-flat-contract proc x))
|
||||
procs)))]
|
||||
[else
|
||||
(make-contract
|
||||
(lambda (val pos neg src-info)
|
||||
(cond
|
||||
[(ormap (lambda (proc)
|
||||
(if (flat-named-contract? proc)
|
||||
((flat-named-contract-predicate proc) val)
|
||||
(proc val)))
|
||||
procs)
|
||||
val]
|
||||
[(null? contracts)
|
||||
(raise-contract-error src-info pos neg "union failed, given: ~e" val)]
|
||||
[(null? (cdr contracts))
|
||||
((contract-f (car contracts)) val pos neg src-info)])))])))
|
||||
|
||||
(provide and/f or/f
|
||||
>=/c <=/c </c >/c
|
||||
|
@ -753,9 +775,37 @@
|
|||
printable?
|
||||
symbols
|
||||
subclass?/c implementation?/c is-a?/c
|
||||
listof vectorof cons/p list/p
|
||||
listof vectorof vector/p cons/p list/p box/p
|
||||
mixin-contract make-mixin-contract)
|
||||
|
||||
;; test-flat-contract : (union pred flat-named-contract) any -> boolean
|
||||
(define (test-flat-contract flat-contract x)
|
||||
(cond
|
||||
[(flat-named-contract? flat-contract)
|
||||
((flat-named-contract-predicate flat-contract) x)]
|
||||
[else
|
||||
(flat-contract x)]))
|
||||
|
||||
|
||||
;; flat-contract? : any -> boolean?
|
||||
;; determines if a value is a flat contract
|
||||
(define (flat-contract? fc)
|
||||
(or (flat-named-contract? fc)
|
||||
(and (procedure? fc)
|
||||
(procedure-arity-includes? fc 1))))
|
||||
|
||||
(define (build-compound-type-name name . fs)
|
||||
(let ([strs (map flat-contract->type-name fs)])
|
||||
(format "(~a~a)"
|
||||
name
|
||||
(apply string-append
|
||||
(let loop ([strs strs])
|
||||
(cond
|
||||
[(null? strs) null]
|
||||
[else (cons " "
|
||||
(cons (car strs)
|
||||
(loop (cdr strs))))]))))))
|
||||
|
||||
(define (symbols . ss)
|
||||
(unless ((length ss) . >= . 1)
|
||||
(error 'symbols "expected at least one argument"))
|
||||
|
@ -769,20 +819,24 @@
|
|||
(lambda (x)
|
||||
(memq x ss))))
|
||||
|
||||
(define (printable? x)
|
||||
(or (symbol? x)
|
||||
(string? x)
|
||||
(boolean? x)
|
||||
(char? x)
|
||||
(null? x)
|
||||
(number? x)
|
||||
(and (pair? x)
|
||||
(printable? (car x))
|
||||
(printable? (cdr x)))
|
||||
(and (vector? x)
|
||||
(andmap printable? (vector->list x)))
|
||||
(and (box? x)
|
||||
(printable? (unbox x)))))
|
||||
(define printable?
|
||||
(make-flat-named-contract
|
||||
"printable"
|
||||
(lambda (x)
|
||||
(let printable? ([x x])
|
||||
(or (symbol? x)
|
||||
(string? x)
|
||||
(boolean? x)
|
||||
(char? x)
|
||||
(null? x)
|
||||
(number? x)
|
||||
(and (pair? x)
|
||||
(printable? (car x))
|
||||
(printable? (cdr x)))
|
||||
(and (vector? x)
|
||||
(andmap printable? (vector->list x)))
|
||||
(and (box? x)
|
||||
(printable? (unbox x))))))))
|
||||
|
||||
(define (and/f . fs)
|
||||
(for-each
|
||||
|
@ -792,12 +846,11 @@
|
|||
(procedure-arity-includes? x 1)))
|
||||
(error 'and/f "expected procedures of arity 1 or <flat-named-contract>s, given: ~e" x)))
|
||||
fs)
|
||||
(lambda (x)
|
||||
(andmap (lambda (f)
|
||||
(if (flat-named-contract? f)
|
||||
((flat-named-contract-predicate f) x)
|
||||
(f x)))
|
||||
fs)))
|
||||
(make-flat-named-contract
|
||||
(apply build-compound-type-name "and/f" fs)
|
||||
(lambda (x)
|
||||
(andmap (lambda (f) (test-flat-contract f x))
|
||||
fs))))
|
||||
|
||||
(define (or/f . fs)
|
||||
(for-each
|
||||
|
@ -807,12 +860,11 @@
|
|||
(procedure-arity-includes? x 1)))
|
||||
(error 'or/f "expected procedures of arity 1 or <flat-named-contract>s, given: ~e" x)))
|
||||
fs)
|
||||
(lambda (x)
|
||||
(ormap (lambda (f)
|
||||
(if (flat-named-contract? f)
|
||||
((flat-named-contract-predicate f) x)
|
||||
(f x)))
|
||||
fs)))
|
||||
(make-flat-named-contract
|
||||
(apply build-compound-type-name "or/f" fs)
|
||||
(lambda (x)
|
||||
(ormap (lambda (f) (test-flat-contract f x))
|
||||
fs))))
|
||||
|
||||
(define (>=/c x)
|
||||
(make-flat-named-contract
|
||||
|
@ -831,10 +883,13 @@
|
|||
(format "number > ~a" x)
|
||||
(lambda (y) (and (number? y) (> y x)))))
|
||||
|
||||
(define (natural-number? x)
|
||||
(and (number? x)
|
||||
(integer? x)
|
||||
(x . >= . 0)))
|
||||
(define natural-number?
|
||||
(make-flat-named-contract
|
||||
"natural-number"
|
||||
(lambda (x)
|
||||
(and (number? x)
|
||||
(integer? x)
|
||||
(x . >= . 0)))))
|
||||
|
||||
(define (is-a?/c <%>)
|
||||
(unless (or (interface? <%>)
|
||||
|
@ -867,26 +922,85 @@
|
|||
"implementation of <<unknown>>")
|
||||
(lambda (x) (implementation? x <%>)))))
|
||||
|
||||
(define (false? x) (not x))
|
||||
(define (any? x) #t)
|
||||
(define false?
|
||||
(make-flat-named-contract
|
||||
"false"
|
||||
(lambda (x) (not x))))
|
||||
|
||||
(define any?
|
||||
(make-flat-named-contract
|
||||
"any"
|
||||
(lambda (x) #t)))
|
||||
|
||||
(define (listof p)
|
||||
(lambda (v)
|
||||
(and (list? v)
|
||||
(andmap p v))))
|
||||
(unless (flat-contract? p)
|
||||
(error 'listof "expected a flat contract as argument, got: ~e" p))
|
||||
(make-flat-named-contract
|
||||
(build-compound-type-name "listof" p)
|
||||
(lambda (v)
|
||||
(and (list? v)
|
||||
(andmap (lambda (ele) (test-flat-contract p ele))
|
||||
v)))))
|
||||
|
||||
(define (vectorof p)
|
||||
(lambda (v)
|
||||
(and (vector? v)
|
||||
(andmap p (vector->list v)))))
|
||||
(unless (flat-contract? p)
|
||||
(error 'vectorof "expected a flat contract as argument, got: ~e" p))
|
||||
(make-flat-named-contract
|
||||
(build-compound-type-name "vectorof" p)
|
||||
(lambda (v)
|
||||
(and (vector? v)
|
||||
(andmap (lambda (ele) (test-flat-contract p ele))
|
||||
(vector->list v))))))
|
||||
|
||||
(define (vector/p . args)
|
||||
(unless (andmap flat-contract? args)
|
||||
(error 'vector/p "expected flat contracts as arguments, got: ~a"
|
||||
(let loop ([args args])
|
||||
(cond
|
||||
[(null? args) ""]
|
||||
[(null? (cdr args)) (format "~e" (car args))]
|
||||
[else (string-append
|
||||
(format "~e " (car args))
|
||||
(loop (cdr args)))]))))
|
||||
(make-flat-named-contract
|
||||
(apply build-compound-type-name "vector/p" args)
|
||||
(lambda (v)
|
||||
(and (vector? v)
|
||||
(= (vector-length v) (length args))
|
||||
(andmap test-flat-contract
|
||||
args
|
||||
(vector->list v))))))
|
||||
|
||||
(define (box/p pred)
|
||||
(unless (flat-contract? pred)
|
||||
(error 'box/p "expected a flat contract, got: ~e" pred))
|
||||
(make-flat-named-contract
|
||||
(build-compound-type-name "box/p" pred)
|
||||
(lambda (x)
|
||||
(and (box? x)
|
||||
(test-flat-contract pred (unbox x))))))
|
||||
|
||||
(define (cons/p hdp tlp)
|
||||
(lambda (x)
|
||||
(and (pair? x)
|
||||
(hdp (car x))
|
||||
(tlp (cdr x)))))
|
||||
(unless (and (flat-contract? hdp)
|
||||
(flat-contract? tlp))
|
||||
(error 'cons/p "expected two flat contracts, got: ~e and ~e" hdp tlp))
|
||||
(make-flat-named-contract
|
||||
(build-compound-type-name "cons/p" hdp tlp)
|
||||
(lambda (x)
|
||||
(and (pair? x)
|
||||
(test-flat-contract hdp (car x))
|
||||
(test-flat-contract tlp (cdr x))))))
|
||||
|
||||
(define (list/p . args)
|
||||
(unless (andmap flat-contract? args)
|
||||
(error 'list/p "expected flat contracts, got: ~a"
|
||||
(let loop ([args args])
|
||||
(cond
|
||||
[(null? args) ""]
|
||||
[(null? (cdr args)) (format "~e" (car args))]
|
||||
[else (string-append
|
||||
(format "~e " (car args))
|
||||
(loop (cdr args)))]))))
|
||||
(let loop ([args args])
|
||||
(cond
|
||||
[(null? args) null?]
|
||||
|
|
Loading…
Reference in New Issue
Block a user