added dirty implementation for iterating over range literals

This commit is contained in:
Pavel Talanov
2012-02-22 21:44:25 +04:00
parent 4075070506
commit 6f84da590e
7 changed files with 185 additions and 4 deletions
@@ -89,7 +89,7 @@ public final class ArrayForTranslator extends ForTranslator {
@NotNull
private JsStatement getBody(@NotNull TemporaryVariable index) {
JsArrayAccess arrayAccess = new JsArrayAccess(rangeExpression.reference(), index.reference());
JsStatement currentVar = AstUtil.newVar(declareParameter(), arrayAccess);
JsStatement currentVar = AstUtil.newVar(parameterName, arrayAccess);
JsStatement realBody = Translation.translateAsStatement(getLoopBody(expression), context());
return AstUtil.newBlock(currentVar, realBody);
}
@@ -23,17 +23,24 @@ import org.jetbrains.jet.lang.psi.JetForExpression;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopParameter;
/**
* @author Pavel Talanov
*/
//TODO: create util class for managing stuff like binary operations
public abstract class ForTranslator extends AbstractTranslator {
@NotNull
public static JsStatement translate(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
if (RangeLiteralForTranslator.isApplicable(expression, context)) {
return RangeLiteralForTranslator.translate(expression, context);
}
if (ArrayForTranslator.isApplicable(expression, context)) {
return ArrayForTranslator.translate(expression, context);
}
@@ -45,15 +52,26 @@ public abstract class ForTranslator extends AbstractTranslator {
@NotNull
protected final JetForExpression expression;
@NotNull
protected final JsName parameterName;
protected ForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(context);
this.expression = forExpression;
this.parameterName = declareParameter();
}
@NotNull
protected JsName declareParameter() {
private JsName declareParameter() {
JetParameter loopParameter = getLoopParameter(expression);
return context().getNameForElement(loopParameter);
}
//TODO: look for should-be-usages
@NotNull
protected JsStatement translateOriginalBodyExpression() {
return Translation.translateAsStatement(getLoopBody(expression), context());
}
}
@@ -50,7 +50,6 @@ public final class IteratorForTranslator extends ForTranslator {
@NotNull
private JsBlock translate() {
JsName parameterName = declareParameter();
TemporaryVariable iterator = context().declareTemporary(iteratorMethodInvocation());
JsBlock bodyBlock = generateCycleBody(parameterName, iterator);
JsWhile cycle = new JsWhile(hasNextMethodInvocation(iterator), bodyBlock);
@@ -81,7 +81,6 @@ public final class RangeForTranslator extends ForTranslator {
@NotNull TemporaryVariable start,
@NotNull TemporaryVariable end) {
JsFor result = new JsFor();
JsName parameterName = declareParameter();
result.setInitVars(initExpression(start, parameterName));
result.setCondition(getCondition(end, parameterName));
result.setIncrExpr(getIncrExpression(incrVar, parameterName));
@@ -0,0 +1,121 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression.foreach;
import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetForExpression;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateLeftExpression;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRightExpression;
/**
* @author Pavel Talanov
*/
// TODO: respect reverse semantics
public final class RangeLiteralForTranslator extends ForTranslator {
@NotNull
public static JsStatement translate(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
return (new RangeLiteralForTranslator(expression, context).translate());
}
public static boolean isApplicable(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
JetExpression loopRange = getLoopRange(expression);
if (!(loopRange instanceof JetBinaryExpression)) {
return false;
}
boolean isRangeToOperation = ((JetBinaryExpression) loopRange).getOperationToken() == JetTokens.RANGE;
return isRangeToOperation && RangeForTranslator.isApplicable(expression, context);
}
@NotNull
private final TemporaryVariable rangeStart;
@NotNull
private final TemporaryVariable rangeEnd;
private RangeLiteralForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(forExpression, context);
JetExpression loopRange = getLoopRange(expression);
assert loopRange instanceof JetBinaryExpression;
JetBinaryExpression loopRangeAsBinary = ((JetBinaryExpression) loopRange);
rangeStart = context.declareTemporary(translateLeftExpression(context, loopRangeAsBinary));
rangeEnd = context.declareTemporary(getRangeEnd(loopRangeAsBinary));
}
@NotNull
private JsExpression getRangeEnd(@NotNull JetBinaryExpression loopRangeAsBinary) {
JsExpression rightExpression = translateRightExpression(context(), loopRangeAsBinary);
return new JsBinaryOperation(JsBinaryOperator.ADD, rightExpression, program().getNumberLiteral(1));
}
@NotNull
private JsBlock translate() {
List<JsStatement> blockStatements = temporariesInitialization(rangeEnd, rangeStart);
blockStatements.add(generateForExpression());
return AstUtil.newBlock(blockStatements);
}
@NotNull
private JsFor generateForExpression() {
JsFor result = new JsFor();
result.setInitVars(initExpression());
result.setCondition(getCondition());
result.setIncrExpr(getIncrExpression());
result.setBody(translateOriginalBodyExpression());
return result;
}
@NotNull
private JsVars initExpression() {
return AstUtil.newVar(parameterName, rangeStart.reference());
}
@NotNull
private JsExpression getCondition() {
return AstUtil.notEqual(parameterName.makeRef(), rangeEnd.reference());
}
@NotNull
private JsExpression getIncrExpression() {
return new JsPrefixOperation(JsUnaryOperator.INC, parameterName.makeRef());
}
//TODO : UTIL!!
@NotNull
private List<JsStatement> temporariesInitialization(@NotNull TemporaryVariable... temporaries) {
List<JsStatement> result = Lists.newArrayList();
for (TemporaryVariable temporary : temporaries) {
result.add(temporary.assignmentExpression().makeStmt());
}
return result;
}
}
@@ -0,0 +1,41 @@
package foo
import js.*
fun box() : Boolean {
var d = 0
for (i in 1..6) {
d += i
}
if (d != 21) return false;
for (x in 100..199) {
d += 1
}
if (d != 121) {
return false;
}
for (y in 1..1) {
d = 100
}
if (d != 100) {
return false;
}
for (c in 100..100) {
d += 1;
}
if (d != 101) {
return false;
}
return true
}
fun main() {
box()
}
@@ -43,4 +43,7 @@ public final class RangeTest extends TranslationTest {
testFooBoxIsTrue("intInRange.kt");
}
public void testIteratingOverRanges() throws Exception {
testFooBoxIsTrue("iteratingOverRanges.kt");
}
}