Use filters when typechecking using tc-body.
Closes PR 11920.
This commit is contained in:
parent
4a7dd75ffd
commit
dd8b646b0b
|
@ -5,17 +5,17 @@
|
||||||
racket/match (prefix-in - (contract-req))
|
racket/match (prefix-in - (contract-req))
|
||||||
"signatures.rkt"
|
"signatures.rkt"
|
||||||
"check-below.rkt" "tc-app-helper.rkt" "../types/kw-types.rkt"
|
"check-below.rkt" "tc-app-helper.rkt" "../types/kw-types.rkt"
|
||||||
(types utils abbrev union subtype type-table classes)
|
(types utils abbrev union subtype type-table classes filter-ops)
|
||||||
(private-in parse-type type-annotation syntax-properties)
|
(private-in parse-type type-annotation syntax-properties)
|
||||||
(rep type-rep filter-rep object-rep)
|
(rep type-rep filter-rep object-rep)
|
||||||
(utils tc-utils)
|
(utils tc-utils)
|
||||||
(env lexical-env tvar-env index-env)
|
(env lexical-env tvar-env index-env)
|
||||||
racket/format
|
racket/format racket/list
|
||||||
racket/private/class-internal
|
racket/private/class-internal
|
||||||
syntax/parse syntax/stx
|
syntax/parse syntax/stx
|
||||||
unstable/syntax
|
unstable/syntax
|
||||||
(only-in racket/list split-at)
|
(only-in racket/list split-at)
|
||||||
(typecheck internal-forms)
|
(typecheck internal-forms tc-envops)
|
||||||
;; Needed for current implementation of typechecking letrec-syntax+values
|
;; Needed for current implementation of typechecking letrec-syntax+values
|
||||||
(for-template (only-in racket/base letrec-values))
|
(for-template (only-in racket/base letrec-values))
|
||||||
|
|
||||||
|
@ -519,6 +519,23 @@
|
||||||
#:stx form
|
#:stx form
|
||||||
"expected single value, got multiple (or zero) values")]))
|
"expected single value, got multiple (or zero) values")]))
|
||||||
|
|
||||||
|
|
||||||
|
;; check-body-form: (All (A) (syntax? (-> A) -> A))
|
||||||
|
;; Checks an expression and then calls the function in a context with an extended lexical environment.
|
||||||
|
;; The environment is extended with the propositions that are true if the expression returns
|
||||||
|
;; (e.g. instead of raising an error).
|
||||||
|
(define (check-body-form e k)
|
||||||
|
(define results (tc-expr/check e tc-any-results))
|
||||||
|
(define props
|
||||||
|
(match results
|
||||||
|
[(tc-any-results:) empty]
|
||||||
|
[(tc-results: _ (FilterSet: f+ f-) _)
|
||||||
|
(map -or f+ f-)]
|
||||||
|
[(tc-results: _ (FilterSet: f+ f-) _ _ _)
|
||||||
|
(map -or f+ f-)]))
|
||||||
|
(with-lexical-env (env+ (lexical-env) props (box #t))
|
||||||
|
(add-unconditional-prop (k) (apply -and props))))
|
||||||
|
|
||||||
;; type-check a body of exprs, producing the type of the last one.
|
;; type-check a body of exprs, producing the type of the last one.
|
||||||
;; if the body is empty, the type is Void.
|
;; if the body is empty, the type is Void.
|
||||||
;; syntax[list[expr]] -> tc-results/c
|
;; syntax[list[expr]] -> tc-results/c
|
||||||
|
@ -526,14 +543,18 @@
|
||||||
(match (syntax->list body)
|
(match (syntax->list body)
|
||||||
[(list) (ret -Void)]
|
[(list) (ret -Void)]
|
||||||
[(list es ... e-final)
|
[(list es ... e-final)
|
||||||
(for ((e es))
|
(define ((continue es))
|
||||||
(tc-expr/check e tc-any-results))
|
(if (empty? es)
|
||||||
(tc-expr e-final)]))
|
(tc-expr e-final)
|
||||||
|
(check-body-form (first es) (continue (rest es)))))
|
||||||
|
((continue es))]))
|
||||||
|
|
||||||
(define (tc-body/check body expected)
|
(define (tc-body/check body expected)
|
||||||
(match (syntax->list body)
|
(match (syntax->list body)
|
||||||
[(list) (check-below (ret -Void) expected)]
|
[(list) (check-below (ret -Void) expected)]
|
||||||
[(list es ... e-final)
|
[(list es ... e-final)
|
||||||
(for ((e es))
|
(define ((continue es))
|
||||||
(tc-expr/check e tc-any-results))
|
(if (empty? es)
|
||||||
(tc-expr/check e-final expected)]))
|
(tc-expr/check e-final expected)
|
||||||
|
(check-body-form (first es) (continue (rest es)))))
|
||||||
|
((continue es))]))
|
||||||
|
|
|
@ -207,6 +207,25 @@
|
||||||
[else
|
[else
|
||||||
(loop (cdr fs) (cons t result))])]))))
|
(loop (cdr fs) (cons t result))])]))))
|
||||||
|
|
||||||
|
;; add-unconditional-prop: tc-results? Filter/c? -> tc-results?
|
||||||
|
;; Ands the given proposition to the filters in the tc-results.
|
||||||
|
;; Useful to express properties of the form: if this expressions returns at all, we learn this
|
||||||
|
(define (add-unconditional-prop results prop)
|
||||||
|
(match results
|
||||||
|
;; TODO add support for filters on tc-any-results
|
||||||
|
[(tc-any-results:) results]
|
||||||
|
[(tc-results: ts (FilterSet: fs+ fs-) os)
|
||||||
|
(ret ts
|
||||||
|
(for/list ([f+ fs+] [f- fs-])
|
||||||
|
(-FS (-and prop f+) (-and prop f-)))
|
||||||
|
os)]
|
||||||
|
[(tc-results: ts (FilterSet: fs+ fs-) os dty dbound)
|
||||||
|
(ret ts
|
||||||
|
(for/list ([f+ fs+] [f- fs-])
|
||||||
|
(-FS (-and prop f+) (-and prop f-)))
|
||||||
|
os)]))
|
||||||
|
|
||||||
|
|
||||||
;; ands the given type filter to both sides of the given arr for each argument
|
;; ands the given type filter to both sides of the given arr for each argument
|
||||||
;; useful to express properties of the form: if this function returns at all,
|
;; useful to express properties of the form: if this function returns at all,
|
||||||
;; we learn this about its arguments (like fx primitives, or car/cdr, etc.)
|
;; we learn this about its arguments (like fx primitives, or car/cdr, etc.)
|
||||||
|
|
|
@ -2667,6 +2667,34 @@
|
||||||
(number? x))
|
(number? x))
|
||||||
-Boolean]
|
-Boolean]
|
||||||
|
|
||||||
|
[tc-e
|
||||||
|
(let ()
|
||||||
|
(: g (Any -> Boolean : #:+ (Number @ 0) #:- Bot))
|
||||||
|
(define (g x)
|
||||||
|
(or (number? x)
|
||||||
|
(g x)))
|
||||||
|
(: x Any)
|
||||||
|
(define x 0)
|
||||||
|
(g x)
|
||||||
|
(add1 x))
|
||||||
|
-Number]
|
||||||
|
|
||||||
|
[tc-e
|
||||||
|
(let: ([x : Any 1])
|
||||||
|
(unless (number? x)
|
||||||
|
(error 'foo))
|
||||||
|
(add1 x))
|
||||||
|
-Number]
|
||||||
|
|
||||||
|
[tc-e
|
||||||
|
(let: ([x : Any 1])
|
||||||
|
(let ()
|
||||||
|
(unless (number? x)
|
||||||
|
(error 'foo))
|
||||||
|
#t)
|
||||||
|
(add1 x))
|
||||||
|
-Number]
|
||||||
|
|
||||||
[tc-e/t
|
[tc-e/t
|
||||||
(let ()
|
(let ()
|
||||||
(: f (Number -> Number))
|
(: f (Number -> Number))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user