Skip to content
This repository was archived by the owner on Sep 10, 2021. It is now read-only.

Commit 93d0eb8

Browse files
committed
wip typeclasses
1 parent 18c56a1 commit 93d0eb8

9 files changed

Lines changed: 155 additions & 17 deletions

coalton.asd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
(:file "toplevel-declare")
3030
(:file "toplevel-define-type")
3131
(:file "toplevel-define")
32+
(:file "toplevel-define-class")
33+
(:file "toplevel-define-instance")
3234
(:file "coalton")
3335
(:file "faux-macros")
3436
(:file "impl-debug-routines")

src/faux-macros.lisp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
(define-coalton-editor-macro coalton:define-type (name &body definition)
3131
"Create a new algebraic data type named NAME. (Coalton top-level operator.)")
3232

33+
(define-coalton-editor-macro coalton:define-class (name &body definition)
34+
"TODO (Coalton top-level operator.)")
35+
36+
(define-coalton-editor-macro coalton:define-instance (name &body definition)
37+
"TODO (Coalton top-level operator.)")
38+
3339
(define-coalton-editor-macro coalton:declare (var type)
3440
"Declare the type of a variable. (Coalton top-level operator.)")
3541

src/hindley-milner.lisp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,5 +198,3 @@
198198
;; Return the type of the entire expression.
199199
result-ty))))))
200200
(analyze value nil nil)))
201-
202-

src/library.lisp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,30 @@
124124
(define-comparators = /= > < >= <=)
125125
(define-predicates evenp oddp plusp minusp zerop))
126126

127+
128+
#+igno
129+
(coalton-toplevel
130+
(define-class (Eq a)
131+
(== (fn a a -> Boolean)))
132+
133+
;; (fn (Eq a) => a a -> Boolean)
134+
(define (/= a b) (not (== a b)))
135+
136+
(define-instance (Eq Boolean)
137+
(define (== a b)
138+
(or (and a b)
139+
(and (not a) (not b)))))
140+
141+
(define-instance ((Eq a) => (Eq (Maybe a)))
142+
(define (== a b)
143+
(match a
144+
((Just x) (match b
145+
((Just y) (== x y))
146+
(Nothing coalton:False)))
147+
(Nothing (match b
148+
((Just _) coalton:False)
149+
(Nothing coalton:True)))))))
150+
127151
;;; Arithmetic
128152
(coalton-toplevel
129153
(declare + (fn Integer Integer -> Integer))

src/package.lisp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010
#:coalton
1111
#:define
1212
#:define-type-alias
13-
#:define-type)
13+
#:define-type
14+
#:define-class
15+
#:define-instance)
1416
(:export
17+
#:for
18+
#:=>
1519
#:->
1620
#:void
1721
#:integer

src/parse-type.lisp

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,25 @@
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)))))

src/toplevel-define-class.lisp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
;;;; toplevel-define-class.lisp
2+
3+
(in-package #:coalton-impl)
4+
5+
;;; Handling of COALTON:TOPLEVEL-DEFINE-CLASS
6+
7+
(defun process-toplevel-class-definitions (defclass-forms)
8+
nil)

src/toplevel-define-instance.lisp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
;;;; toplevel-define-instance.lisp
2+
3+
(in-package #:coalton-impl)
4+
5+
;;; Handling of COALTON:TOPLEVEL-DEFINE-INSTANCE
6+
7+

src/types.lisp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
(in-package #:coalton-impl)
44

5+
(defstruct (cx (:constructor cx (class variable)))
6+
"A constraint (abbreviated CX), also known as a \"predicate\"."
7+
(class nil :type symbol :read-only t)
8+
(variable nil :type tyvar :read-only t))
9+
510
;;; A type constructor is not a constructor for a value, but a
611
;;; constructor for a *type*! Get with the program!
712
(defstruct tycon
@@ -79,6 +84,11 @@ If NAME is not known, it will be made known to the global type database."
7984
:do (return tycon)
8085
:finally (return nil)))
8186

87+
(defstruct (cty (:constructor make-cty (expr &key constraints)))
88+
"A type with constraints on quantified variables."
89+
(constraints nil :type list :read-only t) ; List of CX
90+
(expr nil :type ty :read-only t))
91+
8292
;;; TY is forward declared in node.lisp
8393

8494
(defstruct (tyvar (:include ty)
@@ -216,9 +226,36 @@ Types are equivalent when the structure (TYAPP and TYFUN) matches and there exis
216226
(or (tyvar-name v)
217227
(setf (tyvar-name v) (gensym "T"))))
218228

229+
(defun extract-variables (ty)
230+
"Extract variables from the type expression TY."
231+
(let ((vars '()))
232+
(labels ((descend (ty)
233+
(etypecase ty
234+
(tyvar
235+
(push ty vars))
236+
237+
(tyapp
238+
(mapc #'descend (tyapp-types ty)))
239+
240+
(tyfun
241+
(mapc #'descend (tyfun-from ty))
242+
(descend (tyfun-to ty))))))
243+
(descend ty))
244+
vars))
245+
219246
(defun unparse-type (ty)
220247
"Convert a type TY back into an S-expression representation (which could be parsed back again with PARSE-TYPE)."
221248
(etypecase ty
249+
;; Constrained types
250+
(cty
251+
`(coalton:for ,@(mapcar #'unparse-type (cty-constraints ty))
252+
coalton:=>
253+
,(unparse-type (cty-expr ty))))
254+
255+
(cx
256+
`(,(cx-class ty) ,(unparse-type (cx-variable ty))))
257+
258+
;; TY substructures
222259
(tyvar
223260
(if (tyvar-instance ty)
224261
(unparse-type (tyvar-instance ty))

0 commit comments

Comments
 (0)