Fix new inference algorithm to handle all test cases.

svn: r9538
This commit is contained in:
Sam Tobin-Hochstadt 2008-04-29 21:42:37 +00:00
parent ab81b1d64f
commit 8307bf835b
3 changed files with 59 additions and 34 deletions

View File

@ -139,6 +139,15 @@
(singleton (Un) v (var-demote S V))]
[(S (F: (? (lambda (e) (memq e X)) v)))
(singleton (var-promote S V) v Univ)]
[((Struct: nm p flds proc) (Struct: nm p flds* proc*))
(let-values ([(flds flds*)
(cond [(and proc proc*)
(values (cons proc flds) (cons proc* flds*))]
[(or proc proc*)
(fail! S T)]
[else (values flds flds*)])])
(cset-meet* X (for/list ([f flds] [f* flds*])
(cgen V X f f*))))]
[((Pair: a b) (Pair: a* b*))
(cset-meet (cgen V X a a*) (cgen V X b b*))]
;; if we have two mu's, we rename them to have the same variable
@ -148,6 +157,14 @@
;; other mu's just get unfolded
[(s (? Mu? t)) (cgen V X s (unfold t))]
[((? Mu? s) t) (cgen V X (unfold s) t)]
;; type application
[((App: (Name: n) args _)
(App: (Name: n*) args* _))
(unless (free-identifier=? n n*)
(fail! S T))
(cset-meet* X (for/list ([a args] [a* args*]) (cgen V X a a*)))]
[((Vector: e) (Vector: e*))
(cset-meet (cgen V X e e*) (cgen V X e* e))]
[((Function: (list t-arr ...))
(Function: (list s-arr ...)))
(=> unmatch)
@ -173,9 +190,10 @@
[ret-mapping (cgen V X t s)])
(loop (cdr t-arr) (cdr s-arr)
(cset-meet* X (list cset arg-mapping ret-mapping))))])]))]
[(_ _) (cond [(subtype S T) empty]
;; or, nothing worked, and we fail
[else (fail! S T)])])))
[(_ _)
(cond [(subtype S T) empty]
;; or, nothing worked, and we fail
[else (fail! S T)])])))
(define (subst-gen C R)
(for/list ([(k v) (cset-map C)])
@ -189,23 +207,27 @@
[Covariant S]
[Contravariant T]
[Invariant (unless (type-equal? S T)
(error "invariant and not equal"))
(fail! S T))
S])))])))
;; X : variables to infer
;; S : actual argument types
;; T : formal argument types
;; R : result type
;; R : result type or #f
;; returns a substitution
;; if R is #f, we don't care about the substituion
;; just return a boolean result
(define (infer X S T R)
(with-handlers ([exn:infer? (lambda _ #f)])
(subst-gen (cset-meet* X (for/list ([s S] [t T]) (cgen null X s t))) R)))
(let ([cs (cset-meet* X (for/list ([s S] [t T]) (cgen null X s t)))])
(if R
(subst-gen cs R)
#t))))
;; like infer, but T-var is the vararg type:
(define (infer/vararg X S T T-var R)
(define new-T (extend S T T-var))
(if (>= (length S) (length T))
#f ;; fail
(infer X S new-T R)))
(and ((length S) . >= . (length T))
(infer X S new-T R)))
;; Listof[A] Listof[B] B -> Listof[B]
;; pads out t to be as long as s
@ -215,7 +237,7 @@
(define (infer/simple S T R)
(infer (fv/list T) S T R))
;(trace var-demote)
;(trace infer #;cgen #;cset-meet*)
;(trace cgen)

View File

@ -187,7 +187,7 @@
[else (cons (car l) (cons v (intersperse v (cdr l))))]))
(apply string-append (intersperse between (map (lambda (s) (format "~a" s)) l))))
(define (tc/funapp f-stx args-stx ftype0 argtys)
(define (tc/funapp f-stx args-stx ftype0 argtys expected)
(match-let* ([(list (tc-result: argtypes arg-thn-effs arg-els-effs) ...) argtys])
(let outer-loop ([ftype ftype0]
[argtypes argtypes]
@ -252,16 +252,17 @@
(stringify (map stringify msg-doms) "\n") (stringify argtypes))))]
[(and (= (length (car doms*))
(length argtypes))
(infer vars argtypes (car doms*) (car rngs*))
(infer vars argtypes (car doms*) (if expected #f (car rngs*)))
#;(infer/list (car doms*) argtypes vars))
=> (lambda (substitution)
(let* ([s (lambda (t) (subst-all substitution t))]
[new-doms* (map s (car doms*))])
(if (andmap subtype argtypes new-doms*)
(ret (subst-all substitution (car rngs*)))
;; FIXME
;; should be an error here, something went horribly wrong!!!
(loop (cdr doms*) (cdr rngs*)))))]
(or expected
(let* ([s (lambda (t) (subst-all substitution t))]
[new-doms* (map s (car doms*))])
(if (andmap subtype argtypes new-doms*)
(ret (subst-all substitution (car rngs*)))
;; FIXME
;; should be an error here, something went horribly wrong!!!
(loop (cdr doms*) (cdr rngs*))))))]
#|
(printf "subst is:~a~nret is: ~a~nvars is: ~a~nresult is:~a~n" substitution (car rngs*) vars
(subst-all substitution (car rngs*)))
@ -280,18 +281,19 @@
(unless (<= (length dom) (length argtypes))
(tc-error "incorrect number of arguments to function: ~a ~a" dom argtypes))
(let ([substitution
(infer/vararg vars argtypes dom rest rng)
#;(infer/list/vararg dom rest argtypes vars)])
(if substitution
(let* ([s (lambda (t) (subst-all substitution t))]
[new-dom (map s dom)]
[new-rest (s rest)])
(unless (subtypes/varargs argtypes new-dom new-rest)
(int-err "Inconsistent substitution - arguments not subtypes"))
(ret (subst-all substitution rng)))
(tc-error/expr #:return (ret (Un))
"no polymorphic function domain matched - domain was: ~a rest type was: ~a arguments were ~a"
(stringify dom) rest (stringify argtypes))))]
(infer/vararg vars argtypes dom rest (if expected #f rng))])
(cond
[(and expected substitution) expected]
[substitution
(let* ([s (lambda (t) (subst-all substitution t))]
[new-dom (map s dom)]
[new-rest (s rest)])
(unless (subtypes/varargs argtypes new-dom new-rest)
(int-err "Inconsistent substitution - arguments not subtypes"))
(ret (subst-all substitution rng)))]
[else (tc-error/expr #:return (ret (Un))
"no polymorphic function domain matched - domain was: ~a rest type was: ~a arguments were ~a"
(stringify dom) rest (stringify argtypes))]))]
[(tc-result: (Poly: vars (Function: (list (arr: doms rngs rests thn-effs els-effs) ...))))
(tc-error/expr #:return (ret (Un)) "polymorphic vararg case-lambda application not yet supported")]
;; Union of function types works if we can apply all of them
@ -420,7 +422,7 @@
(and (identifier? #'eq?) (comparator? #'eq?))
(begin
;; make sure the whole expression is type correct
(tc/funapp #'eq? #'(v1 v2) (tc-expr #'eq?) (map tc-expr (syntax->list #'(v1 v2))))
(tc/funapp #'eq? #'(v1 v2) (tc-expr #'eq?) (map tc-expr (syntax->list #'(v1 v2))) expected)
;; check thn and els with the eq? info
(let-values ([(thn-eff els-eff) (tc/eq #'eq? #'v1 #'v2)])
(ret B thn-eff els-eff)))]
@ -493,6 +495,6 @@
[(#%plain-app f args ...)
(begin
;(printf "default case~n~a~n" (syntax->datum form))
(tc/funapp #'f #'(args ...) (tc-expr #'f) (map tc-expr (syntax->list #'(args ...)))))]))
(tc/funapp #'f #'(args ...) (tc-expr #'f) (map tc-expr (syntax->list #'(args ...))) expected))]))
;(trace tc/app/internal)

View File

@ -60,7 +60,8 @@
[with-handlers
([(lambda (e) (and catch-errors? (exn:fail? e) (not (exn:fail:syntax? e))))
(lambda (e) (tc-error "Internal error: ~a" e))])]
[parameterize (;; this parameter is for parsing types
[parameterize ([delay-errors? #f]
;; this parameter is for parsing types
[current-tvars initial-tvar-env]
;; this parameter is just for printing types
;; this is a parameter to avoid dependency issues