diff src/dil/lexer/IdTable.d @ 806:bcb74c9b895c

Moved out files in the trunk folder to the root.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 09 Mar 2008 00:12:19 +0100
parents trunk/src/dil/lexer/IdTable.d@cf2ad5df025c
children 372fa4fbbb1d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dil/lexer/IdTable.d	Sun Mar 09 00:12:19 2008 +0100
@@ -0,0 +1,162 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.lexer.IdTable;
+
+import dil.lexer.TokensEnum;
+import dil.lexer.IdentsGenerator;
+import dil.lexer.Keywords;
+import common;
+
+public import dil.lexer.Identifier;
+public import dil.lexer.IdentsEnum;
+
+/// A namespace for the predefined identifiers.
+struct Ident
+{
+  const static
+  {
+    mixin(generateIdentMembers());
+  }
+
+  static Identifier*[] allIds()
+  {
+    return __allIds;
+  }
+}
+
+/// Global table for hoarding and retrieving identifiers.
+struct IdTable
+{
+static:
+  /// A set of common, predefined identifiers for fast lookups.
+  private Identifier*[string] staticTable;
+  /// A table that grows with every newly found, unique identifier.
+  private Identifier*[string] growingTable;
+
+  /// Loads keywords and predefined identifiers into the static table.
+  static this()
+  {
+    foreach (ref k; g_reservedIds)
+      staticTable[k.str] = &k;
+    foreach (id; Ident.allIds())
+      staticTable[id.str] = id;
+    staticTable.rehash;
+  }
+
+  /// Looks up idString in both tables.
+  Identifier* lookup(string idString)
+  {
+    auto id = inStatic(idString);
+    if (id)
+      return id;
+    return inGrowing(idString);
+  }
+
+  /// Looks up idString in the static table.
+  Identifier* inStatic(string idString)
+  {
+    auto id = idString in staticTable;
+    return id ? *id : null;
+  }
+
+  alias Identifier* function(string idString) LookupFunction;
+  /// Looks up idString in the growing table.
+  LookupFunction inGrowing = &_inGrowing_unsafe; // Default to unsafe function.
+
+  /// Sets the thread safety mode of the growing table.
+  void setThreadsafe(bool b)
+  {
+    if (b)
+      inGrowing = &_inGrowing_safe;
+    else
+      inGrowing = &_inGrowing_unsafe;
+  }
+
+  /// Returns true if access to the growing table is thread-safe.
+  bool isThreadsafe()
+  {
+    return inGrowing is &_inGrowing_safe;
+  }
+
+  /// Looks up idString in the table.
+  ///
+  /// Adds idString to the table if not found.
+  private Identifier* _inGrowing_unsafe(string idString)
+  out(id)
+  { assert(id !is null); }
+  body
+  {
+    auto id = idString in growingTable;
+    if (id)
+      return *id;
+    auto newID = Identifier(idString, TOK.Identifier);
+    growingTable[idString] = newID;
+    return newID;
+  }
+
+  /// Looks up idString in the table.
+  ///
+  /// Adds idString to the table if not found.
+  /// Access to the data structure is synchronized.
+  private Identifier* _inGrowing_safe(string idString)
+  {
+    synchronized
+      return _inGrowing_unsafe(idString);
+  }
+
+  /+
+  Identifier* addIdentifiers(char[][] idStrings)
+  {
+    auto ids = new Identifier*[idStrings.length];
+    foreach (i, idString; idStrings)
+    {
+      Identifier** id = idString in tabulatedIds;
+      if (!id)
+      {
+        auto newID = Identifier(TOK.Identifier, idString);
+        tabulatedIds[idString] = newID;
+        id = &newID;
+      }
+      ids[i] = *id;
+    }
+  }
+  +/
+
+  static uint anonCount; /// Counter for anonymous identifiers.
+
+  /// Generates an anonymous identifier.
+  ///
+  /// Concatenates prefix with anonCount.
+  /// The identifier is not inserted into the table.
+  Identifier* genAnonymousID(string prefix)
+  {
+    ++anonCount;
+    auto x = anonCount;
+    // Convert count to a string and append it to str.
+    char[] num;
+    do
+      num = cast(char)('0' + (x % 10)) ~ num;
+    while (x /= 10)
+    return Identifier(prefix ~ num, TOK.Identifier);
+  }
+
+  /// Generates an identifier for an anonymous enum.
+  Identifier* genAnonEnumID()
+  {
+    return genAnonymousID("__anonenum");
+  }
+}
+
+unittest
+{
+  // TODO: write benchmark.
+  // Single table
+
+  // Single table. synchronized
+
+  // Two tables.
+
+  // Two tables. synchronized
+}