-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmacro.lisp
48 lines (41 loc) · 1.46 KB
/
macro.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
;;;; microlisp.macro: Define and expand macros for MicroLisp code.
(defpackage microlisp.macro
(:use :cl)
(:export :macro
:find-macro
:expand-expression
:expand-expressions))
(in-package :microlisp.macro)
(defmacro macro (name lambda-list &body body)
"Make macro NAME with LAMBDA-LIST and BODY."
`(list ,name
(lambda ,lambda-list ,@body)))
(defun find-macro (name macros)
"Find macro by NAME in MACROS."
(assoc name macros :test #'equal))
(defun find-macro-function (name macros)
"Find macro function by NAME in MACROS."
(second (find-macro name macros)))
(defun expand-expression (expression macros)
"Expand MACROS in EXPRESSION and return expanded expression."
(if (and expression
(listp expression)
(not (eq 'quote (first expression)))) ; QUOTE
(let ((operator (first expression)))
(if (symbolp operator)
(let ((arguments
(expand-expressions (rest expression) macros))
(macro
(find-macro-function (symbol-name operator)
macros)))
(if macro
(expand-expression (apply macro arguments) macros)
(cons operator arguments)))
(expand-expressions expression macros)))
expression))
(defun expand-expressions (expressions macros)
"Expand MACROS in EXPRESSIONS and return expanded expressions."
(when expressions
(let ((rest (rest expressions)))
(cons (expand-expression (first expressions) macros)
(when rest (expand-expressions rest macros))))))