use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class AstBuilder method visitEnhancedArgumentListInPar.
@Override
public Expression visitEnhancedArgumentListInPar(final EnhancedArgumentListInParContext ctx) {
if (!asBoolean(ctx)) {
return null;
}
List<Expression> expressionList = new LinkedList<>();
List<MapEntryExpression> mapEntryExpressionList = new LinkedList<>();
ctx.enhancedArgumentListElement().stream().map(this::visitEnhancedArgumentListElement).forEach(e -> {
if (e instanceof MapEntryExpression) {
MapEntryExpression mapEntryExpression = (MapEntryExpression) e;
validateDuplicatedNamedParameter(mapEntryExpressionList, mapEntryExpression);
mapEntryExpressionList.add(mapEntryExpression);
} else {
expressionList.add(e);
}
});
if (!asBoolean(mapEntryExpressionList)) {
// e.g. arguments like 1, 2 OR someArg, e -> e
return configureAST(new ArgumentListExpression(expressionList), ctx);
}
if (!asBoolean(expressionList)) {
// e.g. arguments like x: 1, y: 2
return configureAST(new TupleExpression(configureAST(new NamedArgumentListExpression(mapEntryExpressionList), ctx)), ctx);
}
if (asBoolean(mapEntryExpressionList) && asBoolean(expressionList)) {
// e.g. arguments like x: 1, 'a', y: 2, 'b', z: 3
ArgumentListExpression argumentListExpression = new ArgumentListExpression(expressionList);
argumentListExpression.getExpressions().add(0, configureAST(new MapExpression(mapEntryExpressionList), ctx));
return configureAST(argumentListExpression, ctx);
}
throw createParsingFailedException("Unsupported argument list: " + ctx.getText(), ctx);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class StaticInvocationWriter method writeInvokeConstructor.
@Override
public void writeInvokeConstructor(final ConstructorCallExpression call) {
MethodNode mn = call.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
if (mn == null) {
super.writeInvokeConstructor(call);
return;
}
if (writeAICCall(call))
return;
ConstructorNode cn;
if (mn instanceof ConstructorNode) {
cn = (ConstructorNode) mn;
} else {
cn = new ConstructorNode(mn.getModifiers(), mn.getParameters(), mn.getExceptions(), mn.getCode());
cn.setDeclaringClass(mn.getDeclaringClass());
}
TupleExpression args = makeArgumentList(call.getArguments());
if (cn.isPrivate()) {
ClassNode classNode = controller.getClassNode();
ClassNode declaringClass = cn.getDeclaringClass();
if (declaringClass != classNode) {
MethodNode bridge = null;
if (call.getNodeMetaData(StaticTypesMarker.PV_METHODS_ACCESS) != null) {
Map<MethodNode, MethodNode> bridgeMethods = declaringClass.getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS);
bridge = bridgeMethods != null ? bridgeMethods.get(cn) : null;
}
if (bridge instanceof ConstructorNode) {
ArgumentListExpression newArgs = args(nullX());
for (Expression arg : args) {
newArgs.addExpression(arg);
}
cn = (ConstructorNode) bridge;
args = newArgs;
} else {
controller.getSourceUnit().addError(new SyntaxException("Cannot call private constructor for " + declaringClass.toString(false) + " from class " + classNode.toString(false), call));
}
}
}
String ownerDescriptor = prepareConstructorCall(cn);
int before = controller.getOperandStack().getStackLength();
loadArguments(args.getExpressions(), cn.getParameters());
finnishConstructorCall(cn, ownerDescriptor, controller.getOperandStack().getStackLength() - before);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class InvocationWriter method invokeClosure.
private void invokeClosure(final Expression arguments, final String methodName) {
AsmClassGenerator acg = controller.getAcg();
acg.visitVariableExpression(new VariableExpression(methodName));
controller.getOperandStack().box();
if (arguments instanceof TupleExpression) {
arguments.visit(acg);
} else {
new TupleExpression(arguments).visit(acg);
}
invokeClosureMethod.call(controller.getMethodVisitor());
controller.getOperandStack().replace(ClassHelper.OBJECT_TYPE);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class InvocationWriter method writeDirectMethodCall.
protected boolean writeDirectMethodCall(final MethodNode target, final boolean implicitThis, final Expression receiver, final TupleExpression args) {
if (target == null)
return false;
ClassNode declaringClass = target.getDeclaringClass();
ClassNode enclosingClass = controller.getClassNode(), receiverType = enclosingClass;
if (receiver != null) {
receiverType = controller.getTypeChooser().resolveType(receiver, enclosingClass);
if (target.isStatic() && isClassClassNodeWrappingConcreteType(receiverType)) {
receiverType = receiverType.getGenericsTypes()[0].getType();
}
}
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
MethodVisitor mv = controller.getMethodVisitor();
int startDepth = operandStack.getStackLength();
// handle receiver
if (!target.isStatic()) {
if (receiver != null) {
Expression objectExpression = receiver;
if (implicitThis && enclosingClass.getOuterClass() != null && !enclosingClass.isDerivedFrom(declaringClass) && !enclosingClass.implementsInterface(declaringClass)) {
// outer class method invocation
compileStack.pushImplicitThis(false);
if (!controller.isInGeneratedFunction() && isThis(receiver)) {
objectExpression = new PropertyExpression(new ClassExpression(declaringClass), "this");
}
} else {
compileStack.pushImplicitThis(implicitThis);
}
objectExpression.visit(controller.getAcg());
operandStack.doGroovyCast(declaringClass);
compileStack.popImplicitThis();
} else {
mv.visitIntInsn(ALOAD, 0);
operandStack.push(enclosingClass);
}
}
int opcode;
if (target.isStatic()) {
opcode = INVOKESTATIC;
} else if (isSuperExpression(receiver)) {
opcode = INVOKESPECIAL;
} else if (declaringClass.isInterface()) {
opcode = INVOKEINTERFACE;
} else {
opcode = INVOKEVIRTUAL;
}
ClassNode ownerClass = declaringClass;
if (opcode == INVOKESPECIAL) {
// GROOVY-8693, GROOVY-9909
if (!declaringClass.isInterface() || receiverType.implementsInterface(declaringClass))
ownerClass = receiverType;
} else if (opcode == INVOKEVIRTUAL && isObjectType(declaringClass)) {
// avoid using a narrowed type if the method is defined on Object, because it can interfere
// with delegate type inference in static compilation mode and trigger a ClassCastException
} else if (opcode == INVOKEVIRTUAL && !receiverType.isArray() && !receiverType.isInterface() && !isPrimitiveType(receiverType) && !receiverType.equals(declaringClass) && receiverType.isDerivedFrom(declaringClass)) {
// use actual for typical call
ownerClass = receiverType;
if (!receiverType.equals(operandStack.getTopOperand())) {
mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(ownerClass));
}
} else if ((declaringClass.getModifiers() & (ACC_FINAL | ACC_PUBLIC)) == 0 && !receiverType.equals(declaringClass) && (declaringClass.isInterface() ? receiverType.implementsInterface(declaringClass) : receiverType.isDerivedFrom(declaringClass))) {
// GROOVY-6962, GROOVY-9955, GROOVY-10380: method declared by inaccessible class or interface
if (declaringClass.isInterface() && !receiverType.isInterface())
opcode = INVOKEVIRTUAL;
ownerClass = receiverType;
}
loadArguments(args.getExpressions(), target.getParameters());
String ownerName = BytecodeHelper.getClassInternalName(ownerClass), methodName = target.getName();
String signature = BytecodeHelper.getMethodDescriptor(target.getReturnType(), target.getParameters());
mv.visitMethodInsn(opcode, ownerName, methodName, signature, ownerClass.isInterface());
ClassNode returnType = target.getReturnType();
if (isPrimitiveVoid(returnType)) {
returnType = ClassHelper.OBJECT_TYPE;
mv.visitInsn(ACONST_NULL);
}
// replace the method call's receiver and argument types with the return type
operandStack.replace(returnType, operandStack.getStackLength() - startDepth);
return true;
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class AsmClassGenerator method despreadList.
public void despreadList(final List<Expression> expressions, final boolean wrap) {
List<Expression> spreadIndexes = new ArrayList<>();
List<Expression> spreadExpressions = new ArrayList<>();
List<Expression> normalArguments = new ArrayList<>();
for (int i = 0, n = expressions.size(); i < n; i += 1) {
Expression expr = expressions.get(i);
if (!(expr instanceof SpreadExpression)) {
normalArguments.add(expr);
} else {
spreadIndexes.add(new ConstantExpression(i - spreadExpressions.size(), true));
spreadExpressions.add(((SpreadExpression) expr).getExpression());
}
}
// load normal arguments as array
visitTupleExpression(new ArgumentListExpression(normalArguments), wrap);
// load spread expressions as array
new TupleExpression(spreadExpressions).visit(this);
// load insertion index
new ArrayExpression(ClassHelper.int_TYPE, spreadIndexes, null).visit(this);
controller.getOperandStack().remove(1);
despreadList.call(controller.getMethodVisitor());
}
Aggregations