use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method transform.
public JCExpression transform(final Tree.BitwiseAssignmentOp op) {
final AssignmentOperatorTranslation operator = Operators.getAssignmentOperator(op.getClass());
if (operator == null) {
return makeErroneous(op, "compiler bug: " + op.getNodeType() + " is not a supported bitwise assignment operator");
}
Type valueType = op.getLeftTerm().getTypeModel();
final Type rightType = getSupertype(op.getRightTerm(), typeFact().getSetDeclaration());
return transformAssignAndReturnOperation(op, op.getLeftTerm(), false, valueType, valueType, new AssignAndReturnOperationFactory() {
@Override
public JCExpression getNewValue(JCExpression previousValue) {
JCExpression result = transformOverridableBinaryOperator(op, op.getLeftTerm(), op.getRightTerm(), rightType, operator.binaryOperator, OptimisationStrategy.NONE, previousValue, op.getTypeModel());
return result;
}
});
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method transformArgumentsForSimpleInvocation.
private List<ExpressionAndType> transformArgumentsForSimpleInvocation(SimpleInvocation invocation, CallBuilder callBuilder) {
final Constructor superConstructor = invocation.getConstructor();
CtorDelegation constructorDelegation;
if (invocation instanceof SuperInvocation) {
constructorDelegation = ((SuperInvocation) invocation).getDelegation();
} else {
constructorDelegation = null;
}
List<ExpressionAndType> result = List.<ExpressionAndType>nil();
if (!(invocation instanceof SuperInvocation) || !((SuperInvocation) invocation).isDelegationDelegation()) {
int numArguments = invocation.getNumArguments();
if (invocation.getNumParameters() == 0) {
// skip transforming arguments
// (Usually, numArguments would already be null, but it's possible to call a
// parameterless function with a *[] argument - see #1593.)
numArguments = 0;
}
boolean wrapIntoArray = false;
ListBuffer<JCExpression> arrayWrap = new ListBuffer<JCExpression>();
for (int argIndex = 0; argIndex < numArguments; argIndex++) {
BoxingStrategy boxingStrategy = invocation.getParameterBoxingStrategy(argIndex);
Type parameterType = invocation.getParameterType(argIndex);
// to avoid ambiguity of foo(1,2) for foo(int...) and foo(Object...) methods
if (!wrapIntoArray && invocation.isParameterJavaVariadic(argIndex) && boxingStrategy == BoxingStrategy.UNBOXED && willEraseToPrimitive(typeFact().getDefiniteType(parameterType)) && !invocation.isSpread())
wrapIntoArray = true;
ExpressionAndType exprAndType;
if (invocation.isArgumentSpread(argIndex)) {
if (!invocation.isParameterSequenced(argIndex)) {
result = transformSpreadTupleArgument(invocation, callBuilder, result, argIndex);
break;
}
if (invocation.isJavaVariadicMethod()) {
// if it's a java method we need a special wrapping
exprAndType = transformSpreadArgument(invocation, numArguments, argIndex, boxingStrategy, parameterType);
argIndex = numArguments;
} else {
Type argType = invocation.getArgumentType(argIndex);
if (argType.getSupertype(typeFact().getSequentialDeclaration()) != null) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
} else if (argType.getSupertype(typeFact().getIterableDeclaration()) != null) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
JCExpression sequential = iterableToSequential(exprAndType.expression);
if (invocation.isParameterVariadicPlus(argIndex)) {
Type iteratedType = typeFact().getIteratedType(argType);
sequential = utilInvocation().castSequentialToSequence(sequential, iteratedType);
}
exprAndType = new ExpressionAndType(sequential, exprAndType.type);
} else if (typeFact().isJavaArrayType(argType)) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
JCExpression iterable;
if (typeFact().isJavaPrimitiveArrayType(argType)) {
iterable = utilInvocation().toIterable(exprAndType.expression);
} else {
Type elementType = typeFact().getJavaArrayElementType(argType);
iterable = utilInvocation().toIterable(makeJavaType(elementType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(elementType), exprAndType.expression);
}
exprAndType = new ExpressionAndType(make().Apply(null, makeSelect(iterable, "sequence"), List.<JCExpression>nil()), makeJavaType(argType));
} else if (typeFact().isJavaIterableType(argType)) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
Type elementType = typeFact().getJavaIteratedType(argType);
JCExpression iterable = utilInvocation().toIterable(makeJavaType(elementType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(elementType), exprAndType.expression);
exprAndType = new ExpressionAndType(make().Apply(null, makeSelect(iterable, "sequence"), List.<JCExpression>nil()), makeJavaType(argType));
} else {
exprAndType = new ExpressionAndType(makeErroneous(invocation.getNode(), "compiler bug: unexpected spread argument"), makeErroneous(invocation.getNode(), "compiler bug: unexpected spread argument"));
}
}
} else if (!invocation.isParameterSequenced(argIndex) || // if it's sequenced, Java and there's no spread at all, pass it along
(invocation.isParameterJavaVariadic(argIndex) && !invocation.isSpread())) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
// This is not required for primitive arrays since they are not Object[]
if (numArguments == 1 && invocation.isIndirect()) {
Type argumentType = invocation.getArgumentType(0);
if (isJavaObjectArray(argumentType) || isNull(argumentType)) {
exprAndType = new ExpressionAndType(make().TypeCast(makeJavaType(typeFact().getObjectType()), exprAndType.expression), exprAndType.type);
}
} else if (invocation.isParameterJavaVariadic(argIndex) && !invocation.isSpread()) {
// in fact, the very same problem happens when passing null or object arrays to a java variadic method
Type argumentType = invocation.getArgumentType(argIndex);
if (isJavaObjectArray(argumentType) || isNull(argumentType)) {
// remove any ambiguity
exprAndType = new ExpressionAndType(make().TypeCast(makeJavaType(parameterType), exprAndType.expression), exprAndType.type);
}
}
} else {
// we must have a sequenced param
if (invocation.isSpread()) {
exprAndType = transformSpreadArgument(invocation, numArguments, argIndex, boxingStrategy, parameterType);
argIndex = numArguments;
} else {
exprAndType = transformVariadicArgument(invocation, numArguments, argIndex, parameterType);
argIndex = numArguments;
}
}
if (!wrapIntoArray) {
if (argIndex == 0 && invocation.isCallable() && !invocation.isArgumentSpread(numArguments - 1)) {
exprAndType = new ExpressionAndType(make().TypeCast(make().Type(syms().objectType), exprAndType.expression), make().Type(syms().objectType));
}
result = result.append(exprAndType);
} else {
arrayWrap.append(exprAndType.expression);
}
}
if (invocation.isIndirect() && invocation.getNumParameters() > numArguments && invocation.isParameterSequenced(numArguments) && !invocation.isArgumentSpread(numArguments - 1)) {
// Calling convention for indirect variadic invocation's requires
// explicit variadic argument (can't use the overloading trick)
result = result.append(new ExpressionAndType(makeEmptyAsSequential(true), make().Erroneous()));
}
if (wrapIntoArray) {
// must have at least one arg, so take the last one
Type parameterType = invocation.getParameterType(numArguments - 1);
JCExpression arrayType = makeJavaType(parameterType, JT_RAW);
JCNewArray arrayExpr = make().NewArray(arrayType, List.<JCExpression>nil(), arrayWrap.toList());
JCExpression arrayTypeExpr = make().TypeArray(makeJavaType(parameterType, JT_RAW));
result = result.append(new ExpressionAndType(arrayExpr, arrayTypeExpr));
}
} else {
for (Parameter p : constructorDelegation.getConstructor().getParameterList().getParameters()) {
result = result.append(new ExpressionAndType(naming.makeName(p.getModel(), Naming.NA_IDENT | Naming.NA_ALIASED), null));
}
}
boolean concreteDelegation = invocation instanceof SuperInvocation && ((SuperInvocation) invocation).getDelegation().isConcreteSelfDelegation();
if (superConstructor == null && concreteDelegation) {
Constructor delegateTo = ((SuperInvocation) invocation).getDelegation().getConstructor();
result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(delegateTo, true), naming.makeNamedConstructorType(delegateTo, true)));
} else if (superConstructor != null && constructorDelegation != null && constructorDelegation.isSelfDelegation()) {
result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(constructorDelegation.getExtendingConstructor(), concreteDelegation), naming.makeNamedConstructorType(constructorDelegation.getExtendingConstructor(), concreteDelegation)));
} else if (superConstructor != null && !Decl.isDefaultConstructor(superConstructor) && !Decl.isJavaArrayWith(superConstructor) && (invocation.getQmePrimary() instanceof Tree.QualifiedTypeExpression == false || !isCeylonCallable(((Tree.QualifiedTypeExpression) invocation.getQmePrimary()).getPrimary().getTypeModel()))) {
result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(superConstructor, concreteDelegation), naming.makeNamedConstructorType(superConstructor, concreteDelegation)));
}
return result;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method transformAssignAndReturnOperation.
private JCExpression transformAssignAndReturnOperation(Node operator, Tree.Term term, boolean boxResult, Type valueType, Type returnType, AssignAndReturnOperationFactory factory) {
List<JCVariableDecl> decls = List.nil();
List<JCStatement> stats = List.nil();
JCExpression result = null;
// (let $tmp = OP(attr); attr = $tmp; $tmp)
if (term instanceof Tree.BaseMemberExpression || (term instanceof Tree.IndexExpression) || // special case for java statics Foo.attr where Foo does not need to be evaluated
(term instanceof Tree.QualifiedMemberExpression && ((Tree.QualifiedMemberExpression) term).getStaticMethodReference())) {
JCExpression getter;
if (term instanceof Tree.BaseMemberExpression)
getter = transform((Tree.BaseMemberExpression) term, null);
else if (term instanceof Tree.IndexExpression)
getter = null;
else
getter = transformMemberExpression((Tree.QualifiedMemberExpression) term, null, null);
at(operator);
// Type $tmp = OP(attr);
JCExpression exprType = makeJavaType(returnType, boxResult ? JT_NO_PRIMITIVES : 0);
Name varName = naming.tempName("op");
// make sure we box the results if necessary
getter = applyErasureAndBoxing(getter, term, boxResult ? BoxingStrategy.BOXED : BoxingStrategy.UNBOXED, valueType);
JCExpression newValue = factory.getNewValue(getter);
// no need to box/unbox here since newValue and $tmpV share the same boxing type
JCVariableDecl tmpVar = make().VarDef(make().Modifiers(0), varName, exprType, newValue);
decls = decls.prepend(tmpVar);
// attr = $tmp
// make sure the result is unboxed if necessary, $tmp may be boxed
JCExpression value = make().Ident(varName);
BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(term);
value = applyErasureAndBoxing(value, returnType, boxResult, boxingStrategy, valueType);
JCExpression assignment = makeAssignment(operator, term, transformAssignmentLhs(operator, term), value);
stats = stats.prepend(at(operator).Exec(assignment));
// $tmp
// return, with the box type we asked for
result = make().Ident(varName);
} else if (term instanceof Tree.QualifiedMemberExpression) {
// e.attr
// (let $tmpE = e, $tmpV = OP($tmpE.attr); $tmpE.attr = $tmpV; $tmpV;)
Tree.QualifiedMemberExpression qualified = (Tree.QualifiedMemberExpression) term;
boolean isSuper = isSuperOrSuperOf(qualified.getPrimary());
// transform the primary, this will get us a boxed primary
JCExpression e = transformQualifiedMemberPrimary(qualified);
at(operator);
// Type $tmpE = e
JCExpression exprType = makeJavaType(qualified.getTarget().getQualifyingType(), JT_NO_PRIMITIVES);
Name varEName = naming.tempName("opE");
JCVariableDecl tmpEVar = make().VarDef(make().Modifiers(0), varEName, exprType, e);
// Type $tmpV = OP($tmpE.attr)
JCExpression attrType = makeJavaType(returnType, boxResult ? JT_NO_PRIMITIVES : 0);
Name varVName = naming.tempName("opV");
JCExpression getter = transformMemberExpression(qualified, isSuper ? transformSuper(qualified) : make().Ident(varEName), null);
// make sure we box the results if necessary
getter = applyErasureAndBoxing(getter, term, boxResult ? BoxingStrategy.BOXED : BoxingStrategy.UNBOXED, valueType);
JCExpression newValue = factory.getNewValue(getter);
// no need to box/unbox here since newValue and $tmpV share the same boxing type
JCVariableDecl tmpVVar = make().VarDef(make().Modifiers(0), varVName, attrType, newValue);
// define all the variables
decls = decls.prepend(tmpVVar);
if (!isSuper) {
decls = decls.prepend(tmpEVar);
}
// $tmpE.attr = $tmpV
// make sure $tmpV is unboxed if necessary
JCExpression value = make().Ident(varVName);
BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(term);
value = applyErasureAndBoxing(value, returnType, boxResult, boxingStrategy, valueType);
JCExpression assignment = makeAssignment(operator, term, qualifyLhs(operator, term, isSuper ? transformSuper(qualified) : make().Ident(varEName)), value);
stats = stats.prepend(at(operator).Exec(assignment));
// $tmpV
// return, with the box type we asked for
result = make().Ident(varVName);
} else {
return makeErroneous(operator, "compiler bug: " + term.getNodeType() + " is not a supported assign and return operator");
}
return make().LetExpr(decls, stats, result);
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method transform.
private List<JCAnnotation> transform(Object useSite, OutputElement target, Tree.AnnotationList annotationList, EnumSet<OutputElement> outputs) {
if (annotationList == null) {
return List.nil();
}
if ((gen().disableAnnotations & CeylonTransformer.DISABLE_USER_ANNOS) != 0) {
return List.nil();
}
LinkedHashMap<Class, ListBuffer<JCAnnotation>> annotationSet = new LinkedHashMap<>();
if (annotationList != null) {
if (annotationList.getAnonymousAnnotation() != null && AnnotationUtil.isNaturalTarget((Function) typeFact().getLanguageModuleDeclaration("doc"), useSite, target)) {
transformAnonymousAnnotation(annotationList.getAnonymousAnnotation(), annotationSet);
}
if (annotationList.getAnnotations() != null) {
for (Tree.Annotation annotation : annotationList.getAnnotations()) {
Function annoCtorDecl = ((Function) ((Tree.BaseMemberExpression) annotation.getPrimary()).getDeclaration());
if (annoCtorDecl != null) {
String aname = annoCtorDecl.getQualifiedNameString();
if ("java.lang::transient".equals(aname) || "java.lang::volatile".equals(aname) || "java.lang::synchronized".equals(aname) || "java.lang::native".equals(aname) || "java.lang::strictfp".equals(aname) || "java.lang::overloaded".equals(aname) || "java.lang::nonbean".equals(aname)) {
continue;
}
}
boolean isNaturalTarget = AnnotationUtil.isNaturalTarget(annoCtorDecl, useSite, target);
EnumSet<OutputElement> possibleTargets = AnnotationUtil.interopAnnotationTargeting(useSite instanceof Declaration ? isEe((Declaration) useSite) : false, outputs, annotation, false, false, useSite instanceof Declaration ? (Declaration) useSite : null);
if ((isNaturalTarget && possibleTargets == null) || (possibleTargets != null && possibleTargets.equals(EnumSet.of(target)))) {
transformAnnotation(annotation, annotationSet);
}
}
}
}
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
for (Class annotationClass : annotationSet.keySet()) {
ListBuffer<JCAnnotation> annotations = annotationSet.get(annotationClass);
if (isSequencedAnnotation(annotationClass)) {
JCAnnotation wrapperAnnotation = make().Annotation(makeJavaType(annotationClass.getType(), JT_ANNOTATIONS), List.<JCExpression>of(make().NewArray(null, null, upcastExprList(annotations.toList()))));
result.append(wrapperAnnotation);
} else if (isRepeatableAnnotation(annotationClass)) {
Interface containerAnnotation = getRepeatableContainer(annotationClass);
JCAnnotation wrapperAnnotation = make().Annotation(makeJavaType(containerAnnotation.appliedType(null, Collections.<Type>emptyList())), List.<JCExpression>of(make().NewArray(null, null, upcastExprList(annotations.toList()))));
result.append(wrapperAnnotation);
} else {
if (annotations.size() > 1) {
makeErroneous(annotationList, "compiler bug: multiple occurances of non-sequenced annotation class " + annotationClass.getQualifiedNameString());
}
result.appendList(annotations);
}
}
// Special case: Generate a @java.lang.Deprecated() if Ceylon deprecated
if (annotationList != null) {
for (Tree.Annotation annotation : annotationList.getAnnotations()) {
if (AnnotationUtil.isNaturalTarget((Function) typeFact().getLanguageModuleDeclaration("deprecated"), useSite, target) && isDeprecatedAnnotation(annotation.getPrimary()) && !(useSite instanceof Function) && !(useSite instanceof Constructor)) {
result.appendList(makeAtDeprecated());
}
}
}
return result.toList();
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method makePackageLiteralCall.
private JCExpression makePackageLiteralCall(Package pkg) {
// get the module
Module module = pkg.getModule();
JCExpression moduleCall = makeModuleLiteralCall(module);
// now get the package
return make().Apply(null, makeSelect(moduleCall, "findPackage"), List.<JCExpression>of(ceylonLiteral(pkg.getNameAsString())));
}
Aggregations