make contract-stronger? recognize that predicates are stronger than
values that they accept (for certain, well-known predicates, anyway)
This commit is contained in:
parent
cd4dde5865
commit
ae298ae353
|
@ -128,6 +128,20 @@
|
||||||
(define x (flat-rec-contract x (or/c (cons/c x '()) '())))
|
(define x (flat-rec-contract x (or/c (cons/c x '()) '())))
|
||||||
(,test #t contract-stronger? x (or/c (cons/c x '()) '()))))
|
(,test #t contract-stronger? x (or/c (cons/c x '()) '()))))
|
||||||
|
|
||||||
|
(ctest #t contract-stronger? "x" string?)
|
||||||
|
(ctest #f contract-stronger? string? "x")
|
||||||
|
|
||||||
|
(ctest #t contract-stronger? 1 real?)
|
||||||
|
(ctest #f contract-stronger? real? 1)
|
||||||
|
|
||||||
|
(ctest #t contract-stronger? 'x symbol?)
|
||||||
|
(ctest #f contract-stronger? symbol? 'x)
|
||||||
|
|
||||||
|
;; chances are, this predicate will accept "x", but
|
||||||
|
;; we don't want to consider it stronger, since it
|
||||||
|
;; will not always accept "x".
|
||||||
|
(ctest #f contract-stronger? "x" (λ (x) (not (zero? (random 10000)))))
|
||||||
|
|
||||||
(contract-eval
|
(contract-eval
|
||||||
`(let ()
|
`(let ()
|
||||||
(define (non-zero? x) (not (zero? x)))
|
(define (non-zero? x) (not (zero? x)))
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
"prop.rkt"
|
"prop.rkt"
|
||||||
"rand.rkt"
|
"rand.rkt"
|
||||||
"generate-base.rkt"
|
"generate-base.rkt"
|
||||||
racket/pretty)
|
racket/pretty
|
||||||
|
(for-syntax racket/base
|
||||||
(require (for-syntax racket/base))
|
"helpers.rkt"))
|
||||||
|
|
||||||
(provide coerce-contract
|
(provide coerce-contract
|
||||||
coerce-contracts
|
coerce-contracts
|
||||||
|
@ -151,7 +151,7 @@
|
||||||
"contract?"
|
"contract?"
|
||||||
x)))
|
x)))
|
||||||
|
|
||||||
;; coerce-contracts : symbols (listof any) -> (listof contract)
|
;; coerce-contracts : symbol (listof any) -> (listof contract)
|
||||||
;; turns all of the arguments in 'xs' into contracts
|
;; turns all of the arguments in 'xs' into contracts
|
||||||
;; the error messages assume that the function named by 'name'
|
;; the error messages assume that the function named by 'name'
|
||||||
;; got 'xs' as it argument directly
|
;; got 'xs' as it argument directly
|
||||||
|
@ -173,13 +173,20 @@
|
||||||
(cond
|
(cond
|
||||||
[(contract-struct? x) x]
|
[(contract-struct? x) x]
|
||||||
[(and (procedure? x) (procedure-arity-includes? x 1))
|
[(and (procedure? x) (procedure-arity-includes? x 1))
|
||||||
(make-predicate-contract (or (object-name x) '???) x #f)]
|
(make-predicate-contract (or (object-name x) '???)
|
||||||
|
x
|
||||||
|
#f
|
||||||
|
(memq x the-known-good-contracts))]
|
||||||
[(or (symbol? x) (boolean? x) (char? x) (null? x) (keyword? x)) (make-eq-contract x)]
|
[(or (symbol? x) (boolean? x) (char? x) (null? x) (keyword? x)) (make-eq-contract x)]
|
||||||
[(or (bytes? x) (string? x)) (make-equal-contract x)]
|
[(or (bytes? x) (string? x)) (make-equal-contract x)]
|
||||||
[(number? x) (make-=-contract x)]
|
[(number? x) (make-=-contract x)]
|
||||||
[(or (regexp? x) (byte-regexp? x)) (make-regexp/c x)]
|
[(or (regexp? x) (byte-regexp? x)) (make-regexp/c x)]
|
||||||
[else #f]))
|
[else #f]))
|
||||||
|
|
||||||
|
(define the-known-good-contracts
|
||||||
|
(let-syntax ([m (λ (x) #`(list #,@(known-good-contracts)))])
|
||||||
|
(m)))
|
||||||
|
|
||||||
(struct wrapped-extra-arg-arrow (real-func extra-neg-party-argument)
|
(struct wrapped-extra-arg-arrow (real-func extra-neg-party-argument)
|
||||||
#:property prop:procedure 0)
|
#:property prop:procedure 0)
|
||||||
|
|
||||||
|
@ -300,8 +307,12 @@
|
||||||
(λ (fuel) (λ () v)))
|
(λ (fuel) (λ () v)))
|
||||||
#:stronger
|
#:stronger
|
||||||
(λ (this that)
|
(λ (this that)
|
||||||
(and (eq-contract? that)
|
(define this-val (eq-contract-val this))
|
||||||
(eq? (eq-contract-val this) (eq-contract-val that))))))
|
(or (and (eq-contract? that)
|
||||||
|
(eq? this-val (eq-contract-val that)))
|
||||||
|
(and (predicate-contract? that)
|
||||||
|
(predicate-contract-sane? that)
|
||||||
|
((predicate-contract-pred that) this-val))))))
|
||||||
|
|
||||||
(define-struct equal-contract (val)
|
(define-struct equal-contract (val)
|
||||||
#:property prop:custom-write custom-write-property-proc
|
#:property prop:custom-write custom-write-property-proc
|
||||||
|
@ -311,8 +322,12 @@
|
||||||
#:name (λ (ctc) (equal-contract-val ctc))
|
#:name (λ (ctc) (equal-contract-val ctc))
|
||||||
#:stronger
|
#:stronger
|
||||||
(λ (this that)
|
(λ (this that)
|
||||||
(and (equal-contract? that)
|
(define this-val (equal-contract-val this))
|
||||||
(equal? (equal-contract-val this) (equal-contract-val that))))
|
(or (and (equal-contract? that)
|
||||||
|
(equal? this-val (equal-contract-val that)))
|
||||||
|
(and (predicate-contract? that)
|
||||||
|
(predicate-contract-sane? that)
|
||||||
|
((predicate-contract-pred that) this-val))))
|
||||||
#:generate
|
#:generate
|
||||||
(λ (ctc)
|
(λ (ctc)
|
||||||
(define v (equal-contract-val ctc))
|
(define v (equal-contract-val ctc))
|
||||||
|
@ -326,8 +341,12 @@
|
||||||
#:name (λ (ctc) (=-contract-val ctc))
|
#:name (λ (ctc) (=-contract-val ctc))
|
||||||
#:stronger
|
#:stronger
|
||||||
(λ (this that)
|
(λ (this that)
|
||||||
(and (=-contract? that)
|
(define this-val (=-contract-val this))
|
||||||
(= (=-contract-val this) (=-contract-val that))))
|
(or (and (=-contract? that)
|
||||||
|
(= this-val (=-contract-val that)))
|
||||||
|
(and (predicate-contract? that)
|
||||||
|
(predicate-contract-sane? that)
|
||||||
|
((predicate-contract-pred that) this-val))))
|
||||||
#:generate
|
#:generate
|
||||||
(λ (ctc)
|
(λ (ctc)
|
||||||
(define v (=-contract-val ctc))
|
(define v (=-contract-val ctc))
|
||||||
|
@ -349,7 +368,9 @@
|
||||||
(and (regexp/c? that) (eq? (regexp/c-reg this) (regexp/c-reg that))))))
|
(and (regexp/c? that) (eq? (regexp/c-reg this) (regexp/c-reg that))))))
|
||||||
|
|
||||||
|
|
||||||
(define-struct predicate-contract (name pred generate)
|
;; sane? : boolean -- indicates if we know that the predicate is well behaved
|
||||||
|
;; (for now, basically amounts to trusting primitive procedures)
|
||||||
|
(define-struct predicate-contract (name pred generate sane?)
|
||||||
#:property prop:custom-write custom-write-property-proc
|
#:property prop:custom-write custom-write-property-proc
|
||||||
#:property prop:flat-contract
|
#:property prop:flat-contract
|
||||||
(build-flat-contract-property
|
(build-flat-contract-property
|
||||||
|
@ -391,7 +412,7 @@
|
||||||
(define (check-flat-named-contract predicate) (coerce-flat-contract 'flat-named-contract predicate))
|
(define (check-flat-named-contract predicate) (coerce-flat-contract 'flat-named-contract predicate))
|
||||||
(define (check-flat-contract predicate) (coerce-flat-contract 'flat-contract predicate))
|
(define (check-flat-contract predicate) (coerce-flat-contract 'flat-contract predicate))
|
||||||
(define (build-flat-contract name pred [generate #f])
|
(define (build-flat-contract name pred [generate #f])
|
||||||
(make-predicate-contract name pred generate))
|
(make-predicate-contract name pred generate #f))
|
||||||
|
|
||||||
|
|
||||||
;; Key used by the continuation mark that holds blame information for the current contract.
|
;; Key used by the continuation mark that holds blame information for the current contract.
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
add-name-prop
|
add-name-prop
|
||||||
all-but-last
|
all-but-last
|
||||||
known-good-contract?
|
known-good-contract?
|
||||||
|
known-good-contracts
|
||||||
update-loc)
|
update-loc)
|
||||||
|
|
||||||
(require setup/main-collects
|
(require setup/main-collects
|
||||||
|
@ -370,3 +371,7 @@
|
||||||
(and (symbol? r-id)
|
(and (symbol? r-id)
|
||||||
(hash-ref known-good-syms-ht r-id #f)
|
(hash-ref known-good-syms-ht r-id #f)
|
||||||
(free-identifier=? id (datum->syntax #'here r-id))))
|
(free-identifier=? id (datum->syntax #'here r-id))))
|
||||||
|
|
||||||
|
(define (known-good-contracts)
|
||||||
|
(for/list ([(k v) (in-hash known-good-syms-ht)])
|
||||||
|
(datum->syntax #'here k)))
|
||||||
|
|
|
@ -1447,9 +1447,9 @@
|
||||||
(cond
|
(cond
|
||||||
[(and (procedure? predicate)
|
[(and (procedure? predicate)
|
||||||
(procedure-arity-includes? predicate 1))
|
(procedure-arity-includes? predicate 1))
|
||||||
(make-predicate-contract name predicate generate)]
|
(make-predicate-contract name predicate generate #f)]
|
||||||
[(flat-contract? predicate)
|
[(flat-contract? predicate)
|
||||||
(make-predicate-contract name (flat-contract-predicate predicate) generate)]
|
(make-predicate-contract name (flat-contract-predicate predicate) generate #f)]
|
||||||
[else
|
[else
|
||||||
(raise-argument-error 'flat-named-contract
|
(raise-argument-error 'flat-named-contract
|
||||||
(format "~s" `(or/c flat-contract?
|
(format "~s" `(or/c flat-contract?
|
||||||
|
|
Loading…
Reference in New Issue
Block a user