From e94087f41eb67d17bb62dca4fef32cbfd9954260 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 8 Oct 2011 16:26:49 +0200 Subject: [PATCH] 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; + } + } +}