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

View File

@ -881,6 +881,22 @@
(send (make-object d%) m 100))
"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)