Lots more fixes

svn: r14631

original commit: 9853ae1f0f0d7c4791bc2237ab8183f6102ffa50
This commit is contained in:
Sam Tobin-Hochstadt 2009-04-27 21:16:34 +00:00
parent 4495909274
commit 4329ac34db
5 changed files with 86 additions and 78 deletions

View File

@ -62,44 +62,51 @@
[#f null]
[(cons a b) (cons a (loop b))]
[e (list e)])))
(for/fold ([ty ty])
([inst (in-improper-stx inst)])
(cond [(not inst) ty]
[(not (or (Poly? ty) (PolyDots? ty)))
(tc-error/expr #:return (Un) "Cannot instantiate non-polymorphic type ~a" ty)]
[(and (Poly? ty)
(not (= (length (syntax->list inst)) (Poly-n ty))))
(match ty
[(list ty)
(list
(for/fold ([ty ty])
([inst (in-improper-stx inst)])
(cond [(not inst) ty]
[(not (or (Poly? ty) (PolyDots? ty)))
(tc-error/expr #:return (Un) "Cannot instantiate non-polymorphic type ~a" ty)]
[(and (Poly? ty)
(not (= (length (syntax->list inst)) (Poly-n ty))))
(tc-error/expr #:return (Un)
"Wrong number of type arguments to polymorphic type ~a:~nexpected: ~a~ngot: ~a"
ty (Poly-n ty) (length (syntax->list inst)))]
[(and (PolyDots? ty) (not (>= (length (syntax->list inst)) (sub1 (PolyDots-n ty)))))
;; we can provide 0 arguments for the ... var
(tc-error/expr #:return (Un)
"Wrong number of type arguments to polymorphic type ~a:~nexpected at least: ~a~ngot: ~a"
ty (sub1 (PolyDots-n ty)) (length (syntax->list inst)))]
[(PolyDots? ty)
;; In this case, we need to check the last thing. If it's a dotted var, then we need to
;; use instantiate-poly-dotted, otherwise we do the normal thing.
(let-values ([(all-but-last last-stx) (split-last (syntax->list inst))])
(match (syntax-e last-stx)
[(cons last-ty-stx (? identifier? last-id-stx))
(unless (Dotted? (lookup (current-tvars) (syntax-e last-id-stx) (lambda _ #f)))
(tc-error/stx last-id-stx "~a is not a type variable bound with ..." (syntax-e last-id-stx)))
(if (= (length all-but-last) (sub1 (PolyDots-n ty)))
(let* ([last-id (syntax-e last-id-stx)]
[last-ty
(parameterize ([current-tvars (extend-env (list last-id)
(list (make-DottedBoth (make-F last-id)))
(current-tvars))])
(parse-type last-ty-stx))])
(instantiate-poly-dotted ty (map parse-type all-but-last) last-ty last-id))
(tc-error/expr #:return (Un) "Wrong number of fixed type arguments to polymorphic type ~a:~nexpected: ~a~ngot: ~a"
ty (sub1 (PolyDots-n ty)) (length all-but-last)))]
[_
(instantiate-poly ty (map parse-type (syntax->list inst)))]))]
[else
(instantiate-poly ty (map parse-type (syntax->list inst)))])))]
[_ (if inst
(tc-error/expr #:return (Un)
"Wrong number of type arguments to polymorphic type ~a:~nexpected: ~a~ngot: ~a"
ty (Poly-n ty) (length (syntax->list inst)))]
[(and (PolyDots? ty) (not (>= (length (syntax->list inst)) (sub1 (PolyDots-n ty)))))
;; we can provide 0 arguments for the ... var
(tc-error/expr #:return (Un)
"Wrong number of type arguments to polymorphic type ~a:~nexpected at least: ~a~ngot: ~a"
ty (sub1 (PolyDots-n ty)) (length (syntax->list inst)))]
[(PolyDots? ty)
;; In this case, we need to check the last thing. If it's a dotted var, then we need to
;; use instantiate-poly-dotted, otherwise we do the normal thing.
(let-values ([(all-but-last last-stx) (split-last (syntax->list inst))])
(match (syntax-e last-stx)
[(cons last-ty-stx (? identifier? last-id-stx))
(unless (Dotted? (lookup (current-tvars) (syntax-e last-id-stx) (lambda _ #f)))
(tc-error/stx last-id-stx "~a is not a type variable bound with ..." (syntax-e last-id-stx)))
(if (= (length all-but-last) (sub1 (PolyDots-n ty)))
(let* ([last-id (syntax-e last-id-stx)]
[last-ty
(parameterize ([current-tvars (extend-env (list last-id)
(list (make-DottedBoth (make-F last-id)))
(current-tvars))])
(parse-type last-ty-stx))])
(instantiate-poly-dotted ty (map parse-type all-but-last) last-ty last-id))
(tc-error/expr #:return (Un) "Wrong number of fixed type arguments to polymorphic type ~a:~nexpected: ~a~ngot: ~a"
ty (sub1 (PolyDots-n ty)) (length all-but-last)))]
[_
(instantiate-poly ty (map parse-type (syntax->list inst)))]))]
[else
(instantiate-poly ty (map parse-type (syntax->list inst)))])))
"Cannot instantiate expression that produces ~a values"
(if (null? ty) 0 "multiple"))
ty)]))
;; typecheck an identifier
;; the identifier has variable effect
@ -324,7 +331,7 @@
(match ty
[(tc-results: ts fs os)
(let ([ts* (do-inst form ts)])
(ret ts fs os))]))))
(ret ts* fs os))]))))
(define (tc/send rcvr method args [expected #f])
(match (tc-expr rcvr)

View File

@ -204,21 +204,6 @@
(cons (car bodies) bodies*)
(cons (syntax-len (car formals)) nums-seen))]))))
;; tc/lambda : syntax syntax-list syntax-list -> tc-result
(define (tc/lambda form formals bodies)
(tc/lambda/internal form formals bodies #f))
;; typecheck a sequence of case-lambda clauses, which is possibly polymorphic
;; tc/lambda/internal syntax syntax-list syntax-list option[type] -> tc-result
(define (tc/lambda/internal form formals bodies expected)
(if (or (syntax-property form 'typechecker:plambda) (Poly? expected) (PolyDots? expected))
(tc/plambda form formals bodies expected)
(ret (tc/mono-lambda formals bodies expected))))
;; tc/lambda : syntax syntax-list syntax-list Type -> tc-result
(define (tc/lambda/check form formals bodies expected)
(tc/lambda/internal form formals bodies expected))
;; tc/plambda syntax syntax-list syntax-list type -> Poly
;; formals and bodies must by syntax-lists
(define (tc/plambda form formals bodies expected)
@ -279,7 +264,21 @@
(unless (check-below (tc/plambda form formals bodies #f) expected)
(tc-error/expr #:return (ret expected) "Expected a value of type ~a, but got a polymorphic function." expected))
(ret expected)]))
;; typecheck a sequence of case-lambda clauses, which is possibly polymorphic
;; tc/lambda/internal syntax syntax-list syntax-list option[type] -> tc-result
(define (tc/lambda/internal form formals bodies expected)
(if (or (syntax-property form 'typechecker:plambda) (Poly? expected) (PolyDots? expected))
(tc/plambda form formals bodies expected)
(ret (make-Function (map lam-result->type (tc/mono-lambda formals bodies expected))))))
;; tc/lambda : syntax syntax-list syntax-list -> tc-result
(define (tc/lambda form formals bodies)
(tc/lambda/internal form formals bodies #f))
;; tc/lambda/check : syntax syntax-list syntax-list Type -> tc-result
(define (tc/lambda/check form formals bodies expected)
(tc/lambda/internal form formals bodies expected))
;; form : a syntax object for error reporting
;; formals : the formal arguments to the loop

View File

@ -4,6 +4,7 @@
(require (private base-types)
(for-syntax
(except-in stxclass id)
scheme/base
(private type-contract)
(types utils convenience)
@ -117,28 +118,28 @@
[expanded-module-stx body2])]
;; typecheck the body, and produce syntax-time code that registers types
[let ([type (tc-toplevel-form body2)])])
(kernel-syntax-case body2 #f
[(head . _)
(or (free-identifier=? #'head #'define-values)
(free-identifier=? #'head #'define-syntaxes)
(free-identifier=? #'head #'require)
(free-identifier=? #'head #'provide)
(free-identifier=? #'head #'begin)
(void? type)
(type-equal? -Void (tc-result-t type)))
(define-syntax-class invis-kw
#:literals (define-values define-syntaxes require provide begin)
(pattern define-values)
(pattern define-syntaxes)
(pattern require)
(pattern provide)
(pattern begin))
(syntax-parse body2
[(head:invis-kw . _)
body2]
;; construct code to print the type
[_
(nest
([with-syntax ([b body2]
[ty-str (match type
[(tc-result: t)
(format "- : ~a\n" t)]
[x (int-err "bad type result: ~a" x)])])])
#`(let ([v b] [type 'ty-str])
(begin0
v
(printf type))))]))]))
[_ (let ([ty-str (match type
[(tc-result1: t)
(if (type-equal? t -Void)
#f
(format "- : ~a\n" t))]
[x (int-err "bad type result: ~a" x)])])
(if #'ty-str
#`(let ([v #,body2] [type '#,ty-str])
(begin0
v
(printf type)))
body2))]))]))

View File

@ -158,8 +158,8 @@
#:rest [rest #f] #:drest [drest #f] #:kws [kws null]
#:filters [filters -no-lfilter] #:object [obj -no-lobj])
(c:->* ((listof Type/c) (or/c Values? ValuesDots? Type/c))
(#:rest Type/c
#:drest (cons/c Type/c symbol?)
(#:rest (or/c #f Type/c)
#:drest (or/c #f (cons/c Type/c symbol?))
#:kws (listof Keyword?)
#:filters LFilterSet?
#:object LatentObject?)

View File

@ -141,7 +141,8 @@
[(Box: e) (fp "(Box ~a)" e)]
[(Union: elems) (fp "~a" (cons 'U elems))]
[(Pair: l r) (fp "(Pair ~a ~a)" l r)]
[(F: nm) (fp "~a" nm)]
[(F: nm) (fp "~a" nm)]
[(Values: (list v)) (fp "~a" v)]
[(Values: (list v ...)) (fp "~a" (cons 'values v))]
[(ValuesDots: v dty dbound) (fp "~a" (cons 'values (append v (list dty '... dbound))))]
[(Param: in out)