summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/check.cpp17
-rw-r--r--source/slang/compiler.h10
-rw-r--r--source/slang/preprocessor.cpp52
-rw-r--r--source/slang/preprocessor.h7
-rw-r--r--source/slang/slang.cpp24
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(