summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-07-08 17:47:31 -0700
committerTim Foley <tfoley@nvidia.com>2017-07-08 18:22:26 -0700
commit780a0bcd3724cad77cb65f931f111273776c9ca4 (patch)
tree559e7c1d6c8cd43121f8e16d8f7686fc1608bb8a /source
parenta40b6679931f672a911070fcc7eeb41c52e8b8fd (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.cpp5
-rw-r--r--source/slang/emit.cpp16
-rw-r--r--source/slang/lower.cpp10
-rw-r--r--source/slang/parser.cpp56
-rw-r--r--source/slang/stmt-defs.h7
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)