Refactored structure of ranges in JS backend.

This commit is contained in:
Evgeny Gerashchenko
2013-01-25 02:58:01 +04:00
parent 4a19cd758c
commit 72b8c4b3c8
5 changed files with 60 additions and 59 deletions
@@ -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");
@@ -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<JsStatement> 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
@@ -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;
}
};
@@ -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);
+43 -44
View File
@@ -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) {