// Originally compiled with dmd 2.031 on Gentoo Linux. import std.stdio; class Foo { Foo b; int c; Foo d; int e; int q; Foo f; Foo opIndex( int val ) { writefln("Foo[%d]",val); if ( f is null ) f = new Foo(); return f; } Foo opIndexAssign( Foo foo, int val ) { writefln("Foo[%d] = foo",val); return f = foo; } } void main() { Foo a = new Foo(); a.b = new Foo(); a.d = new Foo(); Foo p = new Foo(); void reset() { a.b.e = 42; a.b.c = 10; a.d.c = 8; p.q = 4; } void printAll() { writefln("a.b.c = %d", a.b.c); writefln("a.b.e = %d", a.b.e); writefln("a.d.c = %d", a.d.c); writefln("p.q = %d", p.q); } reset(); writefln("initial state:"); printAll(); writefln(""); writefln("monstrosity 1 results:"); a.d[a.b.c++].c *= (p.q++) * (a.b.e = 3); printAll(); reset(); writefln(""); writefln("monstrosity 2 results:"); auto t1 = a; auto t2 = t1.d; // a.d[...] auto t3 = t1.b; // a.b.c++ auto t4 = t3.c; // a.b.c++ auto t5 = t2[t4]; // a.d[a.b.c++] auto t6 = t5.c; // a.d[a.b.c++].c // (p.q++) auto t7 = p; auto t8 = t7.q; // (a.b.e = 3) auto t9 = a; // Must be done again since it appears twice in the expression. auto t10 = t9.b; // Do not make a new temporary for .c; // Explicit assignments call only write properties. They do not read. t6 *= t8 * (t10.e = 3); // (a.b.e = 3) // t9.b = t10; // Multiple assignments to b are refused. Already done at bottom. // a = t9; // Multiple assignments to a are refused. Already done at bottom. // a.d[a.b.c++].c = ... t5.c = t6; // a.d[...] t2[t4] = t5; t1.d = t2; // a = t1; // Multiple assignments to a are refused. Already done at bottom. // The opPostInc expressions must be done last. // (p.q++) t8++; t7.q = t8; p = t7; // (a.b.c++) t4++; t3.c = t4; t1.b = t3; a = t1; // END printAll(); } /* This program should print the following: initial state: a.b.c = 10 a.b.e = 42 a.d.c = 8 p.q = 4 monstrosity 1 results: Foo[10] a.b.c = 11 a.b.e = 3 a.d.c = 8 p.q = 5 monstrosity 2 results: Foo[10] Foo[10] = foo a.b.c = 11 a.b.e = 3 a.d.c = 8 p.q = 5 */