diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-07-08 17:21:37 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-07-08 18:22:26 -0700 |
| commit | a40b6679931f672a911070fcc7eeb41c52e8b8fd (patch) | |
| tree | 0797d803e737ed96c54a58d485b2c803be4184c9 /source/slang/parser.cpp | |
| parent | 6233f9b35f1901ca33c53ce37f9b1517e91e1d79 (diff) | |
Differentiate HLSL `for` loops in AST
HLSL has the bad scoping behavior for `for` loops, and we need to respect that.
But, we need to have correct scoping for GLSL, and we'd like it for Slang.
We also need to ensure that `for` loops written in a "correct" language get the correct behavior when emitted as HLSL.
There was already code to handle this in the emit pass, but it was unfortunately using an `isRewrite` flag to try to tell if the HLSL behavior was wanted.
This doesn't work when the code being emitted might come from a mix of languages.
This change adds a distinct `UnscopedForStmt` syntax node type, and uses that when parsing HLSL input (bot not for other languages).
We make sure to preserve this node type through lowering, and then specialize our emit logic on this case.
With this, there are no more remaining uses of `isRewrite` in the emit logic, which is good because it didn't mean what I needed it to mean any more (since we now emit only a single module, that was merged during lowering).
Diffstat (limited to 'source/slang/parser.cpp')
| -rw-r--r-- | source/slang/parser.cpp | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 0efc8cd77..199275a2d 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -2673,12 +2673,32 @@ namespace Slang RefPtr<ForStatementSyntaxNode> Parser::ParseForStatement() { RefPtr<ScopeDecl> scopeDecl = new ScopeDecl(); - RefPtr<ForStatementSyntaxNode> stmt = new ForStatementSyntaxNode(); + + // HLSL implements the bad approach to scoping a `for` loop + // variable, and we want to respect that, but *only* when + // parsing HLSL code. + // + + bool brokenScoping = translationUnit->sourceLanguage == SourceLanguage::HLSL; + + // We will create a distinct syntax node class for the unscoped + // case, just so that we can correctly handle it in downstream + // logic. + // + RefPtr<ForStatementSyntaxNode> stmt; + if (brokenScoping) + { + stmt = new UnscopedForStmt(); + } + else + { + stmt = new ForStatementSyntaxNode(); + } + stmt->scopeDecl = scopeDecl; - // Note(tfoley): HLSL implements `for` with incorrect scoping. - // We need an option to turn on this behavior in a kind of "legacy" mode -// PushScope(scopeDecl.Ptr()); + if(!brokenScoping) + PushScope(scopeDecl.Ptr()); FillPosition(stmt.Ptr()); ReadToken("for"); ReadToken(TokenType::LParent); @@ -2704,7 +2724,10 @@ namespace Slang stmt->SideEffectExpression = ParseExpression(); ReadToken(TokenType::RParent); stmt->Statement = ParseStatement(); -// PopScope(); + + if (!brokenScoping) + PopScope(); + return stmt; } |
