From d1b8a6b5c78d2108b789595742646bb83048be5b Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 6 Jul 2011 19:36:09 +0400 Subject: [PATCH] Multiple conditions in when entries --- .../jet/codegen/ExpressionCodegen.java | 4 ++- .../jet/lang/cfg/JetControlFlowProcessor.java | 13 +++++-- .../jetbrains/jet/lang/psi/JetWhenEntry.java | 6 ++-- .../jet/lang/types/JetTypeInferrer.java | 36 +++++++++++++++---- idea/testData/checker/regression/Jet169.jet | 8 +++++ 5 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 idea/testData/checker/regression/Jet169.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index ad84469d387..9656e11970d 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1774,7 +1774,9 @@ public class ExpressionCodegen extends JetVisitor { } nextEntry = new Label(); if (!whenEntry.isElse()) { - JetWhenCondition condition = whenEntry.getCondition(); + JetWhenCondition[] conditions = whenEntry.getConditions(); + assert conditions.length == 1 : "Support many conditions"; // TODO + JetWhenCondition condition = conditions[0]; StackValue conditionValue; if (condition instanceof JetWhenConditionWithExpression) { v.load(subjectLocal, subjectType); diff --git a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index cb2381a6a6f..79655f8f571 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -640,8 +640,11 @@ public class JetControlFlowProcessor { } } - JetWhenCondition condition = whenEntry.getCondition(); - if (condition != null) { + Label bodyLabel = builder.createUnboundLabel(); + + JetWhenCondition[] conditions = whenEntry.getConditions(); + for (int i = 0; i < conditions.length; i++) { + JetWhenCondition condition = conditions[i]; condition.accept(new JetVisitor() { private final JetVisitor conditionVisitor = this; @@ -714,10 +717,14 @@ public class JetControlFlowProcessor { throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); } }); + if (i + 1 < conditions.length) { + builder.nondeterministicJump(bodyLabel); + } } builder.nondeterministicJump(nextLabel); + builder.bindLabel(bodyLabel); value(whenEntry.getExpression(), true, inCondition); builder.jump(doneLabel); builder.bindLabel(nextLabel); @@ -771,4 +778,4 @@ public class JetControlFlowProcessor { // Nothing } }; -} \ No newline at end of file +} diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java index c1eb346dfcf..259d11cb479 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java @@ -38,8 +38,8 @@ public class JetWhenEntry extends JetElement { visitor.visitWhenEntry(this); } - @Nullable - public JetWhenCondition getCondition() { - return findChildByClass(JetWhenCondition.class); + @NotNull + public JetWhenCondition[] getConditions() { + return findChildrenByClass(JetWhenCondition.class); } } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index bab31af7a1c..f3f0bfc60ee 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -764,7 +764,7 @@ public class JetTypeInferrer { return getTypeWithNewContext(expression, new TypeInferenceContext(context.trace, scope, preferBlock, context.dataFlowInfo, context.expectedType, context.expectedReturnType)); } - private JetType getTypeWithNewDataFlowInfo(JetScope scope, JetExpression expression, boolean preferBlock, DataFlowInfo newDataFlowInfo) { + private JetType getTypeWithNewDataFlowInfo(JetScope scope, JetExpression expression, boolean preferBlock, @NotNull DataFlowInfo newDataFlowInfo) { return getTypeWithNewContext(expression, new TypeInferenceContext(context.trace, scope, preferBlock, newDataFlowInfo, context.expectedType, context.expectedReturnType)); } @@ -1294,11 +1294,35 @@ public class JetTypeInferrer { Set expressionTypes = Sets.newHashSet(); for (JetWhenEntry whenEntry : expression.getEntries()) { - JetWhenCondition condition = whenEntry.getCondition(); - WritableScope scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in when entry"); - DataFlowInfo newDataFlowInfo = context.dataFlowInfo; - if (condition != null) { - newDataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, scopeToExtend, variableDescriptor); + JetWhenCondition[] conditions = whenEntry.getConditions(); + DataFlowInfo newDataFlowInfo; + WritableScope scopeToExtend; + if (conditions.length == 1) { + scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in when entry"); + newDataFlowInfo = context.dataFlowInfo; + JetWhenCondition condition = conditions[0]; + if (condition != null) { + newDataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, scopeToExtend, variableDescriptor); + } + } + else { + scopeToExtend = newWritableScopeImpl(); // We don't write to this scope + newDataFlowInfo = null; + for (JetWhenCondition condition : conditions) { + DataFlowInfo dataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, newWritableScopeImpl(), variableDescriptor); + if (newDataFlowInfo == null) { + newDataFlowInfo = dataFlowInfo; + } + else { + newDataFlowInfo = newDataFlowInfo.or(dataFlowInfo); + } + } + if (newDataFlowInfo == null) { + newDataFlowInfo = context.dataFlowInfo; + } + else { + newDataFlowInfo = newDataFlowInfo.and(context.dataFlowInfo); + } } JetWhenExpression subWhen = whenEntry.getSubWhen(); JetExpression bodyExpression = subWhen == null ? whenEntry.getExpression() : subWhen; diff --git a/idea/testData/checker/regression/Jet169.jet b/idea/testData/checker/regression/Jet169.jet new file mode 100644 index 00000000000..2bed1f918f3 --- /dev/null +++ b/idea/testData/checker/regression/Jet169.jet @@ -0,0 +1,8 @@ +fun set(key : String, value : String) { + val a : String? = "" + when (a) { + "" => a.get(0) + is String, is Any => a.compareTo("") + else => a.toString() + } +}