Mercurial > projects > dil
diff trunk/src/dil/lexer/IdTable.d @ 601:9f96fd51cb41
Moved dil.IdTable to dil.lexer.IdTable.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Sun, 06 Jan 2008 00:55:37 +0100 |
parents | trunk/src/dil/IdTable.d@041eae272362 |
children | c2e35c83c394 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/dil/lexer/IdTable.d Sun Jan 06 00:55:37 2008 +0100 @@ -0,0 +1,142 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module dil.lexer.IdTable; + +import dil.lexer.TokensEnum; +import dil.IdentsGenerator; +import dil.lexer.Keywords; +import common; + +public import dil.lexer.Identifier; +public import dil.IdentsEnum; + +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. + /// Access must be synchronized. + private Identifier*[string] growingTable; + + /// Initializes the static table. + static this() + { + // Load keywords and pre-defined identifiers into the static table. + foreach (ref k; keywords) + staticTable[k.str] = &k; + foreach (id; Ident.allIds()) + staticTable[id.str] = id; + staticTable.rehash; + } + + /// Looks in both tables. + Identifier* lookup(string idString) + { + auto id = inStatic(idString); + if (id) + return id; + return inGrowing(idString); + } + + /// Look 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; + /// Look up idString in the growing table. + LookupFunction inGrowing = &_inGrowing_unsafe; // Default to unsafe function. + + /++ + Set the thread safety mode of this table. + Call this function only if you can be sure + that this table is not being accessed + (like during lexing, parsing and semantic phase.) + +/ + void setThreadsafe(bool b) + { + if (b) + IdTable.inGrowing = &_inGrowing_safe; + else + IdTable.inGrowing = &_inGrowing_unsafe; + } + + /++ + Returns the Identifier for idString. + 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; + } + + /++ + Returns the Identifier for idString. + 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; + } + } + +/ +} + +unittest +{ + // TODO: write benchmark. + // Single table + + // Single table. synchronized + + // Two tables. + + // Two tables. synchronized +}