(defmacro our-expander (name) `(get ,name 'expander)) (defmacro pre-defmacro (name parms &body body) (let ((g (gensym))) `(progn (setf (our-expander ',name) #'(lambda (,g) (block ,name (destructuring-bind ,parms (cdr ,g) ,@body)))) ',name))) (defun our-macroexpand-1 (expr) (if (and (consp expr) (our-expander (car expr))) (funcall (our-expander (car expr)) expr) expr)) (defun our-macroexpand (expr) (let ((expanded (our-macroexpand-1 expr))) (if (equal expanded expr) expr (our-macroexpand expanded)))) (defun our-macroexpand-and-eval (expr) (if (and (consp expr) (our-expander (car expr))) (let ((expanded (funcall (our-expander (car expr)) expr))) (eval expanded)) ; Directly evaluate the expanded form (eval expr))) ; If no macro expansion, just evaluate the expression (defmacro our-defmacro (name parms &body body) `(progn (pre-defmacro ,name ,parms ,@body) (defun ,name (&rest args) (our-macroexpand-and-eval (cons ',name args))))) (our-defmacro sq (x) `(* ,x ,x)) (sq 5)
— based on p.95, A MODEL OF MACROS, On Lisp, Paul Graham
— xAI
.
Here, we use the built-in defmacro to define our-defmacro. However, the same process does not work for another level of defining another-defmacro by our-defmacro, because our-defmacro is not identical to defmacro.
— Me@2024-12-09 01:40:02 PM
.
.
2024.12.09 Monday (c) All rights reserved by ACHK