[Nickle]Sequencing of expressions with side effects

Keith Packard nickle@nickle.org
Tue, 23 Jul 2002 13:47:19 -0700


Around 12 o'clock on Jul 23, Bart Massey wrote:

> > 	a = (int b = 2) ** b;
> 
> Huh?  The example you give has nothing to do with the order
> of evaluation of assignment, as near as I can tell

I was attempting to demonstrate the issue with the exponentiation operator 
which is also right associative.  In this case, a strict left-to-right 
rule ensures that when 'b' is lexically in scope, the initializer has been 
run.  If the RHS of the '**' operator is evaluated before the LHS, the 
initializer for 'b' won't have been run.

> 1. The meaning of an expression should never be changed by
>    explicitly putting in the parentheses implied by
>    precedence and associativity.

That's true in either evaluation order.

> 2. Expression evaluation should honor explicit parentheses:
>    parenthesized subexpressions should always be evaluated
>    before their containing expressions.

But that doesn't constrain the evaluation of the LHS of a binary operator 
wrt the RHS.  In a strict left-to-right world, you just start evaluating 
the expression elements from left to right, executing the operators when 
the appropriate operands have been evaluated:

	a = (int b = 2) ** b;

	r1 = ref(a)
	r2 = ref(b)
	r3 = 2
	*r2 = r3
	r4 = b
	r5 = r3 ** r4
	*r1 = r5

Consider this in the form of a parse tree:

		=
	       / \
              a   **
                 /  \
                =    b
               / \
              b   2

A left-bearing depth-first walk of the tree yields the correct order of
evaluation.

>> 	a += b		-> 	(poly* ap = &a), (*ap = *ap + b)
>
> Since a is required to be an lvalue, I'm not seeing how this
> matters.  Maybe when a is of pointer type?

	*a++ += b	->	(poly *ap = a++), (*ap = *ap + b)

The important part is to compute the reference value only once.

Keith Packard        XFree86 Core Team        HP Cambridge Research Lab