use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class AbstractTransformer method nonWideningType.
Type nonWideningType(TypedReference declaration, TypedReference refinedDeclaration) {
final Reference pr;
if (declaration.equals(refinedDeclaration)) {
pr = declaration;
} else {
Type refinedType = refinedDeclaration.getType();
// since it may have changed name
if (refinedType.getDeclaration() instanceof TypeParameter && refinedType.getDeclaration().getContainer() instanceof Function) {
// find its index in the refined declaration
TypeParameter refinedTypeParameter = (TypeParameter) refinedType.getDeclaration();
Function refinedMethod = (Function) refinedTypeParameter.getContainer();
int i = 0;
for (TypeParameter tp : refinedMethod.getTypeParameters()) {
if (tp.getName().equals(refinedTypeParameter.getName()))
break;
i++;
}
if (i >= refinedMethod.getTypeParameters().size()) {
throw new BugException("can't find type parameter " + refinedTypeParameter.getName() + " in its container " + refinedMethod.getName());
}
// the refining method type parameter should be at the same index
if (declaration.getDeclaration() instanceof Function == false)
throw new BugException("refining declaration is not a method: " + declaration);
Function refiningMethod = (Function) declaration.getDeclaration();
if (i >= refiningMethod.getTypeParameters().size()) {
throw new BugException("refining method does not have enough type parameters to refine " + refinedMethod.getName());
}
pr = refiningMethod.getTypeParameters().get(i).getType();
} else {
pr = refinedType;
}
}
if (pr.getDeclaration() instanceof Functional && Decl.isMpl((Functional) pr.getDeclaration())) {
// the innermost Callable.
return getReturnTypeOfCallable(pr.getFullType());
}
return pr.getType();
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class AbstractTransformer method getJavaArrayElementType.
private JCExpression getJavaArrayElementType(Type type, int flags) {
if (type == null)
return makeErroneous(null, "compiler bug: " + type + " is not a java array");
type = simplifyType(type);
if (type == null || type.getDeclaration() instanceof Class == false)
return makeErroneous(null, "compiler bug: " + type + " is not a java array");
Class c = (Class) type.getDeclaration();
String name = c.getQualifiedNameString();
if (name.equals("java.lang::ObjectArray")) {
// fetch its type parameter
if (type.getTypeArgumentList().size() != 1)
return makeErroneous(null, "compiler bug: " + type + " is missing parameter type to java ObjectArray");
Type elementType = type.getTypeArgumentList().get(0);
if (elementType == null)
return makeErroneous(null, "compiler bug: " + type + " has null parameter type to java ObjectArray");
return make().TypeArray(makeJavaType(elementType, flags | JT_TYPE_ARGUMENT));
} else if (name.equals("java.lang::ByteArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.BYTE));
} else if (name.equals("java.lang::ShortArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.SHORT));
} else if (name.equals("java.lang::IntArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.INT));
} else if (name.equals("java.lang::LongArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.LONG));
} else if (name.equals("java.lang::FloatArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.FLOAT));
} else if (name.equals("java.lang::DoubleArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.DOUBLE));
} else if (name.equals("java.lang::BooleanArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.BOOLEAN));
} else if (name.equals("java.lang::CharArray")) {
return make().TypeArray(make().TypeIdent(TypeTags.CHAR));
} else {
return makeErroneous(null, "compiler bug: " + type + " is an unknown java array type");
}
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class AbstractTransformer method isWideningTypeArguments.
private boolean isWideningTypeArguments(Type declType, Type refinedDeclType, boolean allowSubtypes) {
if (declType == null || refinedDeclType == null)
return false;
// make sure we work on simplified types, to avoid stuff like optional or size-1 unions
declType = simplifyType(declType);
refinedDeclType = simplifyType(refinedDeclType);
// special case for type parameters
if (declType.getDeclaration() instanceof TypeParameter && refinedDeclType.getDeclaration() instanceof TypeParameter) {
// consider them equivalent if they have the same bounds
TypeParameter tp = (TypeParameter) declType.getDeclaration();
TypeParameter refinedTP = (TypeParameter) refinedDeclType.getDeclaration();
if (haveSameBounds(tp, refinedTP))
return false;
// if they don't have the same bounds and we don't allow subtypes then we're widening
if (!allowSubtypes)
return false;
// if we allow subtypes, we're widening if tp is not a subtype of refinedTP
return !tp.getType().isSubtypeOf(refinedTP.getType());
}
if (allowSubtypes) {
if ((willEraseToObject(refinedDeclType))) {
// - similarly if we both erase to object we're not widening
return false;
}
// if we have exactly the same type don't bother finding a common ancestor
if (!declType.isExactly(refinedDeclType)) {
// check if we can form an informed decision
if (refinedDeclType.getDeclaration() == null)
return true;
// find the instantiation of the refined decl type in the decl type
// special case for optional types: let's find the definite type since
// in java they are equivalent
Type definiteType = typeFact().getDefiniteType(refinedDeclType);
if (definiteType != null)
refinedDeclType = definiteType;
declType = declType.getSupertype(refinedDeclType.getDeclaration());
// could not find common type, we must be widening somehow
if (declType == null)
return true;
}
}
Map<TypeParameter, Type> typeArguments = declType.getTypeArguments();
Map<TypeParameter, Type> refinedTypeArguments = refinedDeclType.getTypeArguments();
java.util.List<TypeParameter> typeParameters = declType.getDeclaration().getTypeParameters();
for (TypeParameter tp : typeParameters) {
Type typeArgument = typeArguments.get(tp);
if (typeArgument == null)
// something fishy here
return true;
Type refinedTypeArgument = refinedTypeArguments.get(tp);
if (refinedTypeArgument == null)
// something fishy here
return true;
// check if the type arg is widening due to erasure
if (isWidening(typeArgument, refinedTypeArgument))
return true;
// check if we are refining a covariant param which we must "fix" because it is dependend on, like Tuple's first TP
if (declType.isCovariant(tp) && hasDependentTypeParameters(typeParameters, tp) && !typeArgument.isExactly(refinedTypeArgument) && // it is not widening if we refine Object with a TP, though
!(willEraseToObject(refinedTypeArgument) && (isTypeParameter(typeArgument) || // it is also not widening if we erase both to Object
willEraseToObject(typeArgument))))
return true;
// check if the type arg is a subtype, or if its type args are widening
if (isWideningTypeArguments(typeArgument, refinedTypeArgument, tp.isCovariant()))
return true;
}
// so far so good
return false;
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class LinkRenderer method decorateWithLinkDropdownMenu.
private String decorateWithLinkDropdownMenu(String link, Type producedType) {
if (!printLinkDropdownMenu || !printAbbreviated || !canLinkToCeylonLanguageModule()) {
return link;
}
List<Type> producedTypes = new ArrayList<Type>();
decompose(producedType, producedTypes);
boolean containsOptional = false;
boolean containsSequential = false;
boolean containsSequence = false;
boolean containsIterable = false;
boolean containsEntry = false;
boolean containsCallable = false;
boolean containsTuple = false;
for (Type pt : producedTypes) {
if (abbreviateOptional(pt)) {
containsOptional = true;
} else if (abbreviateSequential(pt) && !link.contains("'Go to ceylon.language::Sequential'")) {
containsSequential = true;
} else if (abbreviateSequence(pt) && !link.contains("'Go to ceylon.language::Sequence'")) {
containsSequence = true;
} else if (abbreviateIterable(pt) && !link.contains("'Go to ceylon.language::Iterable'")) {
containsIterable = true;
} else if (abbreviateEntry(pt) && !link.contains("'Go to ceylon.language::Entry'")) {
containsEntry = true;
} else if (abbreviateCallable(pt) && !link.contains("'Go to ceylon.language::Callable'")) {
containsCallable = true;
} else if (abbreviateTuple(pt) && !link.contains("'Go to ceylon.language::Tuple'")) {
containsTuple = true;
}
}
Unit unit = producedType.getDeclaration().getUnit();
if (containsOptional || containsSequential || containsSequence || containsIterable || containsEntry || containsCallable || containsTuple) {
StringBuilder sb = new StringBuilder();
sb.append("<span class='link-dropdown'>");
sb.append(link.replaceAll("class='link'", "class='link type-identifier'"));
sb.append("<span class='dropdown'>");
sb.append("<a class='dropdown-toggle' data-toggle='dropdown' href='#'><b title='Show more links' class='caret'></b></a>");
sb.append("<ul class='dropdown-menu'>");
if (containsOptional) {
sb.append(getLinkMenuItem(unit.getNullDeclaration(), "abbreviations X? means Null|X"));
}
if (containsSequential) {
sb.append(getLinkMenuItem(unit.getSequentialDeclaration(), "abbreviation X[] or [X*] means Sequential<X>"));
}
if (containsSequence) {
sb.append(getLinkMenuItem(unit.getSequenceDeclaration(), "abbreviation [X+] means Sequence<X>"));
}
if (containsIterable) {
sb.append(getLinkMenuItem(unit.getIterableDeclaration(), "abbreviation {X+} or {X*} means Iterable<X,Nothing> or Iterable<X,Null>"));
}
if (containsEntry) {
sb.append(getLinkMenuItem(unit.getEntryDeclaration(), "abbreviation X->Y means Entry<X,Y>"));
}
if (containsCallable) {
sb.append(getLinkMenuItem(unit.getCallableDeclaration(), "abbreviation X(Y,Z) means Callable<X,[Y,Z]>"));
}
if (containsTuple) {
sb.append(getLinkMenuItem(unit.getTupleDeclaration(), "abbreviation [X,Y] means Tuple<X|Y,X,Tuple<Y,Y,[]>>"));
}
// dropdown-menu
sb.append("</ul>");
// dropdown
sb.append("</span>");
// link-dropdown
sb.append("</span>");
return sb.toString();
}
return link;
}
use of com.redhat.ceylon.model.typechecker.model.Type in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeOptimizedTypeTest.
JCExpression makeOptimizedTypeTest(JCExpression firstTimeExpr, Naming.CName varName, Type testedType, Type expressionType) {
//TypeDeclaration widerDeclaration = expressionType.getDeclaration();
if (!isTypeTestCheap(firstTimeExpr, varName, testedType, expressionType)) {
//if (widerDeclaration instanceof UnionType
// || widerDeclaration instanceof ClassOrInterface) {
// we've got a X|Y and we're testing for X
// or parhaps a A|B|C|D and we're testing for C|D
java.util.List<Type> cases = expressionType.getCaseTypes();
if (cases != null) {
java.util.List<Type> copiedCases = new ArrayList<>(cases.size());
copiedCases.addAll(cases);
cases = copiedCases;
if ((testedType.isClassOrInterface() || testedType.isTypeParameter()) && cases.remove(testedType)) {
} else if (testedType.isUnion()) {
for (Type ct : testedType.getCaseTypes()) {
if (!cases.remove(ct)) {
cases = null;
break;
}
}
} else {
cases = null;
}
if (cases != null) {
Type complementType = typeFact().getNothingType();
for (Type ct : cases) {
complementType = com.redhat.ceylon.model.typechecker.model.ModelUtil.unionType(complementType, ct, typeFact());
}
if (/*typeFact().getLanguageModuleDeclaration("Finished").equals(complementType.getDeclaration())
||*/
com.redhat.ceylon.model.typechecker.model.ModelUtil.intersectionType(complementType, testedType, typeFact()).isNothing()) {
return make().Unary(JCTree.NOT, makeTypeTest(firstTimeExpr, varName, complementType, expressionType));
}
}
}
//}
}
return makeTypeTest(firstTimeExpr, varName, testedType, expressionType);
}
Aggregations