Make with-lexical-env/extend-props not execute its body if its dead.
This commit is contained in:
parent
e8c14839e1
commit
203311e993
|
@ -8,7 +8,7 @@
|
||||||
(infer-in infer)
|
(infer-in infer)
|
||||||
(rep type-rep filter-rep object-rep rep-utils)
|
(rep type-rep filter-rep object-rep rep-utils)
|
||||||
(utils tc-utils)
|
(utils tc-utils)
|
||||||
(types resolve subtype remove-intersect union filter-ops)
|
(types tc-result resolve subtype remove-intersect union filter-ops)
|
||||||
(env type-env-structs lexical-env)
|
(env type-env-structs lexical-env)
|
||||||
(rename-in (types abbrev)
|
(rename-in (types abbrev)
|
||||||
[-> -->]
|
[-> -->]
|
||||||
|
@ -18,9 +18,6 @@
|
||||||
|
|
||||||
(provide
|
(provide
|
||||||
with-lexical-env/extend-props)
|
with-lexical-env/extend-props)
|
||||||
(provide/cond-contract
|
|
||||||
[env+ (([e env?] [fs (listof Filter/c)] [bx (box/c boolean?)])
|
|
||||||
#:pre (bx) (unbox bx) . ->i . [_ env?])])
|
|
||||||
|
|
||||||
(define/cond-contract (update t ft pos? lo)
|
(define/cond-contract (update t ft pos? lo)
|
||||||
(Type/c Type/c boolean? (listof PathElem?) . -> . Type/c)
|
(Type/c Type/c boolean? (listof PathElem?) . -> . Type/c)
|
||||||
|
@ -63,29 +60,35 @@
|
||||||
(int-err "update along ill-typed path: ~a ~a ~a" t t* lo)
|
(int-err "update along ill-typed path: ~a ~a ~a" t t* lo)
|
||||||
t]))
|
t]))
|
||||||
|
|
||||||
;; sets the flag box to #f if anything becomes (U)
|
;; Returns #f if anything becomes (U)
|
||||||
(define (env+ env fs flag)
|
(define (env+ env fs)
|
||||||
(define-values (props atoms) (combine-props fs (env-props env) flag))
|
(let/ec exit
|
||||||
(for/fold ([Γ (replace-props env (append atoms props))]) ([f (in-list atoms)])
|
(define-values (props atoms) (combine-props fs (env-props env) exit))
|
||||||
(match f
|
(for/fold ([Γ (replace-props env (append atoms props))]) ([f (in-list atoms)])
|
||||||
[(Bot:) (set-box! flag #f) (env-map (lambda (k v) (Un)) Γ)]
|
(match f
|
||||||
[(or (TypeFilter: ft (Path: lo x)) (NotTypeFilter: ft (Path: lo x)))
|
[(or (TypeFilter: ft (Path: lo x)) (NotTypeFilter: ft (Path: lo x)))
|
||||||
(update-type/lexical
|
(update-type/lexical
|
||||||
(lambda (x t) (let ([new-t (update t ft (TypeFilter? f) lo)])
|
(lambda (x t)
|
||||||
(when (type-equal? new-t -Bottom)
|
(define new-t (update t ft (TypeFilter? f) lo))
|
||||||
(set-box! flag #f))
|
(when (type-equal? new-t -Bottom)
|
||||||
new-t))
|
(exit #f))
|
||||||
x Γ)]
|
new-t)
|
||||||
[_ Γ])))
|
x Γ)]
|
||||||
|
[_ Γ]))))
|
||||||
|
|
||||||
;; run code in an extended env and with replaced props. Requires the body to return a tc-results.
|
;; run code in an extended env and with replaced props. Requires the body to return a tc-results.
|
||||||
;; TODO make this only add the new prop instead of the entire environment once tc-id is fixed to
|
;; TODO make this only add the new prop instead of the entire environment once tc-id is fixed to
|
||||||
;; include the interesting props in its filter.
|
;; include the interesting props in its filter.
|
||||||
(define-syntax (with-lexical-env/extend-props stx)
|
(define-syntax (with-lexical-env/extend-props stx)
|
||||||
(define-splicing-syntax-class flag
|
(define-splicing-syntax-class unreachable?
|
||||||
[pattern (~seq #:flag v:expr)]
|
(pattern (~seq #:unreachable form:expr))
|
||||||
[pattern (~seq) #:with v #'(box #t)])
|
(pattern (~seq) #:with form #'(begin)))
|
||||||
(syntax-parse stx
|
(syntax-parse stx
|
||||||
[(_ ps flag:flag . b)
|
[(_ ps:expr u:unreachable? . b)
|
||||||
#'(with-lexical-env (env+ (lexical-env) ps flag.v)
|
#'(let ([new-env (env+ (lexical-env) ps)])
|
||||||
(add-unconditional-prop (let () . b) (apply -and (env-props (lexical-env)))))]))
|
(if new-env
|
||||||
|
(with-lexical-env new-env
|
||||||
|
(add-unconditional-prop (let () . b) (apply -and (env-props new-env))))
|
||||||
|
(let ()
|
||||||
|
u.form
|
||||||
|
(ret -Bottom))))]))
|
||||||
|
|
|
@ -13,28 +13,18 @@
|
||||||
(export tc-if^)
|
(export tc-if^)
|
||||||
|
|
||||||
(define (tc/if-twoarm tst thn els [expected #f])
|
(define (tc/if-twoarm tst thn els [expected #f])
|
||||||
(define (tc expr reachable?)
|
|
||||||
(unless reachable? (warn-unreachable expr))
|
|
||||||
;; If the code is unreachable, the resulting type should be Bottom.
|
|
||||||
(if reachable?
|
|
||||||
(tc-expr/check expr (and expected (erase-filter expected)))
|
|
||||||
(ret -Bottom)))
|
|
||||||
(match (single-value tst)
|
(match (single-value tst)
|
||||||
[(tc-result1: _ (and f1 (FilterSet: fs+ fs-)) _)
|
[(tc-result1: _ (FilterSet: fs+ fs-) _)
|
||||||
(define flag+ (box #t))
|
(define expected* (and expected (erase-filter expected)))
|
||||||
(define flag- (box #t))
|
|
||||||
(define results-t
|
(define results-t
|
||||||
(with-lexical-env/extend-props (list fs+) #:flag flag+
|
(with-lexical-env/extend-props (list fs+)
|
||||||
(add-unconditional-prop
|
#:unreachable (warn-unreachable thn)
|
||||||
(tc thn (unbox flag+)) fs+)))
|
(test-position-add-true tst)
|
||||||
|
(tc-expr/check thn expected*)))
|
||||||
(define results-u
|
(define results-u
|
||||||
(with-lexical-env/extend-props (list fs-) #:flag flag-
|
(with-lexical-env/extend-props (list fs-)
|
||||||
(add-unconditional-prop
|
#:unreachable (warn-unreachable els)
|
||||||
(tc els (unbox flag-)) fs-)))
|
(test-position-add-false tst)
|
||||||
|
(tc-expr/check els expected*)))
|
||||||
|
|
||||||
;; record reachability
|
|
||||||
(when (unbox flag+)
|
|
||||||
(test-position-add-true tst))
|
|
||||||
(when (unbox flag-)
|
|
||||||
(test-position-add-false tst))
|
|
||||||
(merge-tc-results (list results-t results-u))]))
|
(merge-tc-results (list results-t results-u))]))
|
||||||
|
|
|
@ -55,8 +55,8 @@
|
||||||
[(cons (AndFilter: ps*) ps) (loop (append ps* ps))]
|
[(cons (AndFilter: ps*) ps) (loop (append ps* ps))]
|
||||||
[(cons p ps) (cons p (loop ps))])))
|
[(cons p ps) (cons p (loop ps))])))
|
||||||
|
|
||||||
(define/cond-contract (combine-props new-props old-props flag)
|
(define/cond-contract (combine-props new-props old-props exit)
|
||||||
((listof Filter/c) (listof Filter/c) (box/c boolean?)
|
((listof Filter/c) (listof Filter/c) (-> #f none/c)
|
||||||
. -> .
|
. -> .
|
||||||
(values (listof (or/c ImpFilter? OrFilter?)) (listof (or/c TypeFilter? NotTypeFilter?))))
|
(values (listof (or/c ImpFilter? OrFilter?)) (listof (or/c TypeFilter? NotTypeFilter?))))
|
||||||
(define (atomic-prop? p) (or (TypeFilter? p) (NotTypeFilter? p)))
|
(define (atomic-prop? p) (or (TypeFilter? p) (NotTypeFilter? p)))
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
|
|
||||||
[(AndFilter: ps) (loop derived-formulas derived-atoms (append ps (cdr worklist)))]
|
[(AndFilter: ps) (loop derived-formulas derived-atoms (append ps (cdr worklist)))]
|
||||||
[(Top:) (loop derived-formulas derived-atoms (cdr worklist))]
|
[(Top:) (loop derived-formulas derived-atoms (cdr worklist))]
|
||||||
[(Bot:) (set-box! flag #f) (values derived-formulas derived-atoms)])))))
|
[(Bot:) (exit #f)])))))
|
||||||
|
|
||||||
|
|
||||||
(define (unconditional-prop res)
|
(define (unconditional-prop res)
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
[(_ new:expr existing:expr expected:expr box-v:expr)
|
[(_ new:expr existing:expr expected:expr box-v:expr)
|
||||||
(quasisyntax/loc stx
|
(quasisyntax/loc stx
|
||||||
(test-case (~a '(new + existing = expected))
|
(test-case (~a '(new + existing = expected))
|
||||||
(define b (box #t))
|
(define success
|
||||||
(define-values (res-formulas res-props) (combine-props new existing b))
|
(let/ec exit
|
||||||
#,(syntax/loc stx (check-equal? (append res-formulas res-props) expected))
|
(define-values (res-formulas res-props) (combine-props new existing exit))
|
||||||
#,(syntax/loc stx (check-equal? (unbox b) box-v))))]))
|
#,(syntax/loc stx (check-equal? (append res-formulas res-props) expected))
|
||||||
|
#t))
|
||||||
|
#,(syntax/loc stx (check-equal? success box-v))))]))
|
||||||
|
|
||||||
|
|
||||||
(define tests
|
(define tests
|
||||||
|
|
Loading…
Reference in New Issue
Block a user