Here's the evaluation algorithm for compound assignment:

What I believe it's trying to specify is that the compound assignment defers partially to the evaluation of a parse tree that would have been produced if the source text matched by the AssignmentExpression did not have the = at the end of the AssignmentOperator. But there's additional complexity around the dereferencing of the LHS that doesn't allow us to specify it quite like that. A strict reading (aside from the AST/value type mismatch in Evaluation parameters) would cause an implementer to evaluate each of the sub-expressions more than once.
Is there something better we can do here?
defers partially to the evaluation of a parse tree that would have been produced if the source text matched by the AssignmentExpression did not have the = at the end of the AssignmentOperator
I don't think that's what it's trying to say. That is, when it says the expression /lval op rval/, it's not creating a parse tree (which wouldn't work anyway, because lval and rval are language values, not parse nodes, which is maybe what you meant by "AST/value typemismatch"). It's just saying "apply /op/ with the semantics that it has when it appears as an infix operator".
Yeah, I think we can do better.
If we want to explicitly reference existing semantics, it's currently a bit tricky. E.g., say the AssignmentOperator is +=. Then instead of step 6 in the above algorithm, we'd want to go over to evaluating an AdditiveExpression. But since we've already got lval and rval, we'd want to start at step 5 there.
So to make it clean, we could take step 5 etc of that algorithm, factor it out into an abstract operation (e.g., ApplyPlusOperator or maybe just Plus), and then invoke that from both spots. Then repeat for the 11 other AssignmentOperators.
(Note that the BigInt proposal is doing something similar to the above, but at a slightly lower level. I think the two would mesh well.)
To make it really easy for the caller, we could define an abstract operation, roughly:
ApplyBinaryOperator(_operator_, _lval_, _rval_)
1. If _operator_ is `+`, return Plus(_lval_, _rval_)
....
We could also use this in places like the semantics of MultiplicativeExpressions, which is already effectively doing a 'switch' on the operator (and will do so more explicitly when BigInt lands).
We do something similar with the Binary Bitwise Operators evaluation semantics, using @ as a pseudo-argument in the algorithm steps. I'd like to get rid of that as well. We can pass the parsed token to an AO to unify the common parts.
I'd forgotten about this. Shall I make a PR, or is someone else working on it?
@jmdyck I would love that!
Most helpful comment
I'd forgotten about this. Shall I make a PR, or is someone else working on it?