use of org.codehaus.groovy.ast.expr.MethodCallExpression in project groovy-core by groovy.
the class BinaryExpressionHelper method evaluateEqual.
public void evaluateEqual(BinaryExpression expression, boolean defineVariable) {
AsmClassGenerator acg = controller.getAcg();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Expression rightExpression = expression.getRightExpression();
Expression leftExpression = expression.getLeftExpression();
ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
if (defineVariable && rightExpression instanceof EmptyExpression && !(leftExpression instanceof TupleExpression)) {
VariableExpression ve = (VariableExpression) leftExpression;
BytecodeVariable var = compileStack.defineVariable(ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false);
operandStack.loadOrStoreVariable(var, false);
return;
}
// let's evaluate the RHS and store the result
ClassNode rhsType;
if (rightExpression instanceof ListExpression && lhsType.isArray()) {
ListExpression list = (ListExpression) rightExpression;
ArrayExpression array = new ArrayExpression(lhsType.getComponentType(), list.getExpressions());
array.setSourcePosition(list);
array.visit(acg);
} else if (rightExpression instanceof EmptyExpression) {
rhsType = leftExpression.getType();
loadInitValue(rhsType);
} else {
rightExpression.visit(acg);
}
rhsType = operandStack.getTopOperand();
boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression);
int rhsValueId;
if (directAssignment) {
VariableExpression var = (VariableExpression) leftExpression;
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(rhsType)) {
// GROOVY-5570: if a closure shared variable is a primitive type, it must be boxed
rhsType = ClassHelper.getWrapper(rhsType);
operandStack.box();
}
// form as it is closure shared
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && isNull(rightExpression)) {
operandStack.doGroovyCast(var.getOriginType());
// these two are never reached in bytecode and only there
// to avoid verifyerrors and compiler infrastructure hazzle
operandStack.box();
operandStack.doGroovyCast(lhsType);
}
// normal type transformation
if (!ClassHelper.isPrimitiveType(lhsType) && isNull(rightExpression)) {
operandStack.replace(lhsType);
} else {
operandStack.doGroovyCast(lhsType);
}
rhsType = lhsType;
rhsValueId = compileStack.defineVariable(var, lhsType, true).getIndex();
} else {
rhsValueId = compileStack.defineTemporaryVariable("$rhs", rhsType, true);
}
//TODO: if rhs is VariableSlotLoader already, then skip crating a new one
BytecodeExpression rhsValueLoader = new VariableSlotLoader(rhsType, rhsValueId, operandStack);
// assignment for subscript
if (leftExpression instanceof BinaryExpression) {
BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
if (leftBinExpr.getOperation().getType() == Types.LEFT_SQUARE_BRACKET) {
assignToArray(expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader);
}
compileStack.removeVar(rhsValueId);
return;
}
compileStack.pushLHS(true);
// multiple declaration
if (leftExpression instanceof TupleExpression) {
TupleExpression tuple = (TupleExpression) leftExpression;
int i = 0;
for (Expression e : tuple.getExpressions()) {
VariableExpression var = (VariableExpression) e;
MethodCallExpression call = new MethodCallExpression(rhsValueLoader, "getAt", new ArgumentListExpression(new ConstantExpression(i)));
call.visit(acg);
i++;
if (defineVariable) {
operandStack.doGroovyCast(var);
compileStack.defineVariable(var, true);
operandStack.remove(1);
} else {
acg.visitVariableExpression(var);
}
}
} else // single declaration
if (defineVariable) {
rhsValueLoader.visit(acg);
operandStack.remove(1);
compileStack.popLHS();
return;
} else // normal assignment
{
int mark = operandStack.getStackLength();
// to leave a copy of the rightExpression value on the stack after the assignment.
rhsValueLoader.visit(acg);
TypeChooser typeChooser = controller.getTypeChooser();
ClassNode targetType = typeChooser.resolveType(leftExpression, controller.getClassNode());
operandStack.doGroovyCast(targetType);
leftExpression.visit(acg);
operandStack.remove(operandStack.getStackLength() - mark);
}
compileStack.popLHS();
// return value of assignment
rhsValueLoader.visit(acg);
compileStack.removeVar(rhsValueId);
}
use of org.codehaus.groovy.ast.expr.MethodCallExpression in project grails-core by grails.
the class DelegateAsyncTransformation method applyDelegateAsyncTransform.
private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetApi, String fieldName) {
List<MethodNode> methods = targetApi.getAllDeclaredMethods();
ClassNode promisesClass = ClassHelper.make(Promises.class).getPlainNodeReference();
MethodNode createPromiseMethodTargetWithDecorators = promisesClass.getDeclaredMethod("createPromise", new Parameter[] { new Parameter(new ClassNode(Closure.class), "c"), new Parameter(new ClassNode(List.class), "c") });
DelegateAsyncTransactionalMethodTransformer delegateAsyncTransactionalMethodTransformer = lookupAsyncTransactionalMethodTransformer();
for (MethodNode m : methods) {
if (isCandidateMethod(m)) {
MethodNode existingMethod = classNode.getMethod(m.getName(), m.getParameters());
if (existingMethod == null) {
ClassNode promiseNode = ClassHelper.make(Promise.class).getPlainNodeReference();
ClassNode originalReturnType = m.getReturnType();
if (!originalReturnType.getNameWithoutPackage().equals(VOID)) {
ClassNode returnType;
if (ClassHelper.isPrimitiveType(originalReturnType.redirect())) {
returnType = ClassHelper.getWrapper(originalReturnType.redirect());
} else {
returnType = alignReturnType(classNode, originalReturnType);
}
if (!OBJECT_CLASS_NODE.equals(returnType)) {
promiseNode.setGenericsTypes(new GenericsType[] { new GenericsType(returnType) });
}
}
final BlockStatement methodBody = new BlockStatement();
final BlockStatement promiseBody = new BlockStatement();
final ClosureExpression closureExpression = new ClosureExpression(new Parameter[0], promiseBody);
VariableScope variableScope = new VariableScope();
closureExpression.setVariableScope(variableScope);
VariableExpression thisObject = new VariableExpression("this");
ClassNode delegateAsyncUtilsClassNode = new ClassNode(DelegateAsyncUtils.class);
MethodNode getPromiseDecoratorsMethodNode = delegateAsyncUtilsClassNode.getDeclaredMethods("getPromiseDecorators").get(0);
ListExpression promiseDecorators = new ListExpression();
ArgumentListExpression getPromiseDecoratorsArguments = new ArgumentListExpression(thisObject, promiseDecorators);
delegateAsyncTransactionalMethodTransformer.transformTransactionalMethod(classNode, targetApi, m, promiseDecorators);
MethodCallExpression getDecoratorsMethodCall = new MethodCallExpression(new ClassExpression(delegateAsyncUtilsClassNode), "getPromiseDecorators", getPromiseDecoratorsArguments);
getDecoratorsMethodCall.setMethodTarget(getPromiseDecoratorsMethodNode);
MethodCallExpression createPromiseWithDecorators = new MethodCallExpression(new ClassExpression(promisesClass), "createPromise", new ArgumentListExpression(closureExpression, getDecoratorsMethodCall));
if (createPromiseMethodTargetWithDecorators != null) {
createPromiseWithDecorators.setMethodTarget(createPromiseMethodTargetWithDecorators);
}
methodBody.addStatement(new ExpressionStatement(createPromiseWithDecorators));
final ArgumentListExpression arguments = new ArgumentListExpression();
Parameter[] parameters = copyParameters(StaticTypeCheckingSupport.parameterizeArguments(classNode, m));
for (Parameter p : parameters) {
p.setClosureSharedVariable(true);
variableScope.putReferencedLocalVariable(p);
VariableExpression ve = new VariableExpression(p);
ve.setClosureSharedVariable(true);
arguments.addExpression(ve);
}
MethodCallExpression delegateMethodCall = new MethodCallExpression(new VariableExpression(fieldName), m.getName(), arguments);
promiseBody.addStatement(new ExpressionStatement(delegateMethodCall));
MethodNode newMethodNode = new MethodNode(m.getName(), Modifier.PUBLIC, promiseNode, parameters, null, methodBody);
classNode.addMethod(newMethodNode);
}
}
}
}
use of org.codehaus.groovy.ast.expr.MethodCallExpression in project groovy-core by groovy.
the class StaticPropertyAccessHelper method transformToSetterCall.
public static Expression transformToSetterCall(Expression receiver, MethodNode setterMethod, final Expression arguments, boolean implicitThis, boolean safe, boolean spreadSafe, boolean requiresReturnValue, Expression location) {
if (requiresReturnValue) {
TemporaryVariableExpression tmp = new TemporaryVariableExpression(arguments);
PoppingMethodCallExpression call = new PoppingMethodCallExpression(receiver, setterMethod, tmp);
call.setImplicitThis(implicitThis);
call.setSafe(safe);
call.setSpreadSafe(spreadSafe);
call.setSourcePosition(location);
PoppingListOfExpressionsExpression result = new PoppingListOfExpressionsExpression(tmp, call);
result.setSourcePosition(location);
return result;
} else {
MethodCallExpression call = new MethodCallExpression(receiver, setterMethod.getName(), arguments);
call.setImplicitThis(implicitThis);
call.setSafe(safe);
call.setSpreadSafe(spreadSafe);
call.setMethodTarget(setterMethod);
call.setSourcePosition(location);
return call;
}
}
use of org.codehaus.groovy.ast.expr.MethodCallExpression 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.expr.MethodCallExpression in project groovy-core by groovy.
the class StaticTypesStatementWriter method writeIteratorBasedForEachLoop.
private void writeIteratorBasedForEachLoop(CompileStack compileStack, OperandStack operandStack, MethodVisitor mv, ForStatement loop, Expression collectionExpression, ClassNode collectionType, Parameter loopVariable) {
// Declare the loop counter.
BytecodeVariable variable = compileStack.defineVariable(loopVariable, false);
if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(collectionType, ITERABLE_CLASSNODE)) {
MethodCallExpression iterator = new MethodCallExpression(collectionExpression, "iterator", new ArgumentListExpression());
iterator.setMethodTarget(collectionType.getMethod("iterator", Parameter.EMPTY_ARRAY));
iterator.setImplicitThis(false);
iterator.visit(controller.getAcg());
} else {
collectionExpression.visit(controller.getAcg());
mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/DefaultGroovyMethods", "iterator", "(Ljava/lang/Object;)Ljava/util/Iterator;", false);
operandStack.replace(ClassHelper.Iterator_TYPE);
}
// Then get the iterator and generate the loop control
int iteratorIdx = compileStack.defineTemporaryVariable("iterator", ClassHelper.Iterator_TYPE, true);
Label continueLabel = compileStack.getContinueLabel();
Label breakLabel = compileStack.getBreakLabel();
mv.visitLabel(continueLabel);
mv.visitVarInsn(ALOAD, iteratorIdx);
writeIteratorHasNext(mv);
// note: ifeq tests for ==0, a boolean is 0 if it is false
mv.visitJumpInsn(IFEQ, breakLabel);
mv.visitVarInsn(ALOAD, iteratorIdx);
writeIteratorNext(mv);
operandStack.push(ClassHelper.OBJECT_TYPE);
operandStack.storeVar(variable);
// Generate the loop body
loop.getLoopBlock().visit(controller.getAcg());
mv.visitJumpInsn(GOTO, continueLabel);
mv.visitLabel(breakLabel);
}
Aggregations