Opened 13 years ago

Closed 13 years ago

Last modified 11 years ago

#394 closed enhancement (fixed)

implicit renaming macros

Reported by: sjamaan Owned by: felix winkelmann
Priority: not urgent at all Milestone: 4.9.0
Component: expander Version: 4.6.x
Keywords: ir-macros, reverse, er-macros Cc:
Estimated difficulty:

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.

Attachments (2)

ir-macros.patch (5.6 KB) - added by sjamaan 13 years ago.
Add Implicit Renaming macros to Chicken Core (includes testsuite)
ir-macros-documentation.patch (6.6 KB) - added by sjamaan 13 years ago.

Download all attachments as: .zip

Change History (10)

Changed 13 years ago by sjamaan

Attachment: ir-macros.patch added

Add Implicit Renaming macros to Chicken Core (includes testsuite)

comment:1 Changed 13 years ago by Christian Kellermann

This is a nice idea! +1

comment:2 Changed 13 years ago by felix winkelmann

Resolution: fixed
Status: newclosed

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?

Changed 13 years ago by sjamaan

comment:3 Changed 13 years ago by 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.

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?")

comment:4 Changed 13 years ago by sjamaan

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

comment:5 in reply to:  3 Changed 13 years ago by felix winkelmann

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.

comment:6 Changed 13 years ago by sjamaan

Yeah, that looks fine and is what I was getting at. Thanks!

comment:7 Changed 13 years ago by felix winkelmann

Milestone: 4.7.04.8.0

Milestone 4.7.0 deleted

comment:8 Changed 11 years ago by felix winkelmann

Milestone: 4.8.04.9.0

Milestone 4.8.0 deleted

Note: See TracTickets for help on using tickets.