array code gen rewrite and work in progress on outer type info
This commit is contained in:
@@ -45,9 +45,4 @@ public class ClassCodegen {
|
||||
}
|
||||
|
||||
|
||||
public static void newTypeInfo(InstructionAdapter v, boolean isNullable, Type asmType) {
|
||||
v.aconst(asmType);
|
||||
v.iconst(isNullable?1:0);
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -43,7 +46,7 @@ public class CodegenUtil {
|
||||
return getOuterClassDescriptor(classDescriptor) != null && !isClassObject(classDescriptor);
|
||||
}
|
||||
|
||||
public static ClassDescriptor getOuterClassDescriptor(ClassDescriptor descriptor) {
|
||||
public static ClassDescriptor getOuterClassDescriptor(DeclarationDescriptor descriptor) {
|
||||
DeclarationDescriptor outerDescriptor = descriptor.getContainingDeclaration();
|
||||
while(outerDescriptor != null) {
|
||||
if(outerDescriptor instanceof ClassDescriptor)
|
||||
@@ -54,6 +57,48 @@ public class CodegenUtil {
|
||||
return (ClassDescriptor) outerDescriptor;
|
||||
}
|
||||
|
||||
public static boolean hasOuterTypeInfo(ClassDescriptor descriptor) {
|
||||
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(descriptor);
|
||||
if(outerClassDescriptor == null)
|
||||
return false;
|
||||
|
||||
if(outerClassDescriptor.getTypeConstructor().getParameters().size() > 0)
|
||||
return true;
|
||||
|
||||
return hasOuterTypeInfo(outerClassDescriptor);
|
||||
}
|
||||
|
||||
public static boolean hasTypeInfoField(JetType type) {
|
||||
if(type.getConstructor().getParameters().size() > 0)
|
||||
return true;
|
||||
|
||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||
if(hasTypeInfoField(jetType))
|
||||
return true;
|
||||
}
|
||||
|
||||
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
|
||||
if(outerClassDescriptor == null)
|
||||
return false;
|
||||
|
||||
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
|
||||
}
|
||||
|
||||
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
||||
if(!exceptOwn) {
|
||||
if(!isInterface(type))
|
||||
if(hasTypeInfoField(type))
|
||||
return true;
|
||||
}
|
||||
|
||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||
if(hasDerivedTypeInfoField(jetType, false))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Type arrayElementType(Type type) {
|
||||
return Type.getType(type.getDescriptor().substring(1));
|
||||
}
|
||||
|
||||
@@ -17,11 +17,9 @@ public class ConstructorFrameMap extends FrameMap {
|
||||
private int myFirstTypeParameter = -1;
|
||||
private int myTypeParameterCount = 0;
|
||||
|
||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, OwnerKind kind) {
|
||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) {
|
||||
enterTemp(); // this
|
||||
ClassDescriptor classDescriptor = null;
|
||||
if (descriptor != null) {
|
||||
classDescriptor = descriptor.getContainingDeclaration();
|
||||
if (CodegenUtil.hasThis0(classDescriptor)) {
|
||||
myOuterThisIndex = enterTemp(); // outer class instance
|
||||
}
|
||||
@@ -37,7 +35,6 @@ public class ConstructorFrameMap extends FrameMap {
|
||||
enter(parameter, explicitArgTypes.get(i).getSize());
|
||||
}
|
||||
|
||||
|
||||
if (classDescriptor != null) {
|
||||
myTypeParameterCount = classDescriptor.getTypeConstructor().getParameters().size();
|
||||
if (kind == OwnerKind.IMPLEMENTATION) {
|
||||
|
||||
@@ -200,7 +200,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
final JetExpression loopRange = expression.getLoopRange();
|
||||
final JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, loopRange);
|
||||
Type loopRangeType = typeMapper.mapType(expressionType);
|
||||
if (loopRangeType.getSort() == Type.ARRAY) {
|
||||
if (state.getStandardLibrary().getArray().equals(expressionType.getConstructor().getDeclarationDescriptor())) {
|
||||
new ForInArrayLoopGenerator(expression, loopRangeType).invoke();
|
||||
return StackValue.none();
|
||||
}
|
||||
@@ -364,6 +364,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
protected void generatePrologue() {
|
||||
myLengthVar = myMap.enterTemp();
|
||||
gen(expression.getLoopRange(), loopRangeType);
|
||||
derefArray(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getLoopRange()));
|
||||
v.arraylength();
|
||||
v.store(myLengthVar, Type.INT_TYPE);
|
||||
myIndexVar = myMap.enterTemp();
|
||||
@@ -377,9 +378,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.ificmpge(end);
|
||||
|
||||
gen(expression.getLoopRange(), loopRangeType); // array
|
||||
derefArray(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getLoopRange()));
|
||||
v.load(myIndexVar, Type.INT_TYPE);
|
||||
v.aload(CodegenUtil.arrayElementType(loopRangeType));
|
||||
StackValue.onStack(CodegenUtil.arrayElementType(loopRangeType)).put(asmParamType, v);
|
||||
v.aload(asmParamType);
|
||||
StackValue.onStack(asmParamType).put(asmParamType, v);
|
||||
v.store(lookupLocal(parameterDescriptor), asmParamType);
|
||||
}
|
||||
|
||||
@@ -1622,9 +1624,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
else if (constructorDescriptor instanceof ConstructorDescriptor) {
|
||||
//noinspection ConstantConditions
|
||||
type = typeMapper.mapType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression), OwnerKind.IMPLEMENTATION);
|
||||
if (type.getSort() == Type.ARRAY) {
|
||||
generateNewArray(expression, type);
|
||||
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
type = typeMapper.mapType(expressionType, OwnerKind.IMPLEMENTATION);
|
||||
if (state.getStandardLibrary().getArray().equals(expressionType.getConstructor().getDeclarationDescriptor())) {
|
||||
generateNewArray(expression, expressionType);
|
||||
}
|
||||
else {
|
||||
ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration();
|
||||
@@ -1682,9 +1685,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return type;
|
||||
}
|
||||
|
||||
private void generateNewArray(JetCallExpression expression, Type type) {
|
||||
JetType arrayType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
|
||||
private void generateNewArray(JetCallExpression expression, JetType arrayType) {
|
||||
List<? extends ValueArgument> args = expression.getValueArguments();
|
||||
if (args.size() != 1) {
|
||||
throw new CompilationException("array constructor requires one value argument");
|
||||
@@ -1694,23 +1695,53 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
JetType elementType = typeMapper.getGenericsElementType(arrayType);
|
||||
if(elementType != null) {
|
||||
generateTypeInfo(elementType);
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "newArray", "(ILjet/typeinfo/TypeInfo;)[Ljava/lang/Object;");
|
||||
v.checkcast(type);
|
||||
v.invokestatic("jet/arrays/JetArray", "newArray", "(ILjet/typeinfo/TypeInfo;)Ljet/arrays/JetArray;");
|
||||
}
|
||||
else {
|
||||
v.newarray(CodegenUtil.arrayElementType(type));
|
||||
elementType = arrayType.getArguments().get(0).getType();
|
||||
JetStandardLibrary standardLibrary = state.getStandardLibrary();
|
||||
if (elementType.equals(standardLibrary.getIntType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newIntArray", "(I)Ljet/arrays/JetIntArray;");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getLongType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newLongArray", "(I)Ljet/arrays/JetLongArray;");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getShortType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newShortArray", "(I)Ljet/arrays/JetShortArray;");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getByteType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newByteArray", "(I)Ljet/arrays/JetByteArray;");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getCharType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newCharArray", "(I)Ljet/arrays/JetCharArray;");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getFloatType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newFloatArray", "(I)Ljet/arrays/JetFloatArray;");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getDoubleType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newDoubleArray", "(I)Ljet/arrays/JetDoubleArray;");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getBooleanType())) {
|
||||
v.invokestatic("jet/arrays/JetArray", "newBoolArray", "(I)Ljet/arrays/JetBoolArray;");
|
||||
}
|
||||
else {
|
||||
generateTypeInfo(elementType);
|
||||
v.invokestatic("jet/arrays/JetArray", "newGenericArray", "(ILjet/typeinfo/TypeInfo;)Ljet/arrays/JetGenericArray;");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitArrayAccessExpression(JetArrayAccessExpression expression, StackValue receiver) {
|
||||
final JetExpression array = expression.getArrayExpression();
|
||||
final Type arrayType = expressionType(array);
|
||||
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array);
|
||||
final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type);
|
||||
gen(array, arrayType);
|
||||
derefArray(type);
|
||||
generateArrayIndex(expression);
|
||||
if (arrayType.getSort() == Type.ARRAY) {
|
||||
final Type elementType = CodegenUtil.arrayElementType(arrayType);
|
||||
return StackValue.arrayElement(elementType);
|
||||
if (state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
|
||||
JetType elementType = type.getArguments().get(0).getType();
|
||||
return StackValue.arrayElement(typeMapper.mapType(elementType), typeMapper.isGenericsArray(type));
|
||||
}
|
||||
else {
|
||||
final PsiElement declaration = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, expression);
|
||||
@@ -1733,6 +1764,46 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
}
|
||||
|
||||
public void derefArray(JetType type) {
|
||||
if (state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
|
||||
JetType elementType = type.getArguments().get(0).getType();
|
||||
JetStandardLibrary standardLibrary = state.getStandardLibrary();
|
||||
if (elementType.equals(standardLibrary.getIntType())) {
|
||||
v.getfield("jet/arrays/JetIntArray", "array", "[I");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getLongType())) {
|
||||
v.getfield("jet/arrays/JetLongArray", "array", "[J");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getShortType())) {
|
||||
v.getfield("jet/arrays/JetShortArray", "array", "[S");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getByteType())) {
|
||||
v.getfield("jet/arrays/JetByteArray", "array", "[B");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getCharType())) {
|
||||
v.getfield("jet/arrays/JetCharArray", "array", "[C");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getFloatType())) {
|
||||
v.getfield("jet/arrays/JetFloatArray", "array", "[F");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getDoubleType())) {
|
||||
v.getfield("jet/arrays/JetDoubleArray", "array", "[D");
|
||||
}
|
||||
else if (elementType.equals(standardLibrary.getBooleanType())) {
|
||||
v.getfield("jet/arrays/JetBooleanArray", "array", "[Z");
|
||||
}
|
||||
else {
|
||||
if(typeMapper.isGenericsArray(type)) {
|
||||
v.visitTypeInsn(Opcodes.CHECKCAST, "jet/arrays/JetArray");
|
||||
}
|
||||
else {
|
||||
v.getfield("jet/arrays/JetGenericArray", "array", "[Ljava/lang/Object;");
|
||||
v.visitTypeInsn(Opcodes.CHECKCAST, "[" + typeMapper.mapType(elementType).getDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateArrayIndex(JetArrayAccessExpression expression) {
|
||||
final List<JetExpression> indices = expression.getIndexExpressions();
|
||||
for (JetExpression index : indices) {
|
||||
@@ -1989,9 +2060,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return;
|
||||
}
|
||||
|
||||
if(jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor)) {
|
||||
if(!CodegenUtil.hasTypeInfoField(jetType)) {
|
||||
// TODO: we need some better checks here
|
||||
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2044,23 +2115,33 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return;
|
||||
}
|
||||
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration == contextType() && contextType() instanceof ClassDescriptor) {
|
||||
if (contextType() instanceof ClassDescriptor) {
|
||||
ClassDescriptor descriptor = (ClassDescriptor) contextType();
|
||||
JetType defaultType = descriptor.getDefaultType();
|
||||
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
|
||||
Type ownerType = typeMapper.mapType(defaultType);
|
||||
ownerType = JetTypeMapper.boxType(ownerType);
|
||||
if(!CodegenUtil.isInterface(descriptor)) {
|
||||
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
if (containingDeclaration == contextType()) {
|
||||
if(!CodegenUtil.isInterface(descriptor)) {
|
||||
if (CodegenUtil.hasTypeInfoField(defaultType)) {
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
}
|
||||
else {
|
||||
v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
}
|
||||
else {
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
while(descriptor != containingDeclaration) {
|
||||
descriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
|
||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getOuterTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
}
|
||||
v.aconst(ownerType);
|
||||
v.iconst(typeParameterDescriptor.getIndex());
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
@@ -99,6 +98,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
);
|
||||
v.visitSource(myClass.getContainingFile().getName(), null);
|
||||
|
||||
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
v.visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
|
||||
}
|
||||
|
||||
if(myClass instanceof JetClass) {
|
||||
AnnotationVisitor annotationVisitor = v.visitAnnotation("Ljet/typeinfo/JetSignature;", true);
|
||||
annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper()));
|
||||
@@ -205,7 +208,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
Method method;
|
||||
CallableMethod callableMethod;
|
||||
if (constructorDescriptor == null) {
|
||||
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
if (CodegenUtil.hasThis0(descriptor)) {
|
||||
parameterTypes.add(state.getTypeMapper().jvmType(CodegenUtil.getOuterClassDescriptor(descriptor), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
|
||||
for (int n = typeParameters.size(); n > 0; n--) {
|
||||
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
||||
}
|
||||
|
||||
method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
|
||||
}
|
||||
else {
|
||||
@@ -220,13 +233,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
? constructorDescriptor.getValueParameters()
|
||||
: Collections.<ValueParameterDescriptor>emptyList();
|
||||
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, kind);
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind);
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||
|
||||
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
||||
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
if(constructorDescriptor != null)
|
||||
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
else
|
||||
codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
}
|
||||
|
||||
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
||||
@@ -241,7 +257,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
if (superCall == null || superCall instanceof JetDelegatorToSuperClass) {
|
||||
iv.load(0, Type.getType("L" + superClass + ";"));
|
||||
iv.invokespecial(superClass, "<init>", "()V");
|
||||
if(superCall == null) {
|
||||
iv.invokespecial(superClass, "<init>", "()V");
|
||||
}
|
||||
else {
|
||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, superCall.getTypeReference());
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
if (CodegenUtil.hasThis0(superClassDescriptor)) {
|
||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||
parameterTypes.add(state.getTypeMapper().jvmType(CodegenUtil.getOuterClassDescriptor(descriptor), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
|
||||
codegen.generateTypeInfo(typeParameterDescriptor.getType());
|
||||
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
||||
}
|
||||
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
iv.invokespecial(state.getTypeMapper().jvmName(superClassDescriptor, OwnerKind.IMPLEMENTATION), "<init>", superCallMethod.getDescriptor());
|
||||
}
|
||||
}
|
||||
else {
|
||||
iv.load(0, classType);
|
||||
@@ -285,7 +318,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.putfield(classname, fieldName, interfaceDesc);
|
||||
}
|
||||
|
||||
if (frameMap.getFirstTypeParameter() > 0 && kind == OwnerKind.IMPLEMENTATION) {
|
||||
if (CodegenUtil.hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
|
||||
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
|
||||
}
|
||||
|
||||
@@ -473,7 +506,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getSignature().getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, kind);
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||
@@ -507,17 +540,38 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.IMPLEMENTATION));
|
||||
iv.iconst(0);
|
||||
iv.iconst(typeParamCount);
|
||||
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
|
||||
for (int i = 0; i < typeParamCount; i++) {
|
||||
iv.dup();
|
||||
iv.iconst(i);
|
||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||
|
||||
if(typeParamCount != 0) {
|
||||
iv.iconst(typeParamCount);
|
||||
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
|
||||
for (int i = 0; i < typeParamCount; i++) {
|
||||
iv.dup();
|
||||
iv.iconst(i);
|
||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
|
||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
|
||||
iv.invokevirtual(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
|
||||
}
|
||||
|
||||
@@ -617,8 +671,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return;
|
||||
|
||||
JetType defaultType = descriptor.getDefaultType();
|
||||
if(isParametrizedClass(defaultType)) {
|
||||
if(!hasDerivedTypeInfoField(defaultType, true)) {
|
||||
if(CodegenUtil.hasTypeInfoField(defaultType)) {
|
||||
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
|
||||
v.visitField(Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
|
||||
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||
@@ -642,51 +696,45 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
else {
|
||||
if(descriptor.getTypeConstructor().getParameters().isEmpty()) {
|
||||
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(InstructionAdapter v) {
|
||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||
ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
|
||||
v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
});
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(InstructionAdapter v) {
|
||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||
ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
|
||||
v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
});
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
genGetStaticGetTypeInfoMethod();
|
||||
staticTypeInfoField();
|
||||
}
|
||||
}
|
||||
|
||||
private void genGetStaticGetTypeInfoMethod() {
|
||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void staticTypeInfoField() {
|
||||
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(InstructionAdapter v) {
|
||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||
v.aconst(typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
|
||||
v.iconst(0);
|
||||
ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
|
||||
if(outerClassDescriptor == null) {
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
v.getstatic(state.getTypeMapper().jvmName(outerClassDescriptor, OwnerKind.IMPLEMENTATION), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
v.putstatic(typeMapper.jvmName(descriptor, kind), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void generateClassObject(JetClassObject declaration) {
|
||||
state.forClass().generate(context, declaration.getObjectDeclaration());
|
||||
}
|
||||
@@ -737,30 +785,4 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static boolean isParametrizedClass(JetType type) {
|
||||
if(type.getConstructor().getParameters().size() > 0)
|
||||
return true;
|
||||
|
||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||
if(isParametrizedClass(jetType))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
||||
if(!exceptOwn) {
|
||||
if(!CodegenUtil.isInterface(type))
|
||||
if(isParametrizedClass(type))
|
||||
return true;
|
||||
}
|
||||
|
||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||
if(hasDerivedTypeInfoField(jetType, false))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +40,23 @@ public class JetTypeMapper {
|
||||
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
|
||||
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
|
||||
|
||||
public static final Type ARRAY_INT_TYPE = Type.getObjectType("jet/arrays/JetIntArray");
|
||||
public static final Type ARRAY_LONG_TYPE = Type.getObjectType("jet/arrays/JetLongArray");
|
||||
public static final Type ARRAY_SHORT_TYPE = Type.getObjectType("jet/arrays/JetShortArray");
|
||||
public static final Type ARRAY_BYTE_TYPE = Type.getObjectType("jet/arrays/JetByteArray");
|
||||
public static final Type ARRAY_CHAR_TYPE = Type.getObjectType("jet/arrays/JetCharArray");
|
||||
public static final Type ARRAY_FLOAT_TYPE = Type.getObjectType("jet/arrays/JetFloatArray");
|
||||
public static final Type ARRAY_DOUBLE_TYPE = Type.getObjectType("jet/arrays/JetDoubleArray");
|
||||
public static final Type ARRAY_BOOL_TYPE = Type.getObjectType("jet/arrays/JetBoolArray");
|
||||
public static final Type ARRAY_GENERIC_TYPE = Type.getObjectType("jet/arrays/JetGenericArray");
|
||||
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final BindingContext bindingContext;
|
||||
private final Map<JetExpression, String> classNamesForAnonymousClasses = new HashMap<JetExpression, String>();
|
||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||
|
||||
private final HashMap<JetType,String> knowTypes = new HashMap<JetType, String>();
|
||||
private final HashMap<JetType,String> knowArrayTypes = new HashMap<JetType, String>();
|
||||
|
||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
@@ -377,9 +388,36 @@ public class JetTypeMapper {
|
||||
if (jetType.getArguments().size() != 1) {
|
||||
throw new UnsupportedOperationException("arrays must have one type argument");
|
||||
}
|
||||
TypeProjection memberType = jetType.getArguments().get(0);
|
||||
Type elementType = mapType(memberType.getType());
|
||||
return Type.getType("[" + elementType.getDescriptor());
|
||||
JetType memberType = jetType.getArguments().get(0).getType();
|
||||
|
||||
if (memberType.equals(standardLibrary.getIntType())) {
|
||||
return ARRAY_INT_TYPE;
|
||||
}
|
||||
if (memberType.equals(standardLibrary.getLongType())) {
|
||||
return ARRAY_LONG_TYPE;
|
||||
}
|
||||
if (memberType.equals(standardLibrary.getShortType())) {
|
||||
return ARRAY_SHORT_TYPE;
|
||||
}
|
||||
if (memberType.equals(standardLibrary.getByteType())) {
|
||||
return ARRAY_BYTE_TYPE;
|
||||
}
|
||||
if (memberType.equals(standardLibrary.getCharType())) {
|
||||
return ARRAY_CHAR_TYPE;
|
||||
}
|
||||
if (memberType.equals(standardLibrary.getFloatType())) {
|
||||
return ARRAY_FLOAT_TYPE;
|
||||
}
|
||||
if (memberType.equals(standardLibrary.getDoubleType())) {
|
||||
return ARRAY_DOUBLE_TYPE;
|
||||
}
|
||||
if (memberType.equals(standardLibrary.getBooleanType())) {
|
||||
return ARRAY_BOOL_TYPE;
|
||||
}
|
||||
if(!isGenericsArray(jetType))
|
||||
return ARRAY_GENERIC_TYPE;
|
||||
else
|
||||
return TYPE_OBJECT;
|
||||
}
|
||||
if (JetStandardClasses.getAny().equals(descriptor)) {
|
||||
return Type.getType(Object.class);
|
||||
@@ -665,9 +703,21 @@ public class JetTypeMapper {
|
||||
knowTypes.put(standardLibrary.getNullableStringType(),"NULLABLE_STRING_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getTuple0Type(),"TUPLE0_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableTuple0Type(),"NULLABLE_TUPLE0_TYPE_INFO");
|
||||
|
||||
knowArrayTypes.put(standardLibrary.getIntType(), "INT_ARRAY_TYPE_INFO");
|
||||
knowArrayTypes.put(standardLibrary.getLongType(), "LONG_ARRAY_TYPE_INFO");
|
||||
knowArrayTypes.put(standardLibrary.getShortType(),"SHORT_ARRAY_TYPE_INFO");
|
||||
knowArrayTypes.put(standardLibrary.getByteType(),"BYTE_ARRAY_TYPE_INFO");
|
||||
knowArrayTypes.put(standardLibrary.getCharType(),"CHAR_ARRAY_TYPE_INFO");
|
||||
knowArrayTypes.put(standardLibrary.getFloatType(),"FLOAT_ARRAY_TYPE_INFO");
|
||||
knowArrayTypes.put(standardLibrary.getDoubleType(),"DOUBLE_ARRAY_TYPE_INFO");
|
||||
knowArrayTypes.put(standardLibrary.getBooleanType(),"BOOLEAN_ARRAY_TYPE_INFO");
|
||||
}
|
||||
|
||||
public String isKnownTypeInfo(JetType jetType) {
|
||||
if(standardLibrary.getArray().equals(jetType.getConstructor().getDeclarationDescriptor()))
|
||||
return knowArrayTypes.get(jetType.getArguments().get(0).getType());
|
||||
|
||||
return knowTypes.get(jetType);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
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.resolve.java.JavaClassDescriptor;
|
||||
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;
|
||||
|
||||
@@ -44,7 +40,11 @@ public class SignatureUtil {
|
||||
sb.append(type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
sb.append("T").append(descriptor.getName()).append(";");
|
||||
sb.append("T");
|
||||
sb.append(descriptor.getContainingDeclaration().getName());
|
||||
sb.append(";");
|
||||
sb.append(descriptor.getName());
|
||||
sb.append(";");
|
||||
}
|
||||
if(!jetType.getArguments().isEmpty()) {
|
||||
sb.append("<");
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.objectweb.asm.commons.Method;
|
||||
* @author yole
|
||||
*/
|
||||
public abstract class StackValue {
|
||||
protected final Type type;
|
||||
public final Type type;
|
||||
|
||||
public StackValue(Type type) {
|
||||
this.type = type;
|
||||
@@ -75,8 +75,8 @@ public abstract class StackValue {
|
||||
return new Invert(stackValue);
|
||||
}
|
||||
|
||||
public static StackValue arrayElement(Type type) {
|
||||
return new ArrayElement(type);
|
||||
public static StackValue arrayElement(Type type, boolean genericsArray) {
|
||||
return new ArrayElement(type, genericsArray);
|
||||
}
|
||||
|
||||
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter) {
|
||||
@@ -424,19 +424,32 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
private static class ArrayElement extends StackValue {
|
||||
public ArrayElement(Type type) {
|
||||
private boolean genericsArray;
|
||||
|
||||
public ArrayElement(Type type, boolean genericsArray) {
|
||||
super(type);
|
||||
this.genericsArray = genericsArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
v.aload(type); // assumes array and index are on the stack
|
||||
if(genericsArray) {
|
||||
v.invokevirtual("jet/arrays/JetArray", "get", "(I)Ljava/lang/Object;");
|
||||
}
|
||||
else {
|
||||
v.aload(this.type); // assumes array and index are on the stack
|
||||
}
|
||||
coerce(type, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(InstructionAdapter v) {
|
||||
v.astore(type); // assumes array and index are on the stack
|
||||
if(genericsArray) {
|
||||
v.invokevirtual("jet/arrays/JetArray", "set", "(ILjava/lang/Object;)V");
|
||||
}
|
||||
else {
|
||||
v.astore(type); // assumes array and index are on the stack
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
@@ -17,7 +18,33 @@ public class ArraySize implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
v.arraylength();
|
||||
if(receiver.type.equals(JetTypeMapper.TYPE_OBJECT)) {
|
||||
v.visitTypeInsn(Opcodes.CHECKCAST, "jet/arrays/JetArray");
|
||||
v.invokevirtual("jet/arrays/JetArray", "getSize", "()I");
|
||||
}
|
||||
else {
|
||||
if(receiver.type.equals(JetTypeMapper.ARRAY_BYTE_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[B");
|
||||
else if(receiver.type.equals(JetTypeMapper.ARRAY_SHORT_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[S");
|
||||
else if(receiver.type.equals(JetTypeMapper.ARRAY_INT_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[I");
|
||||
else if(receiver.type.equals(JetTypeMapper.ARRAY_LONG_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[J");
|
||||
else if(receiver.type.equals(JetTypeMapper.ARRAY_FLOAT_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[F");
|
||||
else if(receiver.type.equals(JetTypeMapper.ARRAY_DOUBLE_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[D");
|
||||
else if(receiver.type.equals(JetTypeMapper.ARRAY_CHAR_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[C");
|
||||
else if(receiver.type.equals(JetTypeMapper.ARRAY_BOOL_TYPE))
|
||||
v.getfield(receiver.type.getInternalName(), "array", "[Z");
|
||||
else
|
||||
v.getfield("jet/arrays/JetGenericArray", "array", "[Ljava/lang/Object;");
|
||||
|
||||
v.arraylength();
|
||||
}
|
||||
|
||||
return StackValue.onStack(Type.INT_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,22 +63,23 @@ public class JetStandardLibrary {
|
||||
private final ClassDescriptor typeInfoClass;
|
||||
|
||||
private final JetType byteType;
|
||||
private final JetType nullableByteType;
|
||||
private final JetType charType;
|
||||
private final JetType nullableCharType;
|
||||
private final JetType shortType;
|
||||
private final JetType nullableShortType;
|
||||
private final JetType intType;
|
||||
private final JetType nullableIntType;
|
||||
private final JetType longType;
|
||||
private final JetType nullableLongType;
|
||||
private final JetType floatType;
|
||||
private final JetType nullableFloatType;
|
||||
private final JetType doubleType;
|
||||
private final JetType nullableDoubleType;
|
||||
private final JetType booleanType;
|
||||
private final JetType nullableBooleanType;
|
||||
private final JetType stringType;
|
||||
|
||||
private final JetType nullableByteType;
|
||||
private final JetType nullableCharType;
|
||||
private final JetType nullableShortType;
|
||||
private final JetType nullableIntType;
|
||||
private final JetType nullableLongType;
|
||||
private final JetType nullableFloatType;
|
||||
private final JetType nullableDoubleType;
|
||||
private final JetType nullableBooleanType;
|
||||
private final JetType nullableTuple0Type;
|
||||
|
||||
public JetType getTuple0Type() {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
fun box() : String {
|
||||
val a : Array<Int> = Array<Int> (5)
|
||||
var i = 0
|
||||
var sum = 0
|
||||
for(el in 0..4) {
|
||||
a[i] = i++
|
||||
}
|
||||
for (el in a) {
|
||||
sum = sum + el
|
||||
}
|
||||
if(sum != 10) return "a failed"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fun box() : String {
|
||||
val b : Array<Int?> = Array<Int?> (5)
|
||||
var i = 0
|
||||
var sum = 0
|
||||
while(i < 5) {
|
||||
b[i] = i++
|
||||
}
|
||||
sum = 0
|
||||
for (el in b) {
|
||||
sum = sum + (el ?: 0)
|
||||
}
|
||||
System.out?.println(sum)
|
||||
if(sum != 10) return "b failed"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,22 +1,46 @@
|
||||
namespace test
|
||||
|
||||
class List<T>() {
|
||||
val a : Array<T> = Array<T>(1)
|
||||
class List<T>(len: Int) {
|
||||
val a : Array<T> = Array<T>(len)
|
||||
|
||||
fun reverse() {
|
||||
var i = 0
|
||||
var j = a.size-1
|
||||
while(i < j) {
|
||||
val x = a[i]
|
||||
a[i++] = a[j]
|
||||
a[j--] = x
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
val a = List<String>()
|
||||
val d = List<Int>(1)
|
||||
d.a[0] = 10
|
||||
println(d.a[0])
|
||||
|
||||
val a = List<String>(1)
|
||||
a.a[0] = "1"
|
||||
println(a.a[0])
|
||||
|
||||
val b = List<Int?>()
|
||||
val b = List<Int?>(1)
|
||||
b.a[0] = 10
|
||||
println(b.a[0])
|
||||
|
||||
val c = List<Array<Int>>()
|
||||
val c = List<Array<Int>>(1)
|
||||
c.a[0] = Array<Int>(4)
|
||||
println(c.a[0].size)
|
||||
|
||||
val e = List<Int>(5)
|
||||
e.a[0] = 0
|
||||
e.a[1] = 1
|
||||
e.a[2] = 2
|
||||
e.a[3] = 3
|
||||
e.a[4] = 4
|
||||
e.reverse()
|
||||
for(el in e.a)
|
||||
println(el)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
|
||||
@@ -8,18 +8,22 @@ trait javaUtilIterator<T> : java.util.Iterator<T> {
|
||||
}
|
||||
}
|
||||
|
||||
class MyIterator<T>(val array : ReadOnlyArray<T>) : javaUtilIterator<T> {
|
||||
private var index = 0
|
||||
|
||||
override fun hasNext() : Boolean = index < array.size
|
||||
|
||||
override fun next() : T = array.get(index++)
|
||||
}
|
||||
|
||||
trait ReadOnlyArray<out T> : ISized, java.lang.Iterable<T> {
|
||||
fun get(index : Int) : T
|
||||
|
||||
class MyIterator() : javaUtilIterator<T> {
|
||||
private var index = 0
|
||||
|
||||
override fun hasNext() : Boolean = index < size
|
||||
|
||||
override fun next() : T = get(index++)
|
||||
class Default {
|
||||
fun check(v: Any) = v is T
|
||||
}
|
||||
|
||||
override fun iterator() : java.util.Iterator<T> = MyIterator()
|
||||
override fun iterator() : java.util.Iterator<T> = MyIterator<T>(this)
|
||||
}
|
||||
|
||||
trait WriteOnlyArray<in T> : ISized {
|
||||
@@ -53,4 +57,4 @@ fun box() : String {
|
||||
System.out?.println(el)
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
class Box<T>() {
|
||||
open class Inner () {
|
||||
fun isT(s : Any) = if(s is T) "OK" else "fail"
|
||||
}
|
||||
|
||||
class Inner2() : Inner() {
|
||||
|
||||
}
|
||||
|
||||
fun inner() = Inner2()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return Box<String>.inner().isT("OK")
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import jet.arrays.JetGenericArray;
|
||||
import jet.arrays.JetIntArray;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ArrayGenTest extends CodegenTestCase {
|
||||
@@ -9,6 +13,7 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
|
||||
public void testKt326 () throws Exception {
|
||||
blackBoxFile("regressions/kt326.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testCreateMultiInt () throws Exception {
|
||||
@@ -16,7 +21,8 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
Method foo = generateFunction();
|
||||
Object invoke = foo.invoke(null);
|
||||
System.out.println(invoke.getClass());
|
||||
assertTrue(invoke instanceof int[][]);
|
||||
assertTrue(invoke instanceof JetGenericArray);
|
||||
assertTrue(((JetGenericArray)invoke).getTypeInfo() == TypeInfo.INT_ARRAY_TYPE_INFO);
|
||||
}
|
||||
|
||||
public void testCreateMultiString () throws Exception {
|
||||
@@ -24,18 +30,16 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
Method foo = generateFunction();
|
||||
Object invoke = foo.invoke(null);
|
||||
System.out.println(invoke.getClass());
|
||||
assertTrue(invoke instanceof String[][]);
|
||||
assertTrue(invoke instanceof JetGenericArray);
|
||||
}
|
||||
|
||||
public void testCreateMultiGenerics () throws Exception {
|
||||
/*
|
||||
loadText("class L<T>() { val a = Array<T>(5) } fun foo() = L<Int>.a");
|
||||
System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
Object invoke = foo.invoke(null);
|
||||
System.out.println(invoke.getClass());
|
||||
assertTrue(invoke instanceof Integer[]);
|
||||
*/
|
||||
assertTrue(invoke instanceof JetIntArray);
|
||||
}
|
||||
|
||||
public void testIntGenerics () throws Exception {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import jet.arrays.JetGenericArray;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
@@ -89,7 +92,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
String[] args = new String[] { "IntelliJ", " ", "IDEA" };
|
||||
assertEquals("IntelliJ IDEA", main.invoke(null, new Object[] { args }));
|
||||
assertEquals("IntelliJ IDEA", main.invoke(null, new Object[] { new JetGenericArray(args, TypeInfo.STRING_TYPE_INFO) }));
|
||||
}
|
||||
|
||||
public void testForInRange() throws Exception {
|
||||
@@ -145,6 +148,14 @@ public class ControlStructuresTest extends CodegenTestCase {
|
||||
blackBoxFile("controlStructures/forUserType.jet");
|
||||
}
|
||||
|
||||
public void testForIntArray() throws Exception {
|
||||
blackBoxFile("controlStructures/forIntArray.jet");
|
||||
}
|
||||
|
||||
public void testForNullableIntArray() throws Exception {
|
||||
blackBoxFile("controlStructures/forNullableIntArray.jet");
|
||||
}
|
||||
|
||||
public void testKt237() throws Exception {
|
||||
blackBoxFile("regressions/kt237.jet");
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import jet.IntRange;
|
||||
import jet.Tuple2;
|
||||
import jet.arrays.JetGenericArray;
|
||||
import jet.arrays.JetIntArray;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -19,7 +22,7 @@ public class NamespaceGenTest extends CodegenTestCase {
|
||||
System.out.println(text);
|
||||
|
||||
final Method main = generateFunction();
|
||||
Object[] args = new Object[] { new String[0] };
|
||||
Object[] args = new Object[] { new JetGenericArray(0, TypeInfo.STRING_TYPE_INFO) };
|
||||
main.invoke(null, args);
|
||||
}
|
||||
|
||||
@@ -343,14 +346,14 @@ public class NamespaceGenTest extends CodegenTestCase {
|
||||
public void testArrayRead() throws Exception {
|
||||
loadText("fun foo(c: Array<String>) = c[0]");
|
||||
final Method main = generateFunction();
|
||||
assertEquals("main", main.invoke(null, new Object[] { new String[] { "main" } }));
|
||||
assertEquals("main", main.invoke(null, new Object[] { new JetGenericArray(new String[] { "main" }, TypeInfo.STRING_TYPE_INFO) }));
|
||||
}
|
||||
|
||||
public void testArrayWrite() throws Exception {
|
||||
loadText("fun foo(c: Array<String>) { c[0] = \"jet\"; }");
|
||||
final Method main = generateFunction();
|
||||
String[] array = new String[] { null };
|
||||
main.invoke(null, new Object[] { array });
|
||||
main.invoke(null, new Object[] { new JetGenericArray(array, TypeInfo.STRING_TYPE_INFO) });
|
||||
assertEquals("jet", array[0]);
|
||||
}
|
||||
|
||||
@@ -359,22 +362,23 @@ public class NamespaceGenTest extends CodegenTestCase {
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
int[] data = new int[] { 5 };
|
||||
main.invoke(null, new Object[] { data });
|
||||
main.invoke(null, new Object[] { new JetIntArray(data) });
|
||||
assertEquals(10, data[0]);
|
||||
}
|
||||
|
||||
public void testArrayNew() throws Exception {
|
||||
loadText("fun foo() = Array<Int>(4)");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
int[] result = (int[]) main.invoke(null);
|
||||
assertEquals(4, result.length);
|
||||
JetIntArray result = (JetIntArray) main.invoke(null);
|
||||
assertEquals(4, result.array.length);
|
||||
}
|
||||
|
||||
public void testArraySize() throws Exception {
|
||||
loadText("fun foo(a: Array<Int>) = a.size");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
Object[] args = new Object[] { new int[4] };
|
||||
Object[] args = new Object[] { new JetIntArray(new int[4]) };
|
||||
int result = (Integer) main.invoke(null, args);
|
||||
assertEquals(4, result);
|
||||
|
||||
@@ -495,6 +499,7 @@ public class NamespaceGenTest extends CodegenTestCase {
|
||||
final Method main = generateFunction();
|
||||
final String[] args = new String[] { "foo", "bar" };
|
||||
//noinspection ImplicitArrayToString
|
||||
assertEquals("s" + args.toString(), main.invoke(null, "s", args));
|
||||
JetGenericArray jetGenericArray = new JetGenericArray(args, TypeInfo.STRING_TYPE_INFO);
|
||||
assertEquals("s" + jetGenericArray.toString(), main.invoke(null, "s", jetGenericArray));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@ public class TraitsTest extends CodegenTestCase {
|
||||
|
||||
public void testMultiple () throws Exception {
|
||||
blackBoxFile("traits/multiple.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testStdlib () throws Exception {
|
||||
blackBoxFile("traits/stdlib.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,5 +135,9 @@ public class TypeInfoTest extends CodegenTestCase {
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testInner() throws Exception {
|
||||
blackBoxFile("typeinfo/inner.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.JetObject;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public abstract class JetArray<T> implements JetObject {
|
||||
public abstract T get(int index);
|
||||
public abstract void set(int index, T value);
|
||||
public abstract int getSize();
|
||||
|
||||
public static JetArray newArray(int length, TypeInfo elementTypeInfo) {
|
||||
if(elementTypeInfo.equals(TypeInfo.BYTE_TYPE_INFO))
|
||||
return new JetByteArray(length);
|
||||
if(elementTypeInfo.equals(TypeInfo.SHORT_TYPE_INFO))
|
||||
return new JetShortArray(length);
|
||||
if(elementTypeInfo.equals(TypeInfo.INT_TYPE_INFO))
|
||||
return new JetIntArray(length);
|
||||
if(elementTypeInfo.equals(TypeInfo.LONG_TYPE_INFO))
|
||||
return new JetShortArray(length);
|
||||
if(elementTypeInfo.equals(TypeInfo.CHAR_TYPE_INFO))
|
||||
return new JetCharArray(length);
|
||||
if(elementTypeInfo.equals(TypeInfo.BOOL_TYPE_INFO))
|
||||
return new JetBoolArray(length);
|
||||
if(elementTypeInfo.equals(TypeInfo.FLOAT_TYPE_INFO))
|
||||
return new JetFloatArray(length);
|
||||
if(elementTypeInfo.equals(TypeInfo.DOUBLE_TYPE_INFO))
|
||||
return new JetDoubleArray(length);
|
||||
|
||||
return new JetGenericArray(length, elementTypeInfo);
|
||||
}
|
||||
|
||||
public static JetByteArray newByteArray(int length) {
|
||||
return new JetByteArray(length);
|
||||
}
|
||||
|
||||
public static JetShortArray newShortArray(int length) {
|
||||
return new JetShortArray(length);
|
||||
}
|
||||
|
||||
public static JetIntArray newIntArray(int length) {
|
||||
return new JetIntArray(length);
|
||||
}
|
||||
|
||||
public static JetLongArray newLongArray(int length) {
|
||||
return new JetLongArray(length);
|
||||
}
|
||||
|
||||
public static JetCharArray newCharArray(int length) {
|
||||
return new JetCharArray(length);
|
||||
}
|
||||
|
||||
public static JetBoolArray newBoolArray(int length) {
|
||||
return new JetBoolArray(length);
|
||||
}
|
||||
|
||||
public static JetFloatArray newFloatArray(int length) {
|
||||
return new JetFloatArray(length);
|
||||
}
|
||||
|
||||
public static JetDoubleArray newDoubleArray(int length) {
|
||||
return new JetDoubleArray(length);
|
||||
}
|
||||
|
||||
public static JetGenericArray newGenericArray(int length, TypeInfo typeInfo) {
|
||||
return new JetGenericArray(length, typeInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetBoolArray extends JetArray<Boolean> {
|
||||
public final boolean[] array;
|
||||
|
||||
public JetBoolArray(boolean[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetBoolArray(int length) {
|
||||
this.array = new boolean[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Boolean value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetByteArray extends JetArray<Byte> {
|
||||
public final byte[] array;
|
||||
|
||||
public JetByteArray(byte[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetByteArray(int length) {
|
||||
this.array = new byte[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Byte value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetCharArray extends JetArray<Character> {
|
||||
public final char[] array;
|
||||
|
||||
public JetCharArray(char[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetCharArray(int length) {
|
||||
this.array = new char[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Character value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetDoubleArray extends JetArray<Double> {
|
||||
public final double[] array;
|
||||
|
||||
public JetDoubleArray(double[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetDoubleArray(int length) {
|
||||
this.array = new double[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Double value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetFloatArray extends JetArray<Float> {
|
||||
public final float[] array;
|
||||
|
||||
public JetFloatArray(float[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetFloatArray(int length) {
|
||||
this.array = new float[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Float value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetGenericArray<T> extends JetArray<T> {
|
||||
public final T[] array;
|
||||
private final TypeInfo<T> typeInfo;
|
||||
|
||||
public JetGenericArray(T[] array, TypeInfo<T> typeInfo) {
|
||||
this.array = array;
|
||||
this.typeInfo = typeInfo;
|
||||
}
|
||||
|
||||
public JetGenericArray(int length, TypeInfo<T> typeInfo) {
|
||||
this.array = (T[]) TypeInfo.newArray(length, typeInfo);
|
||||
this.typeInfo = typeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, T value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return typeInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetIntArray extends JetArray<Integer> {
|
||||
public final int[] array;
|
||||
|
||||
public JetIntArray(int[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetIntArray(int length) {
|
||||
this.array = new int[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Integer value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetLongArray extends JetArray<Long> {
|
||||
public final long[] array;
|
||||
|
||||
public JetLongArray(long[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetLongArray(int length) {
|
||||
this.array = new long[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Long value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package jet.arrays;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class JetShortArray extends JetArray<Short> {
|
||||
public final short[] array;
|
||||
|
||||
public JetShortArray(short[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public JetShortArray(int length) {
|
||||
this.array = new short[length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short get(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Short value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package jet.typeinfo;
|
||||
|
||||
import jet.JetObject;
|
||||
import jet.Tuple0;
|
||||
import jet.arrays.*;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -25,6 +26,16 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
public static final TypeInfo<Boolean> BOOL_TYPE_INFO = getTypeInfo(Boolean.class, false);
|
||||
public static final TypeInfo<Float> FLOAT_TYPE_INFO = getTypeInfo(Float.class, false);
|
||||
public static final TypeInfo<Double> DOUBLE_TYPE_INFO = getTypeInfo(Double.class, false);
|
||||
|
||||
public static final TypeInfo<byte[]> BYTE_ARRAY_TYPE_INFO = getTypeInfo(byte[].class, false);
|
||||
public static final TypeInfo<short[]> SHORT_ARRAY_TYPE_INFO = getTypeInfo(short[].class, false);
|
||||
public static final TypeInfo<int[]> INT_ARRAY_TYPE_INFO = getTypeInfo(int[].class, false);
|
||||
public static final TypeInfo<long[]> LONG_ARRAY_TYPE_INFO = getTypeInfo(long[].class, false);
|
||||
public static final TypeInfo<char[]> CHAR_ARRAY_TYPE_INFO = getTypeInfo(char[].class, false);
|
||||
public static final TypeInfo<boolean[]> BOOL_ARRAY_TYPE_INFO = getTypeInfo(boolean[].class, false);
|
||||
public static final TypeInfo<float[]> FLOAT_ARRAY_TYPE_INFO = getTypeInfo(float[].class, false);
|
||||
public static final TypeInfo<double[]> DOUBLE_ARRAY_TYPE_INFO = getTypeInfo(double[].class, false);
|
||||
|
||||
public static final TypeInfo<String> STRING_TYPE_INFO = getTypeInfo(String.class, false);
|
||||
public static final TypeInfo<Tuple0> TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, false);
|
||||
|
||||
@@ -40,7 +51,31 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
public static final TypeInfo<Tuple0> NULLABLE_TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, true);
|
||||
|
||||
public static Object [] newArray(int length, TypeInfo typeInfo) {
|
||||
return (Object[]) Array.newInstance(((TypeInfoImpl) typeInfo).signature.klazz, length);
|
||||
Signature signature = ((TypeInfoImpl) typeInfo).signature;
|
||||
if(signature.klazz.isArray() && signature.klazz.getComponentType().isPrimitive()) {
|
||||
Class componentType = signature.klazz.getComponentType();
|
||||
if(componentType == byte.class)
|
||||
return (Object[]) Array.newInstance(JetByteArray.class, length);
|
||||
if(componentType == short.class)
|
||||
return (Object[]) Array.newInstance(JetShortArray.class, length);
|
||||
if(componentType == int.class)
|
||||
return (Object[]) Array.newInstance(JetIntArray.class, length);
|
||||
if(componentType == long.class)
|
||||
return (Object[]) Array.newInstance(JetLongArray.class, length);
|
||||
if(componentType == char.class)
|
||||
return (Object[]) Array.newInstance(JetCharArray.class, length);
|
||||
if(componentType == boolean.class)
|
||||
return (Object[]) Array.newInstance(JetBoolArray.class, length);
|
||||
if(componentType == float.class)
|
||||
return (Object[]) Array.newInstance(JetFloatArray.class, length);
|
||||
if(componentType == double.class)
|
||||
return (Object[]) Array.newInstance(JetDoubleArray.class, length);
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
else {
|
||||
return (Object[]) Array.newInstance(signature.klazz, length);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> TypeInfoProjection invariantProjection(final TypeInfo<T> typeInfo) {
|
||||
@@ -71,6 +106,14 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
return new TypeInfoImpl<T>(klazz, nullable);
|
||||
}
|
||||
|
||||
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfo outerTypeInfo) {
|
||||
return new TypeInfoImpl<T>(klazz, nullable, outerTypeInfo);
|
||||
}
|
||||
|
||||
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfo outerTypeInfo, TypeInfoProjection[] projections) {
|
||||
return new TypeInfoImpl<T>(klazz, nullable, outerTypeInfo, projections);
|
||||
}
|
||||
|
||||
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfoProjection[] projections) {
|
||||
return new TypeInfoImpl<T>(klazz, nullable, projections);
|
||||
}
|
||||
@@ -81,22 +124,29 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
|
||||
public abstract int getProjectionCount();
|
||||
|
||||
public abstract TypeInfo getOuterTypeInfo();
|
||||
|
||||
public abstract TypeInfoProjection getProjection(int index);
|
||||
|
||||
public abstract TypeInfo getArgumentType(Class klass, int index);
|
||||
|
||||
public abstract TypeInfo substitute(List<TypeInfo> myVars);
|
||||
protected abstract TypeInfo substitute(List<TypeInfo> myVars);
|
||||
|
||||
protected abstract TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] projections);
|
||||
|
||||
private static class TypeInfoVar<T> extends TypeInfo<T> {
|
||||
final int varIndex;
|
||||
final Signature signature;
|
||||
final boolean nullable;
|
||||
|
||||
private TypeInfoVar(Integer varIndex) {
|
||||
private TypeInfoVar(Signature signature, Integer varIndex) {
|
||||
this.signature = signature;
|
||||
this.varIndex = varIndex;
|
||||
nullable = false;
|
||||
}
|
||||
|
||||
public TypeInfoVar(boolean nullable, int varIndex) {
|
||||
public TypeInfoVar(Signature signature, boolean nullable, int varIndex) {
|
||||
this.signature = signature;
|
||||
this.nullable = nullable;
|
||||
this.varIndex = varIndex;
|
||||
}
|
||||
@@ -116,6 +166,11 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getOuterTypeInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfoProjection getProjection(int index) {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
@@ -132,7 +187,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeInfo substitute(TypeInfoProjection[] projections) {
|
||||
protected TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] projections) {
|
||||
return projections[varIndex].getType();
|
||||
}
|
||||
|
||||
@@ -143,7 +198,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "T:" + varIndex;
|
||||
return "T:" + signature.klazz.getName() + ":" + varIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,12 +207,22 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
private final Signature signature;
|
||||
private final boolean nullable;
|
||||
private final TypeInfoProjection[] projections;
|
||||
private final TypeInfo outerTypeInfo;
|
||||
|
||||
TypeInfoImpl(Class<T> theClass, boolean nullable) {
|
||||
this(theClass, nullable, EMPTY);
|
||||
private TypeInfoImpl(Class<T> theClass, boolean nullable) {
|
||||
this(theClass, nullable, null, EMPTY);
|
||||
}
|
||||
|
||||
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfo outerTypeInfo) {
|
||||
this(theClass, nullable, outerTypeInfo, EMPTY);
|
||||
}
|
||||
|
||||
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
|
||||
this(theClass, nullable, null, projections);
|
||||
}
|
||||
|
||||
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfo outerTypeInfo, TypeInfoProjection[] projections) {
|
||||
this.outerTypeInfo = outerTypeInfo;
|
||||
this.signature = Parser.parse(theClass);
|
||||
this.nullable = nullable;
|
||||
this.projections = projections;
|
||||
@@ -187,14 +252,14 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
if(klass == this.signature.klazz)
|
||||
return projections[index].getType();
|
||||
else {
|
||||
return getSuperTypeInfo(klass).substitute(projections).getArgumentType(klass, index);
|
||||
return getSuperTypeInfo(klass).substitute(outerTypeInfo, projections).getArgumentType(klass, index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo substitute(final List<TypeInfo> myVars) {
|
||||
if(projections.length == 0)
|
||||
return new TypeInfoImpl(signature.klazz, nullable, EMPTY);
|
||||
return new TypeInfoImpl(this.signature.klazz, nullable, EMPTY);
|
||||
else {
|
||||
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
|
||||
for(int i = 0; i != proj.length; ++i) {
|
||||
@@ -218,19 +283,19 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
};
|
||||
}
|
||||
return new TypeInfoImpl(signature.klazz, nullable, proj);
|
||||
return new TypeInfoImpl(this.signature.klazz, nullable, proj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeInfo substitute(TypeInfoProjection[] prj) {
|
||||
protected TypeInfo substitute(TypeInfo outer, 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);
|
||||
final TypeInfo substitute = projections[finalI].getType().substitute(outer, prj);
|
||||
proj[i] = new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
@@ -299,6 +364,11 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
return projections.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getOuterTypeInfo() {
|
||||
return outerTypeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
StringBuilder sb = new StringBuilder().append(signature.klazz.getName());
|
||||
@@ -344,25 +414,27 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
|
||||
}
|
||||
|
||||
protected abstract TypeInfo substitute(TypeInfoProjection[] projections);
|
||||
|
||||
public static class Signature {
|
||||
final Signature outer;
|
||||
final Class klazz;
|
||||
final List<TypeInfoProjection> variables;
|
||||
final List<TypeInfo> superTypes;
|
||||
|
||||
List<TypeInfoProjection> variables;
|
||||
Map<String,Integer> varNames;
|
||||
List<TypeInfo> superTypes;
|
||||
|
||||
final HashMap<Class,TypeInfo> superSignatures = new HashMap<Class,TypeInfo>();
|
||||
|
||||
public Signature(Class klazz, List<TypeInfoProjection> variables, List<TypeInfo> superTypes) {
|
||||
public Signature(Signature outer, Class klazz) {
|
||||
this.outer = outer;
|
||||
this.klazz = klazz;
|
||||
this.superTypes = superTypes;
|
||||
this.variables = variables;
|
||||
|
||||
}
|
||||
|
||||
protected void afterParse() {
|
||||
List<TypeInfo> myVars = variables == null ? Collections.<TypeInfo>emptyList() : new LinkedList<TypeInfo>();
|
||||
if(variables != null)
|
||||
for(int i = 0; i != variables.size(); ++i)
|
||||
myVars.add(new TypeInfoVar(false, i));
|
||||
|
||||
myVars.add(new TypeInfoVar(this, false, i));
|
||||
|
||||
for(TypeInfo superType : superTypes) {
|
||||
if(superType instanceof TypeInfoImpl) {
|
||||
TypeInfoImpl type = (TypeInfoImpl) superType;
|
||||
@@ -379,7 +451,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
vars.add(substitute);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(Map.Entry<Class,TypeInfo> entry : superSignature.superSignatures.entrySet()) {
|
||||
superSignatures.put(entry.getKey(), entry.getValue().substitute(vars));
|
||||
}
|
||||
@@ -395,8 +467,6 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
int cur;
|
||||
final char [] string;
|
||||
|
||||
Map<String,Integer> variables;
|
||||
|
||||
final ClassLoader classLoader;
|
||||
|
||||
Parser(String string, ClassLoader classLoader) {
|
||||
@@ -405,6 +475,9 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
|
||||
public static Signature parse(Class klass) {
|
||||
if(klass == null)
|
||||
return null;
|
||||
|
||||
lock.readLock().lock();
|
||||
Signature sig = map.get(klass);
|
||||
lock.readLock().unlock();
|
||||
@@ -414,7 +487,6 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
sig = map.get(klass);
|
||||
if (sig == null) {
|
||||
sig = internalParse(klass);
|
||||
map.put(klass, sig);
|
||||
}
|
||||
|
||||
lock.writeLock().unlock();
|
||||
@@ -428,7 +500,13 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
String value = annotation.value();
|
||||
if(value != null) {
|
||||
Parser parser = new Parser(value, klass.getClassLoader());
|
||||
return new Signature(klass, parser.parseVars(), parser.parseTypes());
|
||||
Class enclosingClass = klass.getEnclosingClass();
|
||||
Signature signature = new Signature(parse(enclosingClass), klass);
|
||||
map.put(klass, signature);
|
||||
parser.parseVars(signature);
|
||||
parser.parseTypes(signature);
|
||||
signature.afterParse();
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
return getGenericSignature(klass);
|
||||
@@ -437,21 +515,25 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
private static Signature getGenericSignature(Class klass) {
|
||||
// todo complete impl
|
||||
|
||||
java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass();
|
||||
Signature signature = new Signature(parse(klass.getEnclosingClass()), klass);
|
||||
|
||||
TypeVariable[] typeParameters = klass.getTypeParameters();
|
||||
Map<String,Integer> variables;
|
||||
List<TypeInfoProjection> vars;
|
||||
if(typeParameters == null || typeParameters.length == 0) {
|
||||
variables = Collections.emptyMap();
|
||||
vars = Collections.emptyList();
|
||||
signature.varNames = Collections.emptyMap();
|
||||
signature.variables = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
variables = new HashMap<String, Integer>();
|
||||
vars = new LinkedList<TypeInfoProjection>();
|
||||
signature.varNames = new HashMap<String, Integer>();
|
||||
signature.variables = new LinkedList<TypeInfoProjection>();
|
||||
}
|
||||
|
||||
if (typeParameters != null && typeParameters.length != 0) {
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
TypeVariable typeParameter = typeParameters[i];
|
||||
variables.put(typeParameter.getName(), i);
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(false, i);
|
||||
vars.add(new TypeInfoProjection(){
|
||||
signature.varNames.put(typeParameter.getName(), i);
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, false, i);
|
||||
signature.variables.add(new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
@@ -471,29 +553,27 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
}
|
||||
|
||||
List<TypeInfo> types = new LinkedList<TypeInfo>();
|
||||
java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass();
|
||||
return new Signature(klass, vars, types);
|
||||
return signature;
|
||||
}
|
||||
|
||||
public List<TypeInfoProjection> parseVars() {
|
||||
List<TypeInfoProjection> list = null;
|
||||
public void parseVars(Signature signature) {
|
||||
while(cur < string.length && string[cur] == 'T') {
|
||||
if(list == null) {
|
||||
list = new LinkedList<TypeInfoProjection>();
|
||||
variables = new HashMap<String, Integer>();
|
||||
if(signature.variables == null) {
|
||||
signature.variables = new LinkedList<TypeInfoProjection>();
|
||||
signature.varNames = new HashMap<String, Integer>();
|
||||
}
|
||||
cur++;
|
||||
list.add(parseVar());
|
||||
signature.variables.add(parseVar(signature));
|
||||
}
|
||||
return list == null ? Collections.<TypeInfoProjection>emptyList() : list;
|
||||
signature.variables = signature.variables == null ? Collections.<TypeInfoProjection>emptyList() : signature.variables;
|
||||
signature.varNames = signature.varNames == null ? Collections.<String,Integer>emptyMap() : signature.varNames;
|
||||
}
|
||||
|
||||
private TypeInfoProjection parseVar() {
|
||||
private TypeInfoProjection parseVar(Signature signature) {
|
||||
final TypeInfoVariance variance = parseVariance();
|
||||
String name = parseName();
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(variables.size());
|
||||
variables.put(name, variables.size());
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, signature.variables.size());
|
||||
signature.varNames.put(name, signature.variables.size());
|
||||
return new TypeInfoProjection(){
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
@@ -536,18 +616,18 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
}
|
||||
|
||||
public List<TypeInfo> parseTypes() {
|
||||
public void parseTypes(Signature signature) {
|
||||
List<TypeInfo> types = null;
|
||||
while(cur != string.length) {
|
||||
if(types == null) {
|
||||
types = new LinkedList<TypeInfo>();
|
||||
}
|
||||
types.add(parseType());
|
||||
types.add(parseType(signature));
|
||||
}
|
||||
return types == null ? Collections.<TypeInfo>emptyList() : types;
|
||||
signature.superTypes = types == null ? Collections.<TypeInfo>emptyList() : types;
|
||||
}
|
||||
|
||||
private TypeInfo parseType() {
|
||||
private TypeInfo parseType(Signature signature) {
|
||||
switch (string[cur]) {
|
||||
case 'L':
|
||||
cur++;
|
||||
@@ -565,7 +645,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
while(string[cur] != '>') {
|
||||
if(proj == null)
|
||||
proj = new LinkedList<TypeInfoProjection>();
|
||||
proj.add(parseProjection());
|
||||
proj.add(parseProjection(signature));
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
@@ -579,15 +659,16 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
|
||||
case 'T':
|
||||
cur++;
|
||||
return parseTypeVar();
|
||||
return parseTypeVar(signature);
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(new String(string));
|
||||
}
|
||||
}
|
||||
|
||||
private TypeInfo parseTypeVar() {
|
||||
private TypeInfo parseTypeVar(Signature signature) {
|
||||
TypeInfoVariance variance = parseVariance();
|
||||
String klazz = parseName();
|
||||
String name = parseName();
|
||||
boolean nullable = false;
|
||||
if(string[cur] == '?') {
|
||||
@@ -595,12 +676,23 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
cur++;
|
||||
}
|
||||
|
||||
return new TypeInfoVar(nullable, variables.get(name));
|
||||
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();
|
||||
}
|
||||
|
||||
return new TypeInfoVar(sig, nullable, sig.varNames.get(name));
|
||||
}
|
||||
}
|
||||
|
||||
private TypeInfoProjection parseProjection() {
|
||||
private TypeInfoProjection parseProjection(Signature signature) {
|
||||
final TypeInfoVariance variance = parseVariance();
|
||||
final TypeInfo type = parseType();
|
||||
final TypeInfo type = parseType(signature);
|
||||
return new TypeInfoProjection(){
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
|
||||
Reference in New Issue
Block a user