use of org.eclipse.ceylon.model.typechecker.model.Constructor in project ceylon by eclipse.
the class ClassTransformer method makeMainForClass.
/**
* Makes a {@code main()} method which calls the given top-level method
* @param def
*/
private MethodDefinitionBuilder makeMainForClass(ClassOrInterface model) {
at(null);
List<JCExpression> arguments = List.nil();
if (model.isAlias()) {
TypeDeclaration constr = ((ClassAlias) model).getConstructor();
if (constr instanceof Constructor) {
// must pass the constructor name arg
arguments = List.of(naming.makeNamedConstructorName((Constructor) constr, false));
}
model = (ClassOrInterface) model.getExtendedType().getDeclaration();
}
JCExpression nameId = makeJavaType(model.getType(), JT_RAW);
arguments = makeBottomReifiedTypeParameters(model.getTypeParameters(), arguments);
JCNewClass expr = make().NewClass(null, null, nameId, arguments, null);
return makeMainMethod(model, expr);
}
use of org.eclipse.ceylon.model.typechecker.model.Constructor in project ceylon by eclipse.
the class ExpressionTransformer method appendDeclarationLiteralForAnnotation.
/**
* Appends into the given builder a String representation of the given
* declaration, suitable for parsing my the DeclarationParser.
*/
private static void appendDeclarationLiteralForAnnotation(Declaration decl, StringBuilder sb) {
Scope container = decl.getContainer();
while (true) {
if (container instanceof Declaration) {
appendDeclarationLiteralForAnnotation((Declaration) container, sb);
sb.append(".");
break;
} else if (container instanceof Package) {
appendDeclarationLiteralForAnnotation((Package) container, sb);
sb.append(":");
break;
}
container = container.getContainer();
}
if (decl instanceof Class) {
sb.append("C").append(decl.getName());
} else if (decl instanceof Interface) {
sb.append("I").append(decl.getName());
} else if (decl instanceof TypeAlias) {
sb.append("A").append(decl.getName());
} else if (decl instanceof Value) {
sb.append("V").append(decl.getName());
} else if (decl instanceof Function) {
sb.append("F").append(decl.getName());
} else if (decl instanceof TypeParameter) {
sb.append("P").append(decl.getName());
} else if (decl instanceof Constructor) {
sb.append("c").append(decl.getName());
} else {
throw BugException.unhandledDeclarationCase(decl);
}
}
use of org.eclipse.ceylon.model.typechecker.model.Constructor in project ceylon by eclipse.
the class ExpressionTransformer method transform.
public JCTree transform(Tree.TypeLiteral expr) {
at(expr);
if (!expr.getWantsDeclaration()) {
if (expr.getDeclaration() instanceof Constructor) {
JCExpression classLiteral = makeTypeLiteralCall(expr.getType().getTypeModel().getQualifyingType(), false, expr.getTypeModel());
TypeDeclaration classModelDeclaration = (TypeDeclaration) typeFact().getLanguageModuleModelDeclaration(expr.getType().getTypeModel().getQualifyingType().getDeclaration().isMember() ? "MemberClass" : "Class");
JCTypeCast typeCast = make().TypeCast(makeJavaType(classModelDeclaration.appliedType(null, List.of(expr.getType().getTypeModel().getQualifyingType(), typeFact().getNothingType()))), classLiteral);
Type callableType = expr.getTypeModel().getFullType();
JCExpression reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
return make().Apply(null, naming.makeQualIdent(typeCast, "getConstructor"), List.<JCExpression>of(reifiedArgumentsExpr, make().Literal(expr.getDeclaration().getName())));
} else {
if (coerced) {
Type t = expr.getType().getTypeModel();
if (!typeFact().isJavaObjectArrayType(t) || t.getTypeArgumentList().get(0).isClassOrInterface()) {
return makeSelect(makeJavaType(t, JT_NO_PRIMITIVES | JT_RAW), "class");
}
}
return makeTypeLiteralCall(expr.getType().getTypeModel(), true, expr.getTypeModel());
}
} else if (expr.getDeclaration() instanceof TypeParameter) {
// we must get it from its container
TypeParameter declaration = (TypeParameter) expr.getDeclaration();
Node node = expr;
return makeTypeParameterDeclaration(node, declaration);
} else if (expr.getDeclaration() instanceof Constructor || expr instanceof Tree.NewLiteral) {
Constructor ctor;
if (expr.getDeclaration() instanceof Constructor) {
ctor = (Constructor) expr.getDeclaration();
} else {
ctor = ((Class) expr.getDeclaration()).getDefaultConstructor();
}
JCExpression metamodelCall = makeTypeDeclarationLiteral(ModelUtil.getConstructedClass(ctor));
metamodelCall = make().TypeCast(makeJavaType(typeFact().getClassDeclarationType(), JT_RAW), metamodelCall);
metamodelCall = make().Apply(null, naming.makeQualIdent(metamodelCall, "getConstructorDeclaration"), List.<JCExpression>of(make().Literal(ctor.getName() == null ? "" : ctor.getName())));
if (ModelUtil.isEnumeratedConstructor(ctor)) {
metamodelCall = make().TypeCast(makeJavaType(typeFact().getValueConstructorDeclarationType(), JT_RAW), metamodelCall);
} else /*else if (Decl.isDefaultConstructor(ctor)){
metamodelCall = make().TypeCast(
makeJavaType(typeFact().getDefaultConstructorDeclarationType(), JT_RAW), metamodelCall);
} */
{
metamodelCall = make().TypeCast(makeJavaType(typeFact().getCallableConstructorDeclarationType(), JT_RAW), metamodelCall);
}
return metamodelCall;
} else if (expr.getDeclaration() instanceof ClassOrInterface || expr.getDeclaration() instanceof TypeAlias) {
// use the generated class to get to the declaration literal
JCExpression metamodelCall = makeTypeDeclarationLiteral((TypeDeclaration) expr.getDeclaration());
Type exprType = expr.getTypeModel().resolveAliases();
// now cast if required
if (!exprType.isExactly(((TypeDeclaration) typeFact().getLanguageModuleDeclarationDeclaration("NestableDeclaration")).getType())) {
JCExpression type = makeJavaType(exprType, JT_NO_PRIMITIVES);
return make().TypeCast(type, metamodelCall);
}
return metamodelCall;
} else {
return makeErroneous(expr, "compiler bug: " + expr.getDeclaration() + " is an unsupported declaration type");
}
}
use of org.eclipse.ceylon.model.typechecker.model.Constructor in project ceylon by eclipse.
the class ExpressionTransformer method transformInvocation.
private JCExpression transformInvocation(Invocation invocation, CallBuilder callBuilder, TransformedInvocationPrimary transformedPrimary) {
invocation.location(callBuilder);
boolean needsCast = false;
if (Decl.isConstructorPrimary(invocation.getPrimary())) {
Tree.StaticMemberOrTypeExpression qte = (Tree.StaticMemberOrTypeExpression) invocation.getPrimary();
// instantiator
Constructor ctor = ModelUtil.getConstructor(qte.getDeclaration());
if (Strategy.generateInstantiator(ctor)) {
needsCast = Strategy.isInstantiatorUntyped(ctor);
if (qte instanceof Tree.QualifiedMemberExpression && ((Tree.QualifiedMemberExpression) qte).getPrimary() instanceof Tree.QualifiedTypeExpression && isCeylonCallable(getReturnTypeOfCallable(invocation.getPrimary().getTypeModel()))) {
callBuilder.invoke(naming.makeQualIdent(transformedPrimary.expr, "$call$"));
} else {
callBuilder.typeArguments(List.<JCExpression>nil());
java.util.List<Type> typeModels = qte.getTypeArguments().getTypeModels();
if (typeModels != null) {
for (Type tm : typeModels) {
callBuilder.typeArgument(makeJavaType(tm, AbstractTransformer.JT_TYPE_ARGUMENT));
}
}
callBuilder.invoke(naming.makeInstantiatorMethodName(transformedPrimary.expr, ModelUtil.getConstructedClass(ctor)));
}
} else if (typeFact().isJavaArrayType(ModelUtil.getConstructedClass(ctor).getType())) {
callBuilder.arrayWith(invocation.getReturnType().getQualifyingType(), makeJavaType(invocation.getReturnType(), JT_CLASS_NEW));
} else {
if (ModelUtil.getConstructedClass(invocation.getPrimaryDeclaration()).isMember() && invocation.getPrimary() instanceof Tree.QualifiedMemberOrTypeExpression && !(((Tree.QualifiedMemberOrTypeExpression) invocation.getPrimary()).getPrimary() instanceof Tree.BaseTypeExpression)) {
callBuilder.instantiate(new ExpressionAndType(transformedPrimary.expr, null), makeJavaType(invocation.getReturnType(), JT_CLASS_NEW | (transformedPrimary.expr == null ? 0 : JT_NON_QUALIFIED)));
} else {
callBuilder.instantiate(makeJavaType(invocation.getReturnType(), JT_CLASS_NEW));
}
}
} else if (invocation.getQmePrimary() != null && isJavaArray(invocation.getQmePrimary().getTypeModel()) && transformedPrimary.selector != null && (transformedPrimary.selector.equals("get") || transformedPrimary.selector.equals("set"))) {
if (transformedPrimary.selector.equals("get"))
callBuilder.arrayRead(transformedPrimary.expr);
else if (transformedPrimary.selector.equals("set")) {
callBuilder.arrayWrite(transformedPrimary.expr);
Type arrayType = invocation.getQmePrimary().getTypeModel().resolveAliases();
if (isJavaObjectArray(arrayType) && invocation instanceof PositionalInvocation) {
Type elementType = arrayType.getTypeArgumentList().get(0);
Type argumentType = ((PositionalInvocation) invocation).getArgumentType(1);
if (!argumentType.isSubtypeOf(typeFact().getOptionalType(elementType)))
callBuilder.javaArrayWriteNeedsCast(true);
}
} else
return makeErroneous(invocation.getNode(), "compiler bug: extraneous array selector: " + transformedPrimary.selector);
} else if (invocation.isUnknownArguments()) {
// if we have an unknown parameter list, like Callble<Ret,Args>, need to prepend the callable
// to the argument list, and invoke Util.apply
// note that ATM the typechecker only allows a single argument to be passed in spread form in this
// case so we don't need to look at parameter types
JCExpression callableTypeExpr = makeJavaType(invocation.getPrimary().getTypeModel());
ExpressionAndType callableArg = new ExpressionAndType(transformedPrimary.expr, callableTypeExpr);
Type returnType = invocation.getReturnType();
JCExpression returnTypeExpr = makeJavaType(returnType, JT_NO_PRIMITIVES);
callBuilder.prependArgumentAndType(callableArg);
callBuilder.typeArgument(returnTypeExpr);
callBuilder.invoke(make().Select(make().QualIdent(syms().ceylonUtilType.tsym), names().fromString("apply")));
} else if (invocation.isOnValueType()) {
JCExpression primTypeExpr = makeJavaType(invocation.getQmePrimary().getTypeModel(), JT_NO_PRIMITIVES | JT_VALUE_TYPE);
callBuilder.invoke(naming.makeQuotedQualIdent(primTypeExpr, transformedPrimary.selector));
} else {
callBuilder.invoke(naming.makeQuotedQualIdent(transformedPrimary.expr, transformedPrimary.selector));
}
JCExpression result = callBuilder.build();
if (needsCast) {
result = make().TypeCast(makeJavaType(invocation.getReturnType()), result);
}
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.Constructor 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;
}
Aggregations