JS backend: fix compiler crash on for with empty body

This commit is contained in:
Zalim Bashorov
2015-06-01 19:52:03 +03:00
parent f90df7aa35
commit ca4ce48801
5 changed files with 75 additions and 11 deletions
@@ -57,4 +57,12 @@ public final class ForeachTest extends AbstractExpressionTest {
public void testLabeledForWithWhile() throws Exception { public void testLabeledForWithWhile() throws Exception {
checkFooBoxIsOk(); checkFooBoxIsOk();
} }
public void testForWithEmptyBody() throws Exception {
checkFooBoxIsOk();
}
public void testForWithSideEffectImElementAccessAndWithEmptyBody() throws Exception {
checkFooBoxIsOk();
}
} }
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getIteratorFunction
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getNextFunction import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getNextFunction
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getTypeForExpression import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getTypeForExpression
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.* import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopBody
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopParameter import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopParameter
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopRange import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopRange
import org.jetbrains.kotlin.js.translate.utils.TemporariesUtils.temporariesInitialization import org.jetbrains.kotlin.js.translate.utils.TemporariesUtils.temporariesInitialization
@@ -127,8 +126,8 @@ public fun translateForExpression(expression: JetForExpression, context: Transla
val parameterName: JsName = declareParameter() val parameterName: JsName = declareParameter()
fun translateBody(itemValue: JsExpression?): JsStatement { fun translateBody(itemValue: JsExpression?): JsStatement? {
val realBody = Translation.translateAsStatementAndMergeInBlockIfNeeded(getLoopBody(expression), context) val realBody = expression.getBody()?.let { Translation.translateAsStatementAndMergeInBlockIfNeeded(it, context) }
if (itemValue == null && multiParameter == null) { if (itemValue == null && multiParameter == null) {
return realBody return realBody
} }
@@ -138,6 +137,9 @@ public fun translateForExpression(expression: JetForExpression, context: Transla
newVar(parameterName, itemValue) newVar(parameterName, itemValue)
else else
MultiDeclarationTranslator.translate(multiParameter, parameterName, itemValue, context) MultiDeclarationTranslator.translate(multiParameter, parameterName, itemValue, context)
if (realBody == null) return JsBlock(currentVarInit)
val block = convertToBlock(realBody) val block = convertToBlock(realBody)
block.getStatements().add(0, currentVarInit) block.getStatements().add(0, currentVarInit)
return block return block
@@ -230,7 +232,9 @@ public fun translateForExpression(expression: JetForExpression, context: Transla
} }
context.addStatementToCurrentBlock(iteratorVar.assignmentExpression().makeStmt()) context.addStatementToCurrentBlock(iteratorVar.assignmentExpression().makeStmt())
return JsWhile(hasNextMethodInvocation(), translateBody(nextMethodInvocation())) val nextInvoke = nextMethodInvocation()
val body = translateBody(nextInvoke)
return JsWhile(hasNextMethodInvocation(), body ?: nextInvoke.makeStmt())
} }
return when { return when {
@@ -111,13 +111,6 @@ public final class PsiUtils {
return (binaryExpression.getOperationToken() == JetTokens.IN_KEYWORD); return (binaryExpression.getOperationToken() == JetTokens.IN_KEYWORD);
} }
@NotNull
public static JetExpression getLoopBody(@NotNull JetLoopExpression expression) {
JetExpression body = expression.getBody();
assert body != null : "Loops cannot have null bodies.";
return body;
}
@Nullable @Nullable
public static JetParameter getLoopParameter(@NotNull JetForExpression expression) { public static JetParameter getLoopParameter(@NotNull JetForExpression expression) {
return expression.getLoopParameter(); return expression.getLoopParameter();
@@ -0,0 +1,14 @@
package foo
fun box(): String {
for (i in 0..5);
val r = 0..5
for (i in r);
for (i in arrayOf(1, 2, 3));
for (i in arrayOf(1, 2, 3).asList());
return "OK"
}
@@ -0,0 +1,45 @@
package foo
var log = ""
class T(val id: Int) {
fun component1(): Int {
log += "($id).component1();"
return 1
}
fun component2(): String {
log += "($id).component2();"
return "1"
}
}
class C {
fun iterator(): Iterator<T> = object: Iterator<T> {
var i = 0
var data = arrayOf(T(3), T(1), T(2))
override fun hasNext(): Boolean {
log += "C.hasNext();"
return i < data.size()
}
override fun next(): T {
log += "C.next();"
return data[i++]
}
}
}
fun box(): String {
for ((a, b) in arrayOf(T(3), T(1), T(2)));
assertEquals("(3).component1();(3).component2();(1).component1();(1).component2();(2).component1();(2).component2();", log)
log = ""
for ((a, b) in C());
assertEquals("C.hasNext();C.next();(3).component1();(3).component2();C.hasNext();C.next();" +
"(1).component1();(1).component2();C.hasNext();C.next();" +
"(2).component1();(2).component2();C.hasNext();", log)
return "OK"
}