Re: Multiple assignment

2011-02-26 Thread spir

On 02/26/2011 01:56 AM, bearophile wrote:

Is this program showing a bug in multiple assignments (DMD 2.052)?


void main() {
 int i;
 int[2] x;
 i, x[i] = 1;
 assert(x == [1, 0]); // OK

 int j;
 int[2] y;
 y[j], j = 1;
 assert(y == [0, 0]); // Not OK
}


At the end of the program I expect y to be [1,0] instead of [0,0].


I'm far to be a C expert, but that looks like very normal C semantics, ain't 
it? with all its stupidity, indeed...

I would enjoy an error in both cases. (not enough rvalues)

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Multiple assignment

2011-02-26 Thread spir

On 02/26/2011 04:26 AM, Steven Schveighoffer wrote:

Let me fix that for you:

func(j++, y[j])


That should be illegal: a statement used as expression, but keeping it's effect 
anyway, and not the least kind of, namely an assignment, meaning a change of 
the program state.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Multiple assignment

2011-02-26 Thread Jonathan M Davis
On Saturday 26 February 2011 00:51:45 spir wrote:
 On 02/26/2011 04:26 AM, Steven Schveighoffer wrote:
  Let me fix that for you:
  
  func(j++, y[j])
 
 That should be illegal: a statement used as expression, but keeping it's
 effect anyway, and not the least kind of, namely an assignment, meaning a
 change of the program state.

Umm. There is no statement used as an expression here. The only statement is a 
function call. Both j++ and y[j] are expressions. Even the function call is an 
expression. It's just that if it's followed by a semi-colon, it becomes a 
statement.

Regardless, the best solution is to make the order of evaluation of the 
function 
arguments fixed at left-to-right instead of undefined. And as I understand it, 
Walter intends to make D do that at some point. It's just that he hasn't gotten 
around to it yet.

- Jonathan M Davis


Re: Multiple assignment

2011-02-26 Thread Dan Olson
Jonathan M Davis jmdavisp...@gmx.com writes:

 On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
 On 02/25/2011 05:09 PM, bearophile wrote:
int j;
int[2] y;
y[j] = j = 1;
 
 I think that's undefined behavior in C and C++. It is not defined
 whether j's previous or past value is used in y[j].
 
 I would expect the situation be the same in D.

 No, that should be perfectly defined. What's undefined is when you do
 something like func(j, y[j]). The evaluation order of the function
 arguments is undefined.  However, the evaluation order when dealing
 with an assignment should be defined.  I _could_ be wrong about that,
 but there's no question that the assignments themselves are guaranteed
 to be done in right-to-left order.

 - Jonathan M Davis

Java made assignment well defined by saying:
  First evaluate the left-hand-side to determine a variable to assign to.
  Then evaluate the right-hand-side for the value.

If the right-hand-side is another assignment, repeat...

So given:
int i = 0;
int[] a = new int[4];

a[i++] = a[i+=2] = i = 9;

You are can depend on getting:

i = 9
a = [9, 0, 0, 9]


D today on windows yields the same output.  Will the D language spec
make this the define behavior too?  I noticed that
http://www.digitalmars.com/d/2.0/expression.html currently says it is
implementation defined.  The example given is:

i = i++;

None of this is stuff you'd normally want to write unless entering an
obfuscated programming contest, but Java's rules say if i = 42, 'i' will end up
still being 42.

Dan


Re: Multiple assignment

2011-02-26 Thread Jonathan M Davis
On Saturday 26 February 2011 11:18:20 Dan Olson wrote:
 Jonathan M Davis jmdavisp...@gmx.com writes:
  On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
  On 02/25/2011 05:09 PM, bearophile wrote:
 int j;
 int[2] y;
 y[j] = j = 1;
  
  I think that's undefined behavior in C and C++. It is not defined
  whether j's previous or past value is used in y[j].
  
  I would expect the situation be the same in D.
  
  No, that should be perfectly defined. What's undefined is when you do
  something like func(j, y[j]). The evaluation order of the function
  arguments is undefined.  However, the evaluation order when dealing
  with an assignment should be defined.  I _could_ be wrong about that,
  but there's no question that the assignments themselves are guaranteed
  to be done in right-to-left order.
  
  - Jonathan M Davis
 
 Java made assignment well defined by saying:
   First evaluate the left-hand-side to determine a variable to assign to.
   Then evaluate the right-hand-side for the value.
 
 If the right-hand-side is another assignment, repeat...
 
 So given:
 int i = 0;
 int[] a = new int[4];
 
 a[i++] = a[i+=2] = i = 9;
 
 You are can depend on getting:
 
 i = 9
 a = [9, 0, 0, 9]
 
 
 D today on windows yields the same output.  Will the D language spec
 make this the define behavior too?  I noticed that
 http://www.digitalmars.com/d/2.0/expression.html currently says it is
 implementation defined.  The example given is:
 
 i = i++;
 
 None of this is stuff you'd normally want to write unless entering an
 obfuscated programming contest, but Java's rules say if i = 42, 'i' will
 end up still being 42.

The assignment order is well-defined in both C++ an D, but the order of 
evaluation of the expressions is not. Now, Walter has stated in the past that 
he 
intends to make the order of evaluation of expressions defined in D at some 
point, but he hasn't done it yet, so right now it's still undefined.

Regardless, it doesn't really hurt you any to avoid ambiguous expressions like 
these and since there _are_ languages which leave ther evaluation order as 
undefined, it's probably a good habit to get into to _not_ write such ambiguous 
expressions.

- Jonathan M Davis


Multiple assignment

2011-02-25 Thread bearophile
Is this program showing a bug in multiple assignments (DMD 2.052)?


void main() {
int i;
int[2] x;
i, x[i] = 1;
assert(x == [1, 0]); // OK

int j;
int[2] y;
y[j], j = 1;
assert(y == [0, 0]); // Not OK
}


At the end of the program I expect y to be [1,0] instead of [0,0].

Yet this C program with GCC:

#include stdio.h
int main() {
int i = 0;
int x[2] = {0, 0};
i, x[i] = 1;
printf(%d %d\n, x[0], x[1]);

int j = 0;
int y[2] = {0, 0};
y[j], j = 1;
printf(%d %d\n, y[0], y[1]);

return 0;
}


has the same output as DMD:
1 0
0 0

Bye,
bearophile


Re: Multiple assignment

2011-02-25 Thread simendsjo

On 26.02.2011 01:56, bearophile wrote:

Is this program showing a bug in multiple assignments (DMD 2.052)?


void main() {
 int i;
 int[2] x;
 i, x[i] = 1;
 assert(x == [1, 0]); // OK

 int j;
 int[2] y;
 y[j], j = 1;
 assert(y == [0, 0]); // Not OK
}


At the end of the program I expect y to be [1,0] instead of [0,0].

Yet this C program with GCC:

#include stdio.h
int main() {
 int i = 0;
 int x[2] = {0, 0};
 i, x[i] = 1;
 printf(%d %d\n, x[0], x[1]);

 int j = 0;
 int y[2] = {0, 0};
 y[j], j = 1;
 printf(%d %d\n, y[0], y[1]);

 return 0;
}


has the same output as DMD:
1 0
0 0

Bye,
bearophile


I couldn't find any info on the comma expression in the language 
reference, but this was my first google hit:


A comma expression contains two operands of any type separated by a 
comma and has *left-to-right* associativity. The left operand is fully 
evaluated, possibly producing side effects, and its value, if there is 
one, is *discarded*. The right operand is then evaluated. The type and 
value of the result of a comma expression are those of its right 
operand, after the usual unary conversions




Re: Multiple assignment

2011-02-25 Thread Ali Çehreli

On 02/25/2011 04:56 PM, bearophile wrote:
 Is this program showing a bug in multiple assignments (DMD 2.052)?


 void main() {
  int i;
  int[2] x;
  i, x[i] = 1;

I haven't heard about multiple assignments but that's the comma operator 
up there, separating (and sequencing) two expressions:


1) i
2) x[i] = 1

  assert(x == [1, 0]); // OK

  int j;
  int[2] y;
  y[j], j = 1;

Again, two expressions:

1) y[j]
2) j = 1

Only the second of both cases have an effect.

Ali

  assert(y == [0, 0]); // Not OK
 }


 At the end of the program I expect y to be [1,0] instead of [0,0].

 Yet this C program with GCC:

 #include stdio.h
 int main() {
  int i = 0;
  int x[2] = {0, 0};
  i, x[i] = 1;
  printf(%d %d\n, x[0], x[1]);

  int j = 0;
  int y[2] = {0, 0};
  y[j], j = 1;
  printf(%d %d\n, y[0], y[1]);

  return 0;
 }


 has the same output as DMD:
 1 0
 0 0

 Bye,
 bearophile



Re: Multiple assignment

2011-02-25 Thread bearophile
simendsjo:

 I couldn't find any info on the comma expression in the language 
 reference, but this was my first google hit:
 
 A comma expression contains two operands of any type separated by a 
 comma and has *left-to-right* associativity. The left operand is fully 
 evaluated, possibly producing side effects, and its value, if there is 
 one, is *discarded*. The right operand is then evaluated. The type and 
 value of the result of a comma expression are those of its right 
 operand, after the usual unary conversions
 

Right. But my code was wrong, I meant to write this:

void main() {
int i;
int[2] x;
i = x[i] = 1;
assert(x == [1, 0]); // OK

int j;
int[2] y;
y[j] = j = 1;
assert(y == [0, 1]); // Not OK
}

And I think it is working as you expect it to.

Thank you and sorry for the noise,
bearophile


Re: Multiple assignment

2011-02-25 Thread Ali Çehreli

On 02/25/2011 05:09 PM, bearophile wrote:

  int j;
  int[2] y;
  y[j] = j = 1;

I think that's undefined behavior in C and C++. It is not defined 
whether j's previous or past value is used in y[j].


I would expect the situation be the same in D.

Ali



Re: Multiple assignment

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
 On 02/25/2011 05:09 PM, bearophile wrote:
int j;
int[2] y;
y[j] = j = 1;
 
 I think that's undefined behavior in C and C++. It is not defined
 whether j's previous or past value is used in y[j].
 
 I would expect the situation be the same in D.

No, that should be perfectly defined. What's undefined is when you do something 
like func(j, y[j]). The evaluation order of the function arguments is 
undefined. 
However,  the evaluation order when dealing with an assignment should be 
defined. 
I _could_ be wrong about that, but there's no question that the assignments 
themselves are guaranteed to be done in right-to-left order.

- Jonathan M Davis


Re: Multiple assignment

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis jmdavisp...@gmx.com  
wrote:



On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:

On 02/25/2011 05:09 PM, bearophile wrote:
   int j;
   int[2] y;
   y[j] = j = 1;

I think that's undefined behavior in C and C++. It is not defined
whether j's previous or past value is used in y[j].

I would expect the situation be the same in D.


No, that should be perfectly defined. What's undefined is when you do  
something
like func(j, y[j]). The evaluation order of the function arguments is  
undefined.
However,  the evaluation order when dealing with an assignment should be  
defined.
I _could_ be wrong about that, but there's no question that the  
assignments

themselves are guaranteed to be done in right-to-left order.


Let me fix that for you:

func(j++, y[j])

-Steve


Re: Multiple assignment

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 19:26:14 Steven Schveighoffer wrote:
 On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis jmdavisp...@gmx.com
 
 wrote:
  On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
  On 02/25/2011 05:09 PM, bearophile wrote:
 int j;
 int[2] y;
 y[j] = j = 1;
  
  I think that's undefined behavior in C and C++. It is not defined
  whether j's previous or past value is used in y[j].
  
  I would expect the situation be the same in D.
  
  No, that should be perfectly defined. What's undefined is when you do
  something
  like func(j, y[j]). The evaluation order of the function arguments is
  undefined.
  However,  the evaluation order when dealing with an assignment should be
  defined.
  I _could_ be wrong about that, but there's no question that the
  assignments
  themselves are guaranteed to be done in right-to-left order.
 
 Let me fix that for you:
 
 func(j++, y[j])

LOL. Yes. I forgot to alter j in the expression. Good catch.

- Jonathan M Davis


Re: Multiple assignment

2011-02-25 Thread Ali Çehreli

On 02/25/2011 06:10 PM, Jonathan M Davis wrote:

On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:

On 02/25/2011 05:09 PM, bearophile wrote:
 int j;
 int[2] y;
 y[j] = j = 1;

I think that's undefined behavior in C and C++. It is not defined
whether j's previous or past value is used in y[j].

I would expect the situation be the same in D.


No, that should be perfectly defined. What's undefined is when you do something
like func(j, y[j]). The evaluation order of the function arguments is undefined.
However,  the evaluation order when dealing with an assignment should be 
defined.
I _could_ be wrong about that, but there's no question that the assignments
themselves are guaranteed to be done in right-to-left order.

- Jonathan M Davis


Standard texts are very difficult to read. I found a 2005 draft of the 
C++ standard. 5 Expressions, paragraph 4:


quote
Except where noted, the order of evaluation of operands of individual 
operators and subexpressions of individual expres-
sions, and the order in which side effects take place, is 
unspecified.58) Between the previous and next sequence point a
 scalar object shall have its stored value modified at most once by the 
evaluation of an expression. Furthermore, the prior
  value shall be accessed only to determine the value to be stored. The 
requirements of this paragraph shall be met for
 each allowable ordering of the subexpressions of a full expression; 
otherwise the behavior is undefined. [ Example:

i = v [ i ++]; / / the behavior is undefined
i = 7 , i ++ , i ++; / / i becomes 9
i = ++ i + 1; / / the behavior is undefined
i = i + 1; / / the value of i is incremented
— end example ]
/quote

To complete, footnote 58 is:

quote
58)
The precedence of operators is not directly specified, but it can be 
derived from the syntax.

/quote

The section for the assignment operator does not mention anything to the 
contrary. According to my current understanding and my now-hazy 
recollections of old discussions on C++ news groups, in the following 
statement


  a() = b() = c();

the value of c() is assigned to b(), and the value of that expression is 
assigned to a(); but the order in which the three expressions are 
evaluated are unspecified.


Hence, if the code behaves contrary to 5.1 above, it has undefined behavior.

This was bearophile's statement:

  y[j] = j = 1;

The assignment operators do not introduce sequence points; there are 
only two: before and after the whole line above. The code does not obey 
the prior value shall be accessed only to determine the value to be 
stored. Above, the prior value is used to determine which element of y 
is being assigned to.


Ali


Re: Multiple assignment

2011-02-25 Thread Jonathan M Davis
On Friday 25 February 2011 22:32:47 Ali Çehreli wrote:
 On 02/25/2011 06:10 PM, Jonathan M Davis wrote:
  On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
  On 02/25/2011 05:09 PM, bearophile wrote:
   int j;
   int[2] y;
   y[j] = j = 1;
  
  I think that's undefined behavior in C and C++. It is not defined
  whether j's previous or past value is used in y[j].
  
  I would expect the situation be the same in D.
  
  No, that should be perfectly defined. What's undefined is when you do
  something like func(j, y[j]). The evaluation order of the function
  arguments is undefined. However,  the evaluation order when dealing with
  an assignment should be defined. I _could_ be wrong about that, but
  there's no question that the assignments themselves are guaranteed to be
  done in right-to-left order.
  
  - Jonathan M Davis
 
 Standard texts are very difficult to read. I found a 2005 draft of the
 C++ standard. 5 Expressions, paragraph 4:
 
 quote
 Except where noted, the order of evaluation of operands of individual
 operators and subexpressions of individual expres-
 sions, and the order in which side effects take place, is
 unspecified.58) Between the previous and next sequence point a
   scalar object shall have its stored value modified at most once by the
 evaluation of an expression. Furthermore, the prior
value shall be accessed only to determine the value to be stored. The
 requirements of this paragraph shall be met for
   each allowable ordering of the subexpressions of a full expression;
 otherwise the behavior is undefined. [ Example:
 i = v [ i ++]; / / the behavior is undefined
 i = 7 , i ++ , i ++; / / i becomes 9
 i = ++ i + 1; / / the behavior is undefined
 i = i + 1; / / the value of i is incremented
 — end example ]
 /quote
 
 To complete, footnote 58 is:
 
 quote
 58)
 The precedence of operators is not directly specified, but it can be
 derived from the syntax.
 /quote
 
 The section for the assignment operator does not mention anything to the
 contrary. According to my current understanding and my now-hazy
 recollections of old discussions on C++ news groups, in the following
 statement
 
a() = b() = c();
 
 the value of c() is assigned to b(), and the value of that expression is
 assigned to a(); but the order in which the three expressions are
 evaluated are unspecified.
 
 Hence, if the code behaves contrary to 5.1 above, it has undefined
 behavior.
 
 This was bearophile's statement:
 
y[j] = j = 1;
 
 The assignment operators do not introduce sequence points; there are
 only two: before and after the whole line above. The code does not obey
 the prior value shall be accessed only to determine the value to be
 stored. Above, the prior value is used to determine which element of y
 is being assigned to.

Bleh. Well, good to know. Walter wants to make the order such evaluations 
ordered in D at some point though, so eventually it won't be a problem in D - 
though it'll obviously still be a problem in C++. Regardless, avoiding to alter 
a variable and use it multiple times within the same statement or expression is 
a good idea.

- Jonathan M davis