You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/02/14 05:45:05 UTC

[groovy] branch GROOVY_3_0_X updated (c9dfd46 -> a6eb333)

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a change to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from c9dfd46  Fix for GROOVY-9396
     new 1ce3294  minor edits
     new a6eb333  GROOVY-8707: SC: use makeSetProperty for compound assignment of property (closes #1167)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../classgen/asm/BinaryExpressionHelper.java       | 251 ++++++++++---------
 .../asm/BinaryExpressionMultiTypeDispatcher.java   | 233 +++++++++---------
 ...icTypesBinaryExpressionMultiTypeDispatcher.java | 267 ++++++++++-----------
 .../groovy/transform/stc/STCAssignmentTest.groovy  |  15 ++
 .../asm/sc/AssignmentsStaticCompileTest.groovy     |  11 +-
 5 files changed, 393 insertions(+), 384 deletions(-)


[groovy] 01/02: minor edits

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 1ce32940bf5738c8e35321dfd58fe2bd5a7bad19
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 13 11:38:27 2020 -0600

    minor edits
---
 .../classgen/asm/BinaryExpressionHelper.java       | 251 ++++++++++-----------
 .../asm/BinaryExpressionMultiTypeDispatcher.java   | 233 +++++++++----------
 ...icTypesBinaryExpressionMultiTypeDispatcher.java | 234 ++++++++-----------
 3 files changed, 335 insertions(+), 383 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
index eaefc56..78944d4 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
@@ -101,7 +101,7 @@ import static org.objectweb.asm.Opcodes.IFNE;
 import static org.objectweb.asm.Opcodes.INSTANCEOF;
 
 public class BinaryExpressionHelper {
-    //compare
+    // compare
     private static final MethodCaller compareIdenticalMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareIdentical");
     private static final MethodCaller compareNotIdenticalMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareNotIdentical");
     private static final MethodCaller compareEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareEqual");
@@ -111,27 +111,30 @@ public class BinaryExpressionHelper {
     private static final MethodCaller compareLessThanEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareLessThanEqual");
     private static final MethodCaller compareGreaterThanMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareGreaterThan");
     private static final MethodCaller compareGreaterThanEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareGreaterThanEqual");
-    //regexpr
+    // regexp
     private static final MethodCaller findRegexMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "findRegex");
     private static final MethodCaller matchRegexMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "matchRegex");
-    // isCase
+    // isCase/isNotCase
     private static final MethodCaller isCaseMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "isCase");
-    // isNotCase
     private static final MethodCaller isNotCaseMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "isNotCase");
 
-    private final WriterController controller;
+    protected final WriterController controller;
     private final UnaryExpressionHelper unaryExpressionHelper;
-    
-    public BinaryExpressionHelper(WriterController wc) {
+
+    public BinaryExpressionHelper(final WriterController wc) {
         this.controller = wc;
         this.unaryExpressionHelper = new UnaryExpressionHelper(this.controller);
     }
-    
-    public WriterController getController(){
+
+    public WriterController getController() {
         return controller;
     }
-    
-    public void eval(BinaryExpression expression) {
+
+    public MethodCaller getIsCaseMethod() {
+        return isCaseMethod;
+    }
+
+    public void eval(final BinaryExpression expression) {
         switch (expression.getOperation().getType()) {
         case EQUAL: // = assignment
             evaluateEqual(expression, false);
@@ -327,8 +330,8 @@ public class BinaryExpressionHelper {
             throw new GroovyBugError("Operation: " + expression.getOperation() + " not supported");
         }
     }
-    
-    protected void assignToArray(Expression parent, Expression receiver, Expression index, Expression rhsValueLoader, boolean safe) {
+
+    protected void assignToArray(final Expression parent, final Expression receiver, final Expression index, final Expression rhsValueLoader, final boolean safe) {
         // let's replace this assignment to a subscript operator with a
         // method call
         // e.g. x[5] = 10
@@ -343,15 +346,7 @@ public class BinaryExpressionHelper {
         rhsValueLoader.visit(controller.getAcg());
     }
 
-    private static boolean isNull(Expression exp) {
-        if (exp instanceof ConstantExpression){
-            return ((ConstantExpression) exp).getValue()==null;
-        } else {
-            return false;
-        }
-    }
-
-    public void evaluateElvisEqual(BinaryExpression expression) {
+    public void evaluateElvisEqual(final BinaryExpression expression) {
         Token operation = expression.getOperation();
         BinaryExpression elvisAssignmentExpression =
                 new BinaryExpression(
@@ -363,7 +358,7 @@ public class BinaryExpressionHelper {
         this.evaluateEqual(elvisAssignmentExpression, false);
     }
 
-    public void evaluateEqual(BinaryExpression expression, boolean defineVariable) {
+    public void evaluateEqual(final BinaryExpression expression, final boolean defineVariable) {
         AsmClassGenerator acg = controller.getAcg();
         CompileStack compileStack = controller.getCompileStack();
         OperandStack operandStack = controller.getOperandStack();
@@ -406,18 +401,18 @@ public class BinaryExpressionHelper {
                 operandStack.box();
             }
 
-            // ensure we try to unbox null to cause a runtime NPE in case we assign 
-            // null to a primitive typed variable, even if it is used only in boxed 
+            // ensure we try to unbox null to cause a runtime NPE in case we assign
+            // null to a primitive typed variable, even if it is used only in boxed
             // form as it is closure shared
-            if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && isNull(rightExpression)) {
+            if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && AsmClassGenerator.isNullConstant(rightExpression)) {
                 operandStack.doGroovyCast(var.getOriginType());
-                // these two are never reached in bytecode and only there 
+                // these two are never reached in bytecode and only there
                 // to avoid verifyerrors and compiler infrastructure hazzle
-                operandStack.box(); 
+                operandStack.box();
                 operandStack.doGroovyCast(lhsType);
             }
-            // normal type transformation 
-            if (!ClassHelper.isPrimitiveType(lhsType) && isNull(rightExpression)) {
+            // normal type transformation
+            if (!ClassHelper.isPrimitiveType(lhsType) && AsmClassGenerator.isNullConstant(rightExpression)) {
                 operandStack.replace(lhsType);
             } else {
                 operandStack.doGroovyCast(lhsType);
@@ -429,7 +424,7 @@ public class BinaryExpressionHelper {
         }
         //TODO: if rhs is VariableSlotLoader already, then skip crating a new one
         BytecodeExpression rhsValueLoader = new VariableSlotLoader(rhsType,rhsValueId,operandStack);
-        
+
         // assignment for subscript
         if (leftExpression instanceof BinaryExpression) {
             BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
@@ -439,7 +434,7 @@ public class BinaryExpressionHelper {
             compileStack.removeVar(rhsValueId);
             return;
         }
-        
+
         compileStack.pushLHS(true);
 
         // multiple declaration
@@ -461,14 +456,14 @@ public class BinaryExpressionHelper {
                     acg.visitVariableExpression(var);
                 }
             }
-        } 
+        }
         // single declaration
         else if (defineVariable) {
             rhsValueLoader.visit(acg);
             operandStack.remove(1);
             compileStack.popLHS();
             return;
-        } 
+        }
         // normal assignment
         else {
             int mark = operandStack.getStackLength();
@@ -481,13 +476,13 @@ public class BinaryExpressionHelper {
             operandStack.remove(operandStack.getStackLength()-mark);
         }
         compileStack.popLHS();
-        
+
         // return value of assignment
         rhsValueLoader.visit(acg);
         compileStack.removeVar(rhsValueId);
     }
 
-    private void loadInitValue(ClassNode type) {
+    private void loadInitValue(final ClassNode type) {
         MethodVisitor mv = controller.getMethodVisitor();
         if (ClassHelper.isPrimitiveType(type)) {
             mv.visitLdcInsn(0);
@@ -497,7 +492,7 @@ public class BinaryExpressionHelper {
         controller.getOperandStack().push(type);
     }
 
-    protected void evaluateCompareExpression(MethodCaller compareMethod, BinaryExpression expression) {
+    protected void evaluateCompareExpression(final MethodCaller compareMethod, final BinaryExpression expression) {
         Expression leftExp = expression.getLeftExpression();
         TypeChooser typeChooser = controller.getTypeChooser();
         ClassNode cn = controller.getClassNode();
@@ -512,30 +507,30 @@ public class BinaryExpressionHelper {
             BinaryExpressionMultiTypeDispatcher helper = new BinaryExpressionMultiTypeDispatcher(getController());
             done = helper.doPrimitiveCompare(leftType, rightType, expression);
         }
-        
+
         if (!done) {
             AsmClassGenerator acg = controller.getAcg();
             OperandStack operandStack = controller.getOperandStack();
-            
+
             leftExp.visit(acg);
             operandStack.box();
             rightExp.visit(acg);
             operandStack.box();
-    
+
             compareMethod.call(controller.getMethodVisitor());
             ClassNode resType = ClassHelper.boolean_TYPE;
             if (compareMethod==findRegexMethod) {
                 resType = ClassHelper.OBJECT_TYPE;
-            } 
+            }
             operandStack.replace(resType,2);
         }
     }
-    
-    private void evaluateCompareTo(BinaryExpression expression) {
+
+    private void evaluateCompareTo(final BinaryExpression expression) {
         Expression leftExpression = expression.getLeftExpression();
         AsmClassGenerator acg = controller.getAcg();
         OperandStack operandStack = controller.getOperandStack();
-        
+
         leftExpression.visit(acg);
         operandStack.box();
 
@@ -548,7 +543,7 @@ public class BinaryExpressionHelper {
         operandStack.replace(ClassHelper.Integer_TYPE,2);
     }
 
-    private void evaluateLogicalAndExpression(BinaryExpression expression) {
+    private void evaluateLogicalAndExpression(final BinaryExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
         AsmClassGenerator acg = controller.getAcg();
         OperandStack operandStack = controller.getOperandStack();
@@ -571,8 +566,8 @@ public class BinaryExpressionHelper {
         mv.visitLabel(trueCase);
         operandStack.remove(1); // have to remove 1 because of the GOTO
     }
-    
-    private void evaluateLogicalOrExpression(BinaryExpression expression) {
+
+    private void evaluateLogicalOrExpression(final BinaryExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
         AsmClassGenerator acg = controller.getAcg();
         OperandStack operandStack = controller.getOperandStack();
@@ -582,22 +577,22 @@ public class BinaryExpressionHelper {
         expression.getLeftExpression().visit(acg);
         operandStack.doGroovyCast(ClassHelper.boolean_TYPE);
         Label trueCase = operandStack.jump(IFNE);
-        
+
         expression.getRightExpression().visit(acg);
         operandStack.doGroovyCast(ClassHelper.boolean_TYPE);
         Label falseCase = operandStack.jump(IFEQ);
-        
+
         mv.visitLabel(trueCase);
         ConstantExpression.PRIM_TRUE.visit(acg);
         operandStack.jump(GOTO, end);
 
         mv.visitLabel(falseCase);
         ConstantExpression.PRIM_FALSE.visit(acg);
-        
+
         mv.visitLabel(end);
     }
-    
-    protected void evaluateBinaryExpression(String message, BinaryExpression binExp) {
+
+    protected void evaluateBinaryExpression(final String message, final BinaryExpression binExp) {
         CompileStack compileStack = controller.getCompileStack();
 
         Expression receiver = binExp.getLeftExpression();
@@ -606,10 +601,10 @@ public class BinaryExpressionHelper {
         // ensure VariableArguments are read, not stored
         compileStack.pushLHS(false);
         controller.getInvocationWriter().makeSingleArgumentCall(receiver, message, arguments, binExp.isSafe());
-        compileStack.popLHS();        
+        compileStack.popLHS();
     }
 
-    protected void evaluateArrayAssignmentWithOperator(String method, BinaryExpression expression, BinaryExpression leftBinExpr) {
+    protected void evaluateArrayAssignmentWithOperator(final String method, final BinaryExpression expression, final BinaryExpression leftBinExpr) {
         CompileStack compileStack    = getController().getCompileStack();
         AsmClassGenerator acg             = getController().getAcg();
         OperandStack os              = getController().getOperandStack();
@@ -638,32 +633,32 @@ public class BinaryExpressionHelper {
         compileStack.removeVar(receiver.getIndex());
     }
 
-    protected void evaluateBinaryExpressionWithAssignment(String method, BinaryExpression expression) {
+    protected void evaluateBinaryExpressionWithAssignment(final String method, final BinaryExpression expression) {
         Expression leftExpression = expression.getLeftExpression();
         AsmClassGenerator acg = controller.getAcg();
         OperandStack operandStack = controller.getOperandStack();
-        
+
         if (leftExpression instanceof BinaryExpression) {
             BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
             if (leftBinExpr.getOperation().getType() == Types.LEFT_SQUARE_BRACKET) {
                 evaluateArrayAssignmentWithOperator(method, expression, leftBinExpr);
                 return;
             }
-        } 
+        }
 
         evaluateBinaryExpression(method, expression);
 
         // br to leave a copy of rvalue on the stack. see also isPopRequired()
         operandStack.dup();
-        
+
         controller.getCompileStack().pushLHS(true);
         leftExpression.visit(acg);
         controller.getCompileStack().popLHS();
     }
-    
-    private void evaluateInstanceof(BinaryExpression expression) {
+
+    private void evaluateInstanceof(final BinaryExpression expression) {
         OperandStack operandStack = controller.getOperandStack();
-        
+
         expression.getLeftExpression().visit(controller.getAcg());
         operandStack.box();
         Expression rightExp = expression.getRightExpression();
@@ -680,7 +675,7 @@ public class BinaryExpressionHelper {
         operandStack.replace(ClassHelper.boolean_TYPE);
     }
 
-    private void evaluateNotInstanceof(BinaryExpression expression) {
+    private void evaluateNotInstanceof(final BinaryExpression expression) {
         unaryExpressionHelper.writeNotExpression(
                 new NotExpression(
                         new BinaryExpression(
@@ -692,14 +687,10 @@ public class BinaryExpressionHelper {
         );
     }
 
-    public MethodCaller getIsCaseMethod() {
-        return isCaseMethod;
-    }
-
-    private void evaluatePostfixMethod(int op, String method, Expression expression, Expression orig) {
+    private void evaluatePostfixMethod(final int op, final String method, final Expression expression, final Expression orig) {
         CompileStack compileStack = controller.getCompileStack();
         final OperandStack operandStack = controller.getOperandStack();
-        
+
         // load Expressions
         VariableSlotLoader usesSubscript = loadWithSubscript(expression);
 
@@ -707,20 +698,20 @@ public class BinaryExpressionHelper {
         operandStack.dup();
         ClassNode expressionType = operandStack.getTopOperand();
         int tempIdx = compileStack.defineTemporaryVariable("postfix_" + method, expressionType, true);
-        
+
         // execute Method
-        execMethodAndStoreForSubscriptOperator(op,method,expression,usesSubscript,orig);
-        
+        execMethodAndStoreForSubscriptOperator(op, method, expression, usesSubscript, orig);
+
         // remove the result of the method call
-        operandStack.pop();        
-        
+        operandStack.pop();
+
         //reload saved value
         operandStack.load(expressionType, tempIdx);
         compileStack.removeVar(tempIdx);
-        if (usesSubscript!=null) compileStack.removeVar(usesSubscript.getIndex());
+        if (usesSubscript != null) compileStack.removeVar(usesSubscript.getIndex());
     }
 
-    public void evaluatePostfixMethod(PostfixExpression expression) {
+    public void evaluatePostfixMethod(final PostfixExpression expression) {
         int op = expression.getOperation().getType();
         switch (op) {
             case Types.PLUS_PLUS:
@@ -732,7 +723,7 @@ public class BinaryExpressionHelper {
         }
     }
 
-    public void evaluatePrefixMethod(PrefixExpression expression) {
+    public void evaluatePrefixMethod(final PrefixExpression expression) {
         int type = expression.getOperation().getType();
         switch (type) {
             case Types.PLUS_PLUS:
@@ -743,19 +734,19 @@ public class BinaryExpressionHelper {
                 break;
         }
     }
-    
-    private void evaluatePrefixMethod(int op, String method, Expression expression, Expression orig) {
+
+    private void evaluatePrefixMethod(final int op, final String method, final Expression expression, final Expression orig) {
         // load Expressions
         VariableSlotLoader usesSubscript = loadWithSubscript(expression);
-        
+
         // execute Method
         execMethodAndStoreForSubscriptOperator(op,method,expression,usesSubscript,orig);
 
         // new value is already on stack, so nothing to do here
         if (usesSubscript!=null) controller.getCompileStack().removeVar(usesSubscript.getIndex());
     }
-    
-    private VariableSlotLoader loadWithSubscript(Expression expression) {
+
+    private VariableSlotLoader loadWithSubscript(final Expression expression) {
         final OperandStack operandStack = controller.getOperandStack();
         // if we have a BinaryExpression, let us check if it is with
         // subscription
@@ -775,15 +766,15 @@ public class BinaryExpressionHelper {
                 newBe.setSourcePosition(be);
                 newBe.visit(controller.getAcg());
                 return subscriptExpression;
-            } 
-        } 
-        
+            }
+        }
+
         // normal loading of expression
         expression.visit(controller.getAcg());
         return null;
     }
-    
-    private void execMethodAndStoreForSubscriptOperator(int op, String method, Expression expression, VariableSlotLoader usesSubscript, Expression orig) {
+
+    private void execMethodAndStoreForSubscriptOperator(final int op, String method, final Expression expression, final VariableSlotLoader usesSubscript, final Expression orig) {
         final OperandStack operandStack = controller.getOperandStack();
         writePostOrPrefixMethod(op,method,expression,orig);
 
@@ -791,17 +782,17 @@ public class BinaryExpressionHelper {
         if (usesSubscript!=null) {
             CompileStack compileStack = controller.getCompileStack();
             BinaryExpression be = (BinaryExpression) expression;
-            
+
             ClassNode methodResultType = operandStack.getTopOperand();
             final int resultIdx = compileStack.defineTemporaryVariable("postfix_" + method, methodResultType, true);
             BytecodeExpression methodResultLoader = new VariableSlotLoader(methodResultType, resultIdx, operandStack);
-            
-            // execute the assignment, this will leave the right side 
+
+            // execute the assignment, this will leave the right side
             // (here the method call result) on the stack
             assignToArray(be, be.getLeftExpression(), usesSubscript, methodResultLoader, be.isSafe());
 
             compileStack.removeVar(resultIdx);
-        } 
+        }
         // here we handle a.b++ and a++
         else if (expression instanceof VariableExpression ||
             expression instanceof FieldExpression ||
@@ -815,23 +806,23 @@ public class BinaryExpressionHelper {
         // other cases don't need storing, so nothing to be done for them
     }
 
-    protected void writePostOrPrefixMethod(int op, String method, Expression expression, Expression orig) {
+    protected void writePostOrPrefixMethod(final int op, final String method, final Expression expression, final Expression orig) {
         final OperandStack operandStack = controller.getOperandStack();
         // at this point the receiver will be already on the stack.
         // in a[1]++ the method will be "++" aka "next" and the receiver a[1]
-        
+
         ClassNode BEType = controller.getTypeChooser().resolveType(expression, controller.getClassNode());
         Expression callSiteReceiverSwap = new BytecodeExpression(BEType) {
             @Override
             public void visit(MethodVisitor mv) {
-                // CallSite is normally not showing up on the 
+                // CallSite is normally not showing up on the
                 // operandStack, so we place a dummy here with same
                 // slot length.
                 operandStack.push(ClassHelper.OBJECT_TYPE);
                 // change (receiver,callsite) to (callsite,receiver)
                 operandStack.swap();
                 setType(operandStack.getTopOperand());
-                
+
                 // no need to keep any of those on the operand stack
                 // after this expression is processed, the operand stack
                 // will contain callSiteReceiverSwap.getType()
@@ -841,7 +832,7 @@ public class BinaryExpressionHelper {
         // execute method
         // this will load the callsite and the receiver normally in the wrong
         // order since the receiver is already present, but before the callsite
-        // Therefore we use callSiteReceiverSwap to correct the order. 
+        // Therefore we use callSiteReceiverSwap to correct the order.
         // After this call the JVM operand stack will contain the result of
         // the method call... usually simply Object in operandStack
         controller.getCallSiteWriter().makeCallSite(
@@ -849,37 +840,37 @@ public class BinaryExpressionHelper {
                 method,
                 MethodCallExpression.NO_ARGUMENTS,
                 false, false, false, false);
-        // now rhs is completely done and we need only to store. In a[1]++ this 
+        // now rhs is completely done and we need only to store. In a[1]++ this
         // would be a.getAt(1).next() for the rhs, "lhs" code is a.putAt(1, rhs)
-         
+
     }
-    
-    private void evaluateElvisOperatorExpression(ElvisOperatorExpression expression) {
+
+    private void evaluateElvisOperatorExpression(final ElvisOperatorExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
         CompileStack compileStack = controller.getCompileStack();
         OperandStack operandStack = controller.getOperandStack();
         TypeChooser typeChooser = controller.getTypeChooser();
-        
+
         Expression boolPart = expression.getBooleanExpression().getExpression();
         Expression falsePart = expression.getFalseExpression();
-        
+
         ClassNode truePartType = typeChooser.resolveType(boolPart, controller.getClassNode());
         ClassNode falsePartType = typeChooser.resolveType(falsePart, controller.getClassNode());
         ClassNode common = WideningCategories.lowestUpperBound(truePartType, falsePartType);
-        
-        // x?:y is equal to x?x:y, which evals to 
+
+        // x?:y is equal to x?x:y, which evals to
         //      var t=x; boolean(t)?t:y
-        // first we load x, dup it, convert the dupped to boolean, then 
+        // first we load x, dup it, convert the dupped to boolean, then
         // jump depending on the value. For true we are done, for false we
-        // have to load y, thus we first remove x and then load y. 
+        // have to load y, thus we first remove x and then load y.
         // But since x and y may have different stack lengths, this cannot work
         // Thus we have to have to do the following:
-        // Be X the type of x, Y the type of y and S the common supertype of 
-        // X and Y, then we have to see x?:y as  
+        // Be X the type of x, Y the type of y and S the common supertype of
+        // X and Y, then we have to see x?:y as
         //      var t=x;boolean(t)?S(t):S(y)
-        // so we load x, dup it, store the value in a local variable (t), then 
-        // do boolean conversion. In the true part load t and cast it to S, 
-        // in the false part load y and cast y to S 
+        // so we load x, dup it, store the value in a local variable (t), then
+        // do boolean conversion. In the true part load t and cast it to S,
+        // in the false part load y and cast y to S
 
         // load x, dup it, store one in $t and cast the remaining one to boolean
         int mark = operandStack.getStackLength();
@@ -890,69 +881,69 @@ public class BinaryExpressionHelper {
         }
         int retValueId = compileStack.defineTemporaryVariable("$t", truePartType, true);
         operandStack.castToBool(mark,true);
-        
+
         Label l0 = operandStack.jump(IFEQ);
         // true part: load $t and cast to S
         operandStack.load(truePartType, retValueId);
         operandStack.doGroovyCast(common);
         Label l1 = new Label();
         mv.visitJumpInsn(GOTO, l1);
-        
+
         // false part: load false expression and cast to S
         mv.visitLabel(l0);
-        falsePart.visit(controller.getAcg());        
+        falsePart.visit(controller.getAcg());
         operandStack.doGroovyCast(common);
-        
+
         // finish and cleanup
         mv.visitLabel(l1);
         compileStack.removeVar(retValueId);
-        controller.getOperandStack().replace(common, 2);        
-        
+        controller.getOperandStack().replace(common, 2);
+
     }
 
-    private void evaluateNormalTernary(TernaryExpression expression) {
+    private void evaluateNormalTernary(final TernaryExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
         OperandStack operandStack = controller.getOperandStack();
         TypeChooser typeChooser = controller.getTypeChooser();
-        
+
         Expression boolPart = expression.getBooleanExpression();
         Expression truePart = expression.getTrueExpression();
         Expression falsePart = expression.getFalseExpression();
-        
+
         ClassNode truePartType = typeChooser.resolveType(truePart, controller.getClassNode());
         ClassNode falsePartType = typeChooser.resolveType(falsePart, controller.getClassNode());
         ClassNode common = WideningCategories.lowestUpperBound(truePartType, falsePartType);
 
-        // we compile b?x:y as 
+        // we compile b?x:y as
         //      boolean(b)?S(x):S(y), S = common super type of x,y
-        // so we load b, do boolean conversion. 
-        // In the true part load x and cast it to S, 
-        // in the false part load y and cast y to S 
+        // so we load b, do boolean conversion.
+        // In the true part load x and cast it to S,
+        // in the false part load y and cast y to S
 
         // load b and convert to boolean
         int mark = operandStack.getStackLength();
         boolPart.visit(controller.getAcg());
         operandStack.castToBool(mark,true);
-        
+
         Label l0 = operandStack.jump(IFEQ);
         // true part: load x and cast to S
         truePart.visit(controller.getAcg());
         operandStack.doGroovyCast(common);
         Label l1 = new Label();
         mv.visitJumpInsn(GOTO, l1);
-        
+
         // false part: load y and cast to S
         mv.visitLabel(l0);
-        falsePart.visit(controller.getAcg());        
+        falsePart.visit(controller.getAcg());
         operandStack.doGroovyCast(common);
-        
+
         // finish and cleanup
         mv.visitLabel(l1);
-        controller.getOperandStack().replace(common, 2);        
-        
+        controller.getOperandStack().replace(common, 2);
+
     }
 
-    public void evaluateTernary(TernaryExpression expression) {
+    public void evaluateTernary(final TernaryExpression expression) {
         if (expression instanceof ElvisOperatorExpression) {
             evaluateElvisOperatorExpression((ElvisOperatorExpression) expression);
         } else {
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java
index 640964f..d00bab2 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java
@@ -19,6 +19,7 @@
 
 package org.codehaus.groovy.classgen.asm;
 
+import org.apache.groovy.util.Maps;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.DynamicVariable;
@@ -30,7 +31,6 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.runtime.BytecodeInterface8;
 
-import java.util.HashMap;
 import java.util.Map;
 
 import static org.codehaus.groovy.ast.ClassHelper.boolean_TYPE;
@@ -55,13 +55,13 @@ import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED;
 
 /**
  * This class is for internal use only!
- * This class will dispatch to the right type adapters according to the 
+ * This class will dispatch to the right type adapters according to the
  * kind of binary expression that is provided.
  */
 public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper {
-    
+
     private static class BinaryCharExpressionHelper extends BinaryIntExpressionHelper {
-        public BinaryCharExpressionHelper(WriterController wc) {
+        public BinaryCharExpressionHelper(final WriterController wc) {
             super(wc, charArraySet, charArrayGet);
         }
         private static final MethodCaller
@@ -69,9 +69,9 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
             charArraySet = MethodCaller.newStatic(BytecodeInterface8.class, "cArraySet");
         @Override protected ClassNode getArrayGetResultType() { return ClassHelper.char_TYPE; }
     }
-    
+
     private static class BinaryByteExpressionHelper extends BinaryIntExpressionHelper {
-        public BinaryByteExpressionHelper(WriterController wc) {
+        public BinaryByteExpressionHelper(final WriterController wc) {
             super(wc, byteArraySet, byteArrayGet);
         }
         private static final MethodCaller
@@ -79,9 +79,9 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
             byteArraySet = MethodCaller.newStatic(BytecodeInterface8.class, "bArraySet");
         @Override protected ClassNode getArrayGetResultType() { return ClassHelper.byte_TYPE; }
     }
-    
+
     private static class BinaryShortExpressionHelper extends BinaryIntExpressionHelper {
-        public BinaryShortExpressionHelper(WriterController wc) {
+        public BinaryShortExpressionHelper(final WriterController wc) {
             super(wc, shortArraySet, shortArrayGet);
         }
         private static final MethodCaller
@@ -89,110 +89,113 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
             shortArraySet = MethodCaller.newStatic(BytecodeInterface8.class, "sArraySet");
         @Override protected ClassNode getArrayGetResultType() { return ClassHelper.short_TYPE; }
     }
-    
+
     protected BinaryExpressionWriter[] binExpWriter = initializeDelegateHelpers();
 
     protected BinaryExpressionWriter[] initializeDelegateHelpers() {
         return new BinaryExpressionWriter[]{
-                /* 0: dummy  */ new BinaryObjectExpressionHelper(getController()),
-                /* 1: int    */ new BinaryIntExpressionHelper(getController()),
-                /* 2: long   */ new BinaryLongExpressionHelper(getController()),
-                /* 3: double */ new BinaryDoubleExpressionHelper(getController()),
-                /* 4: char   */ new BinaryCharExpressionHelper(getController()),
-                /* 5: byte   */ new BinaryByteExpressionHelper(getController()),
-                /* 6: short  */ new BinaryShortExpressionHelper(getController()),
-                /* 7: float  */ new BinaryFloatExpressionHelper(getController()),
-                /* 8: bool   */ new BinaryBooleanExpressionHelper(getController()),
+                /* 0: dummy  */ new BinaryObjectExpressionHelper(controller),
+                /* 1: int    */ new BinaryIntExpressionHelper(controller),
+                /* 2: long   */ new BinaryLongExpressionHelper(controller),
+                /* 3: double */ new BinaryDoubleExpressionHelper(controller),
+                /* 4: char   */ new BinaryCharExpressionHelper(controller),
+                /* 5: byte   */ new BinaryByteExpressionHelper(controller),
+                /* 6: short  */ new BinaryShortExpressionHelper(controller),
+                /* 7: float  */ new BinaryFloatExpressionHelper(controller),
+                /* 8: bool   */ new BinaryBooleanExpressionHelper(controller),
         };
     }
 
-    public static final Map<ClassNode,Integer> typeMap = new HashMap<ClassNode,Integer>(14);
-    static {
-        typeMap.put(int_TYPE,       1); typeMap.put(long_TYPE,          2);
-        typeMap.put(double_TYPE,    3); typeMap.put(char_TYPE,          4);
-        typeMap.put(byte_TYPE,      5); typeMap.put(short_TYPE,         6);
-        typeMap.put(float_TYPE,     7); typeMap.put(boolean_TYPE,       8);
-    }
+    public static final Map<ClassNode,Integer> typeMap = Maps.of(
+        int_TYPE,     1,
+        long_TYPE,    2,
+        double_TYPE,  3,
+        char_TYPE,    4,
+        byte_TYPE,    5,
+        short_TYPE,   6,
+        float_TYPE,   7,
+        boolean_TYPE, 8
+    );
     public static final String[] typeMapKeyNames = {"dummy", "int", "long", "double", "char", "byte", "short", "float", "boolean"};
 
-    public BinaryExpressionMultiTypeDispatcher(WriterController wc) {
+    public BinaryExpressionMultiTypeDispatcher(final WriterController wc) {
         super(wc);
     }
 
-    private static int getOperandConversionType(ClassNode leftType, ClassNode rightType) {
+    private static int getOperandConversionType(final ClassNode leftType, final ClassNode rightType) {
         if (isIntCategory(leftType) && isIntCategory(rightType)) return 1;
         if (isLongCategory(leftType) && isLongCategory(rightType)) return 2;
         if (isBigDecCategory(leftType) && isBigDecCategory(rightType)) return 0;
         if (isDoubleCategory(leftType) && isDoubleCategory(rightType)) return 3;
         return 0;
     }
-    
-    protected int getOperandType(ClassNode type) {
+
+    protected int getOperandType(final ClassNode type) {
         Integer ret = typeMap.get(type);
-        if (ret==null) return 0;
+        if (ret == null) return 0;
         return ret;
     }
 
     @Deprecated
-    protected boolean doPrimtiveCompare(ClassNode leftType, ClassNode rightType, BinaryExpression binExp) {
+    protected boolean doPrimtiveCompare(final ClassNode leftType, final ClassNode rightType, final BinaryExpression binExp) {
         return doPrimitiveCompare(leftType, rightType, binExp);
     }
 
-    protected boolean doPrimitiveCompare(ClassNode leftType, ClassNode rightType, BinaryExpression binExp) {
+    protected boolean doPrimitiveCompare(final ClassNode leftType, final ClassNode rightType, final BinaryExpression binExp) {
         Expression leftExp = binExp.getLeftExpression();
         Expression rightExp = binExp.getRightExpression();
         int operation = binExp.getOperation().getType();
-        
+
         int operationType = getOperandConversionType(leftType,rightType);
         BinaryExpressionWriter bew = binExpWriter[operationType];
 
         if (!bew.write(operation, true)) return false;
-            
-        AsmClassGenerator acg = getController().getAcg();
-        OperandStack os = getController().getOperandStack();
+
+        AsmClassGenerator acg = controller.getAcg();
+        OperandStack os = controller.getOperandStack();
         leftExp.visit(acg);
         os.doGroovyCast(bew.getNormalOpResultType());
         rightExp.visit(acg);
         os.doGroovyCast(bew.getNormalOpResultType());
         bew.write(operation, false);
-        
+
         return true;
     }
-    
+
     @Override
-    protected void evaluateCompareExpression(final MethodCaller compareMethod, BinaryExpression binExp) {
-        ClassNode current =  getController().getClassNode();
-        TypeChooser typeChooser = getController().getTypeChooser();
-        
+    protected void evaluateCompareExpression(final MethodCaller compareMethod, final BinaryExpression binExp) {
+        ClassNode current =  controller.getClassNode();
+        TypeChooser typeChooser = controller.getTypeChooser();
+
         Expression leftExp = binExp.getLeftExpression();
         ClassNode leftType = typeChooser.resolveType(leftExp, current);
         Expression rightExp = binExp.getRightExpression();
         ClassNode rightType = typeChooser.resolveType(rightExp, current);
-        
+
         if (!doPrimitiveCompare(leftType, rightType, binExp)) {
             super.evaluateCompareExpression(compareMethod, binExp);
         }
     }
-    
+
     @Override
-    protected void evaluateBinaryExpression(final String message, BinaryExpression binExp) {
+    protected void evaluateBinaryExpression(final String message, final BinaryExpression binExp) {
         int operation = removeAssignment(binExp.getOperation().getType());
-        ClassNode current =  getController().getClassNode();
+        ClassNode current =  controller.getClassNode();
 
         Expression leftExp = binExp.getLeftExpression();
-        ClassNode leftTypeOrig = getController().getTypeChooser().resolveType(leftExp, current);
+        ClassNode leftTypeOrig = controller.getTypeChooser().resolveType(leftExp, current);
         ClassNode leftType = leftTypeOrig;
         Expression rightExp = binExp.getRightExpression();
-        ClassNode rightType = getController().getTypeChooser().resolveType(rightExp, current);
-        
-        AsmClassGenerator acg = getController().getAcg();
-        OperandStack os = getController().getOperandStack();
-        
-        if (operation==LEFT_SQUARE_BRACKET) {
+        ClassNode rightType = controller.getTypeChooser().resolveType(rightExp, current);
+
+        AsmClassGenerator acg = controller.getAcg();
+        OperandStack os = controller.getOperandStack();
+
+        if (operation == LEFT_SQUARE_BRACKET) {
             leftType = leftTypeOrig.getComponentType();
             int operationType = getOperandType(leftType);
             BinaryExpressionWriter bew = binExpWriter[operationType];
-            if (    leftTypeOrig.isArray() && isIntCastableType(rightExp) && 
+            if (    leftTypeOrig.isArray() && isIntCastableType(rightExp) &&
                     bew.arrayGet(operation, true) &&
                     !binExp.isSafe())
             {
@@ -205,8 +208,8 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
             } else {
                 super.evaluateBinaryExpression(message, binExp);
             }
-        } else if (operation == DIVIDE) { 
-            int operationType = getOperandType(getController().getTypeChooser().resolveType(binExp, current));
+        } else if (operation == DIVIDE) {
+            int operationType = getOperandType(controller.getTypeChooser().resolveType(binExp, current));
             BinaryExpressionWriter bew = binExpWriter[operationType];
             if (bew.writeDivision(true)) {
                 leftExp.visit(acg);
@@ -220,9 +223,9 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
         } else {
             int operationType = getOperandConversionType(leftType,rightType);
             BinaryExpressionWriter bew = binExpWriter[operationType];
-            
+
             if ( isShiftOperation(operation) && isIntCastableType(rightExp) &&
-                 bew.write(operation, true)) 
+                 bew.write(operation, true))
             {
                 leftExp.visit(acg);
                 os.doGroovyCast(bew.getNormalOpResultType());
@@ -240,62 +243,60 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
             }
         }
     }
-    
-    private boolean isIntCastableType(Expression rightExp) {
-        ClassNode type = getController().getTypeChooser().resolveType(rightExp, getController().getClassNode());
+
+    private boolean isIntCastableType(final Expression rightExp) {
+        ClassNode type = controller.getTypeChooser().resolveType(rightExp, controller.getClassNode());
         return isNumberCategory(type);
     }
 
-    private static boolean isShiftOperation(int operation) {
-        return  operation==LEFT_SHIFT   || 
-                operation==RIGHT_SHIFT  ||
-                operation==RIGHT_SHIFT_UNSIGNED;
+    private static boolean isShiftOperation(final int operation) {
+        return operation == LEFT_SHIFT || operation == RIGHT_SHIFT || operation == RIGHT_SHIFT_UNSIGNED;
     }
 
-    private static boolean isAssignmentToArray(BinaryExpression binExp) {
+    private static boolean isAssignmentToArray(final BinaryExpression binExp) {
         Expression leftExpression = binExp.getLeftExpression();
         if (!(leftExpression instanceof BinaryExpression)) return false;
         BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
         return leftBinExpr.getOperation().getType() == LEFT_SQUARE_BRACKET;
     }
 
-    private boolean doAssignmentToArray(BinaryExpression binExp) {
+    private boolean doAssignmentToArray(final BinaryExpression binExp) {
         if (!isAssignmentToArray(binExp)) return false;
         // we need to handle only assignment to arrays combined with an operation
         // special here. e.g x[a] += b
-        
+
         int operation = removeAssignment(binExp.getOperation().getType());
-        ClassNode current =  getController().getClassNode();
-        
+        ClassNode current =  controller.getClassNode();
+
         Expression leftExp = binExp.getLeftExpression();
-        ClassNode leftType = getController().getTypeChooser().resolveType(leftExp, current);
+        ClassNode leftType = controller.getTypeChooser().resolveType(leftExp, current);
         Expression rightExp = binExp.getRightExpression();
-        ClassNode rightType = getController().getTypeChooser().resolveType(rightExp, current);
-        
+        ClassNode rightType = controller.getTypeChooser().resolveType(rightExp, current);
+
         int operationType = getOperandType(leftType);
         BinaryExpressionWriter bew = binExpWriter[operationType];
-        
+
         boolean simulationSuccess = bew.arrayGet(LEFT_SQUARE_BRACKET, true);
         simulationSuccess = simulationSuccess && bew.write(operation, true);
         simulationSuccess = simulationSuccess && bew.arraySet(true);
         if (!simulationSuccess) return false;
-        
-        AsmClassGenerator acg = getController().getAcg();
-        OperandStack operandStack = getController().getOperandStack();
-        CompileStack compileStack = getController().getCompileStack();
-               
+
+        AsmClassGenerator acg = controller.getAcg();
+        OperandStack operandStack = controller.getOperandStack();
+        CompileStack compileStack = controller.getCompileStack();
+
         // for x[a] += b we have the structure:
         //   x = left(left(binExp))), b = right(binExp), a = right(left(binExp)))
-        // for array set we need these values on stack: array, index, right 
+        // for array set we need these values on stack: array, index, right
         // for array get we need these values on stack: array, index
         // to eval the expression we need x[a] = x[a]+b
-        // -> arraySet(x,a, x[a]+b) 
+        // -> arraySet(x,a, x[a]+b)
         // -> arraySet(x,a, arrayGet(x,a,b))
         // --> x,a, x,a, b as operands
         // --> load x, load a, DUP2, call arrayGet, load b, call operation,call arraySet
         // since we cannot DUP2 here easily we will save the subscript and DUP x
         // --> sub=a, load x, DUP, load sub, call arrayGet, load b, call operation, load sub, call arraySet
-        
+
         BinaryExpression arrayWithSubscript = (BinaryExpression) leftExp;
         Expression subscript = arrayWithSubscript.getRightExpression();
 
@@ -303,25 +304,25 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
         subscript.visit(acg);
         operandStack.doGroovyCast(int_TYPE);
         int subscriptValueId = compileStack.defineTemporaryVariable("$sub", ClassHelper.int_TYPE, true);
-        
-        // load array: load x and DUP [load sub, call arrayGet, load b, call operation, load sub, call arraySet] 
+
+        // load array: load x and DUP [load sub, call arrayGet, load b, call operation, load sub, call arraySet]
         arrayWithSubscript.getLeftExpression().visit(acg);
         operandStack.doGroovyCast(leftType.makeArray());
         operandStack.dup();
-        
+
         // array get: load sub, call arrayGet [load b, call operation, load sub, call arraySet]
         operandStack.load(ClassHelper.int_TYPE, subscriptValueId);
         bew.arrayGet(LEFT_SQUARE_BRACKET, false);
         operandStack.replace(leftType, 2);
-        
+
         // complete rhs: load b, call operation [load sub, call arraySet]
         binExp.getRightExpression().visit(acg);
         if (! (bew instanceof BinaryObjectExpressionHelper)) {
             // in primopts we convert to the left type for supported binary operations
-            operandStack.doGroovyCast(leftType);  
+            operandStack.doGroovyCast(leftType);
         }
         bew.write(operation, false);
-        
+
         // let us save that value for the return
         operandStack.dup();
         int resultValueId = compileStack.defineTemporaryVariable("$result", rightType, true);
@@ -334,21 +335,21 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
 
         // load return value
         operandStack.load(rightType, resultValueId);
-        
+
         // cleanup
         compileStack.removeVar(resultValueId);
         compileStack.removeVar(subscriptValueId);
         return true;
     }
-    
+
     @Override
-    protected void evaluateBinaryExpressionWithAssignment(String method, BinaryExpression binExp) {
+    protected void evaluateBinaryExpressionWithAssignment(final String method, final BinaryExpression binExp) {
         if (doAssignmentToArray(binExp)) return;
         if (doAssignmentToLocalVariable(method, binExp)) return;
         super.evaluateBinaryExpressionWithAssignment(method, binExp);
     }
 
-    private boolean doAssignmentToLocalVariable(String method, BinaryExpression binExp) {
+    private boolean doAssignmentToLocalVariable(final String method, final BinaryExpression binExp) {
         Expression left = binExp.getLeftExpression();
         if (left instanceof VariableExpression) {
             VariableExpression ve = (VariableExpression) left;
@@ -359,61 +360,61 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
         } else {
             return false;
         }
-        
+
         evaluateBinaryExpression(method, binExp);
-        getController().getOperandStack().dup();
-        getController().getCompileStack().pushLHS(true);
-        binExp.getLeftExpression().visit(getController().getAcg());
-        getController().getCompileStack().popLHS();
-        
+        controller.getOperandStack().dup();
+        controller.getCompileStack().pushLHS(true);
+        binExp.getLeftExpression().visit(controller.getAcg());
+        controller.getCompileStack().popLHS();
+
         return true;
     }
 
     @Override
-    protected void assignToArray(Expression orig, Expression receiver, Expression index, Expression rhsValueLoader, boolean safe) {
-        ClassNode current = getController().getClassNode();
-        ClassNode arrayType = getController().getTypeChooser().resolveType(receiver, current);
+    protected void assignToArray(final Expression orig, final Expression receiver, final Expression index, final Expression rhsValueLoader, final boolean safe) {
+        ClassNode current = controller.getClassNode();
+        ClassNode arrayType = controller.getTypeChooser().resolveType(receiver, current);
         ClassNode arrayComponentType = arrayType.getComponentType();
         int operationType = getOperandType(arrayComponentType);
         BinaryExpressionWriter bew = binExpWriter[operationType];
-        AsmClassGenerator acg = getController().getAcg();
-        
+        AsmClassGenerator acg = controller.getAcg();
+
         if (bew.arraySet(true) && arrayType.isArray() && !safe) {
-            OperandStack operandStack   =   getController().getOperandStack();
-            
+            OperandStack operandStack   =   controller.getOperandStack();
+
             // load the array
             receiver.visit(acg);
             operandStack.doGroovyCast(arrayType);
-            
+
             // load index
             index.visit(acg);
             operandStack.doGroovyCast(int_TYPE);
-            
+
             // load rhs
             rhsValueLoader.visit(acg);
             operandStack.doGroovyCast(arrayComponentType);
-            
+
             // store value in array
             bew.arraySet(false);
-            
+
             // load return value && correct operand stack stack
             operandStack.remove(3);
             rhsValueLoader.visit(acg);
-        } else {        
+        } else {
             super.assignToArray(orig, receiver, index, rhsValueLoader, safe);
         }
     }
-    
+
     @Override
-    protected void writePostOrPrefixMethod(int op, String method, Expression expression, Expression orig) {
-        ClassNode type = getController().getTypeChooser().resolveType(orig, getController().getClassNode());
+    protected void writePostOrPrefixMethod(final int op, final String method, final Expression expression, final Expression orig) {
+        ClassNode type = controller.getTypeChooser().resolveType(orig, controller.getClassNode());
         int operationType = getOperandType(type);
         BinaryExpressionWriter bew = binExpWriter[operationType];
-        if (bew.writePostOrPrefixMethod(op,true)) {
-            OperandStack operandStack   =   getController().getOperandStack();
+        if (bew.writePostOrPrefixMethod(op, true)) {
+            OperandStack operandStack = controller.getOperandStack();
             // at this point the receiver will be already on the stack
             operandStack.doGroovyCast(type);
-            bew.writePostOrPrefixMethod(op,false);
+            bew.writePostOrPrefixMethod(op, false);
             operandStack.replace(bew.getNormalOpResultType());
         } else {
             super.writePostOrPrefixMethod(op, method, expression, orig);
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
index d8c6166..d97ba23 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
@@ -24,14 +24,9 @@ import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.PropertyNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.AttributeExpression;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.CastExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
-import org.codehaus.groovy.ast.expr.DeclarationExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.LambdaExpression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
@@ -42,20 +37,18 @@ import org.codehaus.groovy.ast.stmt.EmptyStatement;
 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.ast.stmt.ForStatement;
 import org.codehaus.groovy.ast.tools.WideningCategories;
+import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.asm.BinaryExpressionMultiTypeDispatcher;
 import org.codehaus.groovy.classgen.asm.BinaryExpressionWriter;
 import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 import org.codehaus.groovy.classgen.asm.CompileStack;
 import org.codehaus.groovy.classgen.asm.OperandStack;
-import org.codehaus.groovy.classgen.asm.TypeChooser;
 import org.codehaus.groovy.classgen.asm.VariableSlotLoader;
 import org.codehaus.groovy.classgen.asm.WriterController;
-import org.codehaus.groovy.syntax.Token;
 import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
 import org.codehaus.groovy.transform.sc.StaticCompilationVisitor;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
-import org.codehaus.groovy.transform.stc.StaticTypesMarker;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
@@ -71,9 +64,22 @@ import static org.codehaus.groovy.ast.ClassHelper.char_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.double_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.float_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 import static org.codehaus.groovy.transform.sc.StaticCompilationVisitor.ARRAYLIST_ADD_METHOD;
 import static org.codehaus.groovy.transform.sc.StaticCompilationVisitor.ARRAYLIST_CLASSNODE;
 import static org.codehaus.groovy.transform.sc.StaticCompilationVisitor.ARRAYLIST_CONSTRUCTOR;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_FUNCTIONAL_INTERFACE_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE;
 
@@ -83,33 +89,27 @@ import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE;
  */
 public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpressionMultiTypeDispatcher implements Opcodes {
 
-    private final AtomicInteger labelCounter = new AtomicInteger();
     private static final MethodNode CLOSURE_GETTHISOBJECT_METHOD = CLOSURE_TYPE.getMethod("getThisObject", Parameter.EMPTY_ARRAY);
 
+    private final AtomicInteger labelCounter = new AtomicInteger();
 
-    public StaticTypesBinaryExpressionMultiTypeDispatcher(WriterController wc) {
+    public StaticTypesBinaryExpressionMultiTypeDispatcher(final WriterController wc) {
         super(wc);
     }
 
     @Override
-    protected void writePostOrPrefixMethod(int op, String method, Expression expression, Expression orig) {
-        MethodNode mn = orig.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
-        WriterController controller = getController();
-        OperandStack operandStack = controller.getOperandStack();
-        if (mn!=null) {
-            operandStack.pop();
-            MethodCallExpression call = new MethodCallExpression(
-                    expression,
-                    method,
-                    ArgumentListExpression.EMPTY_ARGUMENTS
-            );
+    protected void writePostOrPrefixMethod(final int op, final String method, final Expression expression, final Expression orig) {
+        MethodNode mn = orig.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
+        if (mn != null) {
+            controller.getOperandStack().pop();
+            MethodCallExpression call = callX(expression, method);
             call.setMethodTarget(mn);
             call.visit(controller.getAcg());
             return;
         }
 
-        ClassNode top = operandStack.getTopOperand();
-        if (ClassHelper.isPrimitiveType(top) && (ClassHelper.isNumberType(top)||char_TYPE.equals(top))) {
+        ClassNode top = controller.getOperandStack().getTopOperand();
+        if (ClassHelper.isPrimitiveType(top) && (ClassHelper.isNumberType(top) || char_TYPE.equals(top))) {
             MethodVisitor mv = controller.getMethodVisitor();
             visitInsnByType(top, mv, ICONST_1, LCONST_1, FCONST_1, DCONST_1);
             if ("next".equals(method)) {
@@ -119,10 +119,11 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
             }
             return;
         }
+
         super.writePostOrPrefixMethod(op, method, expression, orig);
     }
 
-    private static void visitInsnByType(ClassNode top, MethodVisitor mv, int iInsn, int lInsn, int fInsn, int dInsn) {
+    private static void visitInsnByType(final ClassNode top, final MethodVisitor mv, final int iInsn, final int lInsn, final int fInsn, final int dInsn) {
         if (WideningCategories.isIntCategory(top) || char_TYPE.equals(top)) {
             mv.visitInsn(iInsn);
         } else if (long_TYPE.equals(top)) {
@@ -147,7 +148,9 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
                         pexp.isSafe(),
                         pexp.isSpreadSafe(),
                         pexp.isImplicitThis(),
-                        pexp instanceof AttributeExpression)) return;
+                        pexp instanceof AttributeExpression)) {
+                    return;
+                }
             }
         } else {
             Expression rightExpression = expression.getRightExpression();
@@ -155,7 +158,7 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
                 rightExpression.putNodeMetaData(INFERRED_FUNCTIONAL_INTERFACE_TYPE, leftExpression.getNodeMetaData(INFERRED_TYPE));
             }
         }
-        // GROOVY-5620: Spread safe/Null safe operator on LHS is not supported
+        // GROOVY-5620: spread-safe operator on LHS is not supported
         if (leftExpression instanceof PropertyExpression
                 && ((PropertyExpression) leftExpression).isSpreadSafe()
                 && StaticTypeCheckingSupport.isAssignment(expression.getOperation().getType())) {
@@ -166,91 +169,68 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
         super.evaluateEqual(expression, defineVariable);
     }
 
-    private void transformSpreadOnLHS(BinaryExpression origin) {
-        PropertyExpression spreadExpression = (PropertyExpression) origin.getLeftExpression();
-        Expression value = origin.getRightExpression();
-        WriterController controller = getController();
-        MethodVisitor mv = controller.getMethodVisitor();
+    private void transformSpreadOnLHS(final BinaryExpression expression) {
+        PropertyExpression spreadExpression = (PropertyExpression) expression.getLeftExpression();
+        Expression receiver = spreadExpression.getObjectExpression();
+
+        int counter = labelCounter.incrementAndGet();
         CompileStack compileStack = controller.getCompileStack();
-        TypeChooser typeChooser = controller.getTypeChooser();
         OperandStack operandStack = controller.getOperandStack();
-        ClassNode classNode = controller.getClassNode();
-        int counter = labelCounter.incrementAndGet();
-        Expression receiver = spreadExpression.getObjectExpression();
 
         // create an empty arraylist
-        VariableExpression result = new VariableExpression(
-                this.getClass().getSimpleName()+"$spreadresult" + counter,
-                ARRAYLIST_CLASSNODE
-        );
-        ConstructorCallExpression cce = new ConstructorCallExpression(ARRAYLIST_CLASSNODE, ArgumentListExpression.EMPTY_ARGUMENTS);
-        cce.setNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, ARRAYLIST_CONSTRUCTOR);
-        DeclarationExpression declr = new DeclarationExpression(
-                result,
-                Token.newSymbol("=", spreadExpression.getLineNumber(), spreadExpression.getColumnNumber()),
-                cce
-        );
-        declr.visit(controller.getAcg());
+        VariableExpression result = varX(this.getClass().getSimpleName() + "$spreadresult" + counter, ARRAYLIST_CLASSNODE);
+        ConstructorCallExpression newArrayList = ctorX(ARRAYLIST_CLASSNODE);
+        newArrayList.setNodeMetaData(DIRECT_METHOD_CALL_TARGET, ARRAYLIST_CONSTRUCTOR);
+        Expression decl = ((ExpressionStatement) declS(result, newArrayList)).getExpression();
+        decl.visit(controller.getAcg());
         // if (receiver != null)
         receiver.visit(controller.getAcg());
         Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
+        MethodVisitor mv = controller.getMethodVisitor();
         mv.visitJumpInsn(IFNULL, ifnull);
         operandStack.remove(1); // receiver consumed by if()
         Label nonull = compileStack.createLocalLabel("nonull_" + counter);
         mv.visitLabel(nonull);
-        ClassNode componentType = StaticTypeCheckingVisitor.inferLoopElementType(typeChooser.resolveType(receiver, classNode));
+        ClassNode componentType = StaticTypeCheckingVisitor.inferLoopElementType(
+                controller.getTypeChooser().resolveType(receiver, controller.getClassNode()));
         Parameter iterator = new Parameter(componentType, "for$it$" + counter);
-        VariableExpression iteratorAsVar = new VariableExpression(iterator);
-        PropertyExpression pexp = spreadExpression instanceof AttributeExpression ?
-                new AttributeExpression(iteratorAsVar, spreadExpression.getProperty(), true):
-                new PropertyExpression(iteratorAsVar, spreadExpression.getProperty(), true);
+        VariableExpression iteratorAsVar = varX(iterator);
+        PropertyExpression pexp = spreadExpression instanceof AttributeExpression
+            ? new AttributeExpression(iteratorAsVar, spreadExpression.getProperty(), true)
+            : new PropertyExpression(iteratorAsVar, spreadExpression.getProperty(), true);
         pexp.setImplicitThis(spreadExpression.isImplicitThis());
         pexp.setSourcePosition(spreadExpression);
-        BinaryExpression assignment = new BinaryExpression(
-                pexp,
-                origin.getOperation(),
-                value
-        );
-        MethodCallExpression add = new MethodCallExpression(
-                result,
-                "add",
-                assignment
-        );
+        BinaryExpression assignment = binX(pexp, expression.getOperation(), expression.getRightExpression());
+        MethodCallExpression add = callX(result, "add", assignment);
         add.setMethodTarget(ARRAYLIST_ADD_METHOD);
         // for (e in receiver) { result.add(e?.method(arguments) }
         ForStatement stmt = new ForStatement(
                 iterator,
                 receiver,
-                new ExpressionStatement(add)
+                stmt(add)
         );
         stmt.visit(controller.getAcg());
         // else { empty list }
         mv.visitLabel(ifnull);
-
         // end of if/else
         // return result list
         result.visit(controller.getAcg());
-
     }
 
     private boolean makeSetProperty(final Expression receiver, final Expression message, final Expression arguments, final boolean safe, final boolean spreadSafe, final boolean implicitThis, final boolean isAttribute) {
-        WriterController controller = getController();
-        TypeChooser typeChooser = controller.getTypeChooser();
-        ClassNode receiverType = typeChooser.resolveType(receiver, controller.getClassNode());
+        ClassNode receiverType = controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
         String property = message.getText();
-        boolean isThisExpression = receiver instanceof VariableExpression && ((VariableExpression) receiver).isThisExpression();
-        if (isAttribute
-                || (isThisExpression &&
-                    receiverType.getDeclaredField(property)!=null)) {
+        boolean isThisExpression = AsmClassGenerator.isThisExpression(receiver);
+        if (isAttribute || (isThisExpression && receiverType.getDeclaredField(property) != null)) {
             ClassNode current = receiverType;
             FieldNode fn = null;
-            while (fn==null && current!=null) {
+            while (fn == null && current != null) {
                 fn = current.getDeclaredField(property);
-                if (fn==null){
+                if (fn == null) {
                     current = current.getSuperClass();
                 }
             }
-            if (fn!=null && receiverType!=current && !fn.isPublic()) {
+            if (fn != null && receiverType != current && !fn.isPublic()) {
                 // check that direct access is allowed
                 if (!fn.isProtected()) {
                     return false;
@@ -258,33 +238,32 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
                 if (!Objects.equals(receiverType.getPackageName(), current.getPackageName())) {
                     return false;
                 }
-                OperandStack operandStack = controller.getOperandStack();
-                MethodVisitor mv = controller.getMethodVisitor();
                 if (!fn.isStatic()) {
                     receiver.visit(controller.getAcg());
                 }
                 arguments.visit(controller.getAcg());
+                OperandStack operandStack = controller.getOperandStack();
                 operandStack.doGroovyCast(fn.getOriginType());
+                MethodVisitor mv = controller.getMethodVisitor();
                 mv.visitFieldInsn(fn.isStatic() ? PUTSTATIC : PUTFIELD,
                         BytecodeHelper.getClassInternalName(fn.getOwner()),
                         property,
                         BytecodeHelper.getTypeDescription(fn.getOriginType()));
-                operandStack.remove(fn.isStatic()?1:2);
+                operandStack.remove(fn.isStatic() ? 1 : 2);
                 return true;
             }
         }
         if (!isAttribute) {
             String setter = "set" + capitalize(property);
             MethodNode setterMethod = receiverType.getSetterMethod(setter, false);
-            ClassNode declaringClass = setterMethod!=null?setterMethod.getDeclaringClass():null;
-            if (isThisExpression && declaringClass!=null && declaringClass.equals(controller.getClassNode())) {
+            ClassNode declaringClass = setterMethod != null ? setterMethod.getDeclaringClass() : null;
+            if (isThisExpression && declaringClass != null && declaringClass.equals(controller.getClassNode())) {
                 // this.x = ... shouldn't use a setter if in the same class
                 setterMethod = null;
             } else if (setterMethod == null) {
                 PropertyNode propertyNode = receiverType.getProperty(property);
                 if (propertyNode != null) {
-                    int mods = propertyNode.getModifiers();
-                    if (!Modifier.isFinal(mods)) {
+                    if (!Modifier.isFinal(propertyNode.getModifiers())) {
                         setterMethod = new MethodNode(
                                 setter,
                                 ACC_PUBLIC,
@@ -314,54 +293,46 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
             if (isThisExpression && !controller.isInGeneratedFunction()) {
                 receiverType = controller.getClassNode();
             }
-            if (makeSetPrivateFieldWithBridgeMethod(receiver, receiverType, property, arguments, safe, spreadSafe, implicitThis)) return true;
+            if (makeSetPrivateFieldWithBridgeMethod(receiver, receiverType, property, arguments, safe, spreadSafe, implicitThis)) {
+                return true;
+            }
         }
         return false;
     }
 
-    @SuppressWarnings("unchecked")
     private boolean makeSetPrivateFieldWithBridgeMethod(final Expression receiver, final ClassNode receiverType, final String fieldName, final Expression arguments, final boolean safe, final boolean spreadSafe, final boolean implicitThis) {
-        WriterController controller = getController();
         FieldNode field = receiverType.getField(fieldName);
         ClassNode outerClass = receiverType.getOuterClass();
         if (field == null && implicitThis && outerClass != null && !receiverType.isStaticClass()) {
             Expression pexp;
             if (controller.isInGeneratedFunction()) {
-                MethodCallExpression mce = new MethodCallExpression(
-                    new VariableExpression("this"),
-                    "getThisObject",
-                    ArgumentListExpression.EMPTY_ARGUMENTS
-                );
-                mce.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, controller.getOutermostClass());
+                MethodCallExpression mce = callThisX("getThisObject");
                 mce.setImplicitThis(true);
                 mce.setMethodTarget(CLOSURE_GETTHISOBJECT_METHOD);
-                pexp = new CastExpression(controller.getOutermostClass(),mce);
+                mce.putNodeMetaData(INFERRED_TYPE, controller.getOutermostClass());
+                pexp = castX(controller.getOutermostClass(), mce);
             } else {
-                pexp = new PropertyExpression(
-                    new ClassExpression(outerClass),
-                    "this"
-                );
-                ((PropertyExpression)pexp).setImplicitThis(true);
+                pexp = propX(classX(outerClass), "this");
+                ((PropertyExpression) pexp).setImplicitThis(true);
             }
-            pexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, outerClass);
+            pexp.putNodeMetaData(INFERRED_TYPE, outerClass);
             pexp.setSourcePosition(receiver);
             return makeSetPrivateFieldWithBridgeMethod(pexp, outerClass, fieldName, arguments, safe, spreadSafe, true);
         }
         ClassNode classNode = controller.getClassNode();
-        if (field != null && Modifier.isPrivate(field.getModifiers())
-            && (StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(receiverType, classNode) || StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(classNode,receiverType))
-            && !receiverType.equals(classNode)) {
+        if (field != null && field.isPrivate() && !receiverType.equals(classNode)
+                && (StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(receiverType, classNode)
+                    || StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(classNode,receiverType))) {
             Map<String, MethodNode> mutators = receiverType.redirect().getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_FIELDS_MUTATORS);
             if (mutators != null) {
                 MethodNode methodNode = mutators.get(fieldName);
                 if (methodNode != null) {
-                    MethodCallExpression mce = new MethodCallExpression(receiver, methodNode.getName(),
-                        new ArgumentListExpression(field.isStatic()?new ConstantExpression(null):receiver, arguments));
-                        mce.setMethodTarget(methodNode);
-                        mce.setSafe(safe);
-                        mce.setSpreadSafe(spreadSafe);
-                    mce.setImplicitThis(implicitThis);
-                    mce.visit(controller.getAcg());
+                    MethodCallExpression call = callX(receiver, methodNode.getName(), args(field.isStatic() ? nullX() : receiver, arguments));
+                    call.setImplicitThis(implicitThis);
+                    call.setMethodTarget(methodNode);
+                    call.setSafe(safe);
+                    call.setSpreadSafe(spreadSafe);
+                    call.visit(controller.getAcg());
                     return true;
                 }
             }
@@ -370,50 +341,39 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
     }
 
     @Override
-    protected void assignToArray(Expression parent, Expression receiver, Expression index, Expression rhsValueLoader, boolean safe) {
-        ClassNode current = getController().getClassNode();
-        ClassNode arrayType = getController().getTypeChooser().resolveType(receiver, current);
-        ClassNode arrayComponentType = arrayType.getComponentType();
-        int operationType = getOperandType(arrayComponentType);
+    protected void assignToArray(final Expression parent, final Expression receiver, final Expression index, final Expression rhsValueLoader, final boolean safe) {
+        ClassNode arrayType = controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
+        int operationType = getOperandType(arrayType.getComponentType());
         BinaryExpressionWriter bew = binExpWriter[operationType];
 
         if (bew.arraySet(true) && arrayType.isArray() && !safe) {
             super.assignToArray(parent, receiver, index, rhsValueLoader, safe);
         } else {
-            /******
-            / This code path is needed because ACG creates array access expressions
-            *******/
-
-            WriterController controller = getController();
+            /*
+             * This code path is needed because ACG creates array access expressions
+             */
             StaticTypeCheckingVisitor visitor = new StaticCompilationVisitor(controller.getSourceUnit(), controller.getClassNode());
-            // let's replace this assignment to a subscript operator with a
-            // method call
+            // GROOVY-6061
+            if (rhsValueLoader instanceof VariableSlotLoader && parent instanceof BinaryExpression) {
+                rhsValueLoader.putNodeMetaData(INFERRED_TYPE, controller.getTypeChooser().resolveType(parent, controller.getClassNode()));
+            }
+            // let's replace this assignment to a subscript operator with a method call
             // e.g. x[5] = 10
             // -> (x, [], 5), =, 10
             // -> methodCall(x, "putAt", [5, 10])
-            ArgumentListExpression ae = new ArgumentListExpression(index, rhsValueLoader);
-            if (rhsValueLoader instanceof VariableSlotLoader && parent instanceof BinaryExpression) {
-                // GROOVY-6061
-                rhsValueLoader.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE,
-                        controller.getTypeChooser().resolveType(parent, controller.getClassNode()));
-            }
-            MethodCallExpression mce = new MethodCallExpression(
-                    receiver,
-                    "putAt",
-                    ae
-            );
+            MethodCallExpression call = callX(receiver, "putAt", args(index, rhsValueLoader));
+            call.setSafe(safe);
+            call.setSourcePosition(parent);
+            visitor.visitMethodCallExpression(call);
 
-            mce.setSafe(safe);
-            mce.setSourcePosition(parent);
-            visitor.visitMethodCallExpression(mce);
             OperandStack operandStack = controller.getOperandStack();
             int height = operandStack.getStackLength();
-            mce.visit(controller.getAcg());
+            call.visit(controller.getAcg());
             operandStack.pop();
-            operandStack.remove(operandStack.getStackLength()-height);
+            operandStack.remove(operandStack.getStackLength() - height);
+
             // return value of assignment
             rhsValueLoader.visit(controller.getAcg());
         }
     }
-
 }


[groovy] 02/02: GROOVY-8707: SC: use makeSetProperty for compound assignment of property (closes #1167)

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit a6eb333ddfd81c538493076b68eb81ed104085e6
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 13 13:58:54 2020 -0600

    GROOVY-8707: SC: use makeSetProperty for compound assignment of property (closes #1167)
    
    StaticTypesBinaryExpressionMultiTypeDispatcher#evaluateEqual does this
---
 ...icTypesBinaryExpressionMultiTypeDispatcher.java | 35 ++++++++++++++++++++++
 .../groovy/transform/stc/STCAssignmentTest.groovy  | 15 ++++++++++
 .../asm/sc/AssignmentsStaticCompileTest.groovy     | 11 +++++--
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
index d97ba23..3d1661a 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
@@ -45,6 +45,8 @@ import org.codehaus.groovy.classgen.asm.CompileStack;
 import org.codehaus.groovy.classgen.asm.OperandStack;
 import org.codehaus.groovy.classgen.asm.VariableSlotLoader;
 import org.codehaus.groovy.classgen.asm.WriterController;
+import org.codehaus.groovy.syntax.Token;
+import org.codehaus.groovy.syntax.TokenUtil;
 import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
 import org.codehaus.groovy.transform.sc.StaticCompilationVisitor;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
@@ -136,6 +138,39 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
     }
 
     @Override
+    protected void evaluateBinaryExpressionWithAssignment(final String method, final BinaryExpression expression) {
+        Expression leftExpression = expression.getLeftExpression();
+        if (leftExpression instanceof PropertyExpression) {
+            PropertyExpression pexp = (PropertyExpression) leftExpression;
+
+            BinaryExpression expressionWithoutAssignment = binX(
+                    leftExpression,
+                    Token.newSymbol(
+                            TokenUtil.removeAssignment(expression.getOperation().getType()),
+                            expression.getOperation().getStartLine(),
+                            expression.getOperation().getStartColumn()
+                    ),
+                    expression.getRightExpression()
+            );
+            expressionWithoutAssignment.copyNodeMetaData(expression);
+            expressionWithoutAssignment.setSafe(expression.isSafe());
+            expressionWithoutAssignment.setSourcePosition(expression);
+
+            if (makeSetProperty(
+                    pexp.getObjectExpression(),
+                    pexp.getProperty(),
+                    expressionWithoutAssignment,
+                    pexp.isSafe(),
+                    pexp.isSpreadSafe(),
+                    pexp.isImplicitThis(),
+                    pexp instanceof AttributeExpression)) {
+                return;
+            }
+        }
+        super.evaluateBinaryExpressionWithAssignment(method, expression);
+    }
+
+    @Override
     public void evaluateEqual(final BinaryExpression expression, final boolean defineVariable) {
         Expression leftExpression = expression.getLeftExpression();
         if (!defineVariable) {
diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
index cb688cc..ace7882 100644
--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
@@ -138,6 +138,21 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    void testPlusEqualsOnProperty() {
+        assertScript '''
+            class C {
+                int i
+
+                static main(args) {
+                    def c = new C()
+                    c.i = 5
+                    c.i += 10
+                    assert c.i == 15
+                }
+            }
+        '''
+    }
+
     // GROOVY-9385
     void testPlusEqualsOnPrivateField() {
         assertScript '''
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy
index 24b2f73..538589f 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy
@@ -21,7 +21,14 @@ package org.codehaus.groovy.classgen.asm.sc
 import groovy.transform.stc.STCAssignmentTest
 
 /**
- * Unit tests for static type checking : assignments.
+ * Unit tests for static compilation : assignments.
  */
-class AssignmentsStaticCompileTest extends STCAssignmentTest implements StaticCompilationTestSupport {}
+final class AssignmentsStaticCompileTest extends STCAssignmentTest implements StaticCompilationTestSupport {
 
+    @Override // GROOVY-8707
+    void testPlusEqualsOnProperty() {
+        super.testPlusEqualsOnProperty()
+        String bytecode = astTrees['C'][1]
+        assert !bytecode.contains('ScriptBytecodeAdapter.setGroovyObjectProperty') : '"c.i += 10" should use setter, not dynamic property'
+    }
+}