-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Use less stack space while parsing if-statements #41657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6444,8 +6444,10 @@ private StatementSyntax ParseStatementNoDeclaration(bool allowAnyExpression) | |
| case SyntaxKind.GotoKeyword: | ||
| return this.ParseGotoStatement(); | ||
| case SyntaxKind.IfKeyword: | ||
| case SyntaxKind.ElseKeyword: // Including 'else' keyword to handle 'else without if' error cases | ||
| return this.ParseIfStatement(); | ||
| case SyntaxKind.ElseKeyword: | ||
| // Including 'else' keyword to handle 'else without if' error cases | ||
| return this.ParseMisplacedElse(); | ||
| case SyntaxKind.LockKeyword: | ||
| return this.ParseLockStatement(); | ||
| case SyntaxKind.ReturnKeyword: | ||
|
|
@@ -7709,19 +7711,28 @@ private GotoStatementSyntax ParseGotoStatement() | |
|
|
||
| private IfStatementSyntax ParseIfStatement() | ||
| { | ||
| Debug.Assert(this.CurrentToken.Kind == SyntaxKind.IfKeyword || this.CurrentToken.Kind == SyntaxKind.ElseKeyword); | ||
| Debug.Assert(this.CurrentToken.Kind == SyntaxKind.IfKeyword); | ||
|
|
||
| bool firstTokenIsElse = this.CurrentToken.Kind == SyntaxKind.ElseKeyword; | ||
| var @if = firstTokenIsElse | ||
| ? this.EatToken(SyntaxKind.IfKeyword, ErrorCode.ERR_ElseCannotStartStatement) | ||
| : this.EatToken(SyntaxKind.IfKeyword); | ||
| var openParen = this.EatToken(SyntaxKind.OpenParenToken); | ||
| var condition = this.ParseExpressionCore(); | ||
| var closeParen = this.EatToken(SyntaxKind.CloseParenToken); | ||
| var statement = firstTokenIsElse ? this.ParseExpressionStatement() : this.ParseEmbeddedStatement(); | ||
| var elseClause = this.ParseElseClauseOpt(); | ||
| return _syntaxFactory.IfStatement( | ||
| this.EatToken(SyntaxKind.IfKeyword), | ||
| this.EatToken(SyntaxKind.OpenParenToken), | ||
| this.ParseExpressionCore(), | ||
| this.EatToken(SyntaxKind.CloseParenToken), | ||
| this.ParseEmbeddedStatement(), | ||
| this.ParseElseClauseOpt()); | ||
| } | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. optimie the fast path of a normal if-statement, with no need for flow control or storage for flow control temps. |
||
|
|
||
| private IfStatementSyntax ParseMisplacedElse() | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MisplacedElse is a very rare case (usually just in the IDE as people are typing). it's fine for it to have it's own dedicated parsing method. |
||
| { | ||
| Debug.Assert(this.CurrentToken.Kind == SyntaxKind.ElseKeyword); | ||
|
|
||
| return _syntaxFactory.IfStatement(@if, openParen, condition, closeParen, statement, elseClause); | ||
| return _syntaxFactory.IfStatement( | ||
| this.EatToken(SyntaxKind.IfKeyword, ErrorCode.ERR_ElseCannotStartStatement), | ||
| this.EatToken(SyntaxKind.OpenParenToken), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we call EatToken, ParseExpressionCore, etc in this way even though we know they will always fail? Basically everything before 'ParseElseClauseOpt'?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. That's the idea (and what the code did before). It effectively synthesizes the missing nodes/tokens we want here |
||
| this.ParseExpressionCore(), | ||
| this.EatToken(SyntaxKind.CloseParenToken), | ||
| this.ParseExpressionStatement(), | ||
| this.ParseElseClauseOpt()); | ||
| } | ||
|
|
||
| private ElseClauseSyntax ParseElseClauseOpt() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea!