All the special types are now handled by SpecialTypes class

- this concept used to be called "known types" before
This commit is contained in:
Andrey Breslav
2012-08-13 11:56:26 +04:00
parent f7321a40e0
commit 3b3f1aa016
2 changed files with 110 additions and 123 deletions
@@ -217,7 +217,7 @@ public class CodegenContexts {
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, typeMapper.getClassFQName(contextDescriptor), "this$0", false)
? StackValue.field(type, typeMapper.getJvmClassName(contextDescriptor), "this$0", false)
: null;
}
@@ -83,11 +83,78 @@ public class JetTypeMapper {
public static final Type TYPE_FUNCTION0 = Type.getObjectType("jet/Function0");
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
public static class SpecialTypes {
private static final class SpecialTypeKey {
@NotNull
private final FqNameUnsafe className;
private final boolean nullable;
private SpecialTypeKey(@NotNull FqNameUnsafe className, boolean nullable) {
this.className = className;
this.nullable = nullable;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SpecialTypeKey that = (SpecialTypeKey) o;
if (nullable != that.nullable) return false;
if (!className.equals(that.className)) return false;
return true;
}
@Override
public int hashCode() {
int result = className.hashCode();
result = 31 * result + (nullable ? 1 : 0);
return result;
}
}
private final Map<SpecialTypeKey, Type> asmTypes = Maps.newHashMap();
@Nullable
public Type get(@NotNull JetType type) {
ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor();
return asmTypes.get(new SpecialTypeKey(DescriptorUtils.getFQName(classifier), type.isNullable()));
}
private void register(@NotNull ClassName className, @NotNull Type nonNullType, @NotNull Type nullableType) {
asmTypes.put(new SpecialTypeKey(className.getFqName().toUnsafe(), true), nullableType);
asmTypes.put(new SpecialTypeKey(className.getFqName().toUnsafe(), false), nonNullType);
}
public void init() {
register(JetStandardLibraryNames.NOTHING, TYPE_NOTHING, TYPE_NOTHING);
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
register(primitiveType.getClassName(), jvmPrimitiveType.getAsmType(), jvmPrimitiveType.getWrapper().getAsmType());
}
register(JetStandardLibraryNames.NUMBER, JL_NUMBER_TYPE, JL_NUMBER_TYPE);
register(JetStandardLibraryNames.STRING, JL_STRING_TYPE, JL_STRING_TYPE);
register(JetStandardLibraryNames.CHAR_SEQUENCE, JL_CHAR_SEQUENCE_TYPE, JL_CHAR_SEQUENCE_TYPE);
register(JetStandardLibraryNames.THROWABLE, TYPE_THROWABLE, TYPE_THROWABLE);
register(JetStandardLibraryNames.COMPARABLE, JL_COMPARABLE_TYPE, JL_COMPARABLE_TYPE);
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
register(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType(), jvmPrimitiveType.getAsmArrayType());
}
}
}
public BindingContext bindingContext;
private ClosureAnnotator closureAnnotator;
private boolean mapBuiltinsToJava;
private ClassBuilderMode classBuilderMode;
private final SpecialTypes specialTypes = new SpecialTypes();
@Inject
public void setBindingContext(BindingContext bindingContext) {
@@ -111,12 +178,9 @@ public class JetTypeMapper {
@PostConstruct
public void init() {
initKnownTypes();
specialTypes.init();
}
public boolean hasThis0(ClassDescriptor classDescriptor) {
return closureAnnotator.hasThis0(classDescriptor);
}
@@ -125,40 +189,6 @@ public class JetTypeMapper {
return closureAnnotator;
}
private static final class KnownTypeKey {
@NotNull
private final FqNameUnsafe className;
private final boolean nullable;
private KnownTypeKey(@NotNull FqNameUnsafe className, boolean nullable) {
this.className = className;
this.nullable = nullable;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
KnownTypeKey that = (KnownTypeKey) o;
if (nullable != that.nullable) return false;
if (!className.equals(that.className)) return false;
return true;
}
@Override
public int hashCode() {
int result = className.hashCode();
result = 31 * result + (nullable ? 1 : 0);
return result;
}
}
private final HashMap<KnownTypeKey, Type> knowTypes = Maps.newHashMap();
public static boolean isIntPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
}
@@ -308,17 +338,12 @@ public class JetTypeMapper {
return null;
}
public JvmClassName getClassFQName(ClassDescriptor classDescriptor) {
return JvmClassName.byInternalName(getFQName(classDescriptor));
public JvmClassName getJvmClassName(ClassDescriptor classDescriptor) {
return JvmClassName.byInternalName(getJvmInternalFQName(classDescriptor));
}
/**
* @return Internal name
*
* @see DescriptorUtils#getFQName(DeclarationDescriptor)
*/
@NotNull
private String getFQName(@NotNull DeclarationDescriptor descriptor) {
private String getJvmInternalFQName(@NotNull DeclarationDescriptor descriptor) {
descriptor = descriptor.getOriginal();
if (descriptor instanceof FunctionDescriptor) {
@@ -339,15 +364,15 @@ public class JetTypeMapper {
if (klass.getContainingDeclaration() instanceof ClassDescriptor) {
ClassDescriptor containingKlass = (ClassDescriptor) klass.getContainingDeclaration();
if (containingKlass.getKind() == ClassKind.ENUM_CLASS) {
return getFQName(containingKlass);
return getJvmInternalFQName(containingKlass);
}
else {
return getFQName(containingKlass) + JvmAbi.CLASS_OBJECT_SUFFIX;
return getJvmInternalFQName(containingKlass) + JvmAbi.CLASS_OBJECT_SUFFIX;
}
}
}
else if (klass.getKind() == ClassKind.ENUM_ENTRY) {
return getFQName(klass.getContainingDeclaration());
return getJvmInternalFQName(klass.getContainingDeclaration());
}
}
@@ -365,7 +390,7 @@ public class JetTypeMapper {
return className.getInternalName();
}
String baseName = getFQName(container);
String baseName = getJvmInternalFQName(container);
if (!baseName.isEmpty()) {
return baseName + (container instanceof NamespaceDescriptor ? "/" : "$") + name.getIdentifier();
}
@@ -385,17 +410,16 @@ public class JetTypeMapper {
if (mapBuiltinsToJava) {
if (classifier instanceof ClassDescriptor) {
KnownTypeKey key = new KnownTypeKey(DescriptorUtils.getFQName(classifier), jetType.isNullable());
known = knowTypes.get(key);
known = specialTypes.get(jetType);
}
}
if (known != null) {
if (kind == MapTypeMode.VALUE) {
return mapKnownAsmType(jetType, known, signatureVisitor, false);
return mapKnownAsmType(jetType, known, signatureVisitor);
}
else if (kind == MapTypeMode.TYPE_PARAMETER) {
return mapKnownAsmType(jetType, known, signatureVisitor, true);
return mapKnownAsmType(jetType, boxType(known), signatureVisitor);
}
else if (kind == MapTypeMode.TRAIT_IMPL) {
throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType);
@@ -428,7 +452,7 @@ public class JetTypeMapper {
}
Type asmType = Type.getObjectType("error/NonExistentClass");
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, asmType, true);
writeSimpleType(signatureVisitor, asmType, true);
}
checkValidType(asmType);
return asmType;
@@ -461,7 +485,7 @@ public class JetTypeMapper {
if (JetStandardClasses.getAny().equals(descriptor)) {
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, TYPE_OBJECT, jetType.isNullable());
writeSimpleType(signatureVisitor, TYPE_OBJECT, jetType.isNullable());
}
checkValidType(TYPE_OBJECT);
return TYPE_OBJECT;
@@ -469,33 +493,12 @@ public class JetTypeMapper {
if (descriptor instanceof ClassDescriptor) {
Type asmType;
boolean forceReal;
if (JetStandardLibraryNames.COMPARABLE.is((ClassDescriptor) descriptor) && mapBuiltinsToJava) {
if (jetType.getArguments().size() != 1) {
throw new UnsupportedOperationException("Comparable must have one type argument");
}
JvmClassName name = getJvmClassName((ClassDescriptor) descriptor);
Type asmType = Type.getObjectType(name.getInternalName() + (kind == MapTypeMode.TRAIT_IMPL ? JvmAbi.TRAIT_IMPL_SUFFIX : ""));
boolean forceReal = isForceReal(name);
asmType = JL_COMPARABLE_TYPE;
forceReal = false;
}
else {
JvmClassName name = getClassFQName((ClassDescriptor) descriptor);
asmType = Type.getObjectType(name.getInternalName() + (kind == MapTypeMode.TRAIT_IMPL ? JvmAbi.TRAIT_IMPL_SUFFIX : ""));
forceReal = isForceReal(name);
}
if (signatureVisitor != null) {
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal);
for (TypeProjection proj : jetType.getArguments()) {
// TODO: +-
signatureVisitor.writeTypeArgument(proj.getProjectionKind());
mapType(proj.getType(), signatureVisitor, MapTypeMode.TYPE_PARAMETER);
signatureVisitor.writeTypeArgumentEnd();
}
signatureVisitor.writeClassEnd();
}
writeGenericType(jetType, signatureVisitor, asmType, forceReal);
checkValidType(asmType);
return asmType;
@@ -515,26 +518,34 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("Unknown type " + jetType);
}
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor, boolean boxPrimitive) {
if (boxPrimitive) {
Type boxed = boxType(asmType);
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, boxed, jetType.isNullable());
private void writeGenericType(JetType jetType, BothSignatureWriter signatureVisitor, Type asmType, boolean forceReal) {
if (signatureVisitor != null) {
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal);
for (TypeProjection proj : jetType.getArguments()) {
// TODO: +-
signatureVisitor.writeTypeArgument(proj.getProjectionKind());
mapType(proj.getType(), signatureVisitor, MapTypeMode.TYPE_PARAMETER);
signatureVisitor.writeTypeArgumentEnd();
}
checkValidType(boxed);
return boxed;
}
else {
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, asmType, jetType.isNullable());
}
checkValidType(asmType);
return asmType;
signatureVisitor.writeClassEnd();
}
}
public static void visitAsmType(BothSignatureWriter visitor, Type asmType, boolean nullable) {
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor) {
if (signatureVisitor != null) {
if (jetType.getArguments().isEmpty()) {
writeSimpleType(signatureVisitor, asmType, jetType.isNullable());
}
else {
writeGenericType(jetType, signatureVisitor, asmType, false);
}
}
checkValidType(asmType);
return asmType;
}
public static void writeSimpleType(BothSignatureWriter visitor, Type asmType, boolean nullable) {
visitor.writeAsmType(asmType, nullable);
}
@@ -1029,30 +1040,6 @@ public class JetTypeMapper {
return result;
}
private void registerKnownType(@NotNull ClassName className, @NotNull Type nonNullType, @NotNull Type nullableType) {
knowTypes.put(new KnownTypeKey(className.getFqName().toUnsafe(), true), nullableType);
knowTypes.put(new KnownTypeKey(className.getFqName().toUnsafe(), false), nonNullType);
}
private void initKnownTypes() {
registerKnownType(JetStandardLibraryNames.NOTHING, TYPE_NOTHING, TYPE_NOTHING);
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
registerKnownType(primitiveType.getClassName(), jvmPrimitiveType.getAsmType(), jvmPrimitiveType.getWrapper().getAsmType());
}
registerKnownType(JetStandardLibraryNames.NUMBER, JL_NUMBER_TYPE, JL_NUMBER_TYPE);
registerKnownType(JetStandardLibraryNames.STRING, JL_STRING_TYPE, JL_STRING_TYPE);
registerKnownType(JetStandardLibraryNames.CHAR_SEQUENCE, JL_CHAR_SEQUENCE_TYPE, JL_CHAR_SEQUENCE_TYPE);
registerKnownType(JetStandardLibraryNames.THROWABLE, TYPE_THROWABLE, TYPE_THROWABLE);
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
registerKnownType(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType(), jvmPrimitiveType.getAsmArrayType());
}
}
private static boolean isForceReal(JvmClassName className) {
return JvmPrimitiveType.getByWrapperClass(className) != null
|| className.getFqName().getFqName().equals("java.lang.String")