Add syntax for ...
original commit: e29d4eb881b92a7f96ae1bbb248e311f7f8f90bc
This commit is contained in:
parent
9e78ce0847
commit
ed9af8fdfd
|
@ -24,6 +24,10 @@
|
|||
|
||||
(define (stx-cadr stx) (stx-car (stx-cdr stx)))
|
||||
|
||||
;; t is (make-F v)
|
||||
(define-struct Dotted (t))
|
||||
(define-struct (DottedBoth Dotted) ())
|
||||
|
||||
|
||||
(define (parse-type stx)
|
||||
(parameterize ([current-orig-stx stx])
|
||||
|
@ -74,11 +78,28 @@
|
|||
(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 ...))))
|
||||
(symbolic-identifier=? #'::: (quote-syntax *)))
|
||||
(begin
|
||||
(add-type-name-reference #'->)
|
||||
(->* (map parse-type (syntax->list #'(dom ...))) (parse-type #'rest) (parse-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-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)))))))]
|
||||
;; has to be below the previous one
|
||||
[(dom ... -> rng)
|
||||
(eq? (syntax-e #'->) '->)
|
||||
|
@ -129,6 +150,17 @@
|
|||
[(quot t)
|
||||
(eq? (syntax-e #'quot) 'quote)
|
||||
(-val (syntax-e #'t))]
|
||||
[(All (vars ... v dd) t)
|
||||
(and (eq? (syntax-e #'All) 'All)
|
||||
(eq? (syntax-e #'dd) '...)
|
||||
(andmap identifier? (syntax->list #'(v vars ...))))
|
||||
(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)
|
||||
(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)
|
||||
(and (eq? (syntax-e #'All) 'All)
|
||||
(andmap identifier? (syntax->list #'(vars ...))))
|
||||
|
@ -136,7 +168,7 @@
|
|||
[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))))]
|
||||
(make-Poly vars (parse-type #'t))))]
|
||||
[(Opaque p?)
|
||||
(eq? (syntax-e #'Opaque) 'Opaque)
|
||||
(begin
|
||||
|
@ -157,7 +189,12 @@
|
|||
(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))]
|
||||
[(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))
|
||||
=>
|
||||
|
|
|
@ -198,7 +198,7 @@
|
|||
;; use unification to see if we can use the polytype here
|
||||
[(list (Poly: vs b) s)
|
||||
(=> unmatch)
|
||||
(if (unify vs (list b) (list s)) A0 (unmatch))]
|
||||
(if (unify vs (list b) (list s)) A0 (unmatch))]
|
||||
[(list s (Poly: vs b))
|
||||
(=> unmatch)
|
||||
(if (null? (fv b)) (subtype* A0 s b) (unmatch))]
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
[(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" (cons 'values v))]
|
||||
[(Param: in out)
|
||||
(if (equal? in out)
|
||||
|
|
Loading…
Reference in New Issue
Block a user