May 25, 2015
On 05/25/2015 09:14 PM, Iain Buclaw via Digitalmars-d wrote:
>
>     So what about my previous example?
>
>     int b = 0;
>     ((++b *= 5) *= 2) += ++b * (b -= 6);
>
>     DMD 2.067.1: 60, latest LDC: 65, GDC: ?
>
>
> If the litmus test is "What does GDC do?", then LDC is doing it the
> correct way. :-)

Even if it isn't. ;)
May 25, 2015
> On 05/25/2015 09:14 PM, Iain Buclaw via Digitalmars-d wrote:
>> If the litmus test is "What does GDC do?", then LDC is doing it the correct way. :-)

Perfect. :)

On Monday, 25 May 2015 at 19:17:48 UTC, Timon Gehr wrote:
> Even if it isn't. ;)

It is - on its merge-2.067 branch. ;)
May 25, 2015
On 05/25/2015 09:28 PM, kinke wrote:
>> On 05/25/2015 09:14 PM, Iain Buclaw via Digitalmars-d wrote:
>>> If the litmus test is "What does GDC do?", then LDC is doing it the
>>> correct way. :-)
>
> Perfect. :)
>
> On Monday, 25 May 2015 at 19:17:48 UTC, Timon Gehr wrote:
>> Even if it isn't. ;)
>
> It is - on its merge-2.067 branch. ;)

LDC is doing it the correct way even if "What does GDC do?" is not the litmus test.
May 25, 2015
On 05/24/2015 09:30 PM, kinke wrote:
> <code>
> import core.stdc.stdio;
>
> static int[] _array = [ 0, 1, 2, 3 ];
>
> int[] array() @property { printf("array()\n"); return _array; }
> int   start() @property { printf("start()\n"); return 0; }
> int   end()   @property { printf("end()\n");   return 1; }
>
> void main()
> {
>      array[start..end] = 666;
>      printf("---\n");
>      array[start] = end;
> }
> </code>
>
> <stdout>
> array()
> start()
> end()
> ---
> start()
> array()
> end()
> </stdout>
>
> So for the 2nd assignment's left-hand-side, the index is evaluated
> before evaluating the container! Please don't tell me that's by design. :>
>
> [origin: https://github.com/D-Programming-Language/phobos/pull/3311]

A related issue is that the rewrites documented at http://dlang.org/operatoroverloading.html don't all preserve the order of subexpressions. However, ideally, the order of evaluation would be preserved.
May 25, 2015
On 25 May 2015 21:35, "Timon Gehr via Digitalmars-d" < digitalmars-d@puremagic.com> wrote:
>
> On 05/25/2015 09:28 PM, kinke wrote:
>>>
>>> On 05/25/2015 09:14 PM, Iain Buclaw via Digitalmars-d wrote:
>>>>
>>>> If the litmus test is "What does GDC do?", then LDC is doing it the correct way. :-)
>>
>>
>> Perfect. :)
>>
>> On Monday, 25 May 2015 at 19:17:48 UTC, Timon Gehr wrote:
>>>
>>> Even if it isn't. ;)
>>
>>
>> It is - on its merge-2.067 branch. ;)
>
>
> LDC is doing it the correct way even if "What does GDC do?" is not the
litmus test.

I am not a fan of this dictatorship.  I vote for democracy, if two compilers do 'X', then the odd one out is wrong.  ;-)


May 25, 2015
"Timon Gehr"  wrote in message news:mjvtqm$17d8$1@digitalmars.com...

> A related issue is that the rewrites documented at http://dlang.org/operatoroverloading.html don't all preserve the order of subexpressions. However, ideally, the order of evaluation would be preserved.

As operator overloading is defined in terms of lowering to function calls, I think it's reasonable to decide the order of evaluation after the lowering. This will still be consistent across compilers and platforms.  Preserving the original order would require added complexity that I don't think is warranted. 

May 25, 2015
On 05/25/2015 10:02 PM, Daniel Murphy wrote:
> "Timon Gehr"  wrote in message news:mjvtqm$17d8$1@digitalmars.com...
>
>> A related issue is that the rewrites documented at
>> http://dlang.org/operatoroverloading.html don't all preserve the order
>> of subexpressions. However, ideally, the order of evaluation would be
>> preserved.
>
> As operator overloading is defined in terms of lowering to function
> calls, I think it's reasonable to decide the order of evaluation after
> the lowering. This will still be consistent across compilers and
> platforms.

But almost entirely arbitrary.

> Preserving the original order would require added complexity
> that I don't think is warranted.

The compiler would just need to introduce some temporary variables for the two lowerings. Why wouldn't this be warranted to make overloaded operators consistent with built-in ones? If anything, I think it is desirable to have opBinary(B) on type A and opBinaryRight(A) on type B interchangeable.

What complexity are you worried about?
May 25, 2015
"Timon Gehr"  wrote in message news:mjvvq2$19hd$1@digitalmars.com...

> > As operator overloading is defined in terms of lowering to function
> > calls, I think it's reasonable to decide the order of evaluation after
> > the lowering. This will still be consistent across compilers and
> > platforms.
>
> But almost entirely arbitrary.

Yes.  I don't think this is particularly important, as depending on evaluation order is highly discouraged.

> > Preserving the original order would require added complexity
> > that I don't think is warranted.
>
> The compiler would just need to introduce some temporary variables for the two lowerings. Why wouldn't this be warranted to make overloaded operators consistent with built-in ones? If anything, I think it is desirable to have opBinary(B) on type A and opBinaryRight(A) on type B interchangeable.
>
> What complexity are you worried about?

Introducing temporary variables is added complexity.  It affects all sorts of other parts of the compiler. 

May 25, 2015
On 05/25/2015 10:30 PM, Daniel Murphy wrote:
> "Timon Gehr"  wrote in message news:mjvvq2$19hd$1@digitalmars.com...
>
>> > As operator overloading is defined in terms of lowering to function
>> > calls, I think it's reasonable to decide the order of evaluation after
>> > the lowering. This will still be consistent across compilers and
>> > platforms.
>>
>> But almost entirely arbitrary.
>
> Yes.  I don't think this is particularly important,

Those small ugly corners of the language do add up, and they do cause real problems. For issues like this one, which are not considered important enough, I think it is fine to fix the spec and let the compiler catch up later (with a warning in the spec). I'm not saying this is urgent, just that it is obvious how it ought to be.

> as depending on evaluation order is highly discouraged.
> ...

Doesn't mean it won't happen. Having different evaluation order for expressions that look identical is just asking for really funny problems in generic code, of the sort that will summon more threads like this one.

>> > Preserving the original order would require added complexity
>> > that I don't think is warranted.
>>
>> The compiler would just need to introduce some temporary variables for
>> the two lowerings. Why wouldn't this be warranted to make overloaded
>> operators consistent with built-in ones? If anything, I think it is
>> desirable to have opBinary(B) on type A and opBinaryRight(A) on type B
>> interchangeable.
>>
>> What complexity are you worried about?
>
> Introducing temporary variables is added complexity.  It affects all
> sorts of other parts of the compiler.

This ought to be a matter of changing a few lines in one place. Took me a couple of minutes to implement for opBinaryRight:

-    r=New!CallExp(opoverloadR,[e1]);
-    r.loc=loc;
+    auto tmpe=New!TmpVarExp(e1);
+    tmpe.loc=loc;
+    tmpe.semantic(sc);
+    version(assert) assert(!!tmpe.sym);
+    auto c=New!CallExp(opoverloadR,[tmpe.sym]);
+    r=New!(BinaryExp!(Tok!","))(tmpe,c);
+    r.loc=c.loc=loc;

What makes this different for DMD?

May 25, 2015
On 5/25/15 11:58 AM, Daniel Murphy wrote:
> "Andrei Alexandrescu"  wrote in message
> news:mjvlv5$vch$1@digitalmars.com...
>
>> > which one is correct?
>>
>> GDC. -- Andrei
>
> I don't think it matters too much if we pick strict LTR, or keep dmd's
> existing exception for assign expressions.  IIRC Walter is in favour of
> keeping the exception[1].
>
> Could you and Walter please come to an agreement and confirm here?  It
> should be fairly straightforward to get this fixed once it's clear which
> way it should go.
>
> [1]
> https://github.com/D-Programming-Language/dmd/pull/4035#issuecomment-58861231

I'm fine with RTL for assignment expressions, and LTR everywhere else. Daniel, if you could work this out at front end level so it goes the same way for all backends, that would be fantastic. -- Andrei