Added support for simple case of when expression.

This commit is contained in:
Pavel Talanov
2011-11-17 17:17:52 +04:00
parent 628a2334f5
commit bd33b23f51
13 changed files with 223 additions and 15 deletions
@@ -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;
}
@@ -386,5 +386,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
return new JsConditional(nullCheck, thenExpression, nullLiteral);
}
@Override
@NotNull
public JsNode visitWhenExpression(@NotNull JetWhenExpression expression,
@NotNull TranslationContext context) {
return Translation.translateWhenExpression(expression, context);
}
}
@@ -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) {
@@ -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);
}
}
@@ -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<JsStatement> entries = new ArrayList<JsStatement>();
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());
}
}
@@ -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/";
@@ -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/";
@@ -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<String> generateFilenameList(String inputFile) {
@@ -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");
}
}
@@ -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/";
@@ -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/";
@@ -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/";
@@ -0,0 +1,12 @@
namespace foo
class A() {
}
fun box() : Boolean {
when(A()) {
is A => return true;
else => return false;
}
}