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:
parent
74f8dc7436
commit
8cf1246fb1
|
@ -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)]))
|
||||||
|
|
||||||
|
|
|
@ -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)))))))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)]))
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user