Evaluation order of index expressions
Timon Gehr via Digitalmars-d
digitalmars-d at puremagic.com
Tue May 26 05:51:18 PDT 2015
On 05/26/2015 02:55 AM, deadalnix wrote:
> On Tuesday, 26 May 2015 at 00:07:33 UTC, Timon Gehr wrote:
>>> 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
>>>
>>
>> Why? Strictly left-to-right is the simplest thing.
>
> In case of opAssign kind of thing, LTR is not doable as operator
> overloading, at least not in a backward compatible manner.
Not caching the value of the left hand side is not the same thing as
right-to-left evaluation:
int a=0,b=0;
(b++,a)=b; // ltr gives a==1, rtl gives a==0, caching irrelevant
int a=0,b=0;
((ref a,b)=>a=b)((b++,a),b) // operator overloading lowering gives a==1
However, this is a more general problem with operator overloading: the
first argument is always passed by reference, hence it is not cached:
int[] foo(){
int a=1;
int[] r;
a=(a=a*2)+(a=a+2); // with l-t-r and caching: 6
r~=a;
alias string=immutable(char)[];
static struct S{
int a;
this(int a){ this.a=a; }
S opBinary(string op)(S t){ return S(mixin("a "~op~" t.a")); }
ref S opUnary(string op:"++")(){ ++a; return this; }
}
static struct T{
int a;
this(int a){ this.a=a; }
T opBinaryRight(string op)(T s){ return T(mixin("s.a "~op~" a")); }
ref T opUnary(string op:"++")(){ ++a; return this; }
}
auto s=S(1);
auto t=T(1);
s=(s=s*S(2))+(s=s+S(2)); // with l-t-r and lowering: 8
t=(t=t*T(2))+(t=t+T(2)); // either 8 or 12, depending on whether
evaluation order is preserved during lowering.
r~=s.a,r~=t.a;
return r;
}
I guess overloaded operators could be made to cache the old value. (As
they do in CTFE, apparently. :o))
However, this seems like overkill. Any other ideas?
More information about the Digitalmars-d
mailing list