JS Back-end does not handle complex patterns any more

#KT-2359 In Progress
This commit is contained in:
Andrey Breslav
2012-09-05 12:53:48 +04:00
parent 4dd0b27e93
commit 1b65ba644e
9 changed files with 64 additions and 93 deletions
@@ -48,10 +48,6 @@ public final class PatternMatchingTest extends SingleFileTranslationTest {
fooBoxTest(); fooBoxTest();
} }
public void testWhenNotValue() throws Exception {
fooBoxTest();
}
public void testWhenValueOrType() throws Exception { public void testWhenValueOrType() throws Exception {
fooBoxTest(); fooBoxTest();
} }
@@ -31,8 +31,6 @@ import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getPattern;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getTypeReference;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
@@ -51,45 +49,30 @@ public final class PatternTranslator extends AbstractTranslator {
@NotNull @NotNull
public JsExpression translateIsExpression(@NotNull JetIsExpression expression) { public JsExpression translateIsExpression(@NotNull JetIsExpression expression) {
JsExpression left = Translation.translateAsExpression(expression.getLeftHandSide(), context()); JsExpression left = Translation.translateAsExpression(expression.getLeftHandSide(), context());
JetPattern pattern = getPattern(expression); JetTypeReference typeReference = expression.getTypeRef();
JsExpression resultingExpression = translatePattern(pattern, left); assert typeReference != null;
JsExpression result = translateIsCheck(left, typeReference);
if (expression.isNegated()) { if (expression.isNegated()) {
return negated(resultingExpression); return negated(result);
} }
return resultingExpression; return result;
} }
@NotNull @NotNull
public JsExpression translatePattern(@NotNull JetPattern pattern, @Nullable JsExpression expressionToMatch) { public JsExpression translateIsCheck(@NotNull JsExpression subject, @NotNull JetTypeReference typeReference) {
if (expressionToMatch == null) { JsExpression result = translateAsIntrinsicTypeCheck(subject, typeReference);
assert pattern instanceof JetExpressionPattern : "When using when without parameters we can have only expression patterns";
return translateExpressionForExpressionPattern((JetExpressionPattern)pattern);
}
if (pattern instanceof JetTypePattern) {
return translateTypePattern(expressionToMatch, (JetTypePattern)pattern);
}
if (pattern instanceof JetExpressionPattern) {
return translateExpressionPattern(expressionToMatch, (JetExpressionPattern)pattern);
}
throw new AssertionError("Unsupported pattern type " + pattern.getClass());
}
@NotNull
private JsExpression translateTypePattern(@NotNull JsExpression expressionToMatch,
@NotNull JetTypePattern pattern) {
JsExpression result = translateAsIntrinsicTypeCheck(expressionToMatch, pattern);
if (result != null) { if (result != null) {
return result; return result;
} }
return translateAsIsCheck(expressionToMatch, pattern); return translateAsIsCheck(subject, typeReference);
} }
@NotNull @NotNull
private JsExpression translateAsIsCheck(@NotNull JsExpression expressionToMatch, private JsExpression translateAsIsCheck(@NotNull JsExpression expressionToMatch,
@NotNull JetTypePattern pattern) { @NotNull JetTypeReference typeReference) {
JsInvocation isCheck = new JsInvocation(context().namer().isOperationReference(), JsInvocation isCheck = new JsInvocation(context().namer().isOperationReference(),
expressionToMatch, getClassReference(pattern)); expressionToMatch, getClassReference(typeReference));
if (isNullable(pattern)) { if (isNullable(typeReference)) {
return addNullCheck(expressionToMatch, isCheck); return addNullCheck(expressionToMatch, isCheck);
} }
return isCheck; return isCheck;
@@ -97,9 +80,9 @@ public final class PatternTranslator extends AbstractTranslator {
@Nullable @Nullable
private JsExpression translateAsIntrinsicTypeCheck(@NotNull JsExpression expressionToMatch, private JsExpression translateAsIntrinsicTypeCheck(@NotNull JsExpression expressionToMatch,
@NotNull JetTypePattern pattern) { @NotNull JetTypeReference typeReference) {
JsExpression result = null; JsExpression result = null;
JsName className = getClassReference(pattern).getName(); JsName className = getClassReference(typeReference).getName();
if (className.getIdent().equals("String")) { if (className.getIdent().equals("String")) {
result = typeof(expressionToMatch, program().getStringLiteral("string")); result = typeof(expressionToMatch, program().getStringLiteral("string"));
} }
@@ -114,13 +97,12 @@ public final class PatternTranslator extends AbstractTranslator {
return or(TranslationUtils.isNullCheck(expressionToMatch), isCheck); return or(TranslationUtils.isNullCheck(expressionToMatch), isCheck);
} }
private boolean isNullable(JetTypePattern pattern) { private boolean isNullable(JetTypeReference typeReference) {
return BindingUtils.getTypeByReference(bindingContext(), getTypeReference(pattern)).isNullable(); return BindingUtils.getTypeByReference(bindingContext(), typeReference).isNullable();
} }
@NotNull @NotNull
private JsNameRef getClassReference(@NotNull JetTypePattern pattern) { private JsNameRef getClassReference(@NotNull JetTypeReference typeReference) {
JetTypeReference typeReference = getTypeReference(pattern);
return getClassNameReferenceForTypeReference(typeReference); return getClassNameReferenceForTypeReference(typeReference);
} }
@@ -132,15 +114,13 @@ public final class PatternTranslator extends AbstractTranslator {
} }
@NotNull @NotNull
private JsExpression translateExpressionPattern(@NotNull JsExpression expressionToMatch, JetExpressionPattern pattern) { public JsExpression translateExpressionPattern(@NotNull JsExpression expressionToMatch, @NotNull JetExpression patternExpression) {
JsExpression expressionToMatchAgainst = translateExpressionForExpressionPattern(pattern); JsExpression expressionToMatchAgainst = translateExpressionForExpressionPattern(patternExpression);
return equality(expressionToMatch, expressionToMatchAgainst); return equality(expressionToMatch, expressionToMatchAgainst);
} }
@NotNull @NotNull
private JsExpression translateExpressionForExpressionPattern(@NotNull JetExpressionPattern pattern) { public JsExpression translateExpressionForExpressionPattern(@NotNull JetExpression patternExpression) {
JetExpression patternExpression = pattern.getExpression();
assert patternExpression != null : "Expression patter should have an expression.";
return Translation.translateAsExpression(patternExpression, context()); return Translation.translateAsExpression(patternExpression, context());
} }
} }
@@ -182,14 +182,49 @@ public final class WhenTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression translatePatternCondition(@NotNull JetWhenCondition condition) { private JsExpression translatePatternCondition(@NotNull JetWhenCondition condition) {
JsExpression patternMatchExpression = Translation.patternTranslator(context()). JsExpression patternMatchExpression = translateWhenConditionToBooleanExpression(condition);
translatePattern(getPattern(condition), getExpressionToMatch());
if (isNegated(condition)) { if (isNegated(condition)) {
return negated(patternMatchExpression); return negated(patternMatchExpression);
} }
return 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 @Nullable
private JsExpression getExpressionToMatch() { private JsExpression getExpressionToMatch() {
return expressionToMatch != null ? expressionToMatch.reference() : null; return expressionToMatch != null ? expressionToMatch.reference() : null;
@@ -202,22 +237,6 @@ public final class WhenTranslator extends AbstractTranslator {
return false; return false;
} }
@NotNull
private static JetPattern getPattern(@NotNull JetWhenCondition condition) {
JetPattern pattern;
if (condition instanceof JetWhenConditionIsPattern) {
pattern = ((JetWhenConditionIsPattern)condition).getPattern();
}
else if (condition instanceof JetWhenConditionWithExpression) {
pattern = ((JetWhenConditionWithExpression)condition).getPattern();
}
else {
throw new AssertionError("Wrong type of JetWhenCondition");
}
assert pattern != null : "Condition should have a non null pattern.";
return pattern;
}
@Nullable @Nullable
private JsExpression translateExpressionToMatch(@NotNull JetWhenExpression expression) { private JsExpression translateExpressionToMatch(@NotNull JetWhenExpression expression) {
JetExpression subject = expression.getSubjectExpression(); JetExpression subject = expression.getSubjectExpression();
@@ -153,17 +153,4 @@ public final class PsiUtils {
return rangeExpression; return rangeExpression;
} }
@NotNull
public static JetPattern getPattern(@NotNull JetIsExpression expression) {
JetPattern pattern = expression.getPattern();
assert pattern != null : "Pattern should not be null";
return pattern;
}
@NotNull
public static JetTypeReference getTypeReference(@NotNull JetTypePattern pattern) {
JetTypeReference typeReference = pattern.getTypeReference();
assert typeReference != null : "Type pattern should contain a type reference";
return typeReference;
}
} }
@@ -5,12 +5,12 @@ fun box() : Int {
val d = 5 val d = 5
var z = 0 var z = 0
when(c) { when(c) {
is 5, is 3 -> z++; 5, 3 -> z++;
else -> {z = -1000;} else -> {z = -1000;}
} }
when(d) { when(d) {
is 5, is 3 -> z++; 5, 3 -> z++;
else -> {z = -1000;} else -> {z = -1000;}
} }
return z return z
@@ -4,8 +4,8 @@ package foo
fun box() : Boolean { fun box() : Boolean {
return (when(1) { return (when(1) {
is 2 -> 3 2 -> 3
is 1 -> 1 1 -> 1
else -> 5 else -> 5
} == 1) } == 1)
@@ -1,11 +0,0 @@
package foo
fun box() : Boolean {
var a = 4
when(a) {
!is 3 -> {a = 10;}
!is 4 -> {a = 20;}
else -> {a = 30;}
}
return (a == 10)
}
@@ -3,8 +3,8 @@ package foo
fun box() : Boolean { fun box() : Boolean {
var a = 4 var a = 4
when(a) { when(a) {
is 3 -> {a = 10;} 3 -> {a = 10;}
is 4 -> {a = 20;} 4 -> {a = 20;}
else -> {a = 30;} else -> {a = 30;}
} }
return (a == 20) return (a == 20)
@@ -13,13 +13,13 @@ fun box() : Boolean {
var a = A() : Any? var a = A() : Any?
var b = null : Any? var b = null : Any?
when(a) { when(a) {
is null -> c = 10; null -> c = 10;
is B -> c = 10000 is B -> c = 10000
is A -> c = 20; is A -> c = 20;
else -> c = 1000 else -> c = 1000
} }
when(b) { when(b) {
is null -> c += 5 null -> c += 5
is B -> c += 100 is B -> c += 100
else -> c = 1000 else -> c = 1000
} }