4

is there a way to quote an invocation of a reader macro? More specifically, I want to create a macro, that once evaluated, will generate a defclass statement and a respective XML file. Is this possible?

I thought about using #.( ... ) reader macros, but I assume the macro parameters aren't bound for use inside the reader macro. Is this correct?

Therefore, my second thought was to try to generate a statement that included the reader macros, but I'm unsure if there is a way to do that.

Any suggestions on generating XML files when expanding a macro invocation?

Thanks in advance for any ideas.

2 Answers2

4

A "reader macro" and a "macro" are quite different beasts, used to do very different things.

A "reader macro" is usually a function, to start with. They're bound to one (or a specific sequence of two) characters and change how source code is read. They're not about code, but about object creation.

For a "reader macro", there's no obvious definition of what the "macro parameters" would be (apart, possibly, from the sequence of character(s) that caused the reader macro to be invoked in the first place, useful for, as an example, match a ( to a ) when you read a list).

Vatine
  • 20,782
  • 4
  • 54
  • 70
1

Something along the lines of:

(defmacro def-wsdl-class (name (&rest supers)
                           (&rest slots)
                           &rest options)
  `(progn
     (eval-when (:compile-toplevel :execute)
       (with-open-file (xml-file (make-pathname :name (string-capitalize name)
                                                :type "wsdl"
                                                :defaults (or *compile-pathname*
                                                              *load-pathname*))
                                 :direction :output
                                 :if-exists ,(getf options :if-wsdl-exists :error))
         (when xml-file
           (spit-xml xml-file ',name ',supers ',slots ,@options))))
    `(defclass ,name (,@supers)
       (,@slots)
       ,@(chew options)))))

EDIT: To answer your original question, you can't generally (back)quote reader macros. They are executed right where the syntax is read, let's call it read-time. Reader macros don't participate in normal macro expansion, they act before macro expansion.

You could probably create a reader macro that knows it's being called inside a backquote reader macro to play with it, but it would require knowing or changing implementation dependent behaviour of the backquote reader macro.

However, you can return backquoted forms from reader macros.

acelent
  • 7,965
  • 21
  • 39
  • Thanks! That is just what I needed! One question though, by passing :execute to the eval-when, will it also regenerate the XML file when executing? I spent the day researching ASDF, and I think it might be possible to sub-class compile-op in order to generate the XML file, but parsing the source in search of "def-wsdl-class" wouldn't be very easy, and feels a little kludgy. Thanks again for the answer! – Janito Vaqueiro Ferreira Filho Nov 03 '12 at 03:19
  • @JanitoVaqueiroFerreiraFilho, that's the idea. The `:compile-toplevel` tells the compiler that this toplevel form is to be executed at compile-time-too. The lack of `:load-toplevel` tells both the compiler that it may skip its processing (e.g. compilation) and the loader that it must not execute it. The `:execute` tells any code being executed that this too shall be executed. So, a `def-wsdl-class` may appear as a file's toplevel form or in a REPL, and the XML file will be created. When loaded, it won't recreate the file. – acelent Nov 03 '12 at 14:27
  • @JanitoVaqueiroFerreiraFilho, another option could be to use an implementation-dependant `compiler-let`, e.g. `(compiler-let ((*force-xml* (eval-when (:compile-toplevel :execute) :supersede))) (with-open-file ... :if-exists *force-xml*))`. This way, the file gets generated at any time, but at load time it only generates it if it doesn't exist. – acelent Nov 03 '12 at 14:30
  • @JanitoVaqueiroFerreiraFilho, lastly, note that I skipped at least 1 gensym for `xml-file`. – acelent Nov 03 '12 at 14:41