
org.jetbrains.k2js.translate.expression.WhenTranslator Maven / Gradle / Ivy
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import org.jetbrains.k2js.translate.utils.mutator.AssignToExpressionMutator;
import org.jetbrains.k2js.translate.utils.mutator.LastExpressionMutator;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.convertToStatement;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.negated;
public final class WhenTranslator extends AbstractTranslator {
@Nullable
public static JsNode translate(@NotNull JetWhenExpression expression, @NotNull TranslationContext context) {
WhenTranslator translator = new WhenTranslator(expression, context);
if (BindingUtils.isStatement(context.bindingContext(), expression)) {
translator.translateAsStatement(context.dynamicContext().jsBlock().getStatements());
return null;
}
return translator.translateAsExpression();
}
@NotNull
private final JetWhenExpression whenExpression;
@Nullable
private final Pair expressionToMatch;
@Nullable
private Pair result;
private WhenTranslator(@NotNull JetWhenExpression expression, @NotNull TranslationContext context) {
super(context);
whenExpression = expression;
JetExpression subject = expression.getSubjectExpression();
if (subject != null) {
expressionToMatch = TranslationUtils.createTemporaryIfNeed(Translation.translateAsExpression(subject, context()), context);
}
else {
expressionToMatch = null;
}
}
@Nullable
private JsNode translateAsExpression() {
result = context().dynamicContext().createTemporary(null);
translateAsStatement(context().dynamicContext().jsBlock().getStatements());
return result.second;
}
private void translateAsStatement(List statements) {
addTempVarsStatement(statements);
JsIf prevIf = null;
for (JetWhenEntry entry : whenExpression.getEntries()) {
JsStatement statement = withReturnValueCaptured(translateEntryExpression(entry));
if (entry.isElse()) {
if (prevIf == null) {
statements.add(statement);
}
else {
prevIf.setElseStatement(statement);
}
break;
}
JsIf ifStatement = new JsIf(translateConditions(entry), statement);
if (prevIf == null) {
statements.add(ifStatement);
}
else {
prevIf.setElseStatement(ifStatement);
}
prevIf = ifStatement;
}
}
private void addTempVarsStatement(List statements) {
JsVars vars = new JsVars();
if (expressionToMatch != null && expressionToMatch.first != null) {
vars.add(expressionToMatch.first);
}
if (result != null) {
vars.add(result.first);
}
if (!vars.isEmpty()) {
statements.add(vars);
}
}
@NotNull
private JsStatement withReturnValueCaptured(@NotNull JsNode node) {
return result == null
? convertToStatement(node)
: LastExpressionMutator.mutateLastExpression(node, new AssignToExpressionMutator(result.second));
}
@NotNull
private JsNode translateEntryExpression(@NotNull JetWhenEntry entry) {
JetExpression expressionToExecute = entry.getExpression();
assert expressionToExecute != null : "WhenEntry should have whenExpression to execute.";
return Translation.translateExpression(expressionToExecute, context());
}
@NotNull
private JsExpression translateConditions(@NotNull JetWhenEntry entry) {
JetWhenCondition[] conditions = entry.getConditions();
assert conditions.length > 0 : "When entry (not else) should have at least one condition";
if (conditions.length == 1) {
return translateCondition(conditions[0]);
}
JsExpression result = translateCondition(conditions[0]);
for (int i = 1; i < conditions.length; i++) {
result = new JsBinaryOperation(JsBinaryOperator.OR, translateCondition(conditions[i]), result);
}
return result;
}
@NotNull
private JsExpression translateCondition(@NotNull JetWhenCondition condition) {
if ((condition instanceof JetWhenConditionIsPattern) || (condition instanceof JetWhenConditionWithExpression)) {
return translatePatternCondition(condition);
}
throw new AssertionError("Unsupported when condition " + condition.getClass());
}
@NotNull
private JsExpression translatePatternCondition(@NotNull JetWhenCondition condition) {
JsExpression patternMatchExpression = translateWhenConditionToBooleanExpression(condition);
if (isNegated(condition)) {
return negated(patternMatchExpression);
}
return patternMatchExpression;
}
@NotNull
private JsExpression translateWhenConditionToBooleanExpression(@NotNull JetWhenCondition condition) {
if (condition instanceof JetWhenConditionIsPattern) {
return translateIsCondition((JetWhenConditionIsPattern) condition);
}
else if (condition instanceof JetWhenConditionWithExpression) {
return translateExpressionCondition((JetWhenConditionWithExpression) condition);
}
throw new AssertionError("Wrong type of JetWhenCondition");
}
@NotNull
private JsExpression translateIsCondition(@NotNull JetWhenConditionIsPattern conditionIsPattern) {
JsExpression expressionToMatch = getExpressionToMatch();
assert expressionToMatch != null : "An is-check is not allowed in when() without subject.";
JetTypeReference typeReference = conditionIsPattern.getTypeRef();
assert typeReference != null : "An is-check must have a type reference.";
return Translation.patternTranslator(context()).translateIsCheck(expressionToMatch, typeReference);
}
@NotNull
private JsExpression translateExpressionCondition(@NotNull JetWhenConditionWithExpression condition) {
JetExpression patternExpression = condition.getExpression();
assert patternExpression != null : "Expression pattern should have an expression.";
JsExpression expressionToMatch = getExpressionToMatch();
if (expressionToMatch == null) {
return Translation.patternTranslator(context()).translateExpressionForExpressionPattern(patternExpression);
}
else {
return Translation.patternTranslator(context()).translateExpressionPattern(expressionToMatch, patternExpression);
}
}
@Nullable
private JsExpression getExpressionToMatch() {
return expressionToMatch != null ? expressionToMatch.second : null;
}
private static boolean isNegated(@NotNull JetWhenCondition condition) {
if (condition instanceof JetWhenConditionIsPattern) {
return ((JetWhenConditionIsPattern)condition).isNegated();
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy