Make with-lexical-env/extend-props not execute its body if its dead.

This commit is contained in:
Eric Dobson 2014-05-24 14:55:07 -07:00
parent e8c14839e1
commit 203311e993
4 changed files with 46 additions and 51 deletions

View File

@ -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))))]))

View File

@ -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))]))

View File

@ -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)

View File

@ -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