changeset 513:6160ab7b1816

Refactored code related to settings.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Fri, 14 Dec 2007 19:08:21 +0100
parents 112c17300069
children 6ddff941862a
files trunk/src/config.d trunk/src/dil/CompilerInfo.d trunk/src/dil/Settings.d trunk/src/dil/SettingsLoader.d trunk/src/main.d
diffstat 5 files changed, 243 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/config.d	Thu Dec 13 23:04:50 2007 +0100
+++ b/trunk/src/config.d	Fri Dec 14 19:08:21 2007 +0100
@@ -1,2 +1,16 @@
-option langfile = "lang_en.d";
-option import_paths = [];
+// Relative paths are resolved from the directory of dil's executable.
+
+// Path to the language file.
+auto langfile = "lang_en.d";
+// An array of import paths to look for modules.
+auto import_paths = [];
+/*
+  Customizing error messages.
+  1: file path to the source text.
+  2: line number.
+  3: column number.
+  4: error message.
+*/
+auto lexer_error = "{1}({2},{3})L: {4}";
+auto parser_error = "{1}({2},{3})P: {4}";
+auto semantic_error = "{1}({2},{3})S: {4}";
--- a/trunk/src/dil/CompilerInfo.d	Thu Dec 13 23:04:50 2007 +0100
+++ b/trunk/src/dil/CompilerInfo.d	Fri Dec 14 19:08:21 2007 +0100
@@ -39,4 +39,5 @@
 /// ditto
 const COMPILED_DATE = __TIMESTAMP__;
 
-const DEFAULT_ALIGN_SIZE = 1; /// The global, default alignment size for struct fields.
+/// The global, default alignment size for struct fields.
+const DEFAULT_ALIGN_SIZE = 4;
--- a/trunk/src/dil/Settings.d	Thu Dec 13 23:04:50 2007 +0100
+++ b/trunk/src/dil/Settings.d	Fri Dec 14 19:08:21 2007 +0100
@@ -3,167 +3,20 @@
   License: GPL3
 +/
 module dil.Settings;
-import dil.Messages;
-import dil.Parser, dil.SyntaxTree, dil.Declarations, dil.Expressions;
-import dil.File;
-import tango.io.FilePath;
 import common;
 
 struct GlobalSettings
 {
 static:
-  string language; /// Language of loaded messages catalogue.
-  string[] messages; /// Table of localized compiler messages.
-  string[] importPaths; /// Array of import paths to look for modules.
-  void load()
-  {
-    scope execPath = new FilePath(GetExecutableFilePath());
-    auto fileName = execPath.file("config.d").toUtf8();
-    auto sourceText = loadFile(fileName);
-    auto parser = new Parser(sourceText, fileName);
-    auto root = parser.start();
-
-    if (parser.errors.length || parser.lx.errors.length)
-    {
-      throw new Exception("There are errors in " ~ fileName ~ ".");
-    }
-
-    foreach (decl; root.children)
-    {
-      auto v = Cast!(VariableDeclaration)(decl);
-      if (v is null)
-        continue;
-      auto vname = v.idents[0].str;
-      if (vname == "langfile")
-      {
-        auto e = v.values[0];
-        if (!e)
-          throw new Exception("langfile variable has no value set.");
-        auto val = Cast!(StringExpression)(e);
-        if (val)
-          // Set fileName to d-file with messages table.
-          fileName = val.getString();
-      }
-      else if (vname == "import_paths")
-      {
-        auto e = v.values[0];
-        if (e is null)
-          throw new Exception("import_paths variable has no variable set.");
-        if (auto array = Cast!(ArrayInitializer)(e))
-        {
-          foreach (value; array.values)
-            if (auto str = Cast!(StringExpression)(value))
-              GlobalSettings.importPaths ~= str.getString();
-        }
-        else
-          throw new Exception("import_paths variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
-      }
-    }
-
-    // Load messages
-    sourceText = loadFile(execPath.file(fileName).toUtf8());
-    parser = new Parser(sourceText, fileName);
-    root = parser.start();
-
-    if (parser.errors.length || parser.lx.errors.length)
-    {
-      throw new Exception("There are errors in "~fileName~".");
-    }
-
-    char[][] messages;
-    foreach (decl; root.children)
-    {
-      auto v = Cast!(VariableDeclaration)(decl);
-      if (v is null)
-        continue;
-      if (v.idents[0].str == "messages")
-      {
-        auto e = v.values[0];
-        if (!e)
-          throw new Exception("messages variable in "~fileName~" has no value set.");
-        if (auto array = Cast!(ArrayInitializer)(e))
-        {
-          foreach (value; array.values)
-          {
-            if (auto str = Cast!(StringExpression)(value))
-              messages ~= str.getString();
-          }
-        }
-        else
-          throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
-      }
-      else if(v.idents[0].str == "lang_code")
-      {
-        auto e = v.values[0];
-        if (!e)
-          throw new Exception("lang_code variable in "~fileName~" has no value set.");
-        if (auto str = Cast!(StringExpression)(e))
-            GlobalSettings.language = str.getString();
-      }
-    }
-    if (messages.length != MID.max+1)
-      throw new Exception(Format("messages table in {0} must exactly have {1} entries, but {2} were found.", fileName, MID.max+1, messages.length));
-    GlobalSettings.messages = messages;
-    dil.Messages.SetMessages(messages);
-  }
+  /// Path to the language file.
+  string langFile = "lang_en.d";
+  /// Language code of loaded messages catalogue.
+  string langCode = "en";
+  /// Table of localized compiler messages.
+  string[] messages;
+  /// Array of import paths to look for modules.
+  string[] importPaths;
+  string lexerErrorFormat = "{1}({2},{3})L: {4}";
+  string parserErrorFormat = "{1}({2},{3})L: {4}";
+  string semanticErrorFormat = "{1}({2},{3})L: {4}";
 }
-
-version(Windows)
-{
-private extern(Windows) uint GetModuleFileNameA(void*, char*, uint);
-/++
-  Get the fully qualified path to this executable.
-+/
-char[] GetExecutableFilePath()
-{
-  alias GetModuleFileNameA GetModuleFileName;
-  char[] buffer = new char[256];
-  uint count;
-
-  while (1)
-  {
-    if (buffer is null)
-      return null;
-
-    count = GetModuleFileName(null, buffer.ptr, buffer.length);
-    if (count == 0)
-      return null;
-    if (buffer.length != count && buffer[count] == 0)
-      break;
-    // Increase size of buffer
-    buffer.length = buffer.length * 2;
-  }
-  assert(buffer[count] == 0);
-  // Reduce buffer to the actual length of the string (excluding '\0'.)
-  if (count < buffer.length)
-    buffer.length = count;
-  return buffer;
-}
-}
-else version(linux)
-{
-private extern(C) size_t readlink(char* path, char* buf, size_t bufsize);
-/++
-  Get the fully qualified path to this executable.
-+/
-char[] GetExecutableFilePath()
-{
-  char[] buffer = new char[256];
-  size_t count;
-
-  while (1)
-  {
-    // This won't work on very old Linux systems.
-    count = readlink("/proc/self/exe".ptr, buffer.ptr, buffer.length);
-    if (count == -1)
-      return null;
-    if (count < buffer.length)
-      break;
-    buffer.length = buffer.length * 2;
-  }
-  buffer.length = count;
-  return buffer;
-}
-}
-else
-  static assert(0, "GetExecutableFilePath() is not implemented on your platform.");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/SettingsLoader.d	Fri Dec 14 19:08:21 2007 +0100
@@ -0,0 +1,180 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.SettingsLoader;
+
+import dil.Settings;
+import dil.Messages;
+import dil.Parser, dil.SyntaxTree, dil.Declarations, dil.Expressions;
+import dil.File;
+import tango.io.FilePath;
+import common;
+
+void loadSettings()
+{
+  scope execPath = new FilePath(GetExecutableFilePath());
+
+  // Load config.d
+  auto filePath = execPath.file("config.d").toUtf8();
+  auto sourceText = loadFile(filePath);
+  auto parser = new Parser(sourceText, filePath);
+  auto root = parser.start();
+
+  if (parser.errors.length || parser.lx.errors.length)
+    throw new Exception("There are errors in " ~ filePath ~ ".");
+
+  foreach (decl; root.children)
+  {
+    auto v = Cast!(VariableDeclaration)(decl);
+    if (v is null)
+      continue;
+
+    auto variableName = v.idents[0].str;
+    auto e = v.values[0];
+    if (!e)
+      throw new Exception(variableName ~ " variable has no value set.");
+
+    switch (variableName)
+    {
+    case "langfile":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.langFile = val.getString();
+      break;
+    case "import_paths":
+      if (auto array = Cast!(ArrayInitializer)(e))
+      {
+        foreach (value; array.values)
+          if (auto str = Cast!(StringExpression)(value))
+            GlobalSettings.importPaths ~= str.getString();
+      }
+      else
+        throw new Exception("import_paths variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
+      break;
+    case "lexer_error":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.lexerErrorFormat = val.getString();
+      break;
+    case "parser_error":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.parserErrorFormat = val.getString();
+      break;
+    case "semantic_error":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.semanticErrorFormat = val.getString();
+      break;
+    default:
+    }
+  }
+
+  // Load language file.
+  filePath = GlobalSettings.langFile;
+  sourceText = loadFile(execPath.file(filePath).toUtf8());
+  parser = new Parser(sourceText, filePath);
+  root = parser.start();
+
+  if (parser.errors.length || parser.lx.errors.length)
+    throw new Exception("There are errors in "~filePath~".");
+
+  char[][] messages;
+  foreach (decl; root.children)
+  {
+    auto v = Cast!(VariableDeclaration)(decl);
+    if (v is null)
+      continue;
+
+    auto variableName = v.idents[0].str;
+    auto e = v.values[0];
+    if (!e)
+      throw new Exception(variableName~" variable in "~filePath~" has no value set.");
+
+    switch (variableName)
+    {
+    case "messages":
+      if (auto array = Cast!(ArrayInitializer)(e))
+      {
+        foreach (value; array.values)
+        {
+          if (auto str = Cast!(StringExpression)(value))
+            messages ~= str.getString();
+        }
+      }
+      else
+        throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
+      break;
+    case "lang_code":
+      if (auto str = Cast!(StringExpression)(e))
+          GlobalSettings.langCode = str.getString();
+      break;
+    default:
+    }
+  }
+  if (messages.length != MID.max+1)
+    throw new Exception(
+      Format(
+        "messages table in {0} must exactly have {1} entries, but {2} were found.",
+        filePath, MID.max+1, messages.length)
+      );
+  GlobalSettings.messages = messages;
+  dil.Messages.SetMessages(messages);
+}
+
+version(Windows)
+{
+private extern(Windows) uint GetModuleFileNameA(void*, char*, uint);
+/++
+  Get the fully qualified path to this executable.
++/
+char[] GetExecutableFilePath()
+{
+  alias GetModuleFileNameA GetModuleFileName;
+  char[] buffer = new char[256];
+  uint count;
+
+  while (1)
+  {
+    if (buffer is null)
+      return null;
+
+    count = GetModuleFileName(null, buffer.ptr, buffer.length);
+    if (count == 0)
+      return null;
+    if (buffer.length != count && buffer[count] == 0)
+      break;
+    // Increase size of buffer
+    buffer.length = buffer.length * 2;
+  }
+  assert(buffer[count] == 0);
+  // Reduce buffer to the actual length of the string (excluding '\0'.)
+  if (count < buffer.length)
+    buffer.length = count;
+  return buffer;
+}
+}
+else version(linux)
+{
+private extern(C) size_t readlink(char* path, char* buf, size_t bufsize);
+/++
+  Get the fully qualified path to this executable.
++/
+char[] GetExecutableFilePath()
+{
+  char[] buffer = new char[256];
+  size_t count;
+
+  while (1)
+  {
+    // This won't work on very old Linux systems.
+    count = readlink("/proc/self/exe".ptr, buffer.ptr, buffer.length);
+    if (count == -1)
+      return null;
+    if (count < buffer.length)
+      break;
+    buffer.length = buffer.length * 2;
+  }
+  buffer.length = count;
+  return buffer;
+}
+}
+else
+  static assert(0, "GetExecutableFilePath() is not implemented on this platform.");
--- a/trunk/src/main.d	Thu Dec 13 23:04:50 2007 +0100
+++ b/trunk/src/main.d	Fri Dec 14 19:08:21 2007 +0100
@@ -3,11 +3,13 @@
   License: GPL3
 +/
 module main;
+
 import dil.Parser;
 import dil.Lexer;
 import dil.Token;
 import dil.Messages;
 import dil.Settings;
+import dil.SettingsLoader;
 import dil.CompilerInfo;
 import dil.Declarations, dil.Expressions, dil.SyntaxTree;
 import dil.File;
@@ -17,10 +19,13 @@
 import common;
 
 import Integer = tango.text.convert.Integer;
+import tango.io.File;
+import tango.text.Util;
+import tango.util.time.StopWatch;
 
 void main(char[][] args)
 {
-  GlobalSettings.load();
+  dil.SettingsLoader.loadSettings();
 
   if (args.length <= 1)
     return Stdout(helpMain()).newline;
@@ -130,6 +135,26 @@
       Stdout(token.srcText)(separator);
     }
     break;
+  case "profile":
+    if (args.length < 3)
+      break;
+    char[][] filePaths;
+    if (args[2] == "dstress")
+    {
+      auto text = cast(char[])(new File("dstress_files")).read();
+      filePaths = split(text, "\0");
+    }
+    else
+      filePaths = args[2..$];
+
+    StopWatch swatch;
+    swatch.start;
+
+    foreach (filePath; filePaths)
+      (new Lexer(loadFile(filePath), null)).scanAll();
+
+    Stdout.formatln("Scanned in {:f10}s.", swatch.stop);
+    break;
   case "parse":
     if (args.length == 3)
       parse(args[2]);
@@ -192,6 +217,14 @@
   dil tok -t"module foo; void func(){}"
   dil tok main.d | grep ^[0-9]`;
     break;
+  case "stats", "statistics":
+    msg = "Gather statistics about D source files.
+Usage:
+  dil stat file.d [file2.d, ...]
+
+Example:
+  dil stat src/dil/Parser.d src/dil/Lexer.d";
+    break;
   default:
     msg = helpMain();
   }