-
Notifications
You must be signed in to change notification settings - Fork 0
/
syntax.lisp
67 lines (54 loc) · 2.27 KB
/
syntax.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
(defgeneric pattern-vars (pat))
(defmethod pattern-vars ((pat wildcard-pattern))
nil)
(defmethod pattern-vars ((pat var-pattern))
(list (pattern-symbol pat)))
(defmethod pattern-vars ((pat cons-pattern))
(mapcar #'pattern-vars (pattern-args pat)))
(defun normalize-pat (pat)
(typecase pat
(atom
(cond ((eq pat :wildcard) (make-instance 'wildcard-pattern))
((constructorp pat) (make-instance 'cons-pattern :cons pat))
(t (make-instance 'var-pattern :symbol pat))))
(cons
(make-instance 'cons-pattern
:cons (first pat)
:args (mapcar #'normalize-pat (rest pat))))))
(defun normalize-expr (expr)
(typecase expr
(atom
(make-instance (if (constructorp expr) 'cons-expr 'var-expr) :symbol expr))
(cons
(case (first expr)
((let)
(destructuring-bind ((&rest bindings) body) (rest expr)
(make-instance 'let-expr
:bindings (loop for (name val) in bindings
collect (cons name (normalize-expr val)))
:body (normalize-expr body))))
((lambda)
(destructuring-bind ((&rest patterns) body) (rest expr)
(make-instance 'lambda-expr
:formals (mapcar #'normalize-pat patterns)
:body (normalize-expr body))))
(otherwise
(reduce (lambda (f x) (make-instance 'apply-expr :fun f :arg x))
(mapcar #'normalize-expr expr)))))))
(defgeneric denormalize (x))
(defmethod denormalize ((expr symbol-expr))
(expr-symbol expr))
(defmethod denormalize ((expr let-expr))
`(let ,(loop for (name . val) in (expr-bindings expr) collect (list name (denormalize val)))
,(denormalize (expr-body expr))))
(defmethod denormalize ((expr apply-expr))
(list (denormalize (expr-fun expr)) (denormalize (expr-arg expr))))
(defmethod denormalize ((expr lambda-expr))
`(lambda ,(mapcar #'denormalize (expr-formals expr))
,(denormalize (expr-body expr))))
(defmethod denormalize ((pat var-pattern))
(pattern-symbol pat))
(defmethod denormalize ((pat cons-pattern))
(cons (pattern-cons pat) (mapcar #'denormalize (pattern-args pat))))
(defmethod denormalize ((pat wildcard-pattern))
:wildcard)