-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparse.lisp
149 lines (139 loc) · 5.18 KB
/
parse.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
(in-package #:sandalphon.types)
(defun parse-type (specifier &optional environment)
(let ((specifier (typexpand specifier environment)))
(etypecase specifier
(symbol (or (specifier-variable specifier environment)
(find-class specifier nil environment)
(error "~a is not a defined type" specifier)))
(cons (let ((special
(specifier-special (car specifier)
environment)))
(if special
(funcall special specifier environment)
(apply (or (specifier-function (car specifier)
environment)
(error
"~a is not a defined type function"
(car specifier)))
(mapcar (rcurry #'parse-type environment)
(rest specifier)))))))))
(defun typexpand-1 (specifier &optional env)
(let ((expander (etypecase specifier
(symbol (specifier-symbol-macro specifier env))
(cons (specifier-macro (first specifier)
env)))))
(if expander
;; could use *macroexpand-hook* later
(values (funcall expander specifier env) t)
(values specifier nil))))
(defun typexpand (specifier &optional env)
(labels ((mux (specifier ever-expanded)
(multiple-value-bind (expansion expanded)
(typexpand-1 specifier env)
(if expanded
(mux expansion t)
(values specifier ever-expanded)))))
(mux specifier nil)))
(defvar *global-type-environment-symbol-macros* nil)
(defvar *global-type-environment-macros* nil)
(defvar *global-type-environment-variables* nil)
(defvar *global-type-environment-functions* nil)
(defvar *global-type-environment-specials* nil)
;; this sucks lol. TODO hash tables?
(defmacro remassocf (alist-place key)
(let ((alist (gensym "ALIST"))
(gensym (gensym "ASSOC")))
`(let* ((,alist ,alist-place)
(,gensym (assoc ,key ,alist)))
(when ,gensym
(setf ,alist-place (remove ,gensym ,alist))))))
(defgeneric specifier-symbol-macro (spec env)
(:argument-precedence-order env spec)
(:method (spec (env null))
(values
(assoc-value *global-type-environment-symbol-macros* spec))))
(defgeneric (setf specifier-symbol-macro) (new spec env)
(:argument-precedence-order env spec new)
(:method ((new null) spec (env null))
(remassocf *global-type-environment-symbol-macros* spec)
nil)
(:method ((new function) spec (env null))
(setf (assoc-value *global-type-environment-symbol-macros*
spec)
new)))
(defgeneric specifier-macro (spec env)
(:argument-precedence-order env spec)
(:method (spec (env null))
(values (assoc-value *global-type-environment-macros* spec))))
(defgeneric (setf specifier-macro) (new spec env)
(:argument-precedence-order env spec new)
(:method ((new function) spec (env null))
(setf (assoc-value *global-type-environment-macros* spec)
new))
(:method ((new null) spec (env null))
(remassocf *global-type-environment-macros* spec)
nil))
(defgeneric specifier-variable (spec env)
(:argument-precedence-order env spec)
(:method (spec (env null))
(values
(assoc-value *global-type-environment-variables* spec))))
(defgeneric (setf specifier-variable) (new spec env)
(:argument-precedence-order env spec new)
(:method ((new type) spec (env null))
(setf (assoc-value *global-type-environment-variables*
spec)
new))
(:method ((new null) spec (env null))
(remassocf *global-type-environment-variables* spec)
nil))
(defgeneric specifier-function (spec env)
(:argument-precedence-order env spec)
(:method (spec (env null))
(values
(assoc-value *global-type-environment-functions* spec))))
(defgeneric (setf specifier-function) (new spec env)
(:argument-precedence-order env spec new)
(:method ((new function) spec (env null))
(setf (assoc-value *global-type-environment-functions*
spec)
new))
(:method ((new null) spec (env null))
(remassocf *global-type-environment-functions* spec)
nil))
(defgeneric specifier-special (spec env)
(:argument-precedence-order env spec)
(:method (spec (env null))
(values
(assoc-value *global-type-environment-specials* spec))))
(defgeneric (setf specifier-special) (new spec env)
(:argument-precedence-order env spec new)
(:method ((new function) spec (env null))
(setf (assoc-value *global-type-environment-specials* spec)
new))
(:method ((new null) spec (env null))
(remassocf *global-type-environment-specials* spec)
nil))
(defmacro deftype-variable (name value)
`(setf (assoc-value *global-type-environment-variables* ',name)
,value))
(defmacro deftype-function (name lambda-list &body body)
`(setf (assoc-value *global-type-environment-functions* ',name)
(lambda ,lambda-list ,@body)))
(defmacro deftype-macro (name lambda-list &body body)
;; FIXME: default *, &whole, &environment
(let ((spec (gensym "SPECIFIER"))
(env (gensym "ENVIRONMENT")))
`(setf (assoc-value *global-type-environment-macros* ',name)
(lambda (,spec ,env)
(declare (ignore ,env))
(destructuring-bind ,lambda-list (cdr ,spec)
,@body)))))
(defmacro deftype-symbol-macro (name expansion)
(let ((spec (gensym "SPECIFIER"))
(env (gensym "ENVIRONMENT")))
`(setf (assoc-value *global-type-environment-symbol-macros*
',name)
(lambda (,spec ,env)
(declare (ignore ,spec ,env))
',expansion))))