November 20, 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.
November 20, 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
November 20, 2013
On 20.11.2013. 9:04, Jacob Carlborg wrote:
> 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");

Ok, I see. Yes, I tried to think of a case where this could not work but I was unable to find one.

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

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!
November 21, 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
November 21, 2013
On 21.11.2013. 8:28, Jacob Carlborg wrote:
> 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"?
> 

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?
November 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
November 22, 2013
On 21.11.2013. 9:31, Jacob Carlborg wrote:
> 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{}.
> 

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.

November 22, 2013
On 21.11.2013. 8:28, Jacob Carlborg wrote:
> On 2013-11-20 23:25, luka8088 wrote:
>>
>> 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"?
> 

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 binary

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