Search in sources :

Example 76 with Parameter

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

the class AsmClassGenerator method visitClosureListExpression.

@Override
public void visitClosureListExpression(final ClosureListExpression expression) {
    MethodVisitor mv = controller.getMethodVisitor();
    controller.getCompileStack().pushVariableScope(expression.getVariableScope());
    List<Expression> expressions = expression.getExpressions();
    final int size = expressions.size();
    // init declarations
    for (int i = 0; i < size; i += 1) {
        Expression expr = expressions.get(i);
        if (expr instanceof DeclarationExpression) {
            DeclarationExpression de = (DeclarationExpression) expr;
            BinaryExpression be = new BinaryExpression(de.getLeftExpression(), de.getOperation(), de.getRightExpression());
            expressions.set(i, be);
            de.setRightExpression(ConstantExpression.NULL);
            visitDeclarationExpression(de);
        }
    }
    List<Object> instructions = new LinkedList<>();
    // to keep stack height put a null on stack
    instructions.add(ConstantExpression.NULL);
    // init table
    final Label dflt = new Label();
    final Label tableEnd = new Label();
    final Label[] labels = new Label[size];
    instructions.add(new BytecodeInstruction() {

        @Override
        public void visit(MethodVisitor mv) {
            mv.visitVarInsn(ILOAD, 1);
            mv.visitTableSwitchInsn(0, size - 1, dflt, labels);
        }
    });
    // visit cases
    for (int i = 0; i < size; i += 1) {
        Label label = new Label();
        Expression expr = expressions.get(i);
        labels[i] = label;
        instructions.add(new BytecodeInstruction() {

            @Override
            public void visit(MethodVisitor mv) {
                mv.visitLabel(label);
                // expressions will leave a value on stack, so need to pop the alibi null
                mv.visitInsn(POP);
            }
        });
        instructions.add(expr);
        instructions.add(new BytecodeInstruction() {

            @Override
            public void visit(MethodVisitor mv) {
                mv.visitJumpInsn(GOTO, tableEnd);
            }
        });
    }
    // default case
    instructions.add(new BytecodeInstruction() {

        @Override
        public void visit(MethodVisitor mv) {
            mv.visitLabel(dflt);
        }
    });
    ConstantExpression text = new ConstantExpression("invalid index for closure");
    ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
    ThrowStatement ts = new ThrowStatement(cce);
    instructions.add(ts);
    // return
    instructions.add(new BytecodeInstruction() {

        @Override
        public void visit(MethodVisitor mv) {
            mv.visitLabel(tableEnd);
            mv.visitInsn(ARETURN);
        }
    });
    BlockStatement bs = new BlockStatement();
    bs.addStatement(new BytecodeSequence(instructions));
    Parameter closureIndex = new Parameter(ClassHelper.int_TYPE, "__closureIndex");
    ClosureExpression ce = new ClosureExpression(new Parameter[] { closureIndex }, bs);
    ce.setVariableScope(expression.getVariableScope());
    visitClosureExpression(ce);
    // we need later an array to store the curried
    // closures, so we create it here and ave it
    // in a temporary variable
    BytecodeHelper.pushConstant(mv, size);
    mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
    int listArrayVar = controller.getCompileStack().defineTemporaryVariable("_listOfClosures", true);
    // add curried versions
    for (int i = 0; i < size; i += 1) {
        // stack: closure
        // we need to create a curried closure version
        // so we store the type on stack
        mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/CurriedClosure");
        // stack: closure, type
        // for a constructor call we need the type two times
        // and the closure after them
        mv.visitInsn(DUP2);
        mv.visitInsn(SWAP);
        // stack: closure,type,type,closure
        // so we can create the curried closure
        mv.visitInsn(ICONST_1);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitLdcInsn(i);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/CurriedClosure", "<init>", "(Lgroovy/lang/Closure;[Ljava/lang/Object;)V", false);
        // stack: closure,curriedClosure
        // we need to save the result
        mv.visitVarInsn(ALOAD, listArrayVar);
        mv.visitInsn(SWAP);
        BytecodeHelper.pushConstant(mv, i);
        mv.visitInsn(SWAP);
        mv.visitInsn(AASTORE);
    // stack: closure
    }
    // we don't need the closure any longer, so remove it
    mv.visitInsn(POP);
    // we load the array and create a list from it
    mv.visitVarInsn(ALOAD, listArrayVar);
    createListMethod.call(mv);
    // remove the temporary variable to keep the
    // stack clean
    controller.getCompileStack().removeVar(listArrayVar);
    controller.getOperandStack().pop();
}
Also used : ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) AnnotationConstantExpression(org.codehaus.groovy.ast.expr.AnnotationConstantExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) Label(org.objectweb.asm.Label) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) LinkedList(java.util.LinkedList) TraceMethodVisitor(org.objectweb.asm.util.TraceMethodVisitor) MethodVisitor(org.objectweb.asm.MethodVisitor) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) UnaryMinusExpression(org.codehaus.groovy.ast.expr.UnaryMinusExpression) ClosureListExpression(org.codehaus.groovy.ast.expr.ClosureListExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) MethodReferenceExpression(org.codehaus.groovy.ast.expr.MethodReferenceExpression) TernaryExpression(org.codehaus.groovy.ast.expr.TernaryExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) PrefixExpression(org.codehaus.groovy.ast.expr.PrefixExpression) PostfixExpression(org.codehaus.groovy.ast.expr.PostfixExpression) Expression(org.codehaus.groovy.ast.expr.Expression) UnaryPlusExpression(org.codehaus.groovy.ast.expr.UnaryPlusExpression) AnnotationConstantExpression(org.codehaus.groovy.ast.expr.AnnotationConstantExpression) BitwiseNegationExpression(org.codehaus.groovy.ast.expr.BitwiseNegationExpression) MapExpression(org.codehaus.groovy.ast.expr.MapExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) NotExpression(org.codehaus.groovy.ast.expr.NotExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) MethodPointerExpression(org.codehaus.groovy.ast.expr.MethodPointerExpression) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) LambdaExpression(org.codehaus.groovy.ast.expr.LambdaExpression) GStringExpression(org.codehaus.groovy.ast.expr.GStringExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) RangeExpression(org.codehaus.groovy.ast.expr.RangeExpression) SpreadExpression(org.codehaus.groovy.ast.expr.SpreadExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) SpreadMapExpression(org.codehaus.groovy.ast.expr.SpreadMapExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) AttributeExpression(org.codehaus.groovy.ast.expr.AttributeExpression) Parameter(org.codehaus.groovy.ast.Parameter) ThrowStatement(org.codehaus.groovy.ast.stmt.ThrowStatement) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression)

Example 77 with Parameter

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

the class AsmClassGenerator method visitConstructorOrMethod.

@Override
protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
    Parameter[] parameters = node.getParameters();
    MethodVisitor mv = classVisitor.visitMethod(node.getModifiers() | (isVargs(parameters) ? ACC_VARARGS : 0), node.getName(), BytecodeHelper.getMethodDescriptor(node.getReturnType(), parameters), BytecodeHelper.getGenericsMethodSignature(node), buildExceptions(node.getExceptions()));
    controller.setMethodVisitor(mv);
    controller.resetLineNumber();
    visitAnnotations(node, mv);
    visitTypeParameters(node, mv);
    // ideally following statement would be in visitMethod but mv not visible there
    if (!(node instanceof ConstructorNode)) {
        visitType(node.getReturnType(), mv, newTypeReference(METHOD_RETURN), "", true);
    }
    // add parameter names to the MethodVisitor (JDK8+)
    if (Optional.ofNullable(controller.getClassNode().getCompileUnit()).orElseGet(context::getCompileUnit).getConfig().getParameters()) {
        for (Parameter parameter : parameters) {
            mv.visitParameter(parameter.getName(), parameter.getModifiers());
        }
    }
    for (int i = 0, n = parameters.length; i < n; i += 1) {
        visitParameterAnnotations(parameters[i], i, mv);
        ClassNode paramType = parameters[i].getType();
        if (paramType.isGenericsPlaceHolder()) {
            visitTypeAnnotations(paramType, mv, newFormalParameterReference(i), "", true);
        } else {
            visitType(parameters[i].getType(), mv, newFormalParameterReference(i), "", true);
        }
    }
    if (node.getExceptions() != null) {
        for (int i = 0, n = node.getExceptions().length; i < n; i += 1) {
            visitTypeAnnotations(node.getExceptions()[i], mv, newExceptionReference(i), "", true);
        }
    }
    if (controller.getClassNode().isAnnotationDefinition() && !node.isStaticConstructor()) {
        visitAnnotationDefault(node, mv);
    } else if (!node.isAbstract()) {
        mv.visitCode();
        Statement code = node.getCode();
        // fast path for getters, setters, etc.
        BytecodeInstruction instruction;
        if (code instanceof BytecodeSequence && (instruction = ((BytecodeSequence) code).getBytecodeInstruction()) != null) {
            instruction.visit(mv);
        } else {
            visitStdMethod(node, isConstructor, parameters, code);
        }
        try {
            mv.visitMaxs(0, 0);
        } catch (Exception e) {
            Writer writer = null;
            if (mv instanceof TraceMethodVisitor) {
                writer = new StringBuilderWriter();
                PrintWriter p = new PrintWriter(writer);
                ((TraceMethodVisitor) mv).p.print(p);
                p.flush();
            }
            StringBuilder message = new StringBuilder(64);
            message.append("ASM reporting processing error for ");
            message.append(controller.getClassNode().toString(false)).append('#').append(node.getName());
            message.append(" with signature ").append(node.getTypeDescriptor());
            message.append(" in ").append(sourceFile).append(':').append(node.getLineNumber());
            if (writer != null) {
                message.append("\nLast known generated bytecode in last generated method or constructor:\n");
                message.append(writer);
            }
            throw new GroovyRuntimeException(message.toString(), e);
        }
    }
    mv.visitEnd();
}
Also used : InterfaceHelperClassNode(org.codehaus.groovy.ast.InterfaceHelperClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) StringBuilderWriter(org.apache.groovy.io.StringBuilderWriter) AssertStatement(org.codehaus.groovy.ast.stmt.AssertStatement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) BreakStatement(org.codehaus.groovy.ast.stmt.BreakStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) ThrowStatement(org.codehaus.groovy.ast.stmt.ThrowStatement) SynchronizedStatement(org.codehaus.groovy.ast.stmt.SynchronizedStatement) TryCatchStatement(org.codehaus.groovy.ast.stmt.TryCatchStatement) CaseStatement(org.codehaus.groovy.ast.stmt.CaseStatement) WhileStatement(org.codehaus.groovy.ast.stmt.WhileStatement) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) DoWhileStatement(org.codehaus.groovy.ast.stmt.DoWhileStatement) ContinueStatement(org.codehaus.groovy.ast.stmt.ContinueStatement) SwitchStatement(org.codehaus.groovy.ast.stmt.SwitchStatement) GroovyRuntimeException(groovy.lang.GroovyRuntimeException) TraceMethodVisitor(org.objectweb.asm.util.TraceMethodVisitor) GroovyRuntimeException(groovy.lang.GroovyRuntimeException) RuntimeParserException(org.codehaus.groovy.syntax.RuntimeParserException) TraceMethodVisitor(org.objectweb.asm.util.TraceMethodVisitor) MethodVisitor(org.objectweb.asm.MethodVisitor) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter) OptimizingStatementWriter(org.codehaus.groovy.classgen.asm.OptimizingStatementWriter) MopWriter(org.codehaus.groovy.classgen.asm.MopWriter) StringBuilderWriter(org.apache.groovy.io.StringBuilderWriter) PrintWriter(java.io.PrintWriter) Writer(java.io.Writer) PrintWriter(java.io.PrintWriter)

Example 78 with Parameter

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

the class Verifier method addDefaultParameters.

protected void addDefaultParameters(final DefaultArgsAction action, final MethodNode method) {
    Parameter[] parameters = method.getParameters();
    long n = Arrays.stream(parameters).filter(Parameter::hasInitialExpression).count();
    for (int i = 1; i <= n; i += 1) {
        Parameter[] newParams = new Parameter[parameters.length - i];
        ArgumentListExpression arguments = new ArgumentListExpression();
        int index = 0;
        int j = 1;
        for (Parameter parameter : parameters) {
            if (parameter == null) {
                throw new GroovyBugError("Parameter should not be null for method " + methodNode.getName());
            } else {
                Expression e;
                if (j > n - i && parameter.hasInitialExpression()) {
                    e = parameter.getInitialExpression();
                } else {
                    newParams[index++] = parameter;
                    e = varX(parameter);
                }
                arguments.addExpression(castX(parameter.getType(), e));
                if (parameter.hasInitialExpression())
                    j += 1;
            }
        }
        action.call(arguments, newParams, method);
    }
    for (Parameter parameter : parameters) {
        if (parameter.hasInitialExpression()) {
            // remove default expression and store it as node metadata
            parameter.putNodeMetaData(Verifier.INITIAL_EXPRESSION, parameter.getInitialExpression());
            parameter.setInitialExpression(null);
        }
    }
}
Also used : VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) GroovyBugError(org.codehaus.groovy.GroovyBugError) Parameter(org.codehaus.groovy.ast.Parameter) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression)

Example 79 with Parameter

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

the class Verifier method equalParametersWithGenerics.

private static boolean equalParametersWithGenerics(final MethodNode m1, final MethodNode m2, final Map<String, ClassNode> genericsSpec) {
    Parameter[] p1 = m1.getParameters();
    Parameter[] p2 = m2.getParameters();
    if (p1.length != p2.length)
        return false;
    for (int i = 0, n = p2.length; i < n; i += 1) {
        ClassNode type = p2[i].getType();
        ClassNode genericsType = correctToGenericsSpec(genericsSpec, type);
        ClassNode parameterType = p1[i].getType();
        if (!parameterType.equals(genericsType))
            return false;
    }
    return true;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 80 with Parameter

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

the class Verifier method adjustTypesIfStaticMainMethod.

private static void adjustTypesIfStaticMainMethod(final MethodNode node) {
    if (node.getName().equals("main") && node.isStatic()) {
        Parameter[] params = node.getParameters();
        if (params.length == 1) {
            Parameter param = params[0];
            if (param.getType() == null || isObjectType(param.getType())) {
                param.setType(ClassHelper.STRING_TYPE.makeArray());
                ClassNode returnType = node.getReturnType();
                if (isObjectType(returnType)) {
                    node.setReturnType(ClassHelper.VOID_TYPE);
                }
            }
        }
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Parameter(org.codehaus.groovy.ast.Parameter)

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