use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.
the class StaticTypesBinaryExpressionMultiTypeDispatcher method transformSpreadOnLHS.
private void transformSpreadOnLHS(final BinaryExpression expression) {
PropertyExpression spreadExpression = (PropertyExpression) expression.getLeftExpression();
Expression receiver = spreadExpression.getObjectExpression();
int counter = labelCounter.incrementAndGet();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
// create an empty arraylist
VariableExpression result = varX(this.getClass().getSimpleName() + "$spreadresult" + counter, ARRAYLIST_CLASSNODE);
ConstructorCallExpression newArrayList = ctorX(ARRAYLIST_CLASSNODE);
newArrayList.setNodeMetaData(DIRECT_METHOD_CALL_TARGET, ARRAYLIST_CONSTRUCTOR);
Expression decl = declX(result, newArrayList);
decl.visit(controller.getAcg());
// if (receiver != null)
receiver.visit(controller.getAcg());
Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
MethodVisitor mv = controller.getMethodVisitor();
mv.visitJumpInsn(IFNULL, ifnull);
// receiver consumed by if()
operandStack.remove(1);
Label nonull = compileStack.createLocalLabel("nonull_" + counter);
mv.visitLabel(nonull);
ClassNode componentType = inferLoopElementType(controller.getTypeChooser().resolveType(receiver, controller.getClassNode()));
Parameter iterator = new Parameter(componentType, "for$it$" + counter);
VariableExpression iteratorAsVar = varX(iterator);
PropertyExpression pexp = spreadExpression instanceof AttributeExpression ? new AttributeExpression(iteratorAsVar, spreadExpression.getProperty(), true) : new PropertyExpression(iteratorAsVar, spreadExpression.getProperty(), true);
pexp.setImplicitThis(spreadExpression.isImplicitThis());
pexp.setSourcePosition(spreadExpression);
BinaryExpression assignment = binX(pexp, expression.getOperation(), expression.getRightExpression());
MethodCallExpression add = callX(result, "add", assignment);
add.setMethodTarget(ARRAYLIST_ADD_METHOD);
// for (e in receiver) { result.add(e?.method(arguments) }
ForStatement stmt = new ForStatement(iterator, receiver, stmt(add));
stmt.visit(controller.getAcg());
// else { empty list }
mv.visitLabel(ifnull);
// end of if/else
// return result list
result.visit(controller.getAcg());
}
use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.
the class StaticImportVisitor method transform.
@Override
public Expression transform(Expression exp) {
if (exp == null)
return null;
Class<? extends Expression> clazz = exp.getClass();
if (clazz == VariableExpression.class) {
return transformVariableExpression((VariableExpression) exp);
}
if (clazz == BinaryExpression.class) {
return transformBinaryExpression((BinaryExpression) exp);
}
if (clazz == PropertyExpression.class) {
return transformPropertyExpression((PropertyExpression) exp);
}
if (clazz == MethodCallExpression.class) {
return transformMethodCallExpression((MethodCallExpression) exp);
}
if (exp instanceof ClosureExpression) {
return transformClosureExpression((ClosureExpression) exp);
}
if (clazz == ConstructorCallExpression.class) {
return transformConstructorCallExpression((ConstructorCallExpression) exp);
}
if (clazz == ArgumentListExpression.class) {
Expression result = exp.transformExpression(this);
if (foundArgs == null && inPropertyExpression) {
foundArgs = result;
}
return result;
}
if (exp instanceof ConstantExpression) {
Expression result = exp.transformExpression(this);
if (foundConstant == null && inPropertyExpression) {
foundConstant = result;
}
if (inAnnotation && exp instanceof AnnotationConstantExpression) {
ConstantExpression ce = (ConstantExpression) result;
if (ce.getValue() instanceof AnnotationNode) {
// replicate a little bit of AnnotationVisitor here
// because we can't wait until later to do this
AnnotationNode an = (AnnotationNode) ce.getValue();
Map<String, Expression> attributes = an.getMembers();
for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
Expression attrExpr = transform(entry.getValue());
entry.setValue(attrExpr);
}
}
}
return result;
}
return exp.transformExpression(this);
}
use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.
the class MarkupBuilderCodeTransformer method transform.
@Override
public Expression transform(final Expression exp) {
if (exp instanceof BinaryExpression) {
return transformBinaryExpression((BinaryExpression) exp);
}
if (exp instanceof MethodCallExpression) {
return transformMethodCall((MethodCallExpression) exp);
}
if (exp instanceof ClosureExpression) {
ClosureExpression cl = (ClosureExpression) exp;
cl.getCode().visit(this);
return cl;
}
if (exp instanceof VariableExpression) {
VariableExpression var = (VariableExpression) exp;
if (var.getAccessedVariable() instanceof DynamicVariable) {
MethodCallExpression callGetModel = new MethodCallExpression(new VariableExpression("this"), "getModel", ArgumentListExpression.EMPTY_ARGUMENTS);
callGetModel.setImplicitThis(true);
callGetModel.setSourcePosition(exp);
String varName = var.getName();
if ("model".equals(varName) || "unescaped".equals(varName)) {
return callGetModel;
}
MethodCallExpression mce = new MethodCallExpression(callGetModel, "get", new ArgumentListExpression(new ConstantExpression(varName)));
mce.setSourcePosition(exp);
mce.setImplicitThis(false);
MethodCallExpression yield = new MethodCallExpression(new VariableExpression("this"), "tryEscape", new ArgumentListExpression(mce));
yield.setImplicitThis(true);
yield.setSourcePosition(exp);
yield.putNodeMetaData(TARGET_VARIABLE, varName);
return autoEscape ? yield : mce;
}
}
return super.transform(exp);
}
use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.
the class NAryOperationRewriter method transformBinaryExpression.
private Expression transformBinaryExpression(final BinaryExpression exp) {
final int op = exp.getOperation().getType();
int token = TokenUtil.removeAssignment(op);
if (token == op) {
// no transform needed
return super.transform(exp);
}
BinaryExpression operation = new BinaryExpression(exp.getLeftExpression(), Token.newSymbol(token, -1, -1), exp.getRightExpression());
operation.setSourcePosition(exp);
BinaryExpression result = new BinaryExpression(exp.getLeftExpression(), Token.newSymbol(EQUAL, -1, -1), operation);
result.setSourcePosition(exp);
return result;
}
use of org.codehaus.groovy.ast.expr.BinaryExpression in project groovy by apache.
the class TraitComposer method applyTrait.
private static void applyTrait(final ClassNode trait, final ClassNode cNode, final TraitHelpersTuple helpers, SourceUnit unit) {
ClassNode helperClassNode = helpers.getHelper();
ClassNode fieldHelperClassNode = helpers.getFieldHelper();
ClassNode staticFieldHelperClassNode = helpers.getStaticFieldHelper();
Map<String, ClassNode> genericsSpec = GenericsUtils.createGenericsSpec(trait, GenericsUtils.createGenericsSpec(cNode));
for (MethodNode methodNode : helperClassNode.getAllDeclaredMethods()) {
String name = methodNode.getName();
Parameter[] helperMethodParams = methodNode.getParameters();
int nParams = helperMethodParams.length;
if (nParams > 0 && !methodNode.isAbstract() && ((methodNode.getModifiers() & Opcodes.ACC_STATIC) != 0) && (!name.contains("$") || (methodNode.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0)) {
ArgumentListExpression argList = new ArgumentListExpression();
argList.addExpression(new VariableExpression("this"));
Parameter[] origParams = new Parameter[nParams - 1];
Parameter[] params = new Parameter[nParams - 1];
System.arraycopy(methodNode.getParameters(), 1, params, 0, params.length);
MethodNode originalMethod = trait.getMethod(name, params);
Map<String, ClassNode> methodGenericsSpec = GenericsUtils.addMethodGenerics(Optional.ofNullable(originalMethod).orElse(methodNode), genericsSpec);
for (int i = 1; i < nParams; i += 1) {
Parameter parameter = helperMethodParams[i];
ClassNode originType = parameter.getOriginType();
ClassNode fixedType = correctToGenericsSpecRecurse(methodGenericsSpec, originType);
Parameter newParam = new Parameter(fixedType, parameter.getName());
List<AnnotationNode> copied = new LinkedList<>();
List<AnnotationNode> notCopied = new LinkedList<>();
GeneralUtils.copyAnnotatedNodeAnnotations(parameter, copied, notCopied);
newParam.addAnnotations(copied);
params[i - 1] = newParam;
origParams[i - 1] = parameter;
argList.addExpression(new VariableExpression(newParam));
}
createForwarderMethod(trait, cNode, methodNode, originalMethod, helperClassNode, methodGenericsSpec, helperMethodParams, origParams, params, argList, unit);
}
}
MethodCallExpression staticInitCall = new MethodCallExpression(new ClassExpression(helperClassNode), Traits.STATIC_INIT_METHOD, new ArgumentListExpression(new ClassExpression(cNode)));
MethodNode staticInitMethod = new MethodNode(Traits.STATIC_INIT_METHOD, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(ClassHelper.CLASS_Type, "clazz") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
staticInitMethod.setDeclaringClass(helperClassNode);
staticInitCall.setMethodTarget(staticInitMethod);
cNode.addStaticInitializerStatements(Collections.singletonList(new ExpressionStatement(staticInitCall)), false);
if (fieldHelperClassNode != null && !cNode.declaresInterface(fieldHelperClassNode)) {
// we should implement the field helper interface too
cNode.addInterface(fieldHelperClassNode);
// implementation of methods
List<MethodNode> declaredMethods = new LinkedList<>();
for (MethodNode declaredMethod : fieldHelperClassNode.getAllDeclaredMethods()) {
if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
declaredMethods.add(0, declaredMethod);
} else {
declaredMethods.add(declaredMethod);
}
}
if (staticFieldHelperClassNode != null) {
for (MethodNode declaredMethod : staticFieldHelperClassNode.getAllDeclaredMethods()) {
if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
declaredMethods.add(0, declaredMethod);
} else {
declaredMethods.add(declaredMethod);
}
}
}
for (MethodNode methodNode : declaredMethods) {
String fieldName = methodNode.getName();
if (fieldName.endsWith(Traits.DIRECT_GETTER_SUFFIX) || fieldName.endsWith(Traits.DIRECT_SETTER_SUFFIX)) {
int suffixIdx = fieldName.lastIndexOf('$');
fieldName = fieldName.substring(0, suffixIdx);
String operation = methodNode.getName().substring(suffixIdx + 1);
boolean getter = "get".equals(operation);
ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, methodNode.getReturnType());
int fieldMods = 0;
int isStatic = 0;
boolean publicField = true;
FieldNode helperField = null;
fieldMods = 0;
isStatic = 0;
// look first for field with encoded modifier information
for (Integer mod : Traits.FIELD_PREFIXES) {
helperField = fieldHelperClassNode.getField(String.format("$0x%04x", mod) + fieldName);
if (helperField != null) {
if ((mod & Opcodes.ACC_STATIC) != 0)
isStatic = Opcodes.ACC_STATIC;
fieldMods = fieldMods | mod;
break;
}
}
if (helperField == null) {
// look for possible legacy fields (trait compiled pre 2.4.8)
helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
if (helperField == null) {
publicField = false;
helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
}
if (helperField == null) {
publicField = true;
// try to find a static one
helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
if (helperField == null) {
publicField = false;
helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
}
fieldMods = fieldMods | Opcodes.ACC_STATIC;
isStatic = Opcodes.ACC_STATIC;
}
fieldMods = fieldMods | (publicField ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PRIVATE);
}
if (getter) {
// add field
if (helperField != null) {
List<AnnotationNode> copied = new LinkedList<>();
List<AnnotationNode> notCopied = new LinkedList<>();
GeneralUtils.copyAnnotatedNodeAnnotations(helperField, copied, notCopied);
FieldNode fieldNode = cNode.addField(fieldName, fieldMods, returnType, null);
fieldNode.addAnnotations(copied);
// so instead set within (static) initializer
if (fieldNode.isFinal()) {
String baseName = fieldNode.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD;
StaticMethodCallExpression mce = callX(helperClassNode, baseName + fieldNode.getName(), args(varX("this")));
if (helperClassNode.hasPossibleStaticMethod(mce.getMethod(), mce.getArguments())) {
Statement stmt = stmt(assignX(varX(fieldNode.getName(), fieldNode.getType()), mce));
if (isStatic == 0) {
cNode.addObjectInitializerStatements(stmt);
} else {
List<Statement> staticStatements = new ArrayList<Statement>();
staticStatements.add(stmt);
cNode.addStaticInitializerStatements(staticStatements, true);
}
}
}
}
}
Parameter[] newParams;
if (getter) {
newParams = Parameter.EMPTY_ARRAY;
} else {
ClassNode originType = methodNode.getParameters()[0].getOriginType();
ClassNode fixedType = originType.isGenericsPlaceHolder() ? ClassHelper.OBJECT_TYPE : correctToGenericsSpecRecurse(genericsSpec, originType);
newParams = new Parameter[] { new Parameter(fixedType, "val") };
}
Expression fieldExpr = varX(cNode.getField(fieldName));
boolean finalSetter = !getter && (fieldMods & Opcodes.ACC_FINAL) != 0;
Statement body = getter ? returnS(fieldExpr) : (finalSetter ? null : stmt(new BinaryExpression(fieldExpr, Token.newSymbol(Types.EQUAL, 0, 0), varX(newParams[0]))));
// add getter/setter even though setter not strictly needed for final fields
// but add empty body for setter for legacy compatibility
MethodNode impl = new MethodNode(methodNode.getName(), Opcodes.ACC_PUBLIC | isStatic, returnType, newParams, ClassNode.EMPTY_ARRAY, body);
AnnotationNode an = new AnnotationNode(COMPILESTATIC_CLASSNODE);
impl.addAnnotation(an);
cNode.addTransform(StaticCompileTransformation.class, an);
cNode.addMethod(impl);
}
}
}
cNode.addObjectInitializerStatements(new ExpressionStatement(new MethodCallExpression(new ClassExpression(helperClassNode), Traits.INIT_METHOD, new ArgumentListExpression(new VariableExpression("this")))));
}
Aggregations