From: David C. <cre...@gm...> - 2008-10-03 09:02:31
|
Hi, I've been having a problem with a utility that I'm writing (it generates scripts for a small scripting language I use quite often).. I've got a macro, with-indent (defmacro with-indent(&rest args) (indent+) `(combine ,@args (indent-))) .. and then I've got the functions it calls (indent+/-, combine, outln and others) below in the same file. Then I have another macro, gen-block (defmacro gen-block2 (block-type name &rest args) "This macro is general enough to create batches and scripts The caller can enclose commands inside these blocks to get correct indenting." `(combine (gen-begin `,(if ,block-type ,block-type "")) ;`,(if ,name ,name "")) (with-indent ,@args) (gen-end `,(if ,block-type ,block-type "")))) Then I have a function gen-drop which uses gen-block which in turn uses with-indent, (defun gen-drop (object-type object-name) "drop an object Important that the table name be quoted in upper case" (let* ((object-to-drop (string-upcase object-name)) (object-drop-string (drop-object-string object-type object-to-drop))) (gen-if (combine "exists" (bracketed (combine (quoted object-type) "," (quoted object-to-drop)))) (with-indent (gen-block2 pasql-batch object-drop-string (out (gen-sql object-drop-string))))))) Unfortunately, when I run my test script which does something like (gen-drop "table" "invoices") I get n: DEFUN GEN-DROP ; (PASQL:WITH-INDENT ; (PASQL:GEN-BLOCK2 PASQL:PASQL-BATCH PASQL::OBJECT-DROP-STRING ; (PASQL:OUT (PASQL:GEN-SQL PASQL::OBJECT-DROP-STRING)))) ; ; caught ERROR: ; (in macroexpansion of (WITH-INDENT (GEN-BLOCK2 PASQL-BATCH OBJECT-DROP-STRING ...))) ; (hint: For more precise location, try *BREAK-ON-SIGNALS*.) ; The function INDENT+ is undefined. ; (PASQL:GEN-IF ; (PASQL:COMBINE "exists" ; (PASQL:BRACKETED ; (PASQL:COMBINE (PASQL:QUOTED PASQL::OBJECT-TYPE) "," ; (PASQL:QUOTED PASQL::OBJECT-TO-DROP)))) ; (PASQL:WITH-INDENT ; (PASQL:GEN-BLOCK2 PASQL:PASQL-BATCH PASQL::OBJECT-DROP-STRING ; (PASQL:OUT (PASQL:GEN-SQL PASQL::OBJECT-DROP-STRING))))) Unfortunately I can't quite work out what is wrong here. I would have thought that when defining macros, one is allowed to use functions that might not yet exist, but I'm having trouble getting it to work. The function (and the macro for that matter) is exported in a package and I have a :use for it at the top of the file. Any clues to what I'm doing wrong here ? I can go as far as posting the source here, but I thought that might be asking a bit much. Any help appreciated. Apologies if this is a newbie CL problem and not something specific to SBCL. Cheers David |
From: Gary K. <gw...@me...> - 2008-10-03 12:34:21
|
Hi David, > I've got a macro, with-indent > > (defmacro with-indent(&rest args) > (indent+) > `(combine ,@args (indent-))) > > .. and then I've got the functions it calls (indent+/-, combine, > outln and > others) below in the same file. Two thoughts: 1. Generally speaking, the code generated by the macro expansion should do _all_ the work. In your with-indent macro, #'indent+ is called at macro-expansion time but then code it outputs won't call it. This may be fine in your case but I think that it would be idiomatic to write (defmacro ... `(progn (indent+) ... (indent-))) 2. I think this is barking up the wrong tree, but just to rule out package problems, try adding package qualifiers to the symbols involved. regards, -- Gary Warren King, metabang.com Cell: (413) 559 8738 Fax: (206) 338-4052 gwkkwg on Skype * garethsan on AIM |