On 10.11.2013. 22:20, Jacob Carlborg wrote: > I've been thinking quite long of how AST macros could look like in D. > I've been posting my vision of AST macros here in the newsgroup a couple > of times already. I've now been asked to create a DIP out of it, so here > it is: > > http://wiki.dlang.org/DIP50 >
I took a look at it as here is my conclusion for now: Statement and attribute macro examples look great. But I don't like Linq example. I don't think code like the following should be allowed. query { from element in array where element > 2 add element to data } >From my point of view this whole idea is great as it makes it easier what is already possible. For example, with current behavior if I wanted to write. foo { writeln("foo"); writeln("foo again"); } I would have to write: mixin(foo!(q{ writeln("foo"); writeln("foo again"); })); So the proposed behavior looks much nicer, and I agree with it as the content of foo block is actually written in D and I think whoever is reading it would be comfortable with it. However, for other, non-D syntax-es I would prefer something like: query q{ from element in array where element > 2 add element to data } Which can be handled by: macro query (Context context, string dsl) { return domainSpecificLanguageToD(dsl); } This in terms is already possible by writing the following, it only allows to be written in a more readable way. And the q{ ... } notation clearly points out that there is something special going on. Also by passing such content as string user can implement custom (or call one of the predefined) tokenizer/lexer/parser. mixin(query!(q{ from element in array where element > 2 add element to data })); I also don't like the <[ ... ]> syntax because: 1. Like others have said, it looks very foreign. 2. I don't think there is a need to add a new syntax. I think that string concatenation is enough (at least for now), and if you want another syntax for templates you can write a macro for that. For example: macro myAssert (Context context, Ast!(bool) val, Ast!(string) str = null) { auto message = str ? "Assertion failure: " ~ str.eval : val.toString(); auto msgExpr = literal(constant(message)); return " if (!" ~ val ~ ") throw new AssertError(" ~ msgExpr ~ "); "; // or return astTemplate q{ if (!$val) throw new AssertError($msgExpr); }; } void main () { myAssert(1 + 2 == 4); } What do you guys think? -- Luka