minor edits
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index 5d56aa6..9b1bcf0 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -76,6 +76,9 @@
 import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.isNullConstant;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.isSuperExpression;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.isThisExpression;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.PARAMETER_TYPE;
 import static org.objectweb.asm.Opcodes.ACONST_NULL;
@@ -113,18 +116,16 @@
 
     private MethodCallExpression currentCall;
 
-    public StaticInvocationWriter(WriterController wc) {
+    public StaticInvocationWriter(final WriterController wc) {
         super(wc);
         controller = wc;
     }
 
     @Override
     protected boolean makeDirectCall(final Expression origin, final Expression receiver, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, final boolean implicitThis, final boolean containsSpreadExpression) {
-        if (origin instanceof MethodCallExpression &&
-                receiver instanceof VariableExpression &&
-                ((VariableExpression) receiver).isSuperExpression()) {
+        if (origin instanceof MethodCallExpression && isSuperExpression(receiver)) {
             ClassNode superClass = receiver.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER);
-            if (superClass!=null && !controller.getCompileStack().isLHS()) {
+            if (superClass != null && !controller.getCompileStack().isLHS()) {
                 // GROOVY-7300
                 MethodCallExpression mce = (MethodCallExpression) origin;
                 MethodNode node = superClass.getDeclaredMethod(mce.getMethodAsString(), Parameter.EMPTY_ARRAY);
@@ -190,7 +191,7 @@
     @Override
     public void writeSpecialConstructorCall(final ConstructorCallExpression call) {
         MethodNode mn = call.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
-        if (mn==null) {
+        if (mn == null) {
             super.writeSpecialConstructorCall(call);
             return;
         }
@@ -218,15 +219,14 @@
      * Attempts to make a direct method call on a bridge method, if it exists.
      */
     @Deprecated
-    protected boolean tryBridgeMethod(MethodNode target, Expression receiver, boolean implicitThis, TupleExpression args) {
+    protected boolean tryBridgeMethod(final MethodNode target, final Expression receiver, final boolean implicitThis, final TupleExpression args) {
         return tryBridgeMethod(target, receiver, implicitThis, args, null);
     }
 
     /**
      * Attempts to make a direct method call on a bridge method, if it exists.
      */
-    protected boolean tryBridgeMethod(MethodNode target, Expression receiver, boolean implicitThis,
-                                      TupleExpression args, ClassNode thisClass) {
+    protected boolean tryBridgeMethod(final MethodNode target, final Expression receiver, final boolean implicitThis, final TupleExpression args, final ClassNode thisClass) {
         ClassNode lookupClassNode;
         if (target.isProtected()) {
             lookupClassNode = controller.getClassNode();
@@ -240,7 +240,7 @@
             lookupClassNode = target.getDeclaringClass().redirect();
         }
         Map<MethodNode, MethodNode> bridges = lookupClassNode.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
-        MethodNode bridge = bridges==null?null:bridges.get(target);
+        MethodNode bridge = bridges == null ? null : bridges.get(target);
         if (bridge != null) {
             Expression fixedReceiver = receiver;
             if (implicitThis) {
@@ -271,7 +271,7 @@
 
     @Override
     protected boolean writeDirectMethodCall(final MethodNode target, final boolean implicitThis, final Expression receiver, final TupleExpression args) {
-        if (target==null) return false;
+        if (target == null) return false;
 
         if (target instanceof ExtensionMethodNode) {
             ExtensionMethodNode emn = (ExtensionMethodNode) target;
@@ -287,10 +287,7 @@
                 argumentList.add(0, new ConstantExpression(null));
             } else {
                 ClassNode classNode = controller.getClassNode();
-                boolean isThisOrSuper = false;
-                if (receiver instanceof VariableExpression) {
-                    isThisOrSuper = ((VariableExpression) receiver).isThisExpression() || ((VariableExpression) receiver).isSuperExpression();
-                }
+                boolean isThisOrSuper = isThisExpression(receiver) || isSuperExpression(receiver);
                 Expression fixedReceiver = null;
                 if (isThisOrSuper && classNode instanceof InnerClassNode && controller.isInGeneratedFunction()) {
                     ClassNode current = classNode.getOuterClass();
@@ -360,15 +357,12 @@
             if (target.isPrivate()) {
                 if (tryPrivateMethod(target, implicitThis, receiver, args, classNode)) return true;
             } else if (target.isProtected()) {
-                ClassNode node = receiver==null?ClassHelper.OBJECT_TYPE:controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
-                boolean isThisOrSuper = false;
-                if (receiver instanceof VariableExpression) {
-                    isThisOrSuper = ((VariableExpression) receiver).isThisExpression() || ((VariableExpression) receiver).isSuperExpression();
-                }
+                ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE : controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
+                boolean isThisOrSuper = isThisExpression(receiver) || isSuperExpression(receiver);
                 if (!implicitThis && !isThisOrSuper
                         && !samePackageName(node, classNode)
                         && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node,target.getDeclaringClass())) {
-                    ASTNode src = receiver==null?args:receiver;
+                    ASTNode src = receiver == null ? args : receiver;
                     controller.getSourceUnit().addError(
                             new SyntaxException("Method " + target.getName() + " is protected in " + target.getDeclaringClass().toString(false),
                                     src.getLineNumber(), src.getColumnNumber(), src.getLastLineNumber(), src.getLastColumnNumber()));
@@ -395,7 +389,7 @@
                 }
             }
             if (receiver != null) {
-                boolean callToSuper = receiver instanceof VariableExpression && ((VariableExpression) receiver).isSuperExpression();
+                boolean callToSuper = isSuperExpression(receiver);
                 if (!callToSuper) {
                     fixedReceiver = fixedReceiver == null ? receiver : fixedReceiver;
                     // in order to avoid calls to castToType, which is the dynamic behaviour, we make sure that we call CHECKCAST instead
@@ -423,23 +417,22 @@
         return false;
     }
 
-    private void checkAndAddCannotCallPrivateMethodError(MethodNode target, Expression receiver, ClassNode classNode, ClassNode declaringClass) {
+    private void checkAndAddCannotCallPrivateMethodError(final MethodNode target, final Expression receiver, final ClassNode classNode, final ClassNode declaringClass) {
         if (declaringClass != classNode) {
             controller.getSourceUnit().addError(new SyntaxException("Cannot call private method " + (target.isStatic() ? "static " : "") +
                     declaringClass.toString(false) + "#" + target.getName() + " from class " + classNode.toString(false), receiver.getLineNumber(), receiver.getColumnNumber(), receiver.getLastLineNumber(), receiver.getLastColumnNumber()));
         }
     }
 
-    protected static boolean isPrivateBridgeMethodsCallAllowed(ClassNode receiver, ClassNode caller) {
+    protected static boolean isPrivateBridgeMethodsCallAllowed(final ClassNode receiver, final ClassNode caller) {
         if (receiver == null) return false;
         if (receiver.redirect() == caller) return true;
-        if (caller.redirect() instanceof InnerClassNode) return
-                isPrivateBridgeMethodsCallAllowed(receiver, caller.redirect().getOuterClass()) ||
-                        isPrivateBridgeMethodsCallAllowed(receiver.getOuterClass(), caller);
+        if (isPrivateBridgeMethodsCallAllowed(receiver.getOuterClass(), caller)) return true;
+        if (caller.getOuterClass() != null && isPrivateBridgeMethodsCallAllowed(receiver, caller.getOuterClass())) return true;
         return false;
     }
 
-    protected void loadArguments(List<Expression> argumentList, Parameter[] para) {
+    protected void loadArguments(final List<Expression> argumentList, final Parameter[] para) {
         if (para.length == 0) return;
         ClassNode lastParaType = para[para.length - 1].getOriginType();
         AsmClassGenerator acg = controller.getAcg();
@@ -447,7 +440,7 @@
         OperandStack operandStack = controller.getOperandStack();
         int argumentListSize = argumentList.size();
         ClassNode lastArgType = argumentListSize > 0 ?
-                typeChooser.resolveType(argumentList.get(argumentListSize -1), controller.getClassNode()):null;
+                typeChooser.resolveType(argumentList.get(argumentListSize -1), controller.getClassNode()) : null;
         if (lastParaType.isArray()
                 && ((argumentListSize > para.length)
                 || ((argumentListSize == (para.length - 1)) && !lastParaType.equals(lastArgType))
@@ -460,18 +453,15 @@
             controller.setMethodVisitor(mv);
             // varg call
             // first parameters as usual
-            for (int i = 0; i < para.length - 1; i++) {
+            for (int i = 0; i < para.length - 1; i += 1) {
                 visitArgument(argumentList.get(i), para[i].getType());
             }
             // last parameters wrapped in an array
-            List<Expression> lastParams = new LinkedList<Expression>();
-            for (int i = para.length - 1; i < argumentListSize; i++) {
+            List<Expression> lastParams = new LinkedList<>();
+            for (int i = para.length - 1; i < argumentListSize; i += 1) {
                 lastParams.add(argumentList.get(i));
             }
-            ArrayExpression array = new ArrayExpression(
-                    lastParaType.getComponentType(),
-                    lastParams
-            );
+            ArrayExpression array = new ArrayExpression(lastParaType.getComponentType(), lastParams);
             array.visit(acg);
             // adjust stack length
             while (operandStack.getStackLength() < stackLen) {
@@ -488,14 +478,14 @@
             // method call with default arguments
             ClassNode classNode = controller.getClassNode();
             Expression[] arguments = new Expression[para.length];
-            for (int i = 0, j = 0; i < para.length; i++) {
+            for (int i = 0, j = 0, n = para.length; i < n; i += 1) {
                 Parameter curParam = para[i];
                 ClassNode curParamType = curParam.getType();
                 Expression curArg = j < argumentListSize ? argumentList.get(j) : null;
                 Expression initialExpression = curParam.getNodeMetaData(StaticTypesMarker.INITIAL_EXPRESSION);
                 if (initialExpression == null && curParam.hasInitialExpression())
                     initialExpression = curParam.getInitialExpression();
-                if (initialExpression == null && curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION)!=null) {
+                if (initialExpression == null && curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION) != null) {
                     initialExpression = curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION);
                 }
                 ClassNode curArgType = curArg == null ? null : typeChooser.resolveType(curArg, classNode);
@@ -505,16 +495,16 @@
                     arguments[i] = initialExpression;
                 } else {
                     arguments[i] = curArg;
-                    j++;
+                    j += 1;
                 }
             }
-            for (int i = 0; i < arguments.length; i++) {
+            for (int i = 0, n = arguments.length; i < n; i += 1) {
                 visitArgument(arguments[i], para[i].getType());
             }
         }
     }
 
-    private void visitArgument(Expression argumentExpr, ClassNode parameterType) {
+    private void visitArgument(final Expression argumentExpr, final ClassNode parameterType) {
         argumentExpr.putNodeMetaData(PARAMETER_TYPE, parameterType);
         argumentExpr.visit(controller.getAcg());
         if (!isNullConstant(argumentExpr)) {
@@ -522,11 +512,7 @@
         }
     }
 
-    private static boolean isNullConstant(final Expression expression) {
-        return (expression instanceof ConstantExpression && ((ConstantExpression) expression).getValue() == null);
-    }
-
-    private boolean compatibleArgumentType(ClassNode argumentType, ClassNode paramType) {
+    private boolean compatibleArgumentType(final ClassNode argumentType, final ClassNode paramType) {
         if (argumentType == null) return false;
         if (ClassHelper.getWrapper(argumentType).equals(ClassHelper.getWrapper(paramType))) return true;
         if (paramType.isInterface()) return argumentType.implementsInterface(paramType);
@@ -538,14 +524,13 @@
     @Override
     public void makeCall(final Expression origin, final Expression receiver, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, final boolean safe, final boolean spreadSafe, final boolean implicitThis) {
         ClassNode dynamicCallReturnType = origin.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION);
-        if (dynamicCallReturnType !=null) {
+        if (dynamicCallReturnType != null) {
             StaticTypesWriterController staticController = (StaticTypesWriterController) controller;
             if (origin instanceof MethodCallExpression) {
                 ((MethodCallExpression) origin).setMethodTarget(null);
             }
             InvocationWriter dynamicInvocationWriter = staticController.getRegularInvocationWriter();
-            dynamicInvocationWriter.
-                    makeCall(origin, receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
+            dynamicInvocationWriter.makeCall(origin, receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
             return;
         }
         if (tryImplicitReceiver(origin, message, arguments, adapter, safe, spreadSafe, implicitThis)) {
@@ -671,7 +656,7 @@
 
     boolean tryImplicitReceiver(final Expression origin, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, final boolean safe, final boolean spreadSafe, final boolean implicitThis) {
         Object implicitReceiver = origin.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
-        if (implicitThis && implicitReceiver==null && origin instanceof MethodCallExpression) {
+        if (implicitThis && implicitReceiver == null && origin instanceof MethodCallExpression) {
             implicitReceiver = ((MethodCallExpression) origin).getObjectExpression().getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
         }
         if (implicitReceiver !=null && implicitThis) {
@@ -679,7 +664,7 @@
             // GROOVY-6021
             PropertyExpression pexp = new PropertyExpression(new VariableExpression("this", CLOSURE_TYPE), propertyPath[0]);
             pexp.setImplicitThis(true);
-            for (int i=1; i<propertyPath.length;i++) {
+            for (int i = 1, n = propertyPath.length; i < n; i += 1) {
                 pexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, CLOSURE_TYPE);
                 pexp = new PropertyExpression(pexp, propertyPath[i]);
             }
@@ -745,7 +730,7 @@
 
         @Override
         public ClassNode getType() {
-            if (resolvedType!=null) {
+            if (resolvedType != null) {
                 return resolvedType;
             }
             ClassNode type;
@@ -780,7 +765,7 @@
     }
 
     @Override
-    protected boolean makeCachedCall(Expression origin, ClassExpression sender, Expression receiver, Expression message, Expression arguments, MethodCallerMultiAdapter adapter, boolean safe, boolean spreadSafe, boolean implicitThis, boolean containsSpreadExpression) {
+    protected boolean makeCachedCall(final Expression origin, final ClassExpression sender, final Expression receiver, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, final boolean safe, final boolean spreadSafe, final boolean implicitThis, final boolean containsSpreadExpression) {
         return false;
     }
 }
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
index d726ee8..f17bf7e 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
@@ -21,26 +21,22 @@
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.DeclarationExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.ListExpression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.PropertyExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
 import org.codehaus.groovy.ast.expr.TupleExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.tools.WideningCategories;
 import org.codehaus.groovy.classgen.asm.sc.StaticPropertyAccessHelper;
-import org.codehaus.groovy.classgen.asm.sc.StaticTypesTypeChooser;
 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.codehaus.groovy.syntax.Token;
 import org.codehaus.groovy.syntax.Types;
 import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression;
+import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
 import org.codehaus.groovy.transform.stc.StaticTypesMarker;
 
@@ -50,40 +46,39 @@
 import java.util.Iterator;
 import java.util.List;
 
-import static org.codehaus.groovy.syntax.Types.COMPARE_EQUAL;
-import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_EQUAL;
-import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.BINARY_EXP_TARGET;
-import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isCompareToBoolean;
+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.boolX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.isNullConstant;
 
 public class BinaryExpressionTransformer {
     private static final MethodNode COMPARE_TO_METHOD = ClassHelper.COMPARABLE_TYPE.getMethods("compareTo").get(0);
+    private static final ConstantExpression CONSTANT_MINUS_ONE = constX(-1, true);
+    private static final ConstantExpression CONSTANT_ZERO = constX(0, true);
+    private static final ConstantExpression CONSTANT_ONE = constX(1, true);
 
-    private static final ConstantExpression CONSTANT_ZERO = new ConstantExpression(0, true);
-    private static final ConstantExpression CONSTANT_MINUS_ONE = new ConstantExpression(-1, true);
-    private static final ConstantExpression CONSTANT_ONE = new ConstantExpression(1, true);
-
-    static {
-        CONSTANT_ZERO.setType(ClassHelper.int_TYPE);
-        CONSTANT_ONE.setType(ClassHelper.int_TYPE);
-        CONSTANT_MINUS_ONE.setType(ClassHelper.int_TYPE);
-    }
-
-    private int tmpVarCounter = 0;
+    private int tmpVarCounter;
 
     private final StaticCompilationTransformer staticCompilationTransformer;
 
-    public BinaryExpressionTransformer(StaticCompilationTransformer staticCompilationTransformer) {
+    public BinaryExpressionTransformer(final StaticCompilationTransformer staticCompilationTransformer) {
         this.staticCompilationTransformer = staticCompilationTransformer;
     }
 
-    Expression transformBinaryExpression(final BinaryExpression bin) {
+    public Expression transformBinaryExpression(final BinaryExpression bin) {
         if (bin instanceof DeclarationExpression) {
             Expression optimized = transformDeclarationExpression(bin);
-            if (optimized!=null) {
+            if (optimized != null) {
                 return optimized;
             }
         }
-        Object[] list = bin.getNodeMetaData(BINARY_EXP_TARGET);
+        Object[] list = bin.getNodeMetaData(StaticCompilationMetadataKeys.BINARY_EXP_TARGET);
         Token operation = bin.getOperation();
         int operationType = operation.getType();
         Expression rightExpression = bin.getRightExpression();
@@ -97,7 +92,7 @@
                         && wrapper.isDerivedFrom(ClassHelper.Number_TYPE)
                         && WideningCategories.isDoubleCategory(unwrapper)) {
                     ConstantExpression constant = (ConstantExpression) rightExpression;
-                    if (constant.getValue()!=null) {
+                    if (!constant.isNullExpression()) {
                         return optimizeConstantInitialization(bin, operation, constant, leftExpression, declarationType);
                     }
                 }
@@ -106,7 +101,9 @@
         if (operationType == Types.EQUAL && leftExpression instanceof PropertyExpression) {
             MethodNode directMCT = leftExpression.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
             if (directMCT != null) {
-                return transformPropertyAssignmentToSetterCall((PropertyExpression) leftExpression, rightExpression, directMCT);
+                PropertyExpression left = (PropertyExpression) leftExpression;
+                Expression right = staticCompilationTransformer.transform(rightExpression);
+                return transformPropertyAssignmentToSetterCall(left, right, directMCT);
             }
         }
         if (operationType == Types.COMPARE_EQUAL || operationType == Types.COMPARE_NOT_EQUAL) {
@@ -122,87 +119,82 @@
                 return compareToNullExpression;
             }
         } else if (operationType == Types.KEYWORD_IN) {
-            return convertInOperatorToTernary(bin, rightExpression, leftExpression);
+            return staticCompilationTransformer.transform(convertInOperatorToTernary(bin, rightExpression, leftExpression));
         }
         if (list != null) {
-            if (operationType == Types.COMPARE_TO) {
-                StaticTypesTypeChooser typeChooser = staticCompilationTransformer.getTypeChooser();
-                ClassNode classNode = staticCompilationTransformer.getClassNode();
-                ClassNode leftType = typeChooser.resolveType(leftExpression, classNode);
-                if (leftType.implementsInterface(ClassHelper.COMPARABLE_TYPE)) {
-                    ClassNode rightType = typeChooser.resolveType(rightExpression, classNode);
-                    if (rightType.implementsInterface(ClassHelper.COMPARABLE_TYPE)) {
-                        Expression left = staticCompilationTransformer.transform(leftExpression);
-                        Expression right = staticCompilationTransformer.transform(rightExpression);
-                        MethodCallExpression call = new MethodCallExpression(left, "compareTo", new ArgumentListExpression(right));
-                        call.setImplicitThis(false);
-                        call.setMethodTarget(COMPARE_TO_METHOD);
-                        call.setSourcePosition(bin);
-
-                        CompareIdentityExpression compareIdentity = new CompareIdentityExpression(
-                                left, right
-                        );
-                        compareIdentity.putNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE, ClassHelper.boolean_TYPE);
-                        TernaryExpression result = new TernaryExpression(
-                                new BooleanExpression(compareIdentity), // a==b
-                                CONSTANT_ZERO,
-                                new TernaryExpression(
-                                        new BooleanExpression(new CompareToNullExpression(left, true)), // a==null
-                                        CONSTANT_MINUS_ONE,
-                                        new TernaryExpression(
-                                                new BooleanExpression(new CompareToNullExpression(right, true)), // b==null
-                                                CONSTANT_ONE,
-                                                call
-                                        )
-                                )
-                        );
-                        compareIdentity.putNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE, ClassHelper.int_TYPE);
-                        result.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, ClassHelper.int_TYPE);
-                        TernaryExpression expr = (TernaryExpression) result.getFalseExpression();
-                        expr.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, ClassHelper.int_TYPE);
-                        expr.getFalseExpression().putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, ClassHelper.int_TYPE);
-                        return result;
-                    }
-                }
-            }
-            boolean isAssignment = StaticTypeCheckingSupport.isAssignment(operationType);
             MethodCallExpression call;
-            MethodNode node = (MethodNode) list[0];
-            String name = (String) list[1];
             Expression left = staticCompilationTransformer.transform(leftExpression);
             Expression right = staticCompilationTransformer.transform(rightExpression);
+
+            if (operationType == Types.COMPARE_TO
+                    && findType(leftExpression).implementsInterface(ClassHelper.COMPARABLE_TYPE)
+                    && findType(rightExpression).implementsInterface(ClassHelper.COMPARABLE_TYPE)) {
+                call = callX(left, "compareTo", args(right));
+                call.setImplicitThis(false);
+                call.setMethodTarget(COMPARE_TO_METHOD);
+                call.setSourcePosition(bin);
+
+                // right == null ? 1 : left.compareTo(right)
+                Expression expr = ternaryX(
+                        boolX(new CompareToNullExpression(right, true)),
+                        CONSTANT_ONE,
+                        call
+                );
+                expr.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, ClassHelper.int_TYPE);
+
+                // left == null ? -1 : (right == null ? 1 : left.compareTo(right))
+                expr = ternaryX(
+                        boolX(new CompareToNullExpression(left, true)),
+                        CONSTANT_MINUS_ONE,
+                        expr
+                );
+                expr.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, ClassHelper.int_TYPE);
+
+                // left === right ? 0 : (left == null ? -1 : (right == null ? 1 : left.compareTo(right)))
+                expr = ternaryX(
+                        boolX(new CompareIdentityExpression(left, right)),
+                        CONSTANT_ZERO,
+                        expr
+                );
+                expr.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, ClassHelper.int_TYPE);
+
+                return expr;
+            }
+
             BinaryExpression optimized = tryOptimizeCharComparison(left, right, bin);
-            if (optimized!=null) {
-                optimized.removeNodeMetaData(BINARY_EXP_TARGET);
+            if (optimized != null) {
+                optimized.removeNodeMetaData(StaticCompilationMetadataKeys.BINARY_EXP_TARGET);
                 return transformBinaryExpression(optimized);
             }
-            call = new MethodCallExpression(
-                    left,
-                    name,
-                    new ArgumentListExpression(right)
-            );
-            call.setImplicitThis(false);
-            call.setMethodTarget(node);
+
+            String name = (String) list[1];
+            MethodNode node = (MethodNode) list[0];
+            boolean isAssignment = Types.isAssignment(operationType);
+            Expression expr = left; // TODO: if (isAssignment) scrub source offsets from new copy of left?
             MethodNode adapter = StaticCompilationTransformer.BYTECODE_BINARY_ADAPTERS.get(operationType);
             if (adapter != null) {
-                ClassExpression sba = new ClassExpression(StaticCompilationTransformer.BYTECODE_ADAPTER_CLASS);
-                // replace with compareEquals
-                call = new MethodCallExpression(sba,
-                        "compareEquals",
-                        new ArgumentListExpression(left, right));
+                Expression sba = classX(StaticCompilationTransformer.BYTECODE_ADAPTER_CLASS);
+                call = callX(sba, "compareEquals", args(expr, right));
                 call.setMethodTarget(adapter);
-                call.setImplicitThis(false);
+            } else {
+                call = callX(expr, name, args(right));
+                call.setMethodTarget(node);
             }
-            call.setSourcePosition(bin);
-            if (!isAssignment) return call;
+            call.setImplicitThis(false);
+            if (!isAssignment) {
+                call.setSourcePosition(bin);
+                return call;
+            }
             // case of +=, -=, /=, ...
             // the method represents the operation type only, and we must add an assignment
-            return new BinaryExpression(left, Token.newSymbol("=", operation.getStartLine(), operation.getStartColumn()), call);
+            expr = binX(left, Token.newSymbol(Types.EQUAL, operation.getStartLine(), operation.getStartColumn()), call);
+            expr.setSourcePosition(bin);
+            return expr;
         }
-        if (bin.getOperation().getType() == Types.EQUAL && leftExpression instanceof TupleExpression && rightExpression instanceof ListExpression) {
+        if (operationType == Types.EQUAL && leftExpression instanceof TupleExpression && rightExpression instanceof ListExpression) {
             // multiple assignment
             ListOfExpressionsExpression cle = new ListOfExpressionsExpression();
-            boolean isDeclaration = bin instanceof DeclarationExpression;
+            boolean isDeclaration = (bin instanceof DeclarationExpression);
             List<Expression> leftExpressions = ((TupleExpression) leftExpression).getExpressions();
             List<Expression> rightExpressions = ((ListExpression) rightExpression).getExpressions();
             Iterator<Expression> leftIt = leftExpressions.iterator();
@@ -212,7 +204,7 @@
                     Expression left = leftIt.next();
                     if (rightIt.hasNext()) {
                         Expression right = rightIt.next();
-                        BinaryExpression bexp = new DeclarationExpression(left, bin.getOperation(), right);
+                        BinaryExpression bexp = new DeclarationExpression(left, operation, right);
                         bexp.setSourcePosition(right);
                         cle.addExpression(bexp);
                     }
@@ -225,16 +217,16 @@
                 // next = tmp1
                 // result = tmp2
                 int size = rightExpressions.size();
-                List<Expression> tmpAssignments = new ArrayList<Expression>(size);
-                List<Expression> finalAssignments = new ArrayList<Expression>(size);
-                for (int i = 0; i < Math.min(size, leftExpressions.size()); i++) {
+                List<Expression> tmpAssignments = new ArrayList<>(size);
+                List<Expression> finalAssignments = new ArrayList<>(size);
+                for (int i = 0, n = Math.min(size, leftExpressions.size()); i < n; i += 1) {
                     Expression left = leftIt.next();
                     Expression right = rightIt.next();
-                    VariableExpression tmpVar = new VariableExpression("$tmpVar$" + tmpVarCounter++);
-                    BinaryExpression bexp = new DeclarationExpression(tmpVar, bin.getOperation(), right);
+                    VariableExpression tmpVar = varX("$tmpVar$" + tmpVarCounter++);
+                    BinaryExpression bexp = new DeclarationExpression(tmpVar, operation, right);
                     bexp.setSourcePosition(right);
                     tmpAssignments.add(bexp);
-                    bexp = new BinaryExpression(left, bin.getOperation(), new VariableExpression(tmpVar));
+                    bexp = binX(left, operation, varX(tmpVar));
                     bexp.setSourcePosition(left);
                     finalAssignments.add(bexp);
                 }
@@ -250,15 +242,20 @@
         return staticCompilationTransformer.superTransform(bin);
     }
 
+    private ClassNode findType(final Expression expression) {
+        ClassNode classNode = staticCompilationTransformer.getClassNode();
+        return staticCompilationTransformer.getTypeChooser().resolveType(expression, classNode);
+    }
+
     private static BinaryExpression tryOptimizeCharComparison(final Expression left, final Expression right, final BinaryExpression bin) {
         int op = bin.getOperation().getType();
-        if (isCompareToBoolean(op) || op == COMPARE_EQUAL || op == COMPARE_NOT_EQUAL) {
+        if (StaticTypeCheckingSupport.isCompareToBoolean(op) || op == Types.COMPARE_EQUAL || op == Types.COMPARE_NOT_EQUAL) {
             Character cLeft = tryCharConstant(left);
             Character cRight = tryCharConstant(right);
             if (cLeft != null || cRight != null) {
-                Expression oLeft = cLeft == null ? left : new ConstantExpression(cLeft, true);
+                Expression oLeft = (cLeft == null ? left : constX(cLeft, true));
                 oLeft.setSourcePosition(left);
-                Expression oRight = cRight == null ? right : new ConstantExpression(cRight, true);
+                Expression oRight = (cRight == null ? right : constX(cRight, true));
                 oRight.setSourcePosition(right);
                 bin.setLeftExpression(oLeft);
                 bin.setRightExpression(oRight);
@@ -269,13 +266,10 @@
     }
 
     private static Character tryCharConstant(final Expression expr) {
-        if (expr instanceof ConstantExpression) {
-            ConstantExpression ce = (ConstantExpression) expr;
-            if (ClassHelper.STRING_TYPE.equals(ce.getType())) {
-                String val = (String) ce.getValue();
-                if (val!=null && val.length()==1) {
-                    return val.charAt(0);
-                }
+        if (expr instanceof ConstantExpression && ClassHelper.STRING_TYPE.equals(expr.getType())) {
+            String value = (String) ((ConstantExpression) expr).getValue();
+            if (value != null && value.length() == 1) {
+                return value.charAt(0);
             }
         }
         return null;
@@ -286,51 +280,33 @@
         if (leftExpression instanceof VariableExpression) {
             if (ClassHelper.char_TYPE.equals(((VariableExpression) leftExpression).getOriginType())) {
                 Expression rightExpression = bin.getRightExpression();
-                if (rightExpression instanceof ConstantExpression && ClassHelper.STRING_TYPE.equals(rightExpression.getType())) {
-                    String text = (String) ((ConstantExpression) rightExpression).getValue();
-                    if (text.length() == 1) {
-                        // optimize char initialization
-                        ConstantExpression ce = new ConstantExpression(
-                                text.charAt(0),
-                                true
-                        );
-                        ce.setSourcePosition(rightExpression);
-                        bin.setRightExpression(ce);
-                        return bin;
-                    }
+                Character c = tryCharConstant(rightExpression);
+                if (c != null) {
+                    Expression ce = constX(c, true);
+                    ce.setSourcePosition(rightExpression);
+                    bin.setRightExpression(ce);
+                    return bin;
                 }
             }
         }
         return null;
     }
 
-    private Expression convertInOperatorToTernary(final BinaryExpression bin, final Expression rightExpression, final Expression leftExpression) {
-        MethodCallExpression call = new MethodCallExpression(
-                rightExpression,
-                "isCase",
-                leftExpression
-        );
+    private static Expression convertInOperatorToTernary(final BinaryExpression bin, final Expression rightExpression, final Expression leftExpression) {
+        MethodCallExpression call = callX(rightExpression, "isCase", leftExpression);
         call.setMethodTarget((MethodNode) bin.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET));
         call.setSourcePosition(bin);
         call.copyNodeMetaData(bin);
-        TernaryExpression tExp = new TernaryExpression(
-                new BooleanExpression(
-                        new BinaryExpression(rightExpression, Token.newSymbol("==", -1, -1), new ConstantExpression(null))
-                ),
-                new BinaryExpression(leftExpression, Token.newSymbol("==", -1, -1), new ConstantExpression(null)),
+        Expression tExp = ternaryX(
+                boolX(binX(rightExpression, Token.newSymbol("==", -1, -1), nullX())),
+                binX(leftExpression, Token.newSymbol("==", -1, -1), nullX()),
                 call
         );
-        return staticCompilationTransformer.transform(tExp);
+        return tExp;
     }
 
-    private static DeclarationExpression optimizeConstantInitialization(
-            final BinaryExpression originalDeclaration,
-            final Token operation,
-            final ConstantExpression constant,
-            final Expression leftExpression,
-            final ClassNode declarationType) {
-        ConstantExpression cexp = new ConstantExpression(
-                convertConstant((Number) constant.getValue(), ClassHelper.getWrapper(declarationType)), true);
+    private static DeclarationExpression optimizeConstantInitialization(final BinaryExpression originalDeclaration, final Token operation, final ConstantExpression constant, final Expression leftExpression, final ClassNode declarationType) {
+        Expression cexp = constX(convertConstant((Number) constant.getValue(), ClassHelper.getWrapper(declarationType)), true);
         cexp.setType(declarationType);
         cexp.setSourcePosition(constant);
         DeclarationExpression result = new DeclarationExpression(
@@ -343,7 +319,7 @@
         return result;
     }
 
-    private static Object convertConstant(Number source, ClassNode target) {
+    private static Object convertConstant(final Number source, final ClassNode target) {
         if (ClassHelper.Byte_TYPE.equals(target)) {
             return source.byteValue();
         }
@@ -371,13 +347,12 @@
         throw new IllegalArgumentException("Unsupported conversion");
     }
 
-    private Expression transformPropertyAssignmentToSetterCall(final PropertyExpression leftExpression, final Expression rightExpression, final MethodNode directMCT) {
+    private static Expression transformPropertyAssignmentToSetterCall(final PropertyExpression leftExpression, final Expression rightExpression, final MethodNode directMCT) {
         // transform "a.x = b" into "def tmp = b; a.setX(tmp); tmp"
-        Expression arg = staticCompilationTransformer.transform(rightExpression);
         return StaticPropertyAccessHelper.transformToSetterCall(
                 leftExpression.getObjectExpression(),
                 directMCT,
-                arg,
+                rightExpression,
                 false,
                 leftExpression.isSafe(),
                 false,
@@ -385,9 +360,4 @@
                 leftExpression
         );
     }
-
-    protected static boolean isNullConstant(final Expression expression) {
-        return expression instanceof ConstantExpression && ((ConstantExpression) expression).getValue() == null;
-    }
-
-}
\ No newline at end of file
+}