|  | @@ -23,8 +23,9 @@ import org.elasticsearch.painless.DefBootstrap;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.Location;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.MethodWriter;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.Operation;
 | 
	
		
			
				|  |  | +import org.elasticsearch.painless.WriterConstants;
 | 
	
		
			
				|  |  | +import org.elasticsearch.painless.ir.BinaryImplNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.BinaryMathNode;
 | 
	
		
			
				|  |  | -import org.elasticsearch.painless.ir.BinaryNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.BlockNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.BooleanNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.BreakNode;
 | 
	
	
		
			
				|  | @@ -80,7 +81,6 @@ import org.elasticsearch.painless.ir.ReturnNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.StatementExpressionNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.StatementNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.StaticNode;
 | 
	
		
			
				|  |  | -import org.elasticsearch.painless.ir.StoreAccessNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.StoreBraceDefNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.StoreBraceNode;
 | 
	
		
			
				|  |  |  import org.elasticsearch.painless.ir.StoreDotDefNode;
 | 
	
	
		
			
				|  | @@ -273,17 +273,17 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              blockNode.addStatementNode(returnNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            BinaryNode irBinaryNode = new BinaryNode();
 | 
	
		
			
				|  |  | -            irBinaryNode.setLocation(internalLocation);
 | 
	
		
			
				|  |  | -            irBinaryNode.setExpressionType(CallSite.class);
 | 
	
		
			
				|  |  | +            BinaryImplNode irBinaryImplNode = new BinaryImplNode();
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setLocation(internalLocation);
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setExpressionType(CallSite.class);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            returnNode.setExpressionNode(irBinaryNode);
 | 
	
		
			
				|  |  | +            returnNode.setExpressionNode(irBinaryImplNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              StaticNode staticNode = new StaticNode();
 | 
	
		
			
				|  |  |              staticNode.setLocation(internalLocation);
 | 
	
		
			
				|  |  |              staticNode.setExpressionType(DefBootstrap.class);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            irBinaryNode.setLeftNode(staticNode);
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setLeftNode(staticNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              InvokeCallNode invokeCallNode = new InvokeCallNode();
 | 
	
		
			
				|  |  |              invokeCallNode.setLocation(internalLocation);
 | 
	
	
		
			
				|  | @@ -316,7 +316,7 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |              invokeCallNode.setBox(DefBootstrap.class);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            irBinaryNode.setRightNode(invokeCallNode);
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setRightNode(invokeCallNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              LoadFieldMemberNode irLoadFieldMemberNode = new LoadFieldMemberNode();
 | 
	
		
			
				|  |  |              irLoadFieldMemberNode.setLocation(internalLocation);
 | 
	
	
		
			
				|  | @@ -427,89 +427,67 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |      protected ExpressionNode buildLoadStore(int accessDepth, Location location, boolean isNullSafe,
 | 
	
		
			
				|  |  |              ExpressionNode irPrefixNode, ExpressionNode irIndexNode, ExpressionNode irLoadNode, StoreNode irStoreNode) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        ExpressionNode irExpressionNode;
 | 
	
		
			
				|  |  | +        // build out the load structure for load/compound assignment or the store structure for just store
 | 
	
		
			
				|  |  | +        ExpressionNode irExpressionNode = irLoadNode != null ? irLoadNode : irStoreNode;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        // this load/store is only a load (read)
 | 
	
		
			
				|  |  | -        if (irStoreNode == null) {
 | 
	
		
			
				|  |  | -            ExpressionNode irAccessNode;
 | 
	
		
			
				|  |  | +        if (irPrefixNode != null) {
 | 
	
		
			
				|  |  | +            // this load/store is a dot or brace load/store
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // this load is a symbol or dot load with no index node
 | 
	
		
			
				|  |  | -            if (irIndexNode == null) {
 | 
	
		
			
				|  |  | -                irAccessNode = irLoadNode;
 | 
	
		
			
				|  |  | -            // this load is a dot or brace load with an index node
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                BinaryNode irBinaryNode = new BinaryNode();
 | 
	
		
			
				|  |  | -                irBinaryNode.setLocation(location);
 | 
	
		
			
				|  |  | -                irBinaryNode.setExpressionType(irLoadNode.getExpressionType());
 | 
	
		
			
				|  |  | -                irBinaryNode.setLeftNode(irIndexNode);
 | 
	
		
			
				|  |  | -                irBinaryNode.setRightNode(irLoadNode);
 | 
	
		
			
				|  |  | +            if (irIndexNode != null) {
 | 
	
		
			
				|  |  | +                // this load/store requires an index
 | 
	
		
			
				|  |  | +                BinaryImplNode binaryImplNode = new BinaryImplNode();
 | 
	
		
			
				|  |  | +                binaryImplNode.setLocation(location);
 | 
	
		
			
				|  |  | +                binaryImplNode.setExpressionType(void.class);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                irAccessNode = irBinaryNode;
 | 
	
		
			
				|  |  | +                if (isNullSafe) {
 | 
	
		
			
				|  |  | +                    // the null-safe structure is slightly different from the standard structure since
 | 
	
		
			
				|  |  | +                    // both the index and expression are not written to the stack if the prefix is null
 | 
	
		
			
				|  |  | +                    binaryImplNode.setLeftNode(irIndexNode);
 | 
	
		
			
				|  |  | +                    binaryImplNode.setRightNode(irExpressionNode);
 | 
	
		
			
				|  |  | +                    irExpressionNode = binaryImplNode;
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    binaryImplNode.setLeftNode(irPrefixNode);
 | 
	
		
			
				|  |  | +                    binaryImplNode.setRightNode(irIndexNode);
 | 
	
		
			
				|  |  | +                    irPrefixNode = binaryImplNode;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // this wraps the load if this is a null-safe operation
 | 
	
		
			
				|  |  | -            if (isNullSafe) {
 | 
	
		
			
				|  |  | -                NullSafeSubNode nullSafeSubNode = new NullSafeSubNode();
 | 
	
		
			
				|  |  | -                nullSafeSubNode.setChildNode(irAccessNode);
 | 
	
		
			
				|  |  | -                nullSafeSubNode.setLocation(location);
 | 
	
		
			
				|  |  | -                nullSafeSubNode.setExpressionType(irAccessNode.getExpressionType());
 | 
	
		
			
				|  |  | -                irAccessNode = nullSafeSubNode;
 | 
	
		
			
				|  |  | +            if (irLoadNode != null && irStoreNode != null) {
 | 
	
		
			
				|  |  | +                // this is a compound assignment and requires and additional dup to re-access the prefix
 | 
	
		
			
				|  |  | +                DupNode dupNode = new DupNode();
 | 
	
		
			
				|  |  | +                dupNode.setLocation(location);
 | 
	
		
			
				|  |  | +                dupNode.setExpressionType(void.class);
 | 
	
		
			
				|  |  | +                dupNode.setSize(accessDepth);
 | 
	
		
			
				|  |  | +                dupNode.setDepth(0);
 | 
	
		
			
				|  |  | +                dupNode.setChildNode(irPrefixNode);
 | 
	
		
			
				|  |  | +                irPrefixNode = dupNode;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // this load is a symbol access with no prefix
 | 
	
		
			
				|  |  | -            if (irPrefixNode == null) {
 | 
	
		
			
				|  |  | -                irExpressionNode = irAccessNode;
 | 
	
		
			
				|  |  | -            // this load is a dot or brace access with a prefix node
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                BinaryNode irParentNode = new BinaryNode();
 | 
	
		
			
				|  |  | -                irParentNode.setLocation(location);
 | 
	
		
			
				|  |  | -                irParentNode.setExpressionType(irLoadNode.getExpressionType());
 | 
	
		
			
				|  |  | -                irParentNode.setLeftNode(irPrefixNode);
 | 
	
		
			
				|  |  | -                irParentNode.setRightNode(irAccessNode);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                irExpressionNode = irParentNode;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        // this is a store (write) and possibly also a load (read) for compound assignment
 | 
	
		
			
				|  |  | -        } else {
 | 
	
		
			
				|  |  | -            ExpressionNode irAccessNode;
 | 
	
		
			
				|  |  | +            // build the structure to combine the prefix and the load/store
 | 
	
		
			
				|  |  | +            BinaryImplNode binaryImplNode = new BinaryImplNode();
 | 
	
		
			
				|  |  | +            binaryImplNode.setLocation(location);
 | 
	
		
			
				|  |  | +            binaryImplNode.setExpressionType(irExpressionNode.getExpressionType());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // this store is a symbol or dot store with no index node
 | 
	
		
			
				|  |  | -            if (irIndexNode == null) {
 | 
	
		
			
				|  |  | -                irAccessNode = irPrefixNode;
 | 
	
		
			
				|  |  | -            // this store is a dot or brace load with an index node
 | 
	
		
			
				|  |  | +            if (isNullSafe) {
 | 
	
		
			
				|  |  | +                // build the structure for a null safe load
 | 
	
		
			
				|  |  | +                NullSafeSubNode irNullSafeSubNode = new NullSafeSubNode();
 | 
	
		
			
				|  |  | +                irNullSafeSubNode.setLocation(location);
 | 
	
		
			
				|  |  | +                irNullSafeSubNode.setExpressionType(irExpressionNode.getExpressionType());
 | 
	
		
			
				|  |  | +                irNullSafeSubNode.setChildNode(irExpressionNode);
 | 
	
		
			
				|  |  | +                binaryImplNode.setLeftNode(irPrefixNode);
 | 
	
		
			
				|  |  | +                binaryImplNode.setRightNode(irNullSafeSubNode);
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  | -                BinaryNode irBinaryNode = new BinaryNode();
 | 
	
		
			
				|  |  | -                irBinaryNode.setLocation(location);
 | 
	
		
			
				|  |  | -                irBinaryNode.setExpressionType(void.class);
 | 
	
		
			
				|  |  | -                irBinaryNode.setLeftNode(irPrefixNode);
 | 
	
		
			
				|  |  | -                irBinaryNode.setRightNode(irIndexNode);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                irAccessNode = irBinaryNode;
 | 
	
		
			
				|  |  | +                // build the structure for a standard load/store
 | 
	
		
			
				|  |  | +                binaryImplNode.setLeftNode(irPrefixNode);
 | 
	
		
			
				|  |  | +                binaryImplNode.setRightNode(irExpressionNode);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // this is a simple store
 | 
	
		
			
				|  |  | -            if (irLoadNode == null) {
 | 
	
		
			
				|  |  | -                // this store is a dot or brace store
 | 
	
		
			
				|  |  | -                if (irAccessNode != null) {
 | 
	
		
			
				|  |  | -                    ((StoreAccessNode)irStoreNode).setAccessNode(irAccessNode);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            // this is a compound assignment
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                // this store has a prefix node that we must dup for a load
 | 
	
		
			
				|  |  | -                if (irAccessNode != null) {
 | 
	
		
			
				|  |  | -                    DupNode dupNode = new DupNode();
 | 
	
		
			
				|  |  | -                    dupNode.setLocation(location);
 | 
	
		
			
				|  |  | -                    dupNode.setExpressionType(void.class);
 | 
	
		
			
				|  |  | -                    dupNode.setSize(accessDepth);
 | 
	
		
			
				|  |  | -                    dupNode.setDepth(0);
 | 
	
		
			
				|  |  | -                    dupNode.setChildNode(irAccessNode);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    ((StoreAccessNode)irStoreNode).setAccessNode(dupNode);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                irStoreNode.setChildNode(irLoadNode);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            irExpressionNode = binaryImplNode;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        if (irLoadNode != null && irStoreNode != null) {
 | 
	
		
			
				|  |  | +            // this is a compound assignment and the store is the root
 | 
	
		
			
				|  |  | +            irStoreNode.setChildNode(irExpressionNode);
 | 
	
		
			
				|  |  |              irExpressionNode = irStoreNode;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -844,7 +822,7 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |          Class<?> compoundType = scriptScope.hasDecoration(userAssignmentNode, CompoundType.class) ?
 | 
	
		
			
				|  |  |                  scriptScope.getDecoration(userAssignmentNode, CompoundType.class).getCompoundType() : null;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        StoreNode irStoreNode;
 | 
	
		
			
				|  |  | +        ExpressionNode irAssignmentNode;
 | 
	
		
			
				|  |  |          // add a cast node if necessary for the value node for the assignment
 | 
	
		
			
				|  |  |          ExpressionNode irValueNode = injectCast(userAssignmentNode.getRightNode(), scriptScope);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -852,7 +830,7 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |          if (compoundType != null) {
 | 
	
		
			
				|  |  |              boolean concatenate = userAssignmentNode.getOperation() == Operation.ADD && compoundType == String.class;
 | 
	
		
			
				|  |  |              scriptScope.setCondition(userAssignmentNode.getLeftNode(), Compound.class);
 | 
	
		
			
				|  |  | -            irStoreNode = (StoreNode)visit(userAssignmentNode.getLeftNode(), scriptScope);
 | 
	
		
			
				|  |  | +            StoreNode irStoreNode = (StoreNode)visit(userAssignmentNode.getLeftNode(), scriptScope);
 | 
	
		
			
				|  |  |              ExpressionNode irLoadNode = irStoreNode.getChildNode();
 | 
	
		
			
				|  |  |              ExpressionNode irCompoundNode;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -862,6 +840,11 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |                  stringConcatenationNode.setLocation(irStoreNode.getLocation());
 | 
	
		
			
				|  |  |                  stringConcatenationNode.setExpressionType(String.class);
 | 
	
		
			
				|  |  |                  irCompoundNode = stringConcatenationNode;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // must handle the StringBuilder case for java version <= 8
 | 
	
		
			
				|  |  | +                if (irLoadNode instanceof BinaryImplNode && WriterConstants.INDY_STRING_CONCAT_BOOTSTRAP_HANDLE == null) {
 | 
	
		
			
				|  |  | +                    ((DupNode)((BinaryImplNode)irLoadNode).getLeftNode()).setDepth(1);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |              // handles when the operation is mathematical
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  |                  BinaryMathNode irBinaryMathNode = new BinaryMathNode();
 | 
	
	
		
			
				|  | @@ -938,9 +921,11 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |                  irBinaryMathNode.setLeftNode(irLoadNode);
 | 
	
		
			
				|  |  |                  irBinaryMathNode.setRightNode(irValueNode);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            irAssignmentNode = irStoreNode;
 | 
	
		
			
				|  |  |          // handles a standard assignment
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  | -            irStoreNode = (StoreNode)visit(userAssignmentNode.getLeftNode(), scriptScope);
 | 
	
		
			
				|  |  | +            irAssignmentNode = (ExpressionNode)visit(userAssignmentNode.getLeftNode(), scriptScope);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              // the value is read from after the assignment
 | 
	
		
			
				|  |  |              if (read) {
 | 
	
	
		
			
				|  | @@ -952,14 +937,17 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |                  irDupNode.setSize(MethodWriter.getType(irValueNode.getExpressionType()).getSize());
 | 
	
		
			
				|  |  |                  irDupNode.setDepth(accessDepth);
 | 
	
		
			
				|  |  |                  irDupNode.setChildNode(irValueNode);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |                  irValueNode = irDupNode;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            irStoreNode.setChildNode(irValueNode);
 | 
	
		
			
				|  |  | +            if (irAssignmentNode instanceof BinaryImplNode) {
 | 
	
		
			
				|  |  | +                ((StoreNode)((BinaryImplNode)irAssignmentNode).getRightNode()).setChildNode(irValueNode);
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                ((StoreNode)irAssignmentNode).setChildNode(irValueNode);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        scriptScope.putDecoration(userAssignmentNode, new IRNodeDecoration(irStoreNode));
 | 
	
		
			
				|  |  | +        scriptScope.putDecoration(userAssignmentNode, new IRNodeDecoration(irAssignmentNode));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
	
		
			
				|  | @@ -1289,17 +1277,17 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              irStatementExpressionNode.setExpressionNode(irStoreFieldMemberNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            BinaryNode irBinaryNode = new BinaryNode();
 | 
	
		
			
				|  |  | -            irBinaryNode.setLocation(userRegexNode.getLocation());
 | 
	
		
			
				|  |  | -            irBinaryNode.setExpressionType(Pattern.class);
 | 
	
		
			
				|  |  | +            BinaryImplNode irBinaryImplNode = new BinaryImplNode();
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setLocation(userRegexNode.getLocation());
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setExpressionType(Pattern.class);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            irStoreFieldMemberNode.setChildNode(irBinaryNode);
 | 
	
		
			
				|  |  | +            irStoreFieldMemberNode.setChildNode(irBinaryImplNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              StaticNode irStaticNode = new StaticNode();
 | 
	
		
			
				|  |  |              irStaticNode.setLocation(userRegexNode.getLocation());
 | 
	
		
			
				|  |  |              irStaticNode.setExpressionType(Pattern.class);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            irBinaryNode.setLeftNode(irStaticNode);
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setLeftNode(irStaticNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              InvokeCallNode invokeCallNode = new InvokeCallNode();
 | 
	
		
			
				|  |  |              invokeCallNode.setLocation(userRegexNode.getLocation());
 | 
	
	
		
			
				|  | @@ -1316,7 +1304,7 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |                      )
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            irBinaryNode.setRightNode(invokeCallNode);
 | 
	
		
			
				|  |  | +            irBinaryImplNode.setRightNode(invokeCallNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              ConstantNode irConstantNode = new ConstantNode();
 | 
	
		
			
				|  |  |              irConstantNode.setLocation(userRegexNode.getLocation());
 | 
	
	
		
			
				|  | @@ -1853,12 +1841,12 @@ public class DefaultUserTreeToIRTreePhase implements UserTreeVisitor<ScriptScope
 | 
	
		
			
				|  |  |              irExpressionNode = irNullSafeSubNode;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        BinaryNode irBinaryNode = new BinaryNode();
 | 
	
		
			
				|  |  | -        irBinaryNode.setLeftNode((ExpressionNode)visit(userCallNode.getPrefixNode(), scriptScope));
 | 
	
		
			
				|  |  | -        irBinaryNode.setRightNode(irExpressionNode);
 | 
	
		
			
				|  |  | -        irBinaryNode.setLocation(irExpressionNode.getLocation());
 | 
	
		
			
				|  |  | -        irBinaryNode.setExpressionType(irExpressionNode.getExpressionType());
 | 
	
		
			
				|  |  | +        BinaryImplNode irBinaryImplNode = new BinaryImplNode();
 | 
	
		
			
				|  |  | +        irBinaryImplNode.setLeftNode((ExpressionNode)visit(userCallNode.getPrefixNode(), scriptScope));
 | 
	
		
			
				|  |  | +        irBinaryImplNode.setRightNode(irExpressionNode);
 | 
	
		
			
				|  |  | +        irBinaryImplNode.setLocation(irExpressionNode.getLocation());
 | 
	
		
			
				|  |  | +        irBinaryImplNode.setExpressionType(irExpressionNode.getExpressionType());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        scriptScope.putDecoration(userCallNode, new IRNodeDecoration(irBinaryNode));
 | 
	
		
			
				|  |  | +        scriptScope.putDecoration(userCallNode, new IRNodeDecoration(irBinaryImplNode));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |