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 {
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");
+14 -2
View File
@@ -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 {
+43 -19
View File
@@ -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
+43 -19
View File
@@ -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