Change tc-app-lambda to not return bad filters.

Makes tc/rec-lambda/check return the actual results, and erase the names of
the values bound by the let.
This commit is contained in:
Eric Dobson 2014-03-19 20:19:25 -07:00
parent 74f8dc7436
commit 8cf1246fb1
5 changed files with 64 additions and 52 deletions

View File

@ -3,6 +3,7 @@
(require "../../utils/utils.rkt" (require "../../utils/utils.rkt"
"signatures.rkt" "signatures.rkt"
"utils.rkt" "utils.rkt"
(prefix-in - (contract-req))
syntax/parse racket/match racket/list syntax/parse racket/match racket/list
unstable/sequence unstable/syntax unstable/sequence unstable/syntax
(typecheck signatures find-annotation) (typecheck signatures find-annotation)
@ -53,7 +54,9 @@
expected))))) expected)))))
(define (let-loop-check lam lp actuals args body expected) (define/cond-contract
(let-loop-check lam lp actuals args body expected)
(syntax? syntax? syntax? syntax? syntax? tc-results/c . --> . tc-results/c)
(syntax-parse #`(#,args #,body #,actuals) (syntax-parse #`(#,args #,body #,actuals)
#:literal-sets (kernel-literals lambda-literals) #:literal-sets (kernel-literals lambda-literals)
[((val acc ...) [((val acc ...)
@ -76,8 +79,10 @@
[t (in-list ann-ts)]) [t (in-list ann-ts)])
(tc-expr/check a (ret t))) (tc-expr/check a (ret t)))
;; then check that the function typechecks with the inferred types ;; then check that the function typechecks with the inferred types
(add-typeof-expr lam (tc/rec-lambda/check args body lp ts expected)) (define-values (fun-results body-results)
expected)] (tc/rec-lambda/check args body lp ts expected))
(add-typeof-expr lam fun-results)
body-results)]
;; special case `for/list' ;; special case `for/list'
[((val acc ...) [((val acc ...)
((~and inner-body (if e1 e2 e3:id))) ((~and inner-body (if e1 e2 e3:id)))
@ -95,8 +100,10 @@
[(tc-result1: (and t (Listof: _))) t] [(tc-result1: (and t (Listof: _))) t]
[_ #f]) [_ #f])
(generalize (-val '())))]) (generalize (-val '())))])
(add-typeof-expr lam (tc/rec-lambda/check args body lp (cons acc-ty ts) expected)) (define-values (fun-results body-results)
expected)] (tc/rec-lambda/check args body lp (cons acc-ty ts) expected))
(add-typeof-expr lam fun-results)
body-results)]
;; special case when argument needs inference ;; special case when argument needs inference
[(_ body* _) [(_ body* _)
(let ([ts (for/list ([ac (in-syntax actuals)] (let ([ts (for/list ([ac (in-syntax actuals)]
@ -106,6 +113,8 @@
(if infer-t (if infer-t
(tc-expr/check/t ac (ret infer-t)) (tc-expr/check/t ac (ret infer-t))
(generalize (tc-expr/t ac)))))]) (generalize (tc-expr/t ac)))))])
(add-typeof-expr lam (tc/rec-lambda/check args body lp ts expected)) (define-values (fun-results body-results)
expected)])) (tc/rec-lambda/check args body lp ts expected))
(add-typeof-expr lam fun-results)
body-results)]))

View File

@ -520,12 +520,16 @@
;; name : the name of the loop ;; name : the name of the loop
;; args : the types of the actual arguments to the loop ;; args : the types of the actual arguments to the loop
;; ret : the expected return type of the whole expression ;; ret : the expected return type of the whole expression
(define (tc/rec-lambda/check formals body name args return) ;; Returns both the tc-results of the function and of the body
(define (tc/rec-lambda/check formals* body name args return)
(define formals (syntax->list formals*))
(with-lexical-env/extend (with-lexical-env/extend
(syntax->list formals) args formals args
(let* ([r (tc-results->values return)] (let* ([r (tc-results->values return)]
[t (make-arr args r)] [t (make-arr args r)]
[ft (make-Function (list t))]) [ft (make-Function (list t))])
(with-lexical-env/extend (with-lexical-env/extend
(list name) (list ft) (list name) (list ft)
(begin (tc-body/check body return) (ret ft)))))) (values
(erase-names/results formals (ret ft))
(erase-names/results formals (tc-body/check body return)))))))

View File

@ -8,7 +8,7 @@
global-env type-env-structs scoped-tvar-env) global-env type-env-structs scoped-tvar-env)
(rep type-rep filter-rep) (rep type-rep filter-rep)
syntax/free-vars syntax/free-vars
(typecheck signatures tc-metafunctions tc-subst internal-forms) (typecheck signatures tc-metafunctions internal-forms)
(utils tarjan) (utils tarjan)
racket/match (contract-req) racket/match (contract-req)
syntax/parse syntax/stx syntax/parse syntax/stx
@ -64,18 +64,6 @@
clauses clauses
exprs exprs
expected-results) expected-results)
(let ([subber (lambda (proc lst)
(for/list ([i (in-list lst)])
(for/fold ([s i])
([nm (in-list (apply append abstract namess))])
(proc s nm -empty-obj #t))))])
(define (run res)
(match res
[(tc-any-results:) res]
[(tc-results: ts fs os)
(ret (subber subst-type ts) (subber subst-filter-set fs) (subber subst-object os))]
[(tc-results: ts fs os dt db)
(ret (subber subst-type ts) (subber subst-filter-set fs) (subber subst-object os) dt db)]))
(with-lexical-env/extend/props (with-lexical-env/extend/props
;; we typechecked the rhss with the lhss having types that potentially contain undefined ;; we typechecked the rhss with the lhss having types that potentially contain undefined
;; if undefined can actually show up, a type error will have been triggered ;; if undefined can actually show up, a type error will have been triggered
@ -85,10 +73,10 @@
expected-types ; types w/o undefined expected-types ; types w/o undefined
(append p1 p2) (append p1 p2)
;; typecheck the body ;; typecheck the body
(run (erase-names/results (apply append abstract namess)
(if expected (if expected
(tc-body/check body (erase-filter expected)) (tc-body/check body (erase-filter expected))
(tc-body body))))))) (tc-body body))))))
(define (tc-expr/maybe-expected/t e names) (define (tc-expr/maybe-expected/t e names)
(syntax-parse names (syntax-parse names

View File

@ -5,9 +5,11 @@
(except-in (types abbrev union utils filter-ops) (except-in (types abbrev union utils filter-ops)
-> ->* one-of/c) -> ->* one-of/c)
(rep type-rep filter-rep object-rep rep-utils) (rep type-rep filter-rep object-rep rep-utils)
(typecheck tc-subst)
(contract-req)) (contract-req))
(provide abstract-results (provide abstract-results
erase-names/results
combine-props combine-props
tc-results->values) tc-results->values)
@ -100,20 +102,13 @@
;; the scope count in the keys so that names are ;; the scope count in the keys so that names are
;; substituted with the correct level of nesting ;; substituted with the correct level of nesting
(λ (type) (λ (type)
(abstract-type ids (add-scope keys) type))]) (abstract-type ids (map add-scope keys) type))])
(make-arr (map at dom) (make-arr (map at dom)
(at* rng) ; only increase scope in range (at* rng) ; only increase scope in range
(and rest (at rest)) (and rest (at rest))
(and drest (cons (at (car drest)) (cdr drest))) (and drest (cons (at (car drest)) (cdr drest)))
(map at kws)))])) (map at kws)))]))
;; add-scope : Listof<name-ref/c> -> Listof<name-ref/c>
;; Add a scope to the index object
(define (add-scope keys)
(for/list ([depth+arg keys])
(match-define (list depth arg) depth+arg)
(list (+ 1 depth) arg)))
;; Abstract all given id objects into index objects (keys) in ;; Abstract all given id objects into index objects (keys) in
;; the given object ;; the given object
(define/cond-contract (abstract-object ids keys o) (define/cond-contract (abstract-object ids keys o)
@ -246,3 +241,19 @@
[(Bot:) (set-box! flag #f) (values derived-props derived-atoms)] [(Bot:) (set-box! flag #f) (values derived-props derived-atoms)]
[_ (loop (cons p derived-props) derived-atoms (cdr worklist))]))))) [_ (loop (cons p derived-props) derived-atoms (cdr worklist))])))))
;; erase-names/results: (listof identifier?) tc-results? -> tc-results?
;; Maps all of the given names in the results to the empty object.
;; This is used so that names do not escape the scope of their definitions
;; TODO support mapping names to other objects.
(define (erase-names/results names res)
(define (subber proc lst)
(for/list ([i (in-list lst)])
(for/fold ([s i])
([nm (in-list names)])
(proc s nm -empty-obj #t))))
(match res
[(tc-any-results:) res]
[(tc-results: ts fs os)
(ret (subber subst-type ts) (subber subst-filter-set fs) (subber subst-object os))]
[(tc-results: ts fs os dt db)
(ret (subber subst-type ts) (subber subst-filter-set fs) (subber subst-object os) dt db)]))

View File

@ -933,7 +933,7 @@
(do: : Number ((x : (Listof Number) x (cdr x)) (do: : Number ((x : (Listof Number) x (cdr x))
(sum : Number 0 (+ sum (car x)))) (sum : Number 0 (+ sum (car x))))
((null? x) sum))) ((null? x) sum)))
#:ret (ret -Number -top-filter -no-obj)] #:ret (ret -Number -top-filter -empty-obj)]
[tc-e/t (if #f 1 'foo) (-val 'foo)] [tc-e/t (if #f 1 'foo) (-val 'foo)]
@ -1179,7 +1179,7 @@
([j : Natural (+ i 'a) (+ j i)]) ([j : Natural (+ i 'a) (+ j i)])
((>= j 10)) ((>= j 10))
#f) #f)
#:ret (ret -Void -no-filter -no-obj)] #:ret (ret -Void -top-filter -empty-obj)]
[tc-err (apply +)] [tc-err (apply +)]
[tc-e/t [tc-e/t
(let ([x eof]) (let ([x eof])
@ -1748,7 +1748,7 @@
[tc-e (let ([my-pred (λ () #f)]) [tc-e (let ([my-pred (λ () #f)])
(for/and: : Any ([i (in-range 4)]) (for/and: : Any ([i (in-range 4)])
(my-pred))) (my-pred)))
#:ret (ret Univ -top-filter -no-obj)] #:ret (ret Univ -top-filter -empty-obj)]
[tc-e [tc-e
(let () (let ()
(define: long : (List 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Integer) (define: long : (List 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Integer)
@ -1864,7 +1864,7 @@
(ann (ann
((letrec ((x (lambda (acc #{ v : Symbol}) (if v (list v) acc)))) x) null (list 'bad 'prog)) ((letrec ((x (lambda (acc #{ v : Symbol}) (if v (list v) acc)))) x) null (list 'bad 'prog))
(Listof Symbol)) (Listof Symbol))
#:ret (ret (-lst -Symbol) -no-filter -no-obj)] #:ret (ret (-lst -Symbol) -top-filter -empty-obj)]
[tc-e (filter values empty) [tc-e (filter values empty)
(-lst -Bottom)] (-lst -Bottom)]
[tc-e (lambda lst (map (plambda: (b) ([x : b]) x) lst)) [tc-e (lambda lst (map (plambda: (b) ([x : b]) x) lst))
@ -2150,7 +2150,7 @@
(values x y)) (values x y))
#:ret (ret (-HT -Symbol -String) #:ret (ret (-HT -Symbol -String)
(-FS -top -top) (-FS -top -top)
-no-obj)] -empty-obj)]
[tc-e (for*/hash: : (HashTable Symbol String) [tc-e (for*/hash: : (HashTable Symbol String)
([k (in-list '(x y z))] ([k (in-list '(x y z))]
[v (in-list '("a" "b"))] [v (in-list '("a" "b"))]
@ -2158,7 +2158,7 @@
(values k v)) (values k v))
#:ret (ret (-HT -Symbol -String) #:ret (ret (-HT -Symbol -String)
(-FS -top -top) (-FS -top -top)
-no-obj)] -empty-obj)]
;; PR 13937 ;; PR 13937
[tc-e (let () [tc-e (let ()
@ -2399,9 +2399,9 @@
[tc-e (let/ec k : String (k "foo")) -String] [tc-e (let/ec k : String (k "foo")) -String]
[tc-e (ann (do ([x : Integer 0 (add1 x)]) ((> x 10) x) (displayln x)) [tc-e (ann (do ([x : Integer 0 (add1 x)]) ((> x 10) x) (displayln x))
Integer) Integer)
#:ret (ret -Integer -no-filter -no-obj)] #:ret (ret -Integer -top-filter -empty-obj)]
[tc-e (do : Integer ([x : Integer 0 (add1 x)]) ((> x 10) x) (displayln x)) [tc-e (do : Integer ([x : Integer 0 (add1 x)]) ((> x 10) x) (displayln x))
#:ret (ret -Integer -no-filter -no-obj)] #:ret (ret -Integer -top-filter -empty-obj)]
[tc-e (tr:case-lambda [(x [y : String]) x]) [tc-e (tr:case-lambda [(x [y : String]) x])
#:ret (ret (t:-> Univ -String Univ #:ret (ret (t:-> Univ -String Univ
: (-FS (-not-filter (-val #f) (list 0 0)) : (-FS (-not-filter (-val #f) (list 0 0))