diff options
| -rw-r--r-- | source/slang/check.cpp | 17 | ||||
| -rw-r--r-- | source/slang/compiler.h | 10 | ||||
| -rw-r--r-- | source/slang/preprocessor.cpp | 52 | ||||
| -rw-r--r-- | source/slang/preprocessor.h | 7 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 24 |
5 files changed, 77 insertions, 33 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 463052bc8..582f19448 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -52,6 +52,14 @@ namespace Slang // lexical outer statements List<StatementSyntaxNode*> outerStmts; + + // We need to track what has been `import`ed, + // to avoid importing the same thing more than once + // + // TODO: a smarter approach might be to filter + // out duplicate references during lookup. + HashSet<ProgramSyntaxNode*> importedModules; + public: SemanticsVisitor( DiagnosticSink * pErr, @@ -4909,6 +4917,15 @@ namespace Slang // it later during code generation. decl->importedModuleDecl = importedModuleDecl; + // If we've imported this one already, then + // skip the step where we modify the current scope. + if (importedModules.Contains(importedModuleDecl.Ptr())) + { + return; + } + importedModules.Add(importedModuleDecl.Ptr()); + + // Create a new sub-scope to wire the module // into our lookup chain. auto subScope = new Scope(); diff --git a/source/slang/compiler.h b/source/slang/compiler.h index 7c4a17607..a6f3eee0e 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -203,9 +203,16 @@ namespace Slang RefPtr<ProgramLayout> layout; // Modules that have been dynamically loaded via `import` - Dictionary<String, RefPtr<ProgramSyntaxNode>> loadedModulesMap; + // + // This is a list of unique modules loaded, in the order they were encountered. List<RefPtr<ProgramSyntaxNode> > loadedModulesList; + // Map from the logical name of a module to its definition + Dictionary<String, RefPtr<ProgramSyntaxNode>> mapPathToLoadedModule; + + // Map from the path of a module file to its definition + Dictionary<String, RefPtr<ProgramSyntaxNode>> mapNameToLoadedModules; + CompileRequest(Session* session) : mSession(session) @@ -248,7 +255,6 @@ namespace Slang CodePosition const& loc); void handlePoundImport( - String const& name, String const& path, TokenList const& tokens); diff --git a/source/slang/preprocessor.cpp b/source/slang/preprocessor.cpp index c3cc8cb0a..084f518fb 100644 --- a/source/slang/preprocessor.cpp +++ b/source/slang/preprocessor.cpp @@ -167,11 +167,23 @@ struct Preprocessor // represent end-of-input situations. Token endOfFileToken; - // Syntax for the program we are trying to parse - ProgramSyntaxNode* syntax; + // The translation unit that is being parsed + TranslationUnitRequest* translationUnit; - // The over-arching compile request taht is invoking us - CompileRequest* compileRequest; + TranslationUnitRequest* getTranslationUnit() + { + return translationUnit; + } + + ProgramSyntaxNode* getSyntax() + { + return getTranslationUnit()->SyntaxNode.Ptr(); + } + + CompileRequest* getCompileRequest() + { + return getTranslationUnit()->compileRequest; + } }; // Convenience routine to access the diagnostic sink @@ -1733,7 +1745,7 @@ static void handleGLSLVersionDirective(PreprocessorDirectiveContext* context) // Attach the modifier to the program we are parsing! addModifier( - context->preprocessor->syntax, + context->preprocessor->getSyntax(), modifier); } @@ -1777,7 +1789,7 @@ static void handleGLSLExtensionDirective(PreprocessorDirectiveContext* context) // Attach the modifier to the program we are parsing! addModifier( - context->preprocessor->syntax, + context->preprocessor->getSyntax(), modifier); } @@ -2029,14 +2041,12 @@ TokenList preprocessSource( String const& fileName, DiagnosticSink* sink, IncludeHandler* includeHandler, - Dictionary<String, String> defines, - ProgramSyntaxNode* syntax, - CompileRequest* compileRequest) + Dictionary<String, String> defines, + TranslationUnitRequest* translationUnit) { Preprocessor preprocessor; InitializePreprocessor(&preprocessor, sink); - preprocessor.syntax = syntax; - preprocessor.compileRequest = compileRequest; + preprocessor.translationUnit = translationUnit; preprocessor.includeHandler = includeHandler; for (auto p : defines) @@ -2116,21 +2126,24 @@ static void HandleImportDirective(PreprocessorDirectiveContext* context) expectEndOfDirective(context); // TODO: may want to have some kind of canonicalization step here - String moduleName = foundPath; + String moduleKey = foundPath; // Import code from the chosen file, if needed. We only // need to import on the first `#import` directive, and // after that we ignore additional `#import`s for the same file. { - auto request = context->preprocessor->compileRequest; + auto translationUnit = context->preprocessor->translationUnit; + auto request = translationUnit->compileRequest; // Have we already loaded a module matching this name? - if (request->loadedModulesMap.TryGetValue(moduleName)) + if (request->mapPathToLoadedModule.TryGetValue(moduleKey)) { - // The module has already been loaded, so we bail out - // and leave *nothing* in the input stream. - return; + // The module has already been loaded, so we don't need to + // actually tokenize the code here. But note that we *do* + // go on to insert tokens for an `import` operation into + // the stream, so it is up to downstream code to avoid + // re-importing the same thing twice. } else { @@ -2158,8 +2171,7 @@ static void HandleImportDirective(PreprocessorDirectiveContext* context) // Now we need to do something with those tokens we read request->handlePoundImport( - moduleName, - foundPath, + moduleKey, subTokens); } } @@ -2172,7 +2184,7 @@ static void HandleImportDirective(PreprocessorDirectiveContext* context) token.Type = TokenType::PoundImport; token.Position = GetDirectiveLoc(context); token.flags = 0; - token.Content = moduleName; + token.Content = foundPath; inputStream->lexedTokens.mTokens.Add(token); diff --git a/source/slang/preprocessor.h b/source/slang/preprocessor.h index ebeb810a0..d23b19773 100644 --- a/source/slang/preprocessor.h +++ b/source/slang/preprocessor.h @@ -7,9 +7,9 @@ namespace Slang { -class CompileRequest; class DiagnosticSink; class ProgramSyntaxNode; +class TranslationUnitRequest; enum class IncludeResult { @@ -35,9 +35,8 @@ TokenList preprocessSource( String const& fileName, DiagnosticSink* sink, IncludeHandler* includeHandler, - Dictionary<String, String> defines, - ProgramSyntaxNode* syntax, - CompileRequest* compileRequest); + Dictionary<String, String> defines, + TranslationUnitRequest* translationUnit); } // namespace Slang diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 5e80dabf5..cd48a4152 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -167,8 +167,7 @@ void CompileRequest::parseTranslationUnit( &mSink, &includeHandler, combinedPreprocessorDefinitions, - translationUnitSyntax.Ptr(), - this); + translationUnit); parseSourceFile( translationUnit, @@ -398,7 +397,8 @@ RefPtr<ProgramSyntaxNode> CompileRequest::loadModule( RefPtr<ProgramSyntaxNode> moduleDecl = translationUnit->SyntaxNode; - loadedModulesMap.Add(name, moduleDecl); + mapPathToLoadedModule.Add(path, moduleDecl); + mapNameToLoadedModules.Add(name, moduleDecl); loadedModulesList.Add(moduleDecl); return moduleDecl; @@ -406,7 +406,6 @@ RefPtr<ProgramSyntaxNode> CompileRequest::loadModule( } void CompileRequest::handlePoundImport( - String const& name, String const& path, TokenList const& tokens) { @@ -436,7 +435,13 @@ void CompileRequest::handlePoundImport( RefPtr<ProgramSyntaxNode> moduleDecl = translationUnit->SyntaxNode; - loadedModulesMap.Add(name, moduleDecl); + // TODO: It is a bit broken here that we use the module path, + // as the "name" when registering things, but this saves + // us the trouble of trying to special-case things when + // checking an `import` down the road. + mapNameToLoadedModules.Add(path, moduleDecl); + + mapPathToLoadedModule.Add(path, moduleDecl); loadedModulesList.Add(moduleDecl); } @@ -447,7 +452,7 @@ RefPtr<ProgramSyntaxNode> CompileRequest::findOrImportModule( // Have we already loaded a module matching this name? // If so, return it. RefPtr<ProgramSyntaxNode> moduleDecl; - if (loadedModulesMap.TryGetValue(name, moduleDecl)) + if (mapNameToLoadedModules.TryGetValue(name, moduleDecl)) return moduleDecl; // Derive a file name for the module, by taking the given @@ -486,7 +491,7 @@ RefPtr<ProgramSyntaxNode> CompileRequest::findOrImportModule( { this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName); - loadedModulesMap[name] = nullptr; + mapNameToLoadedModules[name] = nullptr; return nullptr; } break; @@ -495,6 +500,11 @@ RefPtr<ProgramSyntaxNode> CompileRequest::findOrImportModule( break; } + // Maybe this was loaded previously via `#import` + if (mapPathToLoadedModule.TryGetValue(foundPath, moduleDecl)) + return moduleDecl; + + // We've found a file that we can load for the given module, so // go ahead and perform the module-load action return loadModule( |
