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?

Reply via email to