www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Scala macros

reply bearophile <bearophileHUGS lycos.com> writes:
There are plans of adding macros to Scala language, and I think they are
already partially implemented:

https://docs.google.com/document/d/1O879Iz-567FzVb8kw6N5OBpei9dnbW0ZaT7-XNSa6Cs/edit?hl=en_US


From the article:

<<
Here is a prototypical macro definition:

    def m(x: T): R = macro implRef

At first glance macro definitions are equivalent to normal function
definitions, except for their body, which starts with the conditional keyword
macro and is followed by a possibly qualified identifier that refers to a
static macro implementation method.

If, during type-checking, the compiler encounters an application of the macro
m(args), it will expand that application by invoking the corresponding macro
implementation method, with the abstract-syntax trees of the argument
expressions args as arguments. The result of the macro implementation is
another abstract syntax tree, which will be inlined at the call site and will
be type-checked in turn.


Bye, bearophile
Mar 16 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Mar 16, 2012 at 01:42:51PM -0400, bearophile wrote:
 There are plans of adding macros to Scala language, and I think they are
already partially implemented:
 
 https://docs.google.com/document/d/1O879Iz-567FzVb8kw6N5OBpei9dnbW0ZaT7-XNSa6Cs/edit?hl=en_US
 
 
From the article:

<< Here is a prototypical macro definition: def m(x: T): R = macro implRef At first glance macro definitions are equivalent to normal function definitions, except for their body, which starts with the conditional keyword macro and is followed by a possibly qualified identifier that refers to a static macro implementation method. If, during type-checking, the compiler encounters an application of the macro m(args), it will expand that application by invoking the corresponding macro implementation method, with the abstract-syntax trees of the argument expressions args as arguments. The result of the macro implementation is another abstract syntax tree, which will be inlined at the call site and will be type-checked in turn.

Sounds interesting. Does the macro have direct access to the argument AST's, or is it just a matter of substituing the arguments in various places inside the macro, and then the compiler builds an AST of the macro with argument trees attached and returns that? Having direct access to the argument trees will be much more interesting, but also more difficult to implement if we want to do this in D. We'd have to have a built-in AST tree type, with various types of nodes for various language constructs, etc.. Alternatively, a macro could be a tree-rewriting rule formulated as a tree-pattern that is substituted if the pattern matches. For example: // This is just temporary syntax I cooked up to show the idea: // the "..."'s are literal, and are understood as wildcards. // Something of the form "<ident>..." is an AST subtree // wildcard. Each macro parameter is specified as an AST pattern // enclosed by {}, which is matched against the argument at the // macro invocation site. If there is a match, any "X..." // symbols are assigned the matching AST subtree, which may be // referenced in the body of the macro. The macro body is // substituted into the call site by replacing the AST subtree // there. macro denestLoop({foreach(...) { X... }}) { X } void main() { denestLoop({ foreach (a; b) { f(a); } }); } This causes main() to be rewritten into: void main() { f(a); } Basically, the "..." in the macro parameter list matches "a; b" and the "X..." matches "f(a)"; then the macro constructs a new AST to be substituted into the call site. A more useful example: macro factorize(X...*Y... + X...*Z...) { X*(Y + Z) } void main() { int w,x,y; int result = factorize(w*x + w*y); } Here main() gets rewritten into: void main() { int w,x,y; int result = w*(x+y); } Macros can be made recursive too, by recursively rewriting AST's, so factorize() could, for example, factorize w*x+w*y+w*z by rewriting w*x+w*y into w*(x+y) first, then recursively rewriting w*(x+y)+w*z into w*((x+y)+z). But I haven't thought of a good syntax to express that yet. T -- Любишь кататься - люби и саночки возить.
Mar 16 2012
prev sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
There a different tools for rewriting code out there. Maybe you
can get some inspiration by there syntax.

Examples are:

TXL (www.txl.ca)
Domain Maintenance System (www.semdesigns.com)
Raincode (www.raincode.com)

where the last one probably isn't worth the look.
Mar 17 2012