use of org.codehaus.groovy.ast.stmt.Statement in project groovy by apache.
the class Verifier method visitMethod.
public void visitMethod(MethodNode node) {
//GROOVY-3712 - if it's an MOP method, it's an error as they aren't supposed to exist before ACG is invoked
if (MopWriter.isMopMethod(node.getName())) {
throw new RuntimeParserException("Found unexpected MOP methods in the class node for " + classNode.getName() + "(" + node.getName() + ")", classNode);
}
this.methodNode = node;
adjustTypesIfStaticMainMethod(node);
addReturnIfNeeded(node);
Statement statement;
statement = node.getCode();
if (statement != null)
statement.visit(new VerifierCodeVisitor(this));
}
use of org.codehaus.groovy.ast.stmt.Statement in project groovy by apache.
the class Verifier method addDefaultParameterConstructors.
protected void addDefaultParameterConstructors(final ClassNode node) {
List methods = new ArrayList(node.getDeclaredConstructors());
addDefaultParameters(methods, new DefaultArgsAction() {
public void call(ArgumentListExpression arguments, Parameter[] newParams, MethodNode method) {
ConstructorNode ctor = (ConstructorNode) method;
ConstructorCallExpression expression = new ConstructorCallExpression(ClassNode.THIS, arguments);
Statement code = new ExpressionStatement(expression);
addConstructor(newParams, ctor, code, node);
}
});
}
use of org.codehaus.groovy.ast.stmt.Statement in project groovy by apache.
the class Verifier method addGroovyObjectInterfaceAndMethods.
protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
if (!node.isDerivedFromGroovyObject())
node.addInterface(ClassHelper.make(GroovyObject.class));
FieldNode metaClassField = getMetaClassField(node);
if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
addMethod(node, !isAbstract(node.getModifiers()), "getMetaClass", ACC_PUBLIC, ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
Label nullLabel = new Label();
/**
* the code is:
* if (this.metaClass==null) {
* this.metaClass = this.$getStaticMetaClass
* return this.metaClass
* } else {
* return this.metaClass
* }
* with the optimization that the result of the
* first this.metaClass is duped on the operand
* stack and reused for the return in the else part
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(DUP);
mv.visitJumpInsn(IFNULL, nullLabel);
mv.visitInsn(ARETURN);
mv.visitLabel(nullLabel);
mv.visitInsn(POP);
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(ARETURN);
}
}));
}
Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "mc") };
if (!node.hasMethod("setMetaClass", parameters)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
Statement setMetaClassCode;
if (isFinal(metaClassField.getModifiers())) {
ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
setMetaClassCode = new ExpressionStatement(cce);
} else {
List list = new ArrayList();
list.add(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
/**
* the code is (meta class is stored in 1):
* this.metaClass = <1>
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(RETURN);
}
});
setMetaClassCode = new BytecodeSequence(list);
}
addMethod(node, !isAbstract(node.getModifiers()), "setMetaClass", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
}
if (!node.hasMethod("invokeMethod", INVOKE_METHOD_PARAMS)) {
VariableExpression vMethods = new VariableExpression("method");
VariableExpression vArguments = new VariableExpression("arguments");
VariableScope blockScope = new VariableScope();
blockScope.putReferencedLocalVariable(vMethods);
blockScope.putReferencedLocalVariable(vArguments);
addMethod(node, !isAbstract(node.getModifiers()), "invokeMethod", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, INVOKE_METHOD_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true);
mv.visitInsn(ARETURN);
}
}));
}
if (!node.hasMethod("getProperty", GET_PROPERTY_PARAMS)) {
addMethod(node, !isAbstract(node.getModifiers()), "getProperty", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, GET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true);
mv.visitInsn(ARETURN);
}
}));
}
if (!node.hasMethod("setProperty", SET_PROPERTY_PARAMS)) {
addMethod(node, !isAbstract(node.getModifiers()), "setProperty", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true);
mv.visitInsn(RETURN);
}
}));
}
}
use of org.codehaus.groovy.ast.stmt.Statement in project groovy by apache.
the class AsmClassGenerator method visitConstructorOrMethod.
protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
controller.resetLineNumber();
Parameter[] parameters = node.getParameters();
String methodType = BytecodeHelper.getMethodDescriptor(node.getReturnType(), parameters);
String signature = BytecodeHelper.getGenericsMethodSignature(node);
int modifiers = node.getModifiers();
if (isVargs(node.getParameters()))
modifiers |= Opcodes.ACC_VARARGS;
MethodVisitor mv = cv.visitMethod(modifiers, node.getName(), methodType, signature, buildExceptions(node.getExceptions()));
controller.setMethodVisitor(mv);
visitAnnotations(node, mv);
for (int i = 0; i < parameters.length; i++) {
visitParameterAnnotations(parameters[i], i, mv);
}
// Add parameter names to the MethodVisitor (jdk8+ only)
if (getCompileUnit().getConfig().getParameters()) {
for (int i = 0; i < parameters.length; i++) {
// TODO handle ACC_SYNTHETIC for enum method parameters?
mv.visitParameter(parameters[i].getName(), 0);
}
}
if (controller.getClassNode().isAnnotationDefinition() && !node.isStaticConstructor()) {
visitAnnotationDefault(node, mv);
} else if (!node.isAbstract()) {
Statement code = node.getCode();
mv.visitCode();
// fast path for getter/setters etc.
if (code instanceof BytecodeSequence && ((BytecodeSequence) code).getInstructions().size() == 1 && ((BytecodeSequence) code).getInstructions().get(0) instanceof BytecodeInstruction) {
((BytecodeInstruction) ((BytecodeSequence) code).getInstructions().get(0)).visit(mv);
} else {
visitStdMethod(node, isConstructor, parameters, code);
}
//mv.visitInsn(NOP);
try {
mv.visitMaxs(0, 0);
} catch (Exception e) {
throw new GroovyRuntimeException("ASM reporting processing error for " + controller.getClassNode() + "#" + node.getName() + " with signature " + node.getTypeDescriptor() + " in " + sourceFile + ":" + node.getLineNumber(), e);
}
}
mv.visitEnd();
}
use of org.codehaus.groovy.ast.stmt.Statement in project groovy by apache.
the class AsmClassGenerator method visitClosureListExpression.
public void visitClosureListExpression(ClosureListExpression expression) {
MethodVisitor mv = controller.getMethodVisitor();
controller.getCompileStack().pushVariableScope(expression.getVariableScope());
List<Expression> expressions = expression.getExpressions();
final int size = expressions.size();
// init declarations
LinkedList<DeclarationExpression> declarations = new LinkedList<DeclarationExpression>();
for (int i = 0; i < size; i++) {
Expression expr = expressions.get(i);
if (expr instanceof DeclarationExpression) {
declarations.add((DeclarationExpression) expr);
DeclarationExpression de = (DeclarationExpression) expr;
BinaryExpression be = new BinaryExpression(de.getLeftExpression(), de.getOperation(), de.getRightExpression());
expressions.set(i, be);
de.setRightExpression(ConstantExpression.NULL);
visitDeclarationExpression(de);
}
}
LinkedList instructions = new LinkedList();
BytecodeSequence seq = new BytecodeSequence(instructions);
BlockStatement bs = new BlockStatement();
bs.addStatement(seq);
Parameter closureIndex = new Parameter(ClassHelper.int_TYPE, "__closureIndex");
ClosureExpression ce = new ClosureExpression(new Parameter[] { closureIndex }, bs);
ce.setVariableScope(expression.getVariableScope());
// 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() {
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++) {
final Label label = new Label();
Object expr = expressions.get(i);
final boolean isStatement = expr instanceof Statement;
labels[i] = label;
instructions.add(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitLabel(label);
// so expressions need to pop the alibi null
if (!isStatement)
mv.visitInsn(POP);
}
});
instructions.add(expr);
instructions.add(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitJumpInsn(GOTO, tableEnd);
}
});
}
// default case
{
instructions.add(new BytecodeInstruction() {
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() {
public void visit(MethodVisitor mv) {
mv.visitLabel(tableEnd);
mv.visitInsn(ARETURN);
}
});
// load main Closure
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++) {
// 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();
}
Aggregations