44
55; ;; Grammar:
66; ;;
7+ ; ;; <type> := <type alias> ; TODO!
8+ ; ;; | <type expr>
9+ ; ;; | (for <constraint>* => <type expr>)
10+ ; ;;
11+ ; ;; <constraint> := (<class name> <type variable>)
12+ ; ;;
713; ;; <type expr> := <type alias> ; TODO!
814; ;; | <type variable>
915; ;; | <nullary type constructor>
1016; ;; | (fn <type expr>* -> <type-expr>)
1117; ;; | (<type constructor> <type expr>*)
1218
19+ (defun parse-arrow (arrow list &key error )
20+ (let ((arrow-position (position arrow list )))
21+ (when (null arrow-position)
22+ (funcall error ))
23+ (values (subseq list 0 arrow-position)
24+ (subseq list (1+ arrow-position)))))
25+
1326(defun parse-type-expression (whole-expr &key variable-assignments
1427 extra-tycons)
1528 " Parse the type expression WHOLE-EXPR. Return two values:
@@ -42,19 +55,20 @@ EXTRA-TYCONS is a list of tycons that are perhaps not globally defined yet. Thes
4255 (tyapp (find-it expr)))
4356
4457 (parse-function (expr)
45- (let ((arrow (position ' coalton:-> expr)))
46- (when (null arrow)
47- (error-parsing whole-expr " Invalid function type because it lacks an arrow: ~S " expr))
48- (let ((from (subseq expr 1 arrow)) ; exclude FN symbol
49- (to (subseq expr (1+ arrow))))
50- (cond
51- ((null to) (error-parsing whole-expr " Can't have an empty return type in function type: ~S " expr))
52- ((not (null (rest to))) (error-parsing whole-expr " Can't have more than one return type in function type: ~S " expr)))
53- ; ; parse out the input and output types
54- (setf from (mapcar #' parse from))
55- (setf to (parse (first to)))
56- ; ; return the parsed type
57- (tyfun from to))))
58+ (multiple-value-bind (from to)
59+ (parse-arrow ' coalton:-> (rest expr) ; exclude FN symbol
60+ :error (lambda ()
61+ (error-parsing whole-expr " Invalid function type ~
62+ because it lacks an ~
63+ arrow: ~S " expr)))
64+ (cond
65+ ((null to) (error-parsing whole-expr " Can't have an empty return type in function type: ~S " expr))
66+ ((not (null (rest to))) (error-parsing whole-expr " Can't have more than one return type in function type: ~S " expr)))
67+ ; ; parse out the input and output types
68+ (setf from (mapcar #' parse from))
69+ (setf to (parse (first to)))
70+ ; ; return the parsed type
71+ (tyfun from to)))
5872
5973 (parse-application (expr)
6074 (cond
@@ -65,6 +79,10 @@ EXTRA-TYCONS is a list of tycons that are perhaps not globally defined yet. Thes
6579 ; ; New syntax for doing function types.
6680 ((eq ' coalton:fn (first expr)) (parse-function expr))
6781
82+ ; ; Constrained types aren't valid here.
83+ ((eq ' coalton:for (first expr))
84+ (error-parsing whole-expr " Constrained types can't be embedded in a larger type." ))
85+
6886 ; ; Other applications.
6987 (t
7088 (destructuring-bind (tycon &rest args) expr
@@ -77,6 +95,35 @@ EXTRA-TYCONS is a list of tycons that are perhaps not globally defined yet. Thes
7795 (find-it tycon)
7896 (mapcar #' parse args))))))
7997
98+ (parse-constrained-type (expr)
99+ (multiple-value-bind (from to)
100+ (parse-arrow ' coalton:=> (rest expr) ; exclude FOR symbol
101+ :error (lambda ()
102+ (error-parsing whole-expr " Invalid constrained type ~
103+ because it lacks an ~
104+ arrow '=>': ~S " expr)))
105+ (cond
106+ ((null to) (error-parsing whole-expr " Constrained type requires a type to constrain: ~S " expr))
107+ ((not (null (rest to))) (error-parsing whole-expr " Only one type can be constrained: ~S " expr)))
108+
109+ (if (endp from)
110+ (parse (first to))
111+ (make-cty (parse (first to)) :constraints (mapcar #' parse-constraint from)))))
112+
113+ (parse-constraint (constraint)
114+ (unless (and (alexandria :proper-list-p constraint)
115+ (= 2 (length constraint)))
116+ (error-parsing whole-expr " Invalid constraint: ~S " constraint))
117+ (destructuring-bind (class-name-expr variable-expr) constraint
118+ ; ; Check that the class name is a symbol
119+ (unless (symbolp class-name-expr)
120+ (error-parsing whole-expr " Invalud constraint: ~S " constraint))
121+ (let ((class-name class-name-expr)
122+ (var (parse variable-expr)))
123+ (unless (typep var ' tyvar)
124+ (error-parsing whole-expr " Invalid constraint: ~S " constraint))
125+ (cx class-name var))))
126+
80127 (parse (expr)
81128 (typecase expr
82129 ; ; TODO: Allow () for something useful?
@@ -93,5 +140,10 @@ EXTRA-TYCONS is a list of tycons that are perhaps not globally defined yet. Thes
93140
94141 (t
95142 (error-parsing whole-expr " Invalid type expression: ~S " expr)))))
96- (values (parse whole-expr)
143+ ; ; A constrained type can only be at the "top level".
144+ (values (if (and (alexandria :proper-list-p whole-expr)
145+ (not (endp whole-expr))
146+ (eq ' coalton:for (first whole-expr)))
147+ (parse-constrained-type whole-expr)
148+ (parse whole-expr))
97149 (alexandria :hash-table-alist table)))))
0 commit comments