# HG changeset patch # User Aziz K?ksal # Date 1205200081 -3600 # Node ID 525ee3f848d9dcb77ebf8bacf8e6ba56edde774b # Parent 7e84472f4e917462e4682a8b532825a725120e09 Added modules cmd.Compile and dil.ModuleManager. Added options -I, -release and -unittest to the compile command. Tidied main.d up a bit. Renamed start() methods of SemanticPass1 and 2 to run(). Moved function findModuleFilePath() to class ModuleManager. Added msg CouldntLoadModule. Corrected two others. Added member semanticPass to class Module. Implemented visit(ImportDeclaration) in SemanticPass1. diff -r 7e84472f4e91 -r 525ee3f848d9 src/SettingsLoader.d --- a/src/SettingsLoader.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/SettingsLoader.d Tue Mar 11 02:48:01 2008 +0100 @@ -85,7 +85,7 @@ auto context = new CompilationContext; auto pass1 = new SemanticPass1(mod, context); - pass1.start(); + pass1.run(); if (auto array = getValue!(ArrayInitExpression)("version_ids")) foreach (value; array.values) @@ -121,7 +121,7 @@ return; pass1 = new SemanticPass1(mod, context); - pass1.start(); + pass1.run(); if (auto array = getValue!(ArrayInitExpression)("messages")) { @@ -163,7 +163,7 @@ auto context = new CompilationContext; auto pass1 = new SemanticPass1(mod, context); - pass1.start(); + pass1.run(); string[string] map; if (auto array = getValue!(ArrayInitExpression)("map")) diff -r 7e84472f4e91 -r 525ee3f848d9 src/cmd/Compile.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cmd/Compile.d Tue Mar 11 02:48:01 2008 +0100 @@ -0,0 +1,80 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module cmd.Compile; + +import dil.semantic.Module; +import dil.semantic.Pass1; +import dil.semantic.Pass2; +import dil.semantic.Symbols; +import dil.doc.Doc; +import dil.Compilation; +import dil.Information; +import dil.ModuleManager; +import common; + +/// The compile command. +struct CompileCommand +{ + string[] filePaths; /// Explicitly specified modules (on the command line.) + ModuleManager moduleMan; + SemanticPass1[] passes1; + + CompilationContext context; + InfoManager infoMan; + + /// Executes the compile command. + void run() + { + moduleMan = new ModuleManager(context.importPaths, infoMan); + foreach (filePath; filePaths) + { + auto modul = moduleMan.loadModuleFile(filePath); + runPass1(modul); + printSymbolTable(modul, ""); + } + + // foreach (modul; moduleMan.loadedModules) + // { + // auto pass2 = new SemanticPass2(modul); + // pass2.run(); + // } + } + + /// Runs the first pass on modul. + void runPass1(Module modul) + { + if (modul.hasErrors || modul.semanticPass != 0) + return; + auto pass1 = new SemanticPass1(modul, context); + pass1.importModule = &importModule; + pass1.run(); + passes1 ~= pass1; + } + + /// Imports a module and runs the first pass on it. + Module importModule(string moduleFQNPath) + { + auto modul = moduleMan.loadModule(moduleFQNPath); + modul && runPass1(modul); + return modul; + } + + /// Prints all symbols recursively (for debugging.) + static void printSymbolTable(ScopeSymbol scopeSym, char[] indent) + { + foreach (member; scopeSym.members) + { + auto tokens = getDocTokens(member.node); + char[] docText; + foreach (token; tokens) + docText ~= token.srcText; + Stdout(indent).formatln("Id:{}, Symbol:{}, DocText:{}", + member.name.str, member.classinfo.name, + docText); + if (auto s = cast(ScopeSymbol)member) + printSymbolTable(s, indent ~ "→ "); + } + } +} diff -r 7e84472f4e91 -r 525ee3f848d9 src/cmd/DDoc.d --- a/src/cmd/DDoc.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/cmd/DDoc.d Tue Mar 11 02:48:01 2008 +0100 @@ -75,7 +75,7 @@ // Start semantic analysis. auto pass1 = new SemanticPass1(mod, context); - pass1.start(); + pass1.run(); // Build destination file path. auto destPath = new FilePath(destDirPath); diff -r 7e84472f4e91 -r 525ee3f848d9 src/cmd/ImportGraph.d --- a/src/cmd/ImportGraph.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/cmd/ImportGraph.d Tue Mar 11 02:48:01 2008 +0100 @@ -10,6 +10,7 @@ import dil.parser.ImportParser; import dil.SourceText; import dil.Compilation; +import dil.ModuleManager; import Settings; import common; @@ -185,25 +186,6 @@ Status status; /// Used by the cycle detection algorithm. } -/// 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. -string findModuleFilePath(string moduleFQNPath, string[] importPaths) -{ - auto filePath = new FilePath(); - foreach (importPath; importPaths) - { - filePath.set(importPath); - filePath.append(moduleFQNPath); - foreach (moduleSuffix; [".d", ".di"/*interface file*/]) - { - filePath.suffix(moduleSuffix); - if (filePath.exists()) - return filePath.toString(); - } - } - return null; -} - /// Builds a module dependency graph. class GraphBuilder { @@ -246,7 +228,10 @@ } // Locate the module in the file system. - auto moduleFilePath = findModuleFilePath(moduleFQNPath, importPaths); + auto moduleFilePath = ModuleManager.findModuleFilePath( + moduleFQNPath, + importPaths + ); Vertex vertex; diff -r 7e84472f4e91 -r 525ee3f848d9 src/dil/Compilation.d --- a/src/dil/Compilation.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/dil/Compilation.d Tue Mar 11 02:48:01 2008 +0100 @@ -17,6 +17,7 @@ bool[string] debugIds; bool[string] versionIds; bool releaseBuild; + bool unittestBuild; uint structAlign = 4; this(CC parent = null) diff -r 7e84472f4e91 -r 525ee3f848d9 src/dil/Messages.d --- a/src/dil/Messages.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/dil/Messages.d Tue Mar 11 02:48:01 2008 +0100 @@ -154,11 +154,12 @@ auto ExpectedIdentOrInt = "expected an identifier or an integer, not '{}'"; auto MissingCatchOrFinally = "try statement is missing a catch or finally body."; // Semantic analysis: + auto CouldntLoadModule = "couldn't load module '{}'"; auto UndefinedIdentifier = "undefined identifier '{}'"; auto DeclConflictsWithDecl = "declaration '{}' conflicts with declaration @{}"; auto VariableConflictsWithDecl = "variable '{}' conflicts with declaration @{}"; auto InterfaceCantHaveVariables = "an interface can't have member variables"; auto MixinArgumentMustBeString = "the mixin argument must evaluate to a string"; - auto DebugSpecModuleLevel = "debug={} must be a module level"; - auto VersionSpecModuleLevel = "version={} must be a module level"; + auto DebugSpecModuleLevel = "debug={} must be at module level"; + auto VersionSpecModuleLevel = "version={} must be at module level"; } diff -r 7e84472f4e91 -r 525ee3f848d9 src/dil/semantic/Module.d --- a/src/dil/semantic/Module.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/dil/semantic/Module.d Tue Mar 11 02:48:01 2008 +0100 @@ -32,7 +32,13 @@ ModuleDeclaration moduleDecl; /// The optional ModuleDeclaration in this file. Parser parser; /// The parser used to parse this file. - // Module[] modules; + /// Indicates which passes have been run on this module. + /// + /// 0 = no pass$(BR) + /// 1 = semantic pass 1$(BR) + /// 2 = semantic pass 2 + uint semanticPass; + Module[] modules; /// The imported modules. InfoManager infoMan; /// Collects error messages. diff -r 7e84472f4e91 -r 525ee3f848d9 src/dil/semantic/Pass1.d --- a/src/dil/semantic/Pass1.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/dil/semantic/Pass1.d Tue Mar 11 02:48:01 2008 +0100 @@ -26,6 +26,9 @@ import dil.CompilerInfo; import common; +import tango.io.FileConst; +alias FileConst.PathSeparatorChar dirSep; + /// The first pass is the declaration pass. /// /// The basic task of this class is to traverse the parse tree, @@ -36,6 +39,7 @@ Scope scop; /// The current scope. Module modul; /// The module to be semantically checked. CompilationContext context; /// The compilation context. + Module delegate(string) importModule; /// Called when importing a module. // Attributes: LinkageType linkageType; /// Current linkage type. @@ -55,11 +59,12 @@ } /// Starts processing the module. - void start() + void run() { assert(modul.root !is null); // Create module scope. scop = new Scope(null, modul); + modul.semanticPass = 1; visit(modul.root); } @@ -187,14 +192,23 @@ D visit(IllegalDeclaration) { assert(0, "semantic pass on invalid AST"); return null; } - D visit(EmptyDeclaration ed) - { return ed; } + // D visit(EmptyDeclaration ed) + // { return ed; } - D visit(ModuleDeclaration) - { return null; } + // D visit(ModuleDeclaration) + // { return null; } D visit(ImportDeclaration d) { + if (importModule is null) + return d; + foreach (moduleFQNPath; d.getModuleFQNs(dirSep)) + { + auto importedModule = importModule(moduleFQNPath); + if (importedModule is null) + error(d.begin, MSG.CouldntLoadModule, moduleFQNPath ~ ".d"); + modul.modules ~= importedModule; + } return d; } diff -r 7e84472f4e91 -r 525ee3f848d9 src/dil/semantic/Pass2.d --- a/src/dil/semantic/Pass2.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/dil/semantic/Pass2.d Tue Mar 11 02:48:01 2008 +0100 @@ -44,11 +44,12 @@ } /// Start semantic analysis. - void start() + void run() { assert(modul.root !is null); // Create module scope. scop = new Scope(null, modul); + modul.semanticPass = 2; visit(modul.root); } diff -r 7e84472f4e91 -r 525ee3f848d9 src/main.d --- a/src/main.d Sun Mar 09 16:39:46 2008 +0100 +++ b/src/main.d Tue Mar 11 02:48:01 2008 +0100 @@ -24,6 +24,7 @@ import dil.SourceText; import dil.Compilation; +import cmd.Compile; import cmd.Highlight; import cmd.Statistics; import cmd.ImportGraph; @@ -50,59 +51,38 @@ return printErrors(infoMan); if (args.length <= 1) - return Stdout(helpMain()).newline; + return printHelp("main"); string command = args[1]; switch (command) { case "c", "compile": - if (args.length < 2) - return printHelp("compile"); + if (args.length < 3) + return printHelp(command); - string[] filePaths; - auto context = newCompilationContext(); + CompileCommand cmd; + cmd.context = newCompilationContext(); + cmd.infoMan = infoMan; + foreach (arg; args[2..$]) { - if (parseDebugOrVersion(arg, context)) + if (parseDebugOrVersion(arg, cmd.context)) {} + else if (strbeg(arg, "-I")) + cmd.context.importPaths ~= arg[2..$]; + else if (arg == "-release") + cmd.context.releaseBuild = true; + else if (arg == "-unittest") + cmd.context.unittestBuild = true; else - filePaths ~= arg; + cmd.filePaths ~= arg; } - - foreach (filePath; filePaths) - { - auto mod = new Module(filePath, infoMan); - // Parse the file. - mod.parse(); - if (mod.hasErrors) - continue; - - // Start semantic analysis. - auto pass1 = new SemanticPass1(mod, context); - pass1.start(); - - void printSymbolTable(ScopeSymbol scopeSym, char[] indent) - { - foreach (member; scopeSym.members) - { - auto tokens = getDocTokens(member.node); - char[] docText; - foreach (token; tokens) - docText ~= token.srcText; - Stdout(indent).formatln("Id:{}, Symbol:{}, DocText:{}", member.name.str, member.classinfo.name, docText); - if (auto s = cast(ScopeSymbol)member) - printSymbolTable(s, indent ~ "→ "); - } - } - - printSymbolTable(mod, ""); - } - + cmd.run(); infoMan.hasInfo && printErrors(infoMan); break; case "ddoc", "d": if (args.length < 4) - return printHelp("ddoc"); + return printHelp(command); DDocCommand cmd; cmd.destDirPath = args[2]; @@ -131,7 +111,7 @@ break; case "hl", "highlight": if (args.length < 3) - return printHelp("hl"); + return printHelp(command); HighlightCommand cmd; cmd.infoMan = infoMan; @@ -157,7 +137,7 @@ break; case "importgraph", "igraph": if (args.length < 3) - return printHelp("hl"); + return printHelp(command); IGraphCommand cmd; cmd.context = newCompilationContext(); @@ -204,6 +184,8 @@ cmd.run(); break; case "stats", "statistics": + if (args.length < 3) + return printHelp(command); char[][] filePaths; bool printTokensTable; bool printNodesTable; @@ -217,6 +199,8 @@ cmd.Statistics.execute(filePaths, printTokensTable, printNodesTable); break; case "tok", "tokenize": + if (args.length < 3) + return printHelp(command); SourceText sourceText; char[] filePath; char[] separator; @@ -259,7 +243,7 @@ break; case "trans", "translate": if (args.length < 3) - return printHelp("trans"); + return printHelp(command); if (args[2] != "German") return Stdout.formatln("Error: unrecognized target language \"{}\"", args[2]); @@ -296,10 +280,6 @@ Stdout.formatln("Scanned in {:f10}s.", swatch.stop); break; - // case "parse": - // if (args.length == 3) - // parse(args[2]); - // break; case "?", "help": printHelp(args.length >= 3 ? args[2] : ""); break; @@ -307,6 +287,7 @@ // genHTMLTypeRulesTables(); // break; default: + printHelp("main"); } } @@ -408,16 +389,6 @@ } } -/// Prints the compiler's main help message. -char[] helpMain() -{ - auto COMPILED_WITH = __VENDOR__; - auto COMPILED_VERSION = Format("{}.{,:d3}", __VERSION__/1000, __VERSION__%1000); - auto COMPILED_DATE = __TIMESTAMP__; - return FormatMsg(MID.HelpMain, VERSION, COMMANDS, COMPILED_WITH, - COMPILED_VERSION, COMPILED_DATE); -} - /// Prints a help message for command. void printHelp(char[] command) { @@ -438,9 +409,12 @@ -debug=ident : include debug(ident) code -version=level : include version(l) code where l >= level -version=ident : include version(ident) code + -Ipath : add 'path' to the list of import paths + -release : compile a release build + -unittest : compile a unittest build Example: - dil c src/main.d`; + dil c src/main.d -Isrc/`; break; case "ddoc", "d": msg = `Generate documentation from DDoc comments in D source files. @@ -548,25 +522,13 @@ Example: dil trans German src/main.d`; break; + case "main": default: - msg = helpMain(); + auto COMPILED_WITH = __VENDOR__; + auto COMPILED_VERSION = Format("{}.{,:d3}", __VERSION__/1000, __VERSION__%1000); + auto COMPILED_DATE = __TIMESTAMP__; + msg = FormatMsg(MID.HelpMain, VERSION, COMMANDS, COMPILED_WITH, + COMPILED_VERSION, COMPILED_DATE); } Stdout(msg).newline; } - -/+void parse(string fileName) -{ - auto mod = new Module(fileName); - mod.parse(); - - void print(Node[] decls, char[] indent) - { - foreach(decl; decls) - { - assert(decl !is null); - Stdout.formatln("{}{}: begin={} end={}", indent, decl.classinfo.name, decl.begin ? decl.begin.srcText : "\33[31mnull\33[0m", decl.end ? decl.end.srcText : "\33[31mnull\33[0m"); - print(decl.children, indent ~ " "); - } - } - print(mod.root.children, ""); -}+/