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