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();
}
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();
}
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);
}
}
}
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;
}
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);
}
}
}
}
}
Aggregations