use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformBaseInstantiation.
private JCExpression transformBaseInstantiation(Invocation invocation, CallBuilder callBuilder, TransformedInvocationPrimary transformedPrimary) {
JCExpression resultExpr;
Tree.BaseTypeExpression type = (Tree.BaseTypeExpression) invocation.getPrimary();
Declaration declaration = type.getDeclaration();
invocation.location(callBuilder);
if (Strategy.generateInstantiator(declaration)) {
resultExpr = callBuilder.typeArguments(List.<JCExpression>nil()).invoke(naming.makeInstantiatorMethodName(transformedPrimary.expr, (Class) declaration)).build();
if (Strategy.isInstantiatorUntyped(declaration)) {
// $new method declared to return Object, so needs typecast
resultExpr = make().TypeCast(makeJavaType(((TypeDeclaration) declaration).getType()), resultExpr);
}
} else {
Type classType = (Type) type.getTarget();
if (isJavaArray(classType)) {
JCExpression typeExpr = makeJavaType(classType, AbstractTransformer.JT_CLASS_NEW | AbstractTransformer.JT_RAW);
callBuilder.javaArrayInstance(typeExpr);
if (isJavaObjectArray(classType)) {
Type elementType = classType.getTypeArgumentList().get(0);
MultidimensionalArray multiArray = getMultiDimensionalArrayInfo(elementType);
if (multiArray != null)
elementType = multiArray.type;
// array of Foo is fine, array of Nothing too
if (elementType.getDeclaration() instanceof ClassOrInterface || elementType.isNothing()) {
if (!elementType.getTypeArgumentList().isEmpty())
callBuilder.javaArrayInstanceNeedsCast(makeJavaType(classType, AbstractTransformer.JT_NO_PRIMITIVES));
} else {
// if it's an array of union, intersection or type param we need a runtime allocation
callBuilder.javaArrayInstanceIsGeneric(makeReifiedTypeArgument(elementType), multiArray != null ? multiArray.dimension + 1 : 1);
}
}
} else {
if (Decl.isConstructor(classType.getDeclaration())) {
classType = classType.getExtendedType();
}
JCExpression typeExpr = makeJavaType(classType, AbstractTransformer.JT_CLASS_NEW);
callBuilder.instantiate(typeExpr);
}
resultExpr = callBuilder.build();
}
return resultExpr;
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transform.
// Prefix operator
public JCExpression transform(final Tree.PrefixOperatorExpression expr) {
final OperatorTranslation operator = Operators.getOperator(expr.getClass());
if (operator == null) {
return makeErroneous(expr, "compiler bug: " + expr.getNodeType() + " is not supported yet");
}
OptimisationStrategy optimisationStrategy = operator.getUnOpOptimisationStrategy(expr, expr.getTerm(), this);
final boolean canOptimise = optimisationStrategy.useJavaOperator();
Tree.Term term = expr.getTerm();
// only fully optimise if we don't have to access the getter/setter
if (canOptimise && CodegenUtil.isDirectAccessVariable(term)) {
JCExpression jcTerm = transformExpression(term, BoxingStrategy.UNBOXED, expr.getTypeModel(), EXPR_WIDEN_PRIM);
return at(expr).Unary(operator.javacOperator, jcTerm);
}
Interface compoundType = expr.getUnit().getOrdinalDeclaration();
Type valueType = getSupertype(term, compoundType);
final Type returnType = getMostPreciseType(term, getTypeArgument(valueType, 0));
// we work on boxed types unless we could have optimised
return transformAssignAndReturnOperation(expr, term, !canOptimise, valueType, returnType, new AssignAndReturnOperationFactory() {
@Override
public JCExpression getNewValue(JCExpression previousValue) {
// use +1/-1 if we can optimise a bit
if (canOptimise) {
JCExpression ret = make().Binary(operator == OperatorTranslation.UNARY_PREFIX_INCREMENT ? JCTree.PLUS : JCTree.MINUS, previousValue, makeInteger(1));
ret = unAutoPromote(ret, returnType);
return ret;
}
// make this call: previousValue.getSuccessor() or previousValue.getPredecessor()
return make().Apply(null, makeSelect(previousValue, operator.ceylonMethod), List.<JCExpression>nil());
}
});
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class ExpressionTransformer method getComparableType.
protected Type getComparableType(Tree.Term middleTerm) {
final Type middleSuper = getSupertype(middleTerm, typeFact().getComparableDeclaration());
Type middleType = middleSuper;
Type middleSelf = middleType.getDeclaration().getSelfType();
if (middleSelf != null) {
// Simplify Comparable<X> to X
middleType = middleType.getTypeArguments().get(middleSelf.getDeclaration());
}
return middleType;
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class ExpressionTransformer method makeTuple.
private JCExpression makeTuple(Type tupleType, java.util.List<Tree.PositionalArgument> expressions) {
if (typeFact().isEmptyType(tupleType)) {
// A tuple terminated by empty
return makeEmpty();
}
JCExpression tail = null;
List<JCExpression> elems = List.<JCExpression>nil();
for (int i = 0; i < expressions.size(); i++) {
Tree.PositionalArgument expr = expressions.get(i);
if (expr instanceof Tree.ListedArgument) {
JCExpression elem = transformExpression(((Tree.ListedArgument) expr).getExpression());
elems = elems.append(elem);
} else if (expr instanceof Tree.SpreadArgument) {
Tree.SpreadArgument spreadExpr = (Tree.SpreadArgument) expr;
// make sure we get a spread part of the right type
Type spreadType = spreadExpr.getExpression().getTypeModel();
Type sequentialSpreadType = null;
// try to get a Sequence
if (typeFact().isNonemptyIterableType(spreadType))
sequentialSpreadType = spreadType.getSupertype(typeFact().getSequenceDeclaration());
// failing that, try Sequential
if (sequentialSpreadType == null)
sequentialSpreadType = spreadType.getSupertype(typeFact().getSequentialDeclaration());
if (sequentialSpreadType != null) {
tail = transformExpression(spreadExpr.getExpression(), BoxingStrategy.BOXED, sequentialSpreadType);
} else {
// must at least be an Iterable then
Type iterableSpreadType = spreadType.getSupertype(typeFact().getIterableDeclaration());
tail = transformExpression(spreadExpr.getExpression(), BoxingStrategy.BOXED, iterableSpreadType);
tail = utilInvocation().sequentialOf(makeReifiedTypeArgument(typeFact().getIteratedType(iterableSpreadType)), tail);
Type elementType = typeFact().getIteratedType(spreadExpr.getTypeModel());
Type sequentialType = typeFact().getSequentialType(elementType);
Type expectedType = spreadExpr.getTypeModel();
if (typeFact().isNonemptyIterableType(spreadExpr.getTypeModel())) {
expectedType = typeFact().getSequenceType(elementType);
} else if (typeFact().isIterableType(spreadExpr.getTypeModel())) {
expectedType = typeFact().getSequentialType(elementType);
}
tail = sequentialEmptiness(tail, expectedType, sequentialType);
}
} else if (expr instanceof Tree.Comprehension) {
Tree.Comprehension comp = (Tree.Comprehension) expr;
Type elementType = expr.getTypeModel();
Type expectedType = comp.getInitialComprehensionClause().getPossiblyEmpty() ? typeFact().getSequentialType(elementType) : typeFact().getSequenceType(elementType);
tail = comprehensionAsSequential(comp, expectedType);
} else {
return makeErroneous(expr, "compiler bug: " + expr.getNodeType() + " is not a supported tuple argument");
}
}
if (!elems.isEmpty()) {
JCExpression reifiedTypeArg = makeReifiedTypeArgument(tupleType.getTypeArgumentList().get(0));
List<JCExpression> args = List.<JCExpression>of(reifiedTypeArg);
args = args.append(make().NewArray(make().Type(syms().objectType), List.<JCExpression>nil(), elems));
if (tail != null) {
args = args.append(tail);
}
JCExpression typeExpr = makeJavaType(tupleType, JT_TYPE_ARGUMENT);
/* Tuple.instance(reifiedElement, new Object[]{elem, elem, elem}, tail) */
return make().TypeCast(typeExpr, make().Apply(List.<JCExpression>nil(), naming.makeQualIdent(make().QualIdent(syms().ceylonTupleType.tsym), "instance"), args));
} else {
return tail;
}
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformComprehension.
JCExpression transformComprehension(Tree.Comprehension comp, Type expectedType) {
Type elementType = comp.getInitialComprehensionClause().getTypeModel();
// get rid of anonymous types
elementType = typeFact().denotableType(elementType);
elementType = wrapInOptionalForInterop(elementType, expectedType, containsUncheckedNulls(comp));
return new ComprehensionTransformation(comp, elementType).transformComprehension();
}
Aggregations