KT-925 step methods for integral ranges

This commit is contained in:
Alex Tkachman
2012-01-06 13:11:44 +02:00
parent 4627738ca4
commit 1d2e237312
13 changed files with 467 additions and 55 deletions
@@ -1046,11 +1046,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
isInterface = CodegenUtil.isInterface(containingDeclaration);
}
else {
if(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT)
isInterface = false;
if(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.TRAIT)
isInterface = true;
else {
JetClass jetClass = (JetClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, containingDeclaration);
isInterface = jetClass == null || jetClass.isTrait();
isInterface = false;
}
}
}
@@ -2768,7 +2767,11 @@ If finally block is present, its last expression is the value of try expression.
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression);
assert jetType != null;
final DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (isClass(descriptor, "IntRange")) {
if (isClass(descriptor, "IntRange") ||
isClass(descriptor, "CharRange") ||
isClass(descriptor, "ByteRange") ||
isClass(descriptor, "LongRange") ||
isClass(descriptor, "ShortRange")) {
return true;
}
}
@@ -92,6 +92,7 @@ public class IntrinsicMethods {
declareOverload(myStdLib.getLibraryScope().getFunctions("Array"), 1, new NewArray());
declareOverload(myStdLib.getLibraryScope().getFunctions("sure"), 0, new Sure());
declareOverload(myStdLib.getLibraryScope().getFunctions("synchronized"), 1, new StupidSync());
declareOverload(myStdLib.getLibraryScope().getFunctions("iterator"), 0, new IteratorIterator());
declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT);
@@ -0,0 +1,21 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.ExpressionCodegen;
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;
/**
* @author alex.tkachman
*/
public class IteratorIterator implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List<JetExpression> arguments, StackValue receiver) {
return receiver;
}
}
@@ -19,19 +19,22 @@ public class RangeTo implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
if(arguments.size()==1) {
final Type leftType = receiver.type;
final Type rightType = codegen.expressionType(arguments.get(0));
receiver.put(Type.INT_TYPE, v);
codegen.gen(arguments.get(0), Type.INT_TYPE);
v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;");
return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
codegen.gen(arguments.get(0), rightType);
v.invokestatic("jet/runtime/Ranges", "rangeTo", "(" + receiver.type.getDescriptor() + leftType.getDescriptor() + ")" + expectedType.getDescriptor());
return StackValue.onStack(expectedType);
}
else {
JetBinaryExpression expression = (JetBinaryExpression) element;
final Type leftType = codegen.expressionType(expression.getLeft());
final Type rightType = codegen.expressionType(expression.getRight());
if (JetTypeMapper.isIntPrimitive(leftType)) {
codegen.gen(expression.getLeft(), Type.INT_TYPE);
codegen.gen(expression.getRight(), Type.INT_TYPE);
v.invokestatic(expectedType.getInternalName(), "rangeTo", "(" + leftType.getDescriptor() + leftType.getDescriptor() + ")" + expectedType.getDescriptor());
return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
codegen.gen(expression.getLeft(), leftType);
codegen.gen(expression.getRight(), rightType);
v.invokestatic("jet/runtime/Ranges", "rangeTo", "(" + leftType.getDescriptor() + rightType.getDescriptor() + ")" + expectedType.getDescriptor());
return StackValue.onStack(expectedType);
}
else {
throw new UnsupportedOperationException("ranges are only supported for int objects");
+25 -7
View File
@@ -22,53 +22,71 @@ fun <T : Any> T?.sure() : T
fun String?.plus(other: Any?) : String
fun <T> Iterator<T>.iterator() : Iterator<T>
trait Iterator<out T> {
fun next() : T
val hasNext : Boolean
}
fun ByteIterator.iterator() : ByteIterator
abstract open class ByteIterator() : Iterator<Byte> {
abstract open fun nextByte() : Byte
override fun next() : Byte
}
fun ShortIterator.iterator() : ShortIterator
abstract open class ShortIterator() : Iterator<Short> {
abstract open fun nextShort() : Short
override fun next() : Short
}
fun CharIterator.iterator() : CharIterator
abstract open class CharIterator() : Iterator<Char> {
abstract open fun nextChar() : Char
override fun next() : Char
}
fun IntIterator.iterator() : IntIterator
abstract open class IntIterator() : Iterator<Int> {
abstract open fun nextInt() : Int
override fun next() : Int
}
fun LongIterator.iterator() : LongIterator
abstract open class LongIterator() : Iterator<Long> {
abstract open fun nextLong() : Long
override fun next() : Long
}
fun FloatIterator.iterator() : FloatIterator
abstract open class FloatIterator() : Iterator<Float> {
abstract open fun nextFloat() : Float
override fun next() : Float
}
fun DoubleIterator.iterator() : DoubleIterator
abstract open class DoubleIterator() : Iterator<Double> {
abstract open fun nextDouble() : Double
override fun next() : Double
}
fun BooleanIterator.iterator() : BooleanIterator
abstract open class BooleanIterator() : Iterator<Boolean> {
abstract open fun nextBoolean() : Boolean
@@ -247,7 +265,7 @@ class IntRange(val start : Int, val size : Int, val isReversed : Boolean = false
fun minus() : IntRange
fun step(step: Int) : IntIterable
fun step(step: Int) : IntIterator
}
class LongRange(val start : Long, val size : Long, val isReversed : Boolean = false) : Range<Long>, LongIterable {
@@ -259,7 +277,7 @@ class LongRange(val start : Long, val size : Long, val isReversed : Boolean = fa
fun minus() : LongRange
fun step(step: Long) : LongIterable
fun step(step: Long) : LongIterator
}
class ByteRange(val start : Byte, val size : Int, val isReversed : Boolean = false) : Range<Byte>, ByteIterable {
@@ -271,7 +289,7 @@ class ByteRange(val start : Byte, val size : Int, val isReversed : Boolean = fal
fun minus() : ByteRange
fun step(step: Int) : ByteIterable
fun step(step: Int) : ByteIterator
}
class ShortRange(val start : Short, val size : Int, val isReversed : Boolean = false) : Range<Short>, ShortIterable {
@@ -283,7 +301,7 @@ class ShortRange(val start : Short, val size : Int, val isReversed : Boolean = f
fun minus() : ShortRange
fun step(step: Int) : ShortIterable
fun step(step: Int) : ShortIterator
}
class CharRange(val start : Char, val size : Int, val isReversed : Boolean = false) : Range<Char>, CharIterable {
@@ -295,7 +313,7 @@ class CharRange(val start : Char, val size : Int, val isReversed : Boolean = fal
fun minus() : CharRange
fun step(step: Int) : CharIterable
fun step(step: Int) : CharIterator
}
abstract class Number : Hashable {
@@ -635,8 +653,8 @@ class Char : Number, Comparable<Char> {
fun rangeTo(other : Float) : Range<Float>
fun rangeTo(other : Long) : LongRange
fun rangeTo(other : Int) : IntRange
fun rangeTo(other : Short) : IntRange
fun rangeTo(other : Byte) : IntRange
fun rangeTo(other : Short) : ShortRange
fun rangeTo(other : Byte) : CharRange
fun rangeTo(other : Char) : CharRange
fun inc() : Char
@@ -0,0 +1,54 @@
fun test1() : Boolean {
val r1 = 1..10
var s1 = 0
for(e in r1 step 2) {
s1 += e
}
return s1 == 25
}
fun test2() : Boolean {
val r1 = 1.byt..10.byt
var s1 = 0
for(e in r1 step 2) {
s1 += e
}
return s1 == 25
}
fun test3() : Boolean {
val r1 = 1.byt..10.lng
var s1 = 0.lng
for(e in r1 step 2) {
s1 += e
}
return s1 == 25.lng
}
fun test4() : Boolean {
val r1 = 1.byt..10.sht
var s1 = 0.sht
for(e in r1 step 2) {
s1 += e
}
return s1 == 25.sht
}
fun test5() : Boolean {
val r1 = 'a'..'h'
var s1 = 0
for(e in r1 step 2) {
s1 ++
}
return s1 == 4
}
fun box() : String {
if(test1().not()) return "test1 failed"
if(test2().not()) return "test2 failed"
if(test3().not()) return "test3 failed"
if(test4().not()) return "test4 failed"
if(test5().not()) return "test4 failed"
return "OK"
}
@@ -367,4 +367,8 @@ public class PrimitiveTypesTest extends CodegenTestCase {
public void testKt821 () {
blackBoxFile("regressions/kt821.kt");
}
public void testKt925 () {
blackBoxFile("regressions/kt925.kt");
}
}