digitalmars.D - feature request: __ARGS__ for logging (cf __FILE__, __LINE__,
- timotheecour (51/51) Feb 01 2013 One of the rare features I miss in C/C++ is stringification macro
- Jacob Carlborg (6/52) Feb 01 2013 Sounds like an ugly hack for AST macros. This is a proposal for AST
- Timon Gehr (3/7) Feb 01 2013 Make sure to include some way to pattern match on the syntax trees.
- Jacob Carlborg (4/6) Feb 01 2013 Why would pattern matching be needed?
- Timon Gehr (2/6) Feb 01 2013 Analysis and rewriting.
- Jacob Carlborg (10/11) Feb 01 2013 I'm just thinking an API similar to a reflection API. Something like:
- Timon Gehr (5/14) Feb 01 2013 I take it you mean syntax sugar for pattern matching? AST macros have
- bearophile (8/11) Feb 01 2013 Maybe Jacob Carlborg is able to show what kind of syntax for
- Jacob Carlborg (4/6) Feb 01 2013 Yeah, more usage examples are always good.
- bearophile (5/5) Feb 01 2013 The reflection they have added to Scala is sometimes used inside
- bearophile (4/4) Feb 02 2013 And then I suggest to put the incomplete proposal for the macros
- Jacob Carlborg (7/9) Feb 02 2013 I'm planning to do that. I was going to work on it a bit more but
- Jacob Carlborg (4/7) Feb 02 2013 "Sometimes", it's rather _required_ to basically do anything useful.
- timotheecour (8/8) Feb 02 2013 seems like my original post regarding __ARGS__ was completely
- Jacob Carlborg (6/13) Feb 03 2013 Sorry about that. I don't think that __ARGS__ is a bad idea, I just
- Jacob Carlborg (5/8) Feb 04 2013 How would a pattern matching feature look like and behave?. I can see if...
- Timon Gehr (14/21) Feb 04 2013 Well, ideally something like
- Jacob Carlborg (7/13) Feb 04 2013 Could you please elaborate how that would be, what the semantics would
- Timon Gehr (4/16) Feb 05 2013 Eg:
- Jacob Carlborg (4/7) Feb 05 2013 How does the matching syntax work, like regular expression?
- Timon Gehr (3/9) Feb 06 2013 Just like pattern matching usually works. '?a' identifiers are matched
- Jacob Carlborg (5/7) Feb 06 2013 I don't know how pattern matching usually works that's why I'm asking.
- dennis luehring (3/15) Feb 06 2013 i think regex (which are by design not nested-able) aren't enough for
- Jacob Carlborg (5/11) Feb 05 2013 When I think about it, it can't look like that. What's passed to a macro...
- Timon Gehr (9/19) Feb 05 2013 I'd prefer if it needn't be.
- Jacob Carlborg (9/17) Feb 05 2013 The whole point of AST macros is that the compiler will do the lexing
- Timon Gehr (6/22) Feb 05 2013 If it's just about lexing and parsing, you need a lexer and a parser,
- Jacob Carlborg (6/13) Feb 05 2013 True.
- dennis luehring (6/16) Feb 02 2013 from the text
- dennis luehring (8/26) Feb 03 2013 i understand that pushing the context und sub-macro is a need
- Jacob Carlborg (8/15) Feb 03 2013 Ast would be a type defined, most likely, by druntime. I'm trying to
- Jacob Carlborg (7/12) Feb 03 2013 One reason is to not have to introduce a new keyword, which in general
- bearophile (11/14) Feb 01 2013 Maybe it's the first serious proposal for D macros I see :-)
- Jacob Carlborg (16/21) Feb 01 2013 That syntax is just an abstract syntax, it does not need to look like
- bearophile (8/18) Feb 01 2013 OK. (I have asked because syntax costs, so it's good to use it as
- Jacob Carlborg (7/13) Feb 01 2013 Yes, that's why I was thinking if we could do like Scala and implement
- Dejan Lekic (8/69) Feb 03 2013 +1
- bearophile (28/31) Feb 03 2013 The Scala-style macros, with enough reflection (plus maybe
- Jacob Carlborg (4/7) Feb 04 2013 I'm not really sure what to do about hygienicy.
- Timon Gehr (2/9) Feb 04 2013 IMO macros should be fully hygienic by default, with opt-out options.
- Jacob Carlborg (7/8) Feb 04 2013 That's the opposite of how the macros in Scala works.
- Timon Gehr (34/40) Feb 05 2013 As far as my understanding goes, quasi-quoting is hygienic, and manual
- Jacob Carlborg (22/37) Feb 05 2013 How would one navigate these scopes. How would one know which one to
- Timon Gehr (8/44) Feb 06 2013 That would be looking it up in scopes[0]. (Nested scopes continue symbol...
- Jacob Carlborg (5/8) Feb 06 2013 It's not clear? We want to be able have a macro referring to utility
- Timon Gehr (7/13) Feb 06 2013 Of course. What I mean by macro closure is the following:
- Timon Gehr (3/19) Feb 06 2013 Actually
- Jacob Carlborg (4/10) Feb 06 2013 Aha, you mean like that, I see.
- Dejan Lekic (8/69) Feb 03 2013 +1
- Dicebot (3/3) Feb 01 2013 .stringof does pretty much the same, but, unfortunately, there is
One of the rare features I miss in C/C++ is stringification macro using "#x": --- #include ... #define DEBUG(x) disp_val(#x,x) template<typename T> void disp_val(const char*name, const T& x) {std::cout << name << "=" << x;} int main(){ DEBUG(1+2); //will print 1+2=3 (and we can add line, file and func info) ASSERT(1+2==4); //can also be defined such that it'll print 1+2==4 failed... } --- In D, we have built-in assert message that'll print the failing expression "1+2==4 failed" in case of failure but that's about it: no further processing can be done on that message, and there's nothing we can do about the DEBUG(1+2) case. I did a function that requires one to write mixin(myDebug("1+2")); but that's not as good, especially because of the quoting that makes most IDE's unaware of the syntax inside (maybe monod would work but still...). However there could be a clean D solution that alleviates need for macros: I'd like to add __ARGS__ to the list of __FILE__, __LINE__, __FUNC___: P1) 1st proposal: __ARGS__ is a string representing the comma separated list of arguments passed: void DEBUG(T,A)(T a, A args=__ARGS__){writeln(args,"=",a);} void DEBUG2(T1,T2,A)(T1 a1,T2 a2, A args=__ARGS__){writeln(args);} DEBUG(1+ 2); //will print "1+ 2=3", ie args="1+ 2" DEBUG(1+ 2, 3*3); //will print "1+ 2,3*3" (ie normalize the comma separation) P2) same but __ARGS__ is string[] with one string per argument; the compiler already did the job of parsing, might as well use it: void DEBUG(T)(T a1, T a2, string[] args=__ARGS__){ writeln(args[0],"=",a1); writeln(args[1],"=",a2); } A question: whether or not to include the first argument in a UFCS/member function call ("hello".fun(1+2) ). P3) additionally, create a __CONTEXT__ that is a struct consisting of __ARGS__,__FILE__, __LINE__, __FUNC___. This has been proposed before and makes even more sense now. Additionally, it could give info on whether the call was UFCS'd or not, etc, information which is lost otherwise (I don't think traits could help distinguish which version was called, a.fun(b) or fun(a,b)).
Feb 01 2013
On 2013-02-01 11:34, timotheecour wrote:One of the rare features I miss in C/C++ is stringification macro using "#x": --- #include ... #define DEBUG(x) disp_val(#x,x) template<typename T> void disp_val(const char*name, const T& x) {std::cout << name << "=" << x;} int main(){ DEBUG(1+2); //will print 1+2=3 (and we can add line, file and func info) ASSERT(1+2==4); //can also be defined such that it'll print 1+2==4 failed... } --- In D, we have built-in assert message that'll print the failing expression "1+2==4 failed" in case of failure but that's about it: no further processing can be done on that message, and there's nothing we can do about the DEBUG(1+2) case. I did a function that requires one to write mixin(myDebug("1+2")); but that's not as good, especially because of the quoting that makes most IDE's unaware of the syntax inside (maybe monod would work but still...). However there could be a clean D solution that alleviates need for macros: I'd like to add __ARGS__ to the list of __FILE__, __LINE__, __FUNC___: P1) 1st proposal: __ARGS__ is a string representing the comma separated list of arguments passed: void DEBUG(T,A)(T a, A args=__ARGS__){writeln(args,"=",a);} void DEBUG2(T1,T2,A)(T1 a1,T2 a2, A args=__ARGS__){writeln(args);} DEBUG(1+ 2); //will print "1+ 2=3", ie args="1+ 2" DEBUG(1+ 2, 3*3); //will print "1+ 2,3*3" (ie normalize the comma separation) P2) same but __ARGS__ is string[] with one string per argument; the compiler already did the job of parsing, might as well use it: void DEBUG(T)(T a1, T a2, string[] args=__ARGS__){ writeln(args[0],"=",a1); writeln(args[1],"=",a2); } A question: whether or not to include the first argument in a UFCS/member function call ("hello".fun(1+2) ). P3) additionally, create a __CONTEXT__ that is a struct consisting of __ARGS__,__FILE__, __LINE__, __FUNC___. This has been proposed before and makes even more sense now. Additionally, it could give info on whether the call was UFCS'd or not, etc, information which is lost otherwise (I don't think traits could help distinguish which version was called, a.fun(b) or fun(a,b)).Sounds like an ugly hack for AST macros. This is a proposal for AST macros I've been working on. It's not finished but here it is: https://dl.dropbox.com/u/18386187/ast_macros.html -- /Jacob Carlborg
Feb 01 2013
On 02/01/2013 11:54 AM, Jacob Carlborg wrote:... Sounds like an ugly hack for AST macros. This is a proposal for AST macros I've been working on. It's not finished but here it is: https://dl.dropbox.com/u/18386187/ast_macros.htmlMake sure to include some way to pattern match on the syntax trees. (Otherwise we are back to manual parsing of the ast.toString() output.)
Feb 01 2013
On 2013-02-01 12:24, Timon Gehr wrote:Make sure to include some way to pattern match on the syntax trees. (Otherwise we are back to manual parsing of the ast.toString() output.)Why would pattern matching be needed? -- /Jacob Carlborg
Feb 01 2013
On 02/01/2013 02:03 PM, Jacob Carlborg wrote:On 2013-02-01 12:24, Timon Gehr wrote:Analysis and rewriting.Make sure to include some way to pattern match on the syntax trees. (Otherwise we are back to manual parsing of the ast.toString() output.)Why would pattern matching be needed?
Feb 01 2013
On 2013-02-01 16:36, Timon Gehr wrote:Analysis and rewriting.I'm just thinking an API similar to a reflection API. Something like: Ast!(Class) c; foreach (Ast!(Member) m ; c.members) { // do something with each member } Sure it would be easier and better looking with pattern matching. -- /Jacob Carlborg
Feb 01 2013
On 02/01/2013 04:54 PM, Jacob Carlborg wrote:On 2013-02-01 16:36, Timon Gehr wrote:Yes, that will work, as long as all necessary information is exposed.Analysis and rewriting.I'm just thinking an API similar to a reflection API. Something like: Ast!(Class) c; foreach (Ast!(Member) m ; c.members) { // do something with each member }Sure it would be easier and better looking with pattern matching.I take it you mean syntax sugar for pattern matching? AST macros have failed if they do not allow a decent library implementation of such functionality. :)
Feb 01 2013
Timon Gehr:I take it you mean syntax sugar for pattern matching? AST macros have failed if they do not allow a decent library implementation of such functionality. :)Maybe Jacob Carlborg is able to show what kind of syntax for pattern matching the macros are able to create (no need to actually implement it now). That document about D macros could use a good list of possible usages (copying something from the Scala site is OK). Bye, bearophile
Feb 01 2013
On 2013-02-01 18:53, bearophile wrote:That document about D macros could use a good list of possible usages (copying something from the Scala site is OK).Yeah, more usage examples are always good. -- /Jacob Carlborg
Feb 01 2013
The reflection they have added to Scala is sometimes used inside Scala macros: http://lampwww.epfl.ch/~michelou/scala/scala-reflection.html Bye, bearophile
Feb 01 2013
And then I suggest to put the incomplete proposal for the macros in Bugzilla o DWiki or even in a DEP. Bye, bearophile
Feb 02 2013
On Saturday, 2 February 2013 at 11:12:18 UTC, bearophile wrote:And then I suggest to put the incomplete proposal for the macros in Bugzilla o DWiki or even in a DEP.I'm planning to do that. I was going to work on it a bit more but now when it's already out in the wild I'll create a DIP. BTW, it's called DIP, as in D Improvement Proposal, not DEP. http://wiki.dlang.org/DIPs -- /Jacob Carlborg
Feb 02 2013
On 2013-02-02 00:58, bearophile wrote:The reflection they have added to Scala is sometimes used inside Scala macros: http://lampwww.epfl.ch/~michelou/scala/scala-reflection.html"Sometimes", it's rather _required_ to basically do anything useful. -- /Jacob Carlborg
Feb 02 2013
seems like my original post regarding __ARGS__ was completely hijacked by the discussion on AST macros (however fruitful and interesting). I agree macros would solve this issue while providing a much more general solution, however, it's very unclear when that would be implemented, surely not anytime soon. Is there any other feedback on introducing __ARGS__ (see first post) besides AST macros being better? It's much simpler implementation-wise.
Feb 02 2013
On 2013-02-03 03:36, timotheecour wrote:seems like my original post regarding __ARGS__ was completely hijacked by the discussion on AST macros (however fruitful and interesting). I agree macros would solve this issue while providing a much more general solution, however, it's very unclear when that would be implemented, surely not anytime soon. Is there any other feedback on introducing __ARGS__ (see first post) besides AST macros being better? It's much simpler implementation-wise.Sorry about that. I don't think that __ARGS__ is a bad idea, I just think that there are several features in D which could be replaced with a library solution using AST macros (if those were available). -- /Jacob Carlborg
Feb 03 2013
On 2013-02-01 18:53, bearophile wrote:Maybe Jacob Carlborg is able to show what kind of syntax for pattern matching the macros are able to create (no need to actually implement it now).How would a pattern matching feature look like and behave?. I can see if that would be possible to implement using the AST macros I'm thinking about. -- /Jacob Carlborg
Feb 04 2013
On 02/04/2013 01:41 PM, Jacob Carlborg wrote:On 2013-02-01 18:53, bearophile wrote:Well, ideally something like ast.match{ 2*(?a) => a+a, (?a)+2 => 2+a, (?e) => e, } The following would be feasible today, hacking around the usual hygiene issues: mixin(match!("ast",q{ 2*(?a) => a+a, (?a)+2 => 2+a, (?e) => e, });Maybe Jacob Carlborg is able to show what kind of syntax for pattern matching the macros are able to create (no need to actually implement it now).How would a pattern matching feature look like and behave?. I can see if that would be possible to implement using the AST macros I'm thinking about.
Feb 04 2013
On 2013-02-05 01:29, Timon Gehr wrote:Well, ideally something like ast.match{ 2*(?a) => a+a, (?a)+2 => 2+a, (?e) => e, }Could you please elaborate how that would be, what the semantics would be. It doesn't look like any pattern matching I've seen in any other languages. For example, which value does it match on? -- /Jacob Carlborg
Feb 04 2013
On 02/05/2013 08:26 AM, Jacob Carlborg wrote:On 2013-02-05 01:29, Timon Gehr wrote:Eg: if ast == <[2*x]>, then the result will be <[x+x]> if ast == <[y+2]>, then the result will be <[2+y]>Well, ideally something like ast.match{ 2*(?a) => a+a, (?a)+2 => 2+a, (?e) => e, }Could you please elaborate how that would be, what the semantics would be. It doesn't look like any pattern matching I've seen in any other languages. For example, which value does it match on?
Feb 05 2013
On 2013-02-05 12:12, Timon Gehr wrote:Eg: if ast == <[2*x]>, then the result will be <[x+x]> if ast == <[y+2]>, then the result will be <[2+y]>How does the matching syntax work, like regular expression? -- /Jacob Carlborg
Feb 05 2013
On 02/06/2013 08:57 AM, Jacob Carlborg wrote:On 2013-02-05 12:12, Timon Gehr wrote:Just like pattern matching usually works. '?a' identifiers are matched to subterms. (This is necessary because 'a' will match a symbol.)Eg: if ast == <[2*x]>, then the result will be <[x+x]> if ast == <[y+2]>, then the result will be <[2+y]>How does the matching syntax work, like regular expression?
Feb 06 2013
On 2013-02-06 13:56, Timon Gehr wrote:Just like pattern matching usually works. '?a' identifiers are matched to subterms. (This is necessary because 'a' will match a symbol.)I don't know how pattern matching usually works that's why I'm asking. But that syntax doesn't look like the ones I've seen, like in Scala. -- /Jacob Carlborg
Feb 06 2013
Am 06.02.2013 13:56, schrieb Timon Gehr:On 02/06/2013 08:57 AM, Jacob Carlborg wrote:i think regex (which are by design not nested-able) aren't enough for AST handling - because there is much nesting in ASTsOn 2013-02-05 12:12, Timon Gehr wrote:Just like pattern matching usually works. '?a' identifiers are matched to subterms. (This is necessary because 'a' will match a symbol.)Eg: if ast == <[2*x]>, then the result will be <[x+x]> if ast == <[y+2]>, then the result will be <[2+y]>How does the matching syntax work, like regular expression?
Feb 06 2013
On 2013-02-05 01:29, Timon Gehr wrote:Well, ideally something like ast.match{ 2*(?a) => a+a, (?a)+2 => 2+a, (?e) => e, }When I think about it, it can't look like that. What's passed to a macro needs to be syntactically valid. -- /Jacob Carlborg
Feb 05 2013
On 02/05/2013 03:14 PM, Jacob Carlborg wrote:On 2013-02-05 01:29, Timon Gehr wrote:I'd prefer if it needn't be. macro match(Context context, Ast ast, string code){ ... if(...) context.error("invalid syntax", code[a..b]); // (slice of code describes exact location where error // is shown to user at the call site.) ... }Well, ideally something like ast.match{ 2*(?a) => a+a, (?a)+2 => 2+a, (?e) => e, }When I think about it, it can't look like that. What's passed to a macro needs to be syntactically valid.
Feb 05 2013
On 2013-02-05 16:24, Timon Gehr wrote:I'd prefer if it needn't be. macro match(Context context, Ast ast, string code){ ... if(...) context.error("invalid syntax", code[a..b]); // (slice of code describes exact location where error // is shown to user at the call site.) ... }The whole point of AST macros is that the compiler will do the lexing and parsing of the code. It will then just return an AST and it's up to the developer of the macro to implement the semantics. If the code is just passed as a string to the macro you would then need to lex and parse in addition to implementing the semantics and we would be no better than the current situation with string mixins. -- /Jacob Carlborg
Feb 05 2013
On 02/05/2013 06:08 PM, Jacob Carlborg wrote:On 2013-02-05 16:24, Timon Gehr wrote:If it's just about lexing and parsing, you need a lexer and a parser, not a macro.I'd prefer if it needn't be. macro match(Context context, Ast ast, string code){ ... if(...) context.error("invalid syntax", code[a..b]); // (slice of code describes exact location where error // is shown to user at the call site.) ... }The whole point of AST macros is that the compiler will do the lexing and parsing of the code. It will then just return an AST and it's up to the developer of the macro to implement the semantics.If the code is just passed as a string to the macroThat's just one option. Not all macros need to add syntax.you would then need to lex and parse in addition to implementing the semanticsIf one chooses to do so. Parser generators can be provided.and we would be no better than the current situation with string mixins.We surely would be better.
Feb 05 2013
On 2013-02-05 18:49, Timon Gehr wrote:If it's just about lexing and parsing, you need a lexer and a parser, not a macro.Yeah, plus some syntax sugar.That's just one option. Not all macros need to add syntax.True.If one chooses to do so. Parser generators can be provided.Yes.-- /Jacob Carlborgand we would be no better than the current situation with string mixins.We surely would be better.
Feb 05 2013
Am 01.02.2013 12:24, schrieb Timon Gehr:On 02/01/2013 11:54 AM, Jacob Carlborg wrote:from the text "...The first parameter of macro is always of the type Context..." is then there a real need for context as an parameter - it semanticly similar to "this" in the class scope - i would prefer a "context" keyword inside of the macro scope... Sounds like an ugly hack for AST macros. This is a proposal for AST macros I've been working on. It's not finished but here it is: https://dl.dropbox.com/u/18386187/ast_macros.htmlMake sure to include some way to pattern match on the syntax trees. (Otherwise we are back to manual parsing of the ast.toString() output.)
Feb 02 2013
Am 03.02.2013 08:15, schrieb dennis luehring:Am 01.02.2013 12:24, schrieb Timon Gehr:i understand that pushing the context und sub-macro is a need but didn't you define a macro-type by alias macro (Ast!(string) str) my_macro and this type can be used by sub-macros like normal typed parameters another question: why Ast! here - can the input any else than a AST? and why not use your $ notation not also here $string?On 02/01/2013 11:54 AM, Jacob Carlborg wrote:from the text "...The first parameter of macro is always of the type Context..." is then there a real need for context as an parameter - it semanticly similar to "this" in the class scope - i would prefer a "context" keyword inside of the macro scope... Sounds like an ugly hack for AST macros. This is a proposal for AST macros I've been working on. It's not finished but here it is: https://dl.dropbox.com/u/18386187/ast_macros.htmlMake sure to include some way to pattern match on the syntax trees. (Otherwise we are back to manual parsing of the ast.toString() output.)
Feb 03 2013
On 2013-02-03 09:44, dennis luehring wrote:i understand that pushing the context und sub-macro is a need but didn't you define a macro-type by alias macro (Ast!(string) str) my_macro and this type can be used by sub-macros like normal typed parametersI'm not sure I understand the above.another question: why Ast! here - can the input any else than a AST? and why not use your $ notation not also here $string?Ast would be a type defined, most likely, by druntime. I'm trying to minimize the syntactic changes needed to implement this feature request. It's not even sure that the $val syntax would be used. Take a look at the "ast" macro. -- /Jacob Carlborg
Feb 03 2013
On 2013-02-03 08:15, dennis luehring wrote:from the text "...The first parameter of macro is always of the type Context..." is then there a real need for context as an parameter - it semanticly similar to "this" in the class scope - i would prefer a "context" keyword inside of the macro scopeOne reason is to not have to introduce a new keyword, which in general is not very popular around here. Note that "macro" keyword is already reserved for future use, just for a feature like this. -- /Jacob Carlborg
Feb 03 2013
Jacob Carlborg:This is a proposal for AST macros I've been working on. It's not finished but here it is: https://dl.dropbox.com/u/18386187/ast_macros.htmlMaybe it's the first serious proposal for D macros I see :-) Is it possible to re-use the <[ ]> syntax (and $...) for other purposes? Have you seen the macros of Scala language? http://scalamacros.org/ Regarding the attribute macros, my main use case for them is to extend the D type system in some ways. How well is such usage supported? Bye, bearophile
Feb 01 2013
On 2013-02-01 15:35, bearophile wrote:Maybe it's the first serious proposal for D macros I see :-) Is it possible to re-use the <[ ]> syntax (and $...) for other purposes?That syntax is just an abstract syntax, it does not need to look like that. I'm thinking we could do something similar to Scala's reify macro. I call this the "ast" macro. Look at the header "The AST Macro". But to answer your question, no. It didn't cross my mind.Have you seen the macros of Scala language? http://scalamacros.org/Yes, this proposal is basically the same as macros in Scala, just adapted the syntax for D.Regarding the attribute macros, my main use case for them is to extend the D type system in some ways. How well is such usage supported?It might be possible, depending on what you want/need. I'm thinking you can do something like this: foo int a; Which is replaced with: Foo!(int) a; It's a different type so depending on how you look at it you could say it affected the type system. -- /Jacob Carlborg
Feb 01 2013
Jacob Carlborg:But to answer your question, no. It didn't cross my mind.OK. (I have asked because syntax costs, so it's good to use it as much as possible, if it doesn't lead to ambiguities).Yes, this proposal is basically the same as macros in Scala, just adapted the syntax for D.I think Scala macros are simple to implement :-)It might be possible, depending on what you want/need. I'm thinking you can do something like this: foo int a; Which is replaced with: Foo!(int) a; It's a different type so depending on how you look at it you could say it affected the type system.I meant something more like (the now closed) Treehydra: https://developer.mozilla.org/en-US/docs/Treehydra_Manual Bye, bearophile
Feb 01 2013
On 2013-02-01 16:55, bearophile wrote:Jacob Carlborg:Yes, that's why I was thinking if we could do like Scala and implement it as in library, as a macro.But to answer your question, no. It didn't cross my mind.OK. (I have asked because syntax costs, so it's good to use it as much as possible, if it doesn't lead to ambiguities).I meant something more like (the now closed) Treehydra: https://developer.mozilla.org/en-US/docs/Treehydra_ManualCould you give a quick, simple and small example of how you would like it to work in pseudo code or D? -- /Jacob Carlborg
Feb 01 2013
Jacob Carlborg wrote:On 2013-02-01 11:34, timotheecour wrote:+1 Jacob, I humbly believe this should be a new DIP ... This proposal, if realised, would bring very useful feature to D... -- Dejan Lekic dejan.lekic (a) gmail.com http://dejan.lekic.orgOne of the rare features I miss in C/C++ is stringification macro using "#x": --- #include ... #define DEBUG(x) disp_val(#x,x) template<typename T> void disp_val(const char*name, const T& x) {std::cout << name << "=" << x;} int main(){ DEBUG(1+2); //will print 1+2=3 (and we can add line, file and func info) ASSERT(1+2==4); //can also be defined such that it'll print 1+2==4 failed... } --- In D, we have built-in assert message that'll print the failing expression "1+2==4 failed" in case of failure but that's about it: no further processing can be done on that message, and there's nothing we can do about the DEBUG(1+2) case. I did a function that requires one to write mixin(myDebug("1+2")); but that's not as good, especially because of the quoting that makes most IDE's unaware of the syntax inside (maybe monod would work but still...). However there could be a clean D solution that alleviates need for macros: I'd like to add __ARGS__ to the list of __FILE__, __LINE__, __FUNC___: P1) 1st proposal: __ARGS__ is a string representing the comma separated list of arguments passed: void DEBUG(T,A)(T a, A args=__ARGS__){writeln(args,"=",a);} void DEBUG2(T1,T2,A)(T1 a1,T2 a2, A args=__ARGS__){writeln(args);} DEBUG(1+ 2); //will print "1+ 2=3", ie args="1+ 2" DEBUG(1+ 2, 3*3); //will print "1+ 2,3*3" (ie normalize the comma separation) P2) same but __ARGS__ is string[] with one string per argument; the compiler already did the job of parsing, might as well use it: void DEBUG(T)(T a1, T a2, string[] args=__ARGS__){ writeln(args[0],"=",a1); writeln(args[1],"=",a2); } A question: whether or not to include the first argument in a UFCS/member function call ("hello".fun(1+2) ). P3) additionally, create a __CONTEXT__ that is a struct consisting of __ARGS__,__FILE__, __LINE__, __FUNC___. This has been proposed before and makes even more sense now. Additionally, it could give info on whether the call was UFCS'd or not, etc, information which is lost otherwise (I don't think traits could help distinguish which version was called, a.fun(b) or fun(a,b)).Sounds like an ugly hack for AST macros. This is a proposal for AST macros I've been working on. It's not finished but here it is: https://dl.dropbox.com/u/18386187/ast_macros.html
Feb 03 2013
Dejan Lekic:Jacob, I humbly believe this should be a new DIP ...I agree.This proposal, if realised, would bring very useful feature to D...The Scala-style macros, with enough reflection (plus maybe pattern matching implemented with the macro themselves) are able to expand the flexibility of D. But macros have some costs. They add complexity to the language, and make code that uses macros less easy to understand. The almost only good place to use macros is in well known and well debugged library code, standard code, like in Phobos. Most D programmers are not going to be able to use macros. If you add macros you create even more the levels of programmers they talk about in Scala: http://www.scala-lang.org/node/8610 One of the most powerful and useful features of CommonLisp (and similar languages) are macros. They add power to the language, but flexibility itself has a high cost. It makes hard for the programmer A to understand and use code written by programmer B. It goes against some of the things that foster the creation of an ecology of reusable modules as in Python and Perl. Too much flexibility is dangerous. Even Scala is risking that with its macros. Lot of programming situations where today Java is used aren't going to use Scala and its macros. Macros are both part of the power of Lisp and one of the causes of its "failure". So it's a matter of balancing things: are macros going to give to D more than the (high) price they ask for? I like AST macros, but I don't know the answer. Bye, bearophile
Feb 03 2013
On 2013-02-03 21:25, Dejan Lekic wrote:+1 Jacob, I humbly believe this should be a new DIP ... This proposal, if realised, would bring very useful feature to D...I'm not really sure what to do about hygienicy. -- /Jacob Carlborg
Feb 04 2013
On 02/04/2013 01:36 PM, Jacob Carlborg wrote:On 2013-02-03 21:25, Dejan Lekic wrote:IMO macros should be fully hygienic by default, with opt-out options.+1 Jacob, I humbly believe this should be a new DIP ... This proposal, if realised, would bring very useful feature to D...I'm not really sure what to do about hygienicy.
Feb 04 2013
On 2013-02-05 01:15, Timon Gehr wrote:IMO macros should be fully hygienic by default, with opt-out options.That's the opposite of how the macros in Scala works. It's quite easy to say if it should be hygienic or not. The hard part is to figure out the details and how to break hygienicy, when there's need for it. -- /Jacob Carlborg
Feb 04 2013
On 02/05/2013 08:28 AM, Jacob Carlborg wrote:On 2013-02-05 01:15, Timon Gehr wrote:As far as my understanding goes, quasi-quoting is hygienic, and manual AST building provides both options.IMO macros should be fully hygienic by default, with opt-out options.That's the opposite of how the macros in Scala works.It's quite easy to say if it should be hygienic or not. The hard part is to figure out the details and how to break hygienicy, when there's need for it.We could provide all nested scopes in an array as part of the context. macro foo(Context context){ return<[ context.scopes[0].x++; context.scopes[1].x++; ]>; } int x = 2; void main(){ int x=0; foo(); assert(x==1 && .x==3); } If manual AST building is supported, it could additionally do something along the following lines: module macros; int x=0; macro foo(Context context){ return SequenceExp( AssignExp(Symbol!x(), Constant(1)), AssignExp(Identifier("x"), Constant(2)), ); } // --- module m; import macros; int x=0; void main(){ foo(); assert(macros.x==1 && x==2); }
Feb 05 2013
On 2013-02-05 12:05, Timon Gehr wrote:As far as my understanding goes, quasi-quoting is hygienic, and manual AST building provides both options.Yes, that's usually how it works.We could provide all nested scopes in an array as part of the context. macro foo(Context context){ return<[ context.scopes[0].x++; context.scopes[1].x++; ]>; } int x = 2; void main(){ int x=0; foo(); assert(x==1 && .x==3); }How would one navigate these scopes. How would one know which one to use? If I recall correctly Nemerle has a way to indicate a symbol should refer to a symbol at the call site which has the closest lexical scope. We would need a way to introduce a new symbol which does not leak outside the macro and another way to explicitly say the symbol is available outside the macro at call site. So if I do something like: int x; macro foo (Context context) { int y; return <[ x++; y++; ]>; } The above would increment "x" and "y" available in the macro context and not refer to any symbols at the call site? -- /Jacob Carlborg
Feb 05 2013
On 02/06/2013 08:48 AM, Jacob Carlborg wrote:On 2013-02-05 12:05, Timon Gehr wrote:That would be looking it up in scopes[0]. (Nested scopes continue symbol lookup in the parent scopes.) The most important cases are scopes[0] and scopes[$-1], the caller scope and the module scope.As far as my understanding goes, quasi-quoting is hygienic, and manual AST building provides both options.Yes, that's usually how it works.We could provide all nested scopes in an array as part of the context. macro foo(Context context){ return<[ context.scopes[0].x++; context.scopes[1].x++; ]>; } int x = 2; void main(){ int x=0; foo(); assert(x==1 && .x==3); }How would one navigate these scopes. How would one know which one to use? If I recall correctly Nemerle has a way to indicate a symbol should refer to a symbol at the call site which has the closest lexical scope.We would need a way to introduce a new symbol which does not leak outside the macro and another way to explicitly say the symbol is available outside the macro at call site. So if I do something like: int x; macro foo (Context context) { int y; return <[ x++; y++; ]>; } The above would increment "x" and "y" available in the macro context and not refer to any symbols at the call site?Yes, but it is not clear yet what macro closures are exactly (Probably it would make sense to inject the closed over declarations at the call site, without adding them to the scope.)
Feb 06 2013
On 2013-02-06 14:05, Timon Gehr wrote:Yes, but it is not clear yet what macro closures are exactly (Probably it would make sense to inject the closed over declarations at the call site, without adding them to the scope.)It's not clear? We want to be able have a macro referring to utility functions and these should be bind at the macro site and not call site. -- /Jacob Carlborg
Feb 06 2013
On 02/06/2013 03:23 PM, Jacob Carlborg wrote:On 2013-02-06 14:05, Timon Gehr wrote:Of course. What I mean by macro closure is the following: Ast foo(){ int x = 0; // a 'closed over' variable return <[x]>; // escaping reference } macro counter(){ return $(foo())++; }Yes, but it is not clear yet what macro closures are exactly (Probably it would make sense to inject the closed over declarations at the call site, without adding them to the scope.)It's not clear? We want to be able have a macro referring to utility functions and these should be bind at the macro site and not call site.
Feb 06 2013
On 02/06/2013 03:57 PM, Timon Gehr wrote:On 02/06/2013 03:23 PM, Jacob Carlborg wrote:Actually macro counter(){ return <[$(foo())++]>; }On 2013-02-06 14:05, Timon Gehr wrote:Of course. What I mean by macro closure is the following: Ast foo(){ int x = 0; // a 'closed over' variable return <[x]>; // escaping reference } macro counter(){ return $(foo())++; }Yes, but it is not clear yet what macro closures are exactly (Probably it would make sense to inject the closed over declarations at the call site, without adding them to the scope.)It's not clear? We want to be able have a macro referring to utility functions and these should be bind at the macro site and not call site.
Feb 06 2013
On 2013-02-06 15:57, Timon Gehr wrote:Of course. What I mean by macro closure is the following: Ast foo(){ int x = 0; // a 'closed over' variable return <[x]>; // escaping reference } macro counter(){ return $(foo())++; }Aha, you mean like that, I see. -- /Jacob Carlborg
Feb 06 2013
Jacob Carlborg wrote:On 2013-02-01 11:34, timotheecour wrote:+1 Jacob, I humbly believe this should be a new DIP ... This proposal, if realised, would bring very useful feature to D... -- Dejan Lekic dejan.lekic (a) gmail.com http://dejan.lekic.orgOne of the rare features I miss in C/C++ is stringification macro using "#x": --- #include ... #define DEBUG(x) disp_val(#x,x) template<typename T> void disp_val(const char*name, const T& x) {std::cout << name << "=" << x;} int main(){ DEBUG(1+2); //will print 1+2=3 (and we can add line, file and func info) ASSERT(1+2==4); //can also be defined such that it'll print 1+2==4 failed... } --- In D, we have built-in assert message that'll print the failing expression "1+2==4 failed" in case of failure but that's about it: no further processing can be done on that message, and there's nothing we can do about the DEBUG(1+2) case. I did a function that requires one to write mixin(myDebug("1+2")); but that's not as good, especially because of the quoting that makes most IDE's unaware of the syntax inside (maybe monod would work but still...). However there could be a clean D solution that alleviates need for macros: I'd like to add __ARGS__ to the list of __FILE__, __LINE__, __FUNC___: P1) 1st proposal: __ARGS__ is a string representing the comma separated list of arguments passed: void DEBUG(T,A)(T a, A args=__ARGS__){writeln(args,"=",a);} void DEBUG2(T1,T2,A)(T1 a1,T2 a2, A args=__ARGS__){writeln(args);} DEBUG(1+ 2); //will print "1+ 2=3", ie args="1+ 2" DEBUG(1+ 2, 3*3); //will print "1+ 2,3*3" (ie normalize the comma separation) P2) same but __ARGS__ is string[] with one string per argument; the compiler already did the job of parsing, might as well use it: void DEBUG(T)(T a1, T a2, string[] args=__ARGS__){ writeln(args[0],"=",a1); writeln(args[1],"=",a2); } A question: whether or not to include the first argument in a UFCS/member function call ("hello".fun(1+2) ). P3) additionally, create a __CONTEXT__ that is a struct consisting of __ARGS__,__FILE__, __LINE__, __FUNC___. This has been proposed before and makes even more sense now. Additionally, it could give info on whether the call was UFCS'd or not, etc, information which is lost otherwise (I don't think traits could help distinguish which version was called, a.fun(b) or fun(a,b)).Sounds like an ugly hack for AST macros. This is a proposal for AST macros I've been working on. It's not finished but here it is: https://dl.dropbox.com/u/18386187/ast_macros.html
Feb 03 2013
.stringof does pretty much the same, but, unfortunately, there is no way to pass an expression to template/function without evaluating it.
Feb 01 2013