Search in sources :

Example 1 with ElvisOperatorExpression

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

the class BinaryExpressionHelper method evaluateElvisOperatorExpression.

private void evaluateElvisOperatorExpression(ElvisOperatorExpression expression) {
    MethodVisitor mv = controller.getMethodVisitor();
    CompileStack compileStack = controller.getCompileStack();
    OperandStack operandStack = controller.getOperandStack();
    TypeChooser typeChooser = controller.getTypeChooser();
    Expression boolPart = expression.getBooleanExpression().getExpression();
    Expression falsePart = expression.getFalseExpression();
    ClassNode truePartType = typeChooser.resolveType(boolPart, controller.getClassNode());
    ClassNode falsePartType = typeChooser.resolveType(falsePart, controller.getClassNode());
    ClassNode common = WideningCategories.lowestUpperBound(truePartType, falsePartType);
    // x?:y is equal to x?x:y, which evals to 
    //      var t=x; boolean(t)?t:y
    // first we load x, dup it, convert the dupped to boolean, then 
    // jump depending on the value. For true we are done, for false we
    // have to load y, thus we first remove x and then load y. 
    // But since x and y may have different stack lengths, this cannot work
    // Thus we have to have to do the following:
    // Be X the type of x, Y the type of y and S the common supertype of 
    // X and Y, then we have to see x?:y as  
    //      var t=x;boolean(t)?S(t):S(y)
    // so we load x, dup it, store the value in a local variable (t), then 
    // do boolean conversion. In the true part load t and cast it to S, 
    // in the false part load y and cast y to S 
    // load x, dup it, store one in $t and cast the remaining one to boolean
    int mark = operandStack.getStackLength();
    boolPart.visit(controller.getAcg());
    operandStack.dup();
    if (ClassHelper.isPrimitiveType(truePartType) && !ClassHelper.isPrimitiveType(operandStack.getTopOperand())) {
        truePartType = ClassHelper.getWrapper(truePartType);
    }
    int retValueId = compileStack.defineTemporaryVariable("$t", truePartType, true);
    operandStack.castToBool(mark, true);
    Label l0 = operandStack.jump(IFEQ);
    // true part: load $t and cast to S
    operandStack.load(truePartType, retValueId);
    operandStack.doGroovyCast(common);
    Label l1 = new Label();
    mv.visitJumpInsn(GOTO, l1);
    // false part: load false expression and cast to S
    mv.visitLabel(l0);
    falsePart.visit(controller.getAcg());
    operandStack.doGroovyCast(common);
    // finish and cleanup
    mv.visitLabel(l1);
    compileStack.removeVar(retValueId);
    controller.getOperandStack().replace(common, 2);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) 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) Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 2 with ElvisOperatorExpression

use of org.codehaus.groovy.ast.expr.ElvisOperatorExpression in project groovy-core by groovy.

the class BinaryExpressionHelper method evaluateElvisOperatorExpression.

private void evaluateElvisOperatorExpression(ElvisOperatorExpression expression) {
    MethodVisitor mv = controller.getMethodVisitor();
    CompileStack compileStack = controller.getCompileStack();
    OperandStack operandStack = controller.getOperandStack();
    TypeChooser typeChooser = controller.getTypeChooser();
    Expression boolPart = expression.getBooleanExpression().getExpression();
    Expression falsePart = expression.getFalseExpression();
    ClassNode truePartType = typeChooser.resolveType(boolPart, controller.getClassNode());
    ClassNode falsePartType = typeChooser.resolveType(falsePart, controller.getClassNode());
    ClassNode common = WideningCategories.lowestUpperBound(truePartType, falsePartType);
    // x?:y is equal to x?x:y, which evals to 
    //      var t=x; boolean(t)?t:y
    // first we load x, dup it, convert the dupped to boolean, then 
    // jump depending on the value. For true we are done, for false we
    // have to load y, thus we first remove x and then load y. 
    // But since x and y may have different stack lengths, this cannot work
    // Thus we have to have to do the following:
    // Be X the type of x, Y the type of y and S the common supertype of 
    // X and Y, then we have to see x?:y as  
    //      var t=x;boolean(t)?S(t):S(y)
    // so we load x, dup it, store the value in a local variable (t), then 
    // do boolean conversion. In the true part load t and cast it to S, 
    // in the false part load y and cast y to S 
    // load x, dup it, store one in $t and cast the remaining one to boolean
    int mark = operandStack.getStackLength();
    boolPart.visit(controller.getAcg());
    operandStack.dup();
    if (ClassHelper.isPrimitiveType(truePartType) && !ClassHelper.isPrimitiveType(operandStack.getTopOperand())) {
        truePartType = ClassHelper.getWrapper(truePartType);
    }
    int retValueId = compileStack.defineTemporaryVariable("$t", truePartType, true);
    operandStack.castToBool(mark, true);
    Label l0 = operandStack.jump(IFEQ);
    // true part: load $t and cast to S
    operandStack.load(truePartType, retValueId);
    operandStack.doGroovyCast(common);
    Label l1 = new Label();
    mv.visitJumpInsn(GOTO, l1);
    // false part: load false expression and cast to S
    mv.visitLabel(l0);
    falsePart.visit(controller.getAcg());
    operandStack.doGroovyCast(common);
    // finish and cleanup
    mv.visitLabel(l1);
    compileStack.removeVar(retValueId);
    controller.getOperandStack().replace(common, 2);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) 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) Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

ClassNode (org.codehaus.groovy.ast.ClassNode)2 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)2 ArrayExpression (org.codehaus.groovy.ast.expr.ArrayExpression)2 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)2 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)2 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)2 ElvisOperatorExpression (org.codehaus.groovy.ast.expr.ElvisOperatorExpression)2 EmptyExpression (org.codehaus.groovy.ast.expr.EmptyExpression)2 Expression (org.codehaus.groovy.ast.expr.Expression)2 FieldExpression (org.codehaus.groovy.ast.expr.FieldExpression)2 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)2 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)2 PostfixExpression (org.codehaus.groovy.ast.expr.PostfixExpression)2 PrefixExpression (org.codehaus.groovy.ast.expr.PrefixExpression)2 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)2 TernaryExpression (org.codehaus.groovy.ast.expr.TernaryExpression)2 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)2 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)2 BytecodeExpression (org.codehaus.groovy.classgen.BytecodeExpression)2 Label (org.objectweb.asm.Label)2