Move parse-type2 to parse-type.

Re-enable typed-scheme tests automatically.

svn: r15924

original commit: 4907d266df8438b6f0f4a3e3fd0241702ab46b57
This commit is contained in:
Sam Tobin-Hochstadt 2009-09-08 20:02:03 +00:00
parent cf872c4e38
commit 521dee2bb5
2 changed files with 242 additions and 538 deletions

View File

@ -7,7 +7,7 @@
[Un t:Un] [-> t:->])
(private base-types base-types-extra colon)
(for-template (private base-types base-types-extra base-env colon))
(private parse-type2)
(private parse-type)
(schemeunit))
(provide parse-type-tests)

View File

@ -1,577 +1,285 @@
#lang scheme/base
(require "parse-type2.ss")
(provide (all-from-out "parse-type2.ss"))
#|
(require (except-in "../utils/utils.ss" extend))
(require (except-in (rep type-rep) make-arr)
(rename-in (types convenience union utils) [make-arr* make-arr])
(utils tc-utils)
(utils tc-utils stxclass-util)
syntax/stx (prefix-in c: scheme/contract)
(except-in stxclass) stxclass/util
syntax/parse stxclass/util
(env type-environments type-name-env type-alias-env lexical-env)
(prefix-in t: "base-types-extra.ss")
(prefix-in t: (combine-in "base-types-extra.ss" "base-types.ss")) (only-in "colon.ss" :)
scheme/match
(for-syntax scheme/base stxclass stxclass/util)
(for-template scheme/base "base-types-extra.ss"))
(define (atom? v)
(or (number? v) (string? v) (boolean? v) (symbol? v) (keyword? v) (char? v) (bytes? v) (regexp? v)))
(define-syntax-class (3d pred)
(pattern s
#:with datum (syntax-e #'s)
#:when (pred #'datum)))
(define-syntax (parse/get stx)
(syntax-parse stx
[(_ arg:expr attr:id pat)
(let* ([i (generate-temporary)]
[get-i (datum->syntax
i
(string->symbol
(string-append (symbol->string (syntax-e i))
"."
(symbol->string #'attr.datum))))])
(quasisyntax/loc stx
(syntax-parse arg
[#,i #:declare #,i pat #'#,get-i])))]))
(define-pred-stxclass atom atom?)
(define-pred-stxclass byte-pregexp byte-pregexp?)
(define-pred-stxclass byte-regexp byte-regexp?)
(define-pred-stxclass regexp regexp?)
(define-pred-stxclass bytes bytes?)
(for-template scheme/base "base-types-extra.ss" "colon.ss")
(for-template (prefix-in t: "base-types-extra.ss")))
(p/c [parse-type (syntax? . c:-> . Type/c)]
[parse-type/id (syntax? c:any/c . c:-> . Type/c)]
[parse-tc-results (syntax? . c:-> . tc-results?)]
[parse-tc-results/id (syntax? c:any/c . c:-> . tc-results?)]
[parse-type* (syntax? . c:-> . Type/c)])
[parse-tc-results/id (syntax? c:any/c . c:-> . tc-results?)])
(define enable-mu-parsing (make-parameter #t))
(define ((parse/id p) loc datum)
#;(printf "parse-type/id id : ~a~n ty: ~a~n" (syntax-object->datum loc) (syntax-object->datum stx))
(let* ([stx* (datum->syntax loc datum loc loc)])
(p stx*)))
(define (stx-cadr stx) (stx-car (stx-cdr stx)))
(define-syntax-class star
#:description "*"
(pattern star:id
#:when (eq? '* #'star.datum)))
#:fail-unless (eq? '* (syntax-e #'star)) "missing *"))
(define-syntax-class ddd
#:description "..."
(pattern ddd:id
#:when (eq? '... #'ddd.datum)))
(define-syntax-class tvar
#:description "type variable"
(pattern v:id
#:with val (lookup (current-tvars) #'v.datum (lambda (_) #f))
#:with name #'v.datum
#:with datum #'v.datum
#:when #'val))
(define-syntax-class dotted-tvar
#:description "type variable bound with ..."
(pattern v:tvar
#:when (Dotted? #'v.val)
#:with t (Dotted-t #'v.val)
#:with val #'v.val
#:with name #'v.datum
#:with datum #'v.datum))
(define-syntax-class dotted-both-tvar
#:transparent
(pattern v:dotted-tvar
#:when (DottedBoth? #'v.val)
#:with t (Dotted-t #'v.val)
#:with val #'v.val
#:with name #'v.datum
#:with datum #'v.datum))
(define-syntax-class (type/tvars syms var-tys)
(pattern ty
#:with t (parameterize ([current-tvars (extend-env syms
var-tys
(current-tvars))])
(parse-type* #'ty))))
(define-syntax-class (type/tvar sym var-ty)
(pattern ty
#:declare ty (type/tvars (list sym) (list var-ty))
#:with t #'ty.t))
(define-syntax-class fun-ty
#:literals (t:-> :)
#:transparent
#:description "function type"
;; FIXME - shouldn't have to use syntax->datum
(pattern (dom*:type t:-> rng:type : pred:type)
#:when (add-type-name-reference #'t:->)
#:with t (make-pred-ty (list #'dom*.t) #'rng.t #'pred.t)
#:with (dom ...) (list #'dom*))
(pattern (dom:type ... rest:type _:star t:-> rng:type)
#:when (add-type-name-reference #'t:->)
#:with t (->* (syntax->datum #'(dom.t ...)) #'rest.t #'rng.t))
(pattern (dom:type ... rest _:ddd bound:dotted-tvar t:-> rng:type)
#:with rest.t (parse/get #'rest t (type/tvar #'bound.name (make-DottedBoth (make-F #'bound.name))))
#:when (add-type-name-reference #'t:->)
#:with t
(let ([var #'bound.val])
(make-Function
(list
(make-arr-dots (syntax->datum #'(dom.t ...))
#'rng.t
#'rest.t
#'bound.name)))))
(pattern (dom:type ... t:-> rng:type)
#:when (add-type-name-reference #'t:->)
#:with t (->* (syntax->datum #'(dom.t ...)) #'rng.t)))
(define-syntax-class fun-ty/one
(pattern f:fun-ty
#:with arr (match #'f.t [(Function: (list a)) a])))
(define-syntax-class values-ty
#:literals (values)
(pattern (values ts:type ... rest _:ddd bound:dotted-tvar)
#:with rest.t (parse/get #'rest t (type/tvar #'bound.name (make-DottedBoth (make-F #'bound.name))))
#:with t
(make-ValuesDots (syntax->datum #'(ts.t ...))
#'rest.t
#'bound.name))
(pattern (values ts:type ...)
#:with t (-values (syntax->datum #'(ts.t ...)))))
(define-syntax-class type-name
#:description "type name"
(pattern i:id
#:when (lookup-type-name #'i (lambda () #f))
#:with t #'(make-Name #'i)
#:when (add-type-name-reference #'i)))
(define-syntax-class type-alias
#:description "type alias"
(pattern i:id
#:with t (lookup-type-alias #'i parse-type* (lambda () #f))
#:when #'t
#:when (add-type-name-reference #'i)))
(define-syntax-class all-ddd-formals
#:description "\na sequence of identifiers with a ... after the last identifier\n"
(pattern (v:id ... v-last:id _:ddd)))
(define-syntax-class all-formals
#:description "\na sequence of identifiers\n"
(pattern (v:id ...)))
(define-syntax-class all-type
#:description "All type"
#:transparent
#:literals (t:All)
(pattern (t:All :all-ddd-formals b)
#:with b.t (parse/get #'b t (type/tvars (cons #'v-last.datum (syntax->datum #'(v ...)))
(cons (make-Dotted (make-F #'v-last.datum))
(map make-F (syntax->datum #'(v ...))))))
#:when (add-type-name-reference #'All)
#:with t (make-PolyDots (syntax->datum #'(v ... v-last)) #'b.t))
(pattern (t:All :all-formals b)
#:with b.t (parse/get #'b t (type/tvars (syntax->datum #'(v ...)) (map make-F (syntax->datum #'(v ...)))))
#:when (add-type-name-reference #'All)
#:with t (make-Poly (syntax->datum #'(v ...)) #'b.t)))
(define-syntax-class type-app
#:attributes (t)
(pattern (i arg:type args:type ...)
#:declare i type
#:when (identifier? #'i)
#:with t
(let loop
([rator #'i.t] [args (syntax->datum #'(arg.t args.t ...))])
(match rator
[(Name: _)
;; FIXME - need orig stx
(make-App rator args #'here)]
[(Poly: ns _)
(if (not (= (length args) (length ns)))
(begin
(tc-error/delayed "Wrong number of arguments to type ~a, expected ~a but got ~a" rator (length ns) (length args))
(instantiate-poly rator (map (lambda _ Err) ns)))
(instantiate-poly rator args))]
[(Mu: _ _) (loop (unfold rator) args)]
[(Error:) Err]
[_ (tc-error/delayed "Type ~a cannot be applied, arguments were: ~a" rator args)
Err]))))
(define-syntax-class not-kw-id
#:attributes (datum)
(pattern i:id
#:when (not (for/or ([e (syntax->list
#'(quote t:pred t:Tuple case-lambda t:U t:Rec t:Opaque t:Parameter t:Class t:Instance
t:-> t:All))])
(free-identifier=? e #'i)))
#:when (not (memq #'i.datum '(* ...)))
#:with datum #'i.datum))
(define-syntax-class type
#:transparent
#:attributes (t)
#:literals (quote t:pred t:Tuple case-lambda t:U t:Rec t:Opaque t:Parameter t:Class t:Instance)
(pattern ty
#:declare ty (3d Type?)
#:with t #'ty.datum)
(pattern i:dotted-both-tvar
#:with t #'i.t)
#;
(pattern i:dotted-tvar
#:when (tc-error/stx #'i "Type variable ~a must be used with ..." #'i.datum)
#:with t Err)
(pattern i:tvar
#:when (not (Dotted? #'i.val))
#:with t #'i.val)
(pattern i:type-alias
#:with t #'i.t)
(pattern i:type-name
#:with t #'i.t)
#;
(pattern i:not-kw-id
#:with t Err
#:when (tc-error/stx #'i "Unbound type name ~a" #'i.datum)
)
(pattern ty:all-type
#:with t #'ty.t)
(pattern (t:Rec x:id b)
#:when (enable-mu-parsing)
#:with b.t (parse/get #'b t (type/tvar #'x.datum (make-F #'x.datum)))
#:when (add-type-name-reference #'t:Rec)
#:with t (if (memq #'x.datum (fv #'b.t))
(make-Mu #'x.datum #'b.t)
#'b.t))
(pattern (t:pred ty:type)
#:when (add-type-name-reference #'t:pred)
#:with t (make-pred-ty #'ty.t))
(pattern (t:Parameter ty:type)
#:when (add-type-name-reference #'t:Paramter)
#:with t (-Param #'ty.t #'ty.t))
(pattern (t:Parameter t1:type t2:type)
#:when (add-type-name-reference #'t:Paramter)
#:with t (-Param #'t1.t #'t2.t))
(pattern (t:Opaque p?:id)
#:when (add-type-name-reference #'t:Opaque)
#:with t (make-Opaque #'p? (syntax-local-certifier)))
(pattern (t:U ty:type ...)
#:with t (apply Un (syntax->datum #'(ty.t ...))))
(pattern (t:Tuple ty:type ...)
#:with t (-Tuple (syntax->datum #'(ty.t ...))))
(pattern fty:fun-ty
#:with t #'fty.t)
(pattern vt:values-ty
#:with t #'vt.t)
(pattern (fst:type . rst:type)
#:with t (-pair #'fst.t #'rst.t))
(pattern (quote v:atom)
#:with t (-val #'v.datum))
(pattern (case-lambda f:fun-ty/one ...)
#:with t (make-Function (syntax->datum #'(f.arr ...))))
(pattern (t:Class (pos-args:type ...) ([fname:id fty:type (~or (rest:boolean) #:opt) ...] ...) ([mname:id mty:type] ...))
#:with t
(make-Class
(syntax->datum #'(pos-args.t ...))
(syntax->datum #'([fname.datum fty.t rest.datum] ...))
(syntax->datum #'([mname.datum mty.t] ...))))
(pattern (t:Instance ty:type)
#:with t
(if (not (or (Mu? #'ty.t) (Class? #'ty.t) (Union? #'ty.t) (Error? #'ty.t)))
(begin (tc-error/delayed "Argument to Instance must be a class type, got ~a" #'ty.t)
(make-Instance Err))
(make-Instance #'ty.t)))
(pattern tapp:type-app
#:with t #'tapp.t)
(pattern v:atom
#:when (not (symbol? #'v.datum))
#:with t (-val #'v.datum)))
(define (parse-type* stx)
(parameterize ([current-orig-stx stx])
(parse/get stx t type)))
#:fail-unless (eq? '... (syntax-e #'ddd)) "missing ..."))
(define (parse-all-type stx parse-type)
(syntax-parse stx
[(All (vars ... v dd) t)
#:when (eq? (syntax-e #'dd) '...)
#:when (andmap identifier? (syntax->list #'(v vars ...)))
;(printf "parse-all-type: ~a ~n" (syntax->datum stx))
(syntax-parse stx #:literals (t:All)
[(t:All (vars:id ... v:id dd:ddd) t)
(let* ([vars (map syntax-e (syntax->list #'(vars ...)))]
[tvars (map make-F vars)]
[v (syntax-e #'v)]
[tv (make-Dotted (make-F v))])
(add-type-name-reference #'All)
(add-type-name-reference #'t:All)
(parameterize ([current-tvars (extend-env (cons v vars) (cons tv tvars) (current-tvars))])
(make-PolyDots (append vars (list v)) (parse-type #'t))))]
[(All (vars ...) t)
#:when (andmap identifier? (syntax->list #'(vars ...)))
[(t:All (vars:id ...) t)
(let* ([vars (map syntax-e (syntax->list #'(vars ...)))]
[tvars (map make-F vars)])
(add-type-name-reference #'All)
(add-type-name-reference #'t:All)
(parameterize ([current-tvars (extend-env vars tvars (current-tvars))])
(make-Poly vars (parse-type #'t))))]
[(All . rest) (tc-error "All: bad syntax")]))
[(t:All . rest) (tc-error "All: bad syntax")]))
(define (parse-type stx)
(parameterize ([current-orig-stx stx])
(syntax-case* stx ()
symbolic-identifier=?
[t
(Type? (syntax-e #'t))
(syntax-e #'t)]
[(fst . rst)
(not (syntax->list #'rst))
(-pair (parse-type #'fst) (parse-type #'rst))]
[(Class (pos-args ...) ([fname fty . rest] ...) ([mname mty] ...))
(eq? (syntax-e #'Class) 'Class)
(make-Class
(map parse-type (syntax->list #'(pos-args ...)))
(map list
(map syntax-e (syntax->list #'(fname ...)))
(map parse-type (syntax->list #'(fty ...)))
(map (lambda (e) (syntax-case e ()
[(#t) #t]
[_ #f]))
(syntax->list #'(rest ...))))
(map list
(map syntax-e (syntax->list #'(mname ...)))
(map parse-type (syntax->list #'(mty ...)))))]
[(Refinement p?)
(and (eq? (syntax-e #'Refinement) 'Refinement)
(identifier? #'p?))
(match (lookup-type/lexical #'p?)
[(and t (Function: (list (arr: (list dom) _ #f #f '()))))
(make-Refinement dom #'p? (syntax-local-certifier))]
[t (tc-error "cannot declare refinement for non-predicate ~a" t)])]
[(Instance t)
(eq? (syntax-e #'Instance) 'Instance)
(let ([v (parse-type #'t)])
(if (not (or (Mu? v) (Class? v) (Union? v) (Error? v)))
(begin (tc-error/delayed "Argument to Instance must be a class type, got ~a" v)
(make-Instance (Un)))
(make-Instance v)))]
[(Tuple ts ...)
(or (eq? (syntax-e #'Tuple) 'Tuple)
(eq? (syntax-e #'Tuple) 'List))
(begin
(add-type-name-reference (stx-car stx))
(-Tuple (map parse-type (syntax->list #'(ts ...)))))]
[(cons fst rst)
(eq? (syntax-e #'cons) 'cons)
(-pair (parse-type #'fst) (parse-type #'rst))]
[(pred t)
(eq? (syntax-e #'pred) 'pred)
(make-pred-ty (parse-type #'t))]
;; function types
[(dom -> rng : pred-ty)
(and
(eq? (syntax-e #'->) '->)
(eq? (syntax-e #':) ':))
(begin
(add-type-name-reference (stx-cadr stx))
;; use parse-type instead of parse-values-type because we need to add the filters from the pred-ty
(make-pred-ty (list (parse-type #'dom)) (parse-type #'rng) (parse-type #'pred-ty)))]
[(dom ... rest ::: -> rng)
(and (eq? (syntax-e #'->) '->)
(eq? (syntax-e #':::) '*))
(begin
(add-type-name-reference #'->)
(->* (map parse-type (syntax->list #'(dom ...))) (parse-type #'rest) (parse-values-type #'rng)))]
[(dom ... rest ::: bound -> rng)
(and (eq? (syntax-e #'->) '->)
(eq? (syntax-e #':::) '...)
(identifier? #'bound))
(begin
(add-type-name-reference #'->)
(let ([var (lookup (current-tvars) (syntax-e #'bound) (lambda (_) #f))])
(if (not (Dotted? var))
(tc-error/stx #'bound "Used a type variable (~a) not bound with ... as a bound on a ..." (syntax-e #'bound))
(make-Function
(list
(make-arr-dots (map parse-type (syntax->list #'(dom ...)))
(parse-values-type #'rng)
(parameterize ([current-tvars (extend-env (list (syntax-e #'bound))
(list (make-DottedBoth (make-F (syntax-e #'bound))))
(current-tvars))])
(parse-type #'rest))
(syntax-e #'bound)))))))]
[(dom ... rest ::: -> rng)
(and (eq? (syntax-e #'->) '->)
(eq? (syntax-e #':::) '...))
(begin
(add-type-name-reference #'->)
(let ([bounds (filter (compose Dotted? cdr) (env-keys+vals (current-tvars)))])
(when (null? bounds)
(tc-error/stx stx "No type variable bound with ... in scope for ... type"))
(unless (null? (cdr bounds))
(tc-error/stx stx "Cannot infer bound for ... type"))
(match-let ([(cons var (struct Dotted (t))) (car bounds)])
(make-Function
(list
(make-arr-dots (map parse-type (syntax->list #'(dom ...)))
(parse-values-type #'rng)
(parameterize ([current-tvars (extend-env (list var)
(list (make-DottedBoth t))
(current-tvars))])
(parse-type #'rest))
var))))))]
;; has to be below the previous one
[(dom ... -> rng)
(eq? (syntax-e #'->) '->)
(begin
(add-type-name-reference #'->)
(->* (map parse-type (syntax->list #'(dom ...))) (parse-values-type #'rng)))]
[(case-lambda tys ...)
(eq? (syntax-e #'case-lambda) 'case-lambda)
(make-Function
(for/list ([ty (syntax->list #'(tys ...))])
(let ([t (parse-type ty)])
(match t
[(Function: (list arr)) arr]
[_ (tc-error/stx ty "Component of case-lambda type was not a function clause")]))))]
[(Vectorof t)
(eq? (syntax-e #'Vectorof) 'Vectorof)
(begin
(add-type-name-reference #'Vectorof)
(make-Vector (parse-type #'t)))]
[(mu x t)
(and (identifier? #'x)
(memq (syntax-e #'mu) '(mu Rec))
(enable-mu-parsing))
(let* ([var (syntax-e #'x)]
[tvar (make-F var)])
(add-type-name-reference #'mu)
(parameterize ([current-tvars (extend-env (list var) (list tvar) (current-tvars))])
(let ([t (parse-type #'t)])
(if (memq var (fv t))
(make-Mu var t)
t))))]
[(U ts ...)
(eq? (syntax-e #'U) 'U)
(begin
(add-type-name-reference #'U)
(apply Un (map parse-type (syntax->list #'(ts ...)))))]
[(Un-pat ts ...)
(eq? (syntax-e #'Un-pat) 'Un)
(apply Un (map parse-type (syntax->list #'(ts ...))))]
[(quot t)
(eq? (syntax-e #'quot) 'quote)
(-val (syntax-e #'t))]
[(All . rest)
(or (eq? (syntax-e #'All) 'All)
(eq? (syntax-e #'All) '))
(parse-all-type stx parse-type)]
[(Opaque p?)
(eq? (syntax-e #'Opaque) 'Opaque)
(begin
(add-type-name-reference #'Opaque)
(make-Opaque #'p? (syntax-local-certifier)))]
[(Parameter t)
(eq? (syntax-e #'Parameter) 'Parameter)
(let ([ty (parse-type #'t)])
(add-type-name-reference #'Parameter)
(-Param ty ty))]
[(Parameter t1 t2)
(eq? (syntax-e #'Parameter) 'Parameter)
(begin
(add-type-name-reference #'Parameter)
(-Param (parse-type #'t1) (parse-type #'t2)))]
[id
(identifier? #'id)
(cond
;; if it's a type variable, we just produce the corresponding reference (which is in the HT)
[(lookup (current-tvars) (syntax-e #'id) (lambda (_) #f))
=>
(lambda (e) (cond [(DottedBoth? e) (Dotted-t e)]
[(Dotted? e)
(tc-error "Type variable ~a must be used with ..." (syntax-e #'id))]
[else e]))]
;; if it's a type alias, we expand it (the expanded type is stored in the HT)
[(lookup-type-alias #'id parse-type (lambda () #f))
=>
(lambda (t)
;(printf "found a type alias ~a~n" #'id)
(add-type-name-reference #'id)
t)]
;; if it's a type name, we just use the name
[(lookup-type-name #'id (lambda () #f))
(add-type-name-reference #'id)
;(printf "found a type name ~a~n" #'id)
(make-Name #'id)]
[(eq? '-> (syntax-e #'id))
(tc-error/delayed "Incorrect use of -> type constructor")
Err]
[else
(tc-error/delayed "Unbound type name ~a" (syntax-e #'id))
Err])]
[(Opaque . rest) (eq? (syntax-e #'Opaque) 'Opqaue) (tc-error "Opaque: bad syntax")]
[(U . rest) (eq? (syntax-e #'U) 'U) (tc-error "Union: bad syntax")]
[(Vectorof . rest) (eq? (syntax-e #'Vectorof) 'Vectorof) (tc-error "Vectorof: bad syntax")]
[(mu . rest) (eq? (syntax-e #'mu) 'mu) (tc-error "mu: bad syntax")]
[(Un . rest) (eq? (syntax-e #'Un) 'Un) (tc-error "Union: bad syntax")]
[(t ... -> . rest) (eq? (syntax-e #'->) '->) (tc-error "->: bad syntax")]
[(id arg args ...)
(let loop
([rator (parse-type #'id)]
[args (map parse-type (syntax->list #'(arg args ...)))])
(match rator
[(Name: _)
(make-App rator args stx)]
[(Poly: ns _)
(unless (= (length args) (length ns))
(tc-error "Wrong number of arguments to type ~a, expected ~a but got ~a" rator (length ns) (length args)))
(instantiate-poly rator args)]
[(Mu: _ _) (loop (unfold rator) args)]
[(Error:) Err]
[_ (tc-error/delayed "Type ~a cannot be applied, arguments were: ~a" rator args)
Err]))
#;
(let ([ty (parse-type #'id)])
#;(printf "ty is ~a" ty)
(unless (Poly? ty)
(tc-error "not a polymorphic type: ~a" (syntax-e #'id)))
(unless (= (length (syntax->list #'(arg args ...))) (Poly-n ty))
(tc-error "wrong number of arguments to type constructor ~a: expected ~a, got ~a"
(syntax-e #'id)
(Poly-n ty)
(length (syntax->list #'(arg args ...)))))
(instantiate-poly ty (map parse-type (syntax->list #'(arg args ...)))))]
[t
(or (boolean? (syntax-e #'t)) (number? (syntax-e #'t))
(string? (syntax-e #'t)))
(-val (syntax-e #'t))]
[_ (tc-error "not a valid type: ~a" (syntax->datum stx))])))
(syntax-parse
stx
#:literals (t:Class t:Refinement t:Instance t:Tuple t:List cons t:pred t:-> : case-lambda
t:Vectorof t:mu t:Rec t:U t:All t:Opaque t:Parameter quote)
[t
#:declare t (3d Type?)
(printf "3d type ~a~n" #'t.datum)
(attribute t.datum)]
[(fst . rst)
#:fail-unless (not (syntax->list #'rst)) #f
(-pair (parse-type #'fst) (parse-type #'rst))]
[(t:Class (pos-args ...) ([fname fty . rest] ...) ([mname mty] ...))
(make-Class
(map parse-type (syntax->list #'(pos-args ...)))
(map list
(map syntax-e (syntax->list #'(fname ...)))
(map parse-type (syntax->list #'(fty ...)))
(map (lambda (e) (syntax-case e ()
[(#t) #t]
[_ #f]))
(syntax->list #'(rest ...))))
(map list
(map syntax-e (syntax->list #'(mname ...)))
(map parse-type (syntax->list #'(mty ...)))))]
[(t:Refinement p?:id)
(match (lookup-type/lexical #'p?)
[(and t (Function: (list (arr: (list dom) _ #f #f '()))))
(make-Refinement dom #'p? (syntax-local-certifier))]
[t (tc-error "cannot declare refinement for non-predicate ~a" t)])]
[(t:Instance t)
(let ([v (parse-type #'t)])
(if (not (or (Mu? v) (Class? v) (Union? v) (Error? v)))
(begin (tc-error/delayed "Argument to Instance must be a class type, got ~a" v)
(make-Instance (Un)))
(make-Instance v)))]
[(t:List ts ...)
(add-type-name-reference (stx-car stx))
(-Tuple (map parse-type (syntax->list #'(ts ...))))]
[(cons fst rst)
(-pair (parse-type #'fst) (parse-type #'rst))]
[(t:pred t)
(make-pred-ty (parse-type #'t))]
;; function types
[(dom t:-> rng : pred-ty)
(add-type-name-reference (cadr (syntax-e stx)))
;; use parse-type instead of parse-values-type because we need to add the filters from the pred-ty
(make-pred-ty (list (parse-type #'dom)) (parse-type #'rng) (parse-type #'pred-ty))]
[(dom ... rest ddd:star t:-> rng)
#:fail-unless (eq? '* (syntax-e #'ddd))
(add-type-name-reference #'t:->)
(->* (map parse-type (syntax->list #'(dom ...))) (parse-type #'rest) (parse-values-type #'rng))]
[(dom ... rest _:ddd bound:id t:-> rng)
(add-type-name-reference #'t:->)
(let ([var (lookup (current-tvars) (syntax-e #'bound) (lambda (_) #f))])
(if (not (Dotted? var))
(tc-error/stx #'bound
"Used a type variable (~a) not bound with ... as a bound on a ..."
(syntax-e #'bound))
(make-Function
(list
(make-arr-dots (map parse-type (syntax->list #'(dom ...)))
(parse-values-type #'rng)
(parameterize
([current-tvars
(extend-env
(list (syntax-e #'bound))
(list (make-DottedBoth (make-F (syntax-e #'bound))))
(current-tvars))])
(parse-type #'rest))
(syntax-e #'bound))))))]
[(dom ... rest _:ddd t:-> rng)
(add-type-name-reference #'->)
(let ([bounds (filter (compose Dotted? cdr)
(env-keys+vals (current-tvars)))])
(when (null? bounds)
(tc-error/stx stx "No type variable bound with ... in scope for ... type"))
(unless (null? (cdr bounds))
(tc-error/stx stx "Cannot infer bound for ... type"))
(match-let ([(cons var (struct Dotted (t))) (car bounds)])
(make-Function
(list
(make-arr-dots (map parse-type (syntax->list #'(dom ...)))
(parse-values-type #'rng)
(parameterize ([current-tvars
(extend-env (list var)
(list (make-DottedBoth t))
(current-tvars))])
(parse-type #'rest))
var)))))]
;; has to be below the previous one
[(dom ... t:-> rng)
(add-type-name-reference #'t:->)
(->* (map parse-type (syntax->list #'(dom ...)))
(parse-values-type #'rng))]
[(case-lambda tys ...)
(make-Function
(for/list ([ty (syntax->list #'(tys ...))])
(let ([t (parse-type ty)])
(match t
[(Function: (list arr)) arr]
[_ (tc-error/stx
ty
"Component of case-lambda type was not a function clause")]))))]
[(t:Vectorof t)
(add-type-name-reference #'t:Vectorof)
(make-Vector (parse-type #'t))]
[((~and name t:Rec) x:id t)
#:fail-unless (enable-mu-parsing) "Recursive types not allowed"
(let* ([var (syntax-e #'x)]
[tvar (make-F var)])
(add-type-name-reference #'name)
(parameterize ([current-tvars (extend-env
(list var)
(list tvar)
(current-tvars))])
(let ([t (parse-type #'t)])
(if (memq var (fv t))
(make-Mu var t)
t))))]
[(t:U ts ...)
(add-type-name-reference #'t:U)
(apply Un (map parse-type (syntax->list #'(ts ...))))]
[(quote t)
(-val (syntax-e #'t))]
#;
[(All-kw . rest)
#:fail-unless (eq? 'All (syntax-e #'All-kw)) #f
#:fail-unless (printf "id: ~a ~a~n"
(identifier-binding #'All-kw)
(identifier-transformer-binding #'All-kw)) #f
#:fail-unless (printf "kw: ~a ~a~n"
(identifier-binding #'t:All)
(identifier-transformer-binding #'t:All)) #f
#:fail-when #t #f
(error 'never-happen)]
[(t:All . rest)
(parse-all-type stx parse-type)]
[(t:Opaque p?)
(add-type-name-reference #'Opaque)
(make-Opaque #'p? (syntax-local-certifier))]
[(t:Parameter t)
(let ([ty (parse-type #'t)])
(add-type-name-reference #'Parameter)
(-Param ty ty))]
[(t:Parameter t1 t2)
(begin
(add-type-name-reference #'t:Parameter)
(-Param (parse-type #'t1) (parse-type #'t2)))]
[id:identifier
(cond
;; if it's a type variable, we just produce the corresponding reference (which is in the HT)
[(lookup (current-tvars) (syntax-e #'id) (lambda (_) #f))
=>
(lambda (e) (cond [(DottedBoth? e) (Dotted-t e)]
[(Dotted? e)
(tc-error
"Type variable ~a must be used with ..."
(syntax-e #'id))]
[else e]))]
;; if it's a type alias, we expand it (the expanded type is stored in the HT)
[(lookup-type-alias #'id parse-type (lambda () #f))
=>
(lambda (t)
;(printf "found a type alias ~a~n" #'id)
(add-type-name-reference #'id)
t)]
;; if it's a type name, we just use the name
[(lookup-type-name #'id (lambda () #f))
(add-type-name-reference #'id)
;(printf "found a type name ~a~n" #'id)
(make-Name #'id)]
[(free-identifier=? #'id #'t:->)
(tc-error/delayed "Incorrect use of -> type constructor")
Err]
[else
(tc-error/delayed
"Unbound type name ~a"
(syntax-e #'id))
Err])]
[(t:Opaque . rest)
(tc-error "Opaque: bad syntax")]
[(t:U . rest)
(tc-error "Union: bad syntax")]
[(t:Vectorof . rest)
(tc-error "Vectorof: bad syntax")]
[(t:mu . rest)
(tc-error "mu: bad syntax")]
[(t ... t:-> . rest)
(tc-error "->: bad syntax")]
[(id arg args ...)
(let loop
([rator (parse-type #'id)]
[args (map parse-type (syntax->list #'(arg args ...)))])
(match rator
[(Name: _)
(make-App rator args stx)]
[(Poly: ns _)
(unless (= (length args) (length ns))
(tc-error "Wrong number of arguments to type ~a, expected ~a but got ~a" rator (length ns) (length args)))
(instantiate-poly rator args)]
[(Mu: _ _) (loop (unfold rator) args)]
[(Error:) Err]
[_ (tc-error/delayed "Type ~a cannot be applied, arguments were: ~a" rator args)
Err]))
#;
(let ([ty (parse-type #'id)])
#;(printf "ty is ~a" ty)
(unless (Poly? ty)
(tc-error "not a polymorphic type: ~a" (syntax-e #'id)))
(unless (= (length (syntax->list #'(arg args ...))) (Poly-n ty))
(tc-error "wrong number of arguments to type constructor ~a: expected ~a, got ~a"
(syntax-e #'id)
(Poly-n ty)
(length (syntax->list #'(arg args ...)))))
(instantiate-poly ty (map parse-type (syntax->list #'(arg args ...)))))]
[t:atom
(-val (syntax-e #'t))]
[_ (tc-error "not a valid type: ~a" (syntax->datum stx))])))
(define (parse-values-type stx)
(parameterize ([current-orig-stx stx])
(syntax-parse stx
[(values tys ... dty :ddd bound:id)
#:when (eq? (syntax-e #'values) 'values)
(syntax-parse stx #:literals (values t:All)
[(values tys ... dty :ddd bound:id)
(let ([var (lookup (current-tvars) (syntax-e #'bound) (lambda (_) #f))])
(if (not (Dotted? var))
(tc-error/stx #'bound "Used a type variable (~a) not bound with ... as a bound on a ..." (syntax-e #'bound))
@ -581,8 +289,7 @@
(current-tvars))])
(parse-type #'dty))
(syntax-e #'bound))))]
[(values tys ... dty :ddd)
#:when (and (eq? (syntax-e #'values) 'values))
[(values tys ... dty _:ddd)
(add-type-name-reference #'values)
(let ([bounds (filter (compose Dotted? cdr) (env-keys+vals (current-tvars)))])
(when (null? bounds)
@ -597,19 +304,15 @@
(parse-type #'dty))
var)))]
[(values tys ...)
#:when (eq? (syntax-e #'values) 'values)
(-values (map parse-type (syntax->list #'(tys ...))))]
[(All . rest)
#:when (or (eq? (syntax-e #'All) 'All)
(eq? (syntax-e #'All) '))
[(t:All . rest)
(parse-all-type stx parse-values-type)]
[t
(-values (list (parse-type #'t)))])))
(define (parse-tc-results stx)
(syntax-parse stx
(syntax-parse stx #:literals (values)
[(values t ...)
#:when (eq? 'values (syntax-e #'values))
(ret (map parse-type (syntax->list #'(t ...)))
(map (lambda (x) (make-NoFilter)) (syntax->list #'(t ...)))
(map (lambda (x) (make-NoObject)) (syntax->list #'(t ...))))]
@ -618,4 +321,5 @@
(define parse-tc-results/id (parse/id parse-tc-results))
(define parse-type/id (parse/id parse-type))
|#
;(parse-type #'(t:All (A) A t:-> A))