protected void evaluateCompareExpression( MethodCaller compareMethod, BinaryExpression expression) { Expression leftExp = expression.getLeftExpression(); TypeChooser typeChooser = controller.getTypeChooser(); ClassNode cn = controller.getClassNode(); ClassNode leftType = typeChooser.resolveType(leftExp, cn); Expression rightExp = expression.getRightExpression(); ClassNode rightType = typeChooser.resolveType(rightExp, cn); boolean done = false; if (ClassHelper.isPrimitiveType(leftType) && ClassHelper.isPrimitiveType(rightType)) { 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) { Expression leftExpression = expression.getLeftExpression(); AsmClassGenerator acg = controller.getAcg(); OperandStack operandStack = controller.getOperandStack(); leftExpression.visit(acg); operandStack.box(); // if the right hand side is a boolean expression, we need to autobox Expression rightExpression = expression.getRightExpression(); rightExpression.visit(acg); operandStack.box(); compareToMethod.call(controller.getMethodVisitor()); operandStack.replace(ClassHelper.Integer_TYPE, 2); }
private void evaluateInstanceof(BinaryExpression expression) { OperandStack operandStack = controller.getOperandStack(); expression.getLeftExpression().visit(controller.getAcg()); operandStack.box(); Expression rightExp = expression.getRightExpression(); ClassNode classType; if (rightExp instanceof ClassExpression) { ClassExpression classExp = (ClassExpression) rightExp; classType = classExp.getType(); } else { throw new RuntimeException( "Right hand side of the instanceof keyword must be a class name, not: " + rightExp); } String classInternalName = BytecodeHelper.getClassInternalName(classType); controller.getMethodVisitor().visitTypeInsn(INSTANCEOF, classInternalName); operandStack.replace(ClassHelper.boolean_TYPE); }
public void evaluateEqual(BinaryExpression expression, boolean defineVariable) { AsmClassGenerator acg = controller.getAcg(); CompileStack compileStack = controller.getCompileStack(); OperandStack operandStack = controller.getOperandStack(); Expression rightExpression = expression.getRightExpression(); Expression leftExpression = expression.getLeftExpression(); ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode()); if (defineVariable && rightExpression instanceof EmptyExpression && !(leftExpression instanceof TupleExpression)) { VariableExpression ve = (VariableExpression) leftExpression; BytecodeVariable var = compileStack.defineVariable( ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false); operandStack.loadOrStoreVariable(var, false); return; } // let's evaluate the RHS and store the result ClassNode rhsType; if (rightExpression instanceof ListExpression && lhsType.isArray()) { ListExpression list = (ListExpression) rightExpression; ArrayExpression array = new ArrayExpression(lhsType.getComponentType(), list.getExpressions()); array.setSourcePosition(list); array.visit(acg); } else if (rightExpression instanceof EmptyExpression) { rhsType = leftExpression.getType(); loadInitValue(rhsType); } else { rightExpression.visit(acg); } rhsType = operandStack.getTopOperand(); boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression); int rhsValueId; if (directAssignment) { VariableExpression var = (VariableExpression) leftExpression; if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(rhsType)) { // GROOVY-5570: if a closure shared variable is a primitive type, it must be boxed rhsType = ClassHelper.getWrapper(rhsType); 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 // form as it is closure shared if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && isNull(rightExpression)) { operandStack.doGroovyCast(var.getOriginType()); // these two are never reached in bytecode and only there // to avoid verifyerrors and compiler infrastructure hazzle operandStack.box(); operandStack.doGroovyCast(lhsType); } // normal type transformation if (!ClassHelper.isPrimitiveType(lhsType) && isNull(rightExpression)) { operandStack.replace(lhsType); } else { operandStack.doGroovyCast(lhsType); } rhsType = lhsType; rhsValueId = compileStack.defineVariable(var, lhsType, true).getIndex(); } else { rhsValueId = compileStack.defineTemporaryVariable("$rhs", rhsType, true); } // 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; if (leftBinExpr.getOperation().getType() == Types.LEFT_SQUARE_BRACKET) { assignToArray( expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader); } compileStack.removeVar(rhsValueId); return; } compileStack.pushLHS(true); // multiple declaration if (leftExpression instanceof TupleExpression) { TupleExpression tuple = (TupleExpression) leftExpression; int i = 0; for (Expression e : tuple.getExpressions()) { VariableExpression var = (VariableExpression) e; MethodCallExpression call = new MethodCallExpression( rhsValueLoader, "getAt", new ArgumentListExpression(new ConstantExpression(i))); call.visit(acg); i++; if (defineVariable) { operandStack.doGroovyCast(var); compileStack.defineVariable(var, true); operandStack.remove(1); } else { acg.visitVariableExpression(var); } } } // single declaration else if (defineVariable) { rhsValueLoader.visit(acg); operandStack.remove(1); compileStack.popLHS(); return; } // normal assignment else { int mark = operandStack.getStackLength(); // to leave a copy of the rightExpression value on the stack after the assignment. rhsValueLoader.visit(acg); TypeChooser typeChooser = controller.getTypeChooser(); ClassNode targetType = typeChooser.resolveType(leftExpression, controller.getClassNode()); operandStack.doGroovyCast(targetType); leftExpression.visit(acg); operandStack.remove(operandStack.getStackLength() - mark); } compileStack.popLHS(); // return value of assignment rhsValueLoader.visit(acg); compileStack.removeVar(rhsValueId); }