changeset 810:525ee3f848d9

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.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Tue, 11 Mar 2008 02:48:01 +0100
parents 7e84472f4e91
children 5c29f1ebec9f
files src/SettingsLoader.d src/cmd/Compile.d src/cmd/DDoc.d src/cmd/ImportGraph.d src/dil/Compilation.d src/dil/Messages.d src/dil/semantic/Module.d src/dil/semantic/Pass1.d src/dil/semantic/Pass2.d src/main.d
diffstat 10 files changed, 157 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- 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"))
--- /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 ~ "→ ");
+    }
+  }
+}
--- 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);
--- 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;
 
--- 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)
--- 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";
 }
--- 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.
 
--- 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;
   }
 
--- 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);
   }
 
--- 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, "");
-}+/