
Load-time problem with a macro that defines a macro
Hello,
I have a problem while using a macro to write another macro: it works well at
compile and eval time, but puzzles me at load time.
The macro I want should be like "defmethod" (in Lucid's flavor system), but
return the name of the created function as *.
(defmethod-flavor toto) creates a macro named "defmethod-toto", and
(defmethod-toto :foo ...) expands as
(Progn (Defmethod (Toto :Foo) ...)
(Identity (Find-Symbol (String-Append "TOTO" "-" "FOO" "-PRIMARY"))))
so it returns "toto-foo-primary" as * (note: I could have written a simpler
"defmethod2" as a single macro, but "defmethod-toto"-like forms were already
used for "historical" reasons)
When defining a flavor, I put the (defmethod-flavor toto) in an
(eval-when (compile load eval)) form, to define the macro before using it.
Here is a "skinned" piece of code:
;;; In a first file "bug1", the global macro, in a general-utility package
;;; The created function is put in the same package and then exported,
;;; to make things clear.
(in-package 'tools)
(export '(defmethod-flavor))
(defmacro defmethod-flavor (flavor)
`(export
(defmacro ,(intern (string-append "DEFMETHOD-" (symbol-name flavor)) 'tools)
(nom args &body body)
(list 'progn
(cons 'flavors::defmethod
(cons (list (quote ,flavor) nom)
(cons args body)))
(list 'identity
(list 'find-symbol
(list 'string-append
,(symbol-name flavor)
"-"
(symbol-name nom)
"-PRIMARY")))))
'tools))
(provide "bug1")
;;; In a second file, how it is used
(in-package 'user)
(use-package 'flavors)
(require "bug1")
(use-package 'tools)
(defflavor toto
(a)
())
(eval-when (compile load eval)
(defmethod-flavor toto))
(defmethod-toto :foo (x)
(+ x a))
[many other "defmethod-toto"s]
;;; end
The result at load time:
Quote:
> (load "bug2")
;;; Loading binary file "bug2.sbin"
;;; Loading binary file "bug1.sbin"
Quote:
>>Error: FASLOAD: When compiled, a symbol named DEFMETHOD-TOTO was inherited
by the "USER" package; but now, no such symbol is accessible.
FASLOAD:
Required arg 0 (FILENAME): #P"/tmp_mnt/home/sinope/dedieu/kb/lisp/bug2.sbin"
Keyword arg 1 (VERBOSE): NIL
Keyword arg 2 (PRINT): NIL
Keyword arg 3 (IF-DOES-NOT-EXIST): :ERROR
Keyword arg 4 (DEFAULT-PATHNAME): ".sbin"
Keyword arg 5 (CODE-AREA): #<Area "Readonly-Non-Pointer-Area" 745EB6>
Keyword arg 6 (PROCEDURE-AREA): #<Area "Readonly-Pointer-Area" 745EEE>
Keyword arg 7 (PROCEDURE-CONTENTS-POINTER-AREA): #<Area "Readonly-Pointer-Area" 745EEE>
Keyword arg 8 (PROCEDURE-CONTENTS-NON-POINTER-AREA): #<Area "Readonly-Non-Pointer-Area" 745EB6>
Keyword arg 9 (SYMBOL-NAME-AREA): #<Area "Readonly-Non-Pointer-Area" 745EB6>
Keyword arg 10 (OTHER-AREA): #<Area "Ephemeral Level 0" 984496>
:C 0: INTERN DEFMETHOD-TOTO into the "USER" package.
:A 1: Abort to Lisp Top Level
-> :c
INTERN DEFMETHOD-TOTO into the "USER" package.
Quote:
>>Error: DEFMETHOD-TOTO cannot be EXPORT'ed in the TOOLS package because it is not
accessible there.
EXPORT:
Required arg 0 (SYMBOLS): (DEFMETHOD-TOTO)
Optional arg 1 (PACKAGE): #<Package "TOOLS" 98451E>
:C 0: Import symbol Defmethod-Toto into the TOOLS package (and then EXPORT it).
:A 1: Abort to Lisp Top Level
-> :c
Import symbol Defmethod-Toto into the TOOLS package (and then EXPORT it).
#P"/tmp_mnt/home/sinope/dedieu/kb/lisp/bug2.sbin"
And then it does as I want (defmethod-toto is the right macro I described,
but is interned in 'user). I used to continue from the errors while loading the
system, but now I'd rather understand why "defmethod-toto" isn't accessible
at load time...
Thanks,
Eric Dedieu