I've narrowed a problem down to this code
$a = 3;
$a = 3 * $a++;
echo $a; //9
$a = 3;
$a = $a * $a++;
echo $a; //12
Here are VLD opcodes for 1st operation
compiled vars: !0 = $a
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > ASSIGN !0, 3
3 1 POST_INC ~2 !0
2 MUL ~3 ~2, 3
3 ASSIGN !0, ~3
4 4 ECHO !0
5 5 > RETURN 1
for 2nd operation ($a * $a++)
compiled vars: !0 = $a
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > ASSIGN !0, 3
3 1 POST_INC ~2 !0
2 MUL ~3 !0, ~2
3 ASSIGN !0, ~3
4 4 ECHO !0
5 5 > RETURN 1
2 questions :
Why is the post-increment executed first? It doesn't make any sense to me. Traditionally, I thought it would increment the variable after performing all other operations in the expression. That's what it says on the official PHP site as well. So, by my logic (which might be incredibly flawed), both expressions would return 10. But as we can see, the POST_INC is being performed before anything else.
As we can see, during the MUL operation, for first case, ~2 should be the result for the POST_INC (so value should be 4), which then multiplied by 3 is 12. But in the second case, where !0 is still 3, ~2 appears to hold a value of 3 as well, for reasons unknown to me, so we get 9 in the end. Why does this happen?
I'm not fluent with reading opcodes, so maybe i missed something, I'm guessing the order of operands ~2, 3 vs !0, ~2 matters, but I don't understand how.