Hygienic macros and lexical-scoping
Hello! I'm developer of meta-programming system in a new language Nemerle. As we are coming near to implementation of lexical scoping and alpha-renaming in our system, I would like to share some ideas and ask few questions about Haskell Templates' approach to these problems. As I read in 'Template meta-programming in Haskell', the implementation translates [| \x -> $(f [| x |]) |] to do { x <- gensym "x"; lam [Pvar x] (app f (var x) } (I'm not familiar with Haskell, so I may have mistaken some syntax) My question is: when binding of variables is resolved? Is it during translation of quotation, or maybe during expansion of $(...) where the above code is used? After reading the paper, I'm convinced that it's former case. But let's consider: using x val body = [| do { (var x) <- val; body; (var x).Dispose () } |] // x is of type string [| \y -> do { $(using "x" [| x |]); f y |] wouldn't work, and one would have to use gensym by his own to get expected sematics. In our system we are shifting binding of variables from quotation translation to macro expansion phase, so [| x |] can be "catched" inside 'using' meta-function. Resolving of scoping is done after all executions of macros are done. It involves quite complex algorithm to tag variables with place where they come from - we are adapting Dybvig's algorithm into our system, so we could use most flexible convention introduced by Scheme community. Assuming I'm not wrong by now, I also have question, was the other option considered during design of Template Haskell? As we discussed our design, there was some confusion if macros should introduce new definitions into program. I noticed, that in Haskell it is done by special keyword 'splice', and it's forbidden inside quotations. As we decided to resolve names in late phase, we could introduce definitions in arbitrary place. Some questions arise in that case: Let's consider following macros (in Nemerle syntax, as I'm more used to it) using Foo; /// it introduces functions 'blah' and 'bar' variables macro m() { <[ def bar() { 1 } ]> } macro m'() { <[ m(); blah() + bar() ]> } does m'() generate def bar_43 = 1; Foo.blah() + Foo.bar() or def bar_43 () { 1 }; Foo.blah() + bar_43() lexical scoping should theoretically mean the former case, but if we consider function MacroUseSymbol (x : string) - that generates symbol, which will behave as one introduced in macro use site, then latter case is valid. The same function might be used to implement 'using' macro, I've mentioned: macro using (x : string, val, body) { def x = MacroUseSymbol (x); <[ def $(x : var) = $val; $body; $(x : var).Dispose () ]> } My last question is if this approach was considered and what are opinions about introducing this kind of lexial scoping into languages with explicit quoasi-quotations. I can describe our algorithm if anyone is interested (as it is still under discussions). Kamil Skalski Nemerle developer - http://nemerle.org
participants (1)
-
Kamil Skalski