From 78e913762f56d659426e1a0b48aedfa136b53741 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 8 Oct 2011 09:42:25 +0200 Subject: [PATCH 1/4] arrays iterators --- .../jet/codegen/ExpressionCodegen.java | 14 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 36 +-- .../org/jetbrains/jet/codegen/StackValue.java | 3 + .../jet/codegen/intrinsics/ArrayIterator.java | 65 +++++ .../codegen/intrinsics/IntrinsicMethods.java | 11 + compiler/frontend/src/jet/Library.jet | 2 +- .../jet/lang/types/JetStandardLibrary.java | 3 +- .../jetbrains/jet/codegen/ArrayGenTest.java | 28 ++ stdlib/src/jet/arrays/ArrayIterator.java | 274 ++++++++++++++++++ 9 files changed, 410 insertions(+), 26 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java create mode 100644 stdlib/src/jet/arrays/ArrayIterator.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 91c126fd77d..6caf932976d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -52,8 +52,10 @@ public class ExpressionCodegen extends JetVisitor { private final InstructionAdapter v; private final FrameMap myMap; private final JetTypeMapper typeMapper; + private final GenerationState state; private final Type returnType; + private final BindingContext bindingContext; private final Map typeParameterExpressions = new HashMap(); private final ClassContext context; @@ -74,6 +76,14 @@ public class ExpressionCodegen extends JetVisitor { this.intrinsics = state.getIntrinsics(); } + public GenerationState getState() { + return state; + } + + public BindingContext getBindingContext() { + return bindingContext; + } + public JetTypeMapper getTypeMapper() { return state.getTypeMapper(); } @@ -921,7 +931,7 @@ public class ExpressionCodegen extends JetVisitor { callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd); } else if (fd instanceof FunctionDescriptor) { - callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd); + callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, null); } else { throw new UnsupportedOperationException("can't resolve declaration to callable: " + fd); @@ -2076,7 +2086,7 @@ public class ExpressionCodegen extends JetVisitor { } } - void generateTypeInfo(JetType jetType) { + public void generateTypeInfo(JetType jetType) { String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType); if(knownTypeInfo != null) { v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;"); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 2b6513a7a0f..a78333d30c9 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; -import jet.Function1; import jet.JetObject; import jet.typeinfo.TypeInfo; import jet.typeinfo.TypeInfoProjection; @@ -58,6 +57,7 @@ public class JetTypeMapper { private final HashMap knowTypes = new HashMap(); public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1"); + public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator"); public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; @@ -464,17 +464,16 @@ public class JetTypeMapper { } - private Method mapSignature(JetNamedFunction f, List valueParameterTypes, OwnerKind kind) { - final JetTypeReference receiverTypeRef = f.getReceiverTypeRef(); - final JetType receiverType = receiverTypeRef == null ? null : bindingContext.get(BindingContext.TYPE, receiverTypeRef); - final List parameters = f.getValueParameters(); + private Method mapSignature(FunctionDescriptor f, List valueParameterTypes, OwnerKind kind) { + final ReceiverDescriptor receiverTypeRef = f.getReceiver(); + final JetType receiverType = receiverTypeRef == ReceiverDescriptor.NO_RECEIVER ? null : receiverTypeRef.getType(); + final List parameters = f.getValueParameters(); List parameterTypes = new ArrayList(); if (receiverType != null) { parameterTypes.add(mapType(receiverType)); } - FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f); if(kind == OwnerKind.TRAIT_IMPL) { - ClassDescriptor containingDeclaration = (ClassDescriptor) functionDescriptor.getContainingDeclaration(); + ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration(); JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext); Type type = mapType(jetType); if(type.getInternalName().equals("java/lang/Object")) { @@ -484,24 +483,15 @@ public class JetTypeMapper { valueParameterTypes.add(type); parameterTypes.add(type); } - for (JetParameter parameter : parameters) { - final Type type = mapType(bindingContext.get(BindingContext.TYPE, parameter.getTypeReference())); + for (ValueParameterDescriptor parameter : parameters) { + final Type type = mapType(parameter.getOutType()); valueParameterTypes.add(type); parameterTypes.add(type); } for (int n = f.getTypeParameters().size(); n > 0; n--) { parameterTypes.add(TYPE_TYPEINFO); } - final JetTypeReference returnTypeRef = f.getReturnTypeRef(); - Type returnType; - if (returnTypeRef == null) { - assert functionDescriptor != null; - final JetType type = functionDescriptor.getReturnType(); - returnType = mapReturnType(type); - } - else { - returnType = mapReturnType(bindingContext.get(BindingContext.TYPE, returnTypeRef)); - } + Type returnType = mapReturnType(f.getReturnType()); return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); } @@ -515,9 +505,13 @@ public class JetTypeMapper { JetNamedFunction f = (JetNamedFunction) declaration; final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f); assert functionDescriptor != null; + return mapToCallableMethod(functionDescriptor, kind); + } + + public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); final List valueParameterTypes = new ArrayList(); - Method descriptor = mapSignature(f, valueParameterTypes, kind); + Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind); String owner; int invokeOpcode; boolean needsReceiver; @@ -525,7 +519,7 @@ public class JetTypeMapper { if (functionParent instanceof NamespaceDescriptor) { owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent)); invokeOpcode = Opcodes.INVOKESTATIC; - needsReceiver = f.getReceiverTypeRef() != null; + needsReceiver = functionDescriptor.getReceiver() != ReceiverDescriptor.NO_RECEIVER; } else if (functionParent instanceof ClassDescriptor) { ClassDescriptor containingClass = (ClassDescriptor) functionParent; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 7a7c280f8e1..f60fc9804cc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -197,6 +197,9 @@ public abstract class StackValue { if (type.getSort() == Type.BOOLEAN) { v.checkcast(JetTypeMapper.JL_BOOLEAN_TYPE); } + else if (type.getSort() == Type.CHAR) { + v.checkcast(JetTypeMapper.JL_CHAR_TYPE); + } else { v.checkcast(JetTypeMapper.JL_NUMBER_TYPE); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java new file mode 100644 index 00000000000..c61130a7b15 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java @@ -0,0 +1,65 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.psi.JetCallExpression; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.JetStandardLibrary; +import org.jetbrains.jet.lang.types.JetType; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +/** + * @author alex.tkachman + */ +public class ArrayIterator implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + receiver.put(JetTypeMapper.TYPE_OBJECT, v); + JetCallExpression call = (JetCallExpression) element; + FunctionDescriptor funDescriptor = (FunctionDescriptor) codegen.getBindingContext().get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call.getCalleeExpression()); + ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal(); + JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary(); + if(containingDeclaration.equals(standardLibrary.getArray())) { + codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType()); + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getByteArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([B)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getShortArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([S)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getIntArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([I)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getLongArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([J)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getFloatArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([F)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getDoubleArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([D)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getCharArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([C)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getBooleanArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Z)Ljet/Iterator;"); + } + else { + throw new UnsupportedOperationException(containingDeclaration.toString()); + } + return StackValue.onStack(JetTypeMapper.TYPE_ITERATOR); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index ce4c0e29b46..3c2eee1cadc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -34,6 +34,7 @@ public class IntrinsicMethods { private final Project myProject; private final JetStandardLibrary myStdLib; private final Map myMethods = new HashMap(); + private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator(); public IntrinsicMethods(Project project, JetStandardLibrary stdlib) { myProject = project; @@ -87,6 +88,16 @@ public class IntrinsicMethods { declareIntrinsicProperty("DoubleArray", "size", ARRAY_SIZE); declareIntrinsicProperty("CharArray", "size", ARRAY_SIZE); declareIntrinsicProperty("BooleanArray", "size", ARRAY_SIZE); + + declareOverload(myStdLib.getArray().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getByteArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getShortArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getIntArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getLongArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getFloatArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getDoubleArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getCharArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getBooleanArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); } private void declareIntrinsicStringMethods() { diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet index f11575b99d3..1c97f0374d4 100644 --- a/compiler/frontend/src/jet/Library.jet +++ b/compiler/frontend/src/jet/Library.jet @@ -42,7 +42,7 @@ fun Any?.toString() : String// = this === other trait Iterator { fun next() : T - abstract fun hasNext() : Boolean + fun hasNext() : Boolean } trait Iterable { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index 2036d25cafb..6029d19c358 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -312,8 +312,7 @@ public class JetStandardLibrary { @NotNull public JetType getArrayType(@NotNull JetType argument) { - Variance variance = Variance.INVARIANT; - return getArrayType(variance, argument); + return getArrayType(Variance.INVARIANT, argument); } @NotNull diff --git a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java index dcd5e4d9783..292fdbd2518 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java @@ -58,4 +58,32 @@ public class ArrayGenTest extends CodegenTestCase { System.out.println(invoke.getClass()); assertTrue(invoke instanceof Integer); } + + public void testIterator () throws Exception { + loadText("fun box() { val x = Array(5, { it } ).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } + + public void testPrimitiveIterator () throws Exception { + loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } + + public void testLongIterator () throws Exception { + loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } + + public void testCharIterator () throws Exception { + loadText("fun box() { val x = CharArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } } diff --git a/stdlib/src/jet/arrays/ArrayIterator.java b/stdlib/src/jet/arrays/ArrayIterator.java new file mode 100644 index 00000000000..3bbfac045f3 --- /dev/null +++ b/stdlib/src/jet/arrays/ArrayIterator.java @@ -0,0 +1,274 @@ +package jet.arrays; + +import jet.Iterator; +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; + +import java.lang.reflect.GenericArrayType; +import java.util.Arrays; + +/** + * @author alex.tkachman + */ +public abstract class ArrayIterator implements Iterator { + private final int size; + protected int index; + + protected ArrayIterator(int size) { + this.size = size; + } + + @Override + public boolean hasNext() { + return index < size; + } + + private static class GenericIterator extends ArrayIterator { + private final T[] array; + private final TypeInfo elementTypeInfo; + + private GenericIterator(T[] array, TypeInfo elementTypeInfo) { + super(array.length); + this.array = array; + this.elementTypeInfo = elementTypeInfo; + } + + @Override + public T next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.getTypeInfo(GenericIterator.class, false, null, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo}); + } + } + + public static Iterator iterator(T[] array, TypeInfo elementTypeInfo) { + return new GenericIterator(array, elementTypeInfo); + } + + private static class ByteIterator extends ArrayIterator { + private final byte[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(ByteIterator.class, false); + + private ByteIterator(byte[] array) { + super(array.length); + this.array = array; + } + + @Override + public Byte next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(byte[] array) { + return new ByteIterator(array); + } + + private static class ShortIterator extends ArrayIterator { + private final short[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(ShortIterator.class, false); + + private ShortIterator(short[] array) { + super(array.length); + this.array = array; + } + + @Override + public Short next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(short[] array) { + return new ShortIterator(array); + } + + private static class IntegerIterator extends ArrayIterator { + private final int[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(IntegerIterator.class, false); + + private IntegerIterator(int[] array) { + super(array.length); + this.array = array; + } + + @Override + public Integer next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(int[] array) { + return new IntegerIterator(array); + } + + private static class LongIterator extends ArrayIterator { + private final long[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(LongIterator.class, false); + + private LongIterator(long[] array) { + super(array.length); + this.array = array; + } + + @Override + public Long next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(long[] array) { + return new LongIterator(array); + } + + private static class FloatIterator extends ArrayIterator { + private final float[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(FloatIterator.class, false); + + private FloatIterator(float[] array) { + super(array.length); + this.array = array; + } + + @Override + public Float next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(float[] array) { + return new FloatIterator(array); + } + + private static class DoubleIterator extends ArrayIterator { + private final double[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(DoubleIterator.class, false); + + private DoubleIterator(double[] array) { + super(array.length); + this.array = array; + } + + @Override + public Double next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(double[] array) { + return new DoubleIterator(array); + } + + private static class CharacterIterator extends ArrayIterator { + private final char[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(CharacterIterator.class, false); + + private CharacterIterator(char[] array) { + super(array.length); + this.array = array; + } + + @Override + public Character next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(char[] array) { + return new CharacterIterator(array); + } + + private static class BooleanIterator extends ArrayIterator { + private final boolean[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(BooleanIterator.class, false); + + private BooleanIterator(boolean[] array) { + super(array.length); + this.array = array; + } + + @Override + public Boolean next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(boolean[] array) { + return new BooleanIterator(array); + } + + public static void main(String[] args) { + String[] strings = {"Byte", "byte", "Short", "short", "Integer", "int", "Long", "long", "Float", "float", "Double", "double", "Character", "char", "Boolean", "boolean"}; + for(int i = 0; i != strings.length; i += 2) { + String boxed = strings[i]; + String unboxed = strings[i+1]; + System.out.println(" private static class " + boxed + "Iterator extends ArrayIterator<" + boxed + "> {\n" + + " private final " + unboxed + "[] array;\n" + + " private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(" + boxed + "Iterator.class, false);\n" + + "\n" + + " private " + boxed + "Iterator(" + unboxed + "[] array) {\n" + + " super(array.length);\n" + + " this.array = array;\n" + + " }\n" + + "\n" + + " @Override\n" + + " public " + boxed + " next() {\n" + + " return array[index++];\n" + + " }\n" + + "\n" + + " @Override\n" + + " public TypeInfo getTypeInfo() {\n" + + " return typeInfo;\n" + + " }\n" + + " }\n" + + "\n" + + " public static Iterator<" + boxed + "> iterator(" + unboxed + "[] array) {\n" + + " return new " + boxed + "Iterator(array);\n" + + " }\n" + + ""); + } + } +} From e94087f41eb67d17bb62dca4fef32cbfd9954260 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 8 Oct 2011 16:26:49 +0200 Subject: [PATCH 2/4] array.indices --- .../jetbrains/jet/codegen/JetTypeMapper.java | 1 + .../jet/codegen/intrinsics/ArrayIndices.java | 21 +++++ .../codegen/intrinsics/IntrinsicMethods.java | 35 ++++++--- compiler/frontend/src/jet/Library.jet | 78 ++++++++++++------- .../jetbrains/jet/codegen/ArrayGenTest.java | 14 ++++ .../jet/codegen/NamespaceGenTest.java | 4 +- stdlib/src/jet/IntRange.java | 65 +++++++++++++--- stdlib/src/jet/LongRange.java | 75 ++++++++++++++++++ 8 files changed, 246 insertions(+), 47 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIndices.java create mode 100644 stdlib/src/jet/LongRange.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index a78333d30c9..9cf778f138a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -58,6 +58,7 @@ public class JetTypeMapper { private final HashMap knowTypes = new HashMap(); public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1"); public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator"); + public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange"); public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIndices.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIndices.java new file mode 100644 index 00000000000..4049e238e43 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIndices.java @@ -0,0 +1,21 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +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.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +public class ArrayIndices implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + receiver.put(JetTypeMapper.TYPE_OBJECT, v); + v.arraylength(); + v.invokestatic("jet/IntRange", "count", "(I)Ljet/IntRange;"); + return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 3c2eee1cadc..b1efba96116 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -29,7 +29,8 @@ public class IntrinsicMethods { private static final IntrinsicMethod DEC = new Increment(-1); private static final List PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double"); - public static final ArraySize ARRAY_SIZE = new ArraySize(); + public static final IntrinsicMethod ARRAY_SIZE = new ArraySize(); + public static final IntrinsicMethod ARRAY_INDICES = new ArrayIndices(); private final Project myProject; private final JetStandardLibrary myStdLib; @@ -89,15 +90,29 @@ public class IntrinsicMethods { declareIntrinsicProperty("CharArray", "size", ARRAY_SIZE); declareIntrinsicProperty("BooleanArray", "size", ARRAY_SIZE); - declareOverload(myStdLib.getArray().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getByteArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getShortArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getIntArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getLongArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getFloatArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getDoubleArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getCharArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); - declareOverload(myStdLib.getBooleanArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareIntrinsicProperty("Array", "indices", ARRAY_INDICES); + declareIntrinsicProperty("ByteArray", "indices", ARRAY_INDICES); + declareIntrinsicProperty("ShortArray", "indices", ARRAY_INDICES); + declareIntrinsicProperty("IntArray", "indices", ARRAY_INDICES); + declareIntrinsicProperty("LongArray", "indices", ARRAY_INDICES); + declareIntrinsicProperty("FloatArray", "indices", ARRAY_INDICES); + declareIntrinsicProperty("DoubleArray", "indices", ARRAY_INDICES); + declareIntrinsicProperty("CharArray", "indices", ARRAY_INDICES); + declareIntrinsicProperty("BooleanArray", "indices", ARRAY_INDICES); + + declareIterator(myStdLib.getArray()); + declareIterator(myStdLib.getByteArrayClass()); + declareIterator(myStdLib.getShortArrayClass()); + declareIterator(myStdLib.getIntArrayClass()); + declareIterator(myStdLib.getLongArrayClass()); + declareIterator(myStdLib.getFloatArrayClass()); + declareIterator(myStdLib.getDoubleArrayClass()); + declareIterator(myStdLib.getCharArrayClass()); + declareIterator(myStdLib.getBooleanArrayClass()); + } + + private void declareIterator(ClassDescriptor classDescriptor) { + declareOverload(classDescriptor.getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); } private void declareIntrinsicStringMethods() { diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet index 1c97f0374d4..7a763882893 100644 --- a/compiler/frontend/src/jet/Library.jet +++ b/compiler/frontend/src/jet/Library.jet @@ -54,6 +54,8 @@ class Array(val size : Int, init : fun(Int) : T = null ) { fun set(index : Int, value : T) : Unit fun iterator() : Iterator + + val indices : IntRange } class ByteArray(val size : Int) { @@ -61,6 +63,8 @@ class ByteArray(val size : Int) { fun set(index : Int, value : Byte) : Unit fun iterator() : Iterator + + val indices : IntRange } class ShortArray(val size : Int) { @@ -68,6 +72,8 @@ class ShortArray(val size : Int) { fun set(index : Int, value : Short) : Unit fun iterator() : Iterator + + val indices : IntRange } class IntArray(val size : Int) { @@ -75,6 +81,8 @@ class IntArray(val size : Int) { fun set(index : Int, value : Int) : Unit fun iterator() : Iterator + + val indices : IntRange } class LongArray(val size : Int) { @@ -82,6 +90,8 @@ class LongArray(val size : Int) { fun set(index : Int, value : Long) : Unit fun iterator() : Iterator + + val indices : IntRange } class FloatArray(val size : Int) { @@ -89,6 +99,8 @@ class FloatArray(val size : Int) { fun set(index : Int, value : Float) : Unit fun iterator() : Iterator + + val indices : IntRange } class DoubleArray(val size : Int) { @@ -96,6 +108,8 @@ class DoubleArray(val size : Int) { fun set(index : Int, value : Double) : Unit fun iterator() : Iterator + + val indices : IntRange } class CharArray(val size : Int) { @@ -103,6 +117,8 @@ class CharArray(val size : Int) { fun set(index : Int, value : Char) : Unit fun iterator() : Iterator + + val indices : IntRange } class BooleanArray(val size : Int) { @@ -110,6 +126,8 @@ class BooleanArray(val size : Int) { fun set(index : Int, value : Boolean) : Unit fun iterator() : Iterator + + val indices : IntRange } trait Comparable { @@ -152,8 +170,16 @@ trait Range> { fun contains(item : T) : Boolean } -class IntRange>(val start : Int, val end : Int) : Range, Iterable { +class IntRange(val start : Int, val excludedEnd : Int) : Range, Iterable { + fun iterator () : Iterator + fun contains (elem: Int) : Boolean +} + +class LongRange(val start : Long, val end : Long) : Range, Iterable { + fun iterator () : Iterator + + fun contains (elem: Long) : Boolean } abstract class Number : Hashable { @@ -349,11 +375,11 @@ class Long : Number, Comparable { fun rangeTo(other : Double) : Range fun rangeTo(other : Float) : Range - fun rangeTo(other : Long) : IntRange - fun rangeTo(other : Int) : IntRange - fun rangeTo(other : Short) : IntRange - fun rangeTo(other : Byte) : IntRange - fun rangeTo(other : Char) : IntRange + fun rangeTo(other : Long) : LongRange + fun rangeTo(other : Int) : LongRange + fun rangeTo(other : Short) : LongRange + fun rangeTo(other : Byte) : LongRange + fun rangeTo(other : Char) : LongRange fun inc() : Long fun dec() : Long @@ -420,11 +446,11 @@ class Int : Number, Comparable { fun rangeTo(other : Double) : Range fun rangeTo(other : Float) : Range - fun rangeTo(other : Long) : IntRange - fun rangeTo(other : Int) : IntRange - fun rangeTo(other : Short) : IntRange - fun rangeTo(other : Byte) : IntRange - fun rangeTo(other : Char) : IntRange + fun rangeTo(other : Long) : LongRange + fun rangeTo(other : Int) : IntRange + fun rangeTo(other : Short) : IntRange + fun rangeTo(other : Byte) : IntRange + fun rangeTo(other : Char) : IntRange fun inc() : Int fun dec() : Int @@ -491,11 +517,11 @@ class Char : Number, Comparable { fun rangeTo(other : Double) : Range fun rangeTo(other : Float) : Range - fun rangeTo(other : Long) : IntRange - fun rangeTo(other : Int) : IntRange - fun rangeTo(other : Short) : IntRange - fun rangeTo(other : Byte) : IntRange - fun rangeTo(other : Char) : IntRange + fun rangeTo(other : Long) : LongRange + fun rangeTo(other : Int) : IntRange + fun rangeTo(other : Short) : IntRange + fun rangeTo(other : Byte) : IntRange + fun rangeTo(other : Char) : IntRange fun inc() : Char fun dec() : Char @@ -554,11 +580,11 @@ class Short : Number, Comparable { fun rangeTo(other : Double) : Range fun rangeTo(other : Float) : Range - fun rangeTo(other : Long) : IntRange - fun rangeTo(other : Int) : IntRange - fun rangeTo(other : Short) : IntRange - fun rangeTo(other : Byte) : IntRange - fun rangeTo(other : Char) : IntRange + fun rangeTo(other : Long) : LongRange + fun rangeTo(other : Int) : IntRange + fun rangeTo(other : Short) : IntRange + fun rangeTo(other : Byte) : IntRange + fun rangeTo(other : Char) : IntRange fun inc() : Short fun dec() : Short @@ -617,11 +643,11 @@ class Byte : Number, Comparable { fun rangeTo(other : Double) : Range fun rangeTo(other : Float) : Range - fun rangeTo(other : Long) : IntRange - fun rangeTo(other : Int) : IntRange - fun rangeTo(other : Short) : IntRange - fun rangeTo(other : Byte) : IntRange - fun rangeTo(other : Char) : IntRange + fun rangeTo(other : Long) : LongRange + fun rangeTo(other : Int) : IntRange + fun rangeTo(other : Short) : IntRange + fun rangeTo(other : Byte) : IntRange + fun rangeTo(other : Char) : IntRange fun inc() : Byte fun dec() : Byte diff --git a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java index 292fdbd2518..a7aa2572f54 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java @@ -86,4 +86,18 @@ public class ArrayGenTest extends CodegenTestCase { Method foo = generateFunction(); foo.invoke(null); } + + public void testArrayIndices () throws Exception { + loadText("fun box() { val x = Array(5, {it}).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } + + public void testCharIndices () throws Exception { + loadText("fun box() { val x = CharArray(5).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } } diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index a1f2940a78e..4420f4c7321 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -433,8 +433,8 @@ public class NamespaceGenTest extends CodegenTestCase { final Method main = generateFunction(); IntRange result = (IntRange) main.invoke(null); assertTrue(result.contains(1)); - assertTrue(result.contains(10)); - assertFalse(result.contains(11)); + assertTrue(result.contains(9)); + assertFalse(result.contains(10)); } public void testSubstituteJavaMethodTypeParameters() throws Exception { diff --git a/stdlib/src/jet/IntRange.java b/stdlib/src/jet/IntRange.java index dc538cddc4b..67dd7c3ed52 100644 --- a/stdlib/src/jet/IntRange.java +++ b/stdlib/src/jet/IntRange.java @@ -1,28 +1,75 @@ package jet; -public class IntRange implements Range { +import jet.typeinfo.TypeInfo; + +public final class IntRange implements Range, Iterable, JetObject { + private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false); + private final int startValue; - private final int endValue; + private final int excludedEndValue; public IntRange(int startValue, int endValue) { this.startValue = startValue; - this.endValue = endValue; + this.excludedEndValue = endValue; } @Override public boolean contains(Integer item) { if (item == null) return false; - if (startValue <= endValue) { - return item >= startValue && item <= endValue; + if (startValue < excludedEndValue) { + return item >= startValue && item < excludedEndValue; } - return item <= startValue && item >= endValue; + return item <= startValue && item > excludedEndValue; } - public int getStartValue() { + public int getStart() { return startValue; } - public int getEndValue() { - return endValue; + public int getEnd() { + return excludedEndValue; + } + + @Override + public Iterator iterator() { + return new MyIterator(startValue, excludedEndValue); + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + + public static IntRange count(int length) { + return new IntRange(0, length); + } + + private static class MyIterator implements Iterator { + private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false); + private final int lastValue; + + private int cur; + private boolean reversed; + + public MyIterator(int startValue, int endValue) { + reversed = endValue <= startValue; + this.lastValue = reversed ? startValue : endValue-1; + cur = reversed ? endValue-1 : startValue; + } + + @Override + public boolean hasNext() { + return reversed ? cur >= lastValue : cur <= lastValue; + } + + @Override + public Integer next() { + return reversed ? cur-- : cur++; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } } } diff --git a/stdlib/src/jet/LongRange.java b/stdlib/src/jet/LongRange.java new file mode 100644 index 00000000000..05dff1bacba --- /dev/null +++ b/stdlib/src/jet/LongRange.java @@ -0,0 +1,75 @@ +package jet; + +import jet.typeinfo.TypeInfo; + +public final class LongRange implements Range, Iterable, JetObject { + private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false); + + private final long startValue; + private final long excludedEndValue; + + public LongRange(long startValue, long endValue) { + this.startValue = startValue; + this.excludedEndValue = endValue; + } + + @Override + public boolean contains(Long item) { + if (item == null) return false; + if (startValue < excludedEndValue) { + return item >= startValue && item < excludedEndValue; + } + return item <= startValue && item > excludedEndValue; + } + + public long getStart() { + return startValue; + } + + public long getEnd() { + return excludedEndValue; + } + + @Override + public Iterator iterator() { + return new MyIterator(startValue, excludedEndValue); + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + + public static IntRange count(int length) { + return new IntRange(0, length); + } + + private static class MyIterator implements Iterator { + private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false); + private final long lastValue; + + private long cur; + private boolean reversed; + + public MyIterator(long startValue, long endValue) { + reversed = endValue <= startValue; + this.lastValue = reversed ? startValue : endValue-1; + cur = reversed ? endValue-1 : startValue; + } + + @Override + public boolean hasNext() { + return reversed ? cur >= lastValue : cur <= lastValue; + } + + @Override + public Long next() { + return reversed ? cur-- : cur++; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } +} From 7bf066c4bfa0f5ed0ef03be6a2647d3d3e9ce303 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 8 Oct 2011 17:07:08 +0200 Subject: [PATCH 3/4] IntRange allows empty and reversed ranges --- .../jet/codegen/ExpressionCodegen.java | 4 +- .../jet/codegen/intrinsics/RangeTo.java | 10 +-- compiler/frontend/src/jet/Library.jet | 16 ++++- .../jet/codegen/NamespaceGenTest.java | 4 +- stdlib/src/jet/IntRange.java | 62 +++++++++++++------ stdlib/src/jet/LongRange.java | 62 +++++++++++++------ 6 files changed, 106 insertions(+), 52 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 6caf932976d..ea7afc3dd7b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -217,7 +217,7 @@ public class ExpressionCodegen extends JetVisitor { else { assert expressionType != null; final DeclarationDescriptor descriptor = expressionType.getConstructor().getDeclarationDescriptor(); - if (isClass(descriptor, "IntRange")) { // TODO IntRange subclasses + if (isClass(descriptor, "IntRange")) { // TODO IntRange subclasses (now IntRange is final) new ForInRangeLoopGenerator(expression, loopRangeType).invoke(); return StackValue.none(); } @@ -2297,7 +2297,7 @@ public class ExpressionCodegen extends JetVisitor { JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression); assert jetType != null; final DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); - if (isClass(descriptor, "IntRange")) { // TODO IntRange subclasses + if (isClass(descriptor, "IntRange")) { return true; } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java index 79953a13b0f..86850d21051 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java @@ -16,21 +16,15 @@ import java.util.List; * @author yole */ public class RangeTo implements IntrinsicMethod { - private static final String INT_RANGE_CONSTRUCTOR_DESCRIPTOR = "(II)V"; - private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class); - private static final String CLASS_INT_RANGE = "jet/IntRange"; - @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { JetBinaryExpression expression = (JetBinaryExpression) element; final Type leftType = codegen.expressionType(expression.getLeft()); if (JetTypeMapper.isIntPrimitive(leftType)) { - v.anew(INT_RANGE_TYPE); - v.dup(); codegen.gen(expression.getLeft(), Type.INT_TYPE); codegen.gen(expression.getRight(), Type.INT_TYPE); - v.invokespecial(CLASS_INT_RANGE, "", INT_RANGE_CONSTRUCTOR_DESCRIPTOR); - return StackValue.onStack(INT_RANGE_TYPE); + v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;"); + return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE); } else { throw new UnsupportedOperationException("ranges are only supported for int objects"); diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet index 7a763882893..0a57bbf4c91 100644 --- a/compiler/frontend/src/jet/Library.jet +++ b/compiler/frontend/src/jet/Library.jet @@ -170,16 +170,28 @@ trait Range> { fun contains(item : T) : Boolean } -class IntRange(val start : Int, val excludedEnd : Int) : Range, Iterable { +class IntRange(val start : Int, size : Int, reversed : Boolean = false) : Range, Iterable { fun iterator () : Iterator fun contains (elem: Int) : Boolean + + val size : Int + + val end : Int + + val reversed : Boolean } -class LongRange(val start : Long, val end : Long) : Range, Iterable { +class LongRange(val start : Long, size : Long, reversed : Boolean = false) : Range, Iterable { fun iterator () : Iterator fun contains (elem: Long) : Boolean + + val size : Long + + val end : Long + + val reversed : Boolean } abstract class Number : Hashable { diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index 4420f4c7321..a1f2940a78e 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -433,8 +433,8 @@ public class NamespaceGenTest extends CodegenTestCase { final Method main = generateFunction(); IntRange result = (IntRange) main.invoke(null); assertTrue(result.contains(1)); - assertTrue(result.contains(9)); - assertFalse(result.contains(10)); + assertTrue(result.contains(10)); + assertFalse(result.contains(11)); } public void testSubstituteJavaMethodTypeParameters() throws Exception { diff --git a/stdlib/src/jet/IntRange.java b/stdlib/src/jet/IntRange.java index 67dd7c3ed52..abeb2a0f696 100644 --- a/stdlib/src/jet/IntRange.java +++ b/stdlib/src/jet/IntRange.java @@ -5,34 +5,42 @@ import jet.typeinfo.TypeInfo; public final class IntRange implements Range, Iterable, JetObject { private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false); - private final int startValue; - private final int excludedEndValue; + private final int start; + private final int count; - public IntRange(int startValue, int endValue) { - this.startValue = startValue; - this.excludedEndValue = endValue; + public IntRange(int startValue, int count) { + this.start = startValue; + this.count = count; + } + + public IntRange(int startValue, int count, boolean reversed) { + this(startValue, reversed ? -count : count); } @Override public boolean contains(Integer item) { if (item == null) return false; - if (startValue < excludedEndValue) { - return item >= startValue && item < excludedEndValue; + if (count >= 0) { + return item >= start && item < start + count; } - return item <= startValue && item > excludedEndValue; + return item <= start && item > start + count; } public int getStart() { - return startValue; + return start; } public int getEnd() { - return excludedEndValue; + return start+count-1; + } + + public int getSize() { + return count < 0 ? -count : count; } @Override public Iterator iterator() { - return new MyIterator(startValue, excludedEndValue); + return new MyIterator(start, count); } @Override @@ -44,27 +52,43 @@ public final class IntRange implements Range, Iterable, JetObj return new IntRange(0, length); } + public static IntRange rangeTo(int from, int to) { + if(from > to) { + return new IntRange(to, from-to+1, true); + } + else { + return new IntRange(from, to-from+1); + } + } + private static class MyIterator implements Iterator { private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false); - private final int lastValue; private int cur; - private boolean reversed; + private int count; - public MyIterator(int startValue, int endValue) { - reversed = endValue <= startValue; - this.lastValue = reversed ? startValue : endValue-1; - cur = reversed ? endValue-1 : startValue; + private final boolean reversed; + + public MyIterator(int startValue, int count) { + cur = startValue; + reversed = count < 0; + this.count = reversed ? -count : count; } @Override public boolean hasNext() { - return reversed ? cur >= lastValue : cur <= lastValue; + return count > 0; } @Override public Integer next() { - return reversed ? cur-- : cur++; + count--; + if(reversed) { + return cur--; + } + else { + return cur++; + } } @Override diff --git a/stdlib/src/jet/LongRange.java b/stdlib/src/jet/LongRange.java index 05dff1bacba..7932f7d0b5d 100644 --- a/stdlib/src/jet/LongRange.java +++ b/stdlib/src/jet/LongRange.java @@ -5,34 +5,42 @@ import jet.typeinfo.TypeInfo; public final class LongRange implements Range, Iterable, JetObject { private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false); - private final long startValue; - private final long excludedEndValue; + private final long start; + private final long count; - public LongRange(long startValue, long endValue) { - this.startValue = startValue; - this.excludedEndValue = endValue; + public LongRange(long startValue, long count) { + this.start = startValue; + this.count = count; + } + + public LongRange(long startValue, long count, boolean reversed) { + this(startValue, reversed ? -count : count); } @Override public boolean contains(Long item) { if (item == null) return false; - if (startValue < excludedEndValue) { - return item >= startValue && item < excludedEndValue; + if (count >= 0) { + return item >= start && item < start + count; } - return item <= startValue && item > excludedEndValue; + return item <= start && item > start + count; } public long getStart() { - return startValue; + return start; } public long getEnd() { - return excludedEndValue; + return start+count-1; + } + + public long getSize() { + return count < 0 ? -count : count; } @Override public Iterator iterator() { - return new MyIterator(startValue, excludedEndValue); + return new MyIterator(start, count); } @Override @@ -44,27 +52,43 @@ public final class LongRange implements Range, Iterable, JetObject { return new IntRange(0, length); } + public static IntRange rangeTo(int from, int to) { + if(from > to) { + return new IntRange(to, from-to+1, true); + } + else { + return new IntRange(from, to-from+1); + } + } + private static class MyIterator implements Iterator { private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false); - private final long lastValue; private long cur; - private boolean reversed; + private long count; - public MyIterator(long startValue, long endValue) { - reversed = endValue <= startValue; - this.lastValue = reversed ? startValue : endValue-1; - cur = reversed ? endValue-1 : startValue; + private final boolean reversed; + + public MyIterator(long startValue, long count) { + cur = startValue; + reversed = count < 0; + this.count = reversed ? -count : count; } @Override public boolean hasNext() { - return reversed ? cur >= lastValue : cur <= lastValue; + return count > 0; } @Override public Long next() { - return reversed ? cur-- : cur++; + count--; + if(reversed) { + return cur--; + } + else { + return cur++; + } } @Override From 9f53486922e32415108d365416c2071e05e98ad7 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sun, 9 Oct 2011 10:33:23 +0200 Subject: [PATCH 4/4] failing test for kt343 --- idea/testData/codegen/regressions/kt343.jet | 16 ++++++++++++++++ .../org/jetbrains/jet/codegen/ClassGenTest.java | 5 +++++ 2 files changed, 21 insertions(+) create mode 100644 idea/testData/codegen/regressions/kt343.jet diff --git a/idea/testData/codegen/regressions/kt343.jet b/idea/testData/codegen/regressions/kt343.jet new file mode 100644 index 00000000000..d71ccc41a01 --- /dev/null +++ b/idea/testData/codegen/regressions/kt343.jet @@ -0,0 +1,16 @@ +import java.util.ArrayList + +fun box(): String { + val list = ArrayList() + val foo : fun() : Unit = { + list.add(2) //first exception + } + foo() + +// val bar = { +// val x = 1 //second exception +// } +// bar() + + return if (list.get(0) == 2) "OK" else "fail" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 17e5d4f9252..72a131c61c6 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -185,4 +185,9 @@ public class ClassGenTest extends CodegenTestCase { assertEquals(method.getReturnType().getName(), "java.lang.Object"); System.out.println(generateToText()); } + + public void testKt343 () throws Exception { + blackBoxFile("regressions/kt343.jet"); + System.out.println(generateToText()); + } }