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