Mercurial > projects > dil
view src/dil/ModuleManager.d @ 815:615c1386b18d
Added code to class Package.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Wed, 12 Mar 2008 19:11:30 +0100 |
parents | 1abffc396594 |
children | 35d238d502cb |
line wrap: on
line source
/++ Author: Aziz Köksal License: GPL3 +/ module dil.ModuleManager; import dil.semantic.Module; import dil.semantic.Package; 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] 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; /// Constructs a ModuleManager object. this(string[] importPaths, InfoManager infoMan) { this.importPaths = importPaths; this.infoMan = infoMan; } /// Loads a module given a file path. Module loadModuleFile(string moduleFilePath) { 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. 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 moduleFQNPathTable; if (pmodul) return *pmodul; // Locate the module in the file system. auto moduleFilePath = findModuleFilePath(moduleFQNPath, importPaths); if (moduleFilePath.length) { // 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) { auto filePath = new FilePath(); foreach (importPath; importPaths) { 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()) // E.g.: src/dil/ast/Node.d return filePath.toString(); } } return null; } }