From a58672515a88270376c444eaee09e1962a6ddd64 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 19 May 2011 19:48:19 +0200 Subject: [PATCH] pattern matching with type patterns --- .../jet/codegen/ExpressionCodegen.java | 49 ++++++++++++++----- .../jet/lang/psi/JetIsExpression.java | 2 +- .../jet/codegen/PatternMatchingTest.java | 2 +- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 9c8aa0c5a76..2d0eb217f87 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1295,7 +1295,7 @@ public class ExpressionCodegen extends JetVisitor { } @Override - public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) { + public void visitBinaryWithTypeRHSExpression(final JetBinaryExpressionWithTypeRHS expression) { JetSimpleNameExpression operationSign = expression.getOperationSign(); IElementType opToken = operationSign.getReferencedNameElementType(); if (opToken == JetTokens.COLON) { @@ -1311,7 +1311,12 @@ public class ExpressionCodegen extends JetVisitor { Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE); gen(expression.getLeft(), OBJECT_TYPE); if (opToken == JetTokens.AS_SAFE) { - generateInstanceOf(expression.getLeft(), jetType, true); + generateInstanceOf(new Runnable() { + @Override + public void run() { + gen(expression.getLeft(), OBJECT_TYPE); + } + }, jetType, true); Label isInstance = new Label(); v.ifne(isInstance); v.pop(); @@ -1332,33 +1337,41 @@ public class ExpressionCodegen extends JetVisitor { } @Override - public void visitIsExpression(JetIsExpression expression) { - JetPattern pattern = expression.getPattern(); + public void visitIsExpression(final JetIsExpression expression) { + generatePatternMatch(expression.getPattern(), expression.isNegated(), new Runnable() { + @Override + public void run() { + gen(expression.getLeftHandSide(), OBJECT_TYPE); + } + }); + } + + private void generatePatternMatch(JetPattern pattern, boolean negated, Runnable expressionGen) { if (!(pattern instanceof JetTypePattern)) { throw new UnsupportedOperationException("can only generate a type pattern with 'is'"); } JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference(); JetType jetType = bindingContext.resolveTypeReference(typeReference); - generateInstanceOf(expression.getLeftHandSide(), jetType, false); + generateInstanceOf(expressionGen, jetType, false); StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); - myStack.push(expression.isNot() ? StackValue.not(value) : value); + myStack.push(negated ? StackValue.not(value) : value); } - private void generateInstanceOf(JetExpression expression, JetType jetType, boolean leaveExpressionOnStack) { + private void generateInstanceOf(Runnable expressionGen, JetType jetType, boolean leaveExpressionOnStack) { DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); if (!(descriptor instanceof ClassDescriptor)) { throw new UnsupportedOperationException("don't know how to handle non-class types"); } if (jetType.getArguments().size() > 0) { generateTypeInfo(jetType); - gen(expression, OBJECT_TYPE); + expressionGen.run(); if (leaveExpressionOnStack) { v.dupX1(); } v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z"); } else { - gen(expression, OBJECT_TYPE); + expressionGen.run(); if (leaveExpressionOnStack) { v.dup(); } @@ -1405,8 +1418,8 @@ public class ExpressionCodegen extends JetVisitor { @Override public void visitWhenExpression(JetWhenExpression expression) { JetExpression expr = expression.getSubjectExpression(); - Type subjectType = expressionType(expr); - int subjectLocal = myMap.enterTemp(subjectType.getSize()); + final Type subjectType = expressionType(expr); + final int subjectLocal = myMap.enterTemp(subjectType.getSize()); gen(expr, subjectType); v.store(subjectLocal, subjectType); @@ -1426,18 +1439,28 @@ public class ExpressionCodegen extends JetVisitor { Type condType = expressionType(condExpression); gen(condExpression, condType); generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType); - myStack.pop().condJump(nextEntry, true, v); } else if (condition instanceof JetWhenConditionInRange) { JetExpression range = ((JetWhenConditionInRange) condition).getRangeExpression(); gen(range, RANGE_TYPE); new StackValue.Local(subjectLocal, subjectType).put(OBJECT_TYPE, v); v.invokeinterface(CLASS_RANGE, "contains", "(Ljava/lang/Comparable;)Z"); - new StackValue.OnStack(Type.BOOLEAN_TYPE).condJump(nextEntry, true, v); + myStack.push(new StackValue.OnStack(Type.BOOLEAN_TYPE)); + } + else if (condition instanceof JetWhenConditionIsPattern) { + JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; + JetPattern pattern = patternCondition.getPattern(); + generatePatternMatch(pattern, patternCondition.isNegated(), new Runnable() { + @Override + public void run() { + new StackValue.Local(subjectLocal, subjectType).put(OBJECT_TYPE, v); + } + }); } else { throw new UnsupportedOperationException("unsupported kind of when condition"); } + myStack.pop().condJump(nextEntry, true, v); } else { hasElse = true; diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java index b3fa7f19d54..cec1562d18c 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java @@ -34,7 +34,7 @@ public class JetIsExpression extends JetExpression { return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); } - public boolean isNot() { + public boolean isNegated() { return getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IS; } diff --git a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java index eb4436d6507..2f0703678a7 100644 --- a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java @@ -35,7 +35,7 @@ public class PatternMatchingTest extends CodegenTestCase { assertTrue(caught); } - public void _testPattern() throws Exception { + public void testPattern() throws Exception { loadFile(); Method foo = generateFunction(); assertEquals("string", foo.invoke(null, ""));