Mercurial > projects > dil
changeset 370:ae4afb66768f
- Renamed findModule() to findModulePath().
- Added struct Edge.
- Fix: don't append fileDir to importPaths when it's empty.
- Added function findCyclicEdges().
- Added method getFQN() to class ModuleDeclaration.
- Added member moduleFQN to class Module.
- Renamed Module.fileName to filePath.
- Added method setFQN() to class Module.
- Fix in Lexer.scanspecialTokenSequence(): corrected MID.
author | aziz |
---|---|
date | Mon, 03 Sep 2007 16:29:02 +0000 |
parents | 27767e203d64 |
children | 01887f05d4b0 |
files | trunk/src/cmd/ImportGraph.d trunk/src/dil/Declarations.d trunk/src/dil/Lexer.d trunk/src/dil/Module.d |
diffstat | 4 files changed, 138 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/src/cmd/ImportGraph.d Sat Sep 01 19:58:01 2007 +0000 +++ b/trunk/src/cmd/ImportGraph.d Mon Sep 03 16:29:02 2007 +0000 @@ -13,8 +13,9 @@ import std.stdio : writefln; import std.path : getDirName, dirSep = sep; import std.file : exists; +import std.string : replace; -string findModule(string moduleFQN, string[] importPaths) +string findModulePath(string moduleFQN, string[] importPaths) { string modulePath; foreach (path; importPaths) @@ -26,36 +27,66 @@ return null; } +struct Edge +{ + Module outgoing; + Module incoming; + static Edge opCall(Module o, Module i) + { + Edge e; + e.outgoing = o; + e.incoming = i; + return e; + } +} + void execute(string fileName, string[] importPaths) { // Add directory of file and global directories to import paths. - importPaths ~= getDirName(fileName) ~ GlobalSettings.importPaths; + auto fileDir = getDirName(fileName); + if (fileDir.length) + importPaths ~= fileDir; + importPaths ~= GlobalSettings.importPaths; Module[string] loadedModules; + Module[] loadedModulesList; // Ordered list of loaded modules. + Edge edges[]; - Module loadModule(string moduleFQN) + Module loadModule(string moduleFQNPath) { - auto mod_ = moduleFQN in loadedModules; + auto mod_ = moduleFQNPath in loadedModules; if (mod_ !is null) return *mod_; // writefln(moduleFQN); - auto modulePath = findModule(moduleFQN, importPaths); + auto modulePath = findModulePath(moduleFQNPath, importPaths); + Module mod; if (modulePath is null) - writefln("Warning: Module %s.d couldn't be found.", moduleFQN); + { +// writefln("Warning: Module %s.d couldn't be found.", moduleFQNPath); + mod = new Module(null, true); + mod.setFQN(replace(moduleFQNPath, dirSep, ".")); + loadedModules[moduleFQNPath] = mod; + loadedModulesList ~= mod; + } else { - auto mod = new Module(modulePath, true); + mod = new Module(modulePath, true); mod.parse(); - loadedModules[moduleFQN] = mod; + loadedModules[moduleFQNPath] = mod; + loadedModulesList ~= mod; auto moduleFQNs = mod.getImports(); foreach (moduleFQN_; moduleFQNs) - mod.modules ~= loadModule(moduleFQN_); + { + auto loaded_mod = loadModule(moduleFQN_); + edges ~= Edge(mod, loaded_mod); + mod.modules ~= loaded_mod; + } return mod; } - return null; + return mod; } auto mod = new Module(fileName, true); @@ -63,6 +94,54 @@ auto moduleFQNs = mod.getImports(); + loadedModules[mod.getFQNPath()] = mod; + loadedModulesList ~= mod; + foreach (moduleFQN_; moduleFQNs) - mod.modules ~= loadModule(moduleFQN_); + { + auto loaded_mod = loadModule(moduleFQN_); + edges ~= Edge(mod, loaded_mod); + mod.modules ~= loaded_mod; + } + + writefln("digraph module_dependencies\n{"); + foreach (edge; edges) + { + writefln(` "%s" -> "%s"`, edge.outgoing.getFQN(), edge.incoming.getFQN()); + } + writefln("}"); } + +Edge[] findCyclicEdges(Module[] modules, Edge[] edges) +{ + foreach (module_; modules) + { + uint outgoing, incoming; + foreach (edge; edges) + { + if (edge.outgoing == module_) + outgoing++; + if (edge.incoming == module_) + incoming++; + } + + if (outgoing == 0) + { + if (incoming != 0) + { + // sink + } + else + assert(0); // orphaned vertex (module) in graph + } + else if (incoming == 0) + { + // source + } + else + { + // source && sink + } + } + return null; +}
--- a/trunk/src/dil/Declarations.d Sat Sep 01 19:58:01 2007 +0000 +++ b/trunk/src/dil/Declarations.d Mon Sep 03 16:29:02 2007 +0000 @@ -74,6 +74,15 @@ this.packages = moduleFQN[0..$-1]; } + string getFQN() + { + auto pname = getPackageName('.'); + if (pname.length) + return pname ~ "." ~ getName(); + else + return getName(); + } + string getName() { if (moduleName)
--- a/trunk/src/dil/Lexer.d Sat Sep 01 19:58:01 2007 +0000 +++ b/trunk/src/dil/Lexer.d Mon Sep 03 16:29:02 2007 +0000 @@ -1441,7 +1441,7 @@ ++p; if (p[0] != 'l' || p[1] != 'i' || p[2] != 'n' || p[3] != 'e') { - mid = MID.ExpectedNumberAfterSTLine; + mid = MID.ExpectedIdentifierSTLine; goto Lerr; } p += 3;
--- a/trunk/src/dil/Module.d Sat Sep 01 19:58:01 2007 +0000 +++ b/trunk/src/dil/Module.d Mon Sep 03 16:29:02 2007 +0000 @@ -13,7 +13,8 @@ class Module { bool isLightweight; /// If true an ImportParser is used instead of a full Parser. - string fileName; /// Path to the source file. + string filePath; /// Path to the source file. + string moduleFQN; /// Fully qualified name of the module. string packageName; string moduleName; Declarations root; /// The root of the AST. @@ -23,36 +24,40 @@ Module[] modules; - this(string fileName, bool isLight = false) + this(string filePath, bool isLight = false) { - this.fileName = fileName; + this.filePath = filePath; this.isLightweight = isLightweight; } void parse() { - auto sourceText = loadFile(fileName); + auto sourceText = loadFile(filePath); if (this.isLightweight) - this.parser = new ImportParser(sourceText, fileName); + this.parser = new ImportParser(sourceText, filePath); else - this.parser = new Parser(sourceText, fileName); + this.parser = new Parser(sourceText, filePath); this.root = parser.start(); if (root.children.length) { - // moduleDecl will be null if first node can't be casted to ModuleDeclaration. + // moduleDecl will be null if first node can't be cast to ModuleDeclaration. this.moduleDecl = Cast!(ModuleDeclaration)(root.children[0]); if (moduleDecl) { - this.moduleName = moduleDecl.getName(); - this.packageName = moduleDecl.getPackageName(std.path.sep[0]); + this.setFQN(moduleDecl.getFQN()); } else { - auto str = getBaseName(getName(fileName)); + // Take base name of file path as module name. + auto str = getBaseName(getName(filePath)); if (Lexer.isNonReservedIdentifier(str)) - this.moduleName = str; + { + this.moduleFQN = moduleName = str; + } + // else + // TODO: error: file name has invalid identifier characters. } this.imports = parser.imports; @@ -69,6 +74,27 @@ string getFQN() { - return packageName ~ std.path.sep ~ moduleName; + return moduleFQN; + } + + void setFQN(string moduleFQN) + { + uint i = moduleFQN.length; + if (i != 0) // Don't decrement if string has zero length. + i--; + // Find last dot. + for (; i != 0 && moduleFQN[i] != '.'; i--) + {} + this.moduleFQN = moduleFQN; + this.packageName = moduleFQN[0..i]; + this.moduleName = moduleFQN[(i == 0 ? 0 : i+1) .. $]; + } + + string getFQNPath() + { + if (packageName.length) + return packageName ~ std.path.sep ~ moduleName; + else + return moduleName; } }