Path: utzoo!mnetor!uunet!mcvax!unido!ifistg!ffj From: girgenso@ifistg.UUCP Newsgroups: comp.lang.lisp Subject: Re: Common Lisp Macro Expander Wanted - (nf) Message-ID: <258@ifistg.UUCP> Date: 11 Apr 88 10:24:43 GMT Sender: ffj@ifistg.UUCP Lines: 102 Nf-ID: #R:spar:-4900:ifistg:9400005:000:3108 Nf-From: ifistg!girgenso Apr 11 10:51:00 1988 Here are some functions to expand all macros in a lisp expression. I hope this will help. Andreas Girgensohn girgenso%ifistg.uucp%unido.uucp@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)))))