From bd33b23f512028578f5ac752ecf87a1f79df1e0e Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Thu, 17 Nov 2011 17:17:52 +0400 Subject: [PATCH] Added support for simple case of when expression. --- .../k2js/translate/AbstractTranslator.java | 2 +- .../k2js/translate/ExpressionVisitor.java | 7 + ...Translator.java => PatternTranslator.java} | 29 +++- .../jetbrains/k2js/translate/Translation.java | 24 +++- .../k2js/translate/WhenTranslator.java | 130 ++++++++++++++++++ .../jetbrains/k2js/test/BasicClassTest.java | 2 +- .../k2js/test/ClassInheritanceTest.java | 2 +- ...ClassTest.java => IncludeLibraryTest.java} | 2 +- .../k2js/test/PatternMatchingTest.java | 22 +++ .../k2js/test/PropertyAccessorTest.java | 2 +- .../org/jetbrains/k2js/test/RTTITest.java | 2 +- .../org/jetbrains/k2js/test/TraitTest.java | 2 +- .../patternMatching/cases/whenType.kt | 12 ++ 13 files changed, 223 insertions(+), 15 deletions(-) rename translator/src/org/jetbrains/k2js/translate/{TypeOperationTranslator.java => PatternTranslator.java} (76%) create mode 100644 translator/src/org/jetbrains/k2js/translate/WhenTranslator.java rename translator/test/org/jetbrains/k2js/test/{AbstractClassTest.java => IncludeLibraryTest.java} (80%) create mode 100644 translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java create mode 100644 translator/testFiles/patternMatching/cases/whenType.kt diff --git a/translator/src/org/jetbrains/k2js/translate/AbstractTranslator.java b/translator/src/org/jetbrains/k2js/translate/AbstractTranslator.java index 6f44e0846db..a53032a4ad7 100644 --- a/translator/src/org/jetbrains/k2js/translate/AbstractTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/AbstractTranslator.java @@ -11,7 +11,7 @@ public abstract class AbstractTranslator { @NotNull private final TranslationContext context; - public AbstractTranslator(@NotNull TranslationContext context) { + protected AbstractTranslator(@NotNull TranslationContext context) { this.context = context; } diff --git a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java index d96c738341d..b6c5a451ad1 100644 --- a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java @@ -386,5 +386,12 @@ public final class ExpressionVisitor extends TranslatorVisitor { return new JsConditional(nullCheck, thenExpression, nullLiteral); } + @Override + @NotNull + public JsNode visitWhenExpression(@NotNull JetWhenExpression expression, + @NotNull TranslationContext context) { + return Translation.translateWhenExpression(expression, context); + } + } diff --git a/translator/src/org/jetbrains/k2js/translate/TypeOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/PatternTranslator.java similarity index 76% rename from translator/src/org/jetbrains/k2js/translate/TypeOperationTranslator.java rename to translator/src/org/jetbrains/k2js/translate/PatternTranslator.java index 11e3aa1750a..d73984ddc2b 100644 --- a/translator/src/org/jetbrains/k2js/translate/TypeOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/PatternTranslator.java @@ -7,20 +7,21 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.psi.JetIsExpression; +import org.jetbrains.jet.lang.psi.JetPattern; import org.jetbrains.jet.lang.psi.JetTypePattern; import org.jetbrains.jet.lang.psi.JetTypeReference; /** * @author Talanov Pavel */ -public final class TypeOperationTranslator extends AbstractTranslator { +public final class PatternTranslator extends AbstractTranslator { @NotNull - public static TypeOperationTranslator newInstance(@NotNull TranslationContext context) { - return new TypeOperationTranslator(context); + public static PatternTranslator newInstance(@NotNull TranslationContext context) { + return new PatternTranslator(context); } - private TypeOperationTranslator(@NotNull TranslationContext context) { + private PatternTranslator(@NotNull TranslationContext context) { super(context); } @@ -39,16 +40,32 @@ public final class TypeOperationTranslator extends AbstractTranslator { // } @NotNull - JsExpression translateIsExpression(@NotNull JetIsExpression expression) { + public JsExpression translateIsExpression(@NotNull JetIsExpression expression) { JsExpression left = AstUtil.convertToExpression (Translation.translateExpression(expression.getLeftHandSide(), translationContext())); - JsExpression resultingExpression = translateTypePattern(left, (JetTypePattern) expression.getPattern()); + JetPattern pattern = getPattern(expression); + JsExpression resultingExpression = translatePattern(pattern, left); if (expression.isNegated()) { return AstUtil.negation(resultingExpression); } return resultingExpression; } + @NotNull + public JsExpression translatePattern(@NotNull JetPattern pattern, @NotNull JsExpression expressionToMatch) { + if (pattern instanceof JetTypePattern) { + return translateTypePattern(expressionToMatch, (JetTypePattern) pattern); + } + throw new AssertionError("Unsupported pattern type " + pattern.getClass()); + } + + @NotNull + private JetPattern getPattern(@NotNull JetIsExpression expression) { + JetPattern pattern = expression.getPattern(); + assert pattern != null : "Pattern should not be null"; + return pattern; + } + @NotNull private JsExpression translateTypePattern(@NotNull JsExpression expressionToMatch, @NotNull JetTypePattern pattern) { diff --git a/translator/src/org/jetbrains/k2js/translate/Translation.java b/translator/src/org/jetbrains/k2js/translate/Translation.java index f6f4f4b22a0..6580d694345 100644 --- a/translator/src/org/jetbrains/k2js/translate/Translation.java +++ b/translator/src/org/jetbrains/k2js/translate/Translation.java @@ -1,8 +1,12 @@ package org.jetbrains.k2js.translate; +import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsNode; +import com.google.dart.compiler.backend.js.ast.JsStatement; +import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetWhenExpression; /** * @author Talanov Pavel @@ -47,12 +51,28 @@ public final class Translation { } @NotNull - static public TypeOperationTranslator typeOperationTranslator(@NotNull TranslationContext context) { - return TypeOperationTranslator.newInstance(context); + static public PatternTranslator typeOperationTranslator(@NotNull TranslationContext context) { + return PatternTranslator.newInstance(context); } @NotNull static public JsNode translateExpression(@NotNull JetExpression expression, @NotNull TranslationContext context) { return expressionTranslator(context).translate(expression); } + + //TODO: clean out similar code fragments + @NotNull + static public JsExpression translateAsExpression(@NotNull JetExpression expression, @NotNull TranslationContext context) { + return AstUtil.convertToExpression(translateExpression(expression, context)); + } + + @NotNull + static public JsStatement translateAsStatement(@NotNull JetExpression expression, @NotNull TranslationContext context) { + return AstUtil.convertToStatement(translateExpression(expression, context)); + } + + @NotNull + static public JsNode translateWhenExpression(@NotNull JetWhenExpression expression, @NotNull TranslationContext context) { + return WhenTranslator.translateWhenExpression(expression, context); + } } diff --git a/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java b/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java new file mode 100644 index 00000000000..9ad7f3205ef --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java @@ -0,0 +1,130 @@ +package org.jetbrains.k2js.translate; + +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.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Talanov Pavel + */ +public class WhenTranslator extends AbstractTranslator { + + @NotNull + static public JsNode translateWhenExpression(@NotNull JetWhenExpression expression, @NotNull TranslationContext context) { + WhenTranslator translator = new WhenTranslator(expression, context); + return translator.translate(); + } + + @NotNull + private final JetWhenExpression whenExpression; + @NotNull + private final JsExpression expressionToMatch; + @NotNull + private final JsName dummyCounterName; + + private WhenTranslator(@NotNull JetWhenExpression expression, @NotNull TranslationContext context) { + super(context); + this.whenExpression = expression; + this.expressionToMatch = translateExpressionToMatch(whenExpression); + this.dummyCounterName = context.enclosingScope().declareTemporary(); + } + + @NotNull + JsNode translate() { + return translateEntries(); + } + + private JsBlock translateEntries() { + //JsFor resultingFor = generateDummyFor(); + List entries = new ArrayList(); + for (JetWhenEntry entry : whenExpression.getEntries()) { + entries.add(translateEntry(entry)); + } + return AstUtil.newBlock(entries); + } + + @NotNull + private JsFor generateDummyFor() { + JsFor result = new JsFor(); + result.setInitVars(generateInitStatement()); + result.setIncrExpr(generateIncrementStatement()); + result.setCondition(generateConditionStatement()); + return result; + } + + @NotNull + private JsBinaryOperation generateConditionStatement() { + JsNumberLiteral entriesNumber = program().getNumberLiteral(whenExpression.getEntries().size()); + return new JsBinaryOperation(JsBinaryOperator.LT, dummyCounterName.makeRef(), entriesNumber); + } + + @NotNull + private JsPrefixOperation generateIncrementStatement() { + return new JsPrefixOperation(JsUnaryOperator.INC, dummyCounterName.makeRef()); + } + + @NotNull + private JsVars generateInitStatement() { + return AstUtil.newVar(dummyCounterName, translationContext().program().getNumberLiteral(0)); + } + + @NotNull + private JsStatement translateEntry(@NotNull JetWhenEntry entry) { + JsStatement statementToExecute = translateExpressionToExecute(entry); + if (entry.isElse()) { + return statementToExecute; + } + JsExpression condition = translateConditions(entry); + return new JsIf(condition, statementToExecute, null); + } + + @NotNull + private JsStatement translateExpressionToExecute(@NotNull JetWhenEntry entry) { + JetExpression expressionToExecute = entry.getExpression(); + assert expressionToExecute != null : "WhenEntry should have whenExpression to execute."; + return Translation.translateAsStatement(expressionToExecute, translationContext()); + } + + //TODO: ask what these conditions mean + @NotNull + private JsExpression translateConditions(@NotNull JetWhenEntry entry) { + JetWhenCondition[] conditions = entry.getConditions(); +// for (JetWhenCondition condition : conditions) { +// translateCondition(condition); +// } + return translateCondition(conditions[0]); + } + + @NotNull + private JsExpression translateCondition(@NotNull JetWhenCondition condition) { + if (condition instanceof JetWhenConditionIsPattern) { + return translatePatternCondition((JetWhenConditionIsPattern) condition); + } + throw new AssertionError("Unsupported when condition " + condition.getClass()); + } + + + @NotNull + private JsExpression translatePatternCondition(@NotNull JetWhenConditionIsPattern condition) { + return Translation.typeOperationTranslator(translationContext()). + translatePattern(getPattern(condition), expressionToMatch); + } + + @NotNull + private JetPattern getPattern(@NotNull JetWhenConditionIsPattern condition) { + JetPattern pattern = condition.getPattern(); + assert pattern != null : "Is condition should have a non null pattern."; + return pattern; + } + + @NotNull + private JsExpression translateExpressionToMatch(@NotNull JetWhenExpression expression) { + JetExpression subject = expression.getSubjectExpression(); + assert subject != null : "Subject should not be null."; + return Translation.translateAsExpression(subject, translationContext()); + } +} diff --git a/translator/test/org/jetbrains/k2js/test/BasicClassTest.java b/translator/test/org/jetbrains/k2js/test/BasicClassTest.java index c05c9c072f4..42f8efaaa49 100644 --- a/translator/test/org/jetbrains/k2js/test/BasicClassTest.java +++ b/translator/test/org/jetbrains/k2js/test/BasicClassTest.java @@ -5,7 +5,7 @@ import org.junit.Test; /** * @author Talanov Pavel */ -public class BasicClassTest extends AbstractClassTest { +public class BasicClassTest extends IncludeLibraryTest { final private static String MAIN = "class/"; diff --git a/translator/test/org/jetbrains/k2js/test/ClassInheritanceTest.java b/translator/test/org/jetbrains/k2js/test/ClassInheritanceTest.java index 0d2f901d00b..247cf7e1b39 100644 --- a/translator/test/org/jetbrains/k2js/test/ClassInheritanceTest.java +++ b/translator/test/org/jetbrains/k2js/test/ClassInheritanceTest.java @@ -5,7 +5,7 @@ import org.junit.Test; /** * @author Talanov Pavel */ -public final class ClassInheritanceTest extends AbstractClassTest { +public final class ClassInheritanceTest extends IncludeLibraryTest { final private static String MAIN = "inheritance/"; diff --git a/translator/test/org/jetbrains/k2js/test/AbstractClassTest.java b/translator/test/org/jetbrains/k2js/test/IncludeLibraryTest.java similarity index 80% rename from translator/test/org/jetbrains/k2js/test/AbstractClassTest.java rename to translator/test/org/jetbrains/k2js/test/IncludeLibraryTest.java index a5214f7271f..4b87608a5f6 100644 --- a/translator/test/org/jetbrains/k2js/test/AbstractClassTest.java +++ b/translator/test/org/jetbrains/k2js/test/IncludeLibraryTest.java @@ -6,7 +6,7 @@ import java.util.List; /** * @author Talanov Pavel */ -public abstract class AbstractClassTest extends TranslationTest { +public abstract class IncludeLibraryTest extends TranslationTest { @Override protected List generateFilenameList(String inputFile) { diff --git a/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java b/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java new file mode 100644 index 00000000000..8b73a74f9df --- /dev/null +++ b/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java @@ -0,0 +1,22 @@ +package org.jetbrains.k2js.test; + +import org.junit.Test; + +/** + * @author Talanov Pavel + */ +public final class PatternMatchingTest extends IncludeLibraryTest { + + final private static String MAIN = "patternMatching/"; + + @Override + protected String mainDirectory() { + return MAIN; + } + + @Test + public void whenType() throws Exception { + testFooBoxIsTrue("whenType.kt"); + } + +} diff --git a/translator/test/org/jetbrains/k2js/test/PropertyAccessorTest.java b/translator/test/org/jetbrains/k2js/test/PropertyAccessorTest.java index 0d5a7f4d7e7..3052216e426 100644 --- a/translator/test/org/jetbrains/k2js/test/PropertyAccessorTest.java +++ b/translator/test/org/jetbrains/k2js/test/PropertyAccessorTest.java @@ -5,7 +5,7 @@ import org.junit.Test; /** * @author Talanov Pavel */ -public final class PropertyAccessorTest extends AbstractClassTest { +public final class PropertyAccessorTest extends IncludeLibraryTest { final private static String MAIN = "propertyAccess/"; diff --git a/translator/test/org/jetbrains/k2js/test/RTTITest.java b/translator/test/org/jetbrains/k2js/test/RTTITest.java index 4af82cc409c..0fa4ddc4d0f 100644 --- a/translator/test/org/jetbrains/k2js/test/RTTITest.java +++ b/translator/test/org/jetbrains/k2js/test/RTTITest.java @@ -5,7 +5,7 @@ import org.junit.Test; /** * @author Talanov Pavel */ -public class RTTITest extends AbstractClassTest { +public class RTTITest extends IncludeLibraryTest { final private static String MAIN = "rtti/"; diff --git a/translator/test/org/jetbrains/k2js/test/TraitTest.java b/translator/test/org/jetbrains/k2js/test/TraitTest.java index a153e15458c..6546702c631 100644 --- a/translator/test/org/jetbrains/k2js/test/TraitTest.java +++ b/translator/test/org/jetbrains/k2js/test/TraitTest.java @@ -5,7 +5,7 @@ import org.junit.Test; /** * @author Talanov Pavel */ -public final class TraitTest extends AbstractClassTest { +public final class TraitTest extends IncludeLibraryTest { final private static String MAIN = "trait/"; diff --git a/translator/testFiles/patternMatching/cases/whenType.kt b/translator/testFiles/patternMatching/cases/whenType.kt new file mode 100644 index 00000000000..87cfccc929f --- /dev/null +++ b/translator/testFiles/patternMatching/cases/whenType.kt @@ -0,0 +1,12 @@ +namespace foo + +class A() { + +} + +fun box() : Boolean { + when(A()) { + is A => return true; + else => return false; + } +} \ No newline at end of file