Search in sources :

Example 1 with TemporaryVariableExpression

use of org.codehaus.groovy.transform.sc.TemporaryVariableExpression in project groovy-core by groovy.

the class StaticPropertyAccessHelper method transformToSetterCall.

public static Expression transformToSetterCall(Expression receiver, MethodNode setterMethod, final Expression arguments, boolean implicitThis, boolean safe, boolean spreadSafe, boolean requiresReturnValue, Expression location) {
    if (requiresReturnValue) {
        TemporaryVariableExpression tmp = new TemporaryVariableExpression(arguments);
        PoppingMethodCallExpression call = new PoppingMethodCallExpression(receiver, setterMethod, tmp);
        call.setImplicitThis(implicitThis);
        call.setSafe(safe);
        call.setSpreadSafe(spreadSafe);
        call.setSourcePosition(location);
        PoppingListOfExpressionsExpression result = new PoppingListOfExpressionsExpression(tmp, call);
        result.setSourcePosition(location);
        return result;
    } else {
        MethodCallExpression call = new MethodCallExpression(receiver, setterMethod.getName(), arguments);
        call.setImplicitThis(implicitThis);
        call.setSafe(safe);
        call.setSpreadSafe(spreadSafe);
        call.setMethodTarget(setterMethod);
        call.setSourcePosition(location);
        return call;
    }
}
Also used : TemporaryVariableExpression(org.codehaus.groovy.transform.sc.TemporaryVariableExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression)

Example 2 with TemporaryVariableExpression

use of org.codehaus.groovy.transform.sc.TemporaryVariableExpression in project groovy by apache.

the class StaticInvocationWriter method makeCall.

@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) {
    if (origin.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION) != 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);
        return;
    }
    if (implicitThis && tryImplicitReceiver(origin, message, arguments, adapter, safe, spreadSafe)) {
        return;
    }
    // if call is spread safe, replace it with a for in loop
    if (spreadSafe && origin instanceof MethodCallExpression) {
        // receiver expressions with side effects should not be visited twice, avoid by using a temporary variable
        Expression tmpReceiver = receiver;
        if (!(receiver instanceof VariableExpression) && !(receiver instanceof ConstantExpression)) {
            tmpReceiver = new TemporaryVariableExpression(receiver);
        }
        MethodVisitor mv = controller.getMethodVisitor();
        CompileStack compileStack = controller.getCompileStack();
        TypeChooser typeChooser = controller.getTypeChooser();
        OperandStack operandStack = controller.getOperandStack();
        ClassNode classNode = controller.getClassNode();
        int counter = labelCounter.incrementAndGet();
        // use a temporary variable for the arraylist in which the results of the spread call will be stored
        ConstructorCallExpression cce = ctorX(StaticCompilationVisitor.ARRAYLIST_CLASSNODE);
        cce.setNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, StaticCompilationVisitor.ARRAYLIST_CONSTRUCTOR);
        TemporaryVariableExpression result = new TemporaryVariableExpression(cce);
        result.visit(controller.getAcg());
        operandStack.pop();
        // if (receiver != null)
        tmpReceiver.visit(controller.getAcg());
        Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
        mv.visitJumpInsn(IFNULL, ifnull);
        // receiver consumed by if()
        operandStack.remove(1);
        Label nonull = compileStack.createLocalLabel("nonull_" + counter);
        mv.visitLabel(nonull);
        ClassNode componentType = StaticTypeCheckingVisitor.inferLoopElementType(typeChooser.resolveType(tmpReceiver, classNode));
        Parameter iterator = new Parameter(componentType, "for$it$" + counter);
        VariableExpression iteratorAsVar = varX(iterator);
        MethodCallExpression origMCE = (MethodCallExpression) origin;
        MethodCallExpression newMCE = callX(iteratorAsVar, origMCE.getMethodAsString(), origMCE.getArguments());
        newMCE.setImplicitThis(false);
        newMCE.setMethodTarget(origMCE.getMethodTarget());
        newMCE.setSafe(true);
        MethodCallExpression add = callX(result, "add", newMCE);
        add.setImplicitThis(false);
        add.setMethodTarget(StaticCompilationVisitor.ARRAYLIST_ADD_METHOD);
        // for (e in receiver) { result.add(e?.method(arguments) }
        ForStatement stmt = new ForStatement(iterator, tmpReceiver, stmt(add));
        stmt.visit(controller.getAcg());
        // else { empty list }
        mv.visitLabel(ifnull);
        // end of if/else
        // return result list
        result.visit(controller.getAcg());
        // cleanup temporary variables
        if (tmpReceiver instanceof TemporaryVariableExpression) {
            ((TemporaryVariableExpression) tmpReceiver).remove(controller);
        }
        result.remove(controller);
    } else if (safe && origin instanceof MethodCallExpression) {
        // wrap call in an IFNULL check
        MethodVisitor mv = controller.getMethodVisitor();
        CompileStack compileStack = controller.getCompileStack();
        OperandStack operandStack = controller.getOperandStack();
        int counter = labelCounter.incrementAndGet();
        // if (receiver != null)
        ExpressionAsVariableSlot slot = new ExpressionAsVariableSlot(controller, receiver);
        slot.visit(controller.getAcg());
        operandStack.box();
        Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
        mv.visitJumpInsn(IFNULL, ifnull);
        // receiver consumed by if()
        operandStack.remove(1);
        Label nonull = compileStack.createLocalLabel("nonull_" + counter);
        mv.visitLabel(nonull);
        MethodCallExpression origMCE = (MethodCallExpression) origin;
        MethodCallExpression newMCE = callX(new VariableSlotLoader(slot.getType(), slot.getIndex(), controller.getOperandStack()), origMCE.getMethodAsString(), origMCE.getArguments());
        MethodNode methodTarget = origMCE.getMethodTarget();
        newMCE.setImplicitThis(origMCE.isImplicitThis());
        newMCE.setMethodTarget(methodTarget);
        newMCE.setSafe(false);
        newMCE.setSourcePosition(origMCE);
        newMCE.getObjectExpression().setSourcePosition(origMCE.getObjectExpression());
        newMCE.visit(controller.getAcg());
        compileStack.removeVar(slot.getIndex());
        ClassNode returnType = operandStack.getTopOperand();
        if (ClassHelper.isPrimitiveType(returnType) && !isPrimitiveVoid(returnType)) {
            operandStack.box();
        }
        Label endof = compileStack.createLocalLabel("endof_" + counter);
        mv.visitJumpInsn(GOTO, endof);
        mv.visitLabel(ifnull);
        // else { null }
        mv.visitInsn(ACONST_NULL);
        mv.visitLabel(endof);
    } else {
        if (origin instanceof AttributeExpression && (adapter == AsmClassGenerator.getField || adapter == AsmClassGenerator.getGroovyObjectField)) {
            CallSiteWriter callSiteWriter = controller.getCallSiteWriter();
            String fieldName = ((AttributeExpression) origin).getPropertyAsString();
            if (fieldName != null && callSiteWriter instanceof StaticTypesCallSiteWriter) {
                ClassNode receiverType = controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
                if (((StaticTypesCallSiteWriter) callSiteWriter).makeGetField(receiver, receiverType, fieldName, safe, false)) {
                    return;
                }
            }
        }
        super.makeCall(origin, receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
    }
}
Also used : OperandStack(org.codehaus.groovy.classgen.asm.OperandStack) DecompiledClassNode(org.codehaus.groovy.ast.decompiled.DecompiledClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) ExpressionAsVariableSlot(org.codehaus.groovy.classgen.asm.ExpressionAsVariableSlot) VariableSlotLoader(org.codehaus.groovy.classgen.asm.VariableSlotLoader) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) Label(org.objectweb.asm.Label) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) TemporaryVariableExpression(org.codehaus.groovy.transform.sc.TemporaryVariableExpression) AttributeExpression(org.codehaus.groovy.ast.expr.AttributeExpression) CompileStack(org.codehaus.groovy.classgen.asm.CompileStack) MethodVisitor(org.objectweb.asm.MethodVisitor) CallSiteWriter(org.codehaus.groovy.classgen.asm.CallSiteWriter) TypeChooser(org.codehaus.groovy.classgen.asm.TypeChooser) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) TemporaryVariableExpression(org.codehaus.groovy.transform.sc.TemporaryVariableExpression) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ExpressionUtils.isSuperExpression(org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) TemporaryVariableExpression(org.codehaus.groovy.transform.sc.TemporaryVariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) AttributeExpression(org.codehaus.groovy.ast.expr.AttributeExpression) InvocationWriter(org.codehaus.groovy.classgen.asm.InvocationWriter) Parameter(org.codehaus.groovy.ast.Parameter) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement)

Example 3 with TemporaryVariableExpression

use of org.codehaus.groovy.transform.sc.TemporaryVariableExpression in project groovy by apache.

the class StaticPropertyAccessHelper method transformToSetterCall.

public static Expression transformToSetterCall(final Expression receiver, final MethodNode setterMethod, final Expression valueExpression, final boolean implicitThis, final boolean safe, final boolean spreadSafe, final boolean returnValue, final Expression sourceExpression) {
    if (returnValue) {
        TemporaryVariableExpression tmp = new TemporaryVariableExpression(valueExpression);
        PoppingMethodCallExpression call = new PoppingMethodCallExpression(receiver, setterMethod, tmp);
        call.setSafe(safe);
        call.setSpreadSafe(spreadSafe);
        call.setImplicitThis(implicitThis);
        call.setSourcePosition(sourceExpression);
        PoppingListOfExpressionsExpression list = new PoppingListOfExpressionsExpression(tmp, call);
        list.setSourcePosition(sourceExpression);
        return list;
    } else {
        MethodCallExpression call = new MethodCallExpression(receiver, setterMethod.getName(), valueExpression);
        call.setSafe(safe);
        call.setSpreadSafe(spreadSafe);
        call.setImplicitThis(implicitThis);
        call.setMethodTarget(setterMethod);
        call.setSourcePosition(sourceExpression);
        return call;
    }
}
Also used : TemporaryVariableExpression(org.codehaus.groovy.transform.sc.TemporaryVariableExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression)

Aggregations

MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)3 TemporaryVariableExpression (org.codehaus.groovy.transform.sc.TemporaryVariableExpression)3 ExpressionUtils.isSuperExpression (org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression)1 ClassNode (org.codehaus.groovy.ast.ClassNode)1 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)1 MethodNode (org.codehaus.groovy.ast.MethodNode)1 Parameter (org.codehaus.groovy.ast.Parameter)1 DecompiledClassNode (org.codehaus.groovy.ast.decompiled.DecompiledClassNode)1 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)1 ArrayExpression (org.codehaus.groovy.ast.expr.ArrayExpression)1 AttributeExpression (org.codehaus.groovy.ast.expr.AttributeExpression)1 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)1 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)1 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)1 Expression (org.codehaus.groovy.ast.expr.Expression)1 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)1 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)1 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)1 ForStatement (org.codehaus.groovy.ast.stmt.ForStatement)1 CallSiteWriter (org.codehaus.groovy.classgen.asm.CallSiteWriter)1