use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class StaticInvocationWriter method loadArguments.
@Override
protected void loadArguments(final List<Expression> argumentList, final Parameter[] parameters) {
final int nArgs = argumentList.size(), nPrms = parameters.length;
if (nPrms == 0)
return;
ClassNode classNode = controller.getClassNode();
TypeChooser typeChooser = controller.getTypeChooser();
ClassNode lastArgType = nArgs == 0 ? null : typeChooser.resolveType(argumentList.get(nArgs - 1), classNode);
ClassNode lastPrmType = parameters[nPrms - 1].getOriginType();
// target is variadic and args are too many or one short or just enough with array compatibility
if (lastPrmType.isArray() && (nArgs > nPrms || nArgs == nPrms - 1 || (nArgs == nPrms && !lastArgType.isArray() && (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(lastArgType, lastPrmType.getComponentType()) || isGStringType(lastArgType) && isStringType(lastPrmType.getComponentType()))))) {
OperandStack operandStack = controller.getOperandStack();
int stackLength = operandStack.getStackLength() + nArgs;
// first arguments/parameters as usual
for (int i = 0; i < nPrms - 1; i += 1) {
visitArgument(argumentList.get(i), parameters[i].getType());
}
// wrap remaining arguments in an array for last parameter
List<Expression> lastArgs = new ArrayList<>();
for (int i = nPrms - 1; i < nArgs; i += 1) {
lastArgs.add(argumentList.get(i));
}
ArrayExpression array = new ArrayExpression(lastPrmType.getComponentType(), lastArgs);
array.visit(controller.getAcg());
// adjust stack length
while (operandStack.getStackLength() < stackLength) {
operandStack.push(ClassHelper.OBJECT_TYPE);
}
if (nArgs == nPrms - 1) {
operandStack.remove(1);
}
} else if (nArgs == nPrms) {
for (int i = 0; i < nArgs; i += 1) {
visitArgument(argumentList.get(i), parameters[i].getType());
}
} else {
// call with default arguments
Expression[] arguments = new Expression[nPrms];
for (int i = 0, j = 0; i < nPrms; i += 1) {
Parameter p = parameters[i];
ClassNode pType = p.getType();
Expression a = (j < nArgs ? argumentList.get(j) : null);
ClassNode aType = (a == null ? null : typeChooser.resolveType(a, classNode));
// default argument
Expression expression = getInitialExpression(p);
if (expression != null && !isCompatibleArgumentType(aType, pType)) {
arguments[i] = expression;
} else if (a != null) {
arguments[i] = a;
j += 1;
} else {
controller.getSourceUnit().addFatalError("Binding failed" + " for arguments [" + argumentList.stream().map(arg -> typeChooser.resolveType(arg, classNode).toString(false)).collect(Collectors.joining(", ")) + "]" + " and parameters [" + Arrays.stream(parameters).map(prm -> prm.getType().toString(false)).collect(Collectors.joining(", ")) + "]", getCurrentCall());
}
}
for (int i = 0; i < nArgs; i += 1) {
visitArgument(arguments[i], parameters[i].getType());
}
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class InvocationWriter method writeAICCall.
protected boolean writeAICCall(final ConstructorCallExpression call) {
if (!call.isUsingAnonymousInnerClass())
return false;
ConstructorNode cn = call.getType().getDeclaredConstructors().get(0);
OperandStack os = controller.getOperandStack();
String ownerDescriptor = prepareConstructorCall(cn);
List<Expression> args = makeArgumentList(call.getArguments()).getExpressions();
Parameter[] params = cn.getParameters();
// if a this appears as parameter here, then it should be
// not static, unless we are in a static method. But since
// ACG#visitVariableExpression does the opposite for this case, we
// push here an explicit this. This should not have any negative effect
// sine visiting a method call or property with implicit this will push
// a new value for this again.
controller.getCompileStack().pushImplicitThis(true);
for (int i = 0, n = params.length; i < n; i += 1) {
Parameter p = params[i];
Expression arg = args.get(i);
if (arg instanceof VariableExpression) {
VariableExpression var = (VariableExpression) arg;
loadVariableWithReference(var);
} else {
arg.visit(controller.getAcg());
}
os.doGroovyCast(p.getType());
}
controller.getCompileStack().popImplicitThis();
finnishConstructorCall(cn, ownerDescriptor, args.size());
return true;
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class MopWriter method visitMopMethodList.
/**
* Filters a list of method for MOP methods. For all methods that are not
* MOP methods a MOP method is created if the method is not public and the
* call would be a call on "this" (isThis == true). If the call is not on
* "this", then the call is a call on "super" and all methods are used,
* unless they are already a MOP method.
*
* @param methods unfiltered list of methods for MOP
* @param isThis if true, then we are creating a MOP method on "this", "super" else
*
* @see #generateMopCalls(LinkedList, boolean)
*/
private void visitMopMethodList(final Iterable<MethodNode> methods, final boolean isThis, final Set<MopKey> onlyIfThis, final List<String> orThis) {
LinkedList<MethodNode> list = new LinkedList<>();
Map<MopKey, MethodNode> map = new HashMap<>();
for (MethodNode mn : methods) {
// to the target methods; such a method cannot be abstract or a bridge
if ((mn.getModifiers() & (ACC_ABSTRACT | ACC_BRIDGE | ACC_STATIC)) != 0)
continue;
// --> results in XOR
if (isThis ^ mn.isPrivate())
continue;
String methodName = mn.getName();
Parameter[] parameters = mn.getParameters();
if (isMopMethod(methodName)) {
map.put(new MopKey(methodName, parameters), mn);
} else if (!methodName.startsWith("<") && (onlyIfThis.contains(new MopKey(methodName, parameters)) || orThis.contains(methodName))) {
if (map.put(new MopKey(getMopMethodName(mn, isThis), parameters), mn) == null) {
list.add(mn);
}
}
}
generateMopCalls(list, isThis);
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
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 methods list of methods a MOP call method should be generated for
* @param useThis indicates if "this" should be used for the name and call
*/
protected void generateMopCalls(final LinkedList<MethodNode> methods, final boolean useThis) {
for (MethodNode method : methods) {
ClassNode returnType = method.getReturnType();
Parameter[] parameters = method.getParameters();
String mopName = getMopMethodName(method, useThis);
String signature = BytecodeHelper.getMethodDescriptor(returnType, parameters);
MethodVisitor mv = controller.getClassVisitor().visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, mopName, signature, null, null);
controller.setMethodVisitor(mv);
int stackIndex = 0;
// load "this" and the parameters
mv.visitVarInsn(ALOAD, stackIndex++);
OperandStack operandStack = controller.getOperandStack();
for (Parameter parameter : parameters) {
ClassNode type = parameter.getType();
operandStack.load(type, stackIndex++);
if (isPrimitiveLong(type) || isPrimitiveDouble(type))
// long and double use two slots
stackIndex += 1;
}
operandStack.remove(parameters.length);
// make call to this or super method with operands
ClassNode receiverType = controller.getThisType();
if (!useThis) {
receiverType = receiverType.getSuperClass();
ClassNode declaringType = method.getDeclaringClass();
// GROOVY-8693, GROOVY-9909, et al.: method from interface not implemented by super class
if (declaringType.isInterface() && !receiverType.implementsInterface(declaringType))
receiverType = declaringType;
}
mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(receiverType), method.getName(), signature, receiverType.isInterface());
BytecodeHelper.doReturn(mv, returnType);
mv.visitMaxs(0, 0);
mv.visitEnd();
controller.getClassNode().addMethod(mopName, ACC_PUBLIC | ACC_SYNTHETIC, returnType, parameters, null, null);
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy by apache.
the class AbstractFunctionalInterfaceWriter method createBootstrapMethodArguments.
default Object[] createBootstrapMethodArguments(String abstractMethodDesc, int insn, ClassNode methodOwnerClassNode, MethodNode methodNode, boolean serializable) {
Parameter[] parameters = methodNode.getNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE);
List<Object> argumentList = new LinkedList<>();
argumentList.add(Type.getType(abstractMethodDesc));
argumentList.add(new Handle(insn, BytecodeHelper.getClassInternalName(methodOwnerClassNode.getName()), methodNode.getName(), BytecodeHelper.getMethodDescriptor(methodNode), methodOwnerClassNode.isInterface()));
argumentList.add(Type.getType(BytecodeHelper.getMethodDescriptor(methodNode.getReturnType(), parameters)));
if (serializable) {
argumentList.add(5);
argumentList.add(0);
}
return argumentList.toArray();
}
Aggregations