JS backend: support for while/do while with complex conditions
This commit is contained in:
@@ -25,4 +25,20 @@ public class WhileTest extends AbstractExpressionTest {
|
||||
public void testWhileWithComplexOneStatement() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
|
||||
public void testWhileWithComplexCondition() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
|
||||
public void testWhileWithComplexConditionAndContinue() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
|
||||
public void testDoWhileWithComplexCondition() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
|
||||
public void testDoWhileWithComplexConditionAndContinue() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
}
|
||||
|
||||
+32
-6
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.constants.NullValue;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.k2js.translate.context.TemporaryVariable;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.declaration.ClassTranslator;
|
||||
import org.jetbrains.k2js.translate.expression.foreach.ForTranslator;
|
||||
@@ -237,19 +238,44 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
@Override
|
||||
@NotNull
|
||||
public JsNode visitWhileExpression(@NotNull JetWhileExpression expression, @NotNull TranslationContext context) {
|
||||
return createWhile(new JsWhile(), expression, context);
|
||||
return createWhile(false, expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JsNode visitDoWhileExpression(@NotNull JetDoWhileExpression expression, @NotNull TranslationContext context) {
|
||||
return createWhile(new JsDoWhile(), expression, context);
|
||||
return createWhile(true, expression, context);
|
||||
}
|
||||
|
||||
private JsNode createWhile(@NotNull JsWhile result, @NotNull JetWhileExpressionBase expression, @NotNull TranslationContext context) {
|
||||
result.setCondition(translateConditionExpression(expression.getCondition(), context));
|
||||
TranslationContext bodyContext = context.innerBlock();
|
||||
JsStatement bodyStatement = translateNullableExpressionAsNotNullStatement(expression.getBody(), bodyContext);
|
||||
private static JsNode createWhile(boolean doWhile, @NotNull JetWhileExpressionBase expression, @NotNull TranslationContext context) {
|
||||
JetExpression conditionExpression = expression.getCondition();
|
||||
assert conditionExpression != null : "condition expression should not be null: " + expression.getText();
|
||||
|
||||
JsBlock conditionBlock = new JsBlock();
|
||||
JsExpression jsCondition = Translation.translateAsExpression(conditionExpression, context, conditionBlock);
|
||||
JsStatement bodyStatement = translateNullableExpressionAsNotNullStatement(expression.getBody(), context);
|
||||
if (!conditionBlock.isEmpty()) {
|
||||
JsIf IfStatement = new JsIf(not(jsCondition), new JsBreak());
|
||||
JsBlock bodyBlock = JsAstUtils.convertToBlock(bodyStatement);
|
||||
jsCondition = JsLiteral.TRUE;
|
||||
if (doWhile) {
|
||||
// translate to: tmpSecondRun = false; do { if(tmpSecondRun) { <expr> if(!tmpExprVar) break; } else tmpSecondRun=true; <body> } while(true)
|
||||
TemporaryVariable secondRun = context.declareTemporary(JsLiteral.FALSE);
|
||||
context.addStatementToCurrentBlock(secondRun.assignmentExpression().makeStmt());
|
||||
conditionBlock.getStatements().add(IfStatement);
|
||||
bodyBlock.getStatements().add(0,
|
||||
new JsIf(secondRun.reference(), conditionBlock,
|
||||
JsAstUtils.assignment(secondRun.reference(), JsLiteral.TRUE).makeStmt())
|
||||
);
|
||||
} else {
|
||||
// translate to: while (true) { <expr> if(!tmpExprVar) break; <body> }
|
||||
conditionBlock.getStatements().add(IfStatement);
|
||||
bodyBlock.getStatements().addAll(0, conditionBlock.getStatements());
|
||||
}
|
||||
bodyStatement = bodyBlock;
|
||||
}
|
||||
JsWhile result = doWhile ? new JsDoWhile() : new JsWhile();
|
||||
result.setCondition(jsCondition);
|
||||
result.setBody(bodyStatement);
|
||||
return result.source(expression);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package foo
|
||||
|
||||
var global: String = ""
|
||||
|
||||
fun box(): String {
|
||||
var i:Int = 0
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
do i++ while(try { global += "A"; i } finally {} < 3)
|
||||
assertEquals("AAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
do {
|
||||
if (i==3) break
|
||||
i++
|
||||
} while(try { global += "A"; i } finally {} < 10)
|
||||
assertEquals("AAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
do
|
||||
try { global += "B"; i++} finally {}
|
||||
while( try { global += "A"; i } finally{} < 3)
|
||||
assertEquals("BABABA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package foo
|
||||
|
||||
var global: String = ""
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var i = 0
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
do {
|
||||
if (i<3) {i++; continue}
|
||||
break
|
||||
} while(try { global += "A"; i } finally {} < 10)
|
||||
assertEquals("AAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
@labelA do {
|
||||
if (i<3) {i++; continue@labelA}
|
||||
break
|
||||
} while(try { global += "A"; i } finally {} < 10)
|
||||
assertEquals("AAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
var j = 0
|
||||
global = ""
|
||||
@outer do {
|
||||
j = 0
|
||||
while( try {global += "B"; j++ } finally {} < 2) {
|
||||
if (j==1) continue@outer
|
||||
}
|
||||
} while(try { global += "A"; i++ } finally {} < 3)
|
||||
assertEquals("BABABABA", global)
|
||||
assertEquals(4, i)
|
||||
assertEquals(1, j)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package foo
|
||||
|
||||
var global: String = ""
|
||||
|
||||
fun box(): String {
|
||||
var i:Int = 0
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
while(try { global += "A"; i } finally {} < 3)
|
||||
i++
|
||||
assertEquals("AAAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
while(try { global += "A"; i } finally {} < 10) {
|
||||
if (i==3) break
|
||||
i++
|
||||
}
|
||||
assertEquals("AAAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
while( try { global += "A"; i } finally{} < 3)
|
||||
try { global += "B"; i++} finally {}
|
||||
assertEquals("ABABABA", global)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package foo
|
||||
|
||||
var global: String = ""
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var i = 0
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
while(try { global += "A"; i } finally {} < 10) {
|
||||
if (i<3) {i++; continue}
|
||||
break
|
||||
}
|
||||
assertEquals("AAAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
global = ""
|
||||
@labelA while(try { global += "A"; i } finally {} < 10) {
|
||||
if (i<3) {i++; continue@labelA}
|
||||
break
|
||||
}
|
||||
assertEquals("AAAA", global)
|
||||
assertEquals(3, i)
|
||||
|
||||
i = 0
|
||||
var j = 0
|
||||
global = ""
|
||||
@outer while(try { global += "A"; i++ } finally {} < 3) {
|
||||
j = 0
|
||||
while( try {global += "B"; j++ } finally {} < 2) {
|
||||
if (j==1) continue@outer
|
||||
}
|
||||
}
|
||||
assertEquals("ABABABA", global)
|
||||
assertEquals(4, i)
|
||||
assertEquals(1, j)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user