defmacro, 1.2.1

(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