use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticTypesClosureWriter method createDirectCallMethod.
private void createDirectCallMethod(final ClassNode closureClass, final MethodNode doCallMethod) {
// in case there is no "call" method on the closure, we can create a "fast invocation" paths
// to avoid going through ClosureMetaClass by call(Object...) method
// we can't have a specialized version of call(Object...) because the dispatch logic in ClosureMetaClass
// is too complex!
// call(Object)
Parameter args = new Parameter(ClassHelper.OBJECT_TYPE, "args");
MethodCallExpression doCall1arg = new MethodCallExpression(new VariableExpression("this", closureClass), "doCall", new ArgumentListExpression(new VariableExpression(args)));
doCall1arg.setImplicitThis(true);
doCall1arg.setMethodTarget(doCallMethod);
closureClass.addMethod(new MethodNode("call", Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE, new Parameter[] { args }, ClassNode.EMPTY_ARRAY, new ReturnStatement(doCall1arg)));
// call()
MethodCallExpression doCallNoArgs = new MethodCallExpression(new VariableExpression("this", closureClass), "doCall", new ArgumentListExpression(new ConstantExpression(null)));
doCallNoArgs.setImplicitThis(true);
doCallNoArgs.setMethodTarget(doCallMethod);
closureClass.addMethod(new MethodNode("call", Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(doCallNoArgs)));
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticTypesTypeChooser method resolveType.
@Override
public ClassNode resolveType(final Expression exp, final ClassNode current) {
ASTNode target = exp instanceof VariableExpression ? getTarget((VariableExpression) exp) : exp;
ClassNode inferredType = (ClassNode) target.getNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE);
if (inferredType == null) {
inferredType = (ClassNode) target.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
if (inferredType == null && target instanceof VariableExpression && ((VariableExpression) target).getAccessedVariable() instanceof Parameter) {
target = (Parameter) ((VariableExpression) target).getAccessedVariable();
inferredType = ((Parameter) target).getOriginType();
}
}
if (inferredType != null) {
if (ClassHelper.VOID_TYPE == inferredType) {
// we are in a case of a type inference failure, probably because code was generated
// it is better to avoid using this
inferredType = super.resolveType(exp, current);
}
return inferredType;
}
if (target instanceof VariableExpression && ((VariableExpression) target).isThisExpression()) {
// AsmClassGenerator may create "this" expressions that the type checker knows nothing about
return current;
}
return super.resolveType(exp, current);
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StatementWriter method writeTryCatchFinally.
public void writeTryCatchFinally(TryCatchStatement statement) {
controller.getAcg().onLineNumber(statement, "visitTryCatchFinally");
writeStatementLabel(statement);
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Statement tryStatement = statement.getTryStatement();
final Statement finallyStatement = statement.getFinallyStatement();
// start try block, label needed for exception table
Label tryStart = new Label();
mv.visitLabel(tryStart);
BlockRecorder tryBlock = makeBlockRecorder(finallyStatement);
tryBlock.startRange(tryStart);
tryStatement.visit(controller.getAcg());
// goto finally part
Label finallyStart = new Label();
mv.visitJumpInsn(GOTO, finallyStart);
Label tryEnd = new Label();
mv.visitLabel(tryEnd);
tryBlock.closeRange(tryEnd);
// pop for "makeBlockRecorder(finallyStatement)"
controller.getCompileStack().pop();
BlockRecorder catches = makeBlockRecorder(finallyStatement);
for (CatchStatement catchStatement : statement.getCatchStatements()) {
ClassNode exceptionType = catchStatement.getExceptionType();
String exceptionTypeInternalName = BytecodeHelper.getClassInternalName(exceptionType);
// start catch block, label needed for exception table
Label catchStart = new Label();
mv.visitLabel(catchStart);
catches.startRange(catchStart);
// create exception variable and store the exception
Parameter exceptionVariable = catchStatement.getVariable();
compileStack.pushState();
compileStack.defineVariable(exceptionVariable, true);
// handle catch body
catchStatement.visit(controller.getAcg());
// place holder to avoid problems with empty catch blocks
mv.visitInsn(NOP);
// pop for the variable
controller.getCompileStack().pop();
// end of catch
Label catchEnd = new Label();
mv.visitLabel(catchEnd);
catches.closeRange(catchEnd);
// goto finally start
mv.visitJumpInsn(GOTO, finallyStart);
compileStack.writeExceptionTable(tryBlock, catchStart, exceptionTypeInternalName);
}
// Label used to handle exceptions in catches and regularly
// visited finals.
Label catchAny = new Label();
// add "catch any" block to exception table for try part we do this
// after the exception blocks, because else this one would supersede
// any of those otherwise
compileStack.writeExceptionTable(tryBlock, catchAny, null);
// same for the catch parts
compileStack.writeExceptionTable(catches, catchAny, null);
// pop for "makeBlockRecorder(catches)"
compileStack.pop();
// start finally
mv.visitLabel(finallyStart);
finallyStatement.visit(controller.getAcg());
// **
mv.visitInsn(NOP);
// goto after all-catching block
Label skipCatchAll = new Label();
mv.visitJumpInsn(GOTO, skipCatchAll);
// start a block catching any Exception
mv.visitLabel(catchAny);
// store exception
// TODO: maybe define a Throwable and use it here instead of Object
operandStack.push(ClassHelper.OBJECT_TYPE);
int anyExceptionIndex = compileStack.defineTemporaryVariable("exception", true);
finallyStatement.visit(controller.getAcg());
// load the exception and rethrow it
mv.visitVarInsn(ALOAD, anyExceptionIndex);
mv.visitInsn(ATHROW);
mv.visitLabel(skipCatchAll);
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticTypesStatementWriter method writeForInLoop.
@Override
protected void writeForInLoop(final ForStatement loop) {
controller.getAcg().onLineNumber(loop, "visitForLoop");
writeStatementLabel(loop);
CompileStack compileStack = controller.getCompileStack();
MethodVisitor mv = controller.getMethodVisitor();
OperandStack operandStack = controller.getOperandStack();
compileStack.pushLoop(loop.getVariableScope(), loop.getStatementLabels());
// Identify type of collection
TypeChooser typeChooser = controller.getTypeChooser();
Expression collectionExpression = loop.getCollectionExpression();
ClassNode collectionType = typeChooser.resolveType(collectionExpression, controller.getClassNode());
Parameter loopVariable = loop.getVariable();
int size = operandStack.getStackLength();
if (collectionType.isArray() && loopVariable.getOriginType().equals(collectionType.getComponentType())) {
writeOptimizedForEachLoop(compileStack, operandStack, mv, loop, collectionExpression, collectionType, loopVariable);
} else if (ENUMERATION_CLASSNODE.equals(collectionType)) {
writeEnumerationBasedForEachLoop(compileStack, operandStack, mv, loop, collectionExpression, collectionType, loopVariable);
} else {
writeIteratorBasedForEachLoop(compileStack, operandStack, mv, loop, collectionExpression, collectionType, loopVariable);
}
operandStack.popDownTo(size);
compileStack.pop();
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class MopWriter method generateMopCalls.
/**
* generates a Meta Object Protocol method, that is used to call a non public
* method, or to make a call to super.
*
* @param mopCalls list of methods a mop call method should be generated for
* @param useThis true if "this" should be used for the naming
*/
protected void generateMopCalls(LinkedList<MethodNode> mopCalls, boolean useThis) {
for (MethodNode method : mopCalls) {
String name = getMopMethodName(method, useThis);
Parameter[] parameters = method.getParameters();
String methodDescriptor = BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameters());
MethodVisitor mv = controller.getClassVisitor().visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, name, methodDescriptor, null, null);
controller.setMethodVisitor(mv);
mv.visitVarInsn(ALOAD, 0);
int newRegister = 1;
OperandStack operandStack = controller.getOperandStack();
for (Parameter parameter : parameters) {
ClassNode type = parameter.getType();
operandStack.load(parameter.getType(), newRegister);
// increment to next register, double/long are using two places
newRegister++;
if (type == ClassHelper.double_TYPE || type == ClassHelper.long_TYPE)
newRegister++;
}
operandStack.remove(parameters.length);
ClassNode declaringClass = method.getDeclaringClass();
// JDK 8 support for default methods in interfaces
// this should probably be strenghtened when we support the A.super.foo() syntax
int opcode = declaringClass.isInterface() ? INVOKEINTERFACE : INVOKESPECIAL;
mv.visitMethodInsn(opcode, BytecodeHelper.getClassInternalName(declaringClass), method.getName(), methodDescriptor, opcode == INVOKEINTERFACE);
BytecodeHelper.doReturn(mv, method.getReturnType());
mv.visitMaxs(0, 0);
mv.visitEnd();
controller.getClassNode().addMethod(name, ACC_PUBLIC | ACC_SYNTHETIC, method.getReturnType(), parameters, null, null);
}
}
Aggregations