@@ -1761,14 +1761,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase
1761
1761
VariableDeclaration matchedExpressionVariable = engine.forest
1762
1762
.createVariableDeclarationForValue (node.expression,
1763
1763
type: scrutineeType);
1764
- PatternTransformationResult transformationResult = node.patternGuard.pattern
1765
- .transform (
1766
- engine.forest
1767
- .createVariableGet (node.fileOffset, matchedExpressionVariable),
1768
- scrutineeType,
1769
- engine.forest
1770
- .createVariableGet (node.fileOffset, matchedExpressionVariable),
1771
- this );
1772
1764
1773
1765
// isPatternMatchingFailed: bool VAR = true;
1774
1766
VariableDeclaration isPatternMatchingFailed = engine.forest
@@ -1816,6 +1808,32 @@ class InferenceVisitorImpl extends InferenceVisitorBase
1816
1808
];
1817
1809
}
1818
1810
1811
+ PatternTransformationResult transformationResult = node.patternGuard.pattern
1812
+ .transform (
1813
+ engine.forest
1814
+ .createVariableGet (node.fileOffset, matchedExpressionVariable),
1815
+ scrutineeType,
1816
+ engine.forest
1817
+ .createVariableGet (node.fileOffset, matchedExpressionVariable),
1818
+ this );
1819
+ replacementStatements = _transformationResultToStatements (
1820
+ node.fileOffset, transformationResult, replacementStatements);
1821
+
1822
+ replacementStatements = [
1823
+ matchedExpressionVariable,
1824
+ if (otherwise != null ) isPatternMatchingFailed,
1825
+ ...replacementStatements,
1826
+ if (otherwiseBranchAsStatement != null ) otherwiseBranchAsStatement
1827
+ ];
1828
+
1829
+ return new StatementInferenceResult .multiple (
1830
+ node.fileOffset, replacementStatements);
1831
+ }
1832
+
1833
+ List <Statement > _transformationResultToStatements (
1834
+ int fileOffset,
1835
+ PatternTransformationResult transformationResult,
1836
+ List <Statement > replacementStatements) {
1819
1837
List <ContinuationStackElement > continuationStack = [];
1820
1838
for (int i = transformationResult.elements.length - 1 ; i >= 0 ; i-- ) {
1821
1839
PatternTransformationElement transformationElement =
@@ -1831,10 +1849,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase
1831
1849
if (condition != null ) {
1832
1850
replacementStatements = [
1833
1851
engine.forest.createIfStatement (
1834
- node. fileOffset,
1852
+ fileOffset,
1835
1853
condition,
1836
1854
engine.forest.createBlock (
1837
- node. fileOffset, node. fileOffset, replacementStatements),
1855
+ fileOffset, fileOffset, replacementStatements),
1838
1856
null )
1839
1857
];
1840
1858
}
@@ -1870,16 +1888,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
1870
1888
}
1871
1889
assert (continuationStack.isEmpty,
1872
1890
"Continuation stack is not empty at the end of desugaring." );
1873
-
1874
- replacementStatements = [
1875
- matchedExpressionVariable,
1876
- if (otherwise != null ) isPatternMatchingFailed,
1877
- ...replacementStatements,
1878
- if (otherwiseBranchAsStatement != null ) otherwiseBranchAsStatement
1879
- ];
1880
-
1881
- return new StatementInferenceResult .multiple (
1882
- node.fileOffset, replacementStatements);
1891
+ return replacementStatements;
1883
1892
}
1884
1893
1885
1894
ExpressionInferenceResult visitIntJudgment (
@@ -7721,8 +7730,158 @@ class InferenceVisitorImpl extends InferenceVisitorBase
7721
7730
7722
7731
StatementInferenceResult visitPatternSwitchStatement (
7723
7732
PatternSwitchStatement node) {
7724
- return new StatementInferenceResult .single (
7725
- new ExpressionStatement (new InvalidExpression ('$node ' )));
7733
+ Expression expression = node.expression;
7734
+ SwitchStatementTypeAnalysisResult <DartType > analysisResult =
7735
+ analyzeSwitchStatement (node, expression, node.cases.length);
7736
+ DartType scrutineeType = analysisResult.scrutineeType;
7737
+ // Stack: (Expression)
7738
+ Node ? rewrite = popRewrite ();
7739
+ if (! identical (expression, rewrite)) {
7740
+ expression = rewrite as Expression ;
7741
+ }
7742
+
7743
+ // matchedExpressionVariable: `scrutineeType` MVAR = `node.expression`;
7744
+ VariableDeclaration matchedExpressionVariable = engine.forest
7745
+ .createVariableDeclarationForValue (node.expression,
7746
+ type: scrutineeType);
7747
+
7748
+ // matchResultVariable: int RVAR = -1;
7749
+ VariableDeclaration matchResultVariable = engine.forest
7750
+ .createVariableDeclarationForValue (
7751
+ engine.forest.createIntLiteral (node.fileOffset, - 1 ),
7752
+ type: coreTypes.intNonNullableRawType);
7753
+
7754
+ // matchSucceeded: bool SVAR = false;
7755
+ VariableDeclaration matchSucceeded = engine.forest
7756
+ .createVariableDeclarationForValue (
7757
+ engine.forest.createBoolLiteral (node.fileOffset, false ),
7758
+ type: coreTypes.boolNonNullableRawType);
7759
+
7760
+ List <Statement > replacementStatements = [
7761
+ matchedExpressionVariable,
7762
+ matchResultVariable,
7763
+ matchSucceeded
7764
+ ];
7765
+
7766
+ List <SwitchCase > replacementCases = [];
7767
+
7768
+ List <VariableDeclaration > declaredVariableHelpers = [];
7769
+
7770
+ for (int caseIndex = 0 ; caseIndex < node.cases.length; caseIndex++ ) {
7771
+ SwitchCase switchCase = node.cases[caseIndex];
7772
+ if (switchCase is PatternSwitchCase ) {
7773
+ if (switchCase.patternGuards.length != 1 ) {
7774
+ // TODO(cstefantsova): Handle multiple patternGuards.
7775
+ }
7776
+ Pattern pattern = switchCase.patternGuards.first.pattern;
7777
+ Statement body = switchCase.body;
7778
+
7779
+ // setMatchResult: `matchResultVariable` = `caseIndex`;
7780
+ // ==> RVAR = `caseIndex`;
7781
+ Statement setMatchResult = engine.forest.createExpressionStatement (
7782
+ node.fileOffset,
7783
+ engine.forest.createVariableSet (
7784
+ node.fileOffset,
7785
+ matchResultVariable,
7786
+ engine.forest.createIntLiteral (node.fileOffset, caseIndex)));
7787
+
7788
+ // setMatchSucceeded: `matchSucceeded` = true;
7789
+ // ==> SVAR = true;
7790
+ Statement setMatchSucceeded = engine.forest.createExpressionStatement (
7791
+ node.fileOffset,
7792
+ engine.forest.createVariableSet (node.fileOffset, matchSucceeded,
7793
+ engine.forest.createBoolLiteral (node.fileOffset, true )));
7794
+
7795
+ PatternTransformationResult transformationResult = pattern.transform (
7796
+ engine.forest
7797
+ .createVariableGet (node.fileOffset, matchedExpressionVariable),
7798
+ scrutineeType,
7799
+ engine.forest
7800
+ .createVariableGet (node.fileOffset, matchedExpressionVariable),
7801
+ this );
7802
+
7803
+ // condition: `matchSucceeded`!
7804
+ // ==> SVAR!
7805
+ transformationResult = transformationResult.prependElement (
7806
+ new PatternTransformationElement (
7807
+ condition: engine.forest.createNot (
7808
+ node.fileOffset,
7809
+ engine.forest
7810
+ .createVariableGet (node.fileOffset, matchSucceeded)),
7811
+ variableInitializers: [],
7812
+ kind: PatternTransformationElementKind .regular),
7813
+ this );
7814
+
7815
+ List <VariableDeclaration > caseDeclaredVariableHelpers = [];
7816
+ List <Statement > caseDeclaredVariableHelperInitializers = [];
7817
+ for (VariableDeclaration declaredVariable
7818
+ in pattern.declaredVariables) {
7819
+ // declaredVariableHelper: dynamic HVAR;
7820
+ VariableDeclaration declaredVariableHelper = engine.forest
7821
+ .createVariableDeclaration (node.fileOffset, null ,
7822
+ type: const DynamicType ());
7823
+
7824
+ caseDeclaredVariableHelpers.add (declaredVariableHelper);
7825
+
7826
+ // initializer:
7827
+ // `declaredVariableHelper` = `declaredVariable.initializer`;
7828
+ // ==> HVAR = `declaredVariable.initializer`;
7829
+ caseDeclaredVariableHelperInitializers.add (engine.forest
7830
+ .createExpressionStatement (
7831
+ node.fileOffset,
7832
+ engine.forest.createVariableSet (node.fileOffset,
7833
+ declaredVariableHelper, declaredVariable.initializer! )));
7834
+
7835
+ // `declaredVariable`:
7836
+ // declaredVariable` =
7837
+ // `declaredVariableHelper`{`declaredVariable.type`}
7838
+ // ==> `declaredVariable` = HVAR{`declaredVariable.type`}
7839
+ declaredVariable.initializer = engine.forest
7840
+ .createVariableGet (node.fileOffset, declaredVariableHelper)
7841
+ ..promotedType = declaredVariable.type
7842
+ ..parent = declaredVariable;
7843
+ }
7844
+
7845
+ List <Statement > caseReplacementStatements = [
7846
+ setMatchResult,
7847
+ setMatchSucceeded,
7848
+ ...caseDeclaredVariableHelperInitializers
7849
+ ];
7850
+
7851
+ declaredVariableHelpers.addAll (caseDeclaredVariableHelpers);
7852
+
7853
+ caseReplacementStatements = _transformationResultToStatements (
7854
+ node.fileOffset, transformationResult, caseReplacementStatements);
7855
+
7856
+ replacementStatements.addAll (caseReplacementStatements);
7857
+
7858
+ replacementCases.add (new SwitchCaseImpl (
7859
+ [engine.forest.createIntLiteral (node.fileOffset, caseIndex)],
7860
+ [node.fileOffset],
7861
+ engine.forest
7862
+ .createBlock (node.fileOffset, node.fileOffset, < Statement > [
7863
+ ...pattern.declaredVariables,
7864
+ if (body is ! Block || body.statements.isNotEmpty) body
7865
+ ]),
7866
+ hasLabel: false ));
7867
+ } else if (switchCase is SwitchCaseImpl && switchCase.isDefault) {
7868
+ replacementCases.add (switchCase);
7869
+ } else {
7870
+ // TODO(cstefantsova): Report an internal or compile-time error.
7871
+ }
7872
+ }
7873
+
7874
+ replacementStatements = [
7875
+ ...declaredVariableHelpers,
7876
+ ...replacementStatements,
7877
+ engine.forest.createSwitchStatement (
7878
+ node.fileOffset,
7879
+ engine.forest.createVariableGet (node.fileOffset, matchResultVariable),
7880
+ replacementCases)
7881
+ ];
7882
+
7883
+ return new StatementInferenceResult .multiple (
7884
+ node.fileOffset, replacementStatements);
7726
7885
}
7727
7886
7728
7887
@override
@@ -8697,23 +8856,42 @@ class InferenceVisitorImpl extends InferenceVisitorBase
8697
8856
SwitchStatementMemberInfo <Node , Statement , Expression , VariableDeclaration >
8698
8857
getSwitchStatementMemberInfo (
8699
8858
covariant SwitchStatement node, int caseIndex) {
8700
- SwitchCaseImpl case_ = node.cases[caseIndex] as SwitchCaseImpl ;
8701
- return new SwitchStatementMemberInfo ([
8702
- for (Expression expression in case_.expressions)
8703
- new CaseHeadOrDefaultInfo (
8704
- pattern: expression,
8705
- // TODO(scheglov) pass actual variables, not just `{}`.
8706
- variables: {},
8707
- ),
8708
- if (case_.isDefault)
8709
- new CaseHeadOrDefaultInfo (
8710
- pattern: null ,
8711
- variables: {},
8712
- )
8713
- ], [
8714
- case_.body
8715
- ], {}, hasLabels: case_.hasLabel);
8716
- // TODO(scheglov) pass actual variables, not just `{}`.
8859
+ SwitchCase case_ = node.cases[caseIndex];
8860
+ if (case_ is SwitchCaseImpl ) {
8861
+ return new SwitchStatementMemberInfo ([
8862
+ for (Expression expression in case_.expressions)
8863
+ new CaseHeadOrDefaultInfo (
8864
+ pattern: expression,
8865
+ // TODO(scheglov) pass actual variables, not just `{}`.
8866
+ variables: {},
8867
+ ),
8868
+ if (case_.isDefault)
8869
+ new CaseHeadOrDefaultInfo (
8870
+ pattern: null ,
8871
+ variables: {},
8872
+ )
8873
+ ], [
8874
+ case_.body
8875
+ ], {}, hasLabels: case_.hasLabel);
8876
+ // TODO(scheglov) pass actual variables, not just `{}`.
8877
+ } else {
8878
+ case_ as PatternSwitchCase ;
8879
+ return new SwitchStatementMemberInfo ([
8880
+ for (PatternGuard patternGuard in case_.patternGuards)
8881
+ new CaseHeadOrDefaultInfo (
8882
+ pattern: patternGuard.pattern,
8883
+ // TODO(cstefantsova): Pass actual variables, not just `{}`.
8884
+ variables: {},
8885
+ ),
8886
+ if (case_.isDefault)
8887
+ new CaseHeadOrDefaultInfo (
8888
+ pattern: null ,
8889
+ variables: {},
8890
+ )
8891
+ ], [
8892
+ case_.body
8893
+ ], {}, hasLabels: case_.hasLabel);
8894
+ }
8717
8895
}
8718
8896
8719
8897
@override
@@ -8722,21 +8900,25 @@ class InferenceVisitorImpl extends InferenceVisitorBase
8722
8900
// Stack: (Pattern, Expression)
8723
8901
popRewrite (); // "when" expression
8724
8902
// Stack: (Pattern)
8725
- SwitchCaseImpl case_ = node.cases[caseIndex] as SwitchCaseImpl ;
8726
- Expression expression = case_.expressions[subIndex];
8727
- Node ? rewrite = popRewrite ();
8728
- // Stack: ()
8729
- if (! identical (expression, rewrite)) {
8730
- expression = rewrite as Expression ;
8731
- case_.expressions[subIndex] = expression..parent = case_;
8732
- }
8733
- Set <Field ?>? enumFields = _enumFields;
8734
- if (enumFields != null ) {
8735
- if (expression is StaticGet ) {
8736
- enumFields.remove (expression.target);
8737
- } else if (expression is NullLiteral ) {
8738
- enumFields.remove (null );
8903
+ SwitchCase case_ = node.cases[caseIndex];
8904
+ if (case_ is SwitchCaseImpl ) {
8905
+ Expression expression = case_.expressions[subIndex];
8906
+ Node ? rewrite = popRewrite ();
8907
+ // Stack: ()
8908
+ if (! identical (expression, rewrite)) {
8909
+ expression = rewrite as Expression ;
8910
+ case_.expressions[subIndex] = expression..parent = case_;
8739
8911
}
8912
+ Set <Field ?>? enumFields = _enumFields;
8913
+ if (enumFields != null ) {
8914
+ if (expression is StaticGet ) {
8915
+ enumFields.remove (expression.target);
8916
+ } else if (expression is NullLiteral ) {
8917
+ enumFields.remove (null );
8918
+ }
8919
+ }
8920
+ } else {
8921
+ case_ as PatternSwitchCase ;
8740
8922
}
8741
8923
}
8742
8924
0 commit comments