From 7ddfa09be0c1741427808e5a170234610de2f34e Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 14 Dec 2011 22:30:34 +0400 Subject: [PATCH] merge Alex' work with mine, move internal classes to internal subpackage --- .../jet/codegen/BothSignatureWriter.java | 23 +- .../codegen/ImplementationBodyCodegen.java | 5 +- .../jetbrains/jet/codegen/SignatureUtil.java | 86 --- .../java/JetTypeJetSignatureReader.java | 65 +- stdlib/src/jet/typeinfo/JetSignature.java | 2 +- stdlib/src/jet/typeinfo/TypeInfo.java | 643 +----------------- .../src/jet/typeinfo/TypeInfoProjection.java | 34 - .../src/jet/typeinfo/internal/Signature.java | 60 ++ .../jet/typeinfo/internal/TypeInfoImpl.java | 229 +++++++ .../jet/typeinfo/internal/TypeInfoParser.java | 281 ++++++++ .../internal/TypeInfoProjectionImpl.java | 46 ++ .../jet/typeinfo/internal/TypeInfoUtils.java | 40 ++ .../jet/typeinfo/internal/TypeInfoVar.java | 89 +++ .../JetSignatureExceptionsAdapter.java | 88 +++ .../signature/JetSignatureReader.java | 80 ++- 15 files changed, 922 insertions(+), 849 deletions(-) delete mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java create mode 100644 stdlib/src/jet/typeinfo/internal/Signature.java create mode 100644 stdlib/src/jet/typeinfo/internal/TypeInfoImpl.java create mode 100644 stdlib/src/jet/typeinfo/internal/TypeInfoParser.java create mode 100644 stdlib/src/jet/typeinfo/internal/TypeInfoProjectionImpl.java create mode 100644 stdlib/src/jet/typeinfo/internal/TypeInfoUtils.java create mode 100644 stdlib/src/jet/typeinfo/internal/TypeInfoVar.java create mode 100644 stdlib/src/jet/typeinfo/internal/signature/JetSignatureExceptionsAdapter.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java index 153765f12d0..8fcbabac1ac 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java @@ -52,6 +52,7 @@ public class BothSignatureWriter { private JetSignatureWriter jetSignatureWriter; + private String kotlinClassParameters; private String kotlinClassSignature; private List kotlinParameterTypes = new ArrayList(); @@ -207,7 +208,16 @@ public class BothSignatureWriter { } public void writeFormalTypeParametersEnd() { + jetSignatureWriter.visitSuperclass(); // just to call endFormals + + kotlinClassParameters = jetSignatureWriter.toString(); + jetSignatureWriter = null; + + if (DEBUG_SIGNATURE_WRITER) { + new JetSignatureReader(kotlinClassParameters).acceptFormalTypeParametersOnly(new JetSignatureAdapter()); + } + checkState(State.TYPE_PARAMETERS); } @@ -285,6 +295,11 @@ public class BothSignatureWriter { public void writeSupersEnd() { kotlinClassSignature = jetSignatureWriter.toString(); jetSignatureWriter = null; + + if (DEBUG_SIGNATURE_WRITER) { + new JetSignatureReader(kotlinClassSignature).accept(new JetSignatureAdapter()); + } + transitionState(State.SUPERS, State.CLASS_END); } @@ -344,7 +359,13 @@ public class BothSignatureWriter { @Nullable public String makeKotlinClassSignature() { checkState(State.CLASS_END); - return kotlinClassSignature; + if (kotlinClassParameters == null) { + throw new IllegalStateException(); + } + if (kotlinClassSignature == null) { + throw new IllegalStateException(); + } + return kotlinClassParameters + kotlinClassSignature; } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index cd89380cbf5..da2066e7623 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -71,9 +71,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { v.visitOuterClass(typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null); } - if(myClass instanceof JetClass) { + if(myClass instanceof JetClass && signature.getKotlinGenericSignature() != null) { AnnotationVisitor annotationVisitor = v.newAnnotation(myClass, "Ljet/typeinfo/JetSignature;", true); - annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, bindingContext, typeMapper)); + //annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, bindingContext, typeMapper)); + annotationVisitor.visit("value", signature.getKotlinGenericSignature()); annotationVisitor.visitEnd(); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java deleted file mode 100644 index 392037c636e..00000000000 --- a/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.jetbrains.jet.codegen; - -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.psi.JetClass; -import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; -import org.jetbrains.jet.lang.psi.JetTypeParameter; -import org.jetbrains.jet.lang.psi.JetTypeReference; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.TypeProjection; -import org.jetbrains.jet.lang.types.Variance; -import org.objectweb.asm.Type; - -import java.util.List; - -/** - * @author alex.tkachman - */ -public class SignatureUtil { - private SignatureUtil() { - } - - public static String classToSignature(JetClass type, BindingContext bindingContext, JetTypeMapper typeMapper) { - StringBuilder sb = new StringBuilder(); - genTypeParams(type, sb); - List delegationSpecifiers = type.getDelegationSpecifiers(); - for (JetDelegationSpecifier specifier : delegationSpecifiers) { - JetTypeReference typeReference = specifier.getTypeReference(); - JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); - genJetType(sb, jetType, typeMapper); - } - return sb.toString(); - } - - private static void genJetType(StringBuilder sb, JetType jetType, JetTypeMapper typeMapper) { - DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); - if(descriptor instanceof ClassDescriptor) { - JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType(); - Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION); - if(JetTypeMapper.isPrimitive(type)) { - type = JetTypeMapper.boxType(type); - } - sb.append(type.getDescriptor()); - } - else { - sb.append("T"); - JetType defaultType = ((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(); - Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION); - sb.append(type.getDescriptor()); - sb.append(descriptor.getName()); - sb.append(";"); - } - if(!jetType.getArguments().isEmpty()) { - sb.append("<"); - for (TypeProjection typeProjection : jetType.getArguments()) { - if(typeProjection.getProjectionKind() == Variance.IN_VARIANCE) - sb.append("in "); - if(typeProjection.getProjectionKind() == Variance.OUT_VARIANCE) - sb.append("out "); - genJetType(sb, typeProjection.getType(), typeMapper); - } - sb.append(">"); - } - if(jetType.isNullable()) - sb.append("?"); - } - - private static void genTypeParams(JetClass type, StringBuilder sb) { - List parameters = type.getTypeParameterList().getParameters(); - if (parameters.isEmpty()) { - return; - } - sb.append('<'); - for(JetTypeParameter param : parameters) { - Variance variance = param.getVariance(); - if(variance == Variance.IN_VARIANCE) - sb.append("in "); - else if(variance == Variance.OUT_VARIANCE) - sb.append("out "); - sb.append(param.getName()); - sb.append(";"); - } - sb.append('>'); - } -} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java index 7694f3eb8a2..2c190cbc956 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java @@ -1,6 +1,8 @@ package org.jetbrains.jet.lang.resolve.java; import jet.typeinfo.TypeInfoVariance; +import jet.typeinfo.internal.signature.JetSignatureAdapter; +import jet.typeinfo.internal.signature.JetSignatureExceptionsAdapter; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; @@ -20,7 +22,7 @@ import java.util.List; /** * @author Stepan Koltsov */ -public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor { +public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAdapter { private final JavaDescriptorResolver javaDescriptorResolver; private final JetStandardLibrary jetStandardLibrary; @@ -31,47 +33,6 @@ public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor { } - - @Override - public void visitFormalTypeParameter(String name, TypeInfoVariance variance) { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitClassBound() { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitInterfaceBound() { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitSuperclass() { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitInterface() { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitParameterType() { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitReturnType() { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitExceptionType() { - throw new IllegalStateException(); - } - private JetType getPrimitiveType(char descriptor, boolean nullable) { if (!nullable) { switch (descriptor) { @@ -124,16 +85,6 @@ public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor { done(getPrimitiveType(descriptor, nullable)); } - @Override - public void visitTypeVariable(String name, boolean nullable) { - throw new IllegalStateException(); - } - - @Override - public JetSignatureVisitor visitArrayType(boolean nullable) { - throw new IllegalStateException(); - } - private ClassDescriptor classDescriptor; private boolean nullable; @@ -150,16 +101,6 @@ public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor { this.typeArguments = new ArrayList(); } - @Override - public void visitInnerClassType(String name, boolean nullable) { - throw new IllegalStateException(); - } - - @Override - public void visitTypeArgument() { - throw new IllegalStateException(); - } - private static Variance parseVariance(char wildcard) { switch (wildcard) { case '=': return Variance.INVARIANT; diff --git a/stdlib/src/jet/typeinfo/JetSignature.java b/stdlib/src/jet/typeinfo/JetSignature.java index fe43b49b50d..c93f818951b 100644 --- a/stdlib/src/jet/typeinfo/JetSignature.java +++ b/stdlib/src/jet/typeinfo/JetSignature.java @@ -11,7 +11,7 @@ import java.util.*; * @url http://confluence.jetbrains.net/display/JET/Jet+Signatures */ @Retention(RetentionPolicy.RUNTIME) -@interface JetSignature { +public @interface JetSignature { String value(); } diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 925cb84d745..f2bc7734534 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -2,12 +2,8 @@ package jet.typeinfo; import jet.JetObject; import jet.Tuple0; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.TypeVariable; -import java.util.*; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import jet.typeinfo.internal.TypeInfoImpl; +import jet.typeinfo.internal.TypeInfoProjectionImpl; /** * @author abreslav @@ -15,7 +11,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * @author alex.tkachman */ public abstract class TypeInfo implements JetObject { - private final static TypeInfoProjection[] EMPTY = new TypeInfoProjection[0]; public static final TypeInfo BYTE_TYPE_INFO = getTypeInfo(Byte.class, false); public static final TypeInfo SHORT_TYPE_INFO = getTypeInfo(Short.class, false); @@ -56,7 +51,7 @@ public abstract class TypeInfo implements JetObject { } public static TypeInfoProjection inProjection(TypeInfo typeInfo) { - return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) { + return new TypeInfoProjectionImpl(typeInfo) { // @NotNull @Override public TypeInfoVariance getVariance() { @@ -66,7 +61,7 @@ public abstract class TypeInfo implements JetObject { } public static TypeInfoProjection outProjection(TypeInfo typeInfo) { - return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) { + return new TypeInfoProjectionImpl(typeInfo) { // @NotNull @Override public TypeInfoVariance getVariance() { @@ -75,6 +70,15 @@ public abstract class TypeInfo implements JetObject { }; } + private static TypeInfoProjection projection(TypeInfo typeInfo, TypeInfoVariance variance) { + switch (variance) { + case IN: return inProjection(typeInfo); + case OUT: return outProjection(typeInfo); + case INVARIANT: return invariantProjection(typeInfo); + default: throw new IllegalStateException(); + } + } + public static TypeInfo getTypeInfo(Class klazz, boolean nullable) { return new TypeInfoImpl(klazz, nullable); } @@ -94,626 +98,5 @@ public abstract class TypeInfo implements JetObject { public abstract TypeInfoProjection getProjection(int index); public abstract TypeInfo getArgumentType(Class klass, int index); - - protected abstract TypeInfo substitute(List myVars); - protected abstract TypeInfo substitute(TypeInfoProjection[] projections); - - private static class TypeInfoVar extends TypeInfo { - final int varIndex; - final Signature signature; - final boolean nullable; - - private TypeInfoVar(Signature signature, Integer varIndex) { - this.signature = signature; - this.varIndex = varIndex; - nullable = false; - } - - public TypeInfoVar(Signature signature, boolean nullable, int varIndex) { - this.signature = signature; - this.nullable = nullable; - this.varIndex = varIndex; - } - - @Override - public Object[] newArray(int length) { - throw new UnsupportedOperationException(); - } - - @Override - public Class getJavaClass() { - throw new UnsupportedOperationException(); - } - - @Override - public Object getClassObject() { - throw new UnsupportedOperationException("Abstract TypeInfo"); - } - - @Override - public boolean isInstance(Object obj) { - throw new UnsupportedOperationException("Abstract TypeInfo"); - } - - @Override - public int getProjectionCount() { - return 0; - } - - @Override - public TypeInfoProjection getProjection(int index) { - throw new UnsupportedOperationException("Abstract TypeInfo"); - } - - @Override - public TypeInfo getArgumentType(Class klass, int index) { - throw new UnsupportedOperationException("Abstract TypeInfo"); - } - - @Override - public TypeInfo substitute(List myVars) { - return myVars.get(varIndex); - } - - @Override - protected TypeInfo substitute(TypeInfoProjection[] projections) { - return projections[varIndex].getType(); - } - - @Override - public TypeInfo getTypeInfo() { - throw new UnsupportedOperationException("Abstract TypeInfo"); - } - - @Override - public JetObject getOuterObject() { - return null; - } - - @Override - public String toString() { - return "T:" + signature.klazz.getName() + ":" + varIndex; - } - } - - private static class TypeInfoImpl extends TypeInfo implements TypeInfoProjection { - private TypeInfo typeInfo; - private final Signature signature; - private final boolean nullable; - private final TypeInfoProjection[] projections; - - private TypeInfoImpl(Class theClass, boolean nullable) { - this(theClass, nullable, EMPTY); - } - - private TypeInfoImpl(Class theClass, boolean nullable, TypeInfoProjection[] projections) { - this.signature = Parser.parse(theClass); - this.nullable = nullable; - this.projections = projections; - if(signature.variables.size() != projections.length) - throw new IllegalStateException("Wrong signature " + theClass.getName()); - } - - public final TypeInfoProjection getProjection(int index) { - return projections[index]; - } - - @Override - public Object[] newArray(int length) { - return (Object[]) Array.newInstance(signature.klazz, length); - } - - @Override - public Class getJavaClass() { - return signature.klazz; - } - - public final Object getClassObject() { - try { - final Class implClass = signature.klazz.getClassLoader().loadClass(signature.klazz.getCanonicalName()); - final Field classobj = implClass.getField("$classobj"); - return classobj.get(null); - } catch (Exception e) { - return null; - } - } - - TypeInfo getSuperTypeInfo(Class klass) { - return signature.superSignatures.get(klass); - } - - public final TypeInfo getArgumentType(Class klass, int index) { - if(klass == this.signature.klazz) - return projections[index].getType(); - else { - return getSuperTypeInfo(klass).substitute(projections).getArgumentType(klass, index); - } - } - - @Override - public TypeInfo substitute(final List myVars) { - if(projections.length == 0) - return new TypeInfoImpl(this.signature.klazz, nullable, EMPTY); - else { - TypeInfoProjection [] proj = new TypeInfoProjection[projections.length]; - for(int i = 0; i != proj.length; ++i) { - final int finalI = i; - final TypeInfo substitute = projections[finalI].getType().substitute(myVars); - proj[i] = new TypeInfoProjection(){ - - @Override - public TypeInfoVariance getVariance() { - return projections[finalI].getVariance(); - } - - @Override - public TypeInfo getType() { - return substitute; - } - - @Override - public String toString() { - return getVariance().toString() + " " + substitute; - } - }; - } - return new TypeInfoImpl(this.signature.klazz, nullable, proj); - } - } - - @Override - protected TypeInfo substitute(TypeInfoProjection[] prj) { - if(projections.length == 0) - return new TypeInfoImpl(signature.klazz, nullable, EMPTY); - else { - TypeInfoProjection [] proj = new TypeInfoProjection[projections.length]; - for(int i = 0; i != proj.length; ++i) { - final int finalI = i; - final TypeInfo substitute = projections[finalI].getType().substitute(prj); - proj[i] = new TypeInfoProjection(){ - - @Override - public TypeInfoVariance getVariance() { - return projections[finalI].getVariance(); - } - - @Override - public TypeInfo getType() { - return substitute; - } - - @Override - public String toString() { - return getVariance().toString() + " " + substitute; - } - }; - } - return new TypeInfoImpl(signature.klazz, nullable, proj); - } - } - - @Override - public final boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TypeInfoImpl typeInfo = (TypeInfoImpl) o; - - if (!signature.klazz.equals(typeInfo.signature.klazz)) return false; - if (nullable != typeInfo.nullable) return false; - if (!Arrays.equals(projections, typeInfo.projections)) return false; - - return true; - } - -// @NotNull - @Override - public TypeInfoVariance getVariance() { - return TypeInfoVariance.INVARIANT; - } - -// @NotNull - @Override - public TypeInfo getType() { - return this; - } - - @Override - public final int hashCode() { - return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections); - } - - public final boolean isInstance(Object obj) { - if (obj == null) return nullable; - - if (obj instanceof JetObject) { - return ((TypeInfoImpl)((JetObject) obj).getTypeInfo()).isSubtypeOf(this); - } - - return signature.klazz.isAssignableFrom(obj.getClass()); // TODO - } - - @Override - public int getProjectionCount() { - return projections.length; - } - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder().append(signature.klazz.getName()); - if (projections.length != 0) { - sb.append("<"); - for (int i = 0; i != projections.length - 1; ++i) { - sb.append(projections[i].toString()).append(","); - } - sb.append(projections[projections.length - 1].toString()).append(">"); - } - if (nullable) - sb.append("?"); - return sb.toString(); - } - - @Override - public final TypeInfo getTypeInfo() { - if (typeInfo == null) { - // TODO: Implementation must be lazy, otherwise the result would be of an infinite size - throw new UnsupportedOperationException(); // TODO - } - return typeInfo; - } - - @Override - public JetObject getOuterObject() { - return null; - } - - public final boolean isSubtypeOf(TypeInfoImpl superType) { - if (nullable && !superType.nullable) { - return false; - } - if (!superType.signature.klazz.isAssignableFrom(signature.klazz)) { - return false; - } - if (superType.projections == null || superType.projections.length != projections.length) { - throw new IllegalArgumentException("inconsistent type info for the same class"); - } - for (int i = 0; i < projections.length; i++) { - // TODO handle variance here - if (!projections[i].getType().equals(superType.projections[i].getType())) { - return false; - } - } - return true; - } - - } - - public static class Signature { - final Class klazz; - - List variables; - Map varNames; - List superTypes; - - final HashMap superSignatures = new HashMap(); - - public Signature(Class klazz) { - this.klazz = klazz; - } - - protected void afterParse() { - List myVars = variables == null ? Collections.emptyList() : new LinkedList(); - if(variables != null) - for(int i = 0; i != variables.size(); ++i) - myVars.add(new TypeInfoVar(this, false, i)); - - for(TypeInfo superType : superTypes) { - if(superType instanceof TypeInfoImpl) { - TypeInfoImpl type = (TypeInfoImpl) superType; - Signature superSignature = Parser.parse(type.signature.klazz); - - TypeInfo substituted = type.substitute(myVars); - superSignatures.put(type.signature.klazz, substituted); - - List vars = Collections.emptyList(); - if(superType.getProjectionCount() != 0) { - vars = new LinkedList(); - for(int i=0; i != superType.getProjectionCount(); ++i) { - TypeInfo substitute = superType.getProjection(i).getType().substitute(myVars); - vars.add(substitute); - } - } - - for(Map.Entry entry : superSignature.superSignatures.entrySet()) { - superSignatures.put(entry.getKey(), entry.getValue().substitute(vars)); - } - } - } - } - } - - public static class Parser { - static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - static final WeakHashMap map = new WeakHashMap(); - - int cur; - final char [] string; - - final ClassLoader classLoader; - - Parser(String string, ClassLoader classLoader) { - this.classLoader = classLoader; - this.string = string.toCharArray(); - } - - public static Signature parse(Class klass) { - if(klass == null) - return null; - -// lock.readLock().lock(); - Signature sig = map.get(klass); -// lock.readLock().unlock(); - if (sig == null) { -// lock.writeLock().lock(); - - sig = map.get(klass); - if (sig == null) { - sig = internalParse(klass); - } - -// lock.writeLock().unlock(); - } - return sig; - } - - private static Signature internalParse(Class klass) { - if(klass.isArray() && !klass.getComponentType().isPrimitive()) { - Signature signature = new ArraySignature(klass); - map.put(klass, signature); - return signature; - } - - JetSignature annotation = (JetSignature) klass.getAnnotation(JetSignature.class); - if(annotation != null) { - String value = annotation.value(); - if(value != null) { - Parser parser = new Parser(value, klass.getClassLoader()); - Class enclosingClass = klass.getEnclosingClass(); - Signature signature = new Signature(klass); - map.put(klass, signature); - parser.parseVars(signature); - parser.parseTypes(signature); - signature.afterParse(); - return signature; - } - } - return getGenericSignature(klass); - } - - private static Signature getGenericSignature(Class klass) { - // todo complete impl - - java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass(); - Signature signature = new Signature(klass); - - TypeVariable[] typeParameters = klass.getTypeParameters(); - if(typeParameters == null || typeParameters.length == 0) { - signature.varNames = Collections.emptyMap(); - signature.variables = Collections.emptyList(); - } - else { - signature.varNames = new HashMap(); - signature.variables = new LinkedList(); - } - - if (typeParameters != null && typeParameters.length != 0) { - for (int i = 0; i < typeParameters.length; i++) { - TypeVariable typeParameter = typeParameters[i]; - signature.varNames.put(typeParameter.getName(), i); - final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, false, i); - signature.variables.add(new TypeInfoProjection(){ - - @Override - public TypeInfoVariance getVariance() { - return TypeInfoVariance.INVARIANT; - } - - @Override - public TypeInfo getType() { - return typeInfoVar; - } - - @Override - public String toString() { - return typeInfoVar.toString(); - } - }); - } - } - - return signature; - } - - public void parseVars(Signature signature) { - if (cur < string.length && string[cur] == '<') { - cur++; - while(cur < string.length && string[cur] != '>') { - if(signature.variables == null) { - signature.variables = new LinkedList(); - signature.varNames = new HashMap(); - } - signature.variables.add(parseVar(signature)); - } - cur++; - } - signature.variables = signature.variables == null ? Collections.emptyList() : signature.variables; - signature.varNames = signature.varNames == null ? Collections.emptyMap() : signature.varNames; - } - - private TypeInfoProjection parseVar(Signature signature) { - final TypeInfoVariance variance = parseVariance(); - String name = parseName(); - final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, signature.variables.size()); - signature.varNames.put(name, signature.variables.size()); - return new TypeInfoProjection(){ - @Override - public TypeInfoVariance getVariance() { - return variance; - } - - @Override - public TypeInfo getType() { - return typeInfoVar; - } - - @Override - public String toString() { - return typeInfoVar.toString(); - } - }; - } - - private String parseName() { - int c = cur; - while (string[c] != ';') { - c++; - } - String name = new String(string, cur, c - cur); - cur = c+1; - return name; - } - - private TypeInfoVariance parseVariance() { - if(string[cur] == 'i' && string[cur+1] == 'n' && string[cur+2] == ' ' ) { - cur += 3; - return TypeInfoVariance.IN; - } - else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+3] == ' ') { - cur += 4; - return TypeInfoVariance.OUT; - } - else { - return TypeInfoVariance.INVARIANT; - } - } - - public void parseTypes(Signature signature) { - List types = null; - while(cur != string.length) { - if(types == null) { - types = new LinkedList(); - } - types.add(parseType(signature)); - } - signature.superTypes = types == null ? Collections.emptyList() : types; - } - - private TypeInfo parseType(Signature signature) { - switch (string[cur]) { - case 'L': - cur++; - String name = parseName(); - Class aClass; - try { - aClass = classLoader.loadClass(name.replace('/','.')); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - List proj = null; - boolean nullable = false; - if(cur != string.length && string[cur] == '<') { - cur++; - while(string[cur] != '>') { - if(proj == null) - proj = new LinkedList(); - proj.add(parseProjection(signature)); - } - cur++; - } - if(cur != string.length && string[cur] == '?') { - cur++; - nullable = true; - } - if(proj == null) - proj = Collections.emptyList(); - return new TypeInfoImpl(aClass, nullable,proj.toArray(new TypeInfoProjection[proj.size()])); - - case 'T': - cur++; - return parseTypeVar(signature); - - default: - throw new IllegalStateException(new String(string)); - } - } - - private TypeInfo parseTypeVar(Signature signature) { - TypeInfoVariance variance = parseVariance(); - assert string[cur] == 'L'; - cur++; - String klazz = parseName().replace('/','.'); - String name = parseName(); - boolean nullable = false; - if(string[cur] == '?') { - nullable = true; - cur++; - } - - if(klazz.equals(signature.klazz.getName())) - return new TypeInfoVar(signature, nullable, signature.varNames.get(name)); - else { -// Signature sig = signature; -// while(!klazz.equals(sig.klazz.getName())) { -// sig = sig.outer; -// if(sig == null) -// throw new IllegalStateException(); -// } - - throw new UnsupportedOperationException("outer type info does not supported"); - } - } - - private TypeInfoProjection parseProjection(Signature signature) { - final TypeInfoVariance variance = parseVariance(); - final TypeInfo type = parseType(signature); - return new TypeInfoProjection(){ - @Override - public TypeInfoVariance getVariance() { - return variance; - } - - @Override - public TypeInfo getType() { - return type; - } - - @Override - public String toString() { - return type.toString(); - } - }; - } - - private static class ArraySignature extends Signature { - public ArraySignature(Class klass) { - super(klass); - variables = new LinkedList(); - varNames = new HashMap(); - varNames.put("T", 0); - final TypeInfoVar typeInfoVar = new TypeInfoVar(this, 0); - variables.add(new TypeInfoProjection(){ - @Override - public TypeInfoVariance getVariance() { - return TypeInfoVariance.INVARIANT; - } - - @Override - public TypeInfo getType() { - return typeInfoVar; - } - }); - } - } - } } diff --git a/stdlib/src/jet/typeinfo/TypeInfoProjection.java b/stdlib/src/jet/typeinfo/TypeInfoProjection.java index 654794eb539..8f20bcd52d0 100644 --- a/stdlib/src/jet/typeinfo/TypeInfoProjection.java +++ b/stdlib/src/jet/typeinfo/TypeInfoProjection.java @@ -12,38 +12,4 @@ public interface TypeInfoProjection { TypeInfo getType(); - abstract class TypeInfoProjectionImpl implements TypeInfoProjection { - private final TypeInfo type; - - TypeInfoProjectionImpl(TypeInfo typeInfo) { - this.type = typeInfo; - } - - @Override - public final TypeInfo getType() { - return type; - } - - @Override - public final boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TypeInfoProjectionImpl that = (TypeInfoProjectionImpl) o; - // no need to compare variance as we compared classes already - return type.equals(that.type); - } - - @Override - public final int hashCode() { - int result = type.hashCode(); - result = 31 * result + (getVariance().hashCode()); - return result; - } - - @Override - public final String toString() { - return (getVariance() == TypeInfoVariance.INVARIANT ? "" : getVariance().toString() + " ") + type; - } - } } diff --git a/stdlib/src/jet/typeinfo/internal/Signature.java b/stdlib/src/jet/typeinfo/internal/Signature.java new file mode 100644 index 00000000000..879ad3e46ae --- /dev/null +++ b/stdlib/src/jet/typeinfo/internal/Signature.java @@ -0,0 +1,60 @@ +package jet.typeinfo.internal; + +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** +* @author Stepan Koltsov +*/ +class Signature { + + // TODO: make all these fields private + + final Class klazz; + + List variables; + Map varNames; + List superTypes; + + HashMap superSignatures = new HashMap(); + + Signature(Class klazz) { + this.klazz = klazz; + } + + void afterParse() { + List myVars = variables == null ? Collections.emptyList() : new LinkedList(); + if(variables != null) + for(int i = 0; i != variables.size(); ++i) + myVars.add(new TypeInfoVar(this, false, i)); + + for(TypeInfo superType : superTypes) { + if(superType instanceof TypeInfoImpl) { + TypeInfoImpl type = (TypeInfoImpl) superType; + Signature superSignature = TypeInfoParser.parse(type.signature.klazz); + + TypeInfo substituted = TypeInfoUtils.substitute(type, myVars); + superSignatures.put(type.signature.klazz, substituted); + + List vars = Collections.emptyList(); + if(superType.getProjectionCount() != 0) { + vars = new LinkedList(); + for(int i=0; i != superType.getProjectionCount(); ++i) { + TypeInfo substitute = TypeInfoUtils.substitute(superType.getProjection(i).getType(), myVars); + vars.add(substitute); + } + } + + for(Map.Entry entry : superSignature.superSignatures.entrySet()) { + superSignatures.put(entry.getKey(), TypeInfoUtils.substitute(entry.getValue(), vars)); + } + } + } + } +} diff --git a/stdlib/src/jet/typeinfo/internal/TypeInfoImpl.java b/stdlib/src/jet/typeinfo/internal/TypeInfoImpl.java new file mode 100644 index 00000000000..fe784eb8eae --- /dev/null +++ b/stdlib/src/jet/typeinfo/internal/TypeInfoImpl.java @@ -0,0 +1,229 @@ +package jet.typeinfo.internal; + +import jet.JetObject; +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; +import jet.typeinfo.TypeInfoVariance; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; + +/** + * @author abreslav + * @author yole + * @author alex.tkachman + * @author Stepan Koltsov + */ +public class TypeInfoImpl extends TypeInfo implements TypeInfoProjection { + private final static TypeInfoProjection[] EMPTY = new TypeInfoProjection[0]; + + private TypeInfo typeInfo; + public final Signature signature; + private final boolean nullable; + private final TypeInfoProjection[] projections; + + public TypeInfoImpl(Class theClass, boolean nullable) { + this(theClass, nullable, EMPTY); + } + + public TypeInfoImpl(Class theClass, boolean nullable, TypeInfoProjection[] projections) { + this.signature = TypeInfoParser.parse(theClass); + this.nullable = nullable; + this.projections = projections; + if(signature.variables.size() != projections.length) + throw new IllegalStateException("Wrong signature " + theClass.getName()); + } + + public final TypeInfoProjection getProjection(int index) { + return projections[index]; + } + + @Override + public Object[] newArray(int length) { + return (Object[]) Array.newInstance(signature.klazz, length); + } + + @Override + public Class getJavaClass() { + return signature.klazz; + } + + public final Object getClassObject() { + try { + final Class implClass = signature.klazz.getClassLoader().loadClass(signature.klazz.getCanonicalName()); + final Field classobj = implClass.getField("$classobj"); + return classobj.get(null); + } catch (Exception e) { + return null; + } + } + + TypeInfo getSuperTypeInfo(Class klass) { + return signature.superSignatures.get(klass); + } + + public final TypeInfo getArgumentType(Class klass, int index) { + if(klass == this.signature.klazz) + return projections[index].getType(); + else { + return TypeInfoUtils.substitute(getSuperTypeInfo(klass), projections).getArgumentType(klass, index); + } + } + + TypeInfo substitute(final List myVars) { + if(projections.length == 0) + return new TypeInfoImpl(this.signature.klazz, nullable, EMPTY); + else { + TypeInfoProjection [] proj = new TypeInfoProjection[projections.length]; + for(int i = 0; i != proj.length; ++i) { + final int finalI = i; + final TypeInfo substitute = TypeInfoUtils.substitute(projections[finalI].getType(), myVars); + proj[i] = new TypeInfoProjection(){ + + @Override + public TypeInfoVariance getVariance() { + return projections[finalI].getVariance(); + } + + @Override + public TypeInfo getType() { + return substitute; + } + + @Override + public String toString() { + return getVariance().toString() + " " + substitute; + } + }; + } + return new TypeInfoImpl(this.signature.klazz, nullable, proj); + } + } + + TypeInfo substitute(TypeInfoProjection[] prj) { + if(projections.length == 0) + return new TypeInfoImpl(signature.klazz, nullable, EMPTY); + else { + TypeInfoProjection [] proj = new TypeInfoProjection[projections.length]; + for(int i = 0; i != proj.length; ++i) { + final int finalI = i; + final TypeInfo substitute = TypeInfoUtils.substitute(projections[finalI].getType(), prj); + proj[i] = new TypeInfoProjection(){ + + @Override + public TypeInfoVariance getVariance() { + return projections[finalI].getVariance(); + } + + @Override + public TypeInfo getType() { + return substitute; + } + + @Override + public String toString() { + return getVariance().toString() + " " + substitute; + } + }; + } + return new TypeInfoImpl(signature.klazz, nullable, proj); + } + } + + @Override + public final boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TypeInfoImpl typeInfo = (TypeInfoImpl) o; + + if (!signature.klazz.equals(typeInfo.signature.klazz)) return false; + if (nullable != typeInfo.nullable) return false; + if (!Arrays.equals(projections, typeInfo.projections)) return false; + + return true; + } + +// @NotNull + @Override + public TypeInfoVariance getVariance() { + return TypeInfoVariance.INVARIANT; + } + +// @NotNull + @Override + public TypeInfo getType() { + return this; + } + + @Override + public final int hashCode() { + return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections); + } + + public final boolean isInstance(Object obj) { + if (obj == null) return nullable; + + if (obj instanceof JetObject) { + return ((TypeInfoImpl)((JetObject) obj).getTypeInfo()).isSubtypeOf(this); + } + + return signature.klazz.isAssignableFrom(obj.getClass()); // TODO + } + + @Override + public int getProjectionCount() { + return projections.length; + } + + @Override + public final String toString() { + StringBuilder sb = new StringBuilder().append(signature.klazz.getName()); + if (projections.length != 0) { + sb.append("<"); + for (int i = 0; i != projections.length - 1; ++i) { + sb.append(projections[i].toString()).append(","); + } + sb.append(projections[projections.length - 1].toString()).append(">"); + } + if (nullable) + sb.append("?"); + return sb.toString(); + } + + @Override + public final TypeInfo getTypeInfo() { + if (typeInfo == null) { + // TODO: Implementation must be lazy, otherwise the result would be of an infinite size + throw new UnsupportedOperationException(); // TODO + } + return typeInfo; + } + + @Override + public JetObject getOuterObject() { + return null; + } + + public final boolean isSubtypeOf(TypeInfoImpl superType) { + if (nullable && !superType.nullable) { + return false; + } + if (!superType.signature.klazz.isAssignableFrom(signature.klazz)) { + return false; + } + if (superType.projections == null || superType.projections.length != projections.length) { + throw new IllegalArgumentException("inconsistent type info for the same class"); + } + for (int i = 0; i < projections.length; i++) { + // TODO handle variance here + if (!projections[i].getType().equals(superType.projections[i].getType())) { + return false; + } + } + return true; + } + +} diff --git a/stdlib/src/jet/typeinfo/internal/TypeInfoParser.java b/stdlib/src/jet/typeinfo/internal/TypeInfoParser.java new file mode 100644 index 00000000000..4ffdf66fc30 --- /dev/null +++ b/stdlib/src/jet/typeinfo/internal/TypeInfoParser.java @@ -0,0 +1,281 @@ +package jet.typeinfo.internal; + +import jet.typeinfo.JetSignature; +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; +import jet.typeinfo.TypeInfoVariance; +import jet.typeinfo.internal.signature.JetSignatureExceptionsAdapter; +import jet.typeinfo.internal.signature.JetSignatureReader; +import jet.typeinfo.internal.signature.JetSignatureVisitor; + +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.WeakHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** +* @author Stepan Koltsov +*/ +class TypeInfoParser { + static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + static final WeakHashMap map = new WeakHashMap(); + + public static Signature parse(Class klass) { + if(klass == null) + return null; + +// lock.readLock().lock(); + Signature sig = map.get(klass); +// lock.readLock().unlock(); + if (sig == null) { +// lock.writeLock().lock(); + + sig = map.get(klass); + if (sig == null) { + sig = internalParse(klass); + } + +// lock.writeLock().unlock(); + } + return sig; + } + + private static Signature internalParse(Class klass) { + if(klass.isArray() && !klass.getComponentType().isPrimitive()) { + Signature signature = new ArraySignature(klass); + map.put(klass, signature); + return signature; + } + + JetSignature annotation = (JetSignature) klass.getAnnotation(JetSignature.class); + if(annotation != null) { + String value = annotation.value(); + if(value != null) { + Class enclosingClass = klass.getEnclosingClass(); + Signature signature = new Signature(klass); + map.put(klass, signature); + parse(value, signature); + signature.afterParse(); + return signature; + } + } + return getGenericSignature(klass); + } + + private static void parse(String annotationValue, final Signature signature) { + signature.variables = new ArrayList(); + signature.varNames = new HashMap(); + signature.superTypes = new ArrayList(); + new JetSignatureReader(annotationValue).accept(new JetSignatureExceptionsAdapter() { + int varIndex = 0; + + @Override + public void visitFormalTypeParameter(String name, final TypeInfoVariance variance) { + + final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, signature.variables.size()); + + signature.varNames.put(name, signature.variables.size()); + TypeInfoProjection typeInfoProjection = new TypeInfoProjection() { + @Override + public TypeInfoVariance getVariance() { + return variance; + } + + @Override + public TypeInfo getType() { + return typeInfoVar; + } + + @Override + public String toString() { + return typeInfoVar.toString(); + } + }; + + signature.variables.add(typeInfoProjection); + // TODO: supers + // TODO: nullability + } + + @Override + public JetSignatureVisitor visitClassBound() { + return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { + @Override + protected void done(TypeInfo typeInfo) { + // TODO + } + }; + } + + @Override + public JetSignatureVisitor visitInterfaceBound() { + return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { + @Override + protected void done(TypeInfo typeInfo) { + // TODO + } + }; + } + + @Override + public JetSignatureVisitor visitSuperclass() { + return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { + @Override + protected void done(TypeInfo typeInfo) { + signature.superTypes.add(typeInfo); + signature.superSignatures.put(typeInfo.getJavaClass(), typeInfo); + } + }; + } + + @Override + public JetSignatureVisitor visitInterface() { + return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { + @Override + protected void done(TypeInfo typeInfo) { + signature.superTypes.add(typeInfo); + signature.superSignatures.put(typeInfo.getJavaClass(), typeInfo); + } + }; + } + }); + } + + + private static abstract class SignatureParserJetSignatureAdapter extends JetSignatureExceptionsAdapter { + private final ClassLoader classLoader; + private final Signature signature; + + protected SignatureParserJetSignatureAdapter(ClassLoader classLoader, Signature signature) { + this.classLoader = classLoader; + this.signature = signature; + } + + protected abstract void done(TypeInfo typeInfo); + + private Class klass; + private boolean nullable; + private List projections; + + @Override + public void visitClassType(String name, boolean nullable) { + try { + klass = classLoader.loadClass(name.replace('/', '.')); + } catch (ClassNotFoundException e) { + throw new RuntimeException(); + } + this.nullable = nullable; + this.projections = new ArrayList(); + } + + private static TypeInfoVariance parseVariance(char wildcard) { + switch (wildcard) { + case '=': return TypeInfoVariance.INVARIANT; + case '+': return TypeInfoVariance.OUT; + case '-': return TypeInfoVariance.IN; + default: throw new IllegalStateException(); + } + } + + @Override + public JetSignatureVisitor visitTypeArgument(final char wildcard) { + final TypeInfoVariance variance = parseVariance(wildcard); + return new SignatureParserJetSignatureAdapter(classLoader, signature) { + @Override + protected void done(TypeInfo typeInfo) { + projections.add(new TypeInfoProjectionImpl(typeInfo) { + @Override + public TypeInfoVariance getVariance() { + return variance; + } + }); + } + }; + } + + @Override + public void visitTypeVariable(String name, boolean nullable) { + Integer varIndex = signature.varNames.get(name); + if (varIndex == null) { + throw new IllegalStateException("unresolved type variable: " + name); + } + TypeInfoVar typeInfo = new TypeInfoVar(signature, nullable, varIndex); + done(typeInfo); + } + + @Override + public void visitEnd() { + done(new TypeInfoImpl(klass, nullable, projections.toArray(new TypeInfoProjection[0]))); + } + } + + + private static Signature getGenericSignature(Class klass) { + // todo complete impl + + java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass(); + Signature signature = new Signature(klass); + + TypeVariable[] typeParameters = klass.getTypeParameters(); + if(typeParameters == null || typeParameters.length == 0) { + signature.varNames = Collections.emptyMap(); + signature.variables = Collections.emptyList(); + } + else { + signature.varNames = new HashMap(); + signature.variables = new LinkedList(); + } + + if (typeParameters != null && typeParameters.length != 0) { + for (int i = 0; i < typeParameters.length; i++) { + TypeVariable typeParameter = typeParameters[i]; + signature.varNames.put(typeParameter.getName(), i); + final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, false, i); + signature.variables.add(new TypeInfoProjection(){ + + @Override + public TypeInfoVariance getVariance() { + return TypeInfoVariance.INVARIANT; + } + + @Override + public TypeInfo getType() { + return typeInfoVar; + } + + @Override + public String toString() { + return typeInfoVar.toString(); + } + }); + } + } + + return signature; + } + + private static class ArraySignature extends Signature { + public ArraySignature(Class klass) { + super(klass); + variables = new LinkedList(); + varNames = new HashMap(); + varNames.put("T", 0); + final TypeInfoVar typeInfoVar = new TypeInfoVar(this, 0); + variables.add(new TypeInfoProjection() { + @Override + public TypeInfoVariance getVariance() { + return TypeInfoVariance.INVARIANT; + } + + @Override + public TypeInfo getType() { + return typeInfoVar; + } + }); + } + } +} diff --git a/stdlib/src/jet/typeinfo/internal/TypeInfoProjectionImpl.java b/stdlib/src/jet/typeinfo/internal/TypeInfoProjectionImpl.java new file mode 100644 index 00000000000..94438ffbd5e --- /dev/null +++ b/stdlib/src/jet/typeinfo/internal/TypeInfoProjectionImpl.java @@ -0,0 +1,46 @@ +package jet.typeinfo.internal; + +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; +import jet.typeinfo.TypeInfoVariance; + +/** + * @author abreslav + * @author yole + * @author alex.tkachman + * @author Stepan Koltsov + */ +public abstract class TypeInfoProjectionImpl implements TypeInfoProjection { + private final TypeInfo type; + + public TypeInfoProjectionImpl(TypeInfo typeInfo) { + this.type = typeInfo; + } + + @Override + public final TypeInfo getType() { + return type; + } + + @Override + public final boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + jet.typeinfo.internal.TypeInfoProjectionImpl that = (jet.typeinfo.internal.TypeInfoProjectionImpl) o; + // no need to compare variance as we compared classes already + return type.equals(that.type); + } + + @Override + public final int hashCode() { + int result = type.hashCode(); + result = 31 * result + (getVariance().hashCode()); + return result; + } + + @Override + public final String toString() { + return (getVariance() == TypeInfoVariance.INVARIANT ? "" : getVariance().toString() + " ") + type; + } +} diff --git a/stdlib/src/jet/typeinfo/internal/TypeInfoUtils.java b/stdlib/src/jet/typeinfo/internal/TypeInfoUtils.java new file mode 100644 index 00000000000..15747bb7c74 --- /dev/null +++ b/stdlib/src/jet/typeinfo/internal/TypeInfoUtils.java @@ -0,0 +1,40 @@ +package jet.typeinfo.internal; + +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; + +import java.util.List; + +/** + * @author abreslav + * @author yole + * @author alex.tkachman + * @author Stepan Koltsov + */ +class TypeInfoUtils { + + static TypeInfo substitute(TypeInfo typeInfo, TypeInfoProjection[] projections) { + if (typeInfo instanceof TypeInfoImpl) { + TypeInfoImpl typeInfoImpl = (TypeInfoImpl) typeInfo; + return typeInfoImpl.substitute(projections); + } else if (typeInfo instanceof TypeInfoVar) { + TypeInfoVar typeInfoVar = (TypeInfoVar) typeInfo; + return typeInfoVar.substitute(projections); + } else { + throw new IllegalStateException(); + } + } + + static TypeInfo substitute(TypeInfo typeInfo, List myVars) { + if (typeInfo instanceof TypeInfoImpl) { + TypeInfoImpl typeInfoImpl = (TypeInfoImpl) typeInfo; + return typeInfoImpl.substitute(myVars); + } else if (typeInfo instanceof TypeInfoVar) { + TypeInfoVar typeInfoVar = (TypeInfoVar) typeInfo; + return typeInfoVar.substitute(myVars); + } else { + throw new IllegalStateException(); + } + } + +} diff --git a/stdlib/src/jet/typeinfo/internal/TypeInfoVar.java b/stdlib/src/jet/typeinfo/internal/TypeInfoVar.java new file mode 100644 index 00000000000..9b20798ab93 --- /dev/null +++ b/stdlib/src/jet/typeinfo/internal/TypeInfoVar.java @@ -0,0 +1,89 @@ +package jet.typeinfo.internal; + +import jet.JetObject; +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; + +import java.util.List; + +/** + * @author abreslav + * @author yole + * @author alex.tkachman + * @author Stepan Koltsov + */ +class TypeInfoVar extends TypeInfo { + final int varIndex; + final Signature signature; + final boolean nullable; + + public TypeInfoVar(Signature signature, Integer varIndex) { + this.signature = signature; + this.varIndex = varIndex; + nullable = false; + } + + public TypeInfoVar(Signature signature, boolean nullable, int varIndex) { + this.signature = signature; + this.nullable = nullable; + this.varIndex = varIndex; + } + + @Override + public Object[] newArray(int length) { + throw new UnsupportedOperationException(); + } + + @Override + public Class getJavaClass() { + throw new UnsupportedOperationException(); + } + + @Override + public Object getClassObject() { + throw new UnsupportedOperationException("Abstract TypeInfo"); + } + + @Override + public boolean isInstance(Object obj) { + throw new UnsupportedOperationException("Abstract TypeInfo"); + } + + @Override + public int getProjectionCount() { + return 0; + } + + @Override + public TypeInfoProjection getProjection(int index) { + throw new UnsupportedOperationException("Abstract TypeInfo"); + } + + @Override + public TypeInfo getArgumentType(Class klass, int index) { + throw new UnsupportedOperationException("Abstract TypeInfo"); + } + + TypeInfo substitute(List myVars) { + return myVars.get(varIndex); + } + + TypeInfo substitute(TypeInfoProjection[] projections) { + return projections[varIndex].getType(); + } + + @Override + public TypeInfo getTypeInfo() { + throw new UnsupportedOperationException("Abstract TypeInfo"); + } + + @Override + public JetObject getOuterObject() { + return null; + } + + @Override + public String toString() { + return "T:" + signature.klazz.getName() + ":" + varIndex; + } +} diff --git a/stdlib/src/jet/typeinfo/internal/signature/JetSignatureExceptionsAdapter.java b/stdlib/src/jet/typeinfo/internal/signature/JetSignatureExceptionsAdapter.java new file mode 100644 index 00000000000..02b54de2868 --- /dev/null +++ b/stdlib/src/jet/typeinfo/internal/signature/JetSignatureExceptionsAdapter.java @@ -0,0 +1,88 @@ +package jet.typeinfo.internal.signature; + +import jet.typeinfo.TypeInfoVariance; + +/** + * @author Stepan Koltsov + */ +public class JetSignatureExceptionsAdapter implements JetSignatureVisitor { + @Override + public void visitFormalTypeParameter(String name, TypeInfoVariance variance) { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitClassBound() { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitInterfaceBound() { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitSuperclass() { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitInterface() { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitParameterType() { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitReturnType() { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitExceptionType() { + throw new IllegalStateException(); + } + + @Override + public void visitBaseType(char descriptor, boolean nullable) { + throw new IllegalStateException(); + } + + @Override + public void visitTypeVariable(String name, boolean nullable) { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitArrayType(boolean nullable) { + throw new IllegalStateException(); + } + + @Override + public void visitClassType(String name, boolean nullable) { + throw new IllegalStateException(); + } + + @Override + public void visitInnerClassType(String name, boolean nullable) { + throw new IllegalStateException(); + } + + @Override + public void visitTypeArgument() { + throw new IllegalStateException(); + } + + @Override + public JetSignatureVisitor visitTypeArgument(char wildcard) { + throw new IllegalStateException(); + } + + @Override + public void visitEnd() { + throw new IllegalStateException(); + } +} diff --git a/stdlib/src/jet/typeinfo/internal/signature/JetSignatureReader.java b/stdlib/src/jet/typeinfo/internal/signature/JetSignatureReader.java index 3922801bbee..4b94431bf88 100644 --- a/stdlib/src/jet/typeinfo/internal/signature/JetSignatureReader.java +++ b/stdlib/src/jet/typeinfo/internal/signature/JetSignatureReader.java @@ -19,39 +19,7 @@ public class JetSignatureReader { public void accept(final JetSignatureVisitor v) { String signature = this.signature; int len = signature.length(); - int pos; - char c; - - if (signature.charAt(0) == '<') { - pos = 2; - do { - TypeInfoVariance variance; - if (signature.substring(pos).startsWith("in ")) { - variance = TypeInfoVariance.IN; - pos += "in ".length(); - } else if (signature.substring(pos).startsWith("out ")) { - variance = TypeInfoVariance.OUT; - pos += "out ".length(); - } else { - variance = TypeInfoVariance.INVARIANT; - pos += "".length(); - } - int end = signature.indexOf(':', pos); - v.visitFormalTypeParameter(signature.substring(pos - 1, end), variance); - pos = end + 1; - - c = signature.charAt(pos); - if (c == 'L' || c == '[' || c == 'T') { - pos = parseType(signature, pos, v.visitClassBound()); - } - - while ((c = signature.charAt(pos++)) == ':') { - pos = parseType(signature, pos, v.visitInterfaceBound()); - } - } while (c != '>'); - } else { - pos = 0; - } + int pos = acceptFormalTypeParameters(v); if (signature.charAt(pos) == '(') { pos++; @@ -70,6 +38,52 @@ public class JetSignatureReader { } } + public int acceptFormalTypeParameters(JetSignatureVisitor v) { + int pos; + char c; + if (signature.length() > 0 && signature.charAt(0) == '<') { + pos = 1; + do { + TypeInfoVariance variance; + if (signature.substring(pos).startsWith("in ")) { + variance = TypeInfoVariance.IN; + pos += "in ".length(); + } else if (signature.substring(pos).startsWith("out ")) { + variance = TypeInfoVariance.OUT; + pos += "out ".length(); + } else { + variance = TypeInfoVariance.INVARIANT; + pos += "".length(); + } + int end = signature.indexOf(':', pos); + if (end < 0) { + throw new IllegalStateException(); + } + v.visitFormalTypeParameter(signature.substring(pos, end), variance); + pos = end + 1; + + c = signature.charAt(pos); + if (c == 'L' || c == '[' || c == 'T' || c == '?') { + pos = parseType(signature, pos, v.visitClassBound()); + } + + while ((c = signature.charAt(pos++)) == ':') { + pos = parseType(signature, pos, v.visitInterfaceBound()); + } + } while (c != '>'); + } else { + pos = 0; + } + return pos; + } + + public void acceptFormalTypeParametersOnly(JetSignatureVisitor v) { + int r = acceptFormalTypeParameters(v); + if (r != signature.length()) { + throw new IllegalStateException(); + } + } + public int acceptType(JetSignatureVisitor v) { return parseType(this.signature, 0, v); }