Search in sources :

Example 66 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy by apache.

the class StaticTypesLambdaWriter method addSyntheticLambdaMethodNode.

private MethodNode addSyntheticLambdaMethodNode(final LambdaExpression expression, final ClassNode lambdaClass, final MethodNode abstractMethod) {
    Parameter[] parametersWithExactType = createParametersWithExactType(expression, abstractMethod);
    Parameter[] localVariableParameters = getLambdaSharedVariables(expression);
    removeInitialValues(localVariableParameters);
    MethodNode doCallMethod = lambdaClass.addMethod("doCall", ACC_PUBLIC, abstractMethod.getReturnType(), parametersWithExactType.clone(), ClassNode.EMPTY_ARRAY, expression.getCode());
    doCallMethod.putNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE, parametersWithExactType);
    expression.putNodeMetaData(LAMBDA_SHARED_VARIABLES, localVariableParameters);
    doCallMethod.setSourcePosition(expression);
    return doCallMethod;
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 67 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy by apache.

the class StaticTypesLambdaWriter method addDeserializeLambdaMethod.

private void addDeserializeLambdaMethod() {
    ClassNode enclosingClass = controller.getClassNode();
    Parameter[] parameters = createDeserializeLambdaMethodParams();
    if (enclosingClass.hasMethod("$deserializeLambda$", parameters)) {
        return;
    }
    Statement code = block(declS(localVarX("enclosingClass", OBJECT_TYPE), classX(enclosingClass)), ((BlockStatement) new AstStringCompiler().compile("return enclosingClass" + ".getDeclaredMethod(\"\\$deserializeLambda_${serializedLambda.getImplClass().replace('/', '$')}\\$\", serializedLambda.getClass())" + ".invoke(null, serializedLambda)").get(0)).getStatements().get(0));
    enclosingClass.addSyntheticMethod("$deserializeLambda$", ACC_PRIVATE | ACC_STATIC, OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, code);
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) AstStringCompiler(org.codehaus.groovy.ast.builder.AstStringCompiler) Parameter(org.codehaus.groovy.ast.Parameter) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 68 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy by apache.

the class StaticTypesLambdaWriter method createLambdaClass.

protected ClassNode createLambdaClass(final LambdaExpression expression, final int modifiers, final MethodNode abstractMethod) {
    ClassNode enclosingClass = controller.getClassNode();
    ClassNode outermostClass = controller.getOutermostClass();
    boolean staticMethodOrInStaticClass = (controller.isStaticMethod() || enclosingClass.isStaticClass());
    InnerClassNode lambdaClass = new InnerClassNode(enclosingClass, nextLambdaClassName(), modifiers, CLOSURE_TYPE.getPlainNodeReference());
    // lambdaClass.setUsingGenerics(outermostClass.isUsingGenerics());
    lambdaClass.setEnclosingMethod(controller.getMethodNode());
    lambdaClass.setSourcePosition(expression);
    lambdaClass.setSynthetic(true);
    if (controller.isInScriptBody()) {
        lambdaClass.setScriptBody(true);
    }
    if (staticMethodOrInStaticClass) {
        lambdaClass.setStaticClass(true);
    }
    if (expression.isSerializable()) {
        addSerialVersionUIDField(lambdaClass);
    }
    MethodNode syntheticLambdaMethodNode = addSyntheticLambdaMethodNode(expression, lambdaClass, abstractMethod);
    Parameter[] localVariableParameters = expression.getNodeMetaData(LAMBDA_SHARED_VARIABLES);
    addFieldsAndGettersForLocalVariables(lambdaClass, localVariableParameters);
    ConstructorNode constructorNode = addConstructor(expression, localVariableParameters, lambdaClass, createBlockStatementForConstructor(expression, outermostClass, enclosingClass));
    constructorNode.putNodeMetaData(IS_GENERATED_CONSTRUCTOR, Boolean.TRUE);
    syntheticLambdaMethodNode.getCode().visit(new CorrectAccessedVariableVisitor(lambdaClass));
    return lambdaClass;
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 69 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy by apache.

the class StaticTypesLambdaWriter method createParametersWithExactType.

private Parameter[] createParametersWithExactType(final LambdaExpression expression, final MethodNode abstractMethod) {
    Parameter[] targetParameters = cloneParams(abstractMethod.getParameters());
    Parameter[] parameters = getParametersSafe(expression);
    for (int i = 0, n = parameters.length; i < n; i += 1) {
        Parameter targetParameter = targetParameters[i];
        Parameter parameter = parameters[i];
        ClassNode inferredType = parameter.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
        if (inferredType != null) {
            ClassNode type = convertParameterType(targetParameter.getType(), parameter.getType(), inferredType);
            parameter.setOriginType(type);
            parameter.setType(type);
        }
    }
    return parameters;
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 70 with Parameter

use of org.codehaus.groovy.ast.Parameter 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)

Aggregations

Parameter (org.codehaus.groovy.ast.Parameter)342 ClassNode (org.codehaus.groovy.ast.ClassNode)202 MethodNode (org.codehaus.groovy.ast.MethodNode)135 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)117 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)111 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)102 Expression (org.codehaus.groovy.ast.expr.Expression)98 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)90 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)75 FieldNode (org.codehaus.groovy.ast.FieldNode)71 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)71 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)69 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)68 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)66 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)66 Statement (org.codehaus.groovy.ast.stmt.Statement)66 ArrayList (java.util.ArrayList)62 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)56 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)52 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)51