# HG changeset patch # User Aziz K?ksal # Date 1205279357 -3600 # Node ID 1abffc3965949a9848f9fcd8add614cb0cdd4c15 # Parent 3b567bce56f310d9c598504b26f21a2794d118f4 Revised the ModuleManager class. Fixed Parser.parseModuleDeclaration(). diff -r 3b567bce56f3 -r 1abffc396594 src/dil/Messages.d --- a/src/dil/Messages.d Tue Mar 11 17:23:30 2008 +0100 +++ b/src/dil/Messages.d Wed Mar 12 00:49:17 2008 +0100 @@ -155,6 +155,8 @@ auto MissingCatchOrFinally = "try statement is missing a catch or finally body."; // Semantic analysis: auto CouldntLoadModule = "couldn't load module '{}'"; + auto ConflictingModuleFiles = "module is in conflict with '{}'"; + auto ModuleNotInPackage = "expected module to be in package '{}'"; auto UndefinedIdentifier = "undefined identifier '{}'"; auto DeclConflictsWithDecl = "declaration '{}' conflicts with declaration @{}"; auto VariableConflictsWithDecl = "variable '{}' conflicts with declaration @{}"; diff -r 3b567bce56f3 -r 1abffc396594 src/dil/ModuleManager.d --- a/src/dil/ModuleManager.d Tue Mar 11 17:23:30 2008 +0100 +++ b/src/dil/ModuleManager.d Wed Mar 12 00:49:17 2008 +0100 @@ -5,16 +5,24 @@ module dil.ModuleManager; import dil.semantic.Module; +import dil.Location; import dil.Information; +import dil.Messages; import common; import tango.io.FilePath; +import tango.io.FileSystem; +import tango.io.FileConst; + +alias FileConst.PathSeparatorChar dirSep; /// Manages loaded modules in a table. class ModuleManager { /// Maps FQN paths to modules. E.g.: dil/ast/Node - Module[string] modulesTable; + Module[string] moduleFQNPathTable; + /// Maps absolute file paths to modules. E.g.: /home/user/dil/src/main.d + Module[string] absFilePathTable; Module[] loadedModules; /// Loaded modules in sequential order. string[] importPaths; /// Where to look for module files. InfoManager infoMan; @@ -29,41 +37,63 @@ /// Loads a module given a file path. Module loadModuleFile(string moduleFilePath) { - auto modul = new Module(moduleFilePath, infoMan); - modul.parse(); - auto moduleFQNPath = modul.getFQNPath(); - // Return the module if it's in the table already. - // This can happen if the module file path has been defined - // more than once on the command line. - if (auto existingModule = moduleFQNPath in modulesTable) - { - // TODO: avoid parsing the module in the first place, by - // using another table mapping absolute file paths - // to modules. - delete modul; + auto absFilePath = FileSystem.toAbsolute(moduleFilePath); + if (auto existingModule = absFilePath in absFilePathTable) + return *existingModule; + + // Create a new module. + auto newModule = new Module(moduleFilePath, infoMan); + newModule.parse(); + + auto moduleFQNPath = newModule.getFQNPath(); + if (auto existingModule = moduleFQNPath in moduleFQNPathTable) + { // Error: two module files have the same f.q. module name. + auto location = newModule.moduleDecl.begin.getErrorLocation(); + auto msg = Format(MSG.ConflictingModuleFiles, newModule.filePath()); + infoMan ~= new SemanticError(location, msg); return *existingModule; } // Insert new module. - modulesTable[moduleFQNPath] = modul; - loadedModules ~= modul; - return modul; + moduleFQNPathTable[moduleFQNPath] = newModule; + absFilePathTable[absFilePath] = newModule; + loadedModules ~= newModule; + return newModule; } /// Loads a module given an FQN path. Module loadModule(string moduleFQNPath) { // Look up in table if the module is already loaded. - Module* pmodul = moduleFQNPath in modulesTable; + Module* pmodul = moduleFQNPath in moduleFQNPathTable; if (pmodul) return *pmodul; // Locate the module in the file system. - auto moduleFilePath = findModuleFilePath(moduleFQNPath, - importPaths); + auto moduleFilePath = findModuleFilePath(moduleFQNPath, importPaths); if (moduleFilePath.length) - return loadModuleFile(moduleFilePath); + { // Load the found module file. + auto modul = loadModuleFile(moduleFilePath); + if (modul.getFQNPath() != moduleFQNPath) + { // Error: the requested module is not in the correct package. + auto location = modul.moduleDecl.begin.getErrorLocation(); + auto msg = Format(MSG.ModuleNotInPackage, getPackage(moduleFQNPath)); + infoMan ~= new SemanticError(location, msg); + } + return modul; + } return null; } + /// Returns e.g. 'dil.ast' for 'dil/ast/Node'. + string getPackage(string moduleFQNPath) + { + string pckg = moduleFQNPath.dup; + uint lastDirSep; + foreach (i, c; pckg) + if (c == dirSep) + (pckg[i] = '.'), (lastDirSep = i); + return pckg[0..lastDirSep]; + } + /// Searches for a module in the file system looking in importPaths. /// Returns: the file path to the module, or null if it wasn't found. static string findModuleFilePath(string moduleFQNPath, string[] importPaths) @@ -71,12 +101,12 @@ auto filePath = new FilePath(); foreach (importPath; importPaths) { - filePath.set(importPath); - filePath.append(moduleFQNPath); + filePath.set(importPath); // E.g.: src/ + filePath.append(moduleFQNPath); // E.g.: dil/ast/Node foreach (moduleSuffix; [".d", ".di"/*interface file*/]) { filePath.suffix(moduleSuffix); - if (filePath.exists()) + if (filePath.exists()) // E.g.: src/dil/ast/Node.d return filePath.toString(); } } diff -r 3b567bce56f3 -r 1abffc396594 src/dil/parser/Parser.d --- a/src/dil/parser/Parser.d Tue Mar 11 17:23:30 2008 +0100 +++ b/src/dil/parser/Parser.d Wed Mar 12 00:49:17 2008 +0100 @@ -182,8 +182,8 @@ Declaration parseModuleDeclaration() { + auto begin = token; skip(T.Module); - auto begin = token; ModuleFQN moduleFQN; do moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier);