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