use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class EnumCompletionVisitor method transformConstructor.
/**
* If constructor does not define a call to super, then transform constructor
* to get String,int parameters at beginning and add call super(String,int).
*/
private void transformConstructor(final ConstructorNode ctor) {
boolean chainedThisConstructorCall = false;
ConstructorCallExpression cce = null;
if (ctor.firstStatementIsSpecialConstructorCall()) {
Statement code = ctor.getFirstStatement();
cce = (ConstructorCallExpression) ((ExpressionStatement) code).getExpression();
if (cce.isSuperCall())
return;
// must be call to this(...)
chainedThisConstructorCall = true;
}
// we need to add parameters
Parameter[] oldP = ctor.getParameters();
Parameter[] newP = new Parameter[oldP.length + 2];
String stringParameterName = getUniqueVariableName("__str", ctor.getCode());
newP[0] = new Parameter(ClassHelper.STRING_TYPE, stringParameterName);
String intParameterName = getUniqueVariableName("__int", ctor.getCode());
newP[1] = new Parameter(ClassHelper.int_TYPE, intParameterName);
System.arraycopy(oldP, 0, newP, 2, oldP.length);
ctor.setParameters(newP);
VariableExpression stringVariable = new VariableExpression(newP[0]);
VariableExpression intVariable = new VariableExpression(newP[1]);
if (chainedThisConstructorCall) {
TupleExpression args = (TupleExpression) cce.getArguments();
List<Expression> argsExprs = args.getExpressions();
argsExprs.add(0, stringVariable);
argsExprs.add(1, intVariable);
} else {
// add a super call
List<Expression> args = new ArrayList<>();
args.add(stringVariable);
args.add(intVariable);
if (EnumVisitor.isAnonymousInnerClass(ctor.getDeclaringClass())) {
for (Parameter parameter : oldP) {
args.add(new VariableExpression(parameter));
}
ClassNode enumClass = ctor.getDeclaringClass().getSuperClass();
// GROOVY-6747: bridge enum's private constructor
makeBridgeConstructor(enumClass, newP);
args.add(new CastExpression(enumClass.getPlainNodeReference(), ConstantExpression.NULL));
}
cce = new ConstructorCallExpression(ClassNode.SUPER, new ArgumentListExpression(args));
BlockStatement code = new BlockStatement();
code.addStatement(new ExpressionStatement(cce));
Statement oldCode = ctor.getCode();
if (oldCode != null)
code.addStatement(oldCode);
ctor.setCode(code);
}
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class InnerClassVisitor method visitConstructorCallExpression.
@Override
public void visitConstructorCallExpression(ConstructorCallExpression call) {
super.visitConstructorCallExpression(call);
if (!call.isUsingAnonymousInnerClass()) {
passThisReference(call);
return;
}
InnerClassNode innerClass = (InnerClassNode) call.getType();
ClassNode outerClass = innerClass.getOuterClass();
ClassNode superClass = innerClass.getSuperClass();
if (!superClass.isInterface() && superClass.getOuterClass() != null && !(superClass.isStaticClass() || (superClass.getModifiers() & ACC_STATIC) != 0)) {
insertThis0ToSuperCall(call, innerClass);
}
if (!innerClass.getDeclaredConstructors().isEmpty())
return;
if ((innerClass.getModifiers() & ACC_STATIC) != 0)
return;
VariableScope scope = innerClass.getVariableScope();
if (scope == null)
return;
boolean isStatic = !inClosure && isStatic(innerClass, scope, call);
// expressions = constructor call arguments
List<Expression> expressions = ((TupleExpression) call.getArguments()).getExpressions();
// block = init code for the constructor we produce
BlockStatement block = new BlockStatement();
// parameters = parameters of the constructor
int additionalParamCount = (isStatic ? 0 : 1) + scope.getReferencedLocalVariablesCount();
List<Parameter> parameters = new ArrayList<>(expressions.size() + additionalParamCount);
// superCallArguments = arguments for the super call == the constructor call arguments
List<Expression> superCallArguments = new ArrayList<>(expressions.size());
// first we add a super() call for all expressions given in the constructor call expression
for (int i = 0, n = expressions.size(); i < n; i += 1) {
// add one parameter for each expression in the constructor call
Parameter param = new Parameter(ClassHelper.OBJECT_TYPE, "p" + additionalParamCount + i);
parameters.add(param);
// add the corresponding argument to the super constructor call
superCallArguments.add(new VariableExpression(param));
}
// add the super call
ConstructorCallExpression cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression(superCallArguments));
block.addStatement(new ExpressionStatement(cce));
int pCount = 0;
if (!isStatic) {
// need to pass "this" to access unknown methods/properties
ClassNode enclosingType = (inClosure ? ClassHelper.CLOSURE_TYPE : outerClass).getPlainNodeReference();
expressions.add(pCount, new VariableExpression("this", enclosingType));
Parameter thisParameter = new Parameter(enclosingType, "p" + pCount);
parameters.add(pCount++, thisParameter);
// "this" reference is saved in a field named "this$0"
FieldNode thisField = innerClass.addField("this$0", ACC_FINAL | ACC_SYNTHETIC, enclosingType, null);
addFieldInit(thisParameter, thisField, block);
}
// for each shared variable, add a Reference field
for (Iterator<Variable> it = scope.getReferencedLocalVariablesIterator(); it.hasNext(); ) {
Variable var = it.next();
VariableExpression ve = new VariableExpression(var);
ve.setClosureSharedVariable(true);
ve.setUseReferenceDirectly(true);
expressions.add(pCount, ve);
ClassNode referenceType = ClassHelper.REFERENCE_TYPE.getPlainNodeReference();
Parameter p = new Parameter(referenceType, "p" + pCount);
p.setOriginType(var.getOriginType());
parameters.add(pCount++, p);
VariableExpression initial = new VariableExpression(p);
initial.setSynthetic(true);
initial.setUseReferenceDirectly(true);
FieldNode pField = innerClass.addFieldFirst(ve.getName(), ACC_PUBLIC | ACC_SYNTHETIC, referenceType, initial);
pField.setHolder(true);
pField.setOriginType(ClassHelper.getWrapper(var.getOriginType()));
}
innerClass.addConstructor(ACC_SYNTHETIC, parameters.toArray(Parameter.EMPTY_ARRAY), ClassNode.EMPTY_ARRAY, block);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class InnerClassVisitor method passThisReference.
// this is the counterpart of addThisReference(). To non-static inner classes, outer this should be
// passed as the first argument implicitly.
private void passThisReference(final ConstructorCallExpression call) {
ClassNode cn = call.getType().redirect();
if (!shouldHandleImplicitThisForInnerClass(cn))
return;
boolean isInStaticContext;
if (currentMethod != null)
isInStaticContext = currentMethod.isStatic();
else if (currentField != null)
isInStaticContext = currentField.isStatic();
else
isInStaticContext = !processingObjInitStatements;
// GROOVY-10289
ClassNode enclosing = classNode;
while (!isInStaticContext && !enclosing.equals(cn.getOuterClass())) {
isInStaticContext = (enclosing.getModifiers() & ACC_STATIC) != 0;
// TODO: if enclosing is a local type, also test field or method
enclosing = enclosing.getOuterClass();
if (enclosing == null)
break;
}
if (isInStaticContext) {
// constructor call is in static context and the inner class is non-static - 1st arg is supposed to be
// passed as enclosing "this" instance
Expression args = call.getArguments();
if (args instanceof TupleExpression && ((TupleExpression) args).getExpressions().isEmpty()) {
addError("No enclosing instance passed in constructor call of a non-static inner class", call);
}
} else {
insertThis0ToSuperCall(call, cn);
}
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class StaticImportVisitor method transformMethodCallExpression.
protected Expression transformMethodCallExpression(MethodCallExpression mce) {
Expression object = transform(mce.getObjectExpression());
Expression method = transform(mce.getMethod());
Expression args = transform(mce.getArguments());
// GROOVY-10396: skip the instance method checks when the context is static with-respect-to current class
boolean staticWrtCurrent = inSpecialConstructorCall || currentMethod != null && currentMethod.isStatic();
if (mce.isImplicitThis()) {
String name = mce.getMethodAsString();
boolean thisOrSuperMethod = staticWrtCurrent ? hasPossibleStaticMethod(currentClass, name, args, true) : currentClass.tryFindPossibleMethod(name, args) != null;
if (!thisOrSuperMethod && currentClass.getOuterClasses().stream().noneMatch(oc -> oc.tryFindPossibleMethod(name, args) != null)) {
Expression result = findStaticMethodImportFromModule(method, args);
if (result != null) {
setSourcePosition(result, mce);
return result;
}
}
} else if (staticWrtCurrent && isSuperExpression(object)) {
Expression result = new MethodCallExpression(new ClassExpression(currentClass.getSuperClass()), method, args);
result.setSourcePosition(mce);
return result;
}
if (method instanceof ConstantExpression && ((ConstantExpression) method).getValue() instanceof String && (mce.isImplicitThis() || isThisOrSuper(object))) {
String methodName = (String) ((ConstantExpression) method).getValue();
boolean foundInstanceMethod = !staticWrtCurrent && currentClass.hasPossibleMethod(methodName, args);
Predicate<ClassNode> hasPossibleStaticMember = cn -> {
if (hasPossibleStaticMethod(cn, methodName, args, true)) {
return true;
}
// GROOVY-9587: don't check for property for non-empty call args
if (args instanceof TupleExpression && ((TupleExpression) args).getExpressions().isEmpty() && hasPossibleStaticProperty(cn, methodName)) {
return true;
}
return false;
};
if (mce.isImplicitThis()) {
if (isInnerClass(currentClass)) {
if (inSpecialConstructorCall && !foundInstanceMethod) {
// check for reference to outer class method in this(...) or super(...)
if (currentClass.getOuterClass().hasPossibleMethod(methodName, args)) {
object = new PropertyExpression(new ClassExpression(currentClass.getOuterClass()), new ConstantExpression("this"));
} else if (hasPossibleStaticMember.test(currentClass.getOuterClass())) {
Expression result = new StaticMethodCallExpression(currentClass.getOuterClass(), methodName, args);
result.setSourcePosition(mce);
return result;
}
}
} else if (inSpecialConstructorCall || (!inClosure && !foundInstanceMethod && !methodName.equals("call"))) {
// check for reference to static method in this(...) or super(...) or when call not resolved
if (hasPossibleStaticMember.test(currentClass)) {
Expression result = new StaticMethodCallExpression(currentClass, methodName, args);
result.setSourcePosition(mce);
return result;
}
}
}
}
MethodCallExpression result = new MethodCallExpression(object, method, args);
result.setGenericsTypes(mce.getGenericsTypes());
result.setMethodTarget(mce.getMethodTarget());
result.setImplicitThis(mce.isImplicitThis());
result.setSpreadSafe(mce.isSpreadSafe());
result.setSafe(mce.isSafe());
result.setSourcePosition(mce);
return result;
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class BinaryExpressionHelper method evaluateEqual.
public void evaluateEqual(final BinaryExpression expression, final boolean defineVariable) {
AsmClassGenerator acg = controller.getAcg();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Expression leftExpression = expression.getLeftExpression();
Expression rightExpression = expression.getRightExpression();
boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression);
if (directAssignment && rightExpression instanceof EmptyExpression) {
VariableExpression ve = (VariableExpression) leftExpression;
BytecodeVariable var = compileStack.defineVariable(ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false);
operandStack.loadOrStoreVariable(var, false);
return;
}
// evaluate the RHS and store the result
// TODO: LHS has not been visited, it could be a variable in a closure and type chooser is not aware.
ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
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) {
// TODO: lhsType?
loadInitValue(leftExpression.getType());
} else {
rightExpression.visit(acg);
}
ClassNode rhsType = operandStack.getTopOperand();
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()) && isNullConstant(rightExpression)) {
operandStack.doGroovyCast(var.getOriginType());
// these two are never reached in bytecode and only there
// to avoid verify errors and compiler infrastructure hazzle
operandStack.box();
operandStack.doGroovyCast(lhsType);
}
// normal type transformation
if (!ClassHelper.isPrimitiveType(lhsType) && isNullConstant(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 creating 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() == LEFT_SQUARE_BRACKET) {
assignToArray(expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader, leftBinExpr.isSafe());
}
compileStack.removeVar(rhsValueId);
return;
}
compileStack.pushLHS(true);
if (leftExpression instanceof TupleExpression) {
// multiple declaration
TupleExpression tuple = (TupleExpression) leftExpression;
int i = 0;
for (Expression e : tuple.getExpressions()) {
callX(rhsValueLoader, "getAt", args(constX(i++))).visit(acg);
if (defineVariable) {
Variable v = (Variable) e;
operandStack.doGroovyCast(v);
compileStack.defineVariable(v, true);
operandStack.remove(1);
} else {
e.visit(acg);
}
}
} else if (defineVariable) {
// single declaration
rhsValueLoader.visit(acg);
operandStack.remove(1);
compileStack.popLHS();
return;
} else {
// normal assignment
int mark = operandStack.getStackLength();
rhsValueLoader.visit(acg);
leftExpression.visit(acg);
operandStack.remove(operandStack.getStackLength() - mark);
}
compileStack.popLHS();
// return value of assignment
rhsValueLoader.visit(acg);
compileStack.removeVar(rhsValueId);
}
Aggregations