@@ -199,6 +199,7 @@ namespace Slang
199
199
Stmt* parseLabelStatement ();
200
200
DeclStmt* parseVarDeclrStatement (Modifiers modifiers);
201
201
IfStmt* parseIfStatement ();
202
+ Stmt* parseIfLetStatement ();
202
203
ForStmt* ParseForStatement ();
203
204
WhileStmt* ParseWhileStatement ();
204
205
DoWhileStmt* ParseDoWhileStatement ();
@@ -5276,7 +5277,16 @@ namespace Slang
5276
5277
if (LookAheadToken (TokenType::LBrace))
5277
5278
statement = parseBlockStatement ();
5278
5279
else if (LookAheadToken (" if" ))
5279
- statement = parseIfStatement ();
5280
+ {
5281
+ if (LookAheadToken (" let" , 2 ))
5282
+ {
5283
+ statement = parseIfLetStatement ();
5284
+ }
5285
+ else
5286
+ {
5287
+ statement = parseIfStatement ();
5288
+ }
5289
+ }
5280
5290
else if (LookAheadToken (" for" ))
5281
5291
statement = ParseForStatement ();
5282
5292
else if (LookAheadToken (" while" ))
@@ -5579,6 +5589,103 @@ namespace Slang
5579
5589
return varDeclrStatement;
5580
5590
}
5581
5591
5592
+ static Expr* constructIfLetPredicate (Parser* parser, VarExpr* varExpr)
5593
+ {
5594
+ // create a "var.hasValue" expression
5595
+ MemberExpr* memberExpr = parser->astBuilder ->create <MemberExpr>();
5596
+ memberExpr->baseExpression = varExpr;
5597
+ parser->FillPosition (memberExpr);
5598
+ memberExpr->name = getName (parser, " hasValue" );
5599
+
5600
+ return memberExpr;
5601
+ }
5602
+
5603
+ // Parse the syntax 'if (let var = X as Y)'
5604
+ Stmt* Parser::parseIfLetStatement ()
5605
+ {
5606
+ ScopeDecl* scopeDecl = astBuilder->create <ScopeDecl>();
5607
+ pushScopeAndSetParent (scopeDecl);
5608
+
5609
+ SeqStmt* newBody = astBuilder->create <SeqStmt>();
5610
+
5611
+ IfStmt* ifStatement = astBuilder->create <IfStmt>();
5612
+ FillPosition (ifStatement);
5613
+ ReadToken (" if" );
5614
+ ReadToken (TokenType::LParent);
5615
+
5616
+ // parse 'let var = X as Y'
5617
+ ReadToken (" let" );
5618
+ auto identifierToken = ReadToken (TokenType::Identifier);
5619
+ ReadToken (TokenType::OpAssign);
5620
+ auto initExpr = ParseInitExpr ();
5621
+
5622
+ // insert 'let tempVarDecl = X as Y;'
5623
+ auto tempVarDecl = astBuilder->create <LetDecl>();
5624
+ tempVarDecl->nameAndLoc = NameLoc (getName (this , " $OptVar" ), identifierToken.loc );
5625
+ tempVarDecl->initExpr = initExpr;
5626
+ AddMember (currentScope->containerDecl , tempVarDecl);
5627
+
5628
+ DeclStmt* tmpVarDeclStmt = astBuilder->create <DeclStmt>();
5629
+ FillPosition (tmpVarDeclStmt);
5630
+ tmpVarDeclStmt->decl = tempVarDecl;
5631
+ newBody->stmts .add (tmpVarDeclStmt);
5632
+
5633
+ // construct 'if (tempVarDecl.hasValue == true)'
5634
+ VarExpr* tempVarExpr = astBuilder->create <VarExpr>();
5635
+ tempVarExpr->scope = currentScope;
5636
+ FillPosition (tempVarExpr);
5637
+ tempVarExpr->name = tempVarDecl->getName ();
5638
+ ifStatement->predicate = constructIfLetPredicate (this , tempVarExpr);
5639
+
5640
+ ReadToken (TokenType::RParent);
5641
+
5642
+ // Create a new scope surrounding the positive statement, will be used for
5643
+ // the variable declared in the if_let syntax
5644
+ ScopeDecl* positiveScopeDecl = astBuilder->create <ScopeDecl>();
5645
+ pushScopeAndSetParent (positiveScopeDecl);
5646
+ ifStatement->positiveStatement = ParseStatement (ifStatement);
5647
+ PopScope ();
5648
+
5649
+ if (LookAheadToken (" else" ))
5650
+ {
5651
+ ReadToken (" else" );
5652
+ ifStatement->negativeStatement = ParseStatement (ifStatement);
5653
+ }
5654
+
5655
+ if (ifStatement->positiveStatement )
5656
+ {
5657
+ auto seqPositiveStmt = as<SeqStmt>(ifStatement->positiveStatement );
5658
+ if (!seqPositiveStmt)
5659
+ {
5660
+ seqPositiveStmt = astBuilder->create <SeqStmt>();
5661
+ }
5662
+
5663
+ MemberExpr* memberExpr = astBuilder->create <MemberExpr>();
5664
+ memberExpr->baseExpression = tempVarExpr;
5665
+ memberExpr->name = getName (this , " value" );
5666
+
5667
+ auto varDecl = astBuilder->create <LetDecl>();
5668
+ varDecl->nameAndLoc = NameLoc (identifierToken.getName (), identifierToken.loc );
5669
+ varDecl->initExpr = memberExpr;
5670
+
5671
+ DeclStmt* varDeclrStatement = astBuilder->create <DeclStmt>();
5672
+ varDeclrStatement->decl = varDecl;
5673
+
5674
+ // Add scope to the variable declared in the if_let syntax such
5675
+ // that this variable cannot be used outside the positive statement
5676
+ AddMember (positiveScopeDecl, varDecl);
5677
+
5678
+ seqPositiveStmt->stmts .add (varDeclrStatement);
5679
+ seqPositiveStmt->stmts .add (ifStatement->positiveStatement );
5680
+ ifStatement->positiveStatement = seqPositiveStmt;
5681
+ }
5682
+
5683
+ newBody->stmts .add (ifStatement);
5684
+ PopScope ();
5685
+
5686
+ return newBody;
5687
+ }
5688
+
5582
5689
IfStmt* Parser::parseIfStatement ()
5583
5690
{
5584
5691
IfStmt* ifStatement = astBuilder->create <IfStmt>();
0 commit comments