use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class AbstractTransformer method getSimpleNumParametersOfCallable.
private int getSimpleNumParametersOfCallable(Type args) {
// can be a defaulted tuple of Empty|Tuple
if (args.isUnion()) {
java.util.List<Type> caseTypes = args.getCaseTypes();
if (caseTypes == null || caseTypes.size() != 2)
return -1;
Type caseA = caseTypes.get(0);
TypeDeclaration caseADecl = caseA.getDeclaration();
Type caseB = caseTypes.get(1);
TypeDeclaration caseBDecl = caseB.getDeclaration();
if (caseADecl instanceof ClassOrInterface == false || caseBDecl instanceof ClassOrInterface == false)
return -1;
if (caseADecl.getQualifiedNameString().equals("ceylon.language::Empty") && caseBDecl.getQualifiedNameString().equals("ceylon.language::Tuple"))
return getSimpleNumParametersOfCallable(caseB);
if (caseBDecl.getQualifiedNameString().equals("ceylon.language::Empty") && caseADecl.getQualifiedNameString().equals("ceylon.language::Tuple"))
return getSimpleNumParametersOfCallable(caseA);
return -1;
}
// can be Tuple, Empty, Sequence or Sequential
if (!args.isClassOrInterface())
return -1;
TypeDeclaration declaration = args.getDeclaration();
String name = declaration.getQualifiedNameString();
if (name.equals("ceylon.language::Tuple")) {
Type rest = args.getTypeArgumentList().get(2);
int ret = getSimpleNumParametersOfCallable(rest);
if (ret == -1)
return -1;
return ret + 1;
}
if (name.equals("ceylon.language::Empty")) {
return 0;
}
if (name.equals("ceylon.language::Sequential") || name.equals("ceylon.language::Sequence")) {
return 1;
}
return -1;
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class AbstractTransformer method rawSupertype.
/**
* Determine whether the given type, when appearing in
* an {@code extends} or {@code implements} clause, should be made raw.
* This can happen because the type itself must be made raw, or because
* any of its supertypes were made raw.
* See #1875.
*/
public boolean rawSupertype(Type ceylonType, int flags) {
if (ceylonType == null || (flags & (JT_SATISFIES | JT_EXTENDS)) == 0) {
return false;
}
Type simpleType = simplifyType(ceylonType);
Map<TypeParameter, Type> tas = simpleType.getTypeArguments();
java.util.List<TypeParameter> tps = simpleType.getDeclaration().getTypeParameters();
for (TypeParameter tp : tps) {
Type ta = tas.get(tp);
// error handling
if (ta == null)
continue;
// we want, so we make sure it's not Null
if (isOptional(ta) && !isNull(ta)) {
// For an optional type T?:
// - The Ceylon type Foo<T?> results in the Java type Foo<T>.
ta = getNonNullType(ta);
}
// In a type argument Foo<X&Object> or Foo<X?> transform to just Foo<X>
ta = simplifyType(ta);
if (typeFact().isUnion(ta) || typeFact().isIntersection(ta)) {
// conform with where raw types would be used between expressions and constructors
if (((flags & (JT_EXTENDS | JT_SATISFIES)) != 0 && tp.getSelfTypedDeclaration() != null)) {
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
return true;
} else if ((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) == 0) {
return true;
}
// otherwise just go on
}
if (!tp.getSatisfiedTypes().isEmpty()) {
boolean needsCastForBounds = false;
for (Type bound : tp.getSatisfiedTypes()) {
bound = bound.substitute(simpleType);
needsCastForBounds |= expressionGen().needsCast(ta, bound, false, false, false);
}
if (needsCastForBounds) {
// replace with the first bound
ta = tp.getSatisfiedTypes().get(0).substitute(simpleType);
if (tp.getSatisfiedTypes().size() > 1 || isBoundsSelfDependant(tp) || willEraseToObject(ta) || // we should reject it for all non-covariant types, unless we're in satisfies/extends
((flags & (JT_SATISFIES | JT_EXTENDS)) == 0 && !simpleType.isCovariant(tp))) {
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
return true;
}
}
}
if (ta.isNothing() || // use the same erasure rules as bottom: prefer wildcards
((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) != 0 && (typeFact().isUnion(ta) || typeFact().isIntersection(ta)))) {
// For the bottom type Bottom:
if ((flags & (JT_CLASS_NEW)) != 0) {
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
return true;
}
}
}
// deal with supertypes which were raw
for (Type superType : ceylonType.getSatisfiedTypes()) {
if (rawSupertype(superType, flags)) {
return true;
}
}
return rawSupertype(ceylonType.getExtendedType(), flags);
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeTypeParameter.
JCTypeParameter makeTypeParameter(TypeParameter declarationModel, java.util.List<Type> satisfiedTypesForBounds) {
TypeParameter typeParameterForBounds = declarationModel;
if (satisfiedTypesForBounds == null) {
satisfiedTypesForBounds = declarationModel.getSatisfiedTypes();
}
// special case for method refinenement where Java doesn't let us refine the parameter bounds
if (declarationModel.getContainer() instanceof Function) {
Function method = (Function) declarationModel.getContainer();
Function refinedMethod = (Function) method.getRefinedDeclaration();
if (!Decl.equal(method, refinedMethod)) {
// find the param index
int index = method.getTypeParameters().indexOf(declarationModel);
if (index == -1) {
log.error("Failed to find type parameter index: " + declarationModel.getName());
} else if (refinedMethod.getTypeParameters().size() > index) {
// ignore smaller index than size since the typechecker would have found the error
TypeParameter refinedTP = refinedMethod.getTypeParameters().get(index);
if (!haveSameBounds(declarationModel, refinedTP)) {
// find the right instantiation of that type parameter
TypeDeclaration methodContainer = (TypeDeclaration) method.getContainer();
TypeDeclaration refinedMethodContainer = (TypeDeclaration) refinedMethod.getContainer();
// find the supertype that gave us that method and its type arguments
Type supertype = methodContainer.getType().getSupertype(refinedMethodContainer);
satisfiedTypesForBounds = new ArrayList<Type>(refinedTP.getSatisfiedTypes().size());
for (Type satisfiedType : refinedTP.getSatisfiedTypes()) {
// substitute the refined type parameter bounds with the right type arguments
satisfiedTypesForBounds.add(satisfiedType.substitute(supertype));
}
typeParameterForBounds = refinedTP;
}
}
}
}
return makeTypeParameter(declarationModel.getName(), satisfiedTypesForBounds, typeParameterForBounds.isCovariant(), typeParameterForBounds.isContravariant());
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class CallableBuilder method makeCallableVaryParam.
private ParameterDefinitionBuilder makeCallableVaryParam(long flags, int ii) {
Type iteratedType = gen.typeFact().getIteratedType(parameterTypes.get(parameterTypes.size() - 1));
// $call$var()'s variadic parameter is *always* erasred to Sequential
// even if it's a Variadic+ parameter
JCExpression type = gen.makeJavaType(gen.typeFact().getSequentialType(iteratedType), AbstractTransformer.JT_RAW);
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(gen, getParamName(ii));
pdb.modifiers(Flags.FINAL | flags);
pdb.type(type, null);
return pdb;
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class CallableBuilder method unboundValueMemberReference.
/**
* Used for "static" value references. For example:
* <pre>
* value x = Integer.plus;
* value y = Foo.method;
* value z = Outer.Inner;
* </pre>
*/
public static CallableBuilder unboundValueMemberReference(CeylonTransformer gen, Tree.QualifiedMemberOrTypeExpression qmte, Type typeModel, final TypedDeclaration value) {
CallBuilder callBuilder = CallBuilder.instance(gen);
Type qualifyingType = qmte.getTarget().getQualifyingType();
JCExpression target = gen.naming.makeUnquotedIdent(Unfix.$instance$);
target = gen.expressionGen().applyErasureAndBoxing(target, qmte.getPrimary().getTypeModel(), true, BoxingStrategy.BOXED, qualifyingType);
if (gen.expressionGen().isThrowableMessage(qmte)) {
callBuilder.invoke(gen.utilInvocation().throwableMessage());
callBuilder.argument(target);
} else if (gen.expressionGen().isThrowableSuppressed(qmte)) {
callBuilder.invoke(gen.utilInvocation().suppressedExceptions());
callBuilder.argument(target);
} else {
JCExpression memberName = gen.naming.makeQualifiedName(target, value, Naming.NA_GETTER | Naming.NA_MEMBER);
if (value instanceof FieldValue) {
callBuilder.fieldRead(memberName);
} else {
callBuilder.invoke(memberName);
}
}
JCExpression innerInvocation = callBuilder.build();
// use the return type since the value is actually applied
Type returnType = gen.getReturnTypeOfCallable(typeModel);
innerInvocation = gen.expressionGen().applyErasureAndBoxing(innerInvocation, returnType, // expression is a Callable
qmte.getTypeErased(), !CodegenUtil.isUnBoxed(value), BoxingStrategy.BOXED, returnType, 0);
ParameterList outerPl = new ParameterList();
Parameter instanceParameter = new Parameter();
instanceParameter.setName(Naming.name(Unfix.$instance$));
Value valueModel = new Value();
instanceParameter.setModel(valueModel);
Type accessType = gen.getParameterTypeOfCallable(typeModel, 0);
;
if (!value.isShared()) {
accessType = Decl.getPrivateAccessType(qmte);
}
valueModel.setName(instanceParameter.getName());
valueModel.setInitializerParameter(instanceParameter);
valueModel.setType(accessType);
valueModel.setUnboxed(false);
outerPl.getParameters().add(instanceParameter);
CallableBuilder outer = new CallableBuilder(gen, null, typeModel, outerPl);
outer.parameterTypes = outer.getParameterTypesFromParameterModels();
List<JCStatement> innerBody = List.<JCStatement>of(gen.make().Return(innerInvocation));
outer.useDefaultTransformation(innerBody);
outer.companionAccess = Decl.isPrivateAccessRequiringCompanion(qmte);
return outer;
}
Aggregations