June 14, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | monarch_dodra: > *as* a matter of fact, that's how gcc does it for C++: > > //---- > int main() > { > int i = 0; > ++i = ++i; > assert(i == 2); //passes > } > //---- > > Left to right > First, evaluate lhs: i has the value 1. > then evaluate rhs, which will now have the value 2. > assign 2 to i. > * i == 2 * > > right to left: > First, evalutate rhs: i has the value 1, an rhs 1. > Evaluate lhs: i is now 2. > But then assign rhs (1) to lhs. > * i == 1 * > > So yeah, left to right evaluation is completely coherent, and a valid scheme. I think the results of your code is not defined by the C++ standard, so in practice writing that code is a programmer's mistake. And it's a mistake to design a modern programming language that accepts code that gives undefined results. To be considered a grown up language D needs define only one semantics, or forbid code like that. > Evaluation order, even when defined, remains obscure once associative operations come into play, and still bite you in the ass anyways, Even when the programmer isn't able to know what the result will be, it's essential for the D code to give the same result on all CPUs and on all compilers. Bye, bearophile |
June 14, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 14 June 2013 12:04, bearophile <bearophileHUGS@lycos.com> wrote:
> Iain Buclaw:
>
>
>> However yes, the behaviour relies on the order the sucky X86 ABI pushes arguments onto the stack (which for this array op is from right to left). Whereas on *all* other architectures it will execute the parameters in left to right order, which would be a, c, b in this case.
>
>
> D needs the same standard order of evaluations for all expressions on all compilers, regardless of the CPUs. The only other acceptable alternative is to statically forbid code that risks having variable results.
>
> (And I think the right order for that is b, c, a).
>
Right... and the way to do that would be to evaluate the argument before calling the array op.
eg:
ref _tmp1 = b()[];
ref _tmp2 = c()[];
ref _tmp3 = a()[];
_tmp3 = _arrayOp(_tmp3, _tmp2, _tmp1);
--
Iain Buclaw
*(p < e ? p++ : p) = (c & 0x0f) + '0';
|
June 14, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Thursday, 13 June 2013 at 23:25:42 UTC, Jonathan M Davis wrote:
> Walter has expressed a desire in the past to make it so that D requires that
> the evaluation order of arguments be left-to-right in order to avoid bugs, and
> while these aren't exactly function arguments, they're basically function
> arguments to a built-in function called +, so I could definitely see Walter
> wanting to require that the evaluation order be left-to-right. However, while
> Walter has expressed an interest in making it a requirement, AFAIK, it has
> never officially become one and the spec says nothing on the matter.
>
> - Jonathan M Davis
I would like to cast my vote for this feature. It is very nice to have, and it would prevent a few bugs from popping up.
|
June 14, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | Am Fri, 14 Jun 2013 01:09:18 +0200 schrieb "David Nadlinger" <code@klickverbot.at>: > There is a test in the DMD testsuite that verifies that the evaluation order in the following statement > > a()[] = b()[] + c()[]; > > is b, c, a. > > I'm trying to figure out why this regressed with the 2.063 merge in LDC, but (where) is this specified in the first place? > > David Related old discussions: http://bugzilla.gdcproject.org/show_bug.cgi?id=8 http://forum.dlang.org/thread/bniaxycuguviwfdtojzf@forum.dlang.org (I knew we discussed this before ;-) |
June 14, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 06/14/2013 01:04 PM, bearophile wrote:
> ...
> (And I think the right order for that is b, c, a).
> ...
Why?
|
June 14, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 06/14/2013 02:13 AM, Jonathan M Davis wrote:
> ...
> Personally, I would expect it to fully evaluate the right-hand side of an
> assignment expression before evaluating anything on the left, and I'd expect
> the same of any operator which is right-associative, ...
Why? Associativity is unrelated to evaluation order.
|
June 15, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Saturday, June 15, 2013 01:46:49 Timon Gehr wrote:
> On 06/14/2013 02:13 AM, Jonathan M Davis wrote:
> > ...
> > Personally, I would expect it to fully evaluate the right-hand side of an
> > assignment expression before evaluating anything on the left, and I'd
> > expect the same of any operator which is right-associative, ...
>
> Why? Associativity is unrelated to evaluation order.
It seems natural to me that the stuff on the associated side would be evaluated before the stuff on the other, but that doesn't mean that it's the best way to go. It's just what I would have expected. So, if there's a good reason to do it differently, then I don't necessarily have a problem with that.
- Jonathan M Davis
|
June 15, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to Iain Buclaw | On Friday, 14 June 2013 at 09:59:07 UTC, Iain Buclaw wrote:
> Interesting, that certainly doesn't flag up as a regression in the
> 2.063 merge in GDC... :o)
>
> However yes, the behaviour relies on the order the sucky X86 ABI
> pushes arguments onto the stack (which for this array op is from right
> to left). Whereas on *all* other architectures it will execute the
> parameters in left to right order, which would be a, c, b in this
> case.
In LDC, the actual evaluation order is completely separate from the target ABI (you simply pass the SSA vales to a function call in LLVM, and you can decide the order in which to create them yourself).
Turns out that for array operations, we actually need to reverse the order compared to our normal one (left to right), as their signatures have specifically been chosen for the evaluation order in DMD that is intertwined with the backend ABI/function call implementation details.
David
|
June 15, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 06/15/2013 04:21 AM, Jonathan M Davis wrote:
> On Saturday, June 15, 2013 01:46:49 Timon Gehr wrote:
>> On 06/14/2013 02:13 AM, Jonathan M Davis wrote:
>>> ...
>>> Personally, I would expect it to fully evaluate the right-hand side of an
>>> assignment expression before evaluating anything on the left, and I'd
>>> expect the same of any operator which is right-associative, ...
>>
>> Why? Associativity is unrelated to evaluation order.
>
> It seems natural to me that the stuff on the associated side would be evaluated
> before the stuff on the other, but that doesn't mean that it's the best way to
> go. It's just what I would have expected. So, if there's a good reason to do
> it differently, then I don't necessarily have a problem with that.
>
> - Jonathan M Davis
>
Well, I can't think of a _good_ reason now. :)
Since Walter once stated that evaluation is supposed to be LTR, this is what I have implemented for CTFE. The stack-based bytecode interpreter already relies on having the address-related information pushed before the value, and changing the evaluation order would therefore imply a little work.
|
June 15, 2013 Re: Expression evaluation order | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On 15 June 2013 18:16, David Nadlinger <code@klickverbot.at> wrote:
> On Friday, 14 June 2013 at 09:59:07 UTC, Iain Buclaw wrote:
>>
>> Interesting, that certainly doesn't flag up as a regression in the 2.063 merge in GDC... :o)
>>
>> However yes, the behaviour relies on the order the sucky X86 ABI pushes arguments onto the stack (which for this array op is from right to left). Whereas on *all* other architectures it will execute the parameters in left to right order, which would be a, c, b in this case.
>
>
> In LDC, the actual evaluation order is completely separate from the target ABI (you simply pass the SSA vales to a function call in LLVM, and you can decide the order in which to create them yourself).
>
> Turns out that for array operations, we actually need to reverse the order compared to our normal one (left to right), as their signatures have specifically been chosen for the evaluation order in DMD that is intertwined with the backend ABI/function call implementation details.
>
We don't have that luxury, but as I said in the last thread brought up
on this some time ago, for extern(D) we just make temporaries and
compound them all together (_a = a(), _b = b(), _c = c(),
_arrayop(_a, _b, _c)); There's no reason why this can't be done for
extern (C) - other than it will break a load of code that relies on
X86 ABI behaviour (such as what array operations apparently do...)
--
Iain Buclaw
*(p < e ? p++ : p) = (c & 0x0f) + '0';
|
Copyright © 1999-2021 by the D Language Foundation