IntRange allows empty and reversed ranges

This commit is contained in:
Alex Tkachman
2011-10-08 17:07:08 +02:00
parent e94087f41e
commit 7bf066c4bf
6 changed files with 106 additions and 52 deletions
@@ -217,7 +217,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else { else {
assert expressionType != null; assert expressionType != null;
final DeclarationDescriptor descriptor = expressionType.getConstructor().getDeclarationDescriptor(); 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(); new ForInRangeLoopGenerator(expression, loopRangeType).invoke();
return StackValue.none(); return StackValue.none();
} }
@@ -2297,7 +2297,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression); JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression);
assert jetType != null; assert jetType != null;
final DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); final DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (isClass(descriptor, "IntRange")) { // TODO IntRange subclasses if (isClass(descriptor, "IntRange")) {
return true; return true;
} }
} }
@@ -16,21 +16,15 @@ import java.util.List;
* @author yole * @author yole
*/ */
public class RangeTo implements IntrinsicMethod { 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 @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
JetBinaryExpression expression = (JetBinaryExpression) element; JetBinaryExpression expression = (JetBinaryExpression) element;
final Type leftType = codegen.expressionType(expression.getLeft()); final Type leftType = codegen.expressionType(expression.getLeft());
if (JetTypeMapper.isIntPrimitive(leftType)) { if (JetTypeMapper.isIntPrimitive(leftType)) {
v.anew(INT_RANGE_TYPE);
v.dup();
codegen.gen(expression.getLeft(), Type.INT_TYPE); codegen.gen(expression.getLeft(), Type.INT_TYPE);
codegen.gen(expression.getRight(), Type.INT_TYPE); codegen.gen(expression.getRight(), Type.INT_TYPE);
v.invokespecial(CLASS_INT_RANGE, "<init>", INT_RANGE_CONSTRUCTOR_DESCRIPTOR); v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;");
return StackValue.onStack(INT_RANGE_TYPE); return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
} }
else { else {
throw new UnsupportedOperationException("ranges are only supported for int objects"); throw new UnsupportedOperationException("ranges are only supported for int objects");
+14 -2
View File
@@ -170,16 +170,28 @@ trait Range<in T : Comparable<T>> {
fun contains(item : T) : Boolean 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 iterator () : Iterator<Int>
fun contains (elem: Int) : Boolean 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 iterator () : Iterator<Long>
fun contains (elem: Long) : Boolean fun contains (elem: Long) : Boolean
val size : Long
val end : Long
val reversed : Boolean
} }
abstract class Number : Hashable { abstract class Number : Hashable {
@@ -433,8 +433,8 @@ public class NamespaceGenTest extends CodegenTestCase {
final Method main = generateFunction(); final Method main = generateFunction();
IntRange result = (IntRange) main.invoke(null); IntRange result = (IntRange) main.invoke(null);
assertTrue(result.contains(1)); assertTrue(result.contains(1));
assertTrue(result.contains(9)); assertTrue(result.contains(10));
assertFalse(result.contains(10)); assertFalse(result.contains(11));
} }
public void testSubstituteJavaMethodTypeParameters() throws Exception { public void testSubstituteJavaMethodTypeParameters() throws Exception {
+43 -19
View File
@@ -5,34 +5,42 @@ import jet.typeinfo.TypeInfo;
public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObject { public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObject {
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false); private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false);
private final int startValue; private final int start;
private final int excludedEndValue; private final int count;
public IntRange(int startValue, int endValue) { public IntRange(int startValue, int count) {
this.startValue = startValue; this.start = startValue;
this.excludedEndValue = endValue; this.count = count;
}
public IntRange(int startValue, int count, boolean reversed) {
this(startValue, reversed ? -count : count);
} }
@Override @Override
public boolean contains(Integer item) { public boolean contains(Integer item) {
if (item == null) return false; if (item == null) return false;
if (startValue < excludedEndValue) { if (count >= 0) {
return item >= startValue && item < excludedEndValue; return item >= start && item < start + count;
} }
return item <= startValue && item > excludedEndValue; return item <= start && item > start + count;
} }
public int getStart() { public int getStart() {
return startValue; return start;
} }
public int getEnd() { public int getEnd() {
return excludedEndValue; return start+count-1;
}
public int getSize() {
return count < 0 ? -count : count;
} }
@Override @Override
public Iterator<Integer> iterator() { public Iterator<Integer> iterator() {
return new MyIterator(startValue, excludedEndValue); return new MyIterator(start, count);
} }
@Override @Override
@@ -44,27 +52,43 @@ public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObj
return new IntRange(0, length); 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 static class MyIterator implements Iterator<Integer> {
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false); private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false);
private final int lastValue;
private int cur; private int cur;
private boolean reversed; private int count;
public MyIterator(int startValue, int endValue) { private final boolean reversed;
reversed = endValue <= startValue;
this.lastValue = reversed ? startValue : endValue-1; public MyIterator(int startValue, int count) {
cur = reversed ? endValue-1 : startValue; cur = startValue;
reversed = count < 0;
this.count = reversed ? -count : count;
} }
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return reversed ? cur >= lastValue : cur <= lastValue; return count > 0;
} }
@Override @Override
public Integer next() { public Integer next() {
return reversed ? cur-- : cur++; count--;
if(reversed) {
return cur--;
}
else {
return cur++;
}
} }
@Override @Override
+43 -19
View File
@@ -5,34 +5,42 @@ import jet.typeinfo.TypeInfo;
public final class LongRange implements Range<Long>, Iterable<Long>, JetObject { public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false); private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false);
private final long startValue; private final long start;
private final long excludedEndValue; private final long count;
public LongRange(long startValue, long endValue) { public LongRange(long startValue, long count) {
this.startValue = startValue; this.start = startValue;
this.excludedEndValue = endValue; this.count = count;
}
public LongRange(long startValue, long count, boolean reversed) {
this(startValue, reversed ? -count : count);
} }
@Override @Override
public boolean contains(Long item) { public boolean contains(Long item) {
if (item == null) return false; if (item == null) return false;
if (startValue < excludedEndValue) { if (count >= 0) {
return item >= startValue && item < excludedEndValue; return item >= start && item < start + count;
} }
return item <= startValue && item > excludedEndValue; return item <= start && item > start + count;
} }
public long getStart() { public long getStart() {
return startValue; return start;
} }
public long getEnd() { public long getEnd() {
return excludedEndValue; return start+count-1;
}
public long getSize() {
return count < 0 ? -count : count;
} }
@Override @Override
public Iterator<Long> iterator() { public Iterator<Long> iterator() {
return new MyIterator(startValue, excludedEndValue); return new MyIterator(start, count);
} }
@Override @Override
@@ -44,27 +52,43 @@ public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
return new IntRange(0, length); 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 static class MyIterator implements Iterator<Long> {
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false); private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false);
private final long lastValue;
private long cur; private long cur;
private boolean reversed; private long count;
public MyIterator(long startValue, long endValue) { private final boolean reversed;
reversed = endValue <= startValue;
this.lastValue = reversed ? startValue : endValue-1; public MyIterator(long startValue, long count) {
cur = reversed ? endValue-1 : startValue; cur = startValue;
reversed = count < 0;
this.count = reversed ? -count : count;
} }
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return reversed ? cur >= lastValue : cur <= lastValue; return count > 0;
} }
@Override @Override
public Long next() { public Long next() {
return reversed ? cur-- : cur++; count--;
if(reversed) {
return cur--;
}
else {
return cur++;
}
} }
@Override @Override