array code gen rewrite and work in progress on outer type info

This commit is contained in:
Alex Tkachman
2011-09-29 12:55:35 +03:00
parent b40b7ada4d
commit ea9e1bee85
31 changed files with 1035 additions and 232 deletions
@@ -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"
}
+29 -5
View File
@@ -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"
}
+12 -8
View File
@@ -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"
}
}
+15
View File
@@ -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());
}
}
+67
View File
@@ -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);
}
}
+35
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}
+152 -60
View File
@@ -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() {