diff options
| author | Yong He <yonghe@outlook.com> | 2024-08-14 18:41:48 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-14 18:41:48 -0700 |
| commit | 071f1b6062b459928ebfd6f2f60a8d6ad021112b (patch) | |
| tree | 2ba65eb40f39701db6fc775a9258ec8079d161a0 /source/slang/slang-parser.cpp | |
| parent | 35a3d32c87f079749f6b100d01b289c3da02d7d6 (diff) | |
Variadic Generics Part 1: parsing and type checking. (#4833)
Diffstat (limited to 'source/slang/slang-parser.cpp')
| -rw-r--r-- | source/slang/slang-parser.cpp | 174 |
1 files changed, 84 insertions, 90 deletions
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 10b52611f..c1f0f91c2 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -112,6 +112,10 @@ namespace Slang bool hasSeenCompletionToken = false; + // Track whether or not we are inside a generics that has variadic parameters. + // If so we will enable the new `expand` and `each` keyword. + bool isInVariadicGenerics = false; + TokenReader tokenReader; DiagnosticSink* sink; SourceLoc lastErrorLoc; @@ -1476,41 +1480,50 @@ namespace Slang } return paramDecl; } + Decl* paramDecl = nullptr; + if (AdvanceIf(parser, "each")) + { + // A type pack parameter. + paramDecl = parser->astBuilder->create<GenericTypePackParamDecl>(); + parser->FillPosition(paramDecl); + paramDecl->nameAndLoc = NameLoc(parser->ReadToken(TokenType::Identifier)); + } else { // default case is a type parameter - GenericTypeParamDecl* paramDecl = parser->astBuilder->create<GenericTypeParamDecl>(); + paramDecl = parser->astBuilder->create<GenericTypeParamDecl>(); parser->FillPosition(paramDecl); paramDecl->nameAndLoc = NameLoc(parser->ReadToken(TokenType::Identifier)); - if (AdvanceIf(parser, TokenType::Colon)) - { - // The user is apply a constraint to this type parameter... - - auto paramConstraint = parser->astBuilder->create<GenericTypeConstraintDecl>(); - parser->FillPosition(paramConstraint); + } + if (AdvanceIf(parser, TokenType::Colon)) + { + // The user is apply a constraint to this type parameter... - auto paramType = DeclRefType::create( - parser->astBuilder, - DeclRef<Decl>(paramDecl)); + auto paramConstraint = parser->astBuilder->create<GenericTypeConstraintDecl>(); + parser->FillPosition(paramConstraint); - auto paramTypeExpr = parser->astBuilder->create<SharedTypeExpr>(); - paramTypeExpr->loc = paramDecl->loc; - paramTypeExpr->base.type = paramType; - paramTypeExpr->type = QualType(parser->astBuilder->getTypeType(paramType)); - - paramConstraint->sub = TypeExp(paramTypeExpr); - paramConstraint->sup = parser->ParseTypeExp(); + auto paramType = DeclRefType::create( + parser->astBuilder, + DeclRef<Decl>(paramDecl)); - AddMember(genericDecl, paramConstraint); + auto paramTypeExpr = parser->astBuilder->create<SharedTypeExpr>(); + paramTypeExpr->loc = paramDecl->loc; + paramTypeExpr->base.type = paramType; + paramTypeExpr->type = QualType(parser->astBuilder->getTypeType(paramType)); + paramConstraint->sub = TypeExp(paramTypeExpr); + paramConstraint->sup = parser->ParseTypeExp(); - } + AddMember(genericDecl, paramConstraint); + } + if (auto typeParameter = as<GenericTypeParamDecl>(paramDecl)) + { if (AdvanceIf(parser, TokenType::OpAssign)) { - paramDecl->initType = parser->ParseTypeExp(); + typeParameter->initType = parser->ParseTypeExp(); } - return paramDecl; } + return paramDecl; } template<typename TFunc> @@ -1519,6 +1532,9 @@ namespace Slang { parser->ReadToken(TokenType::OpLess); parser->genericDepth++; + bool oldIsInVariadicGenerics = parser->isInVariadicGenerics; + SLANG_DEFER(parser->isInVariadicGenerics = oldIsInVariadicGenerics); + for (;;) { const TokenType tokenType = parser->tokenReader.peekTokenType(); @@ -1530,7 +1546,13 @@ namespace Slang auto currentCursor = parser->tokenReader.getCursor(); - AddMember(decl, ParseGenericParamDecl(parser, decl)); + auto genericParam = ParseGenericParamDecl(parser, decl); + AddMember(decl, genericParam); + + if (as<GenericTypePackParamDecl>(genericParam)) + { + parser->isInVariadicGenerics = true; + } // Make sure we make forward progress. if (parser->tokenReader.getCursor() == currentCursor) @@ -2567,6 +2589,11 @@ namespace Slang typeSpec.expr = createDeclRefType(parser, decl); return typeSpec; } + else if (parser->LookAheadToken("expand") || parser->LookAheadToken("each")) + { + typeSpec.expr = parser->ParseExpression(); + return typeSpec; + } // Uncomment should we decide to enable (a,b,c) tuple types // else if(parser->LookAheadToken(TokenType::LParent)) // { @@ -6161,65 +6188,6 @@ namespace Slang { auto expr = ParseLeafExpression(); return parseInfixExprWithPrecedence(this, expr, level); - -#if 0 - - if (level == Precedence::Prefix) - return ParseLeafExpression(); - if (level == Precedence::TernaryConditional) - { - // parse select clause - auto condition = ParseExpression(Precedence(level + 1)); - if (LookAheadToken(TokenType::QuestionMark)) - { - SelectExpr* select = new SelectExpr(); - FillPosition(select.Ptr()); - - select->Arguments.add(condition); - - select->FunctionExpr = parseOperator(this); - - select->Arguments.add(ParseExpression(level)); - ReadToken(TokenType::Colon); - select->Arguments.add(ParseExpression(level)); - return select; - } - else - return condition; - } - else - { - if (GetAssociativityFromLevel(level) == Associativity::Left) - { - auto left = ParseExpression(Precedence(level + 1)); - while (GetOpLevel(this, tokenReader.PeekTokenType()) == level) - { - OperatorExpr* tmp = new InfixExpr(); - tmp->FunctionExpr = parseOperator(this); - - tmp->Arguments.add(left); - FillPosition(tmp.Ptr()); - tmp->Arguments.add(ParseExpression(Precedence(level + 1))); - left = tmp; - } - return left; - } - else - { - auto left = ParseExpression(Precedence(level + 1)); - if (GetOpLevel(this, tokenReader.PeekTokenType()) == level) - { - OperatorExpr* tmp = new InfixExpr(); - tmp->Arguments.add(left); - FillPosition(tmp.Ptr()); - tmp->FunctionExpr = parseOperator(this); - tmp->Arguments.add(ParseExpression(level)); - left = tmp; - } - return left; - } - } -#endif } // We *might* be looking at an application of a generic to arguments, @@ -7549,10 +7517,10 @@ namespace Slang return ret; } - static Expr* parseSPIRVAsmExpr(Parser* parser) + static Expr* parseSPIRVAsmExpr(Parser* parser, SourceLoc loc) { SPIRVAsmExpr* asmExpr = parser->astBuilder->create<SPIRVAsmExpr>(); - parser->FillPosition(asmExpr); + asmExpr->loc = loc; parser->ReadToken(TokenType::LBrace); while(!parser->tokenReader.isAtEnd()) { @@ -7577,6 +7545,22 @@ namespace Slang return asmExpr; } + static Expr* parseExpandExpr(Parser* parser, SourceLoc loc) + { + ExpandExpr* expandExpr = parser->astBuilder->create<ExpandExpr>(); + expandExpr->loc = loc; + expandExpr->baseExpr = parser->ParseExpression(); + return expandExpr; + } + + static Expr* parseEachExpr(Parser* parser, SourceLoc loc) + { + EachExpr* eachExpr = parser->astBuilder->create<EachExpr>(); + eachExpr->loc = loc; + eachExpr->baseExpr = parser->ParseExpression(); + return eachExpr; + } + static Expr* parsePrefixExpr(Parser* parser) { auto tokenType = peekTokenType(parser); @@ -7584,13 +7568,11 @@ namespace Slang { case TokenType::Identifier: { - auto identifierToken = peekToken(parser); - const auto identifierTokenContent = identifierToken.getContent(); - if (identifierTokenContent == toSlice("new")) + auto tokenLoc = peekToken(parser).getLoc(); + if (AdvanceIf(parser, "new")) { NewExpr* newExpr = parser->astBuilder->create<NewExpr>(); - parser->FillPosition(newExpr); - parser->ReadToken(); + newExpr->loc = tokenLoc; auto subExpr = parsePostfixExpr(parser); if (as<VarExpr>(subExpr) || as<GenericAppExpr>(subExpr)) { @@ -7611,9 +7593,21 @@ namespace Slang } else if (AdvanceIf(parser, "spirv_asm")) { - return parseSPIRVAsmExpr(parser); + return parseSPIRVAsmExpr(parser, tokenLoc); + } + else if (parser->isInVariadicGenerics) + { + // If we are inside a variadic generic, we also need to recognize + // the new `expand` and `each` keyword for dealing with variadic packs. + if (AdvanceIf(parser, "expand")) + { + return parseExpandExpr(parser, tokenLoc); + } + else if (AdvanceIf(parser, "each")) + { + return parseEachExpr(parser, tokenLoc); + } } - return parsePostfixExpr(parser); } default: |
