On Tue, Dec 24, 2013 at 05:15:15PM +0100, Timon Gehr wrote: > On 12/24/2013 01:48 AM, H. S. Teoh wrote: > >Agreed. Note that introducing assignment into the mix may not help > >matters, but complicate them even more. For example: > > > > int x=1, y=0; > > writeln((y = ++x) + (++y--) * (x=y)); // what does this print? > >... > > 'y-- is not an lvalue'.
D'oh, should've tested my code before posting it. Next time I'm gonna write all code snippets as unittests... :-P (OK, kidding.) > Assuming we add parens as follows: > > int x=1, y=0; > writeln((y = ++x) + ((++y)--) * (x=y)); > > We should get 8 according to strict left to right evaluation rules. > Furthermore, we should have the value 2 stored in both x and y. What is "strict left to right evaluation", since * has to be evaluated before +? Or you consider all side-effects to be evaluated first (from left to right), and then the expression? > >Or worse yet: > > > > int func1(int x) { ... } > > int func2(int x) { ... } > > int func3(int x) { ... } > > > > int function(int)[] funcptrs = [ &func1, &func2, &func3 ]; > > > > int x=0, y=0; > > y += funcptrs[++x--](y = --x++); // what does this do? > > > > 'x-- is not an lvalue' > 'x++ is not an lvalue' > > Assuming we run the following code instead: > > int func1(int x) { return 1*x; } > int func2(int x) { return 2*x; } > int func3(int x) { return 3*x; } > > int function(int)[] funcptrs = [ &func1, &func2, &func3 ]; > > int x=0, y=0; > y += funcptrs[(++x)--](y = (--x)++) > > We should be left in a state where x contains 0 and y contains -2 > according to strict left to right evaluation rules. > > >The only place I can see where you'd even*want* to write code like > >this is in an entry to the IOCCC. Make it refuse to compile, I say. > > I don't think it makes sense to add some arbitrary rules to the > compiler implementation just to ban some code that nobody writes > anyway and potentially some perfectly fine code as well. A potential issue is that forcing a particular evaluation order may be detrimental to the optimizer, e.g., according to strict left-to-right evaluation (if I understand you correctly), then to evaluate this: z = (y = ++x) + ((++y)--) * (x=y) you'd have to compile it into the equivalent of: y = ++x; // i.e., ++x; y = x; tmp1 = y; tmp2 = ++y; // i.e., ++y; tmp2 = y; y--; x=y; z = tmp1 + tmp2 * x; // i.e., tmp3 = tmp2*x; tmp3 += tmp1; z = tmp3; Since the order can't be permuted without changing the semantics, the codegen would have to load x and y multiple times as well as introduce temporaries in order to evaluate the final expression, and the optimizer wouldn't be able to do anything about it. Of course, this is probably not *that* big of a deal if normal expressions without side-effects can be optimized as usual -- it'd be the user's own fault for writing unoptimizable code. Code with side-effects are already difficult to optimize anyway, so it probably doesn't make that big of a difference. T -- "No, John. I want formats that are actually useful, rather than over-featured megaliths that address all questions by piling on ridiculous internal links in forms which are hideously over-complex." -- Simon St. Laurent on xml-dev