(module parse-type mzscheme
(provide parse-type parse-type/id)
(require (all-except "type-rep.ss" make-arr)
"type-effect-convenience.ss"
(rename "type-effect-convenience.ss" make-arr make-arr*)
"tc-utils.ss"
"union.ss"
(lib "stx.ss" "syntax")
(all-except "type-environments.ss" Void String)
"type-name-env.ss"
(only (lib "list.ss") foldl foldr)
(all-except (lib "list.ss" "srfi" "1") unfold remove)
(lib "plt-match.ss"))
(define enable-mu-parsing (make-parameter #t))
(define (parse-type/id loc datum)
(printf "parse-type/id id : ~a~n ty: ~a~n" (syntax-object->datum loc) (syntax-object->datum stx))
(let* ([stx* (datum->syntax-object loc datum loc loc)])
(parse-type stx*)))
(define (stx-cadr stx) (stx-car (stx-cdr stx)))
(define (parse-type stx)
(parameterize ([current-orig-stx stx])
(syntax-case* stx ()
symbolic-identifier=?
[(fst . rst)
(not (syntax->list #'rst))
(-pair (parse-type #'fst) (parse-type #'rst))]
[(Tuple ts ...)
(eq? (syntax-e #'Tuple) 'Tuple)
(begin
(add-type-name-reference (stx-car stx))
(foldr -pair (-val '()) (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))]
[(dom -> rng : pred-ty)
(and
(eq? (syntax-e #'->) '->)
(eq? (syntax-e #':) ':))
(begin
(add-type-name-reference (stx-cadr stx))
(make-pred-ty (list (parse-type #'dom)) (parse-type #'rng) (parse-type #'pred-ty)))]
[(dom ... rest ::: -> rng)
(and (eq? (syntax-e #'->) '->)
(or (symbolic-identifier=? #'::: (quote-syntax ..))
(symbolic-identifier=? #'::: (quote-syntax ...))))
(begin
(add-type-name-reference #'->)
(->* (map parse-type (syntax->list #'(dom ...))) (parse-type #'rest) (parse-type #'rng)))]
[(dom ... -> rng)
(eq? (syntax-e #'->) '->)
(begin
(add-type-name-reference #'->)
(->* (map parse-type (syntax->list #'(dom ...))) (parse-type #'rng)))]
[(values tys ...)
(eq? (syntax-e #'values) 'values)
(-values (map parse-type (syntax->list #'(tys ...))))]
[(case-lambda tys ...)
(eq? (syntax-e #'case-lambda) 'case-lambda)
(make-Function (map (lambda (ty)
(syntax-case* ty (->) symbolic-identifier=?
[(dom ... -> rng)
(make-arr
(map parse-type (syntax->list #'(dom ...)))
(parse-type #'rng))]))
(syntax->list #'(tys ...))))]
[(case-lambda ([dom ... -> rng] ...)) (make-funty (list (make-arr (list (parse-type #'dom) ...) (parse-type #'rng)) ...))]
[(list-of t) (make-lst (parse-type #'t))]
[(Listof t) (make-lst (parse-type #'t))]
[(Vectorof t)
(eq? (syntax-e #'Vectorof) 'Vectorof)
(begin
(add-type-name-reference #'Vectorof)
(make-Vector (parse-type #'t)))]
[(mu x t)
(and (identifier? #'x)
(eq? (syntax-e #'mu) 'mu)
(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))])
(make-Mu var (parse-type #'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 (vars ...) t)
(and (eq? (syntax-e #'All) 'All)
(andmap identifier? (syntax->list #'(vars ...))))
(let* ([vars (map syntax-e (syntax->list #'(vars ...)))]
[tvars (map make-F vars)])
(add-type-name-reference #'All)
(parameterize ([current-tvars (extend-env vars tvars (current-tvars))])
(make-Poly vars (parse-type #'t))))]
[(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)
(lookup (current-tvars) (syntax-e #'id)
(lambda (key)
(lookup-type-name #'id
(lambda () (display #'id) (newline)(tc-error "unbound type ~a" key)))))]
[(id arg args ...)
(identifier? #'id)
(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-object->datum stx))])))
)