digitalmars.D - DIP 50 - AST macros
- Jacob Carlborg (7/7) Nov 10 2013 I've been thinking quite long of how AST macros could look like in D.
- bearophile (5/6) Nov 10 2013 I suggest to add some more use cases (possibly with their
- Rob T (6/12) Nov 10 2013 A scalable and elegant solution to the "inspection" problem may
- Timothee Cour (3/19) Nov 10 2013 <[ .. ]> syntax looks very foreign. How about m{...} (with q{...} as a
- Jacob Carlborg (7/9) Nov 10 2013 As the DIP says, that just one suggestion of the syntax. If we even need...
- Jacob Carlborg (5/9) Nov 10 2013 Please, feel free to add it as an example, if your interested. After
- Jacob Carlborg (9/12) Nov 10 2013 I could try and do that. The problem is I have not given much though on
- simendsjo (27/33) Nov 11 2013 I agree examples would help a lot. Trying to define what
- Jacob Carlborg (14/39) Nov 11 2013 I can tell you right now that I haven't figured out everything, far from...
- dennis luehring (2/38) Nov 11 2013 can you add the example to the DIP?
- bearophile (5/6) Nov 10 2013 It's also useful to take a look at what F# is doing:
- Jacob Carlborg (5/7) Nov 10 2013 I'll do that. I've been looking at several languages, mainly Scala. But
- Andrei Alexandrescu (4/9) Nov 11 2013 There is significant regret about the way macros are defined in Scala.
- deadalnix (6/17) Nov 11 2013 Do you have some article/documentation on that ?
- Rob T (5/17) Nov 11 2013 Knowing what went wrong is important so as not to repeat past
- Andrei Alexandrescu (5/21) Nov 11 2013 Not yet. Martin mentioned to me in 2012 he doesn't think they took the
- deadalnix (4/8) Nov 11 2013 Loosely related, but worth watching :
- Jacob Carlborg (5/7) Nov 11 2013 Unfortunately it's not easy to do anything about it if you cannot give
- jerro (4/7) Nov 12 2013 Not an example to follow, but it would definitely
- Timothee Cour (9/15) Nov 10 2013 People have shunned proposals to have @mixin functions because it wouldn...
- Timon Gehr (2/6) Nov 10 2013 macros are hygienic.
- Jacob Carlborg (4/12) Nov 10 2013 I would really prefer if we not had to do that.
- Dicebot (3/14) Nov 11 2013 If macros are supposed to access outer scope, I agree, this is a
- Timon Gehr (4/18) Nov 11 2013 I don't agree. (The argument against implicit mixin features was a
- Dicebot (4/7) Nov 11 2013 How would you expect it to be hygienic in any way if it has
- Timon Gehr (15/21) Nov 11 2013 With mixins _every_ identifier is by _default_ inserted/looked up in the...
- Timon Gehr (2/3) Nov 11 2013 simply
- Jacob Carlborg (4/7) Nov 11 2013 The macros system need to provide both hygienic and non-hygienic macros.
- Shammah Chancellor (5/11) Nov 10 2013 Not a huge fan of the syntax, but I think it's a step in the right
- Shammah Chancellor (8/22) Nov 10 2013 I think this would gain a lot more traction if someone wrote an
- Jacob Carlborg (5/7) Nov 10 2013 To you mean the <[ ]> syntax or something else? See my reply to Timothee...
- Rikki Cattermole (42/47) Nov 10 2013 One of our targets for AST macros should be the ability to
- Jacob Carlborg (13/53) Nov 11 2013 Absolutely. One of my favorite examples is the database query:
- Rikki Cattermole (32/99) Nov 11 2013 Theres a few other things I think would need to be cleared up.
- Jacob Carlborg (11/39) Nov 11 2013 They way I see that is the AST of the whole block would be passed to
- Rikki Cattermole (34/85) Nov 11 2013 An example of this might be:
- Jacob Carlborg (12/45) Nov 11 2013 My idea of handling errors in macros is more something like triggering a...
- Rikki Cattermole (12/68) Nov 11 2013 For errors I was thinking a new pragma.
- Jacob Carlborg (7/18) Nov 11 2013 I like the context parameter better. I'm imagine the context parameter
- Rikki Cattermole (8/25) Nov 11 2013 I can understand wanting to have a high level version of it in
- Jacob Carlborg (5/12) Nov 11 2013 I think we want to have as much as possible of this collected in the
- Rikki Cattermole (6/22) Nov 11 2013 Yes I do agree with that. I'm just more worried about what backs
- Jacob Carlborg (9/14) Nov 11 2013 A function call on the context parameter as I've already showed. This
- Rikki Cattermole (9/16) Nov 11 2013 Ok pragmas essentially call functions like error in the compiler
- Jacob Carlborg (5/12) Nov 11 2013 Yes, I still don't understand why you would want it as a pragma. Be
- Rikki Cattermole (13/15) Nov 11 2013 Yes outside of macros would be useful. For example code like this
- Jacob Carlborg (5/17) Nov 11 2013 I just don't want to add a bunch of pragmas. I don't know what's the
- Rikki Cattermole (21/23) Nov 11 2013 I am only suggesting one :)
- Jacob Carlborg (6/26) Nov 11 2013 I wouldn't say no to this if macros are completely off the table.
- Rikki Cattermole (7/11) Nov 11 2013 I'm not doing one for warnings. See how the error one goes. The
- Jacob Carlborg (9/14) Nov 11 2013 Yes, but I want warnings to be available in the context parameter as
- Rikki Cattermole (3/14) Nov 11 2013 Ah ok, I'll see what I can drum up in that regard then. I guess I
- dennis luehring (8/23) Nov 11 2013 but in macros the context information is much more interesting then
- Rikki Cattermole (6/11) Nov 11 2013 Jacob mentioned originally he wanted to create a compiler error.
- Jacob Carlborg (14/18) Nov 11 2013 "error" would be just a single function that is available in the context...
- Rikki Cattermole (3/22) Nov 11 2013 Is there anything specific for info that I should look at? or
- Jacob Carlborg (4/6) Nov 11 2013 Sorry, I don't understand what you're meaning.
- Timon Gehr (3/5) Nov 11 2013 "error" should also be able to specify where the error occurred in the
- Jacob Carlborg (4/6) Nov 11 2013 That's a good point.
- Timon Gehr (2/8) Nov 11 2013 static assert(0, "Support for x is not implemented on platform y");
- Rikki Cattermole (4/17) Nov 11 2013 Hmm wasn't aware of that syntax. Needs an example I think on docs.
- bearophile (12/18) Nov 11 2013 Can't you do the same thing with functions similar (same API but
- simendsjo (11/32) Nov 11 2013 The problem here is that a library need to know that it has to
- Jacob Carlborg (8/17) Nov 11 2013 This particular example would work. "e" would be a proxy which
- Jacob Carlborg (10/14) Nov 11 2013 I have been thinking about that, a solution where "e" is a proxy that
- dennis luehring (1/17) Nov 11 2013 could you add the example to the DIP wiki page
- Rikki Cattermole (4/25) Nov 11 2013 Adding use case section with Linq example.
- Timothee Cour (14/41) Nov 11 2013 I would really like to use AST macros for the following use case:
- Rikki Cattermole (11/60) Nov 11 2013 Perhaps an alternative would be:
- Jacob Carlborg (5/17) Nov 11 2013 Agree. That's the first example in the DIP. Although a very simplified
- Timothee Cour (11/30) Nov 11 2013 yes, I think your initial example becomes more interesting with this, as...
- Jacob Carlborg (7/17) Nov 11 2013 The current example prints out the exact expression what was passed to
- Rikki Cattermole (5/8) Nov 11 2013 I made a suggestion regarding a macro able to get scoped
- Jacob Carlborg (5/9) Nov 11 2013 I already have an example with the assert (not among the use cases but
- Rikki Cattermole (14/16) Nov 11 2013 I was referring to the use case as to why we should have the
- Jacob Carlborg (5/18) Nov 11 2013 Ok, I see. Please add additional examples to the DIP if you think it's
- Timothee Cour (4/25) Nov 11 2013 I'm using a modified assert that uses the ugly import(file)[line] trick,...
- Jacob Carlborg (4/7) Nov 11 2013 Right, that ugly trick :)
- luka8088 (2/9) Nov 11 2013 Thumbs up!
- Jacob Carlborg (4/5) Nov 11 2013 Thanks.
- Dejan Lekic (4/9) Nov 11 2013 I like it, Jacob. With or without <[ ]> it is a good proposal,
- Jacob Carlborg (4/7) Nov 11 2013 Thank you.
- Dmitry Olshansky (19/24) Nov 11 2013 I have to say I like it.
- Jacob Carlborg (34/50) Nov 11 2013 Ok, I can change that.
- Marco Leise (6/12) Nov 11 2013 Wow, some topics really explode recently. Is the D user base
- Chris Cain (6/8) Nov 11 2013 I'd like to say both. AST macros are one of those few things that
- Jacob Carlborg (5/7) Nov 11 2013 AST macros are drawing so much attension. For some, it's like the holy
- bearophile (11/13) Nov 11 2013 That's a bad approach to technology design. You first need to
- Dicebot (9/14) Nov 11 2013 I don't have time to investigate this in details but I'd like to
- deadalnix (2/18) Nov 11 2013 Can you stop reading my mind, please ?
- Ellery Newcomer (17/22) Nov 11 2013 For macros that generate macros, I think you need a way to escape the
- Jacob Carlborg (4/20) Nov 11 2013 This would require some thought.
- deadalnix (4/33) Nov 11 2013 $ refers to the enclosing scope. so $$foo should refers to $foo
- Ellery Newcomer (3/40) Nov 11 2013 so if I have to splice my ast N times, then I have to generate M $'s
- Jesse Phillips (7/12) Nov 11 2013 Just a quick comment related to the 2007 proposal:
- Walter Bright (49/53) Nov 12 2013 I confess I have some serious reservations about AST macros in general:
- Walter Bright (5/5) Nov 12 2013 I forgot to mention that "expression templates" can be used in D in an
- Walter Bright (6/11) Nov 12 2013 Here's a project to add Linq support to C++:
- Jacob Carlborg (5/10) Nov 13 2013 Again, operator overloading in D is too limiting to implement something
- Walter Bright (3/4) Nov 13 2013 Ok, let's set aside the opEquals and opCmp issue for the moment.
- Don (14/19) Nov 13 2013 With an expression template you still can't create a statement.
- Walter Bright (6/25) Nov 13 2013 Actually, there is a way to do this. I wrote an article years back on ho...
- Walter Bright (65/68) Nov 13 2013 Ah, found the code:
- Timon Gehr (5/12) Nov 13 2013 int foo(int x){
- Walter Bright (2/16) Nov 13 2013 This approach definitely hews to the single-entry/single-exit paradigm.
- deadalnix (6/76) Nov 13 2013 Was is missing is the capability to look into the lazy
- Walter Bright (4/8) Nov 13 2013 That's correct. But you can look into the AST with expression templates....
- deadalnix (4/15) Nov 13 2013 Expression templates are limited to expression and require to use
- Walter Bright (9/23) Nov 13 2013 Yes. But that's a good thing. I'd be pretty skeptical of the value of an...
- deadalnix (7/13) Nov 13 2013 My very first project in D involved quite a lot of them. So I
- Walter Bright (7/11) Nov 13 2013 My question about that is just what problem is this trying to solve, and...
- deadalnix (19/34) Nov 13 2013 I think the whole point of macro is to NOT add too much feature
- Jacob Carlborg (35/51) Nov 13 2013 Unfortunately I don't think we will have a feature freeze from now until...
- dennis luehring (2/55) Nov 13 2013 perfect for the DIP example section - more of these please :)
- Jacob Carlborg (4/5) Nov 14 2013 Done: http://wiki.dlang.org/DIP50#C.2B.2B_Namespaces_.28issue_7961.29
- dennis luehring (4/7) Nov 14 2013 it would be also nice to have (always) an (if possible) string mixin
- Walter Bright (8/21) Nov 14 2013 I agree that async/await has to eventually be added to D. I'm not convin...
- dennis luehring (6/10) Nov 14 2013 the same was said about templates AND string mixins before - but
- Walter Bright (2/9) Nov 14 2013 I don't buy that these are analogous. They are very different features.
- Chris Cain (11/13) Nov 14 2013 Out of curiousity, how would that be implemented without macros?
- deadalnix (2/16) Nov 14 2013 async await do not create parallelism.
- Walter Bright (3/5) Nov 14 2013 Again, I reiterate what experience shows happens with macro systems in t...
- Andrei Alexandrescu (20/25) Nov 14 2013 FWIW Walter talked me back around 2005-2006 into abandoning my own ideas...
- Jacob Carlborg (6/17) Nov 14 2013 AST macros cannot change the syntax or introduce new syntax. C
- Walter Bright (8/11) Nov 14 2013 If it is powerful enough to do async/await but look like normal D syntax...
- dennis luehring (2/4) Nov 14 2013 same can be said about Boost Spirit templates
- Jacob Carlborg (7/9) Nov 14 2013 I don't think so. The idea is to have it look consistent within the
- Walter Bright (5/12) Nov 17 2013 Think about the desired feature mentioned earlier in this thread of bein...
- Jacob Carlborg (5/9) Nov 17 2013 I'm not entirely sure what you're saying. Could you please post a link
- =?UTF-8?B?U2ltZW4gS2rDpnLDpXM=?= (7/13) Nov 17 2013 I believe it is basically this:
- deadalnix (2/20) Nov 17 2013 That never was in the DIP.
- Walter Bright (3/38) Nov 17 2013 It was this by Timon Gehr essentially posting why lazy parameters weren'...
- Timon Gehr (3/20) Nov 17 2013 This code was just supposed to demonstrate that ifthen is not actually a...
- Walter Bright (2/4) Nov 17 2013 Ok, my apologies.
- deadalnix (4/22) Nov 17 2013 As I understand it, Timon choosed that syntax simply to
- Walter Bright (3/5) Nov 17 2013 Ok, then I'm not seeing what AST macros do that lazy parameters / templa...
- deadalnix (5/12) Nov 17 2013 2 things. First, they can act on statement or declaration. Simply
- Walter Bright (4/15) Nov 18 2013 If they can insert a statement or a declaration uplevel, then they are d...
- deadalnix (2/23) Nov 18 2013 *Expression* templates.
- luka8088 (18/22) Nov 19 2013 Well, this is just a small piece of the puzzle but I would like to be
- Jacob Carlborg (4/10) Nov 18 2013 I see, I guess that should work with with the DIP.
- Dicebot (8/12) Nov 17 2013 You do realize that, as per more strict proposal, it won't change
- Rob T (17/17) Nov 17 2013 Walter,
- deadalnix (6/38) Nov 14 2013 This is not proposing to configure syntax.
- Walter Bright (23/24) Nov 14 2013 Right, it is about inserting arbitrarily different meaning into existing...
- H. S. Teoh (9/22) Nov 14 2013 [...]
- Walter Bright (2/3) Nov 17 2013 That would be better, but I don't think enough better.
- Jacob Carlborg (6/7) Nov 17 2013 Then why to we have UDA's with the same syntax as language attributes
- Walter Bright (6/11) Nov 17 2013 1. I don't believe we can decide on language features by analogy. D is c...
- Jacob Carlborg (7/13) Nov 18 2013 You can turn this:
- Timon Gehr (4/16) Nov 18 2013 Well, you could do:
- Jacob Carlborg (5/8) Nov 18 2013 Sure, what I'm saying is that you can do stupid things with other
- Walter Bright (32/34) Nov 18 2013 Yes, you can write terrible code with all features.
- IgorStepanov (12/54) Nov 18 2013 How macros implemented in C#?
- Kapps (10/23) Nov 18 2013 C# doesn't have macros. Linq to Sql is implemented using
- IgorStepanov (19/46) Nov 18 2013 May be this way is good for D? And CTFE allow to parse this tree
- Jacob Carlborg (5/23) Nov 18 2013 The idea is to have something more general. Linq is just one example of
- Ellery Newcomer (3/6) Nov 19 2013 Sure it can. Generate lambda expression tree; invoke Compile(). You just...
- Doodoo (7/22) Nov 18 2013 Now, now Walter, that is C not C++. In C++ we would use Boost
- Dicebot (4/7) Nov 18 2013 Anything that allows it routinely should be banned whenever
- Jacob Carlborg (6/8) Nov 18 2013 The whole point of macros is to modify symbols. Turning this:
- Dicebot (6/13) Nov 18 2013 You don't need to modify actual input lambda for this to become
- Timon Gehr (2/17) Nov 18 2013 So you oppose macro attributes?
- Dicebot (6/7) Nov 19 2013 Yes. For me proper "macro attribute" is just an UDA that can be
- Yota (17/24) Nov 19 2013 This topic really took off. I'm afraid to say that I've only
- SomeDude (2/20) Nov 18 2013 And that's exactly the kind of thing Walter doesn't want to see.
- Jacob Carlborg (5/9) Nov 18 2013 Well, it depends on how you look at it. You don't need to modify the
- Dicebot (19/21) Nov 19 2013 Not really. You won't say that this snippet changes the meaning
- Jacob Carlborg (4/15) Nov 19 2013 No, I guess not.
- Walter Bright (4/16) Nov 18 2013 That is not at all what I was talking about. I was talking about:
- Doodoo (1/1) Nov 17 2013 HS Teoh why u always gotta go and break the forum
- Dicebot (7/10) Nov 14 2013 This is exactly the reason why I have been asking to make
- Zsombor Barna (16/49) Nov 14 2013 You have a point with the example, but just as with templates (
- deadalnix (23/46) Nov 14 2013 Yes, but EXPLICITELY.
- SomeDude (13/16) Nov 17 2013 True but you will hardly use myfunction as an extension to the
- Jacob Carlborg (7/17) Nov 17 2013 We already have templates and operator overloading. Perhaps we should
- Walter Bright (7/8) Nov 17 2013 True, but you also cannot argue that since D has string mixins it must a...
- Zsombor Barna (5/15) Nov 17 2013 Yeah, you are right, but I doubt anybody would use macros in
- Zsombor Barna (8/40) Nov 14 2013 D's syntax remains the same ( statements, expressions, function
- SomeDude (10/16) Nov 17 2013 Which shows all the problems raised by Walter:
- Rob T (39/48) Nov 14 2013 On Thursday, 14 November 2013 at 18:23:20 UTC, Andrei
- Meta (5/12) Nov 14 2013 What kind of macro systems are you talking about? C-like macros?
- Walter Bright (2/5) Nov 14 2013 See my first comment in this thread - it's an ancestor to this one.
- Jacob Carlborg (6/9) Nov 13 2013 You can still do stupid things like that with operator overloading. Not
- Walter Bright (4/11) Nov 14 2013 Sure, but the issue is that expression templates are not for "int+int", ...
- dennis luehring (3/16) Nov 14 2013 "int + int" could be part of an PC<->GPU kombination that generates
- dennis luehring (3/20) Nov 14 2013 or like Don Blade Engine with string mixins
- Walter Bright (2/23) Nov 14 2013 Good example, but still quite doable using type T instead.
- deadalnix (3/8) Nov 13 2013 Yes, they can reflect the ast provided and act accordingly.
- Walter Bright (3/12) Nov 13 2013 The reflection ability is not something specific to an AST, it could be ...
- deadalnix (4/7) Nov 13 2013 Yes, that is why Dicebot was mentioning the parallel with compile
- Jacob Carlborg (9/12) Nov 13 2013 Yes, I been thinking of ways to expand __traits. When there's enough of
- Walter Bright (2/11) Nov 14 2013 No, but then you're face with the issue of where those structs are defin...
- Jacob Carlborg (4/5) Nov 14 2013 In druntime, just like MouldeInfo, TypeInfo and similar classes.
- Jacob Carlborg (4/6) Nov 13 2013 I need to read up on what expression templates can do.
- Rob T (6/7) Nov 13 2013 But where to read? There's no such thing as "expression template"
- Walter Bright (3/5) Nov 13 2013 This may help:
- Jacob Carlborg (5/10) Nov 13 2013 I guess everything about C++ expression templates would be a start.
- Don (20/22) Nov 12 2013 They are crippled compared to C++, because you have no control
- Rob T (20/43) Nov 12 2013 My personal main need for macros at this point, is to make up for
- Jacob Carlborg (4/23) Nov 13 2013 --
- Joseph Cassman (50/77) Nov 12 2013 After using string mixins for a while I have come to feel much
- Jacob Carlborg (23/55) Nov 13 2013 If we got macros we should really have a good way to debug them. At
- Walter Bright (7/13) Nov 12 2013 It is limiting, but I don't know about extremely limiting. Eric Anderton...
- Jacob Carlborg (6/12) Nov 13 2013 I don't know what's so special about the regex engine. It takes a regex
- Walter Bright (3/15) Nov 13 2013 What's special about it was its use of expression templates. It made for...
- Jacob Carlborg (5/7) Nov 13 2013 Is there an actual point in doing that, except a nice exercise in
- Walter Bright (3/8) Nov 13 2013 It actually generated a very fast regex engine, though Dmitry's work has...
- Jacob Carlborg (4/6) Nov 13 2013 Right, a specially tuned engine for that particular regex.
- Wyatt (6/11) Nov 12 2013 Regarding this point, I get that arbitrary expansion is out, but
- Jacob Carlborg (13/21) Nov 12 2013 I was actually not the one that added the Linq examples. I like the
- John Colvin (6/9) Nov 12 2013 for those of us entirely unfamiliar with linq, what is this
- Dicebot (4/8) Nov 12 2013 I don't know much about linq but in macro context I'd expect it
- Jacob Carlborg (5/8) Nov 13 2013 Exactly, spot on. The interesting thing there, in the context of macros,...
- Ellery Newcomer (11/22) Nov 12 2013 linq provides an interface to query any collection, but what is
- John Colvin (9/37) Nov 12 2013 oh, I see. Would AST macros really be enough to make this work in
- Ellery Newcomer (24/66) Nov 12 2013 Actually,
- =?ISO-8859-15?Q?Simen_Kj=E6r=E5s?= (34/39) Nov 13 2013 It's perfectly possible in D to make this work:
- Ellery Newcomer (6/11) Nov 13 2013 hey, cool impl
- =?UTF-8?B?U2ltZW4gS2rDpnLDpXM=?= (14/27) Nov 17 2013 I decided to abandon sanity. Luckily, only for the named parameters. I
- deadalnix (2/35) Nov 17 2013 That is a really cool idea !
- Ellery Newcomer (31/32) Nov 17 2013 I suppose you'd have to do something like
- Jacob Carlborg (6/27) Nov 18 2013 That works with the Rails plugin Squeel. Although you need to prefix
- Timon Gehr (2/13) Nov 17 2013 Still missing overload resolution. :o)
- =?UTF-8?B?U2ltZW4gS2rDpnLDpXM=?= (4/23) Nov 17 2013 Please don't tempt me. :p
- Philippe Sigaud (18/19) Nov 17 2013 Nice ideas. I particularly like this one:
- Jacob Carlborg (5/7) Nov 18 2013 Wouldn't that be enum instead:
- Jacob Carlborg (15/21) Nov 13 2013 Person.where(e => e.name == "John")
- luka8088 (13/40) Nov 13 2013 What about something like this?
- dennis luehring (2/7) Nov 13 2013 it is not generic - and that is the biggest goal to reach
- Jacob Carlborg (4/16) Nov 13 2013 That's basically what would happen.
- luka8088 (4/26) Nov 13 2013 May/Should I add such example to wiki?
- Jacob Carlborg (4/5) Nov 13 2013 Yes, "should". Sure, add it to the DIP.
- Chris Nicholson-Sauls (6/13) Nov 13 2013 Is this in any way better than the basic Ruby
- Jacob Carlborg (8/12) Nov 13 2013 It was mostly to show what happens when the you have limited
- Andrei Alexandrescu (7/10) Nov 12 2013 Maybe the problem needs to be reformulated for D. I think an SQL mixin
- Dicebot (9/15) Nov 12 2013 It does not matter that much if it is macro or mixin. Key feature
- Andrei Alexandrescu (5/14) Nov 12 2013 I don't see how AST reflection is needed for generating correct D code
- Dicebot (6/9) Nov 12 2013 Other way around. Generating arbitrary output (including but not
- Andrei Alexandrescu (5/14) Nov 12 2013 Yah. That I agree with. That's why I said we should reformulate the
- Dicebot (12/22) Nov 12 2013 I had an impression it was exactly the context in which linq was
- Jacob Carlborg (5/8) Nov 13 2013 My example is a DSL:
- deadalnix (50/55) Nov 12 2013 The thing I'd like to be able to do it to create a
- Martin Nowak (2/4) Nov 12 2013 That's a prime example for AST macros.
- Zsombor Barna (57/62) Nov 12 2013 First of all: I haven't used macros extensively yet. Its merely a
- Jacob Carlborg (4/6) Nov 13 2013 Please add this as an example to the DIP.
- Dmitry Olshansky (15/23) Nov 12 2013 Actually I couldn't shake off the feeling that macros are just CTFE
- Dicebot (7/14) Nov 12 2013 Add there "foo.codeof" in the toolset and it will pretty much
- Dmitry Olshansky (23/40) Nov 13 2013 For me it feels a lot like implementing something as a soft-core or
- Martin Nowak (2/4) Nov 13 2013 Well, codeof is nice but it lacks the parser.
- Jacob Carlborg (6/7) Nov 13 2013 Yes, and the you need to mixin it again. Several unnecessary steps, see
- Philippe Sigaud (11/19) Nov 12 2013 Which you still have to mixin, btw. Which means any tree manipulation
- Jacob Carlborg (6/16) Nov 13 2013 It would be at compile time with macros anyway. The DIP even says that
- Jacob Carlborg (9/21) Nov 13 2013 You would still need to do strign mixin. Which results in a some
- Martin Nowak (2/5) Nov 13 2013 Right, that's the basic functionality we want.
- Jacob Carlborg (9/11) Nov 14 2013 That's what the reflection API is for. I guess many people here know a
- dennis luehring (5/10) Nov 12 2013 "actually better than Linq" good statement without knowing it deep
- Andrei Alexandrescu (3/13) Nov 12 2013 Yah, it was an exaggeration. Linq is very powerful.
- Rikki Cattermole (14/28) Nov 12 2013 I was using linq as an example of what we could do with this DIP
- Jacob Carlborg (9/13) Nov 13 2013 The idea of that example is, as Dicebot said, to convert the AST of the
- Regan Heath (24/35) Nov 13 2013 Linq is often confused with LinqToSQL, the above was a description of wh...
- dennis luehring (4/14) Nov 13 2013 linq allows construction AND querying of non table-like hierarchical
- dennis luehring (5/20) Nov 13 2013 but linq isn't good in graph operations like neo4j
- Jacob Carlborg (7/12) Nov 13 2013 My original example was not Linq. I tried to make it look as much as
- Martin Nowak (8/31) Nov 12 2013 Yes, this is a big issue.
- Jacob Carlborg (28/69) Nov 13 2013 DSL's are so popular so many languages are specifically designed to make...
- Dejan Lekic (3/9) Nov 14 2013 Metaprogramming (almost) does the same. At least that is my
- Martin Nowak (2/7) Nov 12 2013 Thanks, looks like an insightful discussion.
- luka8088 (69/76) Nov 13 2013 I took a look at it as here is my conclusion for now:
- Rikki Cattermole (25/69) Nov 13 2013 Currently this would be sent as a string. I have suggested
- Jacob Carlborg (7/13) Nov 13 2013 All macro invocations are already checked. They're lexed and parsed.
- Jacob Carlborg (22/70) Nov 13 2013 I'm not a fan of the Linq example either. Or rather if I put it like
- luka8088 (42/49) Nov 19 2013 Oh, I see. It seems that I indeed missed the point.
- Jacob Carlborg (9/41) Nov 19 2013 So you don't like that it's not a "mixin" there with AST macros?
- luka8088 (21/79) Nov 19 2013 Well, do think about that :)
- Jacob Carlborg (12/24) Nov 20 2013 Using the Rails plugin, which I've got this idea from, I would not make
- luka8088 (23/57) Nov 20 2013 Ok, I see. Yes, I tried to think of a case where this could not work but
- Jacob Carlborg (5/25) Nov 20 2013 So how is this different except for my proposal, except the use of q{}
- luka8088 (11/41) Nov 21 2013 When using q{} compiler treats the contents as a regular string, and you
- Jacob Carlborg (4/14) Nov 21 2013 Sorry, I meant your original suggestion of using t{}.
- luka8088 (4/21) Nov 22 2013 Um, my it's suppose to be the same as <[ ... ]> but I liked t{ ... }
- Jacob Carlborg (4/7) Nov 22 2013 I thought you argued that the t{ } need to contain semantically valid co...
- luka8088 (12/20) Nov 22 2013 Yes. I still do. And I think that <[ ... ]> should contain semantically
- Jacob Carlborg (15/34) Nov 23 2013 Then q{ } or <[ ]> would be very limited. Not even templets need
- luka8088 (18/43) Nov 23 2013 I don't think so. What I was proposing is to split the problem into
- luka8088 (17/26) Nov 22 2013 What we currently have:
- Jacob Carlborg (6/7) Nov 22 2013 I should have been t{ }. I do understand the difference between t{ } and...
- luka8088 (2/10) Nov 22 2013 Yes. t{ } and <[ ]> are the same.
- Dmitry Olshansky (14/24) Nov 13 2013 Actually even now it's can be just
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 -- /Jacob Carlborg
Nov 10 2013
Jacob Carlborg:http://wiki.dlang.org/DIP50I suggest to add some more use cases (possibly with their implementation). Bye, bearophile
Nov 10 2013
On Sunday, 10 November 2013 at 22:33:34 UTC, bearophile wrote:Jacob Carlborg:A scalable and elegant solution to the "inspection" problem may be a AST use case. Discussed here: http://forum.dlang.org/thread/qconpedgdkyeawmdzect forum.dlang.org --rthttp://wiki.dlang.org/DIP50I suggest to add some more use cases (possibly with their implementation). Bye, bearophile
Nov 10 2013
<[ .. ]> syntax looks very foreign. How about m{...} (with q{...} as a precedent)? On Sun, Nov 10, 2013 at 5:08 PM, Rob T <alanb ucora.com> wrote:On Sunday, 10 November 2013 at 22:33:34 UTC, bearophile wrote:Jacob Carlborg: http://wiki.dlang.org/DIP50A scalable and elegant solution to the "inspection" problem may be a AST use case. Discussed here: http://forum.dlang.org/thread/qconpedgdkyeawmdzect forum.dlang.org --rtI suggest to add some more use cases (possibly with their implementation). Bye, bearophile
Nov 10 2013
On 2013-11-11 02:40, Timothee Cour wrote:<[ .. ]> syntax looks very foreign. How about m{...} (with q{...} as a precedent)?As the DIP says, that just one suggestion of the syntax. If we even need a syntax. An alternative, without any new syntax is the "ast" macro: http://wiki.dlang.org/DIP50#The_AST_Macro This is similar to the "refiy" macro in Scala. -- /Jacob Carlborg
Nov 10 2013
On 2013-11-11 02:08, Rob T wrote:A scalable and elegant solution to the "inspection" problem may be a AST use case. Discussed here: http://forum.dlang.org/thread/qconpedgdkyeawmdzect forum.dlang.orgPlease, feel free to add it as an example, if your interested. After all, it is a wiki. -- /Jacob Carlborg
Nov 10 2013
On 2013-11-10 23:33, bearophile wrote:Jacob Carlborg:I could try and do that. The problem is I have not given much though on how the reflection API and the API used to build syntax trees should look like. If this get any serious interest and we start to think about the implementation I was hoping that someone we more experience could help out with designing the API. -- /Jacob Carlborghttp://wiki.dlang.org/DIP50I suggest to add some more use cases (possibly with their implementation).
Nov 10 2013
On Sunday, 10 November 2013 at 22:33:34 UTC, bearophile wrote:Jacob Carlborg:I agree examples would help a lot. Trying to define what information actually exists within these types would also help a lot. In the first example, would Ast!(bool) be something like this? opBinary!"==" left = opBinary!"+" left = Literal type = int value = 1 right = Literal type = int value = 2 right = Literal type = int value = 4 Would there be helpers for matching part of the structure? The same applies to the other types used - what information should they have? As for examples, here's a couple of suggestions: * Expression to prefix notation * Expression to SQL * Number intervals, like "int i = int[10..20];" where only 10 to 20 are legal values * Discriminated union * Pattern matchinghttp://wiki.dlang.org/DIP50I suggest to add some more use cases (possibly with their implementation). Bye, bearophile
Nov 11 2013
On 2013-11-11 09:28, simendsjo wrote:I agree examples would help a lot. Trying to define what information actually exists within these types would also help a lot.I can tell you right now that I haven't figured out everything, far from everything.In the first example, would Ast!(bool) be something like this? opBinary!"==" left = opBinary!"+" left = Literal type = int value = 1 right = Literal type = int value = 2 right = Literal type = int value = 4 Would there be helpers for matching part of the structure?I don't know. As I said above, I haven't figured out everything. I don't see any support for this in the language. But of course, there can be library functions that help with this.The same applies to the other types used - what information should they have?Suggestions are welcome. Also, see my reply to bearophile http://forum.dlang.org/thread/l5otb1$1dhi$1 digitalmars.com#post-l5q1p5:242bs4:241:40digitalmars.comAs for examples, here's a couple of suggestions: * Expression to prefix notation * Expression to SQLWould that be something like the attribute macro example? http://wiki.dlang.org/DIP50#Attribute_macros* Number intervals, like "int i = int[10..20];" where only 10 to 20 are legal values * Discriminated union * Pattern matchingPattern matching usually requires new syntax, which this proposal does not support. -- /Jacob Carlborg
Nov 11 2013
Am 11.11.2013 09:28, schrieb simendsjo:On Sunday, 10 November 2013 at 22:33:34 UTC, bearophile wrote:can you add the example to the DIP?Jacob Carlborg:I agree examples would help a lot. Trying to define what information actually exists within these types would also help a lot. In the first example, would Ast!(bool) be something like this? opBinary!"==" left = opBinary!"+" left = Literal type = int value = 1 right = Literal type = int value = 2 right = Literal type = int value = 4 Would there be helpers for matching part of the structure? The same applies to the other types used - what information should they have? As for examples, here's a couple of suggestions: * Expression to prefix notation * Expression to SQL * Number intervals, like "int i = int[10..20];" where only 10 to 20 are legal values * Discriminated union * Pattern matchinghttp://wiki.dlang.org/DIP50I suggest to add some more use cases (possibly with their implementation). Bye, bearophile
Nov 11 2013
Jacob Carlborg:http://wiki.dlang.org/DIP50http://tomasp.net/blog/2013/computation-zoo-padl/index.html Bye, bearophile
Nov 10 2013
On 2013-11-11 02:46, bearophile wrote:http://tomasp.net/blog/2013/computation-zoo-padl/index.htmlI'll do that. I've been looking at several languages, mainly Scala. But -- /Jacob Carlborg
Nov 10 2013
On 11/10/13 11:46 PM, Jacob Carlborg wrote:On 2013-11-11 02:46, bearophile wrote:There is significant regret about the way macros are defined in Scala. Probably not an example to follow. Andreihttp://tomasp.net/blog/2013/computation-zoo-padl/index.htmlI'll do that. I've been looking at several languages, mainly Scala. But
Nov 11 2013
On Tuesday, 12 November 2013 at 02:37:03 UTC, Andrei Alexandrescu wrote:On 11/10/13 11:46 PM, Jacob Carlborg wrote:Do you have some article/documentation on that ? BTW, scala implemented macros as a plugin called macro paradise, which allowed people to play with it without crippling the core language. We should probably introduce new features that way.On 2013-11-11 02:46, bearophile wrote:There is significant regret about the way macros are defined in Scala. Probably not an example to follow.http://tomasp.net/blog/2013/computation-zoo-padl/index.htmlI'll do that. I've been looking at several languages, mainly Scala. But
Nov 11 2013
On Tuesday, 12 November 2013 at 02:37:03 UTC, Andrei Alexandrescu wrote:On 11/10/13 11:46 PM, Jacob Carlborg wrote:Knowing what went wrong is important so as not to repeat past mistakes, is there more info somewhere to read on what went wrong? --rtOn 2013-11-11 02:46, bearophile wrote:There is significant regret about the way macros are defined in Scala. Probably not an example to follow. Andreihttp://tomasp.net/blog/2013/computation-zoo-padl/index.htmlI'll do that. I've been looking at several languages, mainly Scala. But
Nov 11 2013
On 11/11/13 9:16 PM, Rob T wrote:On Tuesday, 12 November 2013 at 02:37:03 UTC, Andrei Alexandrescu wrote:Not yet. Martin mentioned to me in 2012 he doesn't think they took the right turns with defining macros. I don't know whether more information is available at the moment. AndreiOn 11/10/13 11:46 PM, Jacob Carlborg wrote:Knowing what went wrong is important so as not to repeat past mistakes, is there more info somewhere to read on what went wrong?On 2013-11-11 02:46, bearophile wrote:There is significant regret about the way macros are defined in Scala. Probably not an example to follow. Andreihttp://tomasp.net/blog/2013/computation-zoo-padl/index.htmlI'll do that. I've been looking at several languages, mainly Scala. But
Nov 11 2013
On Tuesday, 12 November 2013 at 05:59:46 UTC, Andrei Alexandrescu wrote:Not yet. Martin mentioned to me in 2012 he doesn't think they took the right turns with defining macros. I don't know whether more information is available at the moment. AndreiLoosely related, but worth watching : http://www.infoq.com/presentations/data-types-issues
Nov 11 2013
On 2013-11-12 03:37, Andrei Alexandrescu wrote:There is significant regret about the way macros are defined in Scala. Probably not an example to follow.Unfortunately it's not easy to do anything about it if you cannot give us any more details to why. So far I haven't found anything. -- /Jacob Carlborg
Nov 11 2013
There is significant regret about the way macros are defined in Scala. Probably not an example to follow. AndreiNot an example to follow, but it would definitely be worth looking into how they defined macros and what aspect of that caused problems, so we can avoid making the same mistakes.
Nov 12 2013
People have shunned proposals to have mixin functions because it wouldn't be obvious at call site that some statement is executed under a mixin (which could access all variables in scope etc). The same will happen here; I think it should be clear at call site that a macro is used. How about: macro!myAssert(1 + 2 == 4); instead of myAssert(1 + 2 == 4); On Sun, Nov 10, 2013 at 1:20 PM, Jacob Carlborg <doob me.com> 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 -- /Jacob Carlborg
Nov 10 2013
On 11/11/2013 02:49 AM, Timothee Cour wrote:People have shunned proposals to have mixin functions because it wouldn't be obvious at call site that some statement is executed under a mixin (which could access all variables in scope etc). The same will happen here; ...macros are hygienic.
Nov 10 2013
On 2013-11-11 02:49, Timothee Cour wrote:People have shunned proposals to have mixin functions because it wouldn't be obvious at call site that some statement is executed under a mixin (which could access all variables in scope etc). The same will happen here; I think it should be clear at call site that a macro is used. How about: macro!myAssert(1 + 2 == 4); instead of myAssert(1 + 2 == 4);I would really prefer if we not had to do that. -- /Jacob Carlborg
Nov 10 2013
On Monday, 11 November 2013 at 01:49:45 UTC, Timothee Cour wrote:People have shunned proposals to have mixin functions because it wouldn't be obvious at call site that some statement is executed under a mixin (which could access all variables in scope etc). The same will happen here; I think it should be clear at call site that a macro is used. How about: macro!myAssert(1 + 2 == 4); instead of myAssert(1 + 2 == 4);If macros are supposed to access outer scope, I agree, this is a necessary restriction.
Nov 11 2013
On 11/11/2013 01:55 PM, Dicebot wrote:On Monday, 11 November 2013 at 01:49:45 UTC, Timothee Cour wrote:I don't agree. (The argument against implicit mixin features was a complete lack of hygiene, not the mere possibility of accessing the caller scope.)People have shunned proposals to have mixin functions because it wouldn't be obvious at call site that some statement is executed under a mixin (which could access all variables in scope etc). The same will happen here; I think it should be clear at call site that a macro is used. How about: macro!myAssert(1 + 2 == 4); instead of myAssert(1 + 2 == 4);If macros are supposed to access outer scope, I agree, this is a necessary restriction.
Nov 11 2013
On Monday, 11 November 2013 at 16:28:17 UTC, Timon Gehr wrote:I don't agree. (The argument against implicit mixin features was a complete lack of hygiene, not the mere possibility of accessing the caller scope.)How would you expect it to be hygienic in any way if it has implicit outer scope access? Reasoning is pretty much the same as with mixins.
Nov 11 2013
On 11/11/2013 05:47 PM, Dicebot wrote:On Monday, 11 November 2013 at 16:28:17 UTC, Timon Gehr wrote:With mixins _every_ identifier is by _default_ inserted/looked up in the so-called 'outer scope', whereas declarations and normal symbol lookups within macros are hygienic by default. Macros are as much about reflection as about code generation. The trade-offs are simly not the same. Implicit outer scope access does not imply it behaves in a counter-intuitive manner. (It could just reflect some debug information after all, or perform some additional checks on the context for more safety, etc.) I will be really unhappy with any proposal that does not allow to interchange function calls with macro calls transparently, even though such a scheme allows more abusive code to be written as well. If in some code base macros should be clearly marked, a naming convention (eg. prefix macro names with 'macro') can be used. (Enforcing such a convention is trivial and amounts to eg. a few lines of additional code in a modified D front end.)I don't agree. (The argument against implicit mixin features was a complete lack of hygiene, not the mere possibility of accessing the caller scope.)How would you expect it to be hygienic in any way if it has implicit outer scope access? Reasoning is pretty much the same as with mixins.
Nov 11 2013
On 11/11/2013 10:23 PM, Timon Gehr wrote:simlysimply
Nov 11 2013
On 2013-11-11 17:28, Timon Gehr wrote:I don't agree. (The argument against implicit mixin features was a complete lack of hygiene, not the mere possibility of accessing the caller scope.)The macros system need to provide both hygienic and non-hygienic macros. -- /Jacob Carlborg
Nov 11 2013
On 2013-11-10 21:20:30 +0000, Jacob Carlborg said: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/DIP50Not a huge fan of the syntax, but I think it's a step in the right direction away from string mixins. R/ Shammah
Nov 10 2013
On 2013-11-11 03:04:34 +0000, Shammah Chancellor said:On 2013-11-10 21:20:30 +0000, Jacob Carlborg said:I think this would gain a lot more traction if someone wrote an std.expressions which produced workable code from a AST. At that point, it's just for the D-frontend to parse code into said std.expressions. The .NET expressions framework might servce as some insperation. R/ ShammahI'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/DIP50Not a huge fan of the syntax, but I think it's a step in the right direction away from string mixins. R/ Shammah
Nov 10 2013
On 2013-11-11 04:04, Shammah Chancellor wrote:Not a huge fan of the syntax, but I think it's a step in the right direction away from string mixins.To you mean the <[ ]> syntax or something else? See my reply to Timothee: http://forum.dlang.org/thread/l5otb1$1dhi$1 digitalmars.com?page=2#post-l5q1vh:242c2k:241:40digitalmars.com -- /Jacob Carlborg
Nov 10 2013
On Sunday, 10 November 2013 at 21:20:34 UTC, 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/DIP50One of our targets for AST macros should be the ability to An example syntax for use with AST could be: auto data = [5, 7, 9]; int[] data2; query { from value in data where value >= 6 add to data2 } Could be unwrapped to: auto data = [5, 7, 9]; int[] data2; foreach(value; data) { if (value >= 6) data2 ~= value; } This isn't a thought out design but it should at least be a target or a possibility. Example: getset { public int id; private bool exit; } Would translate to: private int id; private bool exit; property { void id(int v) {this.id = v;} void exit(bool v) { this.exit = v; } int id() { return this.id; } bool exit() { return this.exit; } } This would definitely open new possibilities up. features. At current point I think the DIP does have the necessary features to implement this. However it would be nice for safety to be able to get all scope variables of where the macro was initiated from. Being able to check for if a variable exists could provide much needed compile safety and better error messages.
Nov 10 2013
On 2013-11-11 08:46, Rikki Cattermole wrote:One of our targets for AST macros should be the ability to replicate An example syntax for use with AST could be: auto data = [5, 7, 9]; int[] data2; query { from value in data where value >= 6 add to data2 } Could be unwrapped to: auto data = [5, 7, 9]; int[] data2; foreach(value; data) { if (value >= 6) data2 ~= value; } This isn't a thought out design but it should at least be a target or a possibility.Absolutely. One of my favorite examples is the database query: auto person = Person.where(e => e.name == "John"); Which translates to the following SQL: select * from person where name = 'John'Example: getset { public int id; private bool exit; } Would translate to: private int id; private bool exit; property { void id(int v) {this.id = v;} void exit(bool v) { this.exit = v; } int id() { return this.id; } bool exit() { return this.exit; } } This would definitely open new possibilities up.That's quite similar one of the examples, I like to call it "property shortcut": http://wiki.dlang.org/DIP50#Attribute_macrosAt current point I think the DIP does have the necessary features to implement this. However it would be nice for safety to be able to get all scope variables of where the macro was initiated from. Being able to check for if a variable exists could provide much needed compile safety and better error messages.Why not? There's quite a lot that is not specified in this DIP. Mostly because I haven't decided/figured out how it should work exactly. Of course, any help is always appreciated. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 08:12:59 UTC, Jacob Carlborg wrote:On 2013-11-11 08:46, Rikki Cattermole wrote:Theres a few other things I think would need to be cleared up. For example take this code: shader { program vertex { #version 150 void main() { } } fragment { #version 150 void main() { } } } At this point the vertex / fragment segments would be treated as strings instead of calling their macros. So perhaps a rule to identify macros inside macros calls? It would save a lot of time for parsing reasons. Also can you alias a macro? alias fragment = tostring; That would make things a lot simpler creating nice structures of them. Perhaps a condition on a macro like the if's we got for templates would be useful in the sense of being able to say: if (lexer.compareLine(0, "[a-zA-Z]{1}[a-zA-Z_0-9]*") && lexer.isSymbol(1, SymbolTypes.Macro, vertex)) This would require us to develop a lexer library. But if done right I don't see why it wouldn't be usable for more than just D macro checks. Preferably also for e.g. c/c++ wink wink for when D's front end is in D.One of our targets for AST macros should be the ability to replicate An example syntax for use with AST could be: auto data = [5, 7, 9]; int[] data2; query { from value in data where value >= 6 add to data2 } Could be unwrapped to: auto data = [5, 7, 9]; int[] data2; foreach(value; data) { if (value >= 6) data2 ~= value; } This isn't a thought out design but it should at least be a target or a possibility.Absolutely. One of my favorite examples is the database query: auto person = Person.where(e => e.name == "John"); Which translates to the following SQL: select * from person where name = 'John'Example: getset { public int id; private bool exit; } Would translate to: private int id; private bool exit; property { void id(int v) {this.id = v;} void exit(bool v) { this.exit = v; } int id() { return this.id; } bool exit() { return this.exit; } } This would definitely open new possibilities up. features.That's quite similar one of the examples, I like to call it "property shortcut": http://wiki.dlang.org/DIP50#Attribute_macrosAt current point I think the DIP does have the necessary features to implement this. However it would be nice for safety to be able to get all scope variables of where the macro was initiated from. Being able to check for if a variable exists could provide much needed compile safety and better error messages.Why not? There's quite a lot that is not specified in this DIP. Mostly because I haven't decided/figured out how it should work exactly. Of course, any help is always appreciated.
Nov 11 2013
On 2013-11-11 09:31, Rikki Cattermole wrote:Theres a few other things I think would need to be cleared up. For example take this code: shader { program vertex { #version 150 void main() { } } fragment { #version 150 void main() { } } } At this point the vertex / fragment segments would be treated as strings instead of calling their macros. So perhaps a rule to identify macros inside macros calls? It would save a lot of time for parsing reasons.They way I see that is the AST of the whole block would be passed to "shader". I have though a bit about macros inside macros, but I haven't come to a conclusion. The easiest way from a design point of view seems to be that "shader" to basically return the whole AST it receives plus any addition it needs to do. The the "vertex" and "fragment" macros are expanded recursively.Also can you alias a macro? alias fragment = tostring; That would make things a lot simpler creating nice structures of them.I don't see why not.Perhaps a condition on a macro like the if's we got for templates would be useful in the sense of being able to say: if (lexer.compareLine(0, "[a-zA-Z]{1}[a-zA-Z_0-9]*") && lexer.isSymbol(1, SymbolTypes.Macro, vertex))I don't think I understand how this should be used.This would require us to develop a lexer library. But if done right I don't see why it wouldn't be usable for more than just D macro checks. Preferably also for e.g. c/c++ wink wink for when D's front end is in D.-- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 09:24:31 UTC, Jacob Carlborg wrote:On 2013-11-11 09:31, Rikki Cattermole wrote:An example of this might be: macro foo (Context context, Ast!(string) str) if (lexer.isSymbol(0, SymbolTypes.Class)) { return str; } class Bar { int i; } foo { Bar(7); } The above code would succeed however the below code will give a compiler error stating that the given macro is not found. struct Haz { int i; } foo { Haz(9); } The above code is based on the assumption of a D lexer in phobos. This is simpler set of code which won't require a lexer. macro foo (Context context, Ast!(string) str) if (str == "working") { return ""; } foo {fails} foo {working} In these cases its a simple string test to determine if the text given is specified value. In the original example I gave, I was using regex to make the point of validation for a given line passed to the macro.Theres a few other things I think would need to be cleared up. For example take this code: shader { program vertex { #version 150 void main() { } } fragment { #version 150 void main() { } } } At this point the vertex / fragment segments would be treated as strings instead of calling their macros. So perhaps a rule to identify macros inside macros calls? It would save a lot of time for parsing reasons.They way I see that is the AST of the whole block would be passed to "shader". I have though a bit about macros inside macros, but I haven't come to a conclusion. The easiest way from a design point of view seems to be that "shader" to basically return the whole AST it receives plus any addition it needs to do. The the "vertex" and "fragment" macros are expanded recursively.Also can you alias a macro? alias fragment = tostring; That would make things a lot simpler creating nice structures of them.I don't see why not.Perhaps a condition on a macro like the if's we got for templates would be useful in the sense of being able to say: if (lexer.compareLine(0, "[a-zA-Z]{1}[a-zA-Z_0-9]*") && lexer.isSymbol(1, SymbolTypes.Macro, vertex))I don't think I understand how this should be used.This would require us to develop a lexer library. But if done right I don't see why it wouldn't be usable for more than just D macro checks. Preferably also for e.g. c/c++ wink wink for when D's front end is in D.
Nov 11 2013
On 2013-11-11 10:38, Rikki Cattermole wrote:An example of this might be: macro foo (Context context, Ast!(string) str) if (lexer.isSymbol(0, SymbolTypes.Class)) { return str; } class Bar { int i; } foo { Bar(7); } The above code would succeed however the below code will give a compiler error stating that the given macro is not found. struct Haz { int i; } foo { Haz(9); } The above code is based on the assumption of a D lexer in phobos. This is simpler set of code which won't require a lexer. macro foo (Context context, Ast!(string) str) if (str == "working") { return ""; } foo {fails} foo {working} In these cases its a simple string test to determine if the text given is specified value. In the original example I gave, I was using regex to make the point of validation for a given line passed to the macro.My idea of handling errors in macros is more something like triggering a real compile error. That could be done via the context parameter, something like: macro foo (Context context, Ast!(string) str) { if (str.eval() == "bar") context.error("Illegal value 'bar'"); // this will trigger the compile error } -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 10:04:31 UTC, Jacob Carlborg wrote:On 2013-11-11 10:38, Rikki Cattermole wrote:For errors I was thinking a new pragma. pragma(error, "You did x wrong"); This would fire an error and display the text given. Returning error code as expected. It is after all in the same league as msg. It would also remove our current static asserts in our code. So other words it could be replicated by: pragma(msg, "You did x wrong"); static assert(0); Just without the whole failed assert message. Although what I was showing was the idea of overloading of macros like we have in templates.An example of this might be: macro foo (Context context, Ast!(string) str) if (lexer.isSymbol(0, SymbolTypes.Class)) { return str; } class Bar { int i; } foo { Bar(7); } The above code would succeed however the below code will give a compiler error stating that the given macro is not found. struct Haz { int i; } foo { Haz(9); } The above code is based on the assumption of a D lexer in phobos. This is simpler set of code which won't require a lexer. macro foo (Context context, Ast!(string) str) if (str == "working") { return ""; } foo {fails} foo {working} In these cases its a simple string test to determine if the text given is specified value. In the original example I gave, I was using regex to make the point of validation for a given line passed to the macro.My idea of handling errors in macros is more something like triggering a real compile error. That could be done via the context parameter, something like: macro foo (Context context, Ast!(string) str) { if (str.eval() == "bar") context.error("Illegal value 'bar'"); // this will trigger the compile error }
Nov 11 2013
On 2013-11-11 11:11, Rikki Cattermole wrote:For errors I was thinking a new pragma. pragma(error, "You did x wrong"); This would fire an error and display the text given. Returning error code as expected. It is after all in the same league as msg. It would also remove our current static asserts in our code. So other words it could be replicated by: pragma(msg, "You did x wrong"); static assert(0); Just without the whole failed assert message.I like the context parameter better. I'm imagine the context parameter containing a lot of information and functionality to interact with the compiler. A pragma seems not be general enough.Although what I was showing was the idea of overloading of macros like we have in templates.Ok, I see. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 10:19:49 UTC, Jacob Carlborg wrote:On 2013-11-11 11:11, Rikki Cattermole wrote:I can understand wanting to have a high level version of it in context. I'm just considering a high reuse language feature that could back it. Really it should have been added a while ago given the static assert trick is used a bit. I do actually like the idea of having the ability to call it on context with a bunch of extra information given to it for you. e.g. line number of initiation ext.For errors I was thinking a new pragma. pragma(error, "You did x wrong"); This would fire an error and display the text given. Returning error code as expected. It is after all in the same league as msg. It would also remove our current static asserts in our code. So other words it could be replicated by: pragma(msg, "You did x wrong"); static assert(0); Just without the whole failed assert message.I like the context parameter better. I'm imagine the context parameter containing a lot of information and functionality to interact with the compiler. A pragma seems not be general enough.
Nov 11 2013
On 2013-11-11 11:28, Rikki Cattermole wrote:I can understand wanting to have a high level version of it in context. I'm just considering a high reuse language feature that could back it. Really it should have been added a while ago given the static assert trick is used a bit. I do actually like the idea of having the ability to call it on context with a bunch of extra information given to it for you. e.g. line number of initiation ext.I think we want to have as much as possible of this collected in the same place. I don't think pragmas are a good fit for this. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 10:47:37 UTC, Jacob Carlborg wrote:On 2013-11-11 11:28, Rikki Cattermole wrote:Yes I do agree with that. I'm just more worried about what backs it then pleasantries that we can give the developer. Also if you're not looking towards pragma's to hook into stopping compilation what are your ideas and thoughts around this issue? Because at this point I only know of static assert to do it.I can understand wanting to have a high level version of it in context. I'm just considering a high reuse language feature that could back it. Really it should have been added a while ago given the static assert trick is used a bit. I do actually like the idea of having the ability to call it on context with a bunch of extra information given to it for you. e.g. line number of initiation ext.I think we want to have as much as possible of this collected in the same place. I don't think pragmas are a good fit for this.
Nov 11 2013
On 2013-11-11 11:51, Rikki Cattermole wrote:Yes I do agree with that. I'm just more worried about what backs it then pleasantries that we can give the developer. Also if you're not looking towards pragma's to hook into stopping compilation what are your ideas and thoughts around this issue? Because at this point I only know of static assert to do it.A function call on the context parameter as I've already showed. This would just call "error" which is already implemented in the compiler. Although I don't know how to actually do the connection between the compiler internals the user code. I think this is one of the big challenges with this DIP. For this function I guess it could be done like an intrinsic (is that the correct word?). -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 10:59:28 UTC, Jacob Carlborg wrote:A function call on the context parameter as I've already showed. This would just call "error" which is already implemented in the compiler. Although I don't know how to actually do the connection between the compiler internals the user code. I think this is one of the big challenges with this DIP. For this function I guess it could be done like an intrinsic (is that the correct word?).Ok pragmas essentially call functions like error in the compiler [0]. What I am thinking error will do is instead of outputting like msg it'll call error[1]. This is exactly what you want. [0] https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c#L2862 [1] https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c#L2957
Nov 11 2013
On 2013-11-11 12:04, Rikki Cattermole wrote:Ok pragmas essentially call functions like error in the compiler [0]. What I am thinking error will do is instead of outputting like msg it'll call error[1]. This is exactly what you want. [0] https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c#L2862 [1] https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c#L2957Yes, I still don't understand why you would want it as a pragma. Be usable outside of macros? -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 12:30:07 UTC, Jacob Carlborg wrote:Yes, I still don't understand why you would want it as a pragma. Be usable outside of macros?Yes outside of macros would be useful. For example code like this would become redundant: pragma(msg, "Support for x is not implemented on platform y"); static assert(0); Becoming: pragma(error, "Support for x is not implemented on platform y"); Also pragma's core responsibility is to cause the compiler to do something. In this case to say we hit an error during compilation please tell the user/dev and die. It is a hook to the compilers workings. Currently working on getting this implemented. Nearly done with it. Just got some extra spaces that shouldn't be in output.
Nov 11 2013
On 2013-11-11 13:36, Rikki Cattermole wrote:Yes outside of macros would be useful. For example code like this would become redundant: pragma(msg, "Support for x is not implemented on platform y"); static assert(0); Becoming: pragma(error, "Support for x is not implemented on platform y"); Also pragma's core responsibility is to cause the compiler to do something. In this case to say we hit an error during compilation please tell the user/dev and die. It is a hook to the compilers workings. Currently working on getting this implemented. Nearly done with it. Just got some extra spaces that shouldn't be in output.I just don't want to add a bunch of pragmas. I don't know what's the best solution. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 13:16:23 UTC, Jacob Carlborg wrote:I just don't want to add a bunch of pragmas. I don't know what's the best solution.I am only suggesting one :) We only need one that'll output any text we want it to and make the compiler consider it an error. On the macro side of things we can build a string which then can be given to the pragma. All of the wrapping giving the goodness would go into the context. Current what I have enables this: void main() { U u; } alias T!("hi", "bye") U; struct T(string a, string b) { pragma(error, a ~ "\n" ~ b); } test.d(8): Error: hi bye test.d(5): Error: template instance test.T!("hi", "bye") error instantiating Not really in pull state but thats the best I can do. Really that final error should be omitted.
Nov 11 2013
On 2013-11-11 14:32, Rikki Cattermole wrote:I am only suggesting one :)What about warnings? And no, the current pragma(msg) isn't the same.We only need one that'll output any text we want it to and make the compiler consider it an error. On the macro side of things we can build a string which then can be given to the pragma. All of the wrapping giving the goodness would go into the context. Current what I have enables this: void main() { U u; } alias T!("hi", "bye") U; struct T(string a, string b) { pragma(error, a ~ "\n" ~ b); } test.d(8): Error: hi bye test.d(5): Error: template instance test.T!("hi", "bye") error instantiating Not really in pull state but thats the best I can do. Really that final error should be omitted.I wouldn't say no to this if macros are completely off the table. Perhaps it's a good addition regardless. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 13:36:14 UTC, Jacob Carlborg wrote:What about warnings? And no, the current pragma(msg) isn't the same.I'm not doing one for warnings. See how the error one goes. The warning one won't stop compilation and pragma msg can be used to fake it.I wouldn't say no to this if macros are completely off the table. Perhaps it's a good addition regardless.Personally I think it was already needed even without macros. Just this has started me off on actually looking into it. We'll see what the compiler devs think though.
Nov 11 2013
On 2013-11-11 14:40, Rikki Cattermole wrote:I'm not doing one for warnings. See how the error one goes. The warning one won't stop compilation and pragma msg can be used to fake it.Yes, but I want warnings to be available in the context parameter as well. That's what I've been talking about all along. It's not just errors, it's all of the stuff that can be added. Warnings can be turned off, pragma(msg) cannot (at least not as far as I know).Personally I think it was already needed even without macros. Just this has started me off on actually looking into it. We'll see what the compiler devs think though.I see. I'm not saying that we don't need it. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 14:10:32 UTC, Jacob Carlborg wrote:On 2013-11-11 14:40, Rikki Cattermole wrote:Ah ok, I'll see what I can drum up in that regard then. I guess I was wrong about being able to fake it with pragma msg.I'm not doing one for warnings. See how the error one goes. The warning one won't stop compilation and pragma msg can be used to fake it.Yes, but I want warnings to be available in the context parameter as well. That's what I've been talking about all along. It's not just errors, it's all of the stuff that can be added. Warnings can be turned off, pragma(msg) cannot (at least not as far as I know).
Nov 11 2013
Am 11.11.2013 13:36, schrieb Rikki Cattermole:On Monday, 11 November 2013 at 12:30:07 UTC, Jacob Carlborg wrote:but in macros the context information is much more interesting then anything else - so #pragma(error,...) won't fully fit the needs to context error returning - it could be much more then just a message example: to help the compiler forming better error messages - or maybe recover from deep macro expansion etc...) what you want is just #pragma(error,...) -> break compiliation now Jacob is talking about the feedback for the compiler thing...Yes, I still don't understand why you would want it as a pragma. Be usable outside of macros?Yes outside of macros would be useful. For example code like this would become redundant: pragma(msg, "Support for x is not implemented on platform y"); static assert(0); Becoming: pragma(error, "Support for x is not implemented on platform y"); Also pragma's core responsibility is to cause the compiler to do something. In this case to say we hit an error during compilation please tell the user/dev and die. It is a hook to the compilers workings. Currently working on getting this implemented. Nearly done with it. Just got some extra spaces that shouldn't be in output.
Nov 11 2013
On Monday, 11 November 2013 at 13:22:34 UTC, dennis luehring wrote:example: to help the compiler forming better error messages - or maybe recover from deep macro expansion etc...) what you want is just #pragma(error,...) -> break compiliation now Jacob is talking about the feedback for the compiler thing...Jacob mentioned originally he wanted to create a compiler error. Or at least thats is how I took it. Hence pragma(error, "text"); We can already message out at both compile and runtime its simply does the compiler recognise it as an error part.
Nov 11 2013
On 2013-11-11 14:36, Rikki Cattermole wrote:Jacob mentioned originally he wanted to create a compiler error. Or at least thats is how I took it. Hence pragma(error, "text"); We can already message out at both compile and runtime its simply does the compiler recognise it as an error part."error" would be just a single function that is available in the context parameter. There would be many others. From the DIP: * The arguments used when the compiler was invoked * Functions for emitting messages of various verbosity level, like error, warning and info * Functions for querying various types of settings/options, like which versions are defined, is "debug" or "release" defined and so on * In general providing as much as possible of what the compiler knows about the compile run * The context should have an associative array with references to all scoped variables at initiation point. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 14:13:31 UTC, Jacob Carlborg wrote:On 2013-11-11 14:36, Rikki Cattermole wrote:Is there anything specific for info that I should look at? or does pragma msg do everything for you?Jacob mentioned originally he wanted to create a compiler error. Or at least thats is how I took it. Hence pragma(error, "text"); We can already message out at both compile and runtime its simply does the compiler recognise it as an error part."error" would be just a single function that is available in the context parameter. There would be many others. From the DIP: * The arguments used when the compiler was invoked * Functions for emitting messages of various verbosity level, like error, warning and info * Functions for querying various types of settings/options, like which versions are defined, is "debug" or "release" defined and so on * In general providing as much as possible of what the compiler knows about the compile run * The context should have an associative array with references to all scoped variables at initiation point.
Nov 11 2013
On 2013-11-11 16:24, Rikki Cattermole wrote:Is there anything specific for info that I should look at? or does pragma msg do everything for you?Sorry, I don't understand what you're meaning. -- /Jacob Carlborg
Nov 11 2013
On 11/11/2013 03:13 PM, Jacob Carlborg wrote:"error" would be just a single function that is available in the context parameter. There would be many others. From the DIP:"error" should also be able to specify where the error occurred in the input, so that it is displayed at the call site.
Nov 11 2013
On 2013-11-11 17:23, Timon Gehr wrote:"error" should also be able to specify where the error occurred in the input, so that it is displayed at the call site.That's a good point. -- /Jacob Carlborg
Nov 11 2013
On 11/11/2013 01:36 PM, Rikki Cattermole wrote:Yes outside of macros would be useful. For example code like this would become redundant: pragma(msg, "Support for x is not implemented on platform y"); static assert(0); Becoming: pragma(error, "Support for x is not implemented on platform y");static assert(0, "Support for x is not implemented on platform y");
Nov 11 2013
On Monday, 11 November 2013 at 16:22:40 UTC, Timon Gehr wrote:On 11/11/2013 01:36 PM, Rikki Cattermole wrote:Hmm wasn't aware of that syntax. Needs an example I think on docs. I will still work on pull request as the point of an assert and pragma message is different, atleast I believe.Yes outside of macros would be useful. For example code like this would become redundant: pragma(msg, "Support for x is not implemented on platform y"); static assert(0); Becoming: pragma(error, "Support for x is not implemented on platform y");static assert(0, "Support for x is not implemented on platform y");
Nov 11 2013
Jacob Carlborg:One of my favorite examples is the database query: auto person = Person.where(e => e.name == "John"); Which translates to the following SQL: select * from person where name = 'John'Can't you do the same thing with functions similar (same API but different semantics) to std.algorithm ones that generate expression templates? auto person = persons.filter!(e => e.name == "John"); -------- simendsjo:* Number intervals, like "int i = int[10..20];" where only 10 to 20 are legal valuesWhat's wrong with this syntax that doesn't reqiire macros? It's more uniform with the rest of the language: Ranged!(int, 10, 20) i; Bye, bearophile
Nov 11 2013
On Monday, 11 November 2013 at 09:02:01 UTC, bearophile wrote:Jacob Carlborg:The problem here is that a library need to know that it has to create SELECT * FROM persons WHERE name = 'John'; and not SELECT * FROM persons; and filter it locally. So it needs a way to inspect the body of the delegate and extract "name" "==" and "John".One of my favorite examples is the database query: auto person = Person.where(e => e.name == "John"); Which translates to the following SQL: select * from person where name = 'John'Can't you do the same thing with functions similar (same API but different semantics) to std.algorithm ones that generate expression templates? auto person = persons.filter!(e => e.name == "John");-------- simendsjo:Nothing wrong with it, I was just trying to come up with some examples. I don't say they're necessarily good :)* Number intervals, like "int i = int[10..20];" where only 10 to 20 are legal valuesWhat's wrong with this syntax that doesn't reqiire macros? It's more uniform with the rest of the language: Ranged!(int, 10, 20) i; Bye, bearophile
Nov 11 2013
On 2013-11-11 10:23, simendsjo wrote:On Monday, 11 November 2013 at 09:02:01 UTC, bearophile wrote:This particular example would work. "e" would be a proxy which implements opDispatch which returns another proxy which overloads opEquals. The problem is that != and all the comparison operators won't work. See my reply to bearophile: http://forum.dlang.org/thread/l5otb1$1dhi$1 digitalmars.com?page=3#post-l5q892:242kpf:241:40digitalmars.com -- /Jacob Carlborgauto person = persons.filter!(e => e.name == "John");The problem here is that a library need to know that it has to create SELECT * FROM persons WHERE name = 'John'; and not SELECT * FROM persons; and filter it locally. So it needs a way to inspect the body of the delegate and extract "name" "==" and "John".
Nov 11 2013
On 2013-11-11 10:02, bearophile wrote:Can't you do the same thing with functions similar (same API but different semantics) to std.algorithm ones that generate expression templates? auto person = persons.filter!(e => e.name == "John");I have been thinking about that, a solution where "e" is a proxy that implements opDispatch and which returns a new proxy which overloads "==". The problem with this is that you cannot separately overload the equal and comparison operators. In D the all the comparisons operators are implement with the single overload, opCmp. You cannot know from inside of opCmp if it's the "<" or the ">" operator that is being called. Same problem with opEquals. -- /Jacob Carlborg
Nov 11 2013
One of our targets for AST macros should be the ability to An example syntax for use with AST could be: auto data = [5, 7, 9]; int[] data2; query { from value in data where value >= 6 add to data2 } Could be unwrapped to: auto data = [5, 7, 9]; int[] data2; foreach(value; data) { if (value >= 6) data2 ~= value; }could you add the example to the DIP wiki page
Nov 11 2013
On Monday, 11 November 2013 at 09:01:31 UTC, dennis luehring wrote:Adding use case section with Linq example. Please remove / modify as required as is first time editing wiki.One of our targets for AST macros should be the ability to An example syntax for use with AST could be: auto data = [5, 7, 9]; int[] data2; query { from value in data where value >= 6 add to data2 } Could be unwrapped to: auto data = [5, 7, 9]; int[] data2; foreach(value; data) { if (value >= 6) data2 ~= value; }could you add the example to the DIP wiki page
Nov 11 2013
I would really like to use AST macros for the following use case: myAssert( x < y); //will print, on failure, a message, along with all values appearing inside macro myAssert: x<y failed: x=..., y=... myAssert( fun(x,y)==z1+z2) //likewise, but nesting down to all individual variables appearing inside the macro: x=..., y=..., fun(x,y)=..., z1=..., z2=..., bar(z1+z2)=... This would advantageously replace the plethora of unittest helpers found in other languages, eg: CHECK_EQ, CHECK_LEQ, etc. Invaluable for debugging or informative unittests and logs. On Mon, Nov 11, 2013 at 1:52 AM, Rikki Cattermole <alphaglosined gmail.com>wrote:On Monday, 11 November 2013 at 09:01:31 UTC, dennis luehring wrote:One of our targets for AST macros should be the ability toAdding use case section with Linq example. Please remove / modify as required as is first time editing wiki.An example syntax for use with AST could be: auto data = [5, 7, 9]; int[] data2; query { from value in data where value >= 6 add to data2 } Could be unwrapped to: auto data = [5, 7, 9]; int[] data2; foreach(value; data) { if (value >= 6) data2 ~= value; }could you add the example to the DIP wiki page
Nov 11 2013
On Monday, 11 November 2013 at 10:10:33 UTC, Timothee Cour wrote:I would really like to use AST macros for the following use case: myAssert( x < y); //will print, on failure, a message, along with all values appearing inside macro myAssert: x<y failed: x=..., y=... myAssert( fun(x,y)==z1+z2) //likewise, but nesting down to all individual variables appearing inside the macro: x=..., y=..., fun(x,y)=..., z1=..., z2=..., bar(z1+z2)=... This would advantageously replace the plethora of unittest helpers found in other languages, eg: CHECK_EQ, CHECK_LEQ, etc. Invaluable for debugging or informative unittests and logs. On Mon, Nov 11, 2013 at 1:52 AM, Rikki Cattermole <alphaglosined gmail.com>wrote:Perhaps an alternative would be: asserts { x < y z == z } Where the macro would do something like this once converted: if (!(x < y)) writeln("x < y failed with x=", x, " y= ", y); if (!(z == z)) writeln("z == z failed with z=", z); This would also have the benefit of allowing for multiple assert statements for one block.On Monday, 11 November 2013 at 09:01:31 UTC, dennis luehring wrote:One of our targets for AST macros should be the ability toAdding use case section with Linq example. Please remove / modify as required as is first time editing wiki.An example syntax for use with AST could be: auto data = [5, 7, 9]; int[] data2; query { from value in data where value >= 6 add to data2 } Could be unwrapped to: auto data = [5, 7, 9]; int[] data2; foreach(value; data) { if (value >= 6) data2 ~= value; }could you add the example to the DIP wiki page
Nov 11 2013
On 2013-11-11 11:10, Timothee Cour wrote:I would really like to use AST macros for the following use case: myAssert( x < y); //will print, on failure, a message, along with all values appearing inside macro myAssert: x<y failed: x=..., y=... myAssert( fun(x,y)==z1+z2) //likewise, but nesting down to all individual variables appearing inside the macro: x=..., y=..., fun(x,y)=..., z1=..., z2=..., bar(z1+z2)=... This would advantageously replace the plethora of unittest helpers found in other languages, eg: CHECK_EQ, CHECK_LEQ, etc. Invaluable for debugging or informative unittests and logs.Agree. That's the first example in the DIP. Although a very simplified version. -- /Jacob Carlborg
Nov 11 2013
On Mon, Nov 11, 2013 at 2:21 AM, Jacob Carlborg <doob me.com> wrote:On 2013-11-11 11:10, Timothee Cour wrote:yes, I think your initial example becomes more interesting with this, as in its current form it can already be done in current D. This would make error messages self-documenting: myAssert(!file.exists ); // "!file. exists" failed: dump of AST: file: string ="foobar.d" |_file.exists: bool = false |_!file. exists: bool = false In many cases, this would be so much more useful than an out of date / incomplete string error message, esp w a lot of variables involved.I would really like to use AST macros for the following use case: myAssert( x < y); //will print, on failure, a message, along with all values appearing inside macro myAssert: x<y failed: x=..., y=... myAssert( fun(x,y)==z1+z2) //likewise, but nesting down to all individual variables appearing inside the macro: x=..., y=..., fun(x,y)=..., z1=..., z2=..., bar(z1+z2)=... This would advantageously replace the plethora of unittest helpers found in other languages, eg: CHECK_EQ, CHECK_LEQ, etc. Invaluable for debugging or informative unittests and logs.Agree. That's the first example in the DIP. Although a very simplified version.
Nov 11 2013
On 2013-11-11 11:39, Timothee Cour wrote:yes, I think your initial example becomes more interesting with this, as in its current form it can already be done in current D.The current example prints out the exact expression what was passed to the assert macro. Not the result of evaluating the expression. I don't see how this can currently be done in DThis would make error messages self-documenting: myAssert(!file.exists ); // "!file. exists" failed: dump of AST: file: string ="foobar.d" |_file.exists: bool = false |_!file. exists: bool = false In many cases, this would be so much more useful than an out of date / incomplete string error message, esp w a lot of variables involved.I agree. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 10:55:23 UTC, Jacob Carlborg wrote:The current example prints out the exact expression what was passed to the assert macro. Not the result of evaluating the expression. I don't see how this can currently be done in DI made a suggestion regarding a macro able to get scoped variables from initiation point with Linq. And why that would be a good thing. This is another use case for it. Perhaps add it as a use case for having that feature on the DIP?
Nov 11 2013
On 2013-11-11 11:58, Rikki Cattermole wrote:I made a suggestion regarding a macro able to get scoped variables from initiation point with Linq. And why that would be a good thing. This is another use case for it. Perhaps add it as a use case for having that feature on the DIP?I already have an example with the assert (not among the use cases but at the top). Or were you referring to something else? -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 11:01:41 UTC, Jacob Carlborg wrote:I already have an example with the assert (not among the use cases but at the top). Or were you referring to something else?I was referring to the use case as to why we should have the ability to get scoped variables from the initiation point. Example: void func(int i) { bool b; macr {} } macro foo (Context context, Ast!(string) str) { writeln(context.scopeVariables!int("i")); writeln(context.scopeVariables!bool("b")); return ""; }
Nov 11 2013
On 2013-11-11 12:08, Rikki Cattermole wrote:I was referring to the use case as to why we should have the ability to get scoped variables from the initiation point. Example: void func(int i) { bool b; macr {} } macro foo (Context context, Ast!(string) str) { writeln(context.scopeVariables!int("i")); writeln(context.scopeVariables!bool("b")); return ""; }Ok, I see. Please add additional examples to the DIP if you think it's missing. -- /Jacob Carlborg
Nov 11 2013
On Mon, Nov 11, 2013 at 2:55 AM, Jacob Carlborg <doob me.com> wrote:On 2013-11-11 11:39, Timothee Cour wrote: yes, I think your initial example becomes more interesting with this, asI'm using a modified assert that uses the ugly import(file)[line] trick, so that can be done (but is really ugly and has impact either runtime or compile time). But we're essentially in agreement.in its current form it can already be done in current D.The current example prints out the exact expression what was passed to the assert macro. Not the result of evaluating the expression. I don't see how this can currently be done in DThis would make error messages self-documenting:myAssert(!file.exists ); // "!file. exists" failed: dump of AST: file: string ="foobar.d" |_file.exists: bool = false |_!file. exists: bool = false In many cases, this would be so much more useful than an out of date / incomplete string error message, esp w a lot of variables involved.I agree. -- /Jacob Carlborg
Nov 11 2013
On 2013-11-11 12:06, Timothee Cour wrote:I'm using a modified assert that uses the ugly import(file)[line] trick, so that can be done (but is really ugly and has impact either runtime or compile time). But we're essentially in agreement.Right, that ugly trick :) -- /Jacob Carlborg
Nov 11 2013
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/DIP50Thumbs up!
Nov 11 2013
On 2013-11-11 09:08, luka8088 wrote:Thumbs up!Thanks. -- /Jacob Carlborg
Nov 11 2013
On Sunday, 10 November 2013 at 21:20:34 UTC, 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/DIP50I like it, Jacob. With or without <[ ]> it is a good proposal, and I see several places where I would use it. +1
Nov 11 2013
On 2013-11-11 10:07, Dejan Lekic wrote:I like it, Jacob. With or without <[ ]> it is a good proposal, and I see several places where I would use it. +1Thank you. -- /Jacob Carlborg
Nov 11 2013
11-Nov-2013 01:20, Jacob Carlborg пишет: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/DIP50I have to say I like it. I find it nice that it would allow one to finally ensure that inlining is always done by making critical primitives macros instead of functions. This is vastly superior compared to the _only_ current option of generating unrolled code with string mixins. I'd call attribute macros - declaration macros in line with statement macros, then describe how they look - a lot like attributes. Things to note though: - Can't implement scope(exit/success/failure) because that would need to capture the outer scope to pack it into try/catch/finally. - Can't implement foreach if only because of the syntax of the latter. - There is no definition of Ast!(T) construct - I take it's a struct or a class of sorts and the whole thing works with the CTFE engine. Then it also needs specification of Statements, Declarations. - It seems like I can use AST literal in R-T code as well? That would be useful but only if some library actually accepted these AST nodes. -- Dmitry Olshansky
Nov 11 2013
On 2013-11-11 12:34, Dmitry Olshansky wrote:I have to say I like it.Cool :)I find it nice that it would allow one to finally ensure that inlining is always done by making critical primitives macros instead of functions. This is vastly superior compared to the _only_ current option of generating unrolled code with string mixins. I'd call attribute macros - declaration macros in line with statement macros, then describe how they look - a lot like attributes.Ok, I can change that.Things to note though: - Can't implement scope(exit/success/failure) because that would need to capture the outer scope to pack it into try/catch/finally.Right. scope(exit) could perhaps be implement with a custom struct and calling a block in the destructor.- Can't implement foreach if only because of the syntax of the latter.I would think something like this: macro foreach (T) (Context context, Ast!(Symbol) var, Ast!(T) collection, Statement block) { if (isRange(collection)) { return <[ for (auto __r = $collection; !__r.empty; __r.popFront()) { auto $var = __r.front; block; } ]>; } else if (hasOpApply(collection)) { ... } else ... } Perhaps not all of the existing syntax can fit in a macro.- There is no definition of Ast!(T) construct - I take it's a struct or a class of sorts and the whole thing works with the CTFE engine. Then it also needs specification of Statements, Declarations.Yes, something like that. I don't know exactly how the Ast type need to look like. See one of my replies to bearophile: http://forum.dlang.org/thread/l5otb1$1dhi$1 digitalmars.com- It seems like I can use AST literal in R-T code as well? That would be useful but only if some library actually accepted these AST nodes.Actually, I haven't thought about this. I think my original idea was that <[ ]> should only work inside macros. But that it would be possible to pass Ast nodes to other functions. -- /Jacob Carlborg
Nov 11 2013
Am Sun, 10 Nov 2013 22:20:30 +0100 schrieb Jacob Carlborg <doob me.com>: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/DIP50Wow, some topics really explode recently. Is the D user base growing or are AST macros drawing so much attention? -- Marco
Nov 11 2013
On Monday, 11 November 2013 at 12:13:54 UTC, Marco Leise wrote:Wow, some topics really explode recently. Is the D user base growing or are AST macros drawing so much attention?I'd like to say both. AST macros are one of those few things that I wouldn't mind seeing breaking changes for and I'm in the camp of "avoid breaking changes at all cost". AST macros are to code what templates are to data. Despite it being possible to go without templates, I'm not at all tempted to switch to Go.
Nov 11 2013
On 2013-11-11 13:13, Marco Leise wrote:Wow, some topics really explode recently. Is the D user base growing or are AST macros drawing so much attention?AST macros are drawing so much attension. For some, it's like the holy grail. -- /Jacob Carlborg
Nov 11 2013
Jacob Carlborg:AST macros are drawing so much attension. For some, it's like the holy grail.That's a bad approach to technology design. You first need to create a good list of things that you want to do, then you have to try to do them without new features, and then if something important is not possible without the new feature (or it becomes too much ugly, too much long, too much bug-prone, etc), you have to see if the complexity of introducing the new feature is paid back. Macros are a significant feature, so they have a significant cost in code complexity, language dis-uniformity, ecc. Bye, bearophile
Nov 11 2013
On Sunday, 10 November 2013 at 21:20:34 UTC, 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/DIP50I don't have time to investigate this in details but I'd like to mention that this is one of few possible new features where ROI is really worth it. It removes lot of burden from core language and allows to replace some very arcane template hacks with cleaner code. I'd say it is a bit too early to go for it (really, we need at least to figure out how to make releases without issues first :)) but it is a good future goal even in context of general feature freezing.
Nov 11 2013
On Monday, 11 November 2013 at 13:26:37 UTC, Dicebot wrote:On Sunday, 10 November 2013 at 21:20:34 UTC, Jacob Carlborg wrote:Can you stop reading my mind, please ?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/DIP50I don't have time to investigate this in details but I'd like to mention that this is one of few possible new features where ROI is really worth it. It removes lot of burden from core language and allows to replace some very arcane template hacks with cleaner code. I'd say it is a bit too early to go for it (really, we need at least to figure out how to make releases without issues first :)) but it is a good future goal even in context of general feature freezing.
Nov 11 2013
On 11/10/2013 01:20 PM, 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/DIP50For macros that generate macros, I think you need a way to escape the splicing and maybe define how splicing works in an inner quasi quote. I guess you want <[ <[ $exp ]> ]> to turn into the ast <[ 1 ]> Then if you wanted ast <[ <[ $exp ]> ]> with the splice associated with the inner quasi quote, you'd have to do something like <[ <[ <[ \\\$exp ]> ]> ]> maybe a way to associate a splice with a quasi quote? <a[ <b[ <c[ $(a, exp) + $(b, exp) + $(c, exp) ]> ]> ]> a's exp is A b's exp is B c's exp is C then splice the quasi quote N times: 1: ast <b[ <c[ A + $(b, exp) + $(c, exp) ]> ]> 2: ast <c[ A + B + $(c, exp) ]> 3: ast A + B + C just dinking around here
Nov 11 2013
On 2013-11-11 20:23, Ellery Newcomer wrote:For macros that generate macros, I think you need a way to escape the splicing and maybe define how splicing works in an inner quasi quote. I guess you want <[ <[ $exp ]> ]> to turn into the ast <[ 1 ]> Then if you wanted ast <[ <[ $exp ]> ]> with the splice associated with the inner quasi quote, you'd have to do something like <[ <[ <[ \\\$exp ]> ]> ]> maybe a way to associate a splice with a quasi quote? <a[ <b[ <c[ $(a, exp) + $(b, exp) + $(c, exp) ]> ]> ]> a's exp is A b's exp is B c's exp is C then splice the quasi quote N times: 1: ast <b[ <c[ A + $(b, exp) + $(c, exp) ]> ]> 2: ast <c[ A + B + $(c, exp) ]> 3: ast A + B + C just dinking around hereThis would require some thought. -- /Jacob Carlborg
Nov 11 2013
On Monday, 11 November 2013 at 19:23:21 UTC, Ellery Newcomer wrote:On 11/10/2013 01:20 PM, Jacob Carlborg wrote:$ refers to the enclosing scope. so $$foo should refers to $foo in the enclosing scope. No need for special rule or label.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/DIP50For macros that generate macros, I think you need a way to escape the splicing and maybe define how splicing works in an inner quasi quote. I guess you want <[ <[ $exp ]> ]> to turn into the ast <[ 1 ]> Then if you wanted ast <[ <[ $exp ]> ]> with the splice associated with the inner quasi quote, you'd have to do something like <[ <[ <[ \\\$exp ]> ]> ]> maybe a way to associate a splice with a quasi quote? <a[ <b[ <c[ $(a, exp) + $(b, exp) + $(c, exp) ]> ]> ]> a's exp is A b's exp is B c's exp is C then splice the quasi quote N times: 1: ast <b[ <c[ A + $(b, exp) + $(c, exp) ]> ]> 2: ast <c[ A + B + $(c, exp) ]> 3: ast A + B + C just dinking around here
Nov 11 2013
On 11/11/2013 12:06 PM, deadalnix wrote:On Monday, 11 November 2013 at 19:23:21 UTC, Ellery Newcomer wrote:so if I have to splice my ast N times, then I have to generate M $'s depending on when I want it to expand?On 11/10/2013 01:20 PM, Jacob Carlborg wrote:$ refers to the enclosing scope. so $$foo should refers to $foo in the enclosing scope. No need for special rule or label.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/DIP50For macros that generate macros, I think you need a way to escape the splicing and maybe define how splicing works in an inner quasi quote. I guess you want <[ <[ $exp ]> ]> to turn into the ast <[ 1 ]> Then if you wanted ast <[ <[ $exp ]> ]> with the splice associated with the inner quasi quote, you'd have to do something like <[ <[ <[ \\\$exp ]> ]> ]> maybe a way to associate a splice with a quasi quote? <a[ <b[ <c[ $(a, exp) + $(b, exp) + $(c, exp) ]> ]> ]> a's exp is A b's exp is B c's exp is C then splice the quasi quote N times: 1: ast <b[ <c[ A + $(b, exp) + $(c, exp) ]> ]> 2: ast <c[ A + B + $(c, exp) ]> 3: ast A + B + C just dinking around here
Nov 11 2013
On Sunday, 10 November 2013 at 21:20:34 UTC, 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/DIP50Just a quick comment related to the 2007 proposal: http://youtu.be/FRfTk44nuWE?t=1h5m38s Page 45: http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf Based on my read though, yours is more powerful. The 2007 proposal is basically the "Quasi-Quoting" portions of your proposal (which is such a small part of your proposal).
Nov 11 2013
On 11/10/2013 1:20 PM, 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/DIP50I confess I have some serious reservations about AST macros in general: 1. I've seen very heavy use of such macros in macro assemblers. What happens is people use it to invent their own (very baroque) language on top of the existing assembler one. Anyone trying to read the code has to learn this new unique language, and given the limitations of the macro capability, it often comes with unfixable bizarre corner cases and limitations. This got so bad that in some cases I know of, the poor sap who is given the job of making improvements resorted to running the assembler to generate an object file, then disassembling the object file back into source code! Something went very wrong for this to be necessary. I know in my own assembler work I have abandoned all use of macros. (Note that macros in typical assemblers are far more powerful than C's macro language, which stands out for being pathetically underpowered.) 2. Macros are something that should be used very sparingly. However, this is not what happens. I used to be perplexed that even top shelf C/C++ programmers tend to write what I not so humbly consider to be pretty abusive use of macros. Now it just saddens me. 3. Lisp is a language that encourages users to write macros to pretty much invent a custom language for the task at hand. Heavy use of such makes the code unrecognizable as being Lisp code. I believe a language ought to have some "anchors" that the person reading the code can reliably recognize. (GO has taken this idea pretty far.) 4. AST macros, pretty much by definition, manipulate the AST. However, if you examine the semantic routines in DMD, a *lot* more is required to do more significant things. The symbol table must be consulted, etc. I just don't see how one could hope to implement something like function overloading with AST macros. Or template type deduction. Or closure semantics, attribute inference, etc. Sure, some forms of foreach can be rewritten into for statements by manipulating the AST, but not the more interesting forms, such as the ones that deal with opApply(). There are some statements in the DIP about the Context parameter and it'll provide semantic information, but I don't see how this can work without making it an ever-expanding collection of arbitrary methods. 5. We've said "no" in the past to things like user-defined tokens, which are closely related. 6. Note that D has a limited form of AST macros with mixin templates. To sum up, any AST macro proposal has some tough barriers to get over. Within its necessarily severe semantic limitations, it has to deliver a pretty compelling set of solutions, while avoiding the morass of incomprehensibility that far too many macro systems become in practice. For example, the Linq example in the DIP is not compelling, as aesthetically nicer code can be written using D's ranges and algorithms: auto data = arr.filter!(x => x > 5).array; blunt it's like the old: #define BEGIN { #define END } macros used in old C code to make it look like Pascal.
Nov 12 2013
I forgot to mention that "expression templates" can be used in D in an equivalent manner that they are used in C++, and can cover much of the functionality used in AST macros. Eric Anderton who wrote a regex expression template module a few years back: http://www.dsource.org/projects/ddl/browser/trunk/meta/regex.d
Nov 12 2013
On 11/12/2013 1:55 AM, Walter Bright wrote:I forgot to mention that "expression templates" can be used in D in an equivalent manner that they are used in C++, and can cover much of the functionality used in AST macros. Eric Anderton who wrote a regex expression template module a few years back: http://www.dsource.org/projects/ddl/browser/trunk/meta/regex.dHere's a project to add Linq support to C++: http://www.codeproject.com/Articles/17844/CLinq-LINQ-support-for-the-C-CLI-language There's also: http://pfultz2.github.io/Linq/ https://github.com/hjiang/linqxx/wiki
Nov 12 2013
On 2013-11-12 11:03, Walter Bright wrote:Here's a project to add Linq support to C++: http://www.codeproject.com/Articles/17844/CLinq-LINQ-support-for-the-C-CLI-language There's also: http://pfultz2.github.io/Linq/ https://github.com/hjiang/linqxx/wikiAgain, operator overloading in D is too limiting to implement something Linq like. -- /Jacob Carlborg
Nov 13 2013
On 11/13/2013 12:03 AM, Jacob Carlborg wrote:Again, operator overloading in D is too limiting to implement something Linq like.Ok, let's set aside the opEquals and opCmp issue for the moment. Can AST macros do anything that expression templates cannot?
Nov 13 2013
On Wednesday, 13 November 2013 at 08:45:13 UTC, Walter Bright wrote:On 11/13/2013 12:03 AM, Jacob Carlborg wrote:With an expression template you still can't create a statement. It has to revolve to a declaration. But as I said before, it's primarily syntax sugar. Expression templates are just a mass of boilerplate code. I came to the conclusion that the code for expression templates was no less ugly than for string mixins. What is true, though, is everything an AST macro can do, can already be done with a string mixin. The syntax is just ugly. calling syntax power implementation string mixin ugly high ugly expr template ok low ugly AST macro good ? ?Again, operator overloading in D is too limiting to implement something Linq like.Ok, let's set aside the opEquals and opCmp issue for the moment. Can AST macros do anything that expression templates cannot?
Nov 13 2013
On 11/13/2013 1:08 AM, Don wrote:On Wednesday, 13 November 2013 at 08:45:13 UTC, Walter Bright wrote:Actually, there is a way to do this. I wrote an article years back on how to write "statement" workalikes using lazy function parameters. I suppose I should dig that up if I can find it.On 11/13/2013 12:03 AM, Jacob Carlborg wrote:With an expression template you still can't create a statement. It has to revolve to a declaration.Again, operator overloading in D is too limiting to implement something Linq like.Ok, let's set aside the opEquals and opCmp issue for the moment. Can AST macros do anything that expression templates cannot?But as I said before, it's primarily syntax sugar. Expression templates are just a mass of boilerplate code. I came to the conclusion that the code for expression templates was no less ugly than for string mixins. What is true, though, is everything an AST macro can do, can already be done with a string mixin. The syntax is just ugly. calling syntax power implementation string mixin ugly high ugly expr template ok low ugly AST macro good ? ?This implies to me that we ought to explore the limits of expression templates, which already exist, in preference to creating a wholesale new feature.
Nov 13 2013
On 11/13/2013 11:24 AM, Walter Bright wrote:Actually, there is a way to do this. I wrote an article years back on how to write "statement" workalikes using lazy function parameters. I suppose I should dig that up if I can find it.Ah, found the code: void ifthen(bool cond, lazy void dg) { if (cond) dg(); } void ifthen(bool cond, lazy void dgthen, lazy void dgelse) { if (cond) dgthen(); else dgelse(); } void dotimes(int i, lazy int dg) { for (int j = 0; j < i; j++) dg(); } void switcher(bool delegate()[] cases...) { foreach (c; cases) { if (c()) break; } } bool scase(bool b, lazy void dg) { if (b) { dg(); return true; } return false; } bool sdefault(lazy void dg) { dg(); return true; } void whiler(lazy bool cond, lazy void bdy) { while (cond()) bdy(); } void test1() { int x = 3; dotimes(5, printf("%d\n", ++x)); ifthen(true, printf("yes\n")); ifthen(false, printf("no\n")); ifthen(true, printf("yes\n"), printf("no\n")); ifthen(false, printf("yes\n"), printf("no\n")); int v = 2; switcher( scase(v == 1, printf("it is 1\n")), scase(v == 2, printf("it is 2\n")), scase(v == 3, printf("it is 3\n")), sdefault( printf("it is default\n")) ); whiler( x < 100, (printf("%d\n", x), x *= 2) ); }
Nov 13 2013
On 11/13/2013 08:25 PM, Walter Bright wrote:int foo(int x){ ifthen(!x, return 2); // uh oh return 3; }Ah, found the code: void ifthen(bool cond, lazy void dg) { if (cond) dg(); }
Nov 13 2013
On 11/13/2013 12:50 PM, Timon Gehr wrote:On 11/13/2013 08:25 PM, Walter Bright wrote:This approach definitely hews to the single-entry/single-exit paradigm.int foo(int x){ ifthen(!x, return 2); // uh oh return 3; }Ah, found the code: void ifthen(bool cond, lazy void dg) { if (cond) dg(); }
Nov 13 2013
On Wednesday, 13 November 2013 at 19:25:18 UTC, Walter Bright wrote:On 11/13/2013 11:24 AM, Walter Bright wrote:Was is missing is the capability to look into the lazy parameter's ast and act accordingly. Here you can wrap something around code, not generation code depending on passed code.Actually, there is a way to do this. I wrote an article years back on how to write "statement" workalikes using lazy function parameters. I suppose I should dig that up if I can find it.Ah, found the code: void ifthen(bool cond, lazy void dg) { if (cond) dg(); } void ifthen(bool cond, lazy void dgthen, lazy void dgelse) { if (cond) dgthen(); else dgelse(); } void dotimes(int i, lazy int dg) { for (int j = 0; j < i; j++) dg(); } void switcher(bool delegate()[] cases...) { foreach (c; cases) { if (c()) break; } } bool scase(bool b, lazy void dg) { if (b) { dg(); return true; } return false; } bool sdefault(lazy void dg) { dg(); return true; } void whiler(lazy bool cond, lazy void bdy) { while (cond()) bdy(); } void test1() { int x = 3; dotimes(5, printf("%d\n", ++x)); ifthen(true, printf("yes\n")); ifthen(false, printf("no\n")); ifthen(true, printf("yes\n"), printf("no\n")); ifthen(false, printf("yes\n"), printf("no\n")); int v = 2; switcher( scase(v == 1, printf("it is 1\n")), scase(v == 2, printf("it is 2\n")), scase(v == 3, printf("it is 3\n")), sdefault( printf("it is default\n")) ); whiler( x < 100, (printf("%d\n", x), x *= 2) ); }
Nov 13 2013
On 11/13/2013 2:18 PM, deadalnix wrote:Was is missing is the capability to look into the lazy parameter's ast and act accordingly. Here you can wrap something around code, not generation code depending on passed code.That's correct. But you can look into the AST with expression templates. So, expression templates combined with lazy arguments and mixin templates may fill the problem space.
Nov 13 2013
On Wednesday, 13 November 2013 at 22:34:02 UTC, Walter Bright wrote:On 11/13/2013 2:18 PM, deadalnix wrote:Expression templates are limited to expression and require to use its own set of types. Still the idea has some merits.Was is missing is the capability to look into the lazy parameter's ast and act accordingly. Here you can wrap something around code, not generation code depending on passed code.That's correct. But you can look into the AST with expression templates. So, expression templates combined with lazy arguments and mixin templates may fill the problem space.
Nov 13 2013
On 11/13/2013 3:58 PM, deadalnix wrote:On Wednesday, 13 November 2013 at 22:34:02 UTC, Walter Bright wrote:Yes. But that's a good thing. I'd be pretty skeptical of the value of an AST macro that took 3+4 and changed it so it did something other than compute 7.On 11/13/2013 2:18 PM, deadalnix wrote:Expression templates are limited to expression and require to use its own set of types.Was is missing is the capability to look into the lazy parameter's ast and act accordingly. Here you can wrap something around code, not generation code depending on passed code.That's correct. But you can look into the AST with expression templates. So, expression templates combined with lazy arguments and mixin templates may fill the problem space.Still the idea has some merits.It has the merit of being implemented and available right now :-) I do understand that expression templates aren't very sexy, and are kinda hard to wrap one's head around. But they're not so bad from the perspective of the user of the expression templates, and I really think that the limits of existing features should be explored before inventing wholesale new ones that may turn out to be redundant.
Nov 13 2013
On Thursday, 14 November 2013 at 00:16:45 UTC, Walter Bright wrote:I do understand that expression templates aren't very sexy, and are kinda hard to wrap one's head around. But they're not so bad from the perspective of the user of the expression templates, and I really think that the limits of existing features should be explored before inventing wholesale new ones that may turn out to be redundant.My very first project in D involved quite a lot of them. So I very aware of what they are. The whole idea is to be able to extends that to statement and declarations. Making what expression templates can do is simply a side effect so to speak.
Nov 13 2013
On 11/13/2013 5:14 PM, deadalnix wrote:My very first project in D involved quite a lot of them. So I very aware of what they are. The whole idea is to be able to extends that to statement and declarations.My question about that is just what problem is this trying to solve, and why that problem cannot be reformulated in terms of expression templates? I.e. we shouldn't be adding things to D just because they are cool. They need to solve a problem that is fairly commonplace and too painful to solve with existing mechanisms. The larger the proposed language enhancement is, the more commonplace and and painful the problems must be that it purports to solve.Making what expression templates can do is simply a side effect so to speak.
Nov 13 2013
On Thursday, 14 November 2013 at 01:38:29 UTC, Walter Bright wrote:On 11/13/2013 5:14 PM, deadalnix wrote:I think the whole point of macro is to NOT add too much feature to the language. See for instance the example I gave before to create generator. an example). But with macro, the feature can be implemented as a library. It is NOT achievable with expression templates. I can say with certainty that the async/await mechanism is heavily used in some codebases and with great benefit. It is being added to all languages one after another. The idea behind macros is that instead of adding new feature to the language, the language should propose a toolkit to build these features as library. I don't think the time has come for macros in D. As discussed before, it seems like filling the gap in existing feature is more important than adding new ones. This should however be considered very seriously when the gaps has been filled.My very first project in D involved quite a lot of them. So I very aware of what they are. The whole idea is to be able to extends that to statement and declarations.My question about that is just what problem is this trying to solve, and why that problem cannot be reformulated in terms of expression templates? I.e. we shouldn't be adding things to D just because they are cool. They need to solve a problem that is fairly commonplace and too painful to solve with existing mechanisms. The larger the proposed language enhancement is, the more commonplace and and painful the problems must be that it purports to solve.
Nov 13 2013
On 2013-11-14 02:56, deadalnix wrote:I think the whole point of macro is to NOT add too much feature to the language. See for instance the example I gave before to create generator. This can with macro, the feature can be implemented as a library. It is NOT achievable with expression templates. I can say with certainty that the async/await mechanism is heavily used in some codebases and with great benefit. It is being added to all languages one after another. The idea behind macros is that instead of adding new feature to the language, the language should propose a toolkit to build these features as library.Agree, good points.I don't think the time has come for macros in D. As discussed before, it seems like filling the gap in existing feature is more important than adding new ones. This should however be considered very seriously when the gaps has been filled.Unfortunately I don't think we will have a feature freeze from now until those gaps has been filled. Most likely there will be added a couple of small features that could have been solved by AST macros. The problem with that is that each of these features, in themselves, are way to small to add AST macros for. So instead we get new features and even less chance of adding AST macros. Example. There's a bug report about adding support for C++ namespaces. That should be solveable with library code. It's just mangling and we already have pragma(mangle). pragma(mangle, namespace("foo::bar")) extern(C++) void x (); The problem here is that "x" needs to be mangled as well. pragma(mangle, namespace("foo::bar", x)) extern(C++) void x (); The above doesn't work due to forward reference errors. pragma(mangle, namespace("foo::bar", void function (), "x")) extern(C++) void x (); The problem with the above is that we now need to repeat the signature and the name of the function. With AST macros: macro namespace (Context context, Ast!(string) name, Declaration declaration) { ... } namespace("foo::bar") extern (C++) void x (); This works because the macro receives the whole declaration that is "x" and "x" is replaced with whatever the macro returns: pragma(mangle, "mangled_name_of_x") extern (C++) void x (); Since it uses the same syntax as UDA's you it can look like real namespaces in C++: namespace("foo::bar") extern (C++) { void x (); void y (); } -- /Jacob Carlborg
Nov 13 2013
Am 14.11.2013 08:50, schrieb Jacob Carlborg:On 2013-11-14 02:56, deadalnix wrote:perfect for the DIP example section - more of these please :)I think the whole point of macro is to NOT add too much feature to the language. See for instance the example I gave before to create generator. This can with macro, the feature can be implemented as a library. It is NOT achievable with expression templates. I can say with certainty that the async/await mechanism is heavily used in some codebases and with great benefit. It is being added to all languages one after another. The idea behind macros is that instead of adding new feature to the language, the language should propose a toolkit to build these features as library.Agree, good points.I don't think the time has come for macros in D. As discussed before, it seems like filling the gap in existing feature is more important than adding new ones. This should however be considered very seriously when the gaps has been filled.Unfortunately I don't think we will have a feature freeze from now until those gaps has been filled. Most likely there will be added a couple of small features that could have been solved by AST macros. The problem with that is that each of these features, in themselves, are way to small to add AST macros for. So instead we get new features and even less chance of adding AST macros. Example. There's a bug report about adding support for C++ namespaces. That should be solveable with library code. It's just mangling and we already have pragma(mangle). pragma(mangle, namespace("foo::bar")) extern(C++) void x (); The problem here is that "x" needs to be mangled as well. pragma(mangle, namespace("foo::bar", x)) extern(C++) void x (); The above doesn't work due to forward reference errors. pragma(mangle, namespace("foo::bar", void function (), "x")) extern(C++) void x (); The problem with the above is that we now need to repeat the signature and the name of the function. With AST macros: macro namespace (Context context, Ast!(string) name, Declaration declaration) { ... } namespace("foo::bar") extern (C++) void x (); This works because the macro receives the whole declaration that is "x" and "x" is replaced with whatever the macro returns: pragma(mangle, "mangled_name_of_x") extern (C++) void x (); Since it uses the same syntax as UDA's you it can look like real namespaces in C++: namespace("foo::bar") extern (C++) { void x (); void y (); }
Nov 13 2013
On 2013-11-14 08:54, dennis luehring wrote:perfect for the DIP example section - more of these please :)Done: http://wiki.dlang.org/DIP50#C.2B.2B_Namespaces_.28issue_7961.29 -- /Jacob Carlborg
Nov 14 2013
Am 14.11.2013 09:40, schrieb Jacob Carlborg:On 2013-11-14 08:54, dennis luehring wrote:it would be also nice to have (always) an (if possible) string mixin and/or expression-template variant of the example around to show the dirtyness, give can't-work information very fastperfect for the DIP example section - more of these please :)Done: http://wiki.dlang.org/DIP50#C.2B.2B_Namespaces_.28issue_7961.29
Nov 14 2013
On 11/13/2013 5:56 PM, deadalnix wrote:I think the whole point of macro is to NOT add too much feature to the language. See for instance the example I gave before to create generator. This can be macro, the feature can be implemented as a library. It is NOT achievable with expression templates. I can say with certainty that the async/await mechanism is heavily used in some codebases and with great benefit. It is being added to all languages one after another.I agree that async/await has to eventually be added to D. I'm not convinced it can or should be done with AST macros.The idea behind macros is that instead of adding new feature to the language, the language should propose a toolkit to build these features as library.I do understand this. I've not only extensively used macro systems, I've designed two successful ones and implemented other peoples' designs. I've also seen the sheer awfulness of what happens with these systems over the long term. The fascinating thing about this awfulness is people are well aware of it in everyone's macro libraries but their own.I don't think the time has come for macros in D. As discussed before, it seems like filling the gap in existing feature is more important than adding new ones. This should however be considered very seriously when the gaps has been filled.
Nov 14 2013
Am 14.11.2013 10:12, schrieb Walter Bright:I've also seen the sheer awfulness of what happens with these systems over the long term. The fascinating thing about this awfulness is people are well aware of it in everyone's macro libraries but their own.the same was said about templates AND string mixins before - but currently only the wise guys building good/great templates/mixins which are in use by everyone - no terror from the deepthe DIP needs to grow by many examples and scenarios - some sort of long term dicussion DIPI don't think the time has come for macros in D.
Nov 14 2013
On 11/14/2013 1:25 AM, dennis luehring wrote:Am 14.11.2013 10:12, schrieb Walter Bright:I don't buy that these are analogous. They are very different features.I've also seen the sheer awfulness of what happens with these systems over the long term. The fascinating thing about this awfulness is people are well aware of it in everyone's macro libraries but their own.the same was said about templates AND string mixins before - but currently only the wise guys building good/great templates/mixins which are in use by everyone - no terror from the deep
Nov 14 2013
On Thursday, 14 November 2013 at 09:12:38 UTC, Walter Bright wrote:I agree that async/await has to eventually be added to D. I'm not convinced it can or should be done with AST macros.Out of curiousity, how would that be implemented without macros? I could see it being done with macros with a rewrite and using some of the standard library (like std.parallelism), maybe. But with a language feature, you couldn't use the standard library. It seems like some parallelism code would have to leak into the runtime to get it to work as people might expect. I guess I would have thought the exact opposite from you... that this is precisely something that *should* be done with a library-defined macro.
Nov 14 2013
On Thursday, 14 November 2013 at 10:07:31 UTC, Chris Cain wrote:On Thursday, 14 November 2013 at 09:12:38 UTC, Walter Bright wrote:async await do not create parallelism.I agree that async/await has to eventually be added to D. I'm not convinced it can or should be done with AST macros.Out of curiousity, how would that be implemented without macros? I could see it being done with macros with a rewrite and using some of the standard library (like std.parallelism), maybe. But with a language feature, you couldn't use the standard library. It seems like some parallelism code would have to leak into the runtime to get it to work as people might expect. I guess I would have thought the exact opposite from you... that this is precisely something that *should* be done with a library-defined macro.
Nov 14 2013
On 11/14/2013 2:07 AM, Chris Cain wrote:I guess I would have thought the exact opposite from you... that this is precisely something that *should* be done with a library-defined macro.Again, I reiterate what experience shows happens with macro systems in the long term.
Nov 14 2013
On 11/14/13 2:17 AM, Walter Bright wrote:On 11/14/2013 2:07 AM, Chris Cain wrote:FWIW Walter talked me back around 2005-2006 into abandoning my own ideas about languages with configurable syntax. There are quite a few failings about comparing programming languages against natural languages, but here's one that I think does have value: fixed syntax is ingrained into people's notion of language, and swapping syntax within an otherwise identical linguistic context is extremely taxing on the brain. Anyone who's read with a C or C++ codebase full of macros and #if-driven code can attest how unbelievably difficult juxtapositions of the normal syntax with preprocessor syntax can quickly become. That's part of why "static if" has been so successful in D - it drives new semantics but within the same syntax. Natural languages are "humans complete" because they are the one vehicle we use to describe and manipulate our understanding of the entire reality. If configurable syntax was something necessary to model the world, it would have inevitably occurred in natural languages one way or another. Instead, all human languages (with no exception I know of) have fixed syntax and prefer to add modeling power in other ways. There must be something about this. AndreiI guess I would have thought the exact opposite from you... that this is precisely something that *should* be done with a library-defined macro.Again, I reiterate what experience shows happens with macro systems in the long term.
Nov 14 2013
On 2013-11-14 19:23, Andrei Alexandrescu wrote:FWIW Walter talked me back around 2005-2006 into abandoning my own ideas about languages with configurable syntax. There are quite a few failings about comparing programming languages against natural languages, but here's one that I think does have value: fixed syntax is ingrained into people's notion of language, and swapping syntax within an otherwise identical linguistic context is extremely taxing on the brain. Anyone who's read with a C or C++ codebase full of macros and #if-driven code can attest how unbelievably difficult juxtapositions of the normal syntax with preprocessor syntax can quickly become. That's part of why "static if" has been so successful in D - it drives new semantics but within the same syntax.AST macros cannot change the syntax or introduce new syntax. C preprocessor macros and AST macros are not the same. I'm starting to regret that I called it "macros". -- /Jacob Carlborg
Nov 14 2013
On 11/14/2013 11:18 AM, Jacob Carlborg wrote:AST macros cannot change the syntax or introduce new syntax. C preprocessor macros and AST macros are not the same. I'm starting to regret that I called it "macros".If it is powerful enough to do async/await but look like normal D syntax, then is going to suffer from these faults. (A lot of the C++ macro abuse looks like normal syntax to the user, but it behaves in a way that the casual user would find completely unexpected. In the same vein, macro assembler abuse of macros did not introduce new syntax - the syntax for the macros was straightforward. It was what those macros *did* that made them incomprehensible.)
Nov 14 2013
Am 14.11.2013 21:54, schrieb Walter Bright:(A lot of the C++ macro abuse looks like normal syntax to the user, but it behaves in a way that the casual user would find completely unexpected.same can be said about Boost Spirit templates
Nov 14 2013
On 2013-11-14 21:54, Walter Bright wrote:If it is powerful enough to do async/await but look like normal D syntax, then is going to suffer from these faults.I don't think so. The idea is to have it look consistent within the language. Take a look at __traits. It looks just like a function call, but it's far from being a function call. Classes and structs look very similar, only the keyword is different, but they are very different. -- /Jacob Carlborg
Nov 14 2013
On 11/14/2013 11:38 PM, Jacob Carlborg wrote:On 2013-11-14 21:54, Walter Bright wrote:Think about the desired feature mentioned earlier in this thread of being able to insert a "return;" statement, causing what looks like a function call to return from the caller. That's a major step increase in obfuscation, not just a detail.If it is powerful enough to do async/await but look like normal D syntax, then is going to suffer from these faults.I don't think so. The idea is to have it look consistent within the language. Take a look at __traits. It looks just like a function call, but it's far from being a function call. Classes and structs look very similar, only the keyword is different, but they are very different.
Nov 17 2013
On 2013-11-17 09:58, Walter Bright wrote:Think about the desired feature mentioned earlier in this thread of being able to insert a "return;" statement, causing what looks like a function call to return from the caller.I'm not entirely sure what you're saying. Could you please post a link to the post mentioning this or show an example.That's a major step increase in obfuscation, not just a detail.-- /Jacob Carlborg
Nov 17 2013
On 2013-11-17 11:37, Jacob Carlborg wrote:On 2013-11-17 09:58, Walter Bright wrote:I believe it is basically this: int bar() { foo(return 3); return 5; } If that program is allowed to compile, and to return 3.Think about the desired feature mentioned earlier in this thread of being able to insert a "return;" statement, causing what looks like a function call to return from the caller.I'm not entirely sure what you're saying. Could you please post a link to the post mentioning this or show an example.
Nov 17 2013
On Sunday, 17 November 2013 at 13:36:32 UTC, Simen Kjærås wrote:On 2013-11-17 11:37, Jacob Carlborg wrote:That never was in the DIP.On 2013-11-17 09:58, Walter Bright wrote:I believe it is basically this: int bar() { foo(return 3); return 5; } If that program is allowed to compile, and to return 3.Think about the desired feature mentioned earlier in this thread of being able to insert a "return;" statement, causing what looks like a function call to return from the caller.I'm not entirely sure what you're saying. Could you please post a link to the post mentioning this or show an example.
Nov 17 2013
On 11/17/2013 10:47 AM, deadalnix wrote:On Sunday, 17 November 2013 at 13:36:32 UTC, Simen Kjærås wrote:It was this by Timon Gehr essentially posting why lazy parameters weren't good enough:On 2013-11-17 11:37, Jacob Carlborg wrote:That never was in the DIP.On 2013-11-17 09:58, Walter Bright wrote:I believe it is basically this: int bar() { foo(return 3); return 5; } If that program is allowed to compile, and to return 3.Think about the desired feature mentioned earlier in this thread of being able to insert a "return;" statement, causing what looks like a function call to return from the caller.I'm not entirely sure what you're saying. Could you please post a link to the post mentioning this or show an example.On 11/13/2013 08:25 PM, Walter Bright wrote:int foo(int x){ ifthen(!x, return 2); // uh oh return 3; }Ah, found the code: void ifthen(bool cond, lazy void dg) { if (cond) dg(); }
Nov 17 2013
On 11/17/2013 09:48 PM, Walter Bright wrote:It was this by Timon Gehr essentially posting why lazy parameters weren't good enough:This code was just supposed to demonstrate that ifthen is not actually a "statement" work-alike as claimed in a previous post.On 11/13/2013 08:25 PM, Walter Bright wrote:int foo(int x){ ifthen(!x, return 2); // uh oh return 3; }Ah, found the code: void ifthen(bool cond, lazy void dg) { if (cond) dg(); }
Nov 17 2013
On 11/17/2013 1:58 PM, Timon Gehr wrote:This code was just supposed to demonstrate that ifthen is not actually a "statement" work-alike as claimed in a previous post.Ok, my apologies.
Nov 17 2013
On Sunday, 17 November 2013 at 20:48:15 UTC, Walter Bright wrote:As I understand it, Timon choosed that syntax simply to demonstrate the limitation of your proposal using a similar syntax. Not to propose a syntax.That never was in the DIP.It was this by Timon Gehr essentially posting why lazy parameters weren't good enough:On 11/13/2013 08:25 PM, Walter Bright wrote:int foo(int x){ ifthen(!x, return 2); // uh oh return 3; }Ah, found the code: void ifthen(bool cond, lazy void dg) { if (cond) dg(); }
Nov 17 2013
On 11/17/2013 7:14 PM, deadalnix wrote:As I understand it, Timon choosed that syntax simply to demonstrate the limitation of your proposal using a similar syntax. Not to propose a syntax.Ok, then I'm not seeing what AST macros do that lazy parameters / template overloading / mixin templates do not?
Nov 17 2013
On Monday, 18 November 2013 at 05:05:02 UTC, Walter Bright wrote:On 11/17/2013 7:14 PM, deadalnix wrote:2 things. First, they can act on statement or declaration. Simply not with the proposed syntax. Second they can reflect what is passed as argument and act accordingly, when the lazy expression solution cannot.As I understand it, Timon choosed that syntax simply to demonstrate the limitation of your proposal using a similar syntax. Not to propose a syntax.Ok, then I'm not seeing what AST macros do that lazy parameters / template overloading / mixin templates do not?
Nov 17 2013
On 11/17/2013 9:10 PM, deadalnix wrote:On Monday, 18 November 2013 at 05:05:02 UTC, Walter Bright wrote:If they can insert a statement or a declaration uplevel, then they are doing what I suggested with the return statement.On 11/17/2013 7:14 PM, deadalnix wrote:2 things. First, they can act on statement or declaration. Simply not with the proposed syntax.As I understand it, Timon choosed that syntax simply to demonstrate the limitation of your proposal using a similar syntax. Not to propose a syntax.Ok, then I'm not seeing what AST macros do that lazy parameters / template overloading / mixin templates do not?Second they can reflect what is passed as argument and act accordingly, when the lazy expression solution cannot.Expression templates can.
Nov 18 2013
On Monday, 18 November 2013 at 09:25:22 UTC, Walter Bright wrote:On 11/17/2013 9:10 PM, deadalnix wrote:*Expression* templates.On Monday, 18 November 2013 at 05:05:02 UTC, Walter Bright wrote:If they can insert a statement or a declaration uplevel, then they are doing what I suggested with the return statement.On 11/17/2013 7:14 PM, deadalnix wrote:2 things. First, they can act on statement or declaration. Simply not with the proposed syntax.As I understand it, Timon choosed that syntax simply to demonstrate the limitation of your proposal using a similar syntax. Not to propose a syntax.Ok, then I'm not seeing what AST macros do that lazy parameters / template overloading / mixin templates do not?Second they can reflect what is passed as argument and act accordingly, when the lazy expression solution cannot.Expression templates can.
Nov 18 2013
On 18.11.2013. 6:05, Walter Bright wrote:On 11/17/2013 7:14 PM, deadalnix wrote: Ok, then I'm not seeing what AST macros do that lazy parameters / template overloading / mixin templates do not?Well, this is just a small piece of the puzzle but I would like to be able to write (as syntax sugar): query q{ select data; } a compiler to rewrite it to: mixin(query!(q{ select data; })); if the following exists: mixin statement query (string code) { // ... } Maybe I am the only one but I found that string mixins + code generation are used this way even i Phobos and I find the first syntax much more cleaner. Or this is not in the general interest?
Nov 19 2013
On 2013-11-17 14:36, Simen Kjærås wrote:I believe it is basically this: int bar() { foo(return 3); return 5; } If that program is allowed to compile, and to return 3.I see, I guess that should work with with the DIP. -- /Jacob Carlborg
Nov 18 2013
Think about the desired feature mentioned earlier in this thread of being able to insert a "return;" statement, causing what looks like a function call to return from the caller. That's a major step increase in obfuscation, not just a detail.You do realize that, as per more strict proposal, it won't change a _single_ thing about semantics of actual D function but allows to generate another one with semantics defined by macro? It has _zero_ added ofbuscation over existing template + traits combo. You have not shown a single example which proves otherwise and keep resorting to personal experience argument instead of doing actual comparison. You have full right to do so but it does not sound like a decision made on behalf of careful reasoning.
Nov 17 2013
Walter, what do you think about allowing mixins to work with parameter list construction? Currently you cannot generate code unless it is syntactically complete on its own, this disallows parameter list construction even for syntactically correct parameter lists. The other failure point of mixins is when stringing together function calls with the dot, eg A.mixin(MYFUNC).foo; A whole lot more could be done with mixins if restrictions were relaxed just a bit more in a few key areas. I don't see too much obfuscation happening so long as the allowable constructs are carefully limited and cannot be manipulated in ways that factor into the concerns you mentioned previously. To make it clear we could have a special parammixin() and dotmixin() or whatever to ensure there's no possibility of confusion. --rt
Nov 17 2013
On Thursday, 14 November 2013 at 18:23:20 UTC, Andrei Alexandrescu wrote:On 11/14/13 2:17 AM, Walter Bright wrote:This is not proposing to configure syntax.On 11/14/2013 2:07 AM, Chris Cain wrote:FWIW Walter talked me back around 2005-2006 into abandoning my own ideas about languages with configurable syntax.I guess I would have thought the exact opposite from you... that this is precisely something that *should* be done with a library-defined macro.Again, I reiterate what experience shows happens with macro systems in the long term.There are quite a few failings about comparing programming languages against natural languages, but here's one that I think does have value: fixed syntax is ingrained into people's notion of language, and swapping syntax within an otherwise identical linguistic context is extremely taxing on the brain. Anyone who's read with a C or C++ codebase full of macros and #if-driven code can attest how unbelievably difficult juxtapositions of the normal syntax with preprocessor syntax can quickly become. That's part of why "static if" has been so successful in D - it drives new semantics but within the same syntax.C macro can introduce new syntax. This cannot.Natural languages are "humans complete" because they are the one vehicle we use to describe and manipulate our understanding of the entire reality. If configurable syntax was something necessary to model the world, it would have inevitably occurred in natural languages one way or another. Instead, all human languages (with no exception I know of) have fixed syntax and prefer to add modeling power in other ways. There must be something about this. AndreiI think this very post pretty much show that you missed the point of the DIP.
Nov 14 2013
On 11/14/2013 11:40 AM, deadalnix wrote:This is not proposing to configure syntax.Right, it is about inserting arbitrarily different meaning into existing syntax. For example, I have a friend from the middle east who worked at Microsoft. His english was excellent. But sometimes he'd get tripped up - for example, he'd take his idea to his boss, who'd discuss it, and then say: "fine" He took that to mean "my boss approves of my great idea!" Unfortunately, "fine" has undergone a meaning reversal colloquially, and actually means "your idea sux". This wound up getting him into trouble. There were a few other phrases like this with unintentionally hilarious misunderstandings. (Also, a popular way of encrypting communications is to have private meanings for phrases like "my cat ate my homework" meaning "initiate Operation X".) Now, let's take the AST macros, and pass it "4+3". Apparently is a feature that the macro can transform this to produce "hello" as the result. The result is that although the language looks the same, there is no "anchor" a person can rely on to indicate the meaning. The meaning of "fine" is reversed, so to speak. The riposte is, of course, every feature can be abused and good programmers won't do that. Unfortunately, it's IN THE VERY NATURE of macros to be abusive, and even the very best programmers can and will take it to the limit. They will see and decry the abuse in everyone else's code but their own, which they will justify. As I said, I see this over and over again. On the other hand, with string mixins, it is immediately obvious that one is dealing with different syntax, and so expect something different to happen.
Nov 14 2013
On Thu, Nov 14, 2013 at 01:12:11PM -0800, Walter Bright wrote:On 11/14/2013 11:40 AM, deadalnix wrote:[...]This is not proposing to configure syntax.Right, it is about inserting arbitrarily different meaning into existing syntax.Now, let's take the AST macros, and pass it "4+3". Apparently is a feature that the macro can transform this to produce "hello" as the result. The result is that although the language looks the same, there is no "anchor" a person can rely on to indicate the meaning. The meaning of "fine" is reversed, so to speak.[...]On the other hand, with string mixins, it is immediately obvious that one is dealing with different syntax, and so expect something different to happen.What if macros adopted an overtly different syntax? T -- English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
Nov 14 2013
On 11/14/2013 1:34 PM, H. S. Teoh wrote:What if macros adopted an overtly different syntax?That would be better, but I don't think enough better.
Nov 17 2013
On 2013-11-17 10:00, Walter Bright wrote:That would be better, but I don't think enough better.Then why to we have UDA's with the same syntax as language attributes and why do we have operator overloading. You can hide arbitrary code behind operator overloading. -- /Jacob Carlborg
Nov 17 2013
On 11/17/2013 2:38 AM, Jacob Carlborg wrote:On 2013-11-17 10:00, Walter Bright wrote:1. I don't believe we can decide on language features by analogy. D is complex enough that one can use analogy to justify anything. 2. You cannot do anything behind a function call - the 'return' discussed earlier, and async/await for another, i.e. operator overloading cannot introduce control flow, cannot introduce variables into the current scope, etc.That would be better, but I don't think enough better.Then why to we have UDA's with the same syntax as language attributes and why do we have operator overloading. You can hide arbitrary code behind operator overloading.
Nov 17 2013
On 2013-11-17 21:52, Walter Bright wrote:1. I don't believe we can decide on language features by analogy. D is complex enough that one can use analogy to justify anything. 2. You cannot do anything behind a function call - the 'return' discussed earlier, and async/await for another, i.e. operator overloading cannot introduce control flow, cannot introduce variables into the current scope, etc.You can turn this: BigInt(3) + 7; Into something that is not 10. You cannot do anything behind a macro. You cannot introduce new syntax. -- /Jacob Carlborg
Nov 18 2013
On 11/18/2013 09:22 AM, Jacob Carlborg wrote:On 2013-11-17 21:52, Walter Bright wrote:Well, you could do: screwUp int foo(){ return 3+7; } assert(foo()!=10);1. I don't believe we can decide on language features by analogy. D is complex enough that one can use analogy to justify anything. 2. You cannot do anything behind a function call - the 'return' discussed earlier, and async/await for another, i.e. operator overloading cannot introduce control flow, cannot introduce variables into the current scope, etc.You can turn this: BigInt(3) + 7; Into something that is not 10. You cannot do anything behind a macro. You cannot introduce new syntax.
Nov 18 2013
On 2013-11-18 10:12, Timon Gehr wrote:Well, you could do: screwUp int foo(){ return 3+7; } assert(foo()!=10);Sure, what I'm saying is that you can do stupid things with other features than macros. -- /Jacob Carlborg
Nov 18 2013
On 11/18/2013 1:14 AM, Jacob Carlborg wrote:Sure, what I'm saying is that you can do stupid things with other features than macros.Yes, you can write terrible code with all features. My point is not that you can do stupid things with macros. It is that macros encourage this to a high degree, and in fact the flexibility that macros have over lazy parameters / expression templates / mixin templates are exactly those features that are abused to the point it is hard to see much good come from them. I am not making this up, this is what happens with macro systems again and again. I know this is a difficult position to argue from and convince people about. D has a deliberate lack of capability in some areas because long experience shows that little good comes from them. Examples include lack of ability to overload && and ||, and lack of expression support for version statements. This is not because these features are hard - they're easy to implement. I've seen attempts to replace version statements with static if in order to get back the ugliness, and the result is ugly and unnecessary and damned hard to figure out what was actually intended and why it didn't work. I fear that implementing these things with the idea that they'll somehow be used with restraint is a pipe dream and that D will degenerate into an ugly snarl that everyone hates, and then some D-Go will be invented that everyone will cheer because it won't allow such code to be written. Case in point - again and again I see utterly wretched use of macros in C++ from the top level of C++ programmers who really ought to know better. Want to see a lovely example? Take a look at the C header files for openssl: https://github.com/D-Programming-Deimos/openssl/tree/master/C This is not unusual. I try to put my money where my mouth is. If you look at older parts of dmd, you'll see macro abuse that I cleverly wrote. The newer bits contain fewer and fewer use of any macros, and I've made an ongoing effort to try and eliminate all of it (yebblies has campaigned to get rid of it, too, even crap I tried to hang on to). This has been done this without compromise on performance and usability and readability of the code - and I hope you'll agree that it looks nice without the usual rat's nest of preprocessor abuse one sees in typical C++ code.
Nov 18 2013
On Monday, 18 November 2013 at 09:55:42 UTC, Walter Bright wrote:On 11/18/2013 1:14 AM, Jacob Carlborg wrote:to SQL WHERE condition. For example s => s.Number > 2 && s.Number < 20 can be translated to ... WHERE s.Number > 2 AND s.Number < 20 It is interesting function, because it allow to write hard code this code hides poorly standardized SQL for the well-standardized language. limitations for ast macros. May be they allowed only for lambda? This is a general macro-feature which I had like to see in D.Sure, what I'm saying is that you can do stupid things with other features than macros.Yes, you can write terrible code with all features. My point is not that you can do stupid things with macros. It is that macros encourage this to a high degree, and in fact the flexibility that macros have over lazy parameters / expression templates / mixin templates are exactly those features that are abused to the point it is hard to see much good come from them. I am not making this up, this is what happens with macro systems again and again. I know this is a difficult position to argue from and convince people about. D has a deliberate lack of capability in some areas because long experience shows that little good comes from them. Examples include lack of ability to overload && and ||, and lack of expression support for version statements. This is not because these features are hard - they're easy to implement. I've seen attempts to replace version statements with static if in order to get back the ugliness, and the result is ugly and unnecessary and damned hard to figure out what was actually intended and why it didn't work. I fear that implementing these things with the idea that they'll somehow be used with restraint is a pipe dream and that D will degenerate into an ugly snarl that everyone hates, and then some D-Go will be invented that everyone will cheer because it won't allow such code to be written. Case in point - again and again I see utterly wretched use of macros in C++ from the top level of C++ programmers who really ought to know better. Want to see a lovely example? Take a look at the C header files for openssl: https://github.com/D-Programming-Deimos/openssl/tree/master/C This is not unusual. I try to put my money where my mouth is. If you look at older parts of dmd, you'll see macro abuse that I cleverly wrote. The newer bits contain fewer and fewer use of any macros, and I've made an ongoing effort to try and eliminate all of it (yebblies has campaigned to get rid of it, too, even crap I tried to hang on to). This has been done this without compromise on performance and usability and readability of the code - and I hope you'll agree that it looks nice without the usual rat's nest of preprocessor abuse one sees in typical C++ code.
Nov 18 2013
On Monday, 18 November 2013 at 16:03:54 UTC, IgorStepanov wrote:to SQL WHERE condition. For example s => s.Number > 2 && s.Number < 20 can be translated to ... WHERE s.Number > 2 AND s.Number < 20 It is interesting function, because it allow to write hard code Also this code hides poorly standardized SQL for the well-standardized language. some limitations for ast macros. May be they allowed only for lambda? This is a general macro-feature which I had like to see in D.expression trees. Essentially, it allows the compiler to generate an expression tree of the lambda expression which your library parses to do some work. It doesn't inject any code, and it's done at runtime. I could be wrong about the exact details, but essentially it comes down to the compiler passing in an expression tree into your method, and then your method parsing it at runtime and doing something with the results; it can't be used to generate new code.
Nov 18 2013
On Monday, 18 November 2013 at 19:21:35 UTC, Kapps wrote:On Monday, 18 November 2013 at 16:03:54 UTC, IgorStepanov wrote:May be this way is good for D? And CTFE allow to parse this tree at compile-time. Something like: property Collection where(alias cond, Collection)(Collection c) { enum ast = cond.astof; static if(is(Collection : DBResultSet)) { string where_cond = generateCondition!(ast, Collection); return c.doWhere(where_cond); } else { ... } } ... auto result = db.myItems.where!(x => x.Count > 10);expression to SQL WHERE condition. For example s => s.Number > 2 && s.Number < 20 can be translated to ... WHERE s.Number > 2 AND s.Number < 20 It is interesting function, because it allow to write hard (SQL). Also this code hides poorly standardized SQL for the well-standardized language. some limitations for ast macros. May be they allowed only for lambda? This is a general macro-feature which I had like to see in D.expression trees. Essentially, it allows the compiler to generate an expression tree of the lambda expression which your library parses to do some work. It doesn't inject any code, and it's done at runtime. I could be wrong about the exact details, but essentially it comes down to the compiler passing in an expression tree into your method, and then your method parsing it at runtime and doing something with the results; it can't be used to generate new code.
Nov 18 2013
On 2013-11-18 22:08, IgorStepanov wrote:May be this way is good for D? And CTFE allow to parse this tree at compile-time. Something like: property Collection where(alias cond, Collection)(Collection c) { enum ast = cond.astof; static if(is(Collection : DBResultSet)) { string where_cond = generateCondition!(ast, Collection); return c.doWhere(where_cond); } else { ... } } ... auto result = db.myItems.where!(x => x.Count > 10);The idea is to have something more general. Linq is just one example of what can be implemented. -- /Jacob Carlborg
Nov 18 2013
On 11/18/2013 11:21 AM, Kapps wrote:On Monday, 18 November 2013 at 16:03:54 UTC, IgorStepanov wrote: it can't be used to generate new code.Sure it can. Generate lambda expression tree; invoke Compile(). You just can't rewrite existing code.
Nov 19 2013
Case in point - again and again I see utterly wretched use of macros in C++ from the top level of C++ programmers who really ought to know better. Want to see a lovely example? Take a look at the C header files for openssl: https://github.com/D-Programming-Deimos/openssl/tree/master/C This is not unusual. I try to put my money where my mouth is. If you look at older parts of dmd, you'll see macro abuse that I cleverly wrote. The newer bits contain fewer and fewer use of any macros, and I've made an ongoing effort to try and eliminate all of it (yebblies has campaigned to get rid of it, too, even crap I tried to hang on to). This has been done this without compromise on performance and usability and readability of the code - and I hope you'll agree that it looks nice without the usual rat's nest of preprocessor abuse one sees in typical C++ code.Now, now Walter, that is C not C++. In C++ we would use Boost Preprocessor:) Also C macros are just crappy textural replacement, I would assume an AST macro would be along the lines of lisp, which doesn't have much of anything to do with the shitty macro system in C despite using the word "macro". Not that I care so whatevars!
Nov 18 2013
On Monday, 18 November 2013 at 09:12:19 UTC, Timon Gehr wrote:Well, you could do: screwUp int foo(){ return 3+7; } assert(foo()!=10);Anything that allows it routinely should be banned whenever macros are accepted or not. Modifying existing "normal" symbols = no way.
Nov 18 2013
On 2013-11-18 16:59, Dicebot wrote:Anything that allows it routinely should be banned whenever macros are accepted or not. Modifying existing "normal" symbols = no way.The whole point of macros is to modify symbols. Turning this: auto p = Person.where(q => q.name == "John"); To an SQL query. -- /Jacob Carlborg
Nov 18 2013
On Monday, 18 November 2013 at 21:09:26 UTC, Jacob Carlborg wrote:On 2013-11-18 16:59, Dicebot wrote:You don't need to modify actual input lambda for this to become SQL query. I fully support macros as convenient way for AST reflection and related code generation but not a single step further. Changing semantics of existing valid piece of code is never worth it.Anything that allows it routinely should be banned whenever macros are accepted or not. Modifying existing "normal" symbols = no way.The whole point of macros is to modify symbols. Turning this: auto p = Person.where(q => q.name == "John"); To an SQL query.
Nov 18 2013
On 11/18/2013 11:09 PM, Dicebot wrote:On Monday, 18 November 2013 at 21:09:26 UTC, Jacob Carlborg wrote:So you oppose macro attributes?On 2013-11-18 16:59, Dicebot wrote:You don't need to modify actual input lambda for this to become SQL query. I fully support macros as convenient way for AST reflection and related code generation but not a single step further. Changing semantics of existing valid piece of code is never worth it.Anything that allows it routinely should be banned whenever macros are accepted or not. Modifying existing "normal" symbols = no way.The whole point of macros is to modify symbols. Turning this: auto p = Person.where(q => q.name == "John"); To an SQL query.
Nov 18 2013
On Monday, 18 November 2013 at 22:47:59 UTC, Timon Gehr wrote:So you oppose macro attributes?Yes. For me proper "macro attribute" is just an UDA that can be used by macro to tweak code generation. Actually I think I'd oppose a very large part of this specific DIP when it comes to exact syntax and usage models - I am more interested in "AST" than in "macro" part.
Nov 19 2013
On Tuesday, 19 November 2013 at 13:10:44 UTC, Dicebot wrote:On Monday, 18 November 2013 at 22:47:59 UTC, Timon Gehr wrote:This topic really took off. I'm afraid to say that I've only gotten through about half of it so far. I noticed computation expressions were mentioned, but has anyone exactly like what is being proposed here. http://msdn.microsoft.com/en-us/library/vstudio/dd233212.aspx The LINQ sample in the DIP kinda rubs me the wrong way. LINQ does not generate imperative code, but rather a chain of extension methods. More importantly, it does not eagerly chomp through all the data. It runs on IEnumerable, and is therefore lazy. (Like D ranges.) I wouldn't mind, however, if I saw these macros generate state machines specifically made for a given query.So you oppose macro attributes?Yes. For me proper "macro attribute" is just an UDA that can be used by macro to tweak code generation. Actually I think I'd oppose a very large part of this specific DIP when it comes to exact syntax and usage models - I am more interested in "AST" than in "macro" part.
Nov 19 2013
On Monday, 18 November 2013 at 22:09:35 UTC, Dicebot wrote:On Monday, 18 November 2013 at 21:09:26 UTC, Jacob Carlborg wrote:And that's exactly the kind of thing Walter doesn't want to see.On 2013-11-18 16:59, Dicebot wrote:You don't need to modify actual input lambda for this to become SQL query. I fully support macros as convenient way for AST reflection and related code generation but not a single step further. Changing semantics of existing valid piece of code is never worth it.Anything that allows it routinely should be banned whenever macros are accepted or not. Modifying existing "normal" symbols = no way.The whole point of macros is to modify symbols. Turning this: auto p = Person.where(q => q.name == "John"); To an SQL query.
Nov 18 2013
On 2013-11-18 23:09, Dicebot wrote:You don't need to modify actual input lambda for this to become SQL query. I fully support macros as convenient way for AST reflection and related code generation but not a single step further. Changing semantics of existing valid piece of code is never worth it.Well, it depends on how you look at it. You don't need to modify the lambda, but you're changing the meaning of it. -- /Jacob Carlborg
Nov 18 2013
On Tuesday, 19 November 2013 at 07:23:52 UTC, Jacob Carlborg wrote:Well, it depends on how you look at it. You don't need to modify the lambda, but you're changing the meaning of it.Not really. You won't say that this snippet changes the meaning of lambda, do you? ``` foo(a => a*2); // ... bool foo(T)(T func) { // does not even call `func` and does something unrelated return is(ReturnType!T == int); } ``` This is pretty much the same. Functions and templates can do arbitrary things unrelated to their input and we do not call it "changing the meaning" of the input. Macros are not much different here. Though I'd still prefer requirement for explicit "macro!" syntax or something similar, just to make clear that code gen is incoming.
Nov 19 2013
On 2013-11-19 14:16, Dicebot wrote:Not really. You won't say that this snippet changes the meaning of lambda, do you? ``` foo(a => a*2); // ... bool foo(T)(T func) { // does not even call `func` and does something unrelated return is(ReturnType!T == int); } ```No, I guess not. -- /Jacob Carlborg
Nov 19 2013
On 11/18/2013 12:22 AM, Jacob Carlborg wrote:On 2013-11-17 21:52, Walter Bright wrote:That is not at all what I was talking about. I was talking about: 3+7 being transformed by AST manipulation into something that is not 10.1. I don't believe we can decide on language features by analogy. D is complex enough that one can use analogy to justify anything. 2. You cannot do anything behind a function call - the 'return' discussed earlier, and async/await for another, i.e. operator overloading cannot introduce control flow, cannot introduce variables into the current scope, etc.You can turn this: BigInt(3) + 7; Into something that is not 10.You cannot do anything behind a macro. You cannot introduce new syntax.
Nov 18 2013
On Thursday, 14 November 2013 at 21:12:11 UTC, Walter Bright wrote:On the other hand, with string mixins, it is immediately obvious that one is dealing with different syntax, and so expect something different to happen.This is exactly the reason why I have been asking to make denoting macro usage with explicit keyword mandatory, like it is done with mixins. It does not change much about the concept itself and is not worth fixating upon as a blocker.
Nov 14 2013
On Thursday, 14 November 2013 at 21:12:11 UTC, Walter Bright wrote:On 11/14/2013 11:40 AM, deadalnix wrote:You have a point with the example, but just as with templates ( the distinctive binary ! operator), making macros not to look first class language elements when called does great job with very foreign. #loop ( ) { -- code -- } Maybe for macros that return macros it would be ugly: But just as in C where the -> operator automatically dereferences pointers, it could be solved. (Just for fun)This is not proposing to configure syntax.Right, it is about inserting arbitrarily different meaning into existing syntax. For example, I have a friend from the middle east who worked at Microsoft. His english was excellent. But sometimes he'd get tripped up - for example, he'd take his idea to his boss, who'd discuss it, and then say: "fine" He took that to mean "my boss approves of my great idea!" Unfortunately, "fine" has undergone a meaning reversal colloquially, and actually means "your idea sux". This wound up getting him into trouble. There were a few other phrases like this with unintentionally hilarious misunderstandings. (Also, a popular way of encrypting communications is to have private meanings for phrases like "my cat ate my homework" meaning "initiate Operation X".) Now, let's take the AST macros, and pass it "4+3". Apparently is a feature that the macro can transform this to produce "hello" as the result. The result is that although the language looks the same, there is no "anchor" a person can rely on to indicate the meaning. The meaning of "fine" is reversed, so to speak. The riposte is, of course, every feature can be abused and good programmers won't do that. Unfortunately, it's IN THE VERY NATURE of macros to be abusive, and even the very best programmers can and will take it to the limit. They will see and decry the abuse in everyone else's code but their own, which they will justify. As I said, I see this over and over again. On the other hand, with string mixins, it is immediately obvious that one is dealing with different syntax, and so expect something different to happen.
Nov 14 2013
On Thursday, 14 November 2013 at 21:12:11 UTC, Walter Bright wrote:On 11/14/2013 11:40 AM, deadalnix wrote:Yes, but EXPLICITELY.This is not proposing to configure syntax.Right, it is about inserting arbitrarily different meaning into existing syntax.(Also, a popular way of encrypting communications is to have private meanings for phrases like "my cat ate my homework" meaning "initiate Operation X".)Note that you do not pretend that sentence with "THIS IS AN ENCRYPTED SENTENCE, HERE TO DECRYPT IT DO XXX".Now, let's take the AST macros, and pass it "4+3". Apparently is a feature that the macro can transform this to produce "hello" as the result. The result is that although the language looks the same, there is no "anchor" a person can rely on to indicate the meaning. The meaning of "fine" is reversed, so to speak.mymacro(4+3); // <= can be "hello" myfunction(4+3); // <= can be "hello as well" Quite frankly, this isn't really convincing.The riposte is, of course, every feature can be abused and good programmers won't do that. Unfortunately, it's IN THE VERY NATURE of macros to be abusive, and even the very best programmers can and will take it to the limit. They will see and decry the abuse in everyone else's code but their own, which they will justify. As I said, I see this over and over again.I can find article on the internet saying the exact same thing for any feature ever invented. You'll find quite easily some about templates or operator overloading, but if you go in Functionnalland, you'll find the same about virtual dispatch and inheritance. If you go in OOPland, you'll find the exact same argument for monads. You are qualifying the nature of macro here, that is not an argument. "Macros are bad, so I conclude macro are bad."On the other hand, with string mixins, it is immediately obvious that one is dealing with different syntax, and so expect something different to happen.string mixins + a CTFE usable lexer+parser+D codegen from AST would achieve something close to the macros proposed here. This would obviously require quite a lot of work and is doomed to be dramatically slow and resources hungry, less hygienic (as identifier are implicitly resolved in the mixed in scope rather than explicitly) but quite close in term of capabilities. You can't argue that string mixin is good while AST macro is bad.
Nov 14 2013
On Thursday, 14 November 2013 at 22:06:06 UTC, deadalnix wrote:mymacro(4+3); // <= can be "hello" myfunction(4+3); // <= can be "hello as well" Quite frankly, this isn't really convincing.True but you will hardly use myfunction as an extension to the language. If I understand the issues, I quite understand Walter's reluctance to add such a feature. Once you add it, you add the capability to change the language, or to create an entirely new language. If you let it, no matter how loud you cry, people *will* abuse the feature, and they will do it from day one. The C++ templates experiment shows what happens when you do that. We don't want to repeat the same mistakes. Basically, people want to change the language, but without having to discuss their own extensions in the newsgroups. It's sometimes handy, but you'll end up with crappy features all over the place.
Nov 17 2013
On 2013-11-17 09:18, SomeDude wrote:True but you will hardly use myfunction as an extension to the language. If I understand the issues, I quite understand Walter's reluctance to add such a feature. Once you add it, you add the capability to change the language, or to create an entirely new language. If you let it, no matter how loud you cry, people *will* abuse the feature, and they will do it from day one. The C++ templates experiment shows what happens when you do that. We don't want to repeat the same mistakes.We already have templates and operator overloading. Perhaps we should remove those, we don't want to take the chance of people abusing them.Basically, people want to change the language, but without having to discuss their own extensions in the newsgroups. It's sometimes handy, but you'll end up with crappy features all over the place.No, people want a general solution that doesn't require the language to be extended each time they come up with a useful feature. -- /Jacob Carlborg
Nov 17 2013
On Sunday, 17 November 2013 at 10:41:46 UTC, Jacob Carlborg wrote:We already have templates and operator overloading. Perhaps we should remove those, we don't want to take the chance of people abusing them.D templates have been designed with the past experience of C++ templates in mind, so the mistakes have been avoided. With macros, we don't have much experience; Lisp macros can't count as the language is too different.Sorry but I tend to value the feedback of people who have already put some serious effort in expression templates and mixins like Don.Basically, people want to change the language, but without having to discuss their own extensions in the newsgroups. It's sometimes handy, but you'll end up with crappy features all over the place.No, people want a general solution that doesn't require the language to be extended each time they come up with a useful feature.
Nov 18 2013
On Monday, 18 November 2013 at 21:38:08 UTC, SomeDude wrote:The very first code I wrote in D used expression templates to do vector/matrices computation. I'm really well aware of they are and what they can do (and what error messages you get when you do something wrong).No, people want a general solution that doesn't require the language to be extended each time they come up with a useful feature.Sorry but I tend to value the feedback of people who have already put some serious effort in expression templates and mixins like Don.
Nov 18 2013
On 11/14/2013 2:06 PM, deadalnix wrote:You can't argue that string mixin is good while AST macro is bad.True, but you also cannot argue that since D has string mixins it must also have AST macros. What macros do is bless, encourage, and make inevitable a particularly abusive style of programming. D already has super powerful metaprogramming abilities that we are far from exploring the limits of. I don't think we should be adding on even more that experience has shown goes quickly out of control.
Nov 17 2013
On Sunday, 17 November 2013 at 09:13:04 UTC, Walter Bright wrote:On 11/14/2013 2:06 PM, deadalnix wrote:Yeah, you are right, but I doubt anybody would use macros in production code without considering much less powerful constructs of the language to solve the problem. In hobby projects, I don't mind if create spaghetti code while experimenting.You can't argue that string mixin is good while AST macro is bad.True, but you also cannot argue that since D has string mixins it must also have AST macros. What macros do is bless, encourage, and make inevitable a particularly abusive style of programming. D already has super powerful metaprogramming abilities that we are far from exploring the limits of. I don't think we should be adding on even more that experience has shown goes quickly out of control.
Nov 17 2013
On Thursday, 14 November 2013 at 18:23:20 UTC, Andrei Alexandrescu wrote:On 11/14/13 2:17 AM, Walter Bright wrote:D's syntax remains the same ( statements, expressions, function calling, numbers etc. ). These AST manipulation tools just define new words or language constructs. Human languages tend to be altered as times passes and the needs change. That's why new words appear. Even the grammar is not the same as the one my grandparents used.On 11/14/2013 2:07 AM, Chris Cain wrote:FWIW Walter talked me back around 2005-2006 into abandoning my own ideas about languages with configurable syntax. There are quite a few failings about comparing programming languages against natural languages, but here's one that I think does have value: fixed syntax is ingrained into people's notion of language, and swapping syntax within an otherwise identical linguistic context is extremely taxing on the brain. Anyone who's read with a C or C++ codebase full of macros and #if-driven code can attest how unbelievably difficult juxtapositions of the normal syntax with preprocessor syntax can quickly become. That's part of why "static if" has been so successful in D - it drives new semantics but within the same syntax. Natural languages are "humans complete" because they are the one vehicle we use to describe and manipulate our understanding of the entire reality. If configurable syntax was something necessary to model the world, it would have inevitably occurred in natural languages one way or another. Instead, all human languages (with no exception I know of) have fixed syntax and prefer to add modeling power in other ways. There must be something about this. AndreiI guess I would have thought the exact opposite from you... that this is precisely something that *should* be done with a library-defined macro.Again, I reiterate what experience shows happens with macro systems in the long term.
Nov 14 2013
On Thursday, 14 November 2013 at 19:42:36 UTC, Zsombor Barna wrote:D's syntax remains the same ( statements, expressions, function calling, numbers etc. ). These AST manipulation tools just define new words or language constructs. Human languages tend to be altered as times passes and the needs change. That's why new words appear. Even the grammar is not the same as the one my grandparents used.Which shows all the problems raised by Walter: 1. you need an entry in the dictionary that you need to look up for each new word that someone has introduced, 2. with natural language, you don't need to know its *exact* semantics when you use a new word, while in programming it is mandatory, 3. you *don't* want your programming language to arbitrarily change over time. That's probably the biggest issue.
Nov 17 2013
On Thursday, 14 November 2013 at 18:23:20 UTC, Andrei Alexandrescu wrote: [...]Natural languages are "humans complete" because they are the one vehicle we use to describe and manipulate our understanding of the entire reality. If configurable syntax was something necessary to model the world, it would have inevitably occurred in natural languages one way or another. Instead, all human languages (with no exception I know of) have fixed syntax and prefer to add modeling power in other ways. There must be something about this. AndreiNot an unreasonable assumption to make, so assuming it's true, then we need a fixed way to deal with a certain set of problems that so far cannot be done reasonably (or at all) in current D. One case, which I also so happen to want to solve, is the async/await type of problem. There's simply no reasonable solution available other than through extensions to the language, which may or may not ever materialize. It's very frustrating when you want to explore possibilities today rather than wait for an extension that may never arrive. Adding in the async/await extensions can help solve only that specific problem, but how many other types of problems that are similar to this one will programmers still want to solve? A more general solution would seem to be far more useful. The other simple problem I encountered, at first seems like a mixin can deal with or perhaps a template, but current D simply cannot do it in a reasonable way that I'm aware of. I want to be able to pass an argument to an "inspect" function, that will log or display the symbol name of the top-level argument and it's corresponding value. Example: int a = 300; inspect( a ); // or inspect!a; The only way I can do this is through double entry of the item to inspect eg inspect( a.stringof, a ); // error prone and irritatingly redundant I can get some success using an alias template parameter, but it does not work in general, only in a few cases will it work, so templates are not a solution without some additional enhancements. May be by adding in something like __ARGS__, or expanding on__traits can solve this type of problem, but there's no doubt many other scenarios that will require similar extensions that users of the language cannot implement. There's no end to this without much better access to reflection. --rt
Nov 14 2013
On Thursday, 14 November 2013 at 09:12:38 UTC, Walter Bright wrote:I do understand this. I've not only extensively used macro systems, I've designed two successful ones and implemented other peoples' designs. I've also seen the sheer awfulness of what happens with these systems over the long term. The fascinating thing about this awfulness is people are well aware of it in everyone's macro libraries but their own.What kind of macro systems are you talking about? C-like macros? Assembly macros? Lisp-like macros? It seems that Jacob's proposed system is similar to none of these.
Nov 14 2013
On 11/14/2013 9:08 AM, Meta wrote:What kind of macro systems are you talking about? C-like macros? Assembly macros? Lisp-like macros? It seems that Jacob's proposed system is similar to none of these.See my first comment in this thread - it's an ancestor to this one.
Nov 14 2013
On Thursday, 14 November 2013 at 17:55:57 UTC, Walter Bright wrote:On 11/14/2013 9:08 AM, Meta wrote:I'm using the website forum, so I see posts in a continuous format, not a threaded view. Anyway, it seems like assembly macros are actually quite similar to Lisp macros. Again, it seems like what Jacob proposes is not really much like Lisp macros, nor C macros.What kind of macro systems are you talking about? C-like macros? Assembly macros? Lisp-like macros? It seems that Jacob's proposed system is similar to none of these.See my first comment in this thread - it's an ancestor to this one.
Nov 14 2013
On Thursday, 14 November 2013 at 19:22:08 UTC, Meta wrote:On Thursday, 14 November 2013 at 17:55:57 UTC, Walter Bright wrote:At the top of the page you should have "view mode" links which supports a threaded view.On 11/14/2013 9:08 AM, Meta wrote:I'm using the website forum, so I see posts in a continuous format, not a threaded view. Anyway, it seems like assembly macros are actually quite similar to Lisp macros. Again, it seems like what Jacob proposes is not really much like Lisp macros, nor C macros.What kind of macro systems are you talking about? C-like macros? Assembly macros? Lisp-like macros? It seems that Jacob's proposed system is similar to none of these.See my first comment in this thread - it's an ancestor to this one.
Nov 14 2013
On Thursday, 14 November 2013 at 19:27:42 UTC, simendsjo wrote:At the top of the page you should have "view mode" links which supports a threaded view.Neat. I have my browser set up to auto-login, so I rarely, if ever, have to look up there.
Nov 14 2013
On 2013-11-14 01:16, Walter Bright wrote:Yes. But that's a good thing. I'd be pretty skeptical of the value of an AST macro that took 3+4 and changed it so it did something other than compute 7.You can still do stupid things like that with operator overloading. Not on built-in types, but on user defined types. Every language allows you to do stupid things, one way or another. -- /Jacob Carlborg
Nov 13 2013
On 11/13/2013 11:37 PM, Jacob Carlborg wrote:On 2013-11-14 01:16, Walter Bright wrote:Sure, but the issue is that expression templates are not for "int+int", but for "T+int". My question is what value would there be in a rewrite of "int+int" to mean something different.Yes. But that's a good thing. I'd be pretty skeptical of the value of an AST macro that took 3+4 and changed it so it did something other than compute 7.You can still do stupid things like that with operator overloading. Not on built-in types, but on user defined types. Every language allows you to do stupid things, one way or another.
Nov 14 2013
Am 14.11.2013 09:53, schrieb Walter Bright:On 11/13/2013 11:37 PM, Jacob Carlborg wrote:"int + int" could be part of an PC<->GPU kombination that generates CUDA- and D-interchange code at compiletimeOn 2013-11-14 01:16, Walter Bright wrote:Sure, but the issue is that expression templates are not for "int+int", but for "T+int". My question is what value would there be in a rewrite of "int+int" to mean something different.Yes. But that's a good thing. I'd be pretty skeptical of the value of an AST macro that took 3+4 and changed it so it did something other than compute 7.You can still do stupid things like that with operator overloading. Not on built-in types, but on user defined types. Every language allows you to do stupid things, one way or another.
Nov 14 2013
Am 14.11.2013 10:06, schrieb dennis luehring:Am 14.11.2013 09:53, schrieb Walter Bright:or like Don Blade Engine with string mixins could produce "high performance x87 asm" code for normal D expressionsOn 11/13/2013 11:37 PM, Jacob Carlborg wrote:"int + int" could be part of an PC<->GPU kombination that generates CUDA- and D-interchange code at compiletimeOn 2013-11-14 01:16, Walter Bright wrote:Sure, but the issue is that expression templates are not for "int+int", but for "T+int". My question is what value would there be in a rewrite of "int+int" to mean something different.Yes. But that's a good thing. I'd be pretty skeptical of the value of an AST macro that took 3+4 and changed it so it did something other than compute 7.You can still do stupid things like that with operator overloading. Not on built-in types, but on user defined types. Every language allows you to do stupid things, one way or another.
Nov 14 2013
On 11/14/2013 1:08 AM, dennis luehring wrote:Am 14.11.2013 10:06, schrieb dennis luehring:Good example, but still quite doable using type T instead.Am 14.11.2013 09:53, schrieb Walter Bright:or like Don Blade Engine with string mixins could produce "high performance x87 asm" code for normal D expressionsOn 11/13/2013 11:37 PM, Jacob Carlborg wrote:"int + int" could be part of an PC<->GPU kombination that generates CUDA- and D-interchange code at compiletimeOn 2013-11-14 01:16, Walter Bright wrote:Sure, but the issue is that expression templates are not for "int+int", but for "T+int". My question is what value would there be in a rewrite of "int+int" to mean something different.Yes. But that's a good thing. I'd be pretty skeptical of the value of an AST macro that took 3+4 and changed it so it did something other than compute 7.You can still do stupid things like that with operator overloading. Not on built-in types, but on user defined types. Every language allows you to do stupid things, one way or another.
Nov 14 2013
On Wednesday, 13 November 2013 at 08:45:13 UTC, Walter Bright wrote:On 11/13/2013 12:03 AM, Jacob Carlborg wrote:Yes, they can reflect the ast provided and act accordingly.Again, operator overloading in D is too limiting to implement something Linq like.Ok, let's set aside the opEquals and opCmp issue for the moment. Can AST macros do anything that expression templates cannot?
Nov 13 2013
On 11/13/2013 1:15 AM, deadalnix wrote:On Wednesday, 13 November 2013 at 08:45:13 UTC, Walter Bright wrote:The reflection ability is not something specific to an AST, it could be added so that any expression node can be reflected. We already do much of that with __traits.On 11/13/2013 12:03 AM, Jacob Carlborg wrote:Yes, they can reflect the ast provided and act accordingly.Again, operator overloading in D is too limiting to implement something Linq like.Ok, let's set aside the opEquals and opCmp issue for the moment. Can AST macros do anything that expression templates cannot?
Nov 13 2013
On Wednesday, 13 November 2013 at 19:19:32 UTC, Walter Bright wrote:The reflection ability is not something specific to an AST, it could be added so that any expression node can be reflected. We already do much of that with __traits.Yes, that is why Dicebot was mentioning the parallel with compile time reflection.
Nov 13 2013
On 2013-11-13 20:19, Walter Bright wrote:The reflection ability is not something specific to an AST, it could be added so that any expression node can be reflected. We already do much of that with __traits.Yes, I been thinking of ways to expand __traits. When there's enough of __traits it's not much left during it into real AST macros. Just the part that passes the AST instead of the evaluated result of the arguments to a function. BTW, is it complicated to return a more structured values, like a struct or a class, than just plain values like strings? -- /Jacob Carlborg
Nov 13 2013
On 11/13/2013 11:53 PM, Jacob Carlborg wrote:On 2013-11-13 20:19, Walter Bright wrote:No, but then you're face with the issue of where those structs are defined.The reflection ability is not something specific to an AST, it could be added so that any expression node can be reflected. We already do much of that with __traits.Yes, I been thinking of ways to expand __traits. When there's enough of __traits it's not much left during it into real AST macros. Just the part that passes the AST instead of the evaluated result of the arguments to a function. BTW, is it complicated to return a more structured values, like a struct or a class, than just plain values like strings?
Nov 14 2013
On 2013-11-14 10:13, Walter Bright wrote:No, but then you're face with the issue of where those structs are defined.In druntime, just like MouldeInfo, TypeInfo and similar classes. -- /Jacob Carlborg
Nov 14 2013
On 2013-11-13 09:45, Walter Bright wrote:Ok, let's set aside the opEquals and opCmp issue for the moment. Can AST macros do anything that expression templates cannot?I need to read up on what expression templates can do. -- /Jacob Carlborg
Nov 13 2013
On Wednesday, 13 November 2013 at 12:21:22 UTC, Jacob Carlborg wrote:I need to read up on what expression templates can do.But where to read? There's no such thing as "expression template" explicitly mentioned in here. http://dlang.org/template.html --rt
Nov 13 2013
On 11/13/2013 3:27 PM, Rob T wrote:But where to read? There's no such thing as "expression template" explicitly mentioned in here.This may help: http://www.dsource.org/projects/ddl/browser/trunk/meta/regex.d
Nov 13 2013
On 2013-11-14 00:27, Rob T wrote:On Wednesday, 13 November 2013 at 12:21:22 UTC, Jacob Carlborg wrote:I guess everything about C++ expression templates would be a start. http://en.wikipedia.org/wiki/Expression_templates -- /Jacob CarlborgI need to read up on what expression templates can do.But where to read? There's no such thing as "expression template" explicitly mentioned in here. http://dlang.org/template.html
Nov 13 2013
On Tuesday, 12 November 2013 at 09:55:20 UTC, Walter Bright wrote:I forgot to mention that "expression templates" can be used in D in an equivalent manner that they are used in C++,They are crippled compared to C++, because you have no control over the return type of opCmp and opEquals, which means that you can't have expression templates involving comparisons. That's extremely limiting. My feeling with AST macros is: (1) AST macros are basically syntax sugar for string mixins. The one and only thing that string mixins have in their favour, is that they have almost no syntax. But that is actually a *huge* plus. Because it's syntax sugar, an AST macro syntax would be most convincing if you took some existing string mixins from various real projects, and show how beautiful they would become with macros. (2) The big functionality we don't have, is comprehensive reflection. I'd like to see more thought in that area. It seems challenging to define reflection in a way that doesn't expose compiler internals. The question I find particularly interesting is, "if we had macros, would reflection look different?"
Nov 12 2013
On Tuesday, 12 November 2013 at 11:06:17 UTC, Don wrote:On Tuesday, 12 November 2013 at 09:55:20 UTC, Walter Bright wrote:My personal main need for macros at this point, is to make up for a lack of better reflection, but as has been pointed out, it's not clear how macros would help anyway without access to the sort of reflection that I'm currently lacking. What we seem to be discussing, is the need to unify within D the abilities to perform better reflection along with a means to automate code generation during compile time. The current way reflection and mixins are done, are totally different, almost like two different languages with D, so it would be nice to have a more unified system that more closely resembles D itself. BTW, I agree with Walters concerns about AST macros. It would be ugly to work with code that is not comprehensible due to over use of macros that attempt to redefine the language into something else. OTOH there's also significant advantages to be able to add certain things into the language that are currently lacking. For example, I've experimented with a method of implementing co-routines that use switch statements, but it's very ugly to do without macro support to the point of being impractical. --rtI forgot to mention that "expression templates" can be used in D in an equivalent manner that they are used in C++,They are crippled compared to C++, because you have no control over the return type of opCmp and opEquals, which means that you can't have expression templates involving comparisons. That's extremely limiting. My feeling with AST macros is: (1) AST macros are basically syntax sugar for string mixins. The one and only thing that string mixins have in their favour, is that they have almost no syntax. But that is actually a *huge* plus. Because it's syntax sugar, an AST macro syntax would be most convincing if you took some existing string mixins from various real projects, and show how beautiful they would become with macros. (2) The big functionality we don't have, is comprehensive reflection. I'd like to see more thought in that area. It seems challenging to define reflection in a way that doesn't expose compiler internals. The question I find particularly interesting is, "if we had macros, would reflection look different?"
Nov 12 2013
On 2013-11-12 19:01, Rob T wrote:My personal main need for macros at this point, is to make up for a lack of better reflection, but as has been pointed out, it's not clear how macros would help anyway without access to the sort of reflection that I'm currently lacking.Macros would need a reflection API to be usable.What we seem to be discussing, is the need to unify within D the abilities to perform better reflection along with a means to automate code generation during compile time. The current way reflection and mixins are done, are totally different, almost like two different languages with D, so it would be nice to have a more unified system that more closely resembles D itself. BTW, I agree with Walters concerns about AST macros. It would be ugly to work with code that is not comprehensible due to over use of macros that attempt to redefine the language into something else. OTOH there's also significant advantages to be able to add certain things into the language that are currently lacking. For example, I've experimented with a method of implementing co-routines that use switch statements, but it's very ugly to do without macro support to the point of being impractical. --rt-- /Jacob Carlborg
Nov 13 2013
On Tuesday, 12 November 2013 at 11:06:17 UTC, Don wrote:On Tuesday, 12 November 2013 at 09:55:20 UTC, Walter Bright wrote:After using string mixins for a while I have come to feel much like your statement in (1). I like the power and flexibility of string mixins. Text and strings are understandable and straightforward to manipulate. This is a clear win in my opinion. There are also some things I find difficult at the moment. - One is the process of what to do when things do not go as expected. To debug I currently use pragma statements and try to visualize what is going on in my mind. This is do-able. But I feel it could be better. - It would be nice to be able to use some more D language concepts to construct the string mixin inside the template. For example, sometimes I would like to use a loop to construct the result. If these two items could be addressed I would be pretty satisfied with using string mixins as they are. One win that the AST macro concept provides that string mixins does not is manipulation of code syntax trees (either at compile or run time). It would be nice to combine the various code manipulation ideas that have been tossed around before into a single module, say std.meta or std.reflection. In addition to combining the various current code manipulation functionality into a single api (e.g. __traits, std.traits), it could provide functionality to work with code-in-use. For example, it would be pretty cool to be able to do the following (the actual syntax for constructing the code is not that important to me, but the underlying functionality for manipulating code is). sample.d import std.meta; void main(string[] args) { auto e = construct("a + %s", args[1]); writefln("%s", e(5)); auto f = construct(e + "b"); writefln("%s", f(?, 10).toDebugString); writefln("%s", f(5, 10)); } -----I forgot to mention that "expression templates" can be used in D in an equivalent manner that they are used in C++,They are crippled compared to C++, because you have no control over the return type of opCmp and opEquals, which means that you can't have expression templates involving comparisons. That's extremely limiting. My feeling with AST macros is: (1) AST macros are basically syntax sugar for string mixins. The one and only thing that string mixins have in their favour, is that they have almost no syntax. But that is actually a *huge* plus. Because it's syntax sugar, an AST macro syntax would be most convincing if you took some existing string mixins from various real projects, and show how beautiful they would become with macros. (2) The big functionality we don't have, is comprehensive reflection. I'd like to see more thought in that area. It seems challenging to define reflection in a way that doesn't expose compiler internals. The question I find particularly interesting is, "if we had macros, would reflection look different?"./sample 2 7 Numerical Expression: a + 2 + 10 17Implementing the "expression tree" side of AST macros seems like it could be done as a library, which would be a win for maintainability and cross-compiler portability. There is probably required, compiler-related functionality that I cannot see making this unfeasable or possibly difficult to do. Still, looks good to me on paper at least. Perhaps going this route could gain the good functionality of AST macros while also making use of the already implemented features? Seems to me like some of these ideas tie into previous discussions. Here are two I remember. I am sure there are others. http://forum.dlang.org/thread/juf7sk$16rl$1 digitalmars.com http://forum.dlang.org/thread/mailman.1716.1340388570.24740.digitalmars-d puremagic.com Joseph
Nov 12 2013
On 2013-11-12 21:03, Joseph Cassman wrote:After using string mixins for a while I have come to feel much like your statement in (1). I like the power and flexibility of string mixins. Text and strings are understandable and straightforward to manipulate. This is a clear win in my opinion. There are also some things I find difficult at the moment. - One is the process of what to do when things do not go as expected. To debug I currently use pragma statements and try to visualize what is going on in my mind. This is do-able. But I feel it could be better.If we got macros we should really have a good way to debug them. At least a flag to shows how the macros are lowered.- It would be nice to be able to use some more D language concepts to construct the string mixin inside the template. For example, sometimes I would like to use a loop to construct the result. If these two items could be addressed I would be pretty satisfied with using string mixins as they are. One win that the AST macro concept provides that string mixins does not is manipulation of code syntax trees (either at compile or run time). It would be nice to combine the various code manipulation ideas that have been tossed around before into a single module, say std.meta or std.reflection. In addition to combining the various current code manipulation functionality into a single api (e.g. __traits, std.traits), it could provide functionality to work with code-in-use. For example, it would be pretty cool to be able to do the following (the actual syntax for constructing the code is not that important to me, but the underlying functionality for manipulating code is). sample.d import std.meta; void main(string[] args) { auto e = construct("a + %s", args[1]); writefln("%s", e(5)); auto f = construct(e + "b"); writefln("%s", f(?, 10).toDebugString); writefln("%s", f(5, 10)); }Yes, but the problem with string mixins is that you need to reparse a lot of code. With string mixins it becomes: 1. The compiler parses the code and creates an AST (fine so far) 2. Does type checking an other stuff 3. Library code parses a string into an AST 4. Library code manipulates the AST 5. Library code converts the AST back to a string 6. The string is interested with a string mixin at the calling context 7. The compiler parses the code and creates an AST 8. Does type checking an other stuff With AST macaros you can avoid many of these steps: 1. The compiler parses the code and creates an AST 2. Does type checking an other stuff 3. Library code (macro) manipulates the AST 4. Compiler inserts the manipulate AST into the calling context 5. Does type checking an other stuff Instead of eight steps we get five steps. We remove the unnecessary conversions between AST's and strings. -- /Jacob Carlborg
Nov 13 2013
On 11/12/2013 3:06 AM, Don wrote:On Tuesday, 12 November 2013 at 09:55:20 UTC, Walter Bright wrote:It is limiting, but I don't know about extremely limiting. Eric Anderton's regex engine didn't need them. And, if you really do need them, you can always define the templates as regular names: lessThan(a,b) equals(a,b) etc. Not the greatest, but not unworkable.I forgot to mention that "expression templates" can be used in D in an equivalent manner that they are used in C++,They are crippled compared to C++, because you have no control over the return type of opCmp and opEquals, which means that you can't have expression templates involving comparisons. That's extremely limiting.
Nov 12 2013
On 2013-11-13 00:26, Walter Bright wrote:It is limiting, but I don't know about extremely limiting. Eric Anderton's regex engine didn't need them. And, if you really do need them, you can always define the templates as regular names: lessThan(a,b) equals(a,b) etc. Not the greatest, but not unworkable.I don't know what's so special about the regex engine. It takes a regex as a string and matches that against another string. Seems to be just like any other regular expression library I've used. -- /Jacob Carlborg
Nov 13 2013
On 11/13/2013 12:17 AM, Jacob Carlborg wrote:On 2013-11-13 00:26, Walter Bright wrote:What's special about it was its use of expression templates. It made for a nice demo of how to do such.It is limiting, but I don't know about extremely limiting. Eric Anderton's regex engine didn't need them. And, if you really do need them, you can always define the templates as regular names: lessThan(a,b) equals(a,b) etc. Not the greatest, but not unworkable.I don't know what's so special about the regex engine. It takes a regex as a string and matches that against another string. Seems to be just like any other regular expression library I've used.
Nov 13 2013
On 2013-11-13 09:38, Walter Bright wrote:What's special about it was its use of expression templates. It made for a nice demo of how to do such.Is there an actual point in doing that, except a nice exercise in expression templates? -- /Jacob Carlborg
Nov 13 2013
On 11/13/2013 4:25 AM, Jacob Carlborg wrote:On 2013-11-13 09:38, Walter Bright wrote:It actually generated a very fast regex engine, though Dmitry's work has since eclipsed it.What's special about it was its use of expression templates. It made for a nice demo of how to do such.Is there an actual point in doing that, except a nice exercise in expression templates?
Nov 13 2013
On 2013-11-13 20:16, Walter Bright wrote:It actually generated a very fast regex engine, though Dmitry's work has since eclipsed it.Right, a specially tuned engine for that particular regex. -- /Jacob Carlborg
Nov 13 2013
On Tuesday, 12 November 2013 at 09:20:07 UTC, Walter Bright wrote:5. We've said "no" in the past to things like user-defined tokens, which are closely related.Regarding this point, I get that arbitrary expansion is out, but would you be amenable to adding a small, _strictly-defined_ set of operators that are compile-time errors unless overloaded?#define BEGIN { #define END } macros used in old C code to make it look like Pascal.A plague o' their houses! -Wyatt
Nov 12 2013
On 2013-11-12 10:20, Walter Bright wrote:For example, the Linq example in the DIP is not compelling, as aesthetically nicer code can be written using D's ranges and algorithms: auto data = arr.filter!(x => x > 5).array;I was actually not the one that added the Linq examples. I like the above better. I've used a similar example as well: auto person = Person.where(e => e.name == "John"); Translates to: select * from person where name = 'John' But I don't see how that can currently be done in D. Operator overloading in D isn't flexible enough. For example, when implementing opEquals, you don't know if it's "==" or "!=" that's being called. Same with the comparison operators.be blunt it's like the old: #define BEGIN { #define END } macros used in old C code to make it look like Pascal.I agree with this. -- /Jacob Carlborg
Nov 12 2013
On Tuesday, 12 November 2013 at 13:50:49 UTC, Jacob Carlborg wrote:auto person = Person.where(e => e.name == "John"); Translates to: select * from person where name = 'John'for those of us entirely unfamiliar with linq, what is this supposed to do? Select people with name "John" from a collection of people, like in sql? It seems trivial to do this using filter, or am I missing something...?
Nov 12 2013
On Tuesday, 12 November 2013 at 14:38:44 UTC, John Colvin wrote:for those of us entirely unfamiliar with linq, what is this supposed to do? Select people with name "John" from a collection of people, like in sql? It seems trivial to do this using filter, or am I missing something...?I don't know much about linq but in macro context I'd expect it to generate an actual SQL query to database (and execute it) based on in-language filter statement (via reflection)
Nov 12 2013
On 2013-11-12 16:20, Dicebot wrote:I don't know much about linq but in macro context I'd expect it to generate an actual SQL query to database (and execute it) based on in-language filter statement (via reflection)Exactly, spot on. The interesting thing there, in the context of macros, is converting the AST of the lambda to an string containing SQL code. -- /Jacob Carlborg
Nov 13 2013
On 11/12/2013 06:38 AM, John Colvin wrote:On Tuesday, 12 November 2013 at 13:50:49 UTC, Jacob Carlborg wrote:linq provides an interface to query any collection, but what is interesting in this case is Person.where(e => e.name == "John") invokes an engine that builds the necessary sql to issue an equivalent query to your sql database and assembles the results into a range of Person. And it can do this for any arbitrary predicate (well, almost. It doesn't handle function calls to arbitrary code too well). the .NET framework can do this because it exposes an api for querying, building, and compiling asts. D cannot do this because it doesn't. (and I have tried to make it work)auto person = Person.where(e => e.name == "John"); Translates to: select * from person where name = 'John'for those of us entirely unfamiliar with linq, what is this supposed to do? Select people with name "John" from a collection of people, like in sql? It seems trivial to do this using filter, or am I missing something...?
Nov 12 2013
On Tuesday, 12 November 2013 at 15:21:16 UTC, Ellery Newcomer wrote:On 11/12/2013 06:38 AM, John Colvin wrote:oh, I see. Would AST macros really be enough to make this work in D? "Arbitrary code" is a huge feature space in D, including much that doesn't map well to anything outside of a relatively low-level language, let alone SQL. I can see it quickly becoming a nightmare that would be worse than just issuing the predicate as an sql string or some generic equivalent.On Tuesday, 12 November 2013 at 13:50:49 UTC, Jacob Carlborg wrote:linq provides an interface to query any collection, but what is interesting in this case is Person.where(e => e.name == "John") invokes an engine that builds the necessary sql to issue an equivalent query to your sql database and assembles the results into a range of Person. And it can do this for any arbitrary predicate (well, almost. It doesn't handle function calls to arbitrary code too well). the .NET framework can do this because it exposes an api for querying, building, and compiling asts. D cannot do this because it doesn't. (and I have tried to make it work)auto person = Person.where(e => e.name == "John"); Translates to: select * from person where name = 'John'for those of us entirely unfamiliar with linq, what is this supposed to do? Select people with name "John" from a collection of people, like in sql? It seems trivial to do this using filter, or am I missing something...?
Nov 12 2013
On Tuesday, 12 November 2013 at 16:14:57 UTC, John Colvin wrote:On Tuesday, 12 November 2013 at 15:21:16 UTC, Ellery Newcomer wrote:Actually, s/arbitrary code/simple to moderately complex expressions that don't call functions that aren't explicitly handled by the translation engine/ and this is a better representation of what linq can do in e.g. entity framework. and you could go the route of django models, e.g. Place.objects.filter(name="Bob's Cafe") as long as you had enough metadata set up. you could probably get this to work in D, but A. it looks like crap B. it in no way resembles sql C. it would look like even worse crap in D (no named parameters!) D. it doesn't readily permit you to make queries with complex expression trees (idk, maybe something like linq's Places.Where(p => p.Elev < 200 && Addresses.Any(a => a.State == p.State)) why am I arguing against this? nobody wants this, nobody asked for this. Also, sql is to databases what assembly is to cpus. It's low level, [moderately] untyped, and it differs on every single platform. provide access to it, sure, but please don't use it to build your abstractions.On 11/12/2013 06:38 AM, John Colvin wrote:oh, I see. Would AST macros really be enough to make this work in D? "Arbitrary code" is a huge feature space in D, including much that doesn't map well to anything outside of a relatively low-level language, let alone SQL. I can see it quickly becoming a nightmare that would be worse than just issuing the predicate as an sql string or some generic equivalent.On Tuesday, 12 November 2013 at 13:50:49 UTC, Jacob Carlborg wrote:linq provides an interface to query any collection, but what is interesting in this case is Person.where(e => e.name == "John") invokes an engine that builds the necessary sql to issue an equivalent query to your sql database and assembles the results into a range of Person. And it can do this for any arbitrary predicate (well, almost. It doesn't handle function calls to arbitrary code too well). the .NET framework can do this because it exposes an api for querying, building, and compiling asts. D cannot do this because it doesn't. (and I have tried to make it work)auto person = Person.where(e => e.name == "John"); Translates to: select * from person where name = 'John'for those of us entirely unfamiliar with linq, what is this supposed to do? Select people with name "John" from a collection of people, like in sql? It seems trivial to do this using filter, or am I missing something...?
Nov 12 2013
On 12.11.2013 18:53, Ellery Newcomer wrote:Place.objects.filter(name="Bob's Cafe")[snip]C. it would look like even worse crap in D (no named parameters!)It's perfectly possible in D to make this work: Place.objects.filter(args.name = "Bob", args.state = "unemployed"); Proof of concept: import std.stdio : writeln; struct NamedArg(string name, Args...) { Args value; alias value this; } struct args { property static auto opDispatch(string name, Args...)(Args args) { return NamedArg!(name, Args)(args); } } void foo(NamedArg!("name", string) a) { writeln(a); } void main() { foo(args.name = "Bob"); } And since the name is statically known, you can use this for e.g. lookup on objects. No, it's nowhere near as pretty, and the receiving code is horrible. If you were to use this for some kind of magic behind the scenes, it might be okay. Might. Please don't do it.D. it doesn't readily permit you to make queries with complex expression trees (idk, maybe something like linq's Places.Where(p => p.Elev < 200 && Addresses.Any(a => a.State == p.State))Sorry, I got nuffin'. :p Waaait... Places.where(args.elev.lessThan(200) & args.state = (state)=>Addresses.any(state)); I *can* make that work. I'm not going to. -- Simen
Nov 13 2013
On Wednesday, 13 November 2013 at 10:51:48 UTC, Simen Kjærås wrote:On 12.11.2013 18:53, Ellery Newcomer wrote: It's perfectly possible in D to make this work:hey, cool impl *comprehends code* I mean EwwwI *can* make that work. I'm not going to. -- SimenI concur with the second part.
Nov 13 2013
On 13.11.2013 20:05, Ellery Newcomer wrote:On Wednesday, 13 November 2013 at 10:51:48 UTC, Simen Kjærås wrote:I decided to abandon sanity. Luckily, only for the named parameters. I now have this code working: void test(int a, int b = 2, string c = "foo", int d = 14) { } alias test2 = nameify!test; void main() { test2(1, Args.d = 4, Args.c = "bar"); } With reasonable error messages for duplicate and missing parameters, as well as type mismatches. Source is attached. I hope God forgives me. -- SimenOn 12.11.2013 18:53, Ellery Newcomer wrote: It's perfectly possible in D to make this work:hey, cool impl *comprehends code* I mean EwwwI *can* make that work. I'm not going to. -- SimenI concur with the second part.
Nov 17 2013
On Sunday, 17 November 2013 at 19:41:40 UTC, Simen Kjærås wrote:On 13.11.2013 20:05, Ellery Newcomer wrote:That is a really cool idea !On Wednesday, 13 November 2013 at 10:51:48 UTC, Simen Kjærås wrote:I decided to abandon sanity. Luckily, only for the named parameters. I now have this code working: void test(int a, int b = 2, string c = "foo", int d = 14) { } alias test2 = nameify!test; void main() { test2(1, Args.d = 4, Args.c = "bar"); } With reasonable error messages for duplicate and missing parameters, as well as type mismatches. Source is attached. I hope God forgives me.On 12.11.2013 18:53, Ellery Newcomer wrote: It's perfectly possible in D to make this work:hey, cool impl *comprehends code* I mean EwwwI *can* make that work. I'm not going to. -- SimenI concur with the second part.
Nov 17 2013
On 11/17/2013 11:41 AM, Simen Kjærås wrote:Source is attached. I hope God forgives me.I suppose you'd have to do something like x.Where(OR( NOT(Args.thing = "thing"), Args.sing = "sing")) for nesting and negation and all that. I'd wait for walter to relax the restrictions on ==, &&, etc operator overloading. Then you probably could do x.Where(X => X.thing != "thing" || X.sing == "sing") let's see here. If X's type is QueryExp!Entity and the return type is SomeRange!Entity then querying looks doable. how about composing expressions? take the result of that lambda EXP, EXP = EXP && X.cling == 1; // should work fine? how about decomposing expressions? EXP = EXP.lhs; // should work fine? EXP.rhs.rhs.value // returns "sing" - should work fine? the lambda should create a closure, so we should be able to get out any value we put in you won't be able to do x.Where(X => upper(X.thing) == "THING") without ast macros but will have to be satisfied with x.Where(X => X.thing.upper() == "THING") will you be able to do x.Where(X => X.thing == "THING" && x.Any(X2 => X2.thing == X.thing && X2.id != X.id)) ? either "Any" would have to be only for template expressions, or X would have to be an outer context like so: x.Where(X => X.it.thing == "THING" && X.x.Any(X2 => X2.it.thing == X.it.thing && X2.it.id != X.it.id)) because x.Any(...) should return bool, but inside the query expression it should return QueryExp. In both cases it would take a param of QueryExp delegate(QueryExp) Anybody else have any other ideas?
Nov 17 2013
On 2013-11-17 22:15, Ellery Newcomer wrote:On 11/17/2013 11:41 AM, Simen Kjærås wrote:That works with the Rails plugin Squeel. Although you need to prefix "upper" with "X.". https://github.com/ernie/squeel -- /Jacob CarlborgSource is attached. I hope God forgives me.I suppose you'd have to do something like x.Where(OR( NOT(Args.thing = "thing"), Args.sing = "sing")) for nesting and negation and all that. I'd wait for walter to relax the restrictions on ==, &&, etc operator overloading. Then you probably could do x.Where(X => X.thing != "thing" || X.sing == "sing") let's see here. If X's type is QueryExp!Entity and the return type is SomeRange!Entity then querying looks doable. how about composing expressions? take the result of that lambda EXP, EXP = EXP && X.cling == 1; // should work fine? how about decomposing expressions? EXP = EXP.lhs; // should work fine? EXP.rhs.rhs.value // returns "sing" - should work fine? the lambda should create a closure, so we should be able to get out any value we put in you won't be able to do x.Where(X => upper(X.thing) == "THING")
Nov 18 2013
On 11/17/2013 08:41 PM, Simen Kjærås wrote:I decided to abandon sanity. Luckily, only for the named parameters. I now have this code working: void test(int a, int b = 2, string c = "foo", int d = 14) { } alias test2 = nameify!test; void main() { test2(1, Args.d = 4, Args.c = "bar"); } With reasonable error messages for duplicate and missing parameters, as well as type mismatches. ...Still missing overload resolution. :o)
Nov 17 2013
On 17.11.2013 23:21, Timon Gehr wrote:On 11/17/2013 08:41 PM, Simen Kjærås wrote:Please don't tempt me. :p -- SimenI decided to abandon sanity. Luckily, only for the named parameters. I now have this code working: void test(int a, int b = 2, string c = "foo", int d = 14) { } alias test2 = nameify!test; void main() { test2(1, Args.d = 4, Args.c = "bar"); } With reasonable error messages for duplicate and missing parameters, as well as type mismatches. ...Still missing overload resolution. :o)
Nov 17 2013
On Sun, Nov 17, 2013 at 8:41 PM, Simen Kjærås <simen.kjaras gmail.com> wrote:Source is attached. I hope God forgives me.Nice ideas. I particularly like this one: final abstract class Args { property static auto opDispatch(string name, Arg)(Arg arg) { return NamedArg!(name, Arg)(arg); } } Which allows you to have Args.c = 1 (and thus storing the name and the value). Half of your implementation is in fact generic enough to be in Phobos (staticFilter, staticZip). I know I use my own... Btw, with DMD 2.064.2, we can now write: template staticToString(T...) { enum staticToString = T.stringof; } as: alias staticToString(T...) = T.stringof; Which is both easier to understand and easier on the eyes.
Nov 17 2013
On 2013-11-17 21:04, Philippe Sigaud wrote:alias staticToString(T...) = T.stringof; Which is both easier to understand and easier on the eyes.Wouldn't that be enum instead: enum staticToString(T...) = T.stringof; -- /Jacob Carlborg
Nov 18 2013
On 2013-11-12 17:14, John Colvin wrote:oh, I see. Would AST macros really be enough to make this work in D? "Arbitrary code" is a huge feature space in D, including much that doesn't map well to anything outside of a relatively low-level language, let alone SQL. I can see it quickly becoming a nightmare that would be worse than just issuing the predicate as an sql string or some generic equivalent.Person.where(e => e.name == "John") I'm thinking that we only need to convert the part that is prefixed with, in this example, "e". Any other code should be executed in the context of the caller. It should be possible to do this as well: auto foo = "John"; auto result = Person.where(e => e.name == foo); Which will result in the same SQL query. I'm using a pluign to Ruby on Rails that does something similar but by overloading operators. The problem with this approach, in Ruby, is that you cannot overload operators like || and &&, so instead they overload | and & resulting in new problems like operator precedence. Example: Person.where{ |e| (e.name == "John") & (e.address == "Main street") } -- /Jacob Carlborg
Nov 13 2013
On 13.11.2013. 9:26, Jacob Carlborg wrote:On 2013-11-12 17:14, John Colvin wrote:What about something like this? class Person { macro where (Context context, Statement statement) { // ... } } auto foo = "John"; auto result = Person.where(e => e.name == foo); // is replaced by auto foo = "John"; auto result = Person.query("select * from person where person.name = " ~ sqlQuote(foo) ~ ";");oh, I see. Would AST macros really be enough to make this work in D? "Arbitrary code" is a huge feature space in D, including much that doesn't map well to anything outside of a relatively low-level language, let alone SQL. I can see it quickly becoming a nightmare that would be worse than just issuing the predicate as an sql string or some generic equivalent.Person.where(e => e.name == "John") I'm thinking that we only need to convert the part that is prefixed with, in this example, "e". Any other code should be executed in the context of the caller. It should be possible to do this as well: auto foo = "John"; auto result = Person.where(e => e.name == foo); Which will result in the same SQL query. I'm using a pluign to Ruby on Rails that does something similar but by overloading operators. The problem with this approach, in Ruby, is that you cannot overload operators like || and &&, so instead they overload | and & resulting in new problems like operator precedence. Example: Person.where{ |e| (e.name == "John") & (e.address == "Main street") }
Nov 13 2013
Am 13.11.2013 09:34, schrieb luka8088:What about something like this? class Person { macro where (Context context, Statement statement) { // ... }it is not generic - and that is the biggest goal to reach
Nov 13 2013
On 2013-11-13 09:34, luka8088 wrote:What about something like this? class Person { macro where (Context context, Statement statement) { // ... } } auto foo = "John"; auto result = Person.where(e => e.name == foo); // is replaced by auto foo = "John"; auto result = Person.query("select * from person where person.name = " ~ sqlQuote(foo) ~ ";");That's basically what would happen. -- /Jacob Carlborg
Nov 13 2013
On 13.11.2013. 13:26, Jacob Carlborg wrote:On 2013-11-13 09:34, luka8088 wrote:May/Should I add such example to wiki? -- LukaWhat about something like this? class Person { macro where (Context context, Statement statement) { // ... } } auto foo = "John"; auto result = Person.where(e => e.name == foo); // is replaced by auto foo = "John"; auto result = Person.query("select * from person where person.name = " ~ sqlQuote(foo) ~ ";");That's basically what would happen.
Nov 13 2013
On 2013-11-13 15:47, luka8088 wrote:May/Should I add such example to wiki?Yes, "should". Sure, add it to the DIP. -- /Jacob Carlborg
Nov 13 2013
On Wednesday, 13 November 2013 at 08:26:52 UTC, Jacob Carlborg wrote:I'm using a pluign to Ruby on Rails that does something similar but by overloading operators. The problem with this approach, in Ruby, is that you cannot overload operators like || and &&, so instead they overload | and & resulting in new problems like operator precedence. Example: Person.where{ |e| (e.name == "John") & (e.address == "Main street") }Is this in any way better than the basic Ruby where( name: 'John', address: 'Main street' ) ? Or was it just something quick and contrived to show the behavior, and not the utility, of the plugin? Just curious.
Nov 13 2013
On Wednesday, 13 November 2013 at 17:13:11 UTC, Chris Nicholson-Sauls wrote:Is this in any way better than the basic Ruby where( name: 'John', address: 'Main street' ) ? Or was it just something quick and contrived to show the behavior, and not the utility, of the plugin? Just curious.It was mostly to show what happens when the you have limited operator overloading. It has it advantages over the hash-syntax. You can do much more, not equal, less then, greater then, like and so on. -- /Jacob Carlborg
Nov 13 2013
On 11/12/13 7:21 AM, Ellery Newcomer wrote:the .NET framework can do this because it exposes an api for querying, building, and compiling asts. D cannot do this because it doesn't. (and I have tried to make it work)Maybe the problem needs to be reformulated for D. I think an SQL mixin that either stays unchanged (for DB engines) or translates to a D expression (for native D data types) would be doable, nontrivial, interesting, and instantly usable for people who already know SQL without any extra learning. In other words... actually better than Linq. Andrei
Nov 12 2013
On Tuesday, 12 November 2013 at 16:39:18 UTC, Andrei Alexandrescu wrote:Maybe the problem needs to be reformulated for D. I think an SQL mixin that either stays unchanged (for DB engines) or translates to a D expression (for native D data types) would be doable, nontrivial, interesting, and instantly usable for people who already know SQL without any extra learning. In other words... actually better than Linq.It does not matter that much if it is macro or mixin. Key feature is AST reflection which allows to augment valid D code with additional semantics when appropriate. It is very similar to how UDA's augment declarative approach, but applied to imperative/procedural instead. We can't do that in D right now. Only way is to import own source file and parse it which does not really sound sane.
Nov 12 2013
On 11/12/13 8:47 AM, Dicebot wrote:On Tuesday, 12 November 2013 at 16:39:18 UTC, Andrei Alexandrescu wrote:I don't see how AST reflection is needed for generating correct D code from an SQL expression. Dmitry did exactly that with ctRegex. Please illuminate. AndreiMaybe the problem needs to be reformulated for D. I think an SQL mixin that either stays unchanged (for DB engines) or translates to a D expression (for native D data types) would be doable, nontrivial, interesting, and instantly usable for people who already know SQL without any extra learning. In other words... actually better than Linq.It does not matter that much if it is macro or mixin. Key feature is AST reflection which allows to augment valid D code with additional semantics when appropriate.
Nov 12 2013
On Tuesday, 12 November 2013 at 16:54:19 UTC, Andrei Alexandrescu wrote:I don't see how AST reflection is needed for generating correct D code from an SQL expression. Dmitry did exactly that with ctRegex. Please illuminate.Other way around. Generating arbitrary output (including but not limited to SQL expressions) from D code. As I have already mentioned, it is the very same thing we do now with __traits and UDA's but not limited to only declarations.
Nov 12 2013
On 11/12/13 9:03 AM, Dicebot wrote:On Tuesday, 12 November 2013 at 16:54:19 UTC, Andrei Alexandrescu wrote:Yah. That I agree with. That's why I said we should reformulate the problem that LINQ solves.I don't see how AST reflection is needed for generating correct D code from an SQL expression. Dmitry did exactly that with ctRegex. Please illuminate.Other way around. Generating arbitrary output (including but not limited to SQL expressions) from D code.As I have already mentioned, it is the very same thing we do now with __traits and UDA's but not limited to only declarations.Interesting. Andrei
Nov 12 2013
On Tuesday, 12 November 2013 at 17:20:20 UTC, Andrei Alexandrescu wrote:I had an impression it was exactly the context in which linq was originally mentioned, no idea why discussion has moved from that to expressing DSL's (which is not really a problem in D) :)Other way around. Generating arbitrary output (including but not limited to SQL expressions) from D code.Yah. That I agree with. That's why I said we should reformulate the problem that LINQ solves.Reason why I am doing this comparison is that some of the cases why UDA's are so useful applies to AST reflection capabilities too. Most importantly, it allows to have the code which is both valid (and used) D code on its own and used to generate some co-product from it in automatic mode. Similar declarative approach has been used to huge success in vibe.d code (rest, forms) and I see no reasons why it can't be so for imperative one.As I have already mentioned, it is the very same thing we do now with __traits and UDA's but not limited to only declarations.Interesting.
Nov 12 2013
On 2013-11-12 21:25, Dicebot wrote:I had an impression it was exactly the context in which linq was originally mentioned, no idea why discussion has moved from that to expressing DSL's (which is not really a problem in D) :)My example is a DSL: Person.where(e => e.name == "John"); -- /Jacob Carlborg
Nov 13 2013
On Tuesday, 12 November 2013 at 17:20:20 UTC, Andrei Alexandrescu wrote:The thing I'd like to be able to do it to create a async/await/yield like mechanism, purely as library. generator uint foo() { writeln("generating !"); return 0; return 1; writeln("and the last one"); return 2; } => auto foo() { enum States { S0, S1, S2, } struct Generator { State s; uint current; property front() { return current; } void popFront() { final switch(s) with(State) { case S0: current = 1; s = S1; return; case S1: writeln("and the last one"); current = 2; s = S2; return; case S2: assert(0, "Nothing more in here"); } } property empty() { return s == State.S2; } } auto g = Generator(); writeln("generating !"); g.current = 0; g.state = State.S0; return g; }As I have already mentioned, it is the very same thing we do now with __traits and UDA's but not limited to only declarations.Interesting.
Nov 12 2013
On 11/12/2013 09:36 PM, deadalnix wrote:The thing I'd like to be able to do it to create a async/await/yield like mechanism, purely as library.That's a prime example for AST macros.
Nov 12 2013
On Tuesday, 12 November 2013 at 23:34:38 UTC, Martin Nowak wrote:On 11/12/2013 09:36 PM, deadalnix wrote:First of all: I haven't used macros extensively yet. Its merely a theoretical viewpoint, so don't take the arguments well-established. Macros could be used as in ScalaCL ( I mean the latest version, which is experimental : https://github.com/ochafik/ScalaCL ). I like the idea using the host language ( or a subset of it) to program GPUs, not C, like PyOpenCL does. It reduces the complexity of the problem when you switch target of the algorithm from CPU to GPU and back. Macros could also be used in (re)implementing some of the basic syntax - that's what developers of Nemerle did. Somebody can argue whether it was a good idea or not, but it would be interesting to disable syntax by disabling the macro that transforms it by a single line in the file ( not importing the macro ). ( Could be useful for microcontroller platforms to control the runtime's memory usage by disabling certain features - not compiling them into the executable ) In AOT compilation, there isn't any difference between macros and CTFE functions which do something with AST. That would be a way to implement them - creating a compiler API which could only be used by compile-time functions. Yeah, and I know, it's crippling when code is ambigous. But I also think macros are the best way to define interfaces for modules. Using them can obfuscate code very easily when not enough care is taken handling them and it can make the learning curve much steeper, but there always existed ill-designed API-s and we could still use the good old tools to get the API done :) . Maybe it wouldn't be as good as a macro-ed API would be, but still works. If we choose the right tool, it can lower the complexity of the API. Let's have a look at the feature: pointers. A very powerful, be also dangerous weapon that cal blow up the entire program suddenly. With some techniques used to fend off the problems it can cause, it can be much safer. Rust made a trial with their pointer system. I don't think it is a solution, but ignoring the problem isn't either. The second example: the first cannons blew up, killing people. But time showed technology can evolve. The area of macros - in my opinion - is not explored yet. Only the use of them can reveal the ways to make them better. Theoretical scientists cannot create good solutions for everyday use in the first place. It's a trial-and-error process. By allowing usage of macros only in certain cases, language desginer can make the burden of the coders lighter ( although I like statement macros, they can be very ambigous ). Also, if designer make macros visually very distinct from other tokens, users can read the code even easier, but sense is needed when alien from D, in my opinion ). Personally I wouldn't like hacking on the compiler or creating a whole new parser to do the same as we could do with macros, and I suggest a trial. Another option is to wait until somebody comes up with an idea and when time proved if the solution is right, include it - doing this saves a lot of work. That's how cutting-edge technologies work ( even if AST macros are an old idea ).The thing I'd like to be able to do it to create a async/await/yield like mechanism, purely as library.That's a prime example for AST macros.
Nov 12 2013
On 2013-11-12 21:36, deadalnix wrote:The thing I'd like to be able to do it to create a async/await/yield like mechanism, purely as library.Please add this as an example to the DIP. -- /Jacob Carlborg
Nov 13 2013
12-Nov-2013 21:03, Dicebot пишет:On Tuesday, 12 November 2013 at 16:54:19 UTC, Andrei Alexandrescu wrote:Actually I couldn't shake off the feeling that macros are just CTFE functions on Ast objects. How objects are created and converted back to source code is a separate question. If we just had: //this would invoke compiler's parser at CTFE auto ast = "x = y;".astof and have it work at CTFE to return sensible AST (a big if btw). And then (after some manipulations): ast.toString() //get back a string of D code It may help code generation of D --> DSL. Alternatively one can implement D parser that works at CTFE and watch it crawl :) -- Dmitry OlshanskyI don't see how AST reflection is needed for generating correct D code from an SQL expression. Dmitry did exactly that with ctRegex. Please illuminate.Other way around. Generating arbitrary output (including but not limited to SQL expressions) from D code. As I have already mentioned, it is the very same thing we do now with __traits and UDA's but not limited to only declarations.
Nov 12 2013
On Tuesday, 12 November 2013 at 20:56:34 UTC, Dmitry Olshansky wrote:If we just had: //this would invoke compiler's parser at CTFE auto ast = "x = y;".astof and have it work at CTFE to return sensible AST (a big if btw). And then (after some manipulations): ast.toString() //get back a string of D code It may help code generation of D --> DSL.Add there "foo.codeof" in the toolset and it will pretty much give core needed stuff. However, it will destroy compilation times if not coupled with compiler internal parsing/semantic phase. Actual "macro" keyword syntax sugar is hardly important to me.
Nov 12 2013
13-Nov-2013 01:16, Dicebot пишет:On Tuesday, 12 November 2013 at 20:56:34 UTC, Dmitry Olshansky wrote:For me it feels a lot like implementing something as a soft-core or emulator in software vs producing a bare-metal chip. It's a good idea to test waters and prototype a soft-thingy before getting dirty. When it comes to manufacture ASICs the idea should be well tested and could be actually sold as is already ;) If we consider that compiler is sort of "hardware" accelerator for getting ast's of strings and functions alike. Ditto with toString of ast. Then if somebody comes up with soft-core implementation of "macros" and shows: a) Cool benefits of manipulating on ASTs compared to cracking some strings b) Limitations of this implementation (unhyginic is one) c) Quantify obvious performance problems d) Prepare a solid file of use cases Then we might get people to manufacture ASICs (pay costs, implement in compiler/spec). Paraphrasing somebody from C++ ISO committee (I think Herb): Boost C++ Lambda is a prime reason we had to add lambdas as a core feature in C++11. If it took these top-notch experts that much of coding to get only this far and it's still brittle, limited and etc. ... we have no choice but to add it to the language.If we just had: //this would invoke compiler's parser at CTFE auto ast = "x = y;".astof and have it work at CTFE to return sensible AST (a big if btw). And then (after some manipulations): ast.toString() //get back a string of D code It may help code generation of D --> DSL.Add there "foo.codeof" in the toolset and it will pretty much give core needed stuff. However, it will destroy compilation times if not coupled with compiler internal parsing/semantic phase.Actual "macro" keyword syntax sugar is hardly important to me.-- Dmitry Olshansky
Nov 13 2013
On 11/12/2013 10:16 PM, Dicebot wrote:Add there "foo.codeof" in the toolset and it will pretty much give core needed stuff.Well, codeof is nice but it lacks the parser.
Nov 13 2013
On 2013-11-13 23:29, Martin Nowak wrote:Well, codeof is nice but it lacks the parser.Yes, and the you need to mixin it again. Several unnecessary steps, see the bottom of: http://forum.dlang.org/thread/l5otb1$1dhi$1 digitalmars.com?page=13#post-l5vcct:242lit:241:40digitalmars.com -- /Jacob Carlborg
Nov 13 2013
On Tue, Nov 12, 2013 at 9:55 PM, Dmitry Olshansky <dmitry.olsh gmail.com> wrote:If we just had: //this would invoke compiler's parser at CTFE auto ast = "x = y;".astof and have it work at CTFE to return sensible AST (a big if btw). And then (after some manipulations): ast.toString() //get back a string of D codeWhich you still have to mixin, btw. Which means any tree manipulation you do must be done at compile-time. Unless, of course, you then put the resulting code into another file, to be compiled and loaded afterwards.It may help code generation of D --> DSL. Alternatively one can implement D parser that works at CTFE and watch it crawl :)*cough cough* But, as other have said, these would be very un-hygienic macros, with no knowledge of the surrounding environment. Unless said CT-compatible parser could also somehow determine the local symbols (you could pass it 'by hand', but who would do that, realistically?)
Nov 12 2013
On 2013-11-12 22:55, Philippe Sigaud wrote:Which you still have to mixin, btw. Which means any tree manipulation you do must be done at compile-time. Unless, of course, you then put the resulting code into another file, to be compiled and loaded afterwards.It would be at compile time with macros anyway. The DIP even says that the macro functions are removed in the code generating phase.*cough cough* But, as other have said, these would be very un-hygienic macros, with no knowledge of the surrounding environment. Unless said CT-compatible parser could also somehow determine the local symbols (you could pass it 'by hand', but who would do that, realistically?)Exactly. -- /Jacob Carlborg
Nov 13 2013
On 2013-11-12 21:55, Dmitry Olshansky wrote:Actually I couldn't shake off the feeling that macros are just CTFE functions on Ast objects. How objects are created and converted back to source code is a separate question.Yes, and reflection.If we just had: //this would invoke compiler's parser at CTFE auto ast = "x = y;".astof and have it work at CTFE to return sensible AST (a big if btw). And then (after some manipulations): ast.toString() //get back a string of D code It may help code generation of D --> DSL. Alternatively one can implement D parser that works at CTFE and watch it crawl :)You would still need to do strign mixin. Which results in a some unnecessary conversion between AST's and strings. See the list at the bottom of: http://forum.dlang.org/thread/l5otb1$1dhi$1 digitalmars.com?page=13#post-l5vcct:242lit:241:40digitalmars.com It also looks ugly. -- /Jacob Carlborg
Nov 13 2013
//this would invoke compiler's parser at CTFE auto ast = "x = y;".astof ast.toString() //get back a string of D codeRight, that's the basic functionality we want. What's not clear is how to get the type of y.
Nov 13 2013
On 2013-11-13 23:29, Martin Nowak wrote:Right, that's the basic functionality we want. What's not clear is how to get the type of y.That's what the reflection API is for. I guess many people here know a lot more about building AST's than me. But here's a simple API: auto ast = "x = y".astof; auto type = ast.right.type; auto name = type.name; assert(ast.left.type == type); -- /Jacob Carlborg
Nov 14 2013
Am 12.11.2013 17:39, schrieb Andrei Alexandrescu:Maybe the problem needs to be reformulated for D. I think an SQL mixin that either stays unchanged (for DB engines) or translates to a D expression (for native D data types) would be doable, nontrivial, interesting, and instantly usable for people who already know SQL without any extra learning. In other words... actually better than Linq."actually better than Linq" good statement without knowing it deep linq allows construction and querieng of non table-like hierarchical data, so its more an object-hierarchy store/retrival system which can "also" work with the lower just-tables-like world of sql results
Nov 12 2013
On 11/12/13 8:56 AM, dennis luehring wrote:Am 12.11.2013 17:39, schrieb Andrei Alexandrescu:Yah, it was an exaggeration. Linq is very powerful. AndreiMaybe the problem needs to be reformulated for D. I think an SQL mixin that either stays unchanged (for DB engines) or translates to a D expression (for native D data types) would be doable, nontrivial, interesting, and instantly usable for people who already know SQL without any extra learning. In other words... actually better than Linq."actually better than Linq" good statement without knowing it deep linq allows construction and querieng of non table-like hierarchical data, so its more an object-hierarchy store/retrival system which can "also" work with the lower just-tables-like world of sql results
Nov 12 2013
On Tuesday, 12 November 2013 at 16:39:18 UTC, Andrei Alexandrescu wrote:On 11/12/13 7:21 AM, Ellery Newcomer wrote:I was using linq as an example of what we could do with this DIP or what it should be able to do. It wasn't a suggestion of how we should implement such a library. I also identified with it that having scoped variables from the initiation call is required for safety as well as pragmas for error. Later Jacob alerted me to warning as well. Will submit pull once warning is done. I also suggested a generic lexer with rules to make it well defined. With it also if's like templates have for macro over loading but nobody was keen for this hence not on wiki. Yes this can be done already in theory however it doesnt make it not a valid use case.the .NET framework can do this because it exposes an api for querying, building, and compiling asts. D cannot do this because it doesn't. (and I have tried to make it work)Maybe the problem needs to be reformulated for D. I think an SQL mixin that either stays unchanged (for DB engines) or translates to a D expression (for native D data types) would be doable, nontrivial, interesting, and instantly usable for people who already know SQL without any extra learning. In other words... actually better than Linq. Andrei
Nov 12 2013
On 2013-11-12 15:38, John Colvin wrote:for those of us entirely unfamiliar with linq, what is this supposed to do? Select people with name "John" from a collection of people, like in sql? It seems trivial to do this using filter, or am I missing something...?The idea of that example is, as Dicebot said, to convert the AST of the lambda to a string containing SQL code then query the database and return the result. The interesting part here, in the context of macros, is to convert the lambda to an SQL string. The filter is not applied on the result, it's converted to SQL and performed in the database. -- /Jacob Carlborg
Nov 13 2013
On Tue, 12 Nov 2013 14:38:43 -0000, John Colvin <john.loughran.colvin gmail.com> wrote:On Tuesday, 12 November 2013 at 13:50:49 UTC, Jacob Carlborg wrote:Linq is often confused with LinqToSQL, the above was a description of what happens in the latter. If Person was an object representing a table from a SQL database, then calling 'where' on it would translate into an IQueryable<Person> object which when iterated upon using foreach would execute the SQL statement shown above and return the resulting rows as <someperson> objects one by one to the foreach body. Pure Linq is a DSL, an alternate syntax, which looks a lot like SQL, which can translate to SQL but is not limited to SQL. It could translate to any alternate database syntax, or simply access a container supporting the required operations. The motivation is the same as for "foreach", it is a general syntax for accessing a wide range of containers including databases with a common syntax. We could, equally, go the other way, use the IMO nicer composition syntax X.where(..).foo(...).etc and translate that to SQL, without the need to the SQL like DSL inside D. For some LINQ examples, see: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b For a specific where example using a simple container, see "Where - simple 1" R -- Using Opera's revolutionary email client: http://www.opera.com/mail/auto person = Person.where(e => e.name == "John"); Translates to: select * from person where name = 'John'for those of us entirely unfamiliar with linq, what is this supposed to do? Select people with name "John" from a collection of people, like in sql? It seems trivial to do this using filter, or am I missing something...?
Nov 13 2013
Am 13.11.2013 10:58, schrieb Regan Heath:Linq is often confused with LinqToSQL, the above was a description of what happens in the latter. If Person was an object representing a table from a SQL database, then calling 'where' on it would translate into an IQueryable<Person> object which when iterated upon using foreach would execute the SQL statement shown above and return the resulting rows as <someperson> objects one by one to the foreach body. Pure Linq is a DSL, an alternate syntax, which looks a lot like SQL, which can translate to SQL but is not limited to SQL. It could translate to any alternate database syntax, or simply access a container supporting the required operations.linq allows construction AND querying of non table-like hierarchical data, so its more an (basetypes|object)-hierarchy store/retrival system which can "also" work with the lower just-tables-like world of sql results
Nov 13 2013
Am 13.11.2013 11:41, schrieb dennis luehring:Am 13.11.2013 10:58, schrieb Regan Heath:but linq isn't good in graph operations like neo4j http://www.neo4j.org/learn/cypher which woulds be also very nice as an macro feature for in D reference traversingLinq is often confused with LinqToSQL, the above was a description of what happens in the latter. If Person was an object representing a table from a SQL database, then calling 'where' on it would translate into an IQueryable<Person> object which when iterated upon using foreach would execute the SQL statement shown above and return the resulting rows as <someperson> objects one by one to the foreach body. Pure Linq is a DSL, an alternate syntax, which looks a lot like SQL, which can translate to SQL but is not limited to SQL. It could translate to any alternate database syntax, or simply access a container supporting the required operations.linq allows construction AND querying of non table-like hierarchical data, so its more an (basetypes|object)-hierarchy store/retrival system which can "also" work with the lower just-tables-like world of sql results
Nov 13 2013
On 2013-11-13 10:58, Regan Heath wrote:The motivation is the same as for "foreach", it is a general syntax for accessing a wide range of containers including databases with a common syntax. We could, equally, go the other way, use the IMO nicer composition syntax X.where(..).foo(...).etc and translate that to SQL, without the need to the SQL like DSL inside D.My original example was not Linq. I tried to make it look as much as ranges as possible. Yes, I'm tinking something like what you're suggesting: Post.where(e => e.title == "Foo" && e.comments.title == "Bar").join(e => e.comments); -- /Jacob Carlborg
Nov 13 2013
On 11/12/2013 10:20 AM, Walter Bright wrote:I confess I have some serious reservations about AST macros in general: 1. I've seen very heavy use of such macros in macro assemblers. What happens is people use it to invent their own (very baroque) language on top of the existing assembler one. Anyone trying to read the code has to learn this new unique language, and given the limitations of the macro capability, it often comes with unfixable bizarre corner cases and limitations.Yes, this is a big issue. I have similar concerns about UDA, but it's easier to put the most needed UDAs into phobos making them more standardized.4. AST macros, pretty much by definition, manipulate the AST. However, if you examine the semantic routines in DMD, a *lot* more is required to do more significant things. The symbol table must be consulted, etc. I just don't see how one could hope to implement something like function overloading with AST macros. Or template type deduction. Or closure semantics, attribute inference, etc. Sure, some forms of foreach can be rewritten into for statements by manipulating the AST, but not the more interesting forms, such as the ones that deal with opApply().That's the question we'd have to answer. I think what we should target for is that constructs like async/await or SIMDifying of code can be implemented using AST macros.For example, the Linq example in the DIP is not compelling, as aesthetically nicer code can be written using D's ranges and algorithms: auto data = arr.filter!(x => x > 5).array; be blunt it's like the old: #define BEGIN { #define END } macros used in old C code to make it look like Pascal.True
Nov 12 2013
On 2013-11-12 10:20, Walter Bright wrote:I confess I have some serious reservations about AST macros in general: 1. I've seen very heavy use of such macros in macro assemblers. What happens is people use it to invent their own (very baroque) language on top of the existing assembler one. Anyone trying to read the code has to learn this new unique language, and given the limitations of the macro capability, it often comes with unfixable bizarre corner cases and limitations.There's a word for that, it's called DSL (Domain Specific Language) :)This got so bad that in some cases I know of, the poor sap who is given the job of making improvements resorted to running the assembler to generate an object file, then disassembling the object file back into source code! Something went very wrong for this to be necessary. I know in my own assembler work I have abandoned all use of macros.DSL's are so popular so many languages are specifically designed to make it easy to create DLS's.(Note that macros in typical assemblers are far more powerful than C's macro language, which stands out for being pathetically underpowered.) 2. Macros are something that should be used very sparingly. However, this is not what happens. I used to be perplexed that even top shelf C/C++ programmers tend to write what I not so humbly consider to be pretty abusive use of macros. Now it just saddens me.It depends on what kind of macros we're talking about. For C preprocessor macros, absolutely. But just because to different features have the same word "macro", you shouldn't put the in the same box. I guess I shouldn't have used the word "macro" at all in the DIP.3. Lisp is a language that encourages users to write macros to pretty much invent a custom language for the task at hand. Heavy use of such makes the code unrecognizable as being Lisp code. I believe a language ought to have some "anchors" that the person reading the code can reliably recognize. (GO has taken this idea pretty far.)Lisp doesn't have any syntax to begin with.4. AST macros, pretty much by definition, manipulate the AST. However, if you examine the semantic routines in DMD, a *lot* more is required to do more significant things. The symbol table must be consulted, etc. I just don't see how one could hope to implement something like function overloading with AST macros. Or template type deduction. Or closure semantics, attribute inference, etc. Sure, some forms of foreach can be rewritten into for statements by manipulating the AST, but not the more interesting forms, such as the ones that deal with opApply().Macros are not for implementing function overloading or template type deduction, we already have those features. I don't consider these easy to implement and they're not lowered in the same way as "scope" or "foreach" are.There are some statements in the DIP about the Context parameter and it'll provide semantic information, but I don't see how this can work without making it an ever-expanding collection of arbitrary methods.We'll just put in what we want and need there. At the worst case you'll get access to the whole compiler. Which is what we want any way, at least the front end, to be usable as a library.5. We've said "no" in the past to things like user-defined tokens, which are closely related.No, they're not.6. Note that D has a limited form of AST macros with mixin templates.Yes, I do know. Note that they are too limiting compared to AST macros.To sum up, any AST macro proposal has some tough barriers to get over. Within its necessarily severe semantic limitations, it has to deliver a pretty compelling set of solutions, while avoiding the morass of incomprehensibility that far too many macro systems become in practice.Note that AST macros (according to the DIP) is not anything like C preprocessor macros. Basically the only thing they have in common is the name, "macro". It's not a valid comparison. C macros are textual macros. They can create completely new syntax. AST macros cannot. They work at the semantic level in the compiler, just as templates. They can add new semantic meaning to existing syntax. Just like templates, macros need to lex and parse correctly. Templates do not need to be semantically correct if they're not instantiated. -- /Jacob Carlborg
Nov 13 2013
1. I've seen very heavy use of such macros in macro assemblers. What happens is people use it to invent their own (very baroque) language on top of the existing assembler one. Anyone trying to read the code has to learn this new unique language, and given the limitations of the macro capability, it often comes with unfixable bizarre corner cases and limitations.Metaprogramming (almost) does the same. At least that is my impression. Sometimes I have to go through hundreds of lines of templated D code to understand what a single line does...
Nov 14 2013
On 11/10/2013 10:20 PM, 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/DIP50Thanks, looks like an insightful discussion.
Nov 12 2013
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/DIP50I 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
Nov 13 2013
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"); }Currently this would be sent as a string. I have suggested previously (given a lexer implementation) a lexer would be included that can work by line and symbol. This is fine but it would mean the lexer would need to parse it before calling the macro itself. Perhaps it should be explored a forced parsing and validation of macro values?I would have to write: mixin(foo!(q{ writeln("foo"); writeln("foo again"); }));AST macros currently suggested do not work at the same stage as mixins, as far as I am aware. They work at a much earlier stage. Mixins have limits because of there lateness in lexing process.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 }I find it intriguing to add a keyword to distinguish a D code block from a string. As currently they are parsed the same way.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 }));Perhaps a different way of identifying such code is required? query "{ from element in array where element > 2 add element to data } Although it would act as a triple quoted string, except only valid for macros maybe? This would signify that the following block of text was to be pushed into a macro. Otherwise it would be assumed as valid D code? Assuming a lexer is available it could check that any code given to a macro is correct. I will be submitting a pull request for pragma error and warning so if it is not valid the macro could fire a compile error.
Nov 13 2013
On 2013-11-13 12:49, Rikki Cattermole wrote:AST macros currently suggested do not work at the same stage as mixins, as far as I am aware. They work at a much earlier stage. Mixins have limits because of there lateness in lexing process.I think macros would work on the same stage as mixins.Assuming a lexer is available it could check that any code given to a macro is correct. I will be submitting a pull request for pragma error and warning so if it is not valid the macro could fire a compile error.All macro invocations are already checked. They're lexed and parsed. Marcos work at the semantic phase. Then when the macro is returned the resulting AST is typed checked as usual. -- /Jacob Carlborg
Nov 13 2013
On 2013-11-13 09:15, luka8088 wrote: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.I'm not a fan of the Linq example either. Or rather if I put it like this. I think the Linq example is quite a good example what can be done with AST macros. But I don't think it's a good fit in D.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:Well, the macros in the DIP only supports the D syntax. The macros work at the semantic level. You cannot create new syntax but you can give existing syntax new meaning. Compared with current D, macros need to lex and parse correctly. But they don't need to be semantically correct. That's the same thing as with templates, they can be semantically invalid as long as they're not instantiated. The Linq example is lexically correct. I'm not sure if the parser will reject it or not.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.As it says in the DIP, this is one suggestion of the syntax, if new syntax is needed at all. It's just easier to show examples like that than building a complete AST with function calls. As you can see I have an alternative that doesn't require new syntax: http://wiki.dlang.org/DIP50#The_AST_Macro Instead of "<[ a + b ]>" you would do "ast(a + b)" or "ast { a + b }".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.Strings are far from enough. Then you have missed the whole idea. It's not supposed to be syntax sugar for string mixins. -- /Jacob Carlborg
Nov 13 2013
On 13.11.2013. 13:47, Jacob Carlborg wrote:On 2013-11-13 09:15, luka8088 wrote:Oh, I see. It seems that I indeed missed the point. It seems to me that this DIP could to be granulated into: AST reflection, AST manipulation and AST template. The reason for this, as far as I see, is that although they overlap in some cases, in other they could be used independently and it could help with understanding. Regarding AST reflection and AST manipulation, I have been thinking and found a few situations that bugs me: In the example of auto person = Person.where(e => e.name == "John"); what would be the response of: auto f = e => e.name == "John"; auto person = Person.where(f); I guess it should be a compiler error because f could be modified at runtime and f's body could be hidden. So basically AST macros are something that look like D but actually are not D. This seems to me like an example that look good as a toy example but fails on the larger scale so I agree with Water in this matter (unless better examples/explanations are provided). Or maybe I am not seeing it clear enough. But! Regarding AST templates, I think something like the following would be a great syntax sugar: int i = 5; Ast a = t{ // t as template int j = $i; int k = $i + $i; }; // ... alter ast here if necessary mixin(a); Where syntax (and semantic) in template must be strictly D. The only difference would be $ sign which would allow reference to symbols outside the template. So if you would want to have conditional template you could write: int i = 5; int j; bool b = false; mixin(t{ $j = $i; static if ($b) { $j++; } });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.Strings are far from enough. Then you have missed the whole idea. It's not supposed to be syntax sugar for string mixins.
Nov 19 2013
On 2013-11-19 19:32, luka8088 wrote:Oh, I see. It seems that I indeed missed the point. It seems to me that this DIP could to be granulated into: AST reflection, AST manipulation and AST template. The reason for this, as far as I see, is that although they overlap in some cases, in other they could be used independently and it could help with understanding. Regarding AST reflection and AST manipulation, I have been thinking and found a few situations that bugs me: In the example of auto person = Person.where(e => e.name == "John"); what would be the response of: auto f = e => e.name == "John"; auto person = Person.where(f); I guess it should be a compiler error because f could be modified at runtime and f's body could be hidden.I haven't thought about that. But AST macros work at compile timeSo basically AST macros are something that look like D but actually are not D. This seems to me like an example that look good as a toy example but fails on the larger scale so I agree with Water in this matter (unless better examples/explanations are provided). Or maybe I am not seeing it clear enough. But! Regarding AST templates, I think something like the following would be a great syntax sugar: int i = 5; Ast a = t{ // t as template int j = $i; int k = $i + $i; }; // ... alter ast here if necessary mixin(a);So you don't like that it's not a "mixin" there with AST macros?Where syntax (and semantic) in template must be strictly D. The only difference would be $ sign which would allow reference to symbols outside the template.If the semantics need to be valid this is very limited. Even more limiting than what we have now with string mixins. Note that with AST macros, the input needs to syntactically valid. The resulting AST of the macro needs to both be syntactically and semantically valid D code. -- /Jacob Carlborg
Nov 19 2013
On 19.11.2013. 21:32, Jacob Carlborg wrote:On 2013-11-19 19:32, luka8088 wrote:Well, do think about that :) auto f = e => e.name == "John"; if (true) f = e => e.name == "Jack"; auto person = Person.where(f); I can think of a many use cases where conditional query generation is required. But I don't see how this could be done using AST macros.Oh, I see. It seems that I indeed missed the point. It seems to me that this DIP could to be granulated into: AST reflection, AST manipulation and AST template. The reason for this, as far as I see, is that although they overlap in some cases, in other they could be used independently and it could help with understanding. Regarding AST reflection and AST manipulation, I have been thinking and found a few situations that bugs me: In the example of auto person = Person.where(e => e.name == "John"); what would be the response of: auto f = e => e.name == "John"; auto person = Person.where(f); I guess it should be a compiler error because f could be modified at runtime and f's body could be hidden.I haven't thought about that. But AST macros work at compile timeUm, sorry. I don't understand the question. This example (and suggestion) was suppose to show that we could allow AST mixins as well as string mixins. It should behave like string mixins but the main difference is that AST is structured so it much cleaner to manipulate.So basically AST macros are something that look like D but actually are not D. This seems to me like an example that look good as a toy example but fails on the larger scale so I agree with Water in this matter (unless better examples/explanations are provided). Or maybe I am not seeing it clear enough. But! Regarding AST templates, I think something like the following would be a great syntax sugar: int i = 5; Ast a = t{ // t as template int j = $i; int k = $i + $i; }; // ... alter ast here if necessary mixin(a);So you don't like that it's not a "mixin" there with AST macros?When I first started programing I was introduced to static typing. Then I discovered dynamic typing and dynamic structures (in php mostly). And for me at that time it was much better and easier to use. However, over time I learned that sometimes limitations are good and now like static typing much more :) My point here is that limits are sometimes good, although that don't seem that way. I think that we should think of a more complex (real world) examples and than real issues will reveal themselves.Where syntax (and semantic) in template must be strictly D. The only difference would be $ sign which would allow reference to symbols outside the template.If the semantics need to be valid this is very limited. Even more limiting than what we have now with string mixins. Note that with AST macros, the input needs to syntactically valid. The resulting AST of the macro needs to both be syntactically and semantically valid D code.
Nov 19 2013
On 2013-11-19 21:54, luka8088 wrote:Well, do think about that :) auto f = e => e.name == "John"; if (true) f = e => e.name == "Jack"; auto person = Person.where(f); I can think of a many use cases where conditional query generation is required. But I don't see how this could be done using AST macros.Using the Rails plugin, which I've got this idea from, I would not make the lambda conditional but the whole statement, translated to D: auto person = Person.scoped(); if (true) person = person.where(e => e.name == "Jack"); else person = person.where(e => e.name == "John");Um, sorry. I don't understand the question. This example (and suggestion) was suppose to show that we could allow AST mixins as well as string mixins. It should behave like string mixins but the main difference is that AST is structured so it much cleaner to manipulate.What I was trying to say is, what don't you like about my suggestion. Is it that the "mixin" keyword isn't used. -- /Jacob Carlborg
Nov 20 2013
On 20.11.2013. 9:04, Jacob Carlborg wrote:On 2013-11-19 21:54, luka8088 wrote:Ok, I see. Yes, I tried to think of a case where this could not work but I was unable to find one.Well, do think about that :) auto f = e => e.name == "John"; if (true) f = e => e.name == "Jack"; auto person = Person.where(f); I can think of a many use cases where conditional query generation is required. But I don't see how this could be done using AST macros.Using the Rails plugin, which I've got this idea from, I would not make the lambda conditional but the whole statement, translated to D: auto person = Person.scoped(); if (true) person = person.where(e => e.name == "Jack"); else person = person.where(e => e.name == "John");If I understood you correctly, the issue with current way DSLs are implemented is that code needs to be parsed two times. First time DSL author parses it and creates D code from it, and second time D compiler parses that D code and compiles it. What I would suggest in this case is that instead of intercepting the compiler and "fixing" the semantics before it is verified we allow the user to build D Ast and give it to the compiler. That is why I used the mixin in my example. Ast dCodeAst = dslToD!(q{ if true do() else dont() dont2() whatever() }); // manipulate dCodeAst mixin(dCodeAst); The point of this example is that mixin() accepts Ast instead of string. That way, we parse our DSL to D Ast and give it straight to the compiler and everything is done only once!Um, sorry. I don't understand the question. This example (and suggestion) was suppose to show that we could allow AST mixins as well as string mixins. It should behave like string mixins but the main difference is that AST is structured so it much cleaner to manipulate.What I was trying to say is, what don't you like about my suggestion. Is it that the "mixin" keyword isn't used.
Nov 20 2013
On 2013-11-20 23:25, luka8088 wrote:If I understood you correctly, the issue with current way DSLs are implemented is that code needs to be parsed two times. First time DSL author parses it and creates D code from it, and second time D compiler parses that D code and compiles it. What I would suggest in this case is that instead of intercepting the compiler and "fixing" the semantics before it is verified we allow the user to build D Ast and give it to the compiler. That is why I used the mixin in my example. Ast dCodeAst = dslToD!(q{ if true do() else dont() dont2() whatever() }); // manipulate dCodeAst mixin(dCodeAst); The point of this example is that mixin() accepts Ast instead of string. That way, we parse our DSL to D Ast and give it straight to the compiler and everything is done only once!So how is this different except for my proposal, except the use of q{} and "mixin"? -- /Jacob Carlborg
Nov 20 2013
On 21.11.2013. 8:28, Jacob Carlborg wrote:On 2013-11-20 23:25, luka8088 wrote:When using q{} compiler treats the contents as a regular string, and you have to parse it and give it to the compiler using "mixin". So basically you can say to the compiler: this part of code is my DSL and I will parse it and check the semantics instead of you, then when I am done I will give you D AST represantation of it. The interpretation of the content of q{} is up to you, where in other proposals compiler builds AST based on, I would say, guessing. Take a look at this last example. And lets say that it is from python. In python dont2() belong inside else block. So how else would you make sure that compiler behaves accordingly?If I understood you correctly, the issue with current way DSLs are implemented is that code needs to be parsed two times. First time DSL author parses it and creates D code from it, and second time D compiler parses that D code and compiles it. What I would suggest in this case is that instead of intercepting the compiler and "fixing" the semantics before it is verified we allow the user to build D Ast and give it to the compiler. That is why I used the mixin in my example. Ast dCodeAst = dslToD!(q{ if true do() else dont() dont2() whatever() }); // manipulate dCodeAst mixin(dCodeAst); The point of this example is that mixin() accepts Ast instead of string. That way, we parse our DSL to D Ast and give it straight to the compiler and everything is done only once!So how is this different except for my proposal, except the use of q{} and "mixin"?
Nov 21 2013
On 2013-11-21 09:01, luka8088 wrote:When using q{} compiler treats the contents as a regular string, and you have to parse it and give it to the compiler using "mixin". So basically you can say to the compiler: this part of code is my DSL and I will parse it and check the semantics instead of you, then when I am done I will give you D AST represantation of it. The interpretation of the content of q{} is up to you, where in other proposals compiler builds AST based on, I would say, guessing. Take a look at this last example. And lets say that it is from python. In python dont2() belong inside else block. So how else would you make sure that compiler behaves accordingly?Sorry, I meant your original suggestion of using t{}. -- /Jacob Carlborg
Nov 21 2013
On 21.11.2013. 9:31, Jacob Carlborg wrote:On 2013-11-21 09:01, luka8088 wrote:Um, my it's suppose to be the same as <[ ... ]> but I liked t{ ... } syntax better as it looked more consistent with what D already has. But I should have used <[ ... ]> , my mistake sorry.When using q{} compiler treats the contents as a regular string, and you have to parse it and give it to the compiler using "mixin". So basically you can say to the compiler: this part of code is my DSL and I will parse it and check the semantics instead of you, then when I am done I will give you D AST represantation of it. The interpretation of the content of q{} is up to you, where in other proposals compiler builds AST based on, I would say, guessing. Take a look at this last example. And lets say that it is from python. In python dont2() belong inside else block. So how else would you make sure that compiler behaves accordingly?Sorry, I meant your original suggestion of using t{}.
Nov 22 2013
On 2013-11-22 10:27, luka8088 wrote:Um, my it's suppose to be the same as <[ ... ]> but I liked t{ ... } syntax better as it looked more consistent with what D already has. But I should have used <[ ... ]> , my mistake sorry.I thought you argued that the t{ } need to contain semantically valid code? -- /Jacob Carlborg
Nov 22 2013
On 22.11.2013. 11:17, Jacob Carlborg wrote:On 2013-11-22 10:27, luka8088 wrote:Yes. I still do. And I think that <[ ... ]> should contain semantically valid code. In my opinion, if you wish to be able to write anything else, the way to go would be: write it using q{ ... }, parse it yourself, build a valid D AST yourself, give D AST to the compiler using mixin(). Currently mixin() only accepts a string that contains a valid D code. So if you have a custom parser for your DSL you need to generate a D code from that DSL and then pass it to the compiler using mixin() in order for the compiler to parse it again. Double parsing could be skipped if mixin() would accept already built D AST and on the other hand parsing DSL and building D AST yourself would allow maximum flexibility.Um, my it's suppose to be the same as <[ ... ]> but I liked t{ ... } syntax better as it looked more consistent with what D already has. But I should have used <[ ... ]> , my mistake sorry.I thought you argued that the t{ } need to contain semantically valid code?
Nov 22 2013
On Friday, 22 November 2013 at 23:43:26 UTC, luka8088 wrote:Yes. I still do. And I think that <[ ... ]> should contain semantically valid code. In my opinion, if you wish to be able to write anything else, the way to go would be: write it using q{ ... }, parse it yourself, build a valid D AST yourself, give D AST to the compiler using mixin().Then q{ } or <[ ]> would be very limited. Not even templets need to contain semantically valid code, as long as it's not instantiated. Usually the idea with AST macros is to take code that is not valid (semantically) and create a meaning for it (make it valid). If it's already valid in the first place why use AST macros at all? Just use the code as is. Hmm, it could be useful to only allow semantically valid code and use macros to add new things to the code. But again, very limiting.Currently mixin() only accepts a string that contains a valid D code.The AST returned from a macro need to be valid D code as well.So if you have a custom parser for your DSL you need to generate a D code from that DSL and then pass it to the compiler using mixin() in order for the compiler to parse it again. Double parsing could be skipped if mixin() would accept already built D AST and on the other hand parsing DSL and building D AST yourself would allow maximum flexibility.You can already do that today with string mixins, although you would need to convert the AST back to a string first. -- /Jacob Carlborg
Nov 23 2013
On 23.11.2013. 11:40, Jacob Carlborg wrote:On Friday, 22 November 2013 at 23:43:26 UTC, luka8088 wrote: Then q{ } or <[ ]> would be very limited. Not even templets need to contain semantically valid code, as long as it's not instantiated. Usually the idea with AST macros is to take code that is not valid (semantically) and create a meaning for it (make it valid). If it's already valid in the first place why use AST macros at all? Just use the code as is. Hmm, it could be useful to only allow semantically valid code and use macros to add new things to the code. But again, very limiting.I don't think so. What I was proposing is to split the problem into sub-problems and then find the best method for each one. Templates are one of them and they solve the problem of not so pretty string concatenation and that is way they should contain only valid D code. I don't think that writing a non valid code and then making in valid in the compilation process should be allowed. Only transforming one valid code into another valid code but hygienically. I don't have a concrete example why that is a bad idea, I can only speak from experience. So this is only my opinion, not an argument.Yeah. I was referring to http://forum.dlang.org/post/l5vcct$2lit$1 digitalmars.com So for example, the problem from referred post could be addressed by defining as AST struct type that is accessible to user and making mixin() accept both string and AST struct. That is also why I wrote http://forum.dlang.org/post/l6n91e$29hd$1 digitalmars.com It seems to me now that we don't understand each other so well :) Maybe we should put in more examples?Currently mixin() only accepts a string that contains a valid D code.The AST returned from a macro need to be valid D code as well.So if you have a custom parser for your DSL you need to generate a D code from that DSL and then pass it to the compiler using mixin() in order for the compiler to parse it again. Double parsing could be skipped if mixin() would accept already built D AST and on the other hand parsing DSL and building D AST yourself would allow maximum flexibility.You can already do that today with string mixins, although you would need to convert the AST back to a string first.
Nov 23 2013
On 21.11.2013. 8:28, Jacob Carlborg wrote:On 2013-11-20 23:25, luka8088 wrote:What we currently have: custom syntax ---> custom parser ---> custom code generator ---> D syntax (as string) D syntax (as string) ---> mixin --- \ D syntax (read by compiler) -----------> D AST (held by the compiler, unreachable) ---> compilation to binary (unreachable) The way I see it we should allow to following: custom syntax ---> custom parser ----- \ D syntax inside <[ ... ]> template -------> D AST (as struct) D AST (as struct) ---> mixin --- \ D syntax (read by compiler) --------> D AST (held by compiler) D AST (held by compiler, reachable) ---> reflection ---> D AST (as struct) D AST (held by compiler) ---> compilation to binaryThe point of this example is that mixin() accepts Ast instead of string. That way, we parse our DSL to D Ast and give it straight to the compiler and everything is done only once!So how is this different except for my proposal, except the use of q{} and "mixin"?
Nov 22 2013
On 2013-11-22 10:44, luka8088 wrote:What we currently have:I should have been t{ }. I do understand the difference between t{ } and q{ }. But not between <[ ]> and t{ }. Is it just two different syntaxes for the same? -- /Jacob Carlborg
Nov 22 2013
On 22.11.2013. 11:19, Jacob Carlborg wrote:On 2013-11-22 10:44, luka8088 wrote:Yes. t{ } and <[ ]> are the same.What we currently have:I should have been t{ }. I do understand the difference between t{ } and q{ }. But not between <[ ]> and t{ }. Is it just two different syntaxes for the same?
Nov 22 2013
13-Nov-2013 12:15, luka8088 пишет:On 10.11.2013. 22:20, Jacob Carlborg wrote:[snip]foo { writeln("foo"); writeln("foo again"); } I would have to write: mixin(foo!(q{ writeln("foo"); writeln("foo again"); }));Actually even now it's can be just foo!q{ ... }; For instance this is compilable: { import std.regex; auto r = ctRegex!"how do you think that works?"; } See ctRegex template in std.regex. -- Dmitry Olshansky
Nov 13 2013