Macro function call works in the interpreter, failure in the compiler (SBCL + CMUCL)

As suggested in a macro question I recently posted to SO , I encoded a macro called “fast” by calling a function (here is a separate code in pastebin) :

(defun main () (progn (format t "~A~%" (+ 1 2 (* 3 4) (+ 5 (- 8 6)))) (format t "~A~%" (fast (+ 1 2 (* 3 4) (+ 5 (- 8 6))))))) 

This works in REPL, under SBCL and CMUCL:

 $ sbcl This is SBCL 1.0.52, an implementation of ANSI Common Lisp. ... * (load "bug.cl") 22 22 $ 

Unfortunately, the code no longer compiles:

 $ sbcl This is SBCL 1.0.52, an implementation of ANSI Common Lisp. ... * (compile-file "bug.cl") ... ; during macroexpansion of (FAST (+ 1 2 ...)). Use *BREAK-ON-SIGNALS* to ; intercept: ; ; The function COMMON-LISP-USER::CLONE is undefined. 

So, it seems that when I run the macros of the "fast" call functions ("clone", "operation-p") during compilation, I run problems in Lisp compilers (it is checked both in CMUCL and SBCL).

Any ideas on what I'm doing wrong and / or how to fix it?

+2
source share
3 answers

Some notes about your code.

  • several object tests for equality can be replaced with MEMBER

  • backquote with the next comma does nothing. You can just delete it.

  • you can guarantee that your functions are accessible for the macro: a) moving these functions to an additional file and compiling / loading, which before using the macro, by b) using EVAL-WHEN to inform the compiler to evaluate the definition of functions, or c) adding functions to the macro as local functions

Example:

 (defmacro fast (&rest sexpr) (labels ((operation-p (x) (member x '(+ - * /))) (clone (sexpr) (if (consp sexpr) (destructuring-bind (head . tail) sexpr (if (operation-p head) `(the fixnum (,head ,@(clone tail))) (cons (clone head) (clone tail)))) sexpr))) (car (clone sexpr)))) 

Please note that this and your version of FAST are not complete code walkers. They recognize only simple function calls (and not other Lisp constructors such as LAMBDA, LET, FLET, LABELS, etc.).

+4
source

Nothing, I understood: I had to transfer the functions called by the macro (and therefore required during compilation) to a separate file, first “compile the file”, “download”, then “compile-file” with the macro.

+2
source

Macro merging occurs (usually) at compile time.

This means that any functions used when expanding a macro (note, not necessarily in macro expansion, as a return value) must be defined when the macro occurs at compile time.

+1
source

All Articles