diff --git a/js/src/com/google/dart/compiler/util/AstUtil.java b/js/src/com/google/dart/compiler/util/AstUtil.java index 6860f941650..31ed38f1510 100644 --- a/js/src/com/google/dart/compiler/util/AstUtil.java +++ b/js/src/com/google/dart/compiler/util/AstUtil.java @@ -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) { diff --git a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java index a5fc37236da..d39c72319d5 100644 --- a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java +++ b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java @@ -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, "", "NumberRange"); + declareMethods(standardClasses, intRangeFQName, "iterator", "contains"); + declareProperties(standardClasses, intRangeFQName, "start", "size", "end", "reversed"); + } + + private static void declareJavaInteger(@NotNull StandardClasses standardClasses) { String integerFQName = ".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; diff --git a/translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java index 3efa7cb4381..ea67febc22b 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java @@ -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 diff --git a/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 7e8afbd0a3a..3d289112993 100644 --- a/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -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 diff --git a/translator/src/org/jetbrains/k2js/translate/utils/IsStatement.java b/translator/src/org/jetbrains/k2js/translate/utils/IsStatement.java new file mode 100644 index 00000000000..ed476a0db0e --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/utils/IsStatement.java @@ -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 { + + @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); + } + } + +} diff --git a/translator/test/org/jetbrains/k2js/test/MiscTest.java b/translator/test/org/jetbrains/k2js/test/MiscTest.java index da01678566a..14786992ac8 100644 --- a/translator/test/org/jetbrains/k2js/test/MiscTest.java +++ b/translator/test/org/jetbrains/k2js/test/MiscTest.java @@ -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"); + } } diff --git a/translator/test/org/jetbrains/k2js/test/RangeTest.java b/translator/test/org/jetbrains/k2js/test/RangeTest.java new file mode 100644 index 00000000000..34580e72619 --- /dev/null +++ b/translator/test/org/jetbrains/k2js/test/RangeTest.java @@ -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"); + } + + +} diff --git a/translator/test/org/jetbrains/k2js/test/SystemTest.java b/translator/test/org/jetbrains/k2js/test/SystemTest.java index 83589966d48..12f680ddbd3 100644 --- a/translator/test/org/jetbrains/k2js/test/SystemTest.java +++ b/translator/test/org/jetbrains/k2js/test/SystemTest.java @@ -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!"); diff --git a/translator/test/org/jetbrains/k2js/test/TranslationTest.java b/translator/test/org/jetbrains/k2js/test/TranslationTest.java index f80e3eedb43..93807dd59f0 100644 --- a/translator/test/org/jetbrains/k2js/test/TranslationTest.java +++ b/translator/test/org/jetbrains/k2js/test/TranslationTest.java @@ -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))); + } + } diff --git a/translator/testFiles/expression/misc/cases/intRange.kt b/translator/testFiles/expression/misc/cases/intRange.kt new file mode 100644 index 00000000000..8811094f239 --- /dev/null +++ b/translator/testFiles/expression/misc/cases/intRange.kt @@ -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) { + System.out?.println(box()) +} \ No newline at end of file diff --git a/translator/testFiles/kotlin_lib.js b/translator/testFiles/kotlin_lib.js index ce375b40a33..1f6adc9ca3e 100644 --- a/translator/testFiles/kotlin_lib.js +++ b/translator/testFiles/kotlin_lib.js @@ -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()); +} +}); \ No newline at end of file diff --git a/translator/testFiles/range/cases/explicitRange.kt b/translator/testFiles/range/cases/explicitRange.kt new file mode 100644 index 00000000000..13ba9becfca --- /dev/null +++ b/translator/testFiles/range/cases/explicitRange.kt @@ -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; + +} \ No newline at end of file