Summary
implicit renaming macros
Metadata
- Id: b3136d4ec5c695e4b91ad70e5d2012f8dbf97c48
- Trac id: 394
- Type: enhancement
- Reporter: sjamaan
- Owner: felix
- Cc:
- Status: closed
- Component: expander
- Estimated difficulty:
- Resolution: fixed
- Priority: not urgent at all
- Milestone: 4.9.0
- Version: 4.6.x
- Changetime: 2012-09-24 21:47:48 UTC
- Created: 2010-09-21 09:09:19 UTC
- Keywords: ir-macros, reverse, er-macros
Attachments
- b3136d4ec5c695e4b91ad70e5d2012f8dbf97c48/attachments/ir-macros-documentation.patch
- b3136d4ec5c695e4b91ad70e5d2012f8dbf97c48/attachments/ir-macros.patch
Description
From my mail, saved here for later because Felix is too busy right now:
I've decided to pick up an old idea of mine which I got from Alex's post about macros which I think would rock to have in Chicken core. The part where he explains how sc-macro-transformer and rsc-macro-transformer relate to eachother made me think there ought to be a similar "inverse" of er-macro-transformer. Something like "rer-macro-transformer".
The idea is to introduce a new kind of macros called "implicit renaming macros" (or "explicit injection macros", I haven't decided on what's better) where instead of explicitly indicating what you want hygienically renamed (like in er macros), you explicitly indicate where you want to break hygiene. This is a lot like what syntax-case does, except without the cruft ;) -- and without the pattern matching :(
A macro would be much simplified. Here's an side-by-side example taken from the testsuite:
(define-syntax loop | (define-syntax loop
(er-macro-transformer | (ir-macro-transformer
(lambda (x r c) | (lambda (x i c)
(let ((body (cdr x))) | (let ((body (cdr x)))
`(,(r 'call/cc) | `(call/cc
(,(r 'lambda) (exit) | (lambda (,(i 'exit))
(,(r 'let) ,(r 'f) () | (let f ()
,@body (,(r 'f)))))))) | ,@body (f))))))))
As you can see, it's a lot cleaner: only "exit" needs to be "injected" because it requires it to be inserted literally. All the rest is implicitly renamed, just like in syntax-rules. It makes a lot more sense to make the default state of identifiers be hygienic, and breaking the hygiene the exception. It also is easier on the eyes; less comma-splicing/quoting punctuation crap. You can get rid of whole LET-blocks in the typical "rename everything once" idiom.
To make this work, I hacked the er-macro-transformer procedure. The idea is extremely simple:
* You first *fully* rename the input expression by calling RENAME on it * You then run the ER macro transformer as usual. The user renames those expressions he wants to insert _un_hygienically. * You then run the renamer in reverse. This causes all previously renamed identifiers (those in the input expression and the ones that were "renamed" by the user) to be reverted to their original state.
The result is that all non-renamed expressions are the ones that actually are renamed in the final output, while the ones that are renamed are not renamed (a simple inversion of the "renamed" state, so to speak).
It adds a little overhead: one extra up front traversal over the input expression and one extra traversal over the output expression. However, the user needs to do less renaming in the macro itself (only on injection), so not the full two traversals count as "extra overhead", since the lookups would be done in either case (if the macro is properly hygienic).
This is a tradeoff the user is free to decide on for himself. The overhead is not there in case of the original er-macros and my patch doesn't add any overhead to it, either.
Changes and comments
[2010-09-21 09:10:01 UTC] sjamaan attached ir-macros.patch (description=Add Implicit Renaming macros to Chicken Core (includes testsuite))
[2010-09-21 09:37:58 UTC] ckeen wrote:
This is a nice idea! +1
[2010-09-26 09:28:19 UTC] felix changed status from new to closed
[2010-09-26 09:28:19 UTC] felix set resolution to fixed
[2010-09-26 09:28:19 UTC] felix wrote:
I have applied to patch to "experimental", but not built or tested it, yet. Peter, could you write some documentation for this, to be added to `manual/Macros`?
[2010-09-26 18:32:44 UTC] sjamaan attached ir-macros-documentation.patch (description=#f)
[2010-09-26 18:36:40 UTC] sjamaan wrote:
Here's a patch for the manual. I've also added a few words to the ER macro text, as well as fixed a potential bug in the "cond" example (the recursive call to cond wasn't renamed). Since it's a tutorial, we might as well be pedantic. I've added an explanation of this potential bug to the tutorial too.
By the way, what do you think about changing the ER macro examples to explicitly use er-macro-transformer? This would make it a little clearer I think (less people wondering "why do we need to use ir-macro-transformer here but nothing there?")
[2010-09-26 18:37:55 UTC] sjamaan wrote:
PS: I didn't add this to the wiki because I think these docs should only be put there when this code is available in a release
[2010-09-26 22:12:52 UTC] felix wrote:
Replying to sjamaan: > Here's a patch for the manual. I've also added a few words to the ER macro text, as well as fixed a potential bug in the "cond" example (the recursive call to cond wasn't renamed). Since it's a tutorial, we might as well be pedantic. I've added an explanation of this potential bug to the tutorial too.
Patch applied - thanks, Peter.
> > By the way, what do you think about changing the ER macro examples to explicitly use er-macro-transformer? This would make it a little clearer I think (less people wondering "why do we need to use ir-macro-transformer here but nothing there?")
Yes, good point. I have changed the examples accordingly - perhaps you could verify that it what you suggested.
[2010-09-26 22:16:49 UTC] sjamaan wrote:
Yeah, that looks fine and is what I was getting at. Thanks!
[2011-06-01 09:00:41 UTC] felix changed milestone from 4.7.0 to 4.8.0
[2011-06-01 09:00:41 UTC] felix wrote:
Milestone 4.7.0 deleted
[2012-09-24 21:47:48 UTC] felix changed milestone from 4.8.0 to 4.9.0
[2012-09-24 21:47:48 UTC] felix wrote:
Milestone 4.8.0 deleted