pattern matching for tuple and expression patterns

This commit is contained in:
Dmitry Jemerov
2011-07-06 15:24:34 +02:00
parent 3fe728dff6
commit 0c85c53c64
2 changed files with 54 additions and 0 deletions
@@ -1634,6 +1634,17 @@ public class ExpressionCodegen extends JetVisitor {
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
return negated ? StackValue.not(value) : value;
}
else if (pattern instanceof JetTuplePattern) {
return generateTuplePatternMatch((JetTuplePattern) pattern, negated, expressionToMatch);
}
else if (pattern instanceof JetExpressionPattern) {
final Type subjectType = expressionToMatch.type;
expressionToMatch.put(subjectType, v);
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
gen(condExpression, OBJECT_TYPE);
generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, OBJECT_TYPE);
return myStack.pop();
}
else if (pattern instanceof JetWildcardPattern) {
return StackValue.constant(!negated, Type.BOOLEAN_TYPE);
}
@@ -1642,6 +1653,41 @@ public class ExpressionCodegen extends JetVisitor {
}
}
private StackValue generateTuplePatternMatch(JetTuplePattern pattern, boolean negated, StackValue expressionToMatch) {
final List<JetTuplePatternEntry> entries = pattern.getEntries();
Label lblFail = new Label();
Label lblDone = new Label();
expressionToMatch.put(OBJECT_TYPE, v);
v.dup();
final String tupleClassName = "jet/Tuple" + entries.size();
Type tupleType = Type.getObjectType(tupleClassName);
v.instanceOf(tupleType);
Label lblCheck = new Label();
v.ifne(lblCheck);
Label lblPopAndFail = new Label();
v.mark(lblPopAndFail);
v.pop();
v.goTo(lblFail);
v.mark(lblCheck);
for (int i = 0; i < entries.size(); i++) {
final boolean isLast = i == entries.size() - 1;
if (!isLast) {
v.dup();
}
final StackValue tupleField = StackValue.field(OBJECT_TYPE, tupleClassName, "_" + (i + 1), false);
final StackValue stackValue = generatePatternMatch(entries.get(i).getPattern(), false, tupleField);
stackValue.condJump(isLast ? lblFail : lblPopAndFail, true, v);
}
v.aconst(!negated);
v.goTo(lblDone);
v.mark(lblFail);
v.aconst(negated);
v.mark(lblDone);
return StackValue.onStack(Type.BOOLEAN_TYPE);
}
private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) {
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (jetType.getArguments().size() > 0 || !(descriptor instanceof ClassDescriptor)) {
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import jet.NoPatternMatchedException;
import jet.Tuple2;
import java.lang.reflect.Method;
@@ -61,4 +62,11 @@ public class PatternMatchingTest extends CodegenTestCase {
Method foo = generateFunction();
assertEquals("x", foo.invoke(null, ""));
}
public void testTuplePattern() throws Exception {
loadText("fun foo(x: Tuple2<Any, Any>) = when(x) { is (1,2) => \"one,two\"; else => \"something\" }");
Method foo = generateFunction();
assertEquals("one,two", foo.invoke(null, new Tuple2<Integer, Integer>(1, 2)));
assertEquals("something", foo.invoke(null, new Tuple2<String, String>("not", "tuple")));
}
}