IntRange allows empty and reversed ranges
This commit is contained in:
@@ -217,7 +217,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<JetExpression> 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, "<init>", 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");
|
||||
|
||||
@@ -170,16 +170,28 @@ trait Range<in T : Comparable<T>> {
|
||||
fun contains(item : T) : Boolean
|
||||
}
|
||||
|
||||
class IntRange(val start : Int, val excludedEnd : Int) : Range<Int>, Iterable<Int> {
|
||||
class IntRange(val start : Int, size : Int, reversed : Boolean = false) : Range<Int>, Iterable<Int> {
|
||||
fun iterator () : Iterator<Int>
|
||||
|
||||
fun contains (elem: Int) : Boolean
|
||||
|
||||
val size : Int
|
||||
|
||||
val end : Int
|
||||
|
||||
val reversed : Boolean
|
||||
}
|
||||
|
||||
class LongRange(val start : Long, val end : Long) : Range<Long>, Iterable<Long> {
|
||||
class LongRange(val start : Long, size : Long, reversed : Boolean = false) : Range<Long>, Iterable<Long> {
|
||||
fun iterator () : Iterator<Long>
|
||||
|
||||
fun contains (elem: Long) : Boolean
|
||||
|
||||
val size : Long
|
||||
|
||||
val end : Long
|
||||
|
||||
val reversed : Boolean
|
||||
}
|
||||
|
||||
abstract class Number : Hashable {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -5,34 +5,42 @@ import jet.typeinfo.TypeInfo;
|
||||
public final class IntRange implements Range<Integer>, Iterable<Integer>, 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<Integer> iterator() {
|
||||
return new MyIterator(startValue, excludedEndValue);
|
||||
return new MyIterator(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,27 +52,43 @@ public final class IntRange implements Range<Integer>, Iterable<Integer>, 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<Integer> {
|
||||
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
|
||||
|
||||
@@ -5,34 +5,42 @@ import jet.typeinfo.TypeInfo;
|
||||
public final class LongRange implements Range<Long>, Iterable<Long>, 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<Long> iterator() {
|
||||
return new MyIterator(startValue, excludedEndValue);
|
||||
return new MyIterator(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,27 +52,43 @@ public final class LongRange implements Range<Long>, Iterable<Long>, 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<Long> {
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user