diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-07-08 17:47:31 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-07-08 18:22:26 -0700 |
| commit | 780a0bcd3724cad77cb65f931f111273776c9ca4 (patch) | |
| tree | 559e7c1d6c8cd43121f8e16d8f7686fc1608bb8a /source | |
| parent | a40b6679931f672a911070fcc7eeb41c52e8b8fd (diff) | |
Add back `UnparsedStmt`
If the user doesn't use any `import` declarations, there is no reason to parse their code at all, so having the option of falling back to `UnparsedStmt` can potentially save us some headaches down the road.
The new rule now is that if you have the "no checking" flag on, *and* the parser hasn't yet seen any `import` declarations, then it still used `UnparsedStmt` to avoid touching function bodies.
Otherwise, I go ahead and parse function bodies, and assume I can rewrite any code I can semantically understand.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/check.cpp | 5 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 16 | ||||
| -rw-r--r-- | source/slang/lower.cpp | 10 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 56 | ||||
| -rw-r--r-- | source/slang/stmt-defs.h | 7 |
5 files changed, 94 insertions, 0 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 556f141c0..2b9abef90 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1790,6 +1790,11 @@ namespace Slang checkStmt(stmt->NegativeStatement); } + void visitUnparsedStmt(UnparsedStmt*) + { + // Nothing to do + } + void visitEmptyStatementSyntaxNode(EmptyStatementSyntaxNode*) { // Nothing to do diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 24b0dd717..20b9856c5 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -2121,6 +2121,17 @@ struct EmitVisitor } } + void EmitUnparsedStmt(RefPtr<UnparsedStmt> stmt) + { + // TODO: actually emit the tokens that made up the statement... + Emit("{\n"); + for( auto& token : stmt->tokens ) + { + emitTokenWithLocation(token); + } + Emit("}\n"); + } + void EmitStmt(RefPtr<StatementSyntaxNode> stmt) { // Try to ensure that debugging can find the right location @@ -2139,6 +2150,11 @@ struct EmitVisitor } return; } + else if( auto unparsedStmt = stmt.As<UnparsedStmt>() ) + { + EmitUnparsedStmt(unparsedStmt); + return; + } else if (auto exprStmt = stmt.As<ExpressionStatementSyntaxNode>()) { EmitExpr(exprStmt->Expression); diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 8a4b7a4b1..0d54faf0b 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -688,6 +688,16 @@ struct LoweringVisitor addStmt(loweredStmt); } + void visitUnparsedStmt(UnparsedStmt* stmt) + { + RefPtr<UnparsedStmt> loweredStmt = new UnparsedStmt(); + lowerStmtFields(loweredStmt, stmt); + + loweredStmt->tokens = stmt->tokens; + + addStmt(loweredStmt); + } + void visitCaseStmt(CaseStmt* stmt) { RefPtr<CaseStmt> loweredStmt = new CaseStmt(); diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 199275a2d..759fc0c20 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -44,6 +44,11 @@ namespace Slang String fileName; int genericDepth = 0; + // Have we seen any `import` declarations? If so, we need + // to parse function bodies completely, even if we are in + // "rewrite" mode. + bool haveSeenAnyImportDecls = false; + // Is the parser in a "recovering" state? // During recovery we don't emit additional errors, until we find // a token that we expected, when we exit recovery. @@ -802,6 +807,8 @@ namespace Slang static RefPtr<Decl> parseImportDecl( Parser* parser) { + parser->haveSeenAnyImportDecls = true; + parser->ReadToken("__import"); auto decl = new ImportDecl(); @@ -842,6 +849,8 @@ namespace Slang static RefPtr<Decl> parsePoundImportDecl( Parser* parser) { + parser->haveSeenAnyImportDecls = true; + Token importToken = parser->ReadToken(TokenType::PoundImport); auto decl = new ImportDecl(); @@ -2599,6 +2608,53 @@ namespace Slang RefPtr<StatementSyntaxNode> Parser::ParseBlockStatement() { + // If we are being asked not to check things *and* we haven't + // seen any `import` declarations yet, then we can safely assume + // that function bodies should be left as-is. + if( (translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING) + && !haveSeenAnyImportDecls ) + { + // We have been asked to parse the input, but not attempt to understand it. + + // TODO: record start/end locations... + + List<Token> tokens; + + ReadToken(TokenType::LBrace); + + int depth = 1; + for( ;;) + { + switch( tokenReader.PeekTokenType() ) + { + case TokenType::EndOfFile: + goto done; + + case TokenType::RBrace: + depth--; + if(depth == 0) + goto done; + break; + + case TokenType::LBrace: + depth++; + break; + + default: + break; + } + + auto token = tokenReader.AdvanceToken(); + tokens.Add(token); + } + done: + ReadToken(TokenType::RBrace); + + RefPtr<UnparsedStmt> unparsedStmt = new UnparsedStmt(); + unparsedStmt->tokens = tokens; + return unparsedStmt; + } + RefPtr<ScopeDecl> scopeDecl = new ScopeDecl(); RefPtr<BlockStmt> blockStatement = new BlockStmt(); blockStatement->scopeDecl = scopeDecl; diff --git a/source/slang/stmt-defs.h b/source/slang/stmt-defs.h index 15826abc4..9dea40fbf 100644 --- a/source/slang/stmt-defs.h +++ b/source/slang/stmt-defs.h @@ -16,6 +16,13 @@ SYNTAX_CLASS(BlockStmt, ScopeStmt) SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, body); END_SYNTAX_CLASS() +// A statement that we aren't going to parse or check, because +// we want to let a downstream compiler handle any issues +SYNTAX_CLASS(UnparsedStmt, StatementSyntaxNode) + // The tokens that were contained between `{` and `}` + FIELD(List<Token>, tokens) +END_SYNTAX_CLASS() + SIMPLE_SYNTAX_CLASS(EmptyStatementSyntaxNode, StatementSyntaxNode) SIMPLE_SYNTAX_CLASS(DiscardStatementSyntaxNode, StatementSyntaxNode) |
