From 2280ad1470514ec7d6025d649d99a7e6ca90f461 Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Thu, 25 Feb 2016 14:27:18 -0800 Subject: [PATCH] Make PatternVariableFinder iterative rather than recursive for binary expressions. Modify pattern matching tests to use new "patternsExperimental" flag for those pattern-matching features not yet ready for prime time. --- .../Portable/Binder/PatternVariableFinder.cs | 30 +++++++++++++++++-- .../Semantics/PatternMatchingTests.cs | 4 ++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/PatternVariableFinder.cs b/src/Compilers/CSharp/Portable/Binder/PatternVariableFinder.cs index 105522e9b64..1607434a6f2 100644 --- a/src/Compilers/CSharp/Portable/Binder/PatternVariableFinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/PatternVariableFinder.cs @@ -6,12 +6,14 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; using System.Collections.Generic; +using System.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp { class PatternVariableFinder : CSharpSyntaxWalker { - ArrayBuilder declarationPatterns = ArrayBuilder.GetInstance(); + private ArrayBuilder declarationPatterns; + private ArrayBuilder expressions = ArrayBuilder.GetInstance(); internal static ArrayBuilder FindPatternVariables( ExpressionSyntax expression = null, ImmutableArray expressions = default(ImmutableArray), @@ -19,12 +21,16 @@ class PatternVariableFinder : CSharpSyntaxWalker { var finder = s_poolInstance.Allocate(); finder.declarationPatterns = ArrayBuilder.GetInstance(); - finder.Visit(expression); + var expressionsToProcess = finder.expressions; + Debug.Assert(expressionsToProcess.Count == 0); + + // push expressions onto the stack to be processed. + if (expression != null) expressionsToProcess.Add(expression); if (!expressions.IsDefaultOrEmpty) { foreach (var subExpression in expressions) { - if (subExpression != null) finder.Visit(subExpression); + expressionsToProcess.Add(subExpression); } } if (!patterns.IsDefaultOrEmpty) @@ -34,6 +40,7 @@ class PatternVariableFinder : CSharpSyntaxWalker finder.Visit(pattern); } } + finder.VisitExpressions(); var result = finder.declarationPatterns; finder.declarationPatterns = null; @@ -41,6 +48,17 @@ class PatternVariableFinder : CSharpSyntaxWalker return result; } + private void VisitExpressions() + { + // process expressions from the stack until none remain. + while (expressions.Count != 0) + { + var e = expressions[expressions.Count - 1]; + expressions.RemoveLast(); + Visit(e); + } + } + public override void VisitDeclarationPattern(DeclarationPatternSyntax node) { declarationPatterns.Add(node); @@ -50,6 +68,12 @@ public override void VisitDeclarationPattern(DeclarationPatternSyntax node) public override void VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node) { } public override void VisitAnonymousMethodExpression(AnonymousMethodExpressionSyntax node) { } public override void VisitQueryExpression(QueryExpressionSyntax node) { } + public override void VisitBinaryExpression(BinaryExpressionSyntax node) + { + // push subexpressions onto the stack to be processed. + expressions.Add(node.Left); + expressions.Add(node.Right); + } public override void VisitMatchExpression(MatchExpressionSyntax node) { Visit(node.Left); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs index 6d7339c6f59..358a03a114c 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs @@ -15,7 +15,9 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests public class PatternMatchingTests : CSharpTestBase { private static CSharpParseOptions patternParseOptions = - TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6).WithFeature("patterns", "true"); + TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6) + .WithFeature("patterns", "true") + .WithFeature("patternsExperimental", "true"); [Fact] public void SimplePatternTest() -- GitLab