public override object VisitAssign(BoundAssignEx x) { // A = A <binOp> <right> if (x.Target is BoundVariableRef trg && MatchExprSkipCopy(x.Value, out BoundBinaryEx binOp, isCopied: out _) && binOp.Left is BoundVariableRef valLeft && trg.Variable == valLeft.Variable) { var newTrg = new BoundVariableRef(trg.Name) .WithAccess(trg.Access.WithRead()) .WithSyntax(trg.PhpSyntax); // A = A +/- 1; => ++A; / --A; if ((binOp.Operation == Ast.Operations.Add || binOp.Operation == Ast.Operations.Sub) && binOp.Right.ConstantValue.IsInteger(out long rightVal) && rightVal == 1) { TransformationCount++; return(new BoundIncDecEx(newTrg, binOp.Operation == Ast.Operations.Add, false).WithAccess(x)); } // A = A & B => A &= B; // &, |, ^, <<, >>, +, -, *, /, %, **, . switch (binOp.Operation) { case Ast.Operations.BitAnd: case Ast.Operations.BitOr: case Ast.Operations.BitXor: case Ast.Operations.ShiftLeft: case Ast.Operations.ShiftRight: case Ast.Operations.Add: case Ast.Operations.Sub: case Ast.Operations.Mul: case Ast.Operations.Div: case Ast.Operations.Mod: case Ast.Operations.Pow: case Ast.Operations.Concat: TransformationCount++; var compoundOp = AstUtils.BinaryToCompoundOp(binOp.Operation); return(new BoundCompoundAssignEx(newTrg, binOp.Right, compoundOp).WithAccess(x)); } } return(base.VisitAssign(x)); }