Hello
Some questions:
(the first two of those may be rather general scheme philosophy questions)
- why are DSSSL style argument declarations not allowed in define-macro?
- why is there no (define-macro foo (lambda(...)...)) form? Is there a lowlevel variant for setting runtime and compiletime macro bindings to some lambda?
- is there a way to get at the converter lambda from a (runtime-)macro definition?
- I need a way to unset a macro definition, so that the corresponding name can be used as normal function/variable binding from there on.
- I'd like to be able to scan a namespace for all bindings and macro bindings. For example for readline completion. (And to be able to remove all runtime macros.)
- how can I macro-expand code with the original context? Until now I've used
(caddr (##decompile (eval `(lambda() ,code))))
but code is eval'ed in a new lexical context of course. (I haven't understood how to use ##macro-expand. I would be grateful for any help for understanding the sources. How do the cte (=compile-time environment?) and such work? What's the exact concept?)
I want macro expansion for writing macros which expand their arguments before working on them. For playing with optimizations (kind of like optimizing mini-compilers).
- is there a way to preserve the line/column numbering of source code which is "wrapped" by macros? For something like for example (receive (a b) (code1) code2) it would be nice if when an error happens in code1 or code2, the error message didn't just mention the line/column of the opening paren of the receive form, but the line/column where the relevant part of code1 or code2 is in the original file.
Thanks, Christian.
Afficher les réponses par date
On Aug 8, 2005, at 11:00 AM, Christian wrote:
- why are DSSSL style argument declarations not allowed in
define-macro?
You can do this by embedding a procedure that takes DSSSL-style argument declarations inside the macro, like this code from my html library:
(##define-macro (define-tag . args) (let ((internal-define-tag (lambda (tag-name #!key (allow-core-attributes? #t) (end-tag? #t) (start-newline? #f) (end-tag-start-newline? #f) (attributes '()) (single-attributes '())) (let ((core-attributes '(class dir id lang onclick ondblclick onkeydown onkeypress onkeyup onmousedown onmousemove onmouseout onmouseover onmouseup style title))) ;; the maps here are done at compile time, so they are the system map.
(let* ((attributes (if allow-core-attributes? (append attributes core-attributes) attributes)) (attribute-strings (map (lambda (x) (symbol->string x)) attributes)) (attribute-keywords (map (lambda (x) (string->keyword x)) attribute-strings)) (attribute-alist (cons 'list (map (lambda (keyword name) `(cons ,keyword (make-attribute ,name #t #f))) attribute-keywords attribute-strings))) (single-attribute-strings (map (lambda (x) (symbol->string x)) single-attributes)) (single-attribute-keywords (map (lambda (x) (string->keyword x)) single-attribute-strings)) (single-attribute-alist (cons 'list (map (lambda (keyword name) `(cons ,keyword (make-attribute ,name #f #f))) single-attribute-keywords single-attribute-strings))) (form-name (string->symbol (string-append "<" (symbol->string tag-name) ">")))) `(define (,form-name . args) (let ((attribute-alist ,(if (null? attribute-keywords) ''() attribute-alist)) (single-attribute-alist ,(if (null? single-attribute-keywords) ''() single-attribute-alist))) (let ((args (html-parse-args ,(list 'quote form-name) ,end-tag? attribute-alist single-attribute-alist args))) (html-build-form ,(symbol->string tag-name) attribute-alist single-attribute-alist args ,start-newline? ,end-tag-start-newline? ,end-tag?)))))))))
(apply internal-define-tag args)))
Brad
Hello
At 12:54 Uhr -0500 08.08.2005, Bradley Lucier wrote:
On Aug 8, 2005, at 11:00 AM, Christian wrote:
- why are DSSSL style argument declarations not allowed in
define-macro?
You can do this by embedding a procedure that takes DSSSL-style argument declarations inside the macro, like this code from my html library:
Sure, I've actually looked at your html library already (the version which is coming bundled with the web server example with gambit), and smiled when I saw that workaround. But I'm wondering why it's not supported directly.
BTW, I've made some corrections to (that version of) your library and put that up with my latest version of chjmodule on http://scheme.mine.nu/gambit/chjmodule/
Thanks Christian.
On 8-Aug-05, at 12:00 PM, Christian wrote:
Hello
Some questions:
(the first two of those may be rather general scheme philosophy questions)
- why are DSSSL style argument declarations not allowed in
define-macro?
In the upcoming beta 16 this will be allowed (see my next message).
- why is there no (define-macro foo (lambda(...)...)) form? Is there
a lowlevel variant for setting runtime and compiletime macro bindings to some lambda?
I'm not sure I understand. This works fine:
(define-macro when (lambda (x y) `(if ,x ,y))) (when #t 111)
111
(when #f 111)
- is there a way to get at the converter lambda from a (runtime-)macro
definition?
Not pretty, but this works:
(define (macro-converter name)
(cond ((##macro-lookup (##cte-top-cte ##interaction-cte) name) => cdr) (else #f)))
(pp (macro-converter 'when))
(lambda (x y) `(,'if ,@`(,x ,@`(,y ,@'()))))
(macro-converter 'for)
#f
- I need a way to unset a macro definition, so that the corresponding
name can be used as normal function/variable binding from there on.
There is no way to do this currently.
- I'd like to be able to scan a namespace for all bindings and macro
bindings. For example for readline completion. (And to be able to remove all runtime macros.)
Look at the definition of ##cte-lookup in lib/_eval.scm . Just cons- up a list of what is in the compile-time environment.
how can I macro-expand code with the original context? Until now I've used
(caddr (##decompile (eval `(lambda() ,code))))
How about (pp (lambda () code)) ?
but code is eval'ed in a new lexical context of course. (I haven't understood how to use ##macro-expand. I would be grateful for any help for understanding the sources. How do the cte (=compile-time environment?) and such work? What's the exact concept?)
I want macro expansion for writing macros which expand their arguments before working on them. For playing with optimizations (kind of like optimizing mini-compilers).
I understand what you want, but the Gambit interpreter and compiler aren't designed to expand the macros first and then compile the code. The macro expansion and compilation are intertwined. So there is no procedure in the interpreter to only macro expand some code. The closest to what you want really is "eval".
- is there a way to preserve the line/column numbering of source code
which is "wrapped" by macros? For something like for example (receive (a b) (code1) code2) it would be nice if when an error happens in code1 or code2, the error message didn't just mention the line/column of the opening paren of the receive form, but the line/column where the relevant part of code1 or code2 is in the original file.
It is really hard (impossible?) to preserve all source code location information when expanding macros that can perform arbitrary computation (i.e. which is what define-macro provides). Source code location information is preserved by the syntax-case expander. Unfortunately the syntax-case expander that is provided with Gambit is not fully integrated with the system (some of the Gambit syntax extensions are not handled by the syntax-case system).
Marc
At 20:02 Uhr -0500 13.11.2005, Marc Feeley wrote:
On 8-Aug-05, at 12:00 PM, Christian wrote:
- why are DSSSL style argument declarations not allowed in
define-macro?
In the upcoming beta 16 this will be allowed (see my next message).
Thanks.
I'm not sure I understand. This works fine:
(define-macro when (lambda (x y) `(if ,x ,y)))
Yes sorry, that problem was just an artifact of my redefinition of define-macro in chjmodule (I'm redefining it to create both compile-time and runtime macros). I've corrected that bug of mine since (not sure it is in my latest released chjmodule version though).
Not pretty, but this works:
(define (macro-converter name)
(cond ((##macro-lookup (##cte-top-cte ##interaction-cte) name) => cdr) (else #f)))
(pp (macro-converter 'when))
(lambda (x y) `(,'if ,@`(,x ,@`(,y ,@'()))))
(macro-converter 'for)
#f
Thanks! (I don't see what isn't pretty about it.)
- I need a way to unset a macro definition, so that the corresponding
name can be used as normal function/variable binding from there on.
There is no way to do this currently.
For reloading a module into a running gambit system, that is necessary, I think. Or is there a way to only temporarily define macros? (I could fork before compilation, then load the object file into the parent; but what to do for interpreted mode?)
- I'd like to be able to scan a namespace for all bindings and macro
bindings. For example for readline completion. (And to be able to remove all runtime macros.)
Look at the definition of ##cte-lookup in lib/_eval.scm . Just cons- up a list of what is in the compile-time environment.
Thanks, I'll look at it when I have time.
how can I macro-expand code with the original context? Until now I've used
(caddr (##decompile (eval `(lambda() ,code))))
How about (pp (lambda () code)) ?
(I know that pp decompiles functions too (that's how I found out about ##decompile), but I need the code in list form.)
I understand what you want, but the Gambit interpreter and compiler aren't designed to expand the macros first and then compile the code. The macro expansion and compilation are intertwined. So there is no procedure in the interpreter to only macro expand some code. The closest to what you want really is "eval".
Is there an eval to which I could give the current context (as a parameter)?
- is there a way to preserve the line/column numbering of source code
It is really hard (impossible?) to preserve all source code location information when expanding macros that can perform arbitrary computation (i.e. which is what define-macro provides).
I guess these two are old ideas (Is there no solution in any other scheme system?):
- store all parsed atoms in a table as key, with their location as value. Would require symbols to be parsed as uninterned symbols, and eq? to be hacked to make it work without changing coding habits. - or wrapp all atoms in an object with their location (about the approach being taken by syntax-case). Would require all string/symbol/number etc. manipulation functions to be hacked for making it work without changing coding habits.
Would there be hooks for me to play with?
With a good module system, the problem with the necessary code changes might be solvable; and even if it isn't, being able to write location maintaining macros as an option using special syntax (define-macro/locations ...), which executes the transformer with the hooks in place, might be helpful.
Source code location information is preserved by the syntax-case expander. Unfortunately the syntax-case expander that is provided with Gambit is not fully integrated with the system (some of the Gambit syntax extensions are not handled by the syntax-case system).
Yes, unless all of gambit's functionality is supported, it's an unattractive solution. At least I recently noticed how I can get rid of syntax-case again after it has been loaded, without restarting gambit: I'm commenting out the code at the bottom of the provided syntax-case.scm file which sets ##expand-source and c#expand-source, then only temporarily set those when I need syntax-case to be active. (I guess ##expand-source and c#expand-source should actually be parameters, so that they could be changed in a thread-safe way. BTW since that makes it necessary to change all code referring to those bindings, I'm wondering why the parameter idea has been adopted by the scheme community, and not a thread-safe fluid-let solution instead?)
Christian.