From: ········@ifistg.UUCP
Subject: Re: Common Lisp Macro Expander Wanted - (nf)
Date:
Message-ID: <258@ifistg.UUCP>
Here are some functions to expand all macros in a lisp expression. I hope
this will help.
Andreas Girgensohn
·······························@uunet.uu.net
------------------------------- cut here -------------------------------
(defun macroexpand-all (form &optional env)
(setq form (macroexpand form env))
(if (atom form)
form
(case (car form)
((catch if multiple-value-call multiple-value-prog1 progn progv
setq tagbody throw unwind-protect)
(macroexpand-lambda-call form env))
((declare go quote) form)
((block eval-when return-from the)
(let ((body (macroexpand-body (cddr form) env)))
(if (eq body (cddr form)) form (list* (car form) (cadr form) body))))
((flet labels macrolet) (macroexpand-flet form env))
(function (let ((func (macroexpand-lambda (cadr form) env)))
(if (eq func (cadr form)) form (list (car form) func))))
((compiler-let let let*) (macroexpand-let form env))
(t (if (or (consp (car form))
(not (special-form-p (car form))))
(macroexpand-lambda-call form env)
form))))) ; unknown special form
(defun macroexpand-lambda-call (form env)
(let ((func (macroexpand-lambda (car form) env))
(args (macroexpand-body (cdr form) env)))
(if (and (eq func (car form))
(eq args (cdr form)))
form
(cons func args))))
(defun macroexpand-lambda (func env)
(if (atom func)
func
(let ((arglist (macroexpand-lambda-list (cadr func) env))
(body (macroexpand-body (cddr func) env)))
(if (and (eq arglist (cadr func))
(eq body (cddr func)))
func
(list* (car func) arglist body)))))
(defun macroexpand-lambda-list (list env)
env
list)
(defun macroexpand-body (body env)
(if (atom body)
body
(let ((first (macroexpand-all (car body) env))
(rest (macroexpand-body (cdr body) env)))
(if (and (eq first (car body))
(eq rest (cdr body)))
body
(cons first rest)))))
(defun macroexpand-flet (form env)
(let ((fdefs (macroexpand-flet-definitions (cadr form) env))
(body (macroexpand-body (cddr form) env)))
(if (and (eq fdefs (cadr form))
(eq body (cddr form)))
form
(list* (car form) fdefs body))))
(defun macroexpand-flet-definitions (defs env)
(if (atom defs)
defs
(let ((first (macroexpand-lambda (car defs) env))
(rest (macroexpand-flet-definitions (cdr defs) env)))
(if (and (eq first (car defs))
(eq rest (cdr defs)))
defs
(cons first rest)))))
(defun macroexpand-let (form env)
(let ((bdgs (macroexpand-bindings (cadr form) env))
(body (macroexpand-body (cddr form) env)))
(if (and (eq bdgs (cadr form))
(eq body (cddr form)))
form
(list* (car form) bdgs body))))
(defun macroexpand-bindings (bdgs env)
(if (atom bdgs)
bdgs
(let ((first (if (atom (car bdgs))
(car bdgs)
(let ((values (macroexpand-body (cdar bdgs) env)))
(if (eq values (cdar bdgs))
(car bdgs)
(cons (caar bdgs) values)))))
(rest (macroexpand-bindings (cdr bdgs) env)))
(if (and (eq first (car bdgs))
(eq rest (cdr bdgs)))
bdgs
(cons first rest)))))