From 7a61a7520d7c6276b77525edd30b37a3f8835b7d Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Mon, 30 Jan 2012 21:17:32 +0400 Subject: [PATCH] if as expression with control statements support --- .idea/workspace.xml | 669 +++++++++--------- .../google/dart/compiler/util/AstUtil.java | 23 + .../translate/context/StandardClasses.java | 1 + .../expression/ExpressionVisitor.java | 35 +- .../translate/expression/WhenTranslator.java | 14 +- .../jetbrains/k2js/test/ConditionalTest.java | 7 +- .../k2js/test/PatternMatchingTest.java | 14 +- .../cases/ifAsExpressionWithThrow.kt | 3 + translator/testFiles/kotlin_lib.js | 3 +- .../cases/whenAsExpressionWithThrow.kt | 19 + .../patternMatching/cases/whenValueOrType.kt | 2 + 11 files changed, 437 insertions(+), 353 deletions(-) create mode 100644 translator/testFiles/expression/conditional/cases/ifAsExpressionWithThrow.kt create mode 100644 translator/testFiles/patternMatching/cases/whenAsExpressionWithThrow.kt diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 3050b4b6845..59ecaca0820 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -12,9 +12,17 @@ - - + + + + + + + + + + @@ -115,27 +123,9 @@ - + - - - - - - - - - - - - - - - - - - @@ -185,10 +175,46 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -198,62 +224,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -261,28 +278,39 @@ - - + + - + - - + + - + - - + + - + + + + + + + + + + + + @@ -313,22 +341,22 @@ @@ -602,8 +630,22 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -828,6 +742,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1201,21 +1227,112 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + @@ -1224,91 +1341,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/js/src/com/google/dart/compiler/util/AstUtil.java b/js/src/com/google/dart/compiler/util/AstUtil.java index 110b9fc5404..b05cf4711f7 100644 --- a/js/src/com/google/dart/compiler/util/AstUtil.java +++ b/js/src/com/google/dart/compiler/util/AstUtil.java @@ -7,6 +7,7 @@ package com.google.dart.compiler.util; import com.google.dart.compiler.InternalCompilerException; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.common.SourceInfo; +import com.sun.istack.internal.NotNull; import java.util.List; @@ -357,6 +358,9 @@ public class AstUtil { if (node instanceof JsBlock) { JsBlock block = (JsBlock) node; List statements = block.getStatements(); + + if (statements.isEmpty()) return block; + int size = statements.size(); statements.set(size - 1, AstUtil.convertToStatement(mutateLastExpression(statements.get(size - 1), mutator))); @@ -376,4 +380,23 @@ public class AstUtil { } return mutator.mutate(node); } + + + public static final class SaveLastExpressionMutator implements Mutator { + + @NotNull + private final JsExpression toAssign; + + public SaveLastExpressionMutator(@NotNull JsExpression toAssign) { + this.toAssign = toAssign; + } + + @Override + public JsNode mutate(JsNode node) { + if (!(node instanceof JsExpression)) { + return node; + } + return AstUtil.assignment(toAssign, (JsExpression) node); + } + } } diff --git a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java index 1e27949f65d..86a9024f426 100644 --- a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java +++ b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java @@ -153,6 +153,7 @@ public final class StandardClasses { standardClasses.declare().forFQ("js.parseInt").kotlinFunction("parseInt"); standardClasses.declare().forFQ("js.println").kotlinFunction("println"); standardClasses.declare().forFQ("js.print").kotlinFunction("print"); + standardClasses.declare().forFQ("js.Exception").kotlinClass("Exception"); } @NotNull diff --git a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index d6decdab024..04def85bada 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.NullValue; +import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslatorVisitor; @@ -18,7 +19,6 @@ import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator; import org.jetbrains.k2js.translate.reference.AccessTranslator; import org.jetbrains.k2js.translate.reference.CallTranslator; import org.jetbrains.k2js.translate.reference.ReferenceTranslator; -import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils; import java.util.List; @@ -122,12 +122,14 @@ public final class ExpressionVisitor extends TranslatorVisitor { @Override @NotNull public JsNode visitIfExpression(@NotNull JetIfExpression expression, @NotNull TranslationContext context) { - boolean isStatement = BindingUtils.isStatement(context.bindingContext(), expression); - if (isStatement) { - return translateAsIfStatement(expression, context); - } else { - return translateAsConditionalExpression(expression, context); - } + TemporaryVariable result = context.declareTemporary(context.program().getNullLiteral()); + AstUtil.SaveLastExpressionMutator saveResultToTemporaryMutator = + new AstUtil.SaveLastExpressionMutator(result.nameReference()); + JsNode mutatedIfStatement = AstUtil.mutateLastExpression(translateAsIfStatement(expression, context), + saveResultToTemporaryMutator); + JsStatement resultingStatement = AstUtil.convertToStatement(mutatedIfStatement); + context.jsBlock().addStatement(resultingStatement); + return result.nameReference(); } @Override @@ -158,16 +160,6 @@ public final class ExpressionVisitor extends TranslatorVisitor { return AstUtil.convertToStatement(jetElse.accept(this, context)); } - @NotNull - private JsConditional translateAsConditionalExpression(@NotNull JetIfExpression expression, - @NotNull TranslationContext context) { - JsConditional result = new JsConditional(); - result.setTestExpression(translateConditionExpression(expression.getCondition(), context)); - result.setThenExpression(translateNullableExpression(expression.getThen(), context)); - result.setElseExpression(translateNullableExpression(expression.getElse(), context)); - return result; - } - @NotNull private JsStatement translateNullableExpressionAsNotNullStatement(@Nullable JetExpression nullableExpression, @NotNull TranslationContext context) { @@ -354,4 +346,13 @@ public final class ExpressionVisitor extends TranslatorVisitor { } return result; } + + @Override + @NotNull + public JsNode visitThrowExpression(@NotNull JetThrowExpression expression, + @NotNull TranslationContext context) { + JetExpression thrownExpression = expression.getThrownExpression(); + assert thrownExpression != null : "Thrown expression must not be null"; + return new JsThrow(translateAsExpression(thrownExpression, context)); + } } diff --git a/translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java b/translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java index dd55b7fb407..21871633516 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java @@ -16,7 +16,6 @@ import java.util.List; /** * @author Pavel Talanov */ -//TODO: look into using temporary variable for counter public class WhenTranslator extends AbstractTranslator { @NotNull @@ -102,16 +101,9 @@ public class WhenTranslator extends AbstractTranslator { @NotNull JsStatement withReturnValueCaptured(@NotNull JsNode node) { - AstUtil.Mutator lastExpressionCapturer = new AstUtil.Mutator() { - @Override - public JsNode mutate(JsNode node) { - if (!(node instanceof JsExpression)) { - return node; - } - return AstUtil.assignment(result.nameReference(), (JsExpression) node); - } - }; - return AstUtil.convertToStatement(AstUtil.mutateLastExpression(node, lastExpressionCapturer)); + + return AstUtil.convertToStatement(AstUtil.mutateLastExpression(node, + new AstUtil.SaveLastExpressionMutator(result.nameReference()))); } @NotNull diff --git a/translator/test/org/jetbrains/k2js/test/ConditionalTest.java b/translator/test/org/jetbrains/k2js/test/ConditionalTest.java index 83fd0fd34c3..a5434d74123 100644 --- a/translator/test/org/jetbrains/k2js/test/ConditionalTest.java +++ b/translator/test/org/jetbrains/k2js/test/ConditionalTest.java @@ -1,6 +1,7 @@ package org.jetbrains.k2js.test; import org.junit.Test; +import org.mozilla.javascript.JavaScriptException; /** * @author Pavel Talanov @@ -24,9 +25,13 @@ public class ConditionalTest extends AbstractExpressionTest { testFunctionOutput("if.kt", "foo", "box", 5); } - //TODO: test fails due to isStatement issue, include when issue is solved or implement another solution @Test public void ifElseIf() throws Exception { testFunctionOutput("elseif.kt", "foo", "box", 5); } + + @Test(expected = JavaScriptException.class) + public void ifElseAsExpressionWithThrow() throws Exception { + testFooBoxIsTrue("ifAsExpressionWithThrow.kt"); + } } diff --git a/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java b/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java index 0d208559776..94a90c86f93 100644 --- a/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java +++ b/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java @@ -39,11 +39,10 @@ public final class PatternMatchingTest extends TranslationTest { testFooBoxIsTrue("whenNotValue.kt"); } - //TODO: fails due to analyzing bug -// @Test -// public void whenValueOrType() throws Exception { -// testFooBoxIsTrue("whenValueOrType.kt"); -// } + @Test + public void whenValueOrType() throws Exception { + testFooBoxIsTrue("whenValueOrType.kt"); + } @Test public void whenWithIf() throws Exception { @@ -64,4 +63,9 @@ public final class PatternMatchingTest extends TranslationTest { public void whenAsExpression() throws Exception { testFooBoxIsTrue("whenAsExpression.kt"); } + + @Test(expected = org.mozilla.javascript.JavaScriptException.class) + public void whenAsExpressionWithThrow() throws Exception { + testFooBoxIsTrue("whenAsExpressionWithThrow.kt"); + } } diff --git a/translator/testFiles/expression/conditional/cases/ifAsExpressionWithThrow.kt b/translator/testFiles/expression/conditional/cases/ifAsExpressionWithThrow.kt new file mode 100644 index 00000000000..f73f96b80dd --- /dev/null +++ b/translator/testFiles/expression/conditional/cases/ifAsExpressionWithThrow.kt @@ -0,0 +1,3 @@ +package foo + +fun box() = if (true) throw Exception() else false \ No newline at end of file diff --git a/translator/testFiles/kotlin_lib.js b/translator/testFiles/kotlin_lib.js index 242b721c62b..cc4d2188044 100644 --- a/translator/testFiles/kotlin_lib.js +++ b/translator/testFiles/kotlin_lib.js @@ -250,6 +250,7 @@ Kotlin.equals = function (obj1, obj2) { }; Kotlin.Exceptions = {} +Kotlin.Exception = Kotlin.Class.create(); Kotlin.Exceptions.IndexOutOfBounds = {} Kotlin.array = function (len) { return new Kotlin.Array(len, function () { @@ -902,7 +903,7 @@ Kotlin.StringBuilder = Kotlin.Class.create( } ); -Kotlin.toString = function(obj) { +Kotlin.toString = function (obj) { return obj.toString(); }; diff --git a/translator/testFiles/patternMatching/cases/whenAsExpressionWithThrow.kt b/translator/testFiles/patternMatching/cases/whenAsExpressionWithThrow.kt new file mode 100644 index 00000000000..77f35cf338f --- /dev/null +++ b/translator/testFiles/patternMatching/cases/whenAsExpressionWithThrow.kt @@ -0,0 +1,19 @@ +package foo + +fun box() : Boolean { + + + (when (1) { + 3 -> { + 3 + } + 1 -> { + throw Exception(); + } + else -> { + return false + } + }) + + return false +} \ No newline at end of file diff --git a/translator/testFiles/patternMatching/cases/whenValueOrType.kt b/translator/testFiles/patternMatching/cases/whenValueOrType.kt index 5489fae2bd4..880a7d17ed5 100644 --- a/translator/testFiles/patternMatching/cases/whenValueOrType.kt +++ b/translator/testFiles/patternMatching/cases/whenValueOrType.kt @@ -16,10 +16,12 @@ fun box() : Boolean { is null -> c = 10; is B -> c = 10000 is A -> c = 20; + else -> c = 1000 } when(b) { is null -> c += 5 is B -> c += 100 + else -> c = 1000 } return (c == 25) } \ No newline at end of file