range standard implementation added. tests added.

This commit is contained in:
Pavel Talanov
2011-12-13 16:52:46 +04:00
parent aa35f00843
commit a105792a85
12 changed files with 331 additions and 18 deletions
@@ -317,11 +317,11 @@ public class AstUtil {
}
public static JsBinaryOperation equals(JsExpression arg1, JsExpression arg2) {
return new JsBinaryOperation(JsBinaryOperator.REF_EQ, arg1, arg2);
return new JsBinaryOperation(JsBinaryOperator.EQ, arg1, arg2);
}
public static JsBinaryOperation notEqual(JsExpression arg1, JsExpression arg2) {
return new JsBinaryOperation(JsBinaryOperator.REF_NEQ, arg1, arg2);
return new JsBinaryOperation(JsBinaryOperator.NEQ, arg1, arg2);
}
public static JsExpression equalsTrue(JsExpression expression, JsProgram program) {
@@ -28,13 +28,23 @@ public final class StandardClasses {
StandardClasses standardClasses = new StandardClasses(kotlinObjectScope);
declareArray(standardClasses, standardLibrary);
declareIterator(standardClasses, standardLibrary);
declareRange(standardClasses, standardLibrary);
declareJavaArrayList(standardClasses);
declareJavaSystem(standardClasses);
declareInteger(standardClasses);
declareJavaInteger(standardClasses);
return standardClasses;
}
private static void declareInteger(@NotNull StandardClasses standardClasses) {
//TODO: duplication
private static void declareRange(@NotNull StandardClasses standardClasses, @NotNull JetStandardLibrary standardLibrary) {
String intRangeFQName = "jet.IntRange";
standardClasses.declareStandardTopLevelObject(intRangeFQName, "NumberRange");
standardClasses.declareStandardInnerDeclaration(intRangeFQName, "<init>", "NumberRange");
declareMethods(standardClasses, intRangeFQName, "iterator", "contains");
declareProperties(standardClasses, intRangeFQName, "start", "size", "end", "reversed");
}
private static void declareJavaInteger(@NotNull StandardClasses standardClasses) {
String integerFQName = "<java_root>.java.lang.Integer";
standardClasses.declareStandardTopLevelObject(integerFQName, "Integer");
declareMethods(standardClasses, integerFQName, "parseInt");
@@ -87,6 +97,15 @@ public final class StandardClasses {
}
}
private static void declareProperties(@NotNull StandardClasses standardClasses,
@NotNull String classFQName,
@NotNull String... propertyNames) {
for (String propertyName : propertyNames) {
standardClasses.declareStandardInnerDeclaration(classFQName,
propertyName, Namer.getNameForGetter(propertyName));
}
}
@NotNull
private final JsScope kotlinScope;
@@ -11,7 +11,6 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.reference.AccessTranslator;
import static org.jetbrains.k2js.translate.utils.BindingUtils.isStatement;
import static org.jetbrains.k2js.translate.utils.BindingUtils.isVariableReassignment;
import static org.jetbrains.k2js.translate.utils.PsiUtils.*;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isIntrinsicOperation;
@@ -65,7 +64,9 @@ public abstract class IncrementTranslator extends AbstractTranslator {
}
private boolean returnValueIgnored() {
return isStatement(context().bindingContext(), expression);
//TODO: it's a hack but for now there is now legal way to know whether expression is statement or not.
return false;
//return isStatement(context().bindingContext(), expression);
}
@NotNull
@@ -115,6 +115,7 @@ public final class BindingUtils {
Boolean isStatement = context.get(BindingContext.STATEMENT, expression);
assert isStatement != null : "Invalid behaviour of get(BindingContext.STATEMENT)";
return isStatement;
// return IsStatement.isStatement(expression);
}
@NotNull
@@ -0,0 +1,77 @@
package org.jetbrains.k2js.translate.utils;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
/**
* @author Talanov Pavel
*/
@SuppressWarnings("NullableProblems")
public final class IsStatement {
private IsStatement() {
}
private static IsStatementVisitor visitor = new IsStatementVisitor();
public static boolean isStatement(@NotNull JetExpression expression) {
return (expression.accept(visitor, null));
}
private static final class IsStatementVisitor extends JetVisitor<Boolean, Void> {
@NotNull
private Boolean visitParent(@NotNull JetElement element) {
PsiElement parent = element.getParent();
assert parent != null : "Cannot visit top level expressions.";
assert parent instanceof JetElement : "Elements of Kotlin PSI must be instances of JetElement";
return ((JetElement) parent).accept(this, null);
}
@Override
@NotNull
public Boolean visitJetElement(@NotNull JetElement element, @Nullable Void nothing) {
return false;
}
@Override
@NotNull
public Boolean visitBlockExpression(@NotNull JetBlockExpression expression, @Nullable Void nothing) {
return true;
}
@Override
@NotNull
public Boolean visitWhenExpression(@NotNull JetWhenExpression expression, @Nullable Void nothing) {
return visitParent(expression);
}
@Override
@NotNull
public Boolean visitIfExpression(@NotNull JetIfExpression expression, @Nullable Void nothing) {
return visitParent(expression);
}
@Override
@NotNull
public Boolean visitWhenEntry(@NotNull JetWhenEntry expression, @Nullable Void nothing) {
return visitParent(expression);
}
@Override
@NotNull
public Boolean visitWhenCondition(@NotNull JetWhenCondition expression, @Nullable Void nothing) {
return visitParent(expression);
}
@Override
@NotNull
public Boolean visitContainerNode(@NotNull JetContainerNode expression, @Nullable Void nothing) {
return visitParent(expression);
}
}
}
@@ -20,4 +20,10 @@ public class MiscTest extends AbstractExpressionTest {
public void namespaceProperties() throws Exception {
testFunctionOutput("localProperty.jet", "foo", "box", 50);
}
@Test
public void intRange() throws Exception {
// checkOutput("intRange.kt", " ");
testFooBoxIsTrue("intRange.kt");
}
}
@@ -0,0 +1,23 @@
package org.jetbrains.k2js.test;
import org.junit.Test;
/**
* @author Talanov Pavel
*/
public final class RangeTest extends TranslationTest {
final private static String MAIN = "range/";
@Override
protected String mainDirectory() {
return MAIN;
}
@Test
public void explicitRange() throws Exception {
testFooBoxIsTrue("explicitRange.kt");
}
}
@@ -2,8 +2,6 @@ package org.jetbrains.k2js.test;
import org.junit.Test;
import java.util.Arrays;
/**
* @author Talanov Pavel
*/
@@ -16,12 +14,6 @@ public final class SystemTest extends JavaClassesTest {
return MAIN;
}
public void checkOutput(String filename, String expectedResult, String... args) throws Exception {
translateFile(filename);
runRhinoTest(generateFilenameList(getOutputFilePath(filename)),
new RhinoSystemOutputChecker(expectedResult, Arrays.asList(args)));
}
@Test
public void systemPrint() throws Exception {
checkOutput("systemPrint.kt", "Hello, world!");
@@ -105,4 +105,10 @@ public abstract class TranslationTest {
testFunctionOutput(filename, "foo", "box", "OK");
}
protected void checkOutput(String filename, String expectedResult, String... args) throws Exception {
translateFile(filename);
runRhinoTest(generateFilenameList(getOutputFilePath(filename)),
new RhinoSystemOutputChecker(expectedResult, Arrays.asList(args)));
}
}
@@ -0,0 +1,98 @@
namespace foo
class RangeIterator(val start : Int, var count : Int, val reversed : Boolean) {
fun next() : Int {
--count
return start + if (reversed) -count else count;
}
fun hasNext() = (count > 0);
}
class NumberRange(val start : Int, val size : Int, val reversed : Boolean) {
val end : Int
get() = start + size
fun contains(number : Int) : Boolean {
if (reversed) {
return (number <= start) && (number > start - size);
} else {
return (number >= start) && (number < start + size);
}
}
fun iterator() = RangeIterator(start, size, reversed);
}
fun box() = testRange() && testReversedRange();
fun testRange() : Boolean {
val oneToFive = NumberRange(1, 4, false);
if (oneToFive.contains(5)) return false;
if (oneToFive.contains(0)) return false;
if (oneToFive.contains(-100)) return false;
if (oneToFive.contains(10)) return false;
if (!oneToFive.contains(1)) return false;
if (!oneToFive.contains(2)) return false;
if (!oneToFive.contains(3)) return false;
if (!oneToFive.contains(4)) return false;
if (!(oneToFive.start == 1)) return false;
if (!(oneToFive.size == 4)) return false;
if (!(oneToFive.end == 5)) return false;
var sum = 0;
for (i in oneToFive) {
sum += i;
}
for (i in oneToFive) {
System.out?.print(i)
}
if (sum != 10) return false;
return true;
}
fun testReversedRange() : Boolean {
System.out?.println("Testing revesed range.");
val tenToFive = NumberRange(10, 5, true);
if (tenToFive.contains(5)) return false;
if (tenToFive.contains(11)) return false;
if (tenToFive.contains(-100)) return false;
if (tenToFive.contains(1000)) return false;
if (!tenToFive.contains(6)) return false;
if (!tenToFive.contains(7)) return false;
if (!tenToFive.contains(8)) return false;
if (!tenToFive.contains(9)) return false;
if (!tenToFive.contains(10)) return false;
for (i in tenToFive) {
System.out?.println(i)
}
var sum = 0;
for (i in tenToFive) {
sum += i;
}
if (sum != 40) {
return false;
}
return true;
}
fun main(args : Array<String>) {
System.out?.println(box())
}
+63 -4
View File
@@ -446,6 +446,12 @@ Object.extend(Function.prototype, (function () {
})());
Kotlin = {}
Kotlin.Class = Class;
Kotlin.Namespace = Namespace;
Kotlin.Trait = Trait;
Kotlin.isType = isType;
Kotlin.Exceptions = {}
Kotlin.Exceptions.IndexOutOfBounds = {}
Kotlin.array = function (len) {
@@ -574,7 +580,60 @@ Kotlin.System = function () {
};
}();
Kotlin.Class = Class;
Kotlin.Namespace = Namespace;
Kotlin.Trait = Trait;
Kotlin.isType = isType;
Kotlin.ArrayIterator = Class.create({
initialize:function (array) {
this.array = array;
this.index = 0;
},
next:function () {
return this.array.get(this.index++);
},
hasNext:function () {
return (this.array.size() > this.index);
}
});
Kotlin.RangeIterator = Kotlin.Class.create({initialize:function (start, count, reversed) {
this.$start = start;
this.$count = count;
this.$reversed = reversed;
}, get_start:function () {
return this.$start;
}, get_count:function () {
return this.$count;
}, set_count:function (tmp$0) {
this.$count = tmp$0;
}, get_reversed:function () {
return this.$reversed;
}, next:function () {
this.set_count(this.get_count() - 1);
return this.get_start() + (this.get_reversed() ? -this.get_count() : this.get_count());
}, hasNext:function () {
return this.get_count() > 0;
}
});
Kotlin.NumberRange = Kotlin.Class.create({initialize:function (start, size, reversed) {
this.$start = start;
this.$size = size;
this.$reversed = reversed;
}, get_start:function () {
return this.$start;
}, get_size:function () {
return this.$size;
}, get_reversed:function () {
return this.$reversed;
}, get_end:function () {
return this.get_start() + this.get_size();
}, contains:function (number) {
if (this.get_reversed()) {
return number <= this.get_start() && number > this.get_start() - this.get_size();
}
else {
return number >= this.get_start() && number < this.get_start() + this.get_size();
}
}, iterator:function () {
return new Kotlin.RangeIterator(this.get_start(), this.get_size(), this.get_reversed());
}
});
@@ -0,0 +1,31 @@
namespace foo
fun box() : Boolean {
var oneToFive = IntRange(1, 4)
if (oneToFive.contains(5)) return false;
if (oneToFive.contains(0)) return false;
if (oneToFive.contains(-100)) return false;
if (oneToFive.contains(10)) return false;
if (!oneToFive.contains(1)) return false;
if (!oneToFive.contains(2)) return false;
if (!oneToFive.contains(3)) return false;
if (!oneToFive.contains(4)) return false;
if (!(oneToFive.start == 1)) return false;
if (!(oneToFive.size == 4)) return false;
if (!(oneToFive.end == 5)) return false;
var sum = 0;
for (i in oneToFive) {
sum += i;
}
for (i in oneToFive) {
System.out?.print(i)
}
if (sum != 10) return false;
return true;
}