From 0c85c53c643343429bc11b18619c739ca148cc66 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 6 Jul 2011 15:24:34 +0200 Subject: [PATCH] pattern matching for tuple and expression patterns --- .../jet/codegen/ExpressionCodegen.java | 46 +++++++++++++++++++ .../jet/codegen/PatternMatchingTest.java | 8 ++++ 2 files changed, 54 insertions(+) diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 8bfe9bde50e..07d5a41d460 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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 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)) { diff --git a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java index 87a2980c25e..9c31be0dde8 100644 --- a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java @@ -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) = when(x) { is (1,2) => \"one,two\"; else => \"something\" }"); + Method foo = generateFunction(); + assertEquals("one,two", foo.invoke(null, new Tuple2(1, 2))); + assertEquals("something", foo.invoke(null, new Tuple2("not", "tuple"))); + } }