Make inst mark the #%expression.

This commit is contained in:
Eric Dobson 2013-05-27 01:20:11 -07:00
parent 91c3a3a6d4
commit ee64a15265
2 changed files with 87 additions and 104 deletions

View File

@ -424,12 +424,15 @@ This file defines two sorts of primitives. All of them are provided into any mod
;; FIXME: Is the right choice to use a #:row keyword or just ;; FIXME: Is the right choice to use a #:row keyword or just
;; to use a Row type constructor and keep it consistent? ;; to use a Row type constructor and keep it consistent?
[(_ arg #:row e ...) [(_ arg #:row e ...)
(syntax-property #'arg 'type-inst #'(#:row e ...))] (with-syntax ([expr (type-inst-property #'#%expression #'(#:row e ...))])
(syntax/loc #'arg (expr arg)))]
[(_ arg tys ... ty ddd b:id) [(_ arg tys ... ty ddd b:id)
#:when (eq? (syntax-e #'ddd) '...) #:when (eq? (syntax-e #'ddd) '...)
(type-inst-property (syntax/loc #'arg (#%expression arg)) #'(tys ... (ty . b)))] (with-syntax ([expr (type-inst-property #'#%expression #'(tys ... (ty . b)))])
(syntax/loc #'arg (expr arg)))]
[(_ arg tys ...) [(_ arg tys ...)
(type-inst-property (syntax/loc #'arg (#%expression arg)) #'(tys ...))])) (with-syntax ([expr (type-inst-property #'#%expression #'(tys ...))])
(syntax/loc #'arg (expr arg)))]))
(define-syntax (lambda: stx) (define-syntax (lambda: stx)
(syntax-parse stx (syntax-parse stx

View File

@ -29,14 +29,29 @@
(define-literal-set tc-expr-literals #:for-label (define-literal-set tc-expr-literals #:for-label
(find-method/who)) (find-method/who))
;; do-inst : syntax type -> type ;; do-inst : tc-results? syntax? -> tc-results?
;; Perform a type instantiation, delegating to the appropriate helper ;; Perform a type instantiation, delegating to the appropriate helper
;; function depending on if the argument is a row or not ;; function depending on if the argument is a row or not
(define (do-inst stx ty) (define (do-inst tc-res inst)
(define inst (type-inst-property stx)) (define inst-type
(if (row-syntax? inst) (if (row-syntax? inst) do-row-inst do-normal-inst))
(do-row-inst stx inst ty) (define (error-case tys)
(do-normal-inst stx inst ty))) (tc-error/expr
"Cannot instantiate expression that produces ~a values"
(if (null? tys) 0 "multiple")))
(match tc-res
[(tc-results: tys fs os)
(match tys
[(list ty)
(ret (list (inst-type ty inst)) fs os)]
[_
(error-case tys)])]
[(tc-results: tys fs os dty dbound)
(match tys
[(list ty)
(ret (list (inst-type ty inst)) fs os dty dbound)]
[_
(error-case tys)])]))
;; row-syntax? Syntax -> Boolean ;; row-syntax? Syntax -> Boolean
;; This checks if the syntax object resulted from a row instantiation ;; This checks if the syntax object resulted from a row instantiation
@ -45,14 +60,10 @@
(and lst (pair? lst) (and lst (pair? lst)
(eq? (syntax-e (car lst)) '#:row))) (eq? (syntax-e (car lst)) '#:row)))
;; do-normal-inst : Syntax (Option Syntax) Type -> Type ;; do-normal-inst : Type Syntax -> Type
;; Instantiate a normal polymorphic type ;; Instantiate a normal polymorphic type
(define (do-normal-inst stx inst ty) (define (do-normal-inst ty inst)
(match ty
[(list ty)
(list
(cond (cond
[(not inst) ty]
[(not (or (Poly? ty) (PolyDots? ty))) [(not (or (Poly? ty) (PolyDots? ty)))
(tc-error/expr #:return (Un) "Cannot instantiate non-polymorphic type ~a" (tc-error/expr #:return (Un) "Cannot instantiate non-polymorphic type ~a"
(cleanup-type ty))] (cleanup-type ty))]
@ -83,16 +94,11 @@
[stx-list [stx-list
(instantiate-poly ty (map parse-type stx-list))])] (instantiate-poly ty (map parse-type stx-list))])]
[else [else
(instantiate-poly ty (stx-map parse-type inst))]))] (instantiate-poly ty (stx-map parse-type inst))]))
[_ (if inst
(tc-error/expr #:return (Un)
"Cannot instantiate expression that produces ~a values"
(if (null? ty) 0 "multiple"))
ty)]))
;; do-row-inst : Syntax ClassRow Type -> Type ;; do-row-inst : Type ClassRow -> Type
;; Instantiate a row polymorphic function ;; Instantiate a row polymorphic function type
(define (do-row-inst stx row-stx ty) (define (do-row-inst ty row-stx)
;; At this point, we know `stx` represents a row so we can parse it. ;; At this point, we know `stx` represents a row so we can parse it.
;; The parsing is done here because if `inst` did the parsing, it's ;; The parsing is done here because if `inst` did the parsing, it's
;; too early and ends up with an empty type environment. ;; too early and ends up with an empty type environment.
@ -100,10 +106,7 @@
(syntax-parse row-stx (syntax-parse row-stx
[(#:row (~var clauses (row-clauses parse-type))) [(#:row (~var clauses (row-clauses parse-type)))
(attribute clauses.row)])) (attribute clauses.row)]))
(match ty (cond
[(list ty)
(list
(cond [(not row) ty]
[(not (PolyRow? ty)) [(not (PolyRow? ty))
(tc-error/expr #:return (Un) "Cannot instantiate non-row-polymorphic type ~a" (tc-error/expr #:return (Un) "Cannot instantiate non-row-polymorphic type ~a"
(cleanup-type ty))] (cleanup-type ty))]
@ -112,15 +115,10 @@
(check-row-constraints (check-row-constraints
row constraints row constraints
(λ (name) (λ (name)
(tc-error/delayed (tc-error/expr
(~a "Cannot instantiate row with member " name (~a "Cannot instantiate row with member " name
" that the given row variable requires to be absent")))) " that the given row variable requires to be absent"))))
(instantiate-poly ty (list row))]))] (instantiate-poly ty (list row))]))
[_ (if row
(tc-error/expr #:return (Un)
"Cannot instantiate expression that produces ~a values"
(if (null? ty) 0 "multiple"))
ty)]))
;; typecheck an identifier ;; typecheck an identifier
;; the identifier has variable effect ;; the identifier has variable effect
@ -165,19 +163,6 @@
;; around again in case there is an instantiation ;; around again in case there is an instantiation
;; remove the ascription so we don't loop infinitely ;; remove the ascription so we don't loop infinitely
(loop (remove-ascription form*) r* #t)))] (loop (remove-ascription form*) r* #t)))]
[(type-inst-property form*)
;; check without property first
;; to get the appropriate type to instantiate
(match (tc-expr (type-inst-property form* #f))
[(tc-results: ts fs os)
;; do the instantiation on the old type
(let* ([ts* (do-inst form* ts)]
[ts** (ret ts* fs os)])
(add-typeof-expr form ts**)
;; make sure the new type is ok
(check-below ts** expected))]
;; no annotations possible on dotted results
[ty (add-typeof-expr form ty) ty])]
[(external-check-property form*) [(external-check-property form*)
=> =>
(lambda (check) (lambda (check)
@ -281,7 +266,11 @@
;; application ;; application
[(#%plain-app . _) (tc/app/check form expected)] [(#%plain-app . _) (tc/app/check form expected)]
;; #%expression ;; #%expression
[(#%expression e) (tc-expr/check #'e expected)] [((~and exp #%expression) e)
#:when (type-inst-property #'exp)
(do-inst (tc-expr #'e) (type-inst-property #'exp))]
[(#%expression e)
(tc-expr/check #'e expected)]
;; syntax ;; syntax
;; for now, we ignore the rhs of macros ;; for now, we ignore the rhs of macros
[(letrec-syntaxes+values stxs vals . body) [(letrec-syntaxes+values stxs vals . body)
@ -445,6 +434,9 @@
;; top-level variable reference - occurs at top level ;; top-level variable reference - occurs at top level
[(#%top . id) (tc-id #'id)] [(#%top . id) (tc-id #'id)]
;; #%expression ;; #%expression
[((~and exp #%expression) e)
#:when (type-inst-property #'exp)
(do-inst (tc-expr #'e) (type-inst-property #'exp))]
[(#%expression e) (tc-expr #'e)] [(#%expression e) (tc-expr #'e)]
;; #%variable-reference ;; #%variable-reference
[(#%variable-reference . _) [(#%variable-reference . _)
@ -482,20 +474,8 @@
[(type-ascription form) => (lambda (ann) (tc-expr/check form ann))] [(type-ascription form) => (lambda (ann) (tc-expr/check form ann))]
[else [else
(let ([ty (internal-tc-expr form)]) (let ([ty (internal-tc-expr form)])
(match ty
[(tc-any-results:)
(add-typeof-expr form ty) (add-typeof-expr form ty)
ty] ty)])))
[(tc-results: ts fs os)
(let* ([ts* (do-inst form ts)]
[r (ret ts* fs os)])
(add-typeof-expr form r)
r)]
[(tc-results: ts fs os dty dbound)
(define ts* (do-inst form ts))
(define r (ret ts* fs os dty dbound))
(add-typeof-expr form r)
r]))])))
(define (single-value form [expected #f]) (define (single-value form [expected #f])
(define t (if expected (tc-expr/check form expected) (tc-expr form))) (define t (if expected (tc-expr/check form expected) (tc-expr form)))