Expanding Guile macros one step at a time
Published by Arun Isaac on
In other languages: தமிழ்
When debugging Guile macros, sometimes one expansion step is all you need. Here’s a small tool I wrote to scratch that itch.
I’ve always found Guile’s macroexpand confusing and hard to understand. Sometimes, it seems to expand too much—down to the lowest level primitives. That’s not what I want to see when I’m debugging a macro I wrote. All I want to see is an expansion of the first level. So, I wrote me1 (stands for macroexpand-1), and have been using it successfully for a while. Here I share it with you.
(define (me1 x)
(syntax->datum
(syntax-case x ()
((head _ ...)
(and=> (module-variable (current-module)
(syntax->datum #'head))
(compose macro? variable-ref))
((macro-transformer (module-ref (current-module)
(syntax->datum #'head)))
x))
(_ x))))
Here’s a simple or macro definition from the Guile manual.
(define-syntax my-or
(syntax-rules ()
((my-or)
#f)
((my-or exp)
exp)
((my-or exp rest ...)
(let ((t exp))
(if t
t
(my-or rest ...))))))
And here’s how you use me1 on it:
(me1 #'(my-or 1 2 3))
which produces:
(let ((t 1)) (if t t (my-or 2 3)))
Note that me1 takes a syntax object (defined using #' ). And, a caveat: me1 only works with macros defined in the current module.