Search in sources :

Example 11 with BinaryExpression

use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.

the class BinaryExpressionHelper method evaluateEqual.

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();
        }
        // 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);
            }
        }
    } else // single declaration
    if (defineVariable) {
        rhsValueLoader.visit(acg);
        operandStack.remove(1);
        compileStack.popLHS();
        return;
    } else // normal assignment
    {
        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);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ElvisOperatorExpression(org.codehaus.groovy.ast.expr.ElvisOperatorExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) PrefixExpression(org.codehaus.groovy.ast.expr.PrefixExpression) PostfixExpression(org.codehaus.groovy.ast.expr.PostfixExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) TernaryExpression(org.codehaus.groovy.ast.expr.TernaryExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression)

Example 12 with BinaryExpression

use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.

the class BinaryExpressionMultiTypeDispatcher method doAssignmentToArray.

private boolean doAssignmentToArray(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();
    Expression leftExp = binExp.getLeftExpression();
    ClassNode leftType = getController().getTypeChooser().resolveType(leftExp, current);
    Expression rightExp = binExp.getRightExpression();
    ClassNode rightType = getController().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();
    // 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 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, 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();
    // load array index: sub=a [load x, DUP, load sub, call arrayGet, load b, call operation, load sub, call arraySet]
    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] 
    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);
    }
    bew.write(operation, false);
    // let us save that value for the return
    operandStack.dup();
    int resultValueId = compileStack.defineTemporaryVariable("$result", rightType, true);
    // array set: load sub, call arraySet []
    operandStack.load(ClassHelper.int_TYPE, subscriptValueId);
    operandStack.swap();
    bew.arraySet(false);
    // 3 operands, the array, the index and the value!
    operandStack.remove(3);
    // load return value
    operandStack.load(rightType, resultValueId);
    // cleanup
    compileStack.removeVar(resultValueId);
    compileStack.removeVar(subscriptValueId);
    return true;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) Expression(org.codehaus.groovy.ast.expr.Expression) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator)

Example 13 with BinaryExpression

use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.

the class FinalVariableAnalyzer method visitBinaryExpression.

@Override
public void visitBinaryExpression(final BinaryExpression expression) {
    boolean assignment = StaticTypeCheckingSupport.isAssignment(expression.getOperation().getType());
    boolean isDeclaration = expression instanceof DeclarationExpression;
    Expression leftExpression = expression.getLeftExpression();
    Expression rightExpression = expression.getRightExpression();
    if (isDeclaration && leftExpression instanceof VariableExpression) {
        VariableExpression var = (VariableExpression) leftExpression;
        if (Modifier.isFinal(var.getModifiers())) {
            declaredFinalVariables.add(var);
        }
    }
    leftExpression.visit(this);
    inAssignment = assignment;
    rightExpression.visit(this);
    inAssignment = false;
    if (assignment) {
        if (leftExpression instanceof Variable) {
            boolean uninitialized = isDeclaration && rightExpression == EmptyExpression.INSTANCE;
            recordAssignment((Variable) leftExpression, isDeclaration, uninitialized, false, expression);
        } else if (leftExpression instanceof TupleExpression) {
            TupleExpression te = (TupleExpression) leftExpression;
            for (Expression next : te.getExpressions()) {
                if (next instanceof Variable) {
                    recordAssignment((Variable) next, isDeclaration, false, false, next);
                }
            }
        }
    }
}
Also used : Variable(org.codehaus.groovy.ast.Variable) PrefixExpression(org.codehaus.groovy.ast.expr.PrefixExpression) PostfixExpression(org.codehaus.groovy.ast.expr.PostfixExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 14 with BinaryExpression

use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.

the class IfElseTest method testLoop.

public void testLoop() throws Exception {
    ClassNode classNode = new ClassNode("Foo", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
    classNode.addConstructor(new ConstructorNode(ACC_PUBLIC, null));
    classNode.addProperty(new PropertyNode("bar", ACC_PUBLIC, ClassHelper.STRING_TYPE, classNode, null, null, null));
    classNode.addProperty(new PropertyNode("result", ACC_PUBLIC, ClassHelper.STRING_TYPE, classNode, null, null, null));
    BooleanExpression expression = new BooleanExpression(new BinaryExpression(new FieldExpression(new FieldNode("bar", ACC_PRIVATE, ClassHelper.STRING_TYPE, classNode, ConstantExpression.NULL)), Token.newSymbol("==", 0, 0), new ConstantExpression("abc")));
    Statement trueStatement = new ExpressionStatement(new BinaryExpression(new FieldExpression(new FieldNode("result", ACC_PRIVATE, ClassHelper.STRING_TYPE, classNode, ConstantExpression.NULL)), Token.newSymbol("=", 0, 0), new ConstantExpression("worked")));
    Statement falseStatement = createPrintlnStatement(new ConstantExpression("false"));
    IfStatement statement = new IfStatement(expression, trueStatement, falseStatement);
    classNode.addMethod(new MethodNode("ifDemo", ACC_PUBLIC, ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, statement));
    Class fooClass = loadClass(classNode);
    assertTrue("Loaded a new class", fooClass != null);
    Object bean = fooClass.newInstance();
    assertTrue("Managed to create bean", bean != null);
    assertSetProperty(bean, "bar", "abc");
    System.out.println("################ Now about to invoke method");
    Object[] array = {};
    InvokerHelper.invokeMethod(bean, "ifDemo", array);
    System.out.println("################ Done");
    assertGetProperty(bean, "result", "worked");
}
Also used : Statement(org.codehaus.groovy.ast.stmt.Statement) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement)

Example 15 with BinaryExpression

use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.

the class StaticImportVisitor method transformBinaryExpression.

protected Expression transformBinaryExpression(BinaryExpression be) {
    int type = be.getOperation().getType();
    boolean oldInLeftExpression;
    Expression right = transform(be.getRightExpression());
    be.setRightExpression(right);
    Expression left;
    if (type == Types.EQUAL && be.getLeftExpression() instanceof VariableExpression) {
        oldInLeftExpression = inLeftExpression;
        inLeftExpression = true;
        left = transform(be.getLeftExpression());
        inLeftExpression = oldInLeftExpression;
        if (left instanceof StaticMethodCallExpression) {
            StaticMethodCallExpression smce = (StaticMethodCallExpression) left;
            StaticMethodCallExpression result = new StaticMethodCallExpression(smce.getOwnerType(), smce.getMethod(), right);
            setSourcePosition(result, be);
            return result;
        }
    } else {
        left = transform(be.getLeftExpression());
    }
    be.setLeftExpression(left);
    return be;
}
Also used : ListExpression(org.codehaus.groovy.ast.expr.ListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) NamedArgumentListExpression(org.codehaus.groovy.ast.expr.NamedArgumentListExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) AnnotationConstantExpression(org.codehaus.groovy.ast.expr.AnnotationConstantExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Aggregations

BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)93 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)82 Expression (org.codehaus.groovy.ast.expr.Expression)70 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)56 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)50 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)49 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)47 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)38 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)35 BooleanExpression (org.codehaus.groovy.ast.expr.BooleanExpression)33 ClassNode (org.codehaus.groovy.ast.ClassNode)31 TernaryExpression (org.codehaus.groovy.ast.expr.TernaryExpression)29 EmptyExpression (org.codehaus.groovy.ast.expr.EmptyExpression)28 FieldExpression (org.codehaus.groovy.ast.expr.FieldExpression)28 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)25 DeclarationExpression (org.codehaus.groovy.ast.expr.DeclarationExpression)23 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)21 ArrayExpression (org.codehaus.groovy.ast.expr.ArrayExpression)20 CastExpression (org.codehaus.groovy.ast.expr.CastExpression)20 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)19