diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java index 6a64754a684..ffc679328ce 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java @@ -101,7 +101,10 @@ public final class StandardClasses { standardClasses.declare().forFQ("jet.Iterator").kotlinClass("Iterator").methods("next").properties("hasNext"); standardClasses.declare().forFQ("jet.IntRange").kotlinClass("NumberRange") - .methods("iterator", "contains").properties("start", "size", "end", "reversed"); + .methods("iterator", "contains").properties("start", "end", "increment"); + + standardClasses.declare().forFQ("jet.IntSequence").kotlinClass("NumberSequence") + .methods("iterator", "contains").properties("start", "end", "increment"); standardClasses.declare().forFQ("jet.Any.toString").kotlinFunction("toString"); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java index c318727ea35..48a086959dd 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/RangeForTranslator.java @@ -54,28 +54,24 @@ public final class RangeForTranslator extends ForTranslator { @NotNull private final TemporaryVariable rangeExpression; @NotNull - private final TemporaryVariable incrVar; - @NotNull private final TemporaryVariable start; @NotNull private final TemporaryVariable end; + @NotNull + private final TemporaryVariable increment; private RangeForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) { super(forExpression, context); rangeExpression = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context)); - JsExpression isReversed = callFunction("get_reversed"); - JsConditional incrVarValue = new JsConditional(isReversed, - program().getNumberLiteral(-1), - program().getNumberLiteral(1)); - incrVar = context().declareTemporary(incrVarValue); start = context().declareTemporary(callFunction("get_start")); - end = context().declareTemporary(sum(callFunction("get_end"), incrVar.reference())); + end = context().declareTemporary(callFunction("get_end")); + increment = context().declareTemporary(callFunction("get_increment")); } @NotNull private JsBlock translate() { List blockStatements = Lists.newArrayList(); - blockStatements.add(temporariesInitialization(rangeExpression, incrVar, start, end).makeStmt()); + blockStatements.add(temporariesInitialization(rangeExpression, start, end, increment).makeStmt()); blockStatements.add(generateForExpression()); return new JsBlock(blockStatements); } @@ -94,12 +90,12 @@ public final class RangeForTranslator extends ForTranslator { @NotNull private JsExpression getCondition() { - return inequality(parameterName.makeRef(), end.reference()); + return lessThanEq(parameterName.makeRef(), end.reference()); } @NotNull private JsExpression getIncrExpression() { - return addAssign(parameterName.makeRef(), incrVar.reference()); + return addAssign(parameterName.makeRef(), increment.reference()); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java index e6a59687b51..ef77f1049fe 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java @@ -51,12 +51,10 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory { assert arguments.size() == 1 : "RangeTo must have one argument."; assert rangeStart != null; JsExpression rangeEnd = arguments.get(0); - JsBinaryOperation rangeSize = sum(subtract(rangeEnd, rangeStart), - context.program().getNumberLiteral(1)); JsNameRef expr = AstUtil.newQualifiedNameRef("Kotlin.NumberRange"); HasArguments numberRangeConstructorInvocation = context.isEcma5() ? new JsInvocation(expr) : new JsNew(expr); //TODO: add tests and correct expression for reversed ranges. - setArguments(numberRangeConstructorInvocation, rangeStart, rangeSize, /*range is not reversed*/JsLiteral.FALSE); + setArguments(numberRangeConstructorInvocation, rangeStart, rangeEnd); return (JsExpression) numberRangeConstructorInvocation; } }; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java index ec6f9fdaadc..44ea882b910 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java @@ -115,6 +115,11 @@ public final class JsAstUtils { return new JsBinaryOperation(JsBinaryOperator.REF_NEQ, arg1, arg2); } + @NotNull + public static JsBinaryOperation lessThanEq(@NotNull JsExpression arg1, @NotNull JsExpression arg2) { + return new JsBinaryOperation(JsBinaryOperator.LTE, arg1, arg2); + } + @NotNull public static JsExpression assignment(@NotNull JsExpression left, @NotNull JsExpression right) { return new JsBinaryOperation(JsBinaryOperator.ASG, left, right); diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index 7043e0376f7..3ea5856d088 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -63,12 +63,12 @@ var kotlin = {set:function (receiver, key, value) { return args === null || args === undefined ? [] : args.slice(); }; - Kotlin.intUpto = function (from, limit) { - return Kotlin.$new(Kotlin.NumberRange)(from, limit - from + 1, false); + Kotlin.intUpto = function (from, to) { + return Kotlin.$new(Kotlin.NumberRange)(from, to); }; - Kotlin.intDownto = function (from, limit) { - return Kotlin.$new(Kotlin.NumberRange)(from, from - limit + 1, true); + Kotlin.intDownto = function (from, to) { + return Kotlin.$new(Kotlin.NumberSequence)(from, to, -1); }; Kotlin.modules = {}; @@ -344,23 +344,17 @@ var kotlin = {set:function (receiver, key, value) { }; Kotlin.RangeIterator = Kotlin.$createClass(Kotlin.Iterator, { - initialize: function (start, count, reversed) { + initialize: function (start, end, increment) { this.$start = start; - this.$count = count; - this.$reversed = reversed; - this.$i = this.get_start(); + this.$end = end; + this.$increment = increment; + this.$i = start; }, 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; + get_end: function () { + return this.$end; }, get_i: function () { return this.$i; @@ -369,49 +363,54 @@ var kotlin = {set:function (receiver, key, value) { this.$i = tmp$0; }, next: function () { - this.set_count(this.get_count() - 1); - if (this.get_reversed()) { - this.set_i(this.get_i() - 1); - return this.get_i() + 1; - } - else { - this.set_i(this.get_i() + 1); - return this.get_i() - 1; - } + var value = this.$i; + this.set_i(this.$i + this.$increment) + return value; }, get_hasNext: function () { - return this.get_count() > 0; + return this.$increment > 0 ? this.$next <= this.$end : this.$next >= this.$end; } }); Kotlin.NumberRange = Kotlin.$createClass({ - initialize: function (start, size, reversed) { + initialize: function (start, end) { this.$start = start; - this.$size = size; - this.$reversed = reversed; + this.$end = end; }, get_start: function () { return this.$start; }, - get_size: function () { - return this.$size; - }, - get_reversed: function () { - return this.$reversed; - }, get_end: function () { - return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1; + return this.$end; + }, + get_increment: function () { + return 1; }, 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(); - } + return this.$start <= number && number <= this.$end; }, iterator: function () { - return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed()); + return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_end()); + } + }); + + Kotlin.NumberSequence = Kotlin.$createClass({ + initialize: function (start, end, increment) { + this.$start = start; + this.$end = end; + this.$increment = increment; + }, + get_start: function () { + return this.$start; + }, + get_end: function () { + return this.$end; + }, + get_increment: function () { + return this.$increment; + }, + iterator: function () { + return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_end(), this.get_increment()); } }); @@ -483,7 +482,7 @@ var kotlin = {set:function (receiver, key, value) { }; Kotlin.arrayIndices = function (arr) { - return Kotlin.$new(Kotlin.NumberRange)(0, arr.length); + return Kotlin.$new(Kotlin.NumberRange)(0, arr.length - 1); }; Kotlin.arrayIterator = function (array) {