Hi Nils,

Thanks for the link, I hadn't seen that before.  Happily, what you describe
is pretty much exactly what Riddley does, in this case by accessing the
compiler internals.  An example of how macrolet or symbol-macrolet could be
implemented using this is linked above in my response to Konrad.  This
means that macros which rely on the clojure.lang.Compiler$LocalBinding
(which includes [1] and [2]) will still work.  As far as I can tell, this
is not the case in either tools.macro or core.async.

If you know of any ways to make the code-walking more complete, please let
me know.

Zach

[1] https://github.com/ztellman/proteus/blob/master/src/proteus.clj#L60
[2]
https://github.com/flatland/useful/blob/develop/src/flatland/useful/datatypes.clj#L62


On Thu, Sep 5, 2013 at 3:31 AM, bertschi
<nils.bertschin...@googlemail.com>wrote:

> Hi Zach,
>
> you might want to look at this paper explaining how to write a correct
> macroexpand-all (which requires a code walker) in Common Lisp:
> http://www.merl.com/publications/TR1993-017/
>
> The compiler certainly has to do something like that, but might not do all
> of the macroexpansion before starting any compilation as Konrad explained.
> What the compiler needs to do is track the lexical environment while
> walking down the source forms. When a code walker wants to introduce
> additional bindings, such as macrolet (for local macros) or symbol-macrolet
> (for new symbols) it needs to be able to extend the environment
> accordingly. So, you either have to access the compiler internals,
> especially its environment handling, or track the environment yourself (as
> Konrad suggested).
> As an aside: The problem in Common Lisp is mainly that the environment
> handling is not exposed in the standard, thus you cannot write a portable
> code walker without doing some environment handling yourself.
>
> You might also want to look at core.async, which uses a code walker to
> transform go blocks into state machines. I have not (yet) checked its
> restrictions (someone told me, that it cannot even look into anonymous fn
> forms within its body!), but it is generally very hard to write a code
> walker that can handle all special forms (in Common Lisp I don't know any).
>
> +10 for having a library that supports writing correct and (almost)
> complete code walkers
>
> Best,
>
>    Nils
>
> On Thursday, September 5, 2013 12:09:28 PM UTC+2, Konrad Hinsen wrote:
>>
>> Zach Tellman writes:
>>
>>  > I guess I'm confused, then.  You contrast "complete recursive
>>  > expansion" with what the compiler does, and then say it's recursive
>>  > prewalk expansion, which is exactly what the compiler does.  Can
>>  > you clarify the difference between what you're doing and what the
>>  > compiler does?
>>
>> Here's an example:
>>
>>    (defmacro foo [x]
>>      `(list ~x ~x))
>>
>>    (defmacro bar [x]
>>      `[~x ~x])
>>
>> Now let's work on the form
>>
>>    (foo (bar 'baz))
>>
>> Plain macroexpand returns
>>
>>    (list (bar 'baz) (bar 'baz))
>>
>> whereas tools.macro/mexpand-all gives
>>
>>    (list ['baz 'baz] ['baz 'baz])
>>
>> It does this by first calling macroexpand, so foo gets called exactly
>> as during Clojure compilation and returns
>>
>>    (list (bar 'baz) (bar 'baz))
>>
>> mexpand-all then goes through that form and expands the two subforms
>> (bar 'baz).
>>
>> So mexpand-all does exactly what the compiler does, in particular it
>> calls the macros with exactly the same arguments. But the compiler
>> interleaves macro expansion with compilation, so it never gives you
>> access to the fully expanded but uncompiled form which is
>>
>>    (list ['baz 'baz] ['baz 'baz])
>>
>> Konrad
>>
>  --
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/a68aThpvP4o/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to