提交 ea9e1bee 编写于 作者: A Alex Tkachman

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

上级 b40b7ada
......@@ -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;");
}
}
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);
}
......
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() {
......
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"
}
\ No newline at end of file
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"
}
\ No newline at end of file
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> {
}
}
trait ReadOnlyArray<out T> : ISized, java.lang.Iterable<T> {
fun get(index : Int) : T
class MyIterator() : javaUtilIterator<T> {
class MyIterator<T>(val array : ReadOnlyArray<T>) : javaUtilIterator<T> {
private var index = 0
override fun hasNext() : Boolean = index < size
override fun hasNext() : Boolean = index < array.size
override fun next() : T = array.get(index++)
}
override fun next() : T = get(index++)
trait ReadOnlyArray<out T> : ISized, java.lang.Iterable<T> {
fun get(index : Int) : T
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"
}
\ No newline at end of file
}
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")
}
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 {
......
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());
}
}
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);
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册