Made tc/exprs check its non final terms with the correct type.

Closes PR12974.

original commit: 5a43a5c73078b71dbe4d8b170a88b55812dcb383
This commit is contained in:
Eric Dobson 2012-09-03 19:00:08 -07:00 committed by Sam Tobin-Hochstadt
parent 6e55c674d6
commit 378daf06b9
6 changed files with 66 additions and 36 deletions

View File

@ -0,0 +1,18 @@
#lang typed/racket
(define (f)
(let loop ((i 5))
(if (zero? i)
(void)
(loop (sub1 i))))
2)
(let loop ((i 5))
(if (zero? i)
(void)
(loop (sub1 i))))
(define (g)
(values 1 2)
2)

View File

@ -550,11 +550,11 @@
(define (tc-exprs exprs)
(cond [(null? exprs) (ret -Void)]
[(null? (cdr exprs)) (tc-expr (car exprs))]
[else (tc-expr/check/type (car exprs) Univ)
[else (tc-expr/check (car exprs) tc-any-results)
(tc-exprs (cdr exprs))]))
(define (tc-exprs/check exprs expected)
(cond [(null? exprs) (check-below (ret -Void) expected)]
[(null? (cdr exprs)) (tc-expr/check (car exprs) expected)]
[else (tc-expr/check/type (car exprs) Univ)
[else (tc-expr/check (car exprs) tc-any-results)
(tc-exprs/check (cdr exprs) expected)]))

View File

@ -17,6 +17,7 @@
(define (erase-filter tc)
(match tc
[(tc-any-results:) tc]
[(tc-results: ts _ _)
(ret ts (for/list ([f ts]) (make-NoFilter)) (for/list ([f ts]) (make-NoObject)))]))
@ -44,9 +45,11 @@
[new-thn-props (filter (λ (e) (and (atomic-filter? e) (not (memq e (env-props (lexical-env))))))
(env-props env-thn))]
[new-els-props (filter (λ (e) (and (atomic-filter? e) (not (memq e (env-props (lexical-env))))))
(env-props env-els))]
[(tc-results: ts fs2 os2) (with-lexical-env env-thn (tc thn (unbox flag+)))]
[(tc-results: us fs3 os3) (with-lexical-env env-els (tc els (unbox flag-)))])
(env-props env-els))])
(define results-t (with-lexical-env env-thn (tc thn (unbox flag+))))
(define results-u (with-lexical-env env-els (tc els (unbox flag-))))
;(printf "old props: ~a\n" (env-props (lexical-env)))
;(printf "fs+: ~a\n" fs+)
;(printf "fs-: ~a\n" fs-)
@ -72,36 +75,43 @@
(add-tautology tst)]
[else
(add-neither tst)])
;; if we have the same number of values in both cases
(cond [(= (length ts) (length us))
(let ([r (combine-results
(for/list ([f2 fs2] [f3 fs3] [t2 ts] [t3 us] [o2 os2] [o3 os3])
(let ([filter
(match* (f2 f3)
[((NoFilter:) _)
(-FS -top -top)]
[(_ (NoFilter:))
(-FS -top -top)]
[((FilterSet: f2+ f2-) (FilterSet: f3+ f3-))
;(printf "f2- ~a f+ ~a\n" f2- fs+)
(-FS (-or (apply -and fs+ f2+ new-thn-props) (apply -and fs- f3+ new-els-props))
(-or (apply -and fs+ f2- new-thn-props) (apply -and fs- f3- new-els-props)))])]
[type (Un t2 t3)]
[object (if (object-equal? o2 o3) o2 (make-Empty))])
;(printf "result filter is: ~a\n" filter)
(ret type filter object))))])
(cond-check-below r expected))]
;; special case if one of the branches is unreachable
[(and (= 1 (length us)) (type-equal? (car us) (Un)))
(cond-check-below (ret ts fs2 os2) expected)]
[(and (= 1 (length ts)) (type-equal? (car ts) (Un)))
(cond-check-below (ret us fs3 os3) expected)]
;; otherwise, error
(match* (results-t results-u)
[((tc-any-results:) _) (cond-check-below tc-any-results expected)]
[(_ (tc-any-results:)) (cond-check-below tc-any-results expected)]
[((tc-results: ts fs2 os2)
(tc-results: us fs3 os3))
;; if we have the same number of values in both cases
(cond [(= (length ts) (length us))
(let ([r (combine-results
(for/list ([f2 fs2] [f3 fs3] [t2 ts] [t3 us] [o2 os2] [o3 os3])
(let ([filter
(match* (f2 f3)
[((NoFilter:) _)
(-FS -top -top)]
[(_ (NoFilter:))
(-FS -top -top)]
[((FilterSet: f2+ f2-) (FilterSet: f3+ f3-))
;(printf "f2- ~a f+ ~a\n" f2- fs+)
(-FS (-or (apply -and fs+ f2+ new-thn-props) (apply -and fs- f3+ new-els-props))
(-or (apply -and fs+ f2- new-thn-props) (apply -and fs- f3- new-els-props)))])]
[type (Un t2 t3)]
[object (if (object-equal? o2 o3) o2 (make-Empty))])
;(printf "result filter is: ~a\n" filter)
(ret type filter object))))])
(cond-check-below r expected))]
;; special case if one of the branches is unreachable
[(and (= 1 (length us)) (type-equal? (car us) (Un)))
(cond-check-below (ret ts fs2 os2) expected)]
[(and (= 1 (length ts)) (type-equal? (car ts) (Un)))
(cond-check-below (ret us fs3 os3) expected)]
;; otherwise, error
[else
(tc-error/expr #:return (ret (or expected Err))
(tc-error/expr #:return (or expected (ret Err))
"Expected the same number of values from both branches of `if' expression, but got ~a and ~a"
(length ts) (length us))])))]
(length ts) (length us))])])))]
[(tc-any-results:)
(tc-error/expr #:return (or expected (ret Err))
"Test expression expects one value, given unknown amount")]
[(tc-results: t _ _)
(tc-error/expr #:return (ret (or expected Err))
(tc-error/expr #:return (or expected (ret Err))
"Test expression expects one value, given ~a" t)]))

View File

@ -23,12 +23,13 @@
(define (erase-filter tc)
(match tc
[(tc-any-results:) tc]
[(tc-results: ts _ _)
(ret ts (for/list ([f ts]) (make-NoFilter)) (for/list ([f ts]) (make-NoObject)))]))
(define/cond-contract (do-check expr->type namess results expected-results form exprs body clauses expected #:abstract [abstract null])
(((syntax? syntax? tc-results/c . c:-> . any/c)
(listof (listof identifier?)) (listof tc-results/c) (listof tc-results/c)
(listof (listof identifier?)) (listof tc-results?) (listof tc-results?)
syntax? (listof syntax?) syntax? (listof syntax?) (or/c #f tc-results/c))
(#:abstract any/c)
. c:->* .

View File

@ -73,6 +73,7 @@
(define (tc-results->values tc)
(match tc
[(tc-any-results:) ManyUniv]
[(tc-results: ts) (-values ts)]))
(provide combine-props tc-results->values)

View File

@ -255,7 +255,7 @@
(loop (cdr l)))))]
;; otherwise, the form was just an expression
[_ (tc-expr form)])))
[_ (tc-expr/check form tc-any-results)])))