November 11, 2013
On Monday, 11 November 2013 at 08:12:59 UTC, Jacob Carlborg wrote:
> On 2013-11-11 08:46, Rikki Cattermole wrote:
>
>> One of our targets for AST macros should be the ability to replicate
>> roughly linq from c# / .net.
>>
>> 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'
>
>> Also c#'s get set should be rather similar as well.
>> 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.
>> Disclaimer I don't like c# or .net but I am partial to these features.
>
> That's quite similar one of the examples, I like to call it "property shortcut":
>
> http://wiki.dlang.org/DIP50#Attribute_macros
>
>> 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.
>
> 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.

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.

November 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.com

> As for examples, here's a couple of suggestions:
> * Expression to prefix notation
> * Expression to SQL
> * AutoImplement properties (like C#)

Would 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 matching

Pattern matching usually requires new syntax, which this proposal does not support.

-- 
/Jacob Carlborg
November 11, 2013
Am 11.11.2013 09:28, schrieb simendsjo:
> On Sunday, 10 November 2013 at 22:33:34 UTC, bearophile wrote:
>> Jacob Carlborg:
>>
>>> http://wiki.dlang.org/DIP50
>>
>> I suggest to add some more use cases (possibly with their
>> implementation).
>>
>> Bye,
>> bearophile
>
> 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
> * AutoImplement properties (like C#)
> * Number intervals, like "int i = int[10..20];" where only 10 to
> 20 are legal values
> * Discriminated union
> * Pattern matching
>

can you add the example to the DIP?
November 11, 2013
> One of our targets for AST macros should be the ability to
> replicate roughly linq from c# / .net.
>
> 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

November 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 values

What'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
November 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/DIP50

I like it, Jacob. With or without <[ ]> it is a good proposal, and I see several places where I would use it.

+1
November 11, 2013
On Monday, 11 November 2013 at 09:02:01 UTC, bearophile wrote:
> 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");

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".

> --------
>
> simendsjo:
>
>> * Number intervals, like "int i = int[10..20];" where only 10 to 20 are legal values
>
> What'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

Nothing wrong with it, I was just trying to come up with some examples. I don't say they're necessarily good :)
November 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
November 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
November 11, 2013
On 2013-11-11 10:23, simendsjo wrote:
> On Monday, 11 November 2013 at 09:02:01 UTC, bearophile wrote:

>> auto 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".

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 Carlborg