chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] need help with hygienic macros


From: Jörg F . Wittenberger
Subject: Re: [Chicken-users] need help with hygienic macros
Date: 12 May 2013 18:57:12 +0200

On May 12 2013, Peter Bex wrote:

On Sun, May 12, 2013 at 05:02:46PM +0200, Jörg F. Wittenberger wrote:
Thanks Peter,

but... it doesn't do the trick for me either.

Nevertheless when I follow your advice and pass _ for the unused outer
ellipsis, I still end up with the same problem: "foo" is unbound
in my body...

I have no idea what this macro is attempting to do, but when you
simplify it to the following, you'll see that its expansion doesn't
know about foo:

The idea is to have a definer, `deftig` here, which only abstracts the
argument list of the defined procedure away.  Here a literal of the
original macro (as used in a limited/extended XSLT implementation to be
changed).

(define-macro (define-transformer symbol . body)
 `(define (,symbol
           place
           message
            root-node
           variables
            namespaces
           ancestor
           self-node
           nl
           mode-choice
           proc-chain
           ) . ,body))

The code references those parameters by their name, with all
the downsides of unhygienic macros.

So `deftig` is `define-transformer`.

There is another lengthy macro `xml-walk-down`, which processes it's
argument list a sequence (<keyword> <value> ...), which collects <value>s
of those arguments mentioned as <keyword> and passes them in the correct
position to `proc-chain` to continue the traversal of the xml tree.

To get rid of the predefined-to-be-kept-in-head list of arguments,
I want better macros.  All arguments not changed by keyword to
`xml-walk-down` (which would be `foo` or `gosh` in my example) shall
just use the values from the enclosing `deftig`.  (Let alone that I can
probably sort out keyword-value-pairs from `foo`.)  `gosh` BTW
simulates a macro to access a parameter from the procedure defined
by `deftig`.  I don't mind it being either `gosh` or `(gosh)`; a one-time
change in the source doesn't matter.  BUT the actual argument list
of procedures defined by `deftig` is supposed to change without
touching every use of `deftig`.  Therefore access to those arguments
shall be done by sub-macros (reasonably) available (only) within
the body of `deftig`-defined procedures.

The usage example:

(deftig bar <body>)

would be e.g. (define-transformer xslt:if <body>) in real life.

<body> is arbitrary Scheme code, wherein those "hidden" parameters
are available to for the test-condition and the optional expansion
of the content.

With the original, unhygienic, macro I can just use the parameters
by their name (bewaring of rebound names).

What I want is (foo) - or for that matter (foo x) - withing <body>
to expand to (proc-chain nl) respectively (proc-chain x) eventually.

For this I need some magic in the definition of `deftig`, which will rewrite the <body> to expand occurrences of whatever-syntax-to-be-defined (`foo` and `gosh` here) to access the hidden arguments.

I'm just too much of a newbie wrt. hygienic macros to get that done.

Whatever *I* do, I can watch (by means of some debug code not included here)
the `let-alias` to do it's work in resolving the replacement.
But - as you observed - once my code arrives at the actual <body>
this replacement is no longer effective, leaving `foo` unbound.

Hm. As Goethe wrote: "This letter is quite long, because I'm short on time." Here: "...is quite confusing, because I am."

;-)

/Jörg


(define-syntax deftig
 (syntax-rules ()
   ((_ name body ...)
    (let-syntax
        ((pinapple
          (syntax-rules <...> ()
                        ((_ ((p v) <...>) bdy <...>)
                         (let-syntax ((helper (syntax-rules ()
((_ p <...>) '(begin bdy <...>)))))
                           (helper v <...>))))))
      (pinapple ((foo (x y)) (foog (x y)) (gosh y)) body ...)))))

(deftig bar (foo) (foog 2) (foog 2.5) (let ((n gosh)) (foog n)) 'phar)
=> (begin (foo) (foog 2) (foog 2.5) (let ((n gosh)) (foog n)) (quote phar))

foo really is undefined here.  There's no binding construct that
introduces foo, as far as I can tell.  That's because "p" is not used
anywhere in the expansion.

In the example, helper is defined as:

(syntax-rules ()
 ((_ foo bar) (begin body ...)))

and it is invoked as (helper (x y) (x y) body ...)
You really need to expand to something that defines foo if you wish foo
to be visible.  There's no hygiene problem I can see: all names are fed
into the macro.

Maybe it would help if you could show us an example invocation and
what it should expand to.

Cheers,
Peter




reply via email to

[Prev in Thread] Current Thread [Next in Thread]