original commit: 2a6090270b1766d7b4798afd8171a5c5f953ca60
This commit is contained in:
Robby Findler 2003-01-22 23:59:22 +00:00
parent 1f91794eea
commit 0826088493
2 changed files with 128 additions and 72 deletions

View File

@ -822,75 +822,74 @@
(and (and
(andmap method-specifier? (syntax->list (syntax (method-specifier ...)))) (andmap method-specifier? (syntax->list (syntax (method-specifier ...))))
(andmap identifier? (syntax->list (syntax (meth-name ...))))) (andmap identifier? (syntax->list (syntax (meth-name ...)))))
(match-let ([(`(,make-outer-checks ,xxx ,build-pieces) ...) (let* ([outer-args (syntax (val pos-blame neg-blame src-info))]
(map (lambda (meth-contract-stx) [val-meth-names (syntax->list (syntax (meth-name ...)))]
(let ([/h (select/h meth-contract-stx 'class-contract stx)]) [val-publics? (map (lambda (x) (eq? 'public (syntax-e x)))
(let-values ([(make-outer-check xxx build-pieces impl-wrap impl-builder impl-info) (syntax->list (syntax (method-specifier ...))))]
(/h meth-contract-stx)]) [super-meth-names (map prefix-super val-meth-names)]
(list make-outer-check xxx build-pieces)))) [val-meth-contracts (syntax->list (syntax (meth-contract ...)))]
(syntax->list (syntax (meth-contract ...))))]) [val-meth-contract-vars (generate-temporaries val-meth-contracts)])
(let* ([outer-args (syntax (val pos-blame neg-blame src-info))]
[val-meth-names (syntax->list (syntax (meth-name ...)))] (let ([ht (make-hash-table)])
[val-publics? (map (lambda (x) (eq? 'public (syntax-e x))) (for-each (lambda (name)
(syntax->list (syntax (method-specifier ...))))] (let ([key (syntax-e name)])
[super-meth-names (map prefix-super val-meth-names)] (when (hash-table-get ht key (lambda () #f))
[val-meth-contracts (syntax->list (syntax (meth-contract ...)))] (raise-syntax-error 'class/contract "duplicate method name in contract" stx name))
[val-meth-contract-vars (generate-temporaries val-meth-contracts)]) (hash-table-put! ht key #t)))
(with-syntax ([outer-args outer-args] val-meth-names))
[(super-meth-name ...) super-meth-names]
[(get-meth-contract ...) (map method-name->contract-method-name val-meth-names)] (with-syntax ([outer-args outer-args]
[(method ...) (map (lambda (meth-name meth-contract-var contract-stx public?) [(super-meth-name ...) super-meth-names]
(if public? [(get-meth-contract ...) (map method-name->contract-method-name val-meth-names)]
(make-wrapper-method outer-args meth-name meth-contract-var contract-stx) [(method ...) (map (lambda (meth-name meth-contract-var contract-stx public?)
(make-wrapper-method/impl outer-args meth-name meth-contract-var contract-stx))) (if public?
val-meth-names (make-wrapper-method outer-args meth-name meth-contract-var contract-stx)
val-meth-contract-vars (make-wrapper-method/impl outer-args meth-name meth-contract-var contract-stx)))
val-meth-contracts val-meth-names
val-publics?)] val-meth-contract-vars
[(meth-contract-var ...) val-meth-contract-vars] val-meth-contracts
[(method-contract-declarations ...) (map (lambda (meth-name meth-contract-var public?) val-publics?)]
(if public? [(meth-contract-var ...) val-meth-contract-vars]
(make-public-method-contract-declaration meth-name meth-contract-var) [(method-contract-declarations ...) (map (lambda (meth-name meth-contract-var public?)
(make-override-method-contract-declaration meth-name meth-contract-var))) (if public?
val-meth-names (make-public-method-contract-declaration meth-name meth-contract-var)
val-meth-contract-vars (make-override-method-contract-declaration meth-name meth-contract-var)))
val-publics?)]) val-meth-names
(foldr val-meth-contract-vars
(lambda (f stx) (f stx)) val-publics?)])
(syntax/loc stx (syntax/loc stx
(let ([meth-contract-var meth-contract] ...) (let ([meth-contract-var meth-contract] ...)
(make-contract (make-contract
(lambda outer-args (lambda outer-args
(unless (class? val) (unless (class? val)
(raise-contract-error src-info pos-blame neg-blame "expected a class, got: ~e" val)) (raise-contract-error src-info pos-blame neg-blame "expected a class, got: ~e" val))
(let ([class-i (class->interface val)]) (let ([class-i (class->interface val)])
(void) (void)
(unless (method-in-interface? 'meth-name class-i) (unless (method-in-interface? 'meth-name class-i)
(raise-contract-error src-info (raise-contract-error src-info
pos-blame pos-blame
neg-blame neg-blame
"expected class to have method ~a, got: ~e" "expected class to have method ~a, got: ~e"
'meth-name 'meth-name
val)) val))
... ...
(let ([override-spec? (eq? 'override 'method-specifier)] (let ([override-spec? (eq? 'override 'method-specifier)]
[override? (method-in-interface? 'get-meth-contract class-i)]) [override? (method-in-interface? 'get-meth-contract class-i)])
(unless (boolean=? override-spec? override?) (unless (boolean=? override-spec? override?)
(if override-spec? (if override-spec?
(error 'class-contract "method ~a is declared as an overriding method in ~e, but isn't" 'meth-name val) (error 'class-contract "method ~a is declared as an overriding method in ~e, but isn't" 'meth-name val)
(error 'class-contract "method ~a is declared as a public method in ~e, but isn't" 'meth-name val)))) (error 'class-contract "method ~a is declared as a public method in ~e, but isn't" 'meth-name val))))
...) ...)
(class val (class val
method-contract-declarations ... method-contract-declarations ...
(rename [super-meth-name meth-name] ...) (rename [super-meth-name meth-name] ...)
method ... method ...
(super-instantiate ()))) (super-instantiate ())))
(lambda x (error 'impl-contract "unimplemented"))))) (lambda x (error 'impl-contract "unimplemented")))))))]
make-outer-checks))))]
[(_ (meth-specifier meth-name meth-contract) ...) [(_ (meth-specifier meth-name meth-contract) ...)
(for-each (lambda (specifier name) (for-each (lambda (specifier name)
(unless (method-specifier? name) (unless (method-specifier? name)
@ -1570,8 +1569,10 @@
((contract-wrap (car contracts)) val pos neg src-info)])) ((contract-wrap (car contracts)) val pos neg src-info)]))
(lambda x (error 'impl-contract "unimplemented")))]))) (lambda x (error 'impl-contract "unimplemented")))])))
(provide and/f or/f (provide and/f or/f not/f
>=/c <=/c </c >/c >=/c <=/c </c >/c
integer-in real-in
string/len
natural-number? natural-number?
false? any? false? any?
printable? printable?
@ -1608,6 +1609,15 @@
(cons (car strs) (cons (car strs)
(loop (cdr strs))))])))))) (loop (cdr strs))))]))))))
(define (string/len n)
(unless (number? n)
(error 'string/len "expected a number as argument, got ~e" n))
(make-flat-named-contract
(format "string (up to ~a characters)" n)
(lambda (x)
(and (string? x)
((string-length x) . < . n)))))
(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"))
@ -1653,7 +1663,7 @@
(lambda (x) (lambda (x)
(andmap (lambda (f) (test-flat-contract f x)) (andmap (lambda (f) (test-flat-contract f x))
fs)))) fs))))
(define (or/f . fs) (define (or/f . fs)
(for-each (for-each
(lambda (x) (lambda (x)
@ -1667,6 +1677,16 @@
(lambda (x) (lambda (x)
(ormap (lambda (f) (test-flat-contract f x)) (ormap (lambda (f) (test-flat-contract f x))
fs)))) fs))))
(define (not/f f)
(unless (or (flat-named-contract? f)
(and (procedure? f)
(procedure-arity-includes? f 1)))
(error 'not/f "expected a procedure of arity 1 or <flat-named-contract>, given: ~e" f))
(make-flat-named-contract
(build-compound-type-name "not/f" f)
(lambda (x)
(not (f x)))))
(define (>=/c x) (define (>=/c x)
(make-flat-named-contract (make-flat-named-contract
@ -1728,7 +1748,7 @@
(make-flat-named-contract (make-flat-named-contract
"false" "false"
(lambda (x) (not x)))) (lambda (x) (not x))))
(define any? (define any?
(make-flat-named-contract (make-flat-named-contract
"any" "any"
@ -1773,6 +1793,26 @@
args args
(vector->list v)))))) (vector->list v))))))
(define (integer-in start end)
(unless (and (integer? start)
(integer? end))
(error 'integer-in "expected two integers as arguments, got ~e and ~e" start end))
(make-flat-named-contract
(format "integer between ~a and ~a, inclusive" start end)
(lambda (x)
(and (integer? x)
(<= start x end)))))
(define (real-in start end)
(unless (and (real? start)
(real? end))
(error 'real-in "expected two real numbers as arguments, got ~e and ~e" start end))
(make-flat-named-contract
(format "real between ~a and ~a, inclusive" start end)
(lambda (x)
(and (real? x)
(<= start x end)))))
(define (box/p pred) (define (box/p pred)
(unless (flat-contract? pred) (unless (flat-contract? pred)
(error 'box/p "expected a flat contract, got: ~e" pred)) (error 'box/p "expected a flat contract, got: ~e" pred))

View File

@ -881,6 +881,22 @@
(send (make-object d%) m 100)) (send (make-object d%) m 100))
"pos-d") "pos-d")
(test/spec-failed
'not/f1
'(contract (not/f integer?)
1
'pos
'neg)
"pos-d")
(test/spec-passed/result
'not/f2
'(contract (not/f integer?)
'not-integer
'pos
'neg)
'not-integer)
)) ))
(report-errs) (report-errs)