From 9316f35f41c7aad9a71983ba20b05703f347bfd4 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 3 Feb 2015 02:04:06 -0800 Subject: [PATCH 1/2] Experiment with making the type system enforce string interning --- containers | 2 +- libdparse | 2 +- src/actypes.d | 204 ++++++++++++++++++---------------- src/autocomplete.d | 12 +- src/conversion/astconverter.d | 5 +- src/conversion/first.d | 121 ++++++++++---------- src/conversion/second.d | 4 +- src/conversion/third.d | 14 +-- src/modulecache.d | 2 +- src/semantic.d | 8 +- src/string_interning.d | 18 ++- 11 files changed, 209 insertions(+), 183 deletions(-) diff --git a/containers b/containers index 394c27f..d99c858 160000 --- a/containers +++ b/containers @@ -1 +1 @@ -Subproject commit 394c27f110a94596c65f31e97207bf1ca3e60aaa +Subproject commit d99c858c5a6e09ec1900a7adc125fe10ca682ec8 diff --git a/libdparse b/libdparse index 36e3bcd..f73bed9 160000 --- a/libdparse +++ b/libdparse @@ -1 +1 @@ -Subproject commit 36e3bcd5d0db2fc6ba6300b168109752961330c1 +Subproject commit f73bed9279602a228933b21156d8f1f2ec5e4fdd diff --git a/src/actypes.d b/src/actypes.d index fb1f159..0849462 100644 --- a/src/actypes.d +++ b/src/actypes.d @@ -31,6 +31,7 @@ import std.d.lexer; import messages; import string_interning; +public import string_interning : istring; import std.range : isOutputRange; @@ -68,7 +69,7 @@ public: * Params: * name = the symbol's name */ - this(string name) nothrow @safe + this(istring name) nothrow @safe { this.name = name is null ? name : internString(name); } @@ -78,7 +79,7 @@ public: * name = the symbol's name * kind = the symbol's completion kind */ - this(string name, CompletionKind kind) nothrow @safe @nogc + this(istring name, CompletionKind kind) nothrow @safe @nogc { this.name = name is null ? name : internString(name); this.kind = kind; @@ -90,7 +91,7 @@ public: * kind = the symbol's completion kind * resolvedType = the resolved type of the symbol */ - this(string name, CompletionKind kind, ACSymbol* type) + this(istring name, CompletionKind kind, ACSymbol* type) { this.name = name is null ? name : internString(name); this.kind = kind; @@ -120,7 +121,7 @@ public: /** * Gets all parts whose name matches the given string. */ - ACSymbol*[] getPartsByName(string name) const + ACSymbol*[] getPartsByName(istring name) const { import std.range : chain; ACSymbol s = ACSymbol(name); @@ -151,7 +152,7 @@ public: /** * Symbol's name */ - string name; + istring name; /** * Symbols that compose this symbol, such as enum members, class variables, @@ -167,12 +168,12 @@ public: /** * Module containing the symbol. */ - string symbolFile; + istring symbolFile; /** * Documentation for the symbol. */ - string doc; + istring doc; /** * The symbol that represents the type. @@ -276,7 +277,7 @@ struct Scope * Returns: * all symbols in this scope or parent scopes with the given name */ - ACSymbol*[] getSymbolsByName(string name) const + ACSymbol*[] getSymbolsByName(istring name) const { ACSymbol s = ACSymbol(name); auto er = symbols.equalRange(&s); @@ -325,7 +326,7 @@ struct Scope * all symbols with the given name in the scope containing the cursor * and its parent scopes */ - ACSymbol*[] getSymbolsByNameAndCursor(string name, size_t cursorPosition) const + ACSymbol*[] getSymbolsByNameAndCursor(istring name, size_t cursorPosition) const { auto s = getScopeByCursor(cursorPosition); if (s is null) @@ -336,7 +337,7 @@ struct Scope /** * Returns an array of symbols that are present at global scope */ - ACSymbol*[] getSymbolsAtGlobalScope(string name) const + ACSymbol*[] getSymbolsAtGlobalScope(istring name) const { if (parent !is null) return parent.getSymbolsAtGlobalScope(name); @@ -368,11 +369,11 @@ struct Scope struct ImportInformation { /// Import statement parts - UnrolledList!string importParts; + UnrolledList!istring importParts; /// module relative path - string modulePath; + istring modulePath; /// symbols to import from this module - UnrolledList!(Tuple!(string, string), false) importedSymbols; + UnrolledList!(Tuple!(istring, istring), false) importedSymbols; /// true if the import is public bool isPublic; } @@ -403,25 +404,27 @@ TTree!(ACSymbol*, true, "a < b", false) aggregateSymbols; */ TTree!(ACSymbol*, true, "a < b", false) classSymbols; -private immutable(string[24]) builtinTypeNames; +private immutable(istring[24]) builtinTypeNames; -/** - * Name given to the public import symbol. Its value is "public" because this - * is not a valid identifier. This is initialized to an interned string during - * static construction. - */ -immutable string IMPORT_SYMBOL_NAME; - -/** - * Name given to the symbol in a "with" expression. Initialized during a static - * constructor. - */ -immutable string WITH_SYMBOL_NAME; +/// Constants for buit-in or dummy symbol names +immutable istring IMPORT_SYMBOL_NAME; +/// ditto +immutable istring WITH_SYMBOL_NAME; +/// ditto +immutable istring CONSTRUCTOR_SYMBOL_NAME; +/// ditto +immutable istring DESTRUCTOR_SYMBOL_NAME; +/// ditto +immutable istring ARGPTR_SYMBOL_NAME; +/// ditto +immutable istring ARGUMENTS_SYMBOL_NAME; +/// ditto +immutable istring THIS_SYMBOL_NAME; /** * Translates the IDs for built-in types into an interned string. */ -string getBuiltinTypeName(IdType id) nothrow pure @nogc @safe +istring getBuiltinTypeName(IdType id) nothrow pure @nogc @safe { switch (id) { @@ -486,53 +489,58 @@ static this() IMPORT_SYMBOL_NAME = internString("public"); WITH_SYMBOL_NAME = internString("with"); + CONSTRUCTOR_SYMBOL_NAME = internString("*constructor*"); + DESTRUCTOR_SYMBOL_NAME = internString("~this"); + ARGPTR_SYMBOL_NAME = internString("_argptr"); + ARGUMENTS_SYMBOL_NAME = internString("_arguments"); + THIS_SYMBOL_NAME = internString("this"); - auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword); - auto int_ = allocate!ACSymbol(Mallocator.it, "int", CompletionKind.keyword); - auto long_ = allocate!ACSymbol(Mallocator.it, "long", CompletionKind.keyword); - auto byte_ = allocate!ACSymbol(Mallocator.it, "byte", CompletionKind.keyword); - auto char_ = allocate!ACSymbol(Mallocator.it, "char", CompletionKind.keyword); - auto dchar_ = allocate!ACSymbol(Mallocator.it, "dchar", CompletionKind.keyword); - auto short_ = allocate!ACSymbol(Mallocator.it, "short", CompletionKind.keyword); - auto ubyte_ = allocate!ACSymbol(Mallocator.it, "ubyte", CompletionKind.keyword); - auto uint_ = allocate!ACSymbol(Mallocator.it, "uint", CompletionKind.keyword); - auto ulong_ = allocate!ACSymbol(Mallocator.it, "ulong", CompletionKind.keyword); - auto ushort_ = allocate!ACSymbol(Mallocator.it, "ushort", CompletionKind.keyword); - auto wchar_ = allocate!ACSymbol(Mallocator.it, "wchar", CompletionKind.keyword); + auto bool_ = allocate!ACSymbol(Mallocator.it, internString("bool"), CompletionKind.keyword); + auto int_ = allocate!ACSymbol(Mallocator.it, internString("int"), CompletionKind.keyword); + auto long_ = allocate!ACSymbol(Mallocator.it, internString("long"), CompletionKind.keyword); + auto byte_ = allocate!ACSymbol(Mallocator.it, internString("byte"), CompletionKind.keyword); + auto char_ = allocate!ACSymbol(Mallocator.it, internString("char"), CompletionKind.keyword); + auto dchar_ = allocate!ACSymbol(Mallocator.it, internString("dchar"), CompletionKind.keyword); + auto short_ = allocate!ACSymbol(Mallocator.it, internString("short"), CompletionKind.keyword); + auto ubyte_ = allocate!ACSymbol(Mallocator.it, internString("ubyte"), CompletionKind.keyword); + auto uint_ = allocate!ACSymbol(Mallocator.it, internString("uint"), CompletionKind.keyword); + auto ulong_ = allocate!ACSymbol(Mallocator.it, internString("ulong"), CompletionKind.keyword); + auto ushort_ = allocate!ACSymbol(Mallocator.it, internString("ushort"), CompletionKind.keyword); + auto wchar_ = allocate!ACSymbol(Mallocator.it, internString("wchar"), CompletionKind.keyword); - auto alignof_ = allocate!ACSymbol(Mallocator.it, "alignof", CompletionKind.keyword); - auto mangleof_ = allocate!ACSymbol(Mallocator.it, "mangleof", CompletionKind.keyword); - auto sizeof_ = allocate!ACSymbol(Mallocator.it, "sizeof", CompletionKind.keyword); - auto stringof_ = allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword); - auto init = allocate!ACSymbol(Mallocator.it, "stringof", CompletionKind.keyword); + auto alignof_ = allocate!ACSymbol(Mallocator.it, internString("alignof"), CompletionKind.keyword); + auto mangleof_ = allocate!ACSymbol(Mallocator.it, internString("mangleof"), CompletionKind.keyword); + auto sizeof_ = allocate!ACSymbol(Mallocator.it, internString("sizeof"), CompletionKind.keyword); + auto stringof_ = allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword); + auto init = allocate!ACSymbol(Mallocator.it, internString("stringof"), CompletionKind.keyword); arraySymbols.insert(alignof_); - arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "dup", CompletionKind.keyword)); - arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "idup", CompletionKind.keyword)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("dup"), CompletionKind.keyword)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("idup"), CompletionKind.keyword)); arraySymbols.insert(init); - arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "length", CompletionKind.keyword, ulong_)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("length"), CompletionKind.keyword, ulong_)); arraySymbols.insert(mangleof_); - arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "ptr", CompletionKind.keyword)); - arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "reverse", CompletionKind.keyword)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("ptr"), CompletionKind.keyword)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("reverse"), CompletionKind.keyword)); arraySymbols.insert(sizeof_); - arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "sort", CompletionKind.keyword)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("sort"), CompletionKind.keyword)); arraySymbols.insert(stringof_); assocArraySymbols.insert(alignof_); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "byKey", CompletionKind.keyword)); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "byValue", CompletionKind.keyword)); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "dup", CompletionKind.keyword)); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "get", CompletionKind.keyword)); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword)); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "keys", CompletionKind.keyword)); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "length", CompletionKind.keyword, ulong_)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("byKey"), CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("byValue"), CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("dup"), CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("get"), CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("keys"), CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("length"), CompletionKind.keyword, ulong_)); assocArraySymbols.insert(mangleof_); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "rehash", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("rehash"), CompletionKind.keyword)); assocArraySymbols.insert(sizeof_); assocArraySymbols.insert(stringof_); assocArraySymbols.insert(init); - assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "values", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("values"), CompletionKind.keyword)); ACSymbol*[11] integralTypeArray; integralTypeArray[0] = bool_; @@ -550,9 +558,9 @@ static this() foreach (s; integralTypeArray) { - s.parts.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "min", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "max", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("max"), CompletionKind.keyword, s)); s.parts.insert(alignof_); s.parts.insert(sizeof_); s.parts.insert(stringof_); @@ -560,17 +568,17 @@ static this() s.parts.insert(init); } - auto cdouble_ = allocate!ACSymbol(Mallocator.it, "cdouble", CompletionKind.keyword); - auto cent_ = allocate!ACSymbol(Mallocator.it, "cent", CompletionKind.keyword); - auto cfloat_ = allocate!ACSymbol(Mallocator.it, "cfloat", CompletionKind.keyword); - auto creal_ = allocate!ACSymbol(Mallocator.it, "creal", CompletionKind.keyword); - auto double_ = allocate!ACSymbol(Mallocator.it, "double", CompletionKind.keyword); - auto float_ = allocate!ACSymbol(Mallocator.it, "float", CompletionKind.keyword); - auto idouble_ = allocate!ACSymbol(Mallocator.it, "idouble", CompletionKind.keyword); - auto ifloat_ = allocate!ACSymbol(Mallocator.it, "ifloat", CompletionKind.keyword); - auto ireal_ = allocate!ACSymbol(Mallocator.it, "ireal", CompletionKind.keyword); - auto real_ = allocate!ACSymbol(Mallocator.it, "real", CompletionKind.keyword); - auto ucent_ = allocate!ACSymbol(Mallocator.it, "ucent", CompletionKind.keyword); + auto cdouble_ = allocate!ACSymbol(Mallocator.it, internString("cdouble"), CompletionKind.keyword); + auto cent_ = allocate!ACSymbol(Mallocator.it, internString("cent"), CompletionKind.keyword); + auto cfloat_ = allocate!ACSymbol(Mallocator.it, internString("cfloat"), CompletionKind.keyword); + auto creal_ = allocate!ACSymbol(Mallocator.it, internString("creal"), CompletionKind.keyword); + auto double_ = allocate!ACSymbol(Mallocator.it, internString("double"), CompletionKind.keyword); + auto float_ = allocate!ACSymbol(Mallocator.it, internString("float"), CompletionKind.keyword); + auto idouble_ = allocate!ACSymbol(Mallocator.it, internString("idouble"), CompletionKind.keyword); + auto ifloat_ = allocate!ACSymbol(Mallocator.it, internString("ifloat"), CompletionKind.keyword); + auto ireal_ = allocate!ACSymbol(Mallocator.it, internString("ireal"), CompletionKind.keyword); + auto real_ = allocate!ACSymbol(Mallocator.it, internString("real"), CompletionKind.keyword); + auto ucent_ = allocate!ACSymbol(Mallocator.it, internString("ucent"), CompletionKind.keyword); ACSymbol*[11] floatTypeArray; floatTypeArray[0] = cdouble_; @@ -588,49 +596,49 @@ static this() foreach (s; floatTypeArray) { s.parts.insert(alignof_); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "dig", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "epsilon", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "infinity", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("dig"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("epsilon"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("infinity"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword, s)); s.parts.insert(mangleof_); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "mant_dig", CompletionKind.keyword, int_)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "max", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "max_10_exp", CompletionKind.keyword, int_)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "max_exp", CompletionKind.keyword, int_)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "min", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_exp", CompletionKind.keyword, int_)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_10_exp", CompletionKind.keyword, int_)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_normal", CompletionKind.keyword, s)); - s.parts.insert(allocate!ACSymbol(Mallocator.it, "nan", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("mant_dig"), CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("max"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("max_10_exp"), CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("max_exp"), CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min_exp"), CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min_10_exp"), CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min_normal"), CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("nan"), CompletionKind.keyword, s)); s.parts.insert(sizeof_); s.parts.insert(stringof_); } - aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.keyword)); + aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("tupleof"), CompletionKind.keyword)); aggregateSymbols.insert(mangleof_); aggregateSymbols.insert(alignof_); aggregateSymbols.insert(sizeof_); aggregateSymbols.insert(stringof_); aggregateSymbols.insert(init); - classSymbols.insert(allocate!ACSymbol(Mallocator.it, "classInfo", CompletionKind.variableName)); - classSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.variableName)); - classSymbols.insert(allocate!ACSymbol(Mallocator.it, "__vptr", CompletionKind.variableName)); - classSymbols.insert(allocate!ACSymbol(Mallocator.it, "__monitor", CompletionKind.variableName)); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("classInfo"), CompletionKind.variableName)); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("tupleof"), CompletionKind.variableName)); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("__vptr"), CompletionKind.variableName)); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("__monitor"), CompletionKind.variableName)); classSymbols.insert(mangleof_); classSymbols.insert(alignof_); classSymbols.insert(sizeof_); classSymbols.insert(stringof_); classSymbols.insert(init); - ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, real_)); - ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, float_)); - idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, double_)); - ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, real_)); - ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, float_)); - idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, double_)); + ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, real_)); + ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, float_)); + idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, double_)); + ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, real_)); + ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, float_)); + idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, double_)); - auto void_ = allocate!ACSymbol(Mallocator.it, "void", CompletionKind.keyword); + auto void_ = allocate!ACSymbol(Mallocator.it, internString("void"), CompletionKind.keyword); builtinSymbols.insert(bool_); bool_.type = bool_; diff --git a/src/autocomplete.d b/src/autocomplete.d index c148c43..f975ff3 100644 --- a/src/autocomplete.d +++ b/src/autocomplete.d @@ -680,7 +680,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, case tok!"ireal": case tok!"creal": case tok!"this": - symbols = symbols[0].getPartsByName(str(tokens[i].type)); + symbols = symbols[0].getPartsByName(istring(str(tokens[i].type))); if (symbols.length == 0) break loop; break; @@ -695,7 +695,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, } // Log.trace("looking for ", tokens[i].text, " in ", symbols[0].name); - symbols = symbols[0].getPartsByName(tokens[i].text); + symbols = symbols[0].getPartsByName(istring(tokens[i].text)); if (symbols.length == 0) { // Log.trace("Couldn't find it."); @@ -751,9 +751,9 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, p.setTokens(tokens[h .. i].array()); ACSymbol*[] overloads; if (p.isSliceExpression()) - overloads = symbols[0].getPartsByName("opSlice"); + overloads = symbols[0].getPartsByName(istring("opSlice")); else - overloads = symbols[0].getPartsByName("opIndex"); + overloads = symbols[0].getPartsByName(istring("opIndex")); if (overloads.length > 0) { symbols = overloads[0].type is null ? [] : [overloads[0].type]; @@ -1120,9 +1120,9 @@ string formatComment(string comment) .replaceAll(regex("\n"), `\n`).outdent(); } -string stringToken()(auto ref const Token a) +istring stringToken()(auto ref const Token a) { - return a.text is null ? str(a.type) : a.text; + return a.text is null ? istring(str(a.type)) : istring(a.text); } //unittest diff --git a/src/conversion/astconverter.d b/src/conversion/astconverter.d index b74249d..4efe0b2 100644 --- a/src/conversion/astconverter.d +++ b/src/conversion/astconverter.d @@ -28,14 +28,15 @@ import std.d.ast; import std.d.lexer; import std.d.parser; import std.typecons; +import string_interning; /** * Used by autocompletion. */ Scope* generateAutocompleteTrees(const(Token)[] tokens, CAllocator symbolAllocator) { - Module m = parseModule(tokens, "stdin", symbolAllocator, &doesNothing); - auto first = scoped!FirstPass(m, "stdin", symbolAllocator, symbolAllocator); + Module m = parseModule(tokens, internString("stdin"), symbolAllocator, &doesNothing); + auto first = scoped!FirstPass(m, internString("stdin"), symbolAllocator, symbolAllocator); first.run(); SecondPass second = SecondPass(first); diff --git a/src/conversion/first.d b/src/conversion/first.d index 650eea9..09a85ee 100644 --- a/src/conversion/first.d +++ b/src/conversion/first.d @@ -54,7 +54,7 @@ final class FirstPass : ASTVisitor * symbolAllocator = allocator used for the auto-complete symbols * semanticAllocator = allocator used for semantic symbols */ - this(Module mod, string symbolFile, CAllocator symbolAllocator, + this(Module mod, istring symbolFile, CAllocator symbolAllocator, CAllocator semanticAllocator) in { @@ -83,7 +83,7 @@ final class FirstPass : ASTVisitor // Create a dummy symbol because we don't want unit test symbols leaking // into the symbol they're declared in. SemanticSymbol* s = allocateSemanticSymbol(internString("*unittest*"), - CompletionKind.dummy, null, 0); + CompletionKind.dummy, istring(null), 0); s.parent = currentSymbol; currentSymbol.addChild(s); currentSymbol = s; @@ -130,7 +130,7 @@ final class FirstPass : ASTVisitor override void visit(const FunctionDeclaration dec) { // Log.trace(__FUNCTION__, " ", typeof(dec).stringof, " ", dec.name.text); - SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, + SemanticSymbol* symbol = allocateSemanticSymbol(istring(dec.name.text), CompletionKind.functionName, symbolFile, dec.name.index, dec.returnType); processParameters(symbol, dec.returnType, symbol.acSymbol.name, @@ -201,7 +201,7 @@ final class FirstPass : ASTVisitor foreach (declarator; dec.declarators) { SemanticSymbol* symbol = allocateSemanticSymbol( - declarator.name.text, CompletionKind.variableName, + istring(declarator.name.text), CompletionKind.variableName, symbolFile, declarator.name.index, t); symbol.protection = protection; symbol.parent = currentSymbol; @@ -213,8 +213,8 @@ final class FirstPass : ASTVisitor foreach (i, identifier; dec.autoDeclaration.identifiers) { SemanticSymbol* symbol = allocateSemanticSymbol( - identifier.text, CompletionKind.variableName, symbolFile, - identifier.index, null); + istring(identifier.text), CompletionKind.variableName, + symbolFile, identifier.index, null); populateInitializer(symbol, dec.autoDeclaration.initializers[i]); symbol.protection = protection; symbol.parent = currentSymbol; @@ -231,7 +231,7 @@ final class FirstPass : ASTVisitor foreach (name; aliasDeclaration.identifierList.identifiers) { SemanticSymbol* symbol = allocateSemanticSymbol( - name.text, + istring(name.text), CompletionKind.aliasName, symbolFile, name.index, @@ -247,7 +247,7 @@ final class FirstPass : ASTVisitor foreach (initializer; aliasDeclaration.initializers) { SemanticSymbol* symbol = allocateSemanticSymbol( - initializer.name.text, + istring(initializer.name.text), CompletionKind.aliasName, symbolFile, initializer.name.index, @@ -289,7 +289,7 @@ final class FirstPass : ASTVisitor { // Log.trace(__FUNCTION__, " ", typeof(mod).stringof); // - currentSymbol = allocateSemanticSymbol(null, CompletionKind.moduleName, + currentSymbol = allocateSemanticSymbol(istring(null), CompletionKind.moduleName, symbolFile); rootSymbol = currentSymbol; currentScope = allocate!Scope(semanticAllocator, 0, size_t.max); @@ -305,7 +305,7 @@ final class FirstPass : ASTVisitor { assert (currentSymbol); // Log.trace(__FUNCTION__, " ", typeof(dec).stringof); - SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, + SemanticSymbol* symbol = allocateSemanticSymbol(istring(dec.name.text), CompletionKind.enumName, symbolFile, dec.name.index, dec.type); symbol.parent = currentSymbol; symbol.acSymbol.doc = internString(dec.comment); @@ -331,7 +331,7 @@ final class FirstPass : ASTVisitor Scope* s = allocate!Scope(semanticAllocator, structBody.startLocation, structBody.endLocation); // Log.trace("Added scope ", s.startLocation, " ", s.endLocation); - ACSymbol* thisSymbol = allocate!ACSymbol(symbolAllocator, "this", + ACSymbol* thisSymbol = allocate!ACSymbol(symbolAllocator, internString("this"), CompletionKind.variableName, currentSymbol.acSymbol); thisSymbol.location = s.startLocation; thisSymbol.symbolFile = symbolFile; @@ -373,7 +373,7 @@ final class FirstPass : ASTVisitor } foreach (bind; importDeclaration.importBindings.importBinds) { - Tuple!(string, string) bindTuple; + Tuple!(istring, istring) bindTuple; if (bind.right == tok!"") { bindTuple[1] = internString(bind.left.text); @@ -456,7 +456,7 @@ final class FirstPass : ASTVisitor { // Log.trace("Handling foreachtype ", feType.identifier.text); SemanticSymbol* symbol = allocateSemanticSymbol( - feType.identifier.text, CompletionKind.variableName, + istring(feType.identifier.text), CompletionKind.variableName, symbolFile, feType.identifier.index, feType.type); if (symbol.type is null && feExpression !is null) { @@ -514,8 +514,9 @@ private: override void visit(const T member) { // Log.trace(__FUNCTION__, " ", typeof(member).stringof); - SemanticSymbol* symbol = allocateSemanticSymbol(member.name.text, - CompletionKind.enumMember, symbolFile, member.name.index, member.type); + SemanticSymbol* symbol = allocateSemanticSymbol( + istring(member.name.text), CompletionKind.enumMember, symbolFile, + member.name.index, member.type); symbol.parent = currentSymbol; symbol.acSymbol.doc = internString(member.comment); currentSymbol.addChild(symbol); @@ -530,7 +531,7 @@ private: dec.accept(this); return; } - SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, + SemanticSymbol* symbol = allocateSemanticSymbol(istring(dec.name.text), kind, symbolFile, dec.name.index); if (kind == CompletionKind.className) symbol.acSymbol.parts.insert(classSymbols[]); @@ -561,9 +562,9 @@ private: const TemplateParameters templateParameters, const FunctionBody functionBody, string doc) { - SemanticSymbol* symbol = allocateSemanticSymbol("*constructor*", + SemanticSymbol* symbol = allocateSemanticSymbol(CONSTRUCTOR_SYMBOL_NAME, CompletionKind.functionName, symbolFile, location); - processParameters(symbol, null, "this", parameters, templateParameters); + processParameters(symbol, null, THIS_SYMBOL_NAME, parameters, templateParameters); symbol.protection = protection; symbol.parent = currentSymbol; symbol.acSymbol.doc = internString(doc); @@ -584,7 +585,7 @@ private: void visitDestructor(size_t location, const FunctionBody functionBody, string doc) { - SemanticSymbol* symbol = allocateSemanticSymbol("~this", + SemanticSymbol* symbol = allocateSemanticSymbol(DESTRUCTOR_SYMBOL_NAME, CompletionKind.functionName, symbolFile, location); symbol.acSymbol.callTip = "~this()"; symbol.protection = protection; @@ -606,7 +607,7 @@ private: } void processParameters(SemanticSymbol* symbol, const Type returnType, - string functionName, const Parameters parameters, + istring functionName, const Parameters parameters, const TemplateParameters templateParameters) { processTemplateParameters(symbol, templateParameters); @@ -615,20 +616,22 @@ private: foreach (const Parameter p; parameters.parameters) { SemanticSymbol* parameter = allocateSemanticSymbol( - p.name.text, CompletionKind.variableName, symbolFile, + istring(p.name.text), CompletionKind.variableName, symbolFile, p.name.index, p.type); symbol.addChild(parameter); parameter.parent = symbol; } if (parameters.hasVarargs) { - SemanticSymbol* argptr = allocateSemanticSymbol("_argptr", - CompletionKind.variableName, null, size_t.max, argptrType); + SemanticSymbol* argptr = allocateSemanticSymbol(ARGPTR_SYMBOL_NAME, + CompletionKind.variableName, istring(null), size_t.max, + argptrType); argptr.parent = symbol; symbol.addChild(argptr); - SemanticSymbol* arguments = allocateSemanticSymbol("_arguments", - CompletionKind.variableName, null, size_t.max, argumentsType); + SemanticSymbol* arguments = allocateSemanticSymbol( + ARGUMENTS_SYMBOL_NAME, CompletionKind.variableName, + istring(null), size_t.max, argumentsType); arguments.parent = symbol; symbol.addChild(arguments); } @@ -643,40 +646,40 @@ private: { foreach (const TemplateParameter p; templateParameters.templateParameterList.items) { - string name; + istring name; CompletionKind kind; size_t index; Rebindable!(const(Type)) type; if (p.templateAliasParameter !is null) { - name = p.templateAliasParameter.identifier.text; + name = istring(p.templateAliasParameter.identifier.text); kind = CompletionKind.aliasName; index = p.templateAliasParameter.identifier.index; } else if (p.templateTypeParameter !is null) { - name = p.templateTypeParameter.identifier.text; + name = istring(p.templateTypeParameter.identifier.text); kind = CompletionKind.aliasName; index = p.templateTypeParameter.identifier.index; } else if (p.templateValueParameter !is null) { - name = p.templateValueParameter.identifier.text; + name = istring(p.templateValueParameter.identifier.text); kind = CompletionKind.variableName; index = p.templateValueParameter.identifier.index; type = p.templateValueParameter.type; } else continue; - SemanticSymbol* templateParameter = allocateSemanticSymbol(name, kind, - symbolFile, index, type); + SemanticSymbol* templateParameter = allocateSemanticSymbol(name, + kind, symbolFile, index, type); symbol.addChild(templateParameter); templateParameter.parent = symbol; } } } - string formatCallTip(const Type returnType, string name, + string formatCallTip(const Type returnType, istring name, const Parameters parameters, const TemplateParameters templateParameters) { QuickAllocator!1024 q; @@ -704,8 +707,8 @@ private: visitor.visit(initializer); } - SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind, - string symbolFile, size_t location = 0, const Type type = null) + SemanticSymbol* allocateSemanticSymbol(istring name, CompletionKind kind, + istring symbolFile, size_t location = 0, const Type type = null) in { assert (symbolAllocator !is null); @@ -729,7 +732,7 @@ private: SemanticSymbol* currentSymbol; /// Path to the file being converted - string symbolFile; + istring symbolFile; Module mod; @@ -760,21 +763,21 @@ Scope* createFunctionScope(const FunctionBody functionBody, CAllocator semanticA return allocate!Scope(semanticAllocator, scopeBegin, scopeEnd); } -string[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc) +istring[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc) { - string[] retVal = cast(string[]) allocator.allocate((string[]).sizeof + istring[] retVal = cast(istring[]) allocator.allocate((istring[]).sizeof * iotc.identifiersOrTemplateInstances.length); foreach (i, ioti; iotc.identifiersOrTemplateInstances) { if (ioti.identifier != tok!"") - retVal[i] = internString(ioti.identifier.text); + retVal[i] = istring(ioti.identifier.text); else - retVal[i] = internString(ioti.templateInstance.identifier.text); + retVal[i] = istring(ioti.templateInstance.identifier.text); } return retVal; } -static string convertChainToImportPath(const IdentifierChain ic) +static istring convertChainToImportPath(const IdentifierChain ic) { import std.path : dirSeparator; QuickAllocator!1024 q; @@ -802,7 +805,7 @@ class InitializerVisitor : ASTVisitor override void visit(const IdentifierOrTemplateInstance ioti) { if (on && ioti.identifier != tok!"") - semanticSymbol.initializer.insert(ioti.identifier.text); + semanticSymbol.initializer.insert(istring(ioti.identifier.text)); ioti.accept(this); } @@ -812,53 +815,53 @@ class InitializerVisitor : ASTVisitor // the prefix '*' so that that the third pass can tell the difference // between "int.abc" and "10.abc". if (on && primary.basicType != tok!"") - semanticSymbol.initializer.insert(str(primary.basicType.type)); + semanticSymbol.initializer.insert(internString(str(primary.basicType.type))); if (on) switch (primary.primary.type) { case tok!"identifier": - semanticSymbol.initializer.insert(primary.primary.text); + semanticSymbol.initializer.insert(istring(primary.primary.text)); break; case tok!"doubleLiteral": - semanticSymbol.initializer.insert("*double"); + semanticSymbol.initializer.insert(istring("*double")); break; case tok!"floatLiteral": - semanticSymbol.initializer.insert("*float"); + semanticSymbol.initializer.insert(istring("*float")); break; case tok!"idoubleLiteral": - semanticSymbol.initializer.insert("*idouble"); + semanticSymbol.initializer.insert(istring("*idouble")); break; case tok!"ifloatLiteral": - semanticSymbol.initializer.insert("*ifloat"); + semanticSymbol.initializer.insert(istring("*ifloat")); break; case tok!"intLiteral": - semanticSymbol.initializer.insert("*int"); + semanticSymbol.initializer.insert(istring("*int")); break; case tok!"longLiteral": - semanticSymbol.initializer.insert("*long"); + semanticSymbol.initializer.insert(istring("*long")); break; case tok!"realLiteral": - semanticSymbol.initializer.insert("*real"); + semanticSymbol.initializer.insert(istring("*real")); break; case tok!"irealLiteral": - semanticSymbol.initializer.insert("*ireal"); + semanticSymbol.initializer.insert(istring("*ireal")); break; case tok!"uintLiteral": - semanticSymbol.initializer.insert("*uint"); + semanticSymbol.initializer.insert(istring("*uint")); break; case tok!"ulongLiteral": - semanticSymbol.initializer.insert("*ulong"); + semanticSymbol.initializer.insert(istring("*ulong")); break; case tok!"characterLiteral": - semanticSymbol.initializer.insert("*char"); + semanticSymbol.initializer.insert(istring("*char")); break; case tok!"dstringLiteral": - semanticSymbol.initializer.insert("*dstring"); + semanticSymbol.initializer.insert(istring("*dstring")); break; case tok!"stringLiteral": - semanticSymbol.initializer.insert("*string"); + semanticSymbol.initializer.insert(istring("*string")); break; case tok!"wstringLiteral": - semanticSymbol.initializer.insert("*wstring"); + semanticSymbol.initializer.insert(istring("*wstring")); break; default: break; @@ -870,7 +873,7 @@ class InitializerVisitor : ASTVisitor { unary.accept(this); if (unary.indexExpression) - semanticSymbol.initializer.insert("[]"); + semanticSymbol.initializer.insert(istring("[]")); } override void visit(const ArgumentList) {} @@ -880,7 +883,7 @@ class InitializerVisitor : ASTVisitor on = true; initializer.accept(this); if (appendForeach) - semanticSymbol.initializer.insert("foreach"); + semanticSymbol.initializer.insert(istring("foreach")); on = false; } diff --git a/src/conversion/second.d b/src/conversion/second.d index 4ec3fb8..b6f6fe7 100644 --- a/src/conversion/second.d +++ b/src/conversion/second.d @@ -113,7 +113,7 @@ private: body { // top-level package name - immutable string firstPart = info.importParts[].front; + immutable istring firstPart = info.importParts[].front; // top-level package symbol ACSymbol* firstSymbol = void; @@ -125,7 +125,7 @@ private: CompletionKind.packageName); ACSymbol* currentSymbol = firstSymbol; size_t i = 0; - foreach (string importPart; info.importParts[]) + foreach (importPart; info.importParts[]) { i++; if (i == 1) // Skip the top-level package diff --git a/src/conversion/third.d b/src/conversion/third.d index aeccbc2..3e22f75 100644 --- a/src/conversion/third.d +++ b/src/conversion/third.d @@ -152,7 +152,7 @@ private: void resolveInheritance(SemanticSymbol* currentSymbol) { - outer: foreach (string[] base; currentSymbol.baseClasses) + outer: foreach (istring[] base; currentSymbol.baseClasses) { ACSymbol* baseClass; if (base.length == 0) @@ -283,7 +283,7 @@ private: { // TODO: global scoped symbol handling size_t l = t.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances.length; - string[] symbolParts = (cast(string*) Mallocator.it.allocate(l * string.sizeof))[0 .. l]; + istring[] symbolParts = (cast(istring*) Mallocator.it.allocate(l * istring.sizeof))[0 .. l]; scope(exit) Mallocator.it.deallocate(symbolParts); expandSymbol(symbolParts, t.type2.symbol.identifierOrTemplateChain); auto symbols = moduleScope.getSymbolsByNameAndCursor( @@ -305,14 +305,14 @@ private: return s; } - static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain) + static void expandSymbol(istring[] strings, const IdentifierOrTemplateChain chain) { for (size_t i = 0; i < chain.identifiersOrTemplateInstances.length; ++i) { auto identOrTemplate = chain.identifiersOrTemplateInstances[i]; if (identOrTemplate is null) { - strings[i] = null; + strings[i] = istring(null); continue; } strings[i] = internString(identOrTemplate.templateInstance is null ? @@ -327,7 +327,7 @@ private: return symbol; if (suffix.array || suffix.type) { - ACSymbol* s = allocate!ACSymbol(symbolAllocator, null); + ACSymbol* s = allocate!ACSymbol(symbolAllocator, istring(null)); s.parts.insert(suffix.array ? arraySymbols[] : assocArraySymbols[]); s.type = symbol; @@ -339,7 +339,7 @@ private: import conversion.first : formatNode; import memory.allocators : QuickAllocator; import memory.appender : Appender; - ACSymbol* s = allocate!ACSymbol(symbolAllocator, null); + ACSymbol* s = allocate!ACSymbol(symbolAllocator, istring(null)); s.type = symbol; s.qualifier = SymbolQualifier.func; QuickAllocator!1024 q; @@ -354,7 +354,7 @@ private: ACSymbol* convertBuiltinType(const Type2 type2) { - string stringRepresentation = getBuiltinTypeName(type2.builtinType); + istring stringRepresentation = getBuiltinTypeName(type2.builtinType); ACSymbol s = ACSymbol(stringRepresentation); assert(s.name.ptr == stringRepresentation.ptr); return builtinSymbols.equalRange(&s).front(); diff --git a/src/modulecache.d b/src/modulecache.d index e3bb4f2..49a675f 100644 --- a/src/modulecache.d +++ b/src/modulecache.d @@ -141,7 +141,7 @@ struct ModuleCache assert (location !is null); - string cachedLocation = internString(location); + istring cachedLocation = internString(location); if (!needsReparsing(cachedLocation)) { diff --git a/src/semantic.d b/src/semantic.d index 758e0e1..80b94e2 100644 --- a/src/semantic.d +++ b/src/semantic.d @@ -70,16 +70,16 @@ public: ACSymbol* acSymbol; /// Base classes - UnrolledList!(string[]) baseClasses; + UnrolledList!(istring[]) baseClasses; /// Variable type or function return type const Type type; /// Alias this symbols - UnrolledList!(string) aliasThis; + UnrolledList!(istring) aliasThis; /// MixinTemplates - UnrolledList!(string[]) mixinTemplates; + UnrolledList!(istring[]) mixinTemplates; /// Protection level for this symobol IdType protection; @@ -91,7 +91,7 @@ public: UnrolledList!(SemanticSymbol*) children; /// Assign expression identifier chain used for auto declarations - UnrolledList!(string) initializer; + UnrolledList!(istring) initializer; } /** diff --git a/src/string_interning.d b/src/string_interning.d index ecc691c..a39c620 100644 --- a/src/string_interning.d +++ b/src/string_interning.d @@ -23,9 +23,9 @@ import std.d.lexer; /** * Interns the given string and returns the interned version. */ -string internString(string s) nothrow @safe @nogc +istring internString(string s) nothrow @safe @nogc { - return stringCache.intern(s); + return istring(stringCache.intern(s)); } static this() @@ -33,5 +33,19 @@ static this() stringCache = StringCache(StringCache.defaultBucketCount); } +alias istring = InternedString; + //private size_t[string] dupCheck; private StringCache stringCache = void; + +private struct InternedString +{ + void opAssign(T)(T other) if (is(Unqual!T == istring)) + { + this.data = other.data; + } + string data; + alias data this; +private: + import std.traits : Unqual; +} From e216a493d8b62d4acb8d2f8202726f29f9e21794 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 3 Feb 2015 03:54:21 -0800 Subject: [PATCH 2/2] Bugfixes --- src/actypes.d | 59 +++++++++++++++++++++++++-- src/autocomplete.d | 23 +++-------- src/conversion/first.d | 90 ++++++++++++++++++++---------------------- src/semantic.d | 3 +- 4 files changed, 105 insertions(+), 70 deletions(-) diff --git a/src/actypes.d b/src/actypes.d index 0849462..01ee93e 100644 --- a/src/actypes.d +++ b/src/actypes.d @@ -69,9 +69,15 @@ public: * Params: * name = the symbol's name */ + this(string name) nothrow @safe + { + this.name = name is null ? istring(null) : internString(name); + } + + /// ditto this(istring name) nothrow @safe { - this.name = name is null ? name : internString(name); + this.name = name; } /** @@ -79,9 +85,16 @@ public: * name = the symbol's name * kind = the symbol's completion kind */ + this(string name, CompletionKind kind) nothrow @safe @nogc + { + this.name = name is null ? istring(name) : internString(name); + this.kind = kind; + } + + /// ditto this(istring name, CompletionKind kind) nothrow @safe @nogc { - this.name = name is null ? name : internString(name); + this.name = name; this.kind = kind; } @@ -91,9 +104,17 @@ public: * kind = the symbol's completion kind * resolvedType = the resolved type of the symbol */ + this(string name, CompletionKind kind, ACSymbol* type) + { + this.name = name is null ? istring(name) : internString(name); + this.kind = kind; + this.type = type; + } + + /// ditto this(istring name, CompletionKind kind, ACSymbol* type) { - this.name = name is null ? name : internString(name); + this.name = name; this.kind = kind; this.type = type; } @@ -420,6 +441,22 @@ immutable istring ARGPTR_SYMBOL_NAME; immutable istring ARGUMENTS_SYMBOL_NAME; /// ditto immutable istring THIS_SYMBOL_NAME; +/// ditto +immutable istring UNITTEST_SYMBOL_NAME; +immutable istring DOUBLE_LITERAL_SYMBOL_NAME; +immutable istring FLOAT_LITERAL_SYMBOL_NAME; +immutable istring IDOUBLE_LITERAL_SYMBOL_NAME; +immutable istring IFLOAT_LITERAL_SYMBOL_NAME; +immutable istring INT_LITERAL_SYMBOL_NAME; +immutable istring LONG_LITERAL_SYMBOL_NAME; +immutable istring REAL_LITERAL_SYMBOL_NAME; +immutable istring IREAL_LITERAL_SYMBOL_NAME; +immutable istring UINT_LITERAL_SYMBOL_NAME; +immutable istring ULONG_LITERAL_SYMBOL_NAME; +immutable istring CHAR_LITERAL_SYMBOL_NAME; +immutable istring DSTRING_LITERAL_SYMBOL_NAME; +immutable istring STRING_LITERAL_SYMBOL_NAME; +immutable istring WSTRING_LITERAL_SYMBOL_NAME; /** * Translates the IDs for built-in types into an interned string. @@ -494,7 +531,21 @@ static this() ARGPTR_SYMBOL_NAME = internString("_argptr"); ARGUMENTS_SYMBOL_NAME = internString("_arguments"); THIS_SYMBOL_NAME = internString("this"); - + UNITTEST_SYMBOL_NAME = internString("*unittest*"); + DOUBLE_LITERAL_SYMBOL_NAME = internString("*double"); + FLOAT_LITERAL_SYMBOL_NAME = internString("*float"); + IDOUBLE_LITERAL_SYMBOL_NAME = internString("*idouble"); + IFLOAT_LITERAL_SYMBOL_NAME = internString("*ifloat"); + INT_LITERAL_SYMBOL_NAME = internString("*int"); + LONG_LITERAL_SYMBOL_NAME = internString("*long"); + REAL_LITERAL_SYMBOL_NAME = internString("*real"); + IREAL_LITERAL_SYMBOL_NAME = internString("*ireal"); + UINT_LITERAL_SYMBOL_NAME = internString("*uint"); + ULONG_LITERAL_SYMBOL_NAME = internString("*ulong"); + CHAR_LITERAL_SYMBOL_NAME = internString("*char"); + DSTRING_LITERAL_SYMBOL_NAME = internString("*dstring"); + STRING_LITERAL_SYMBOL_NAME = internString("*string"); + WSTRING_LITERAL_SYMBOL_NAME = internString("*wstring"); auto bool_ = allocate!ACSymbol(Mallocator.it, internString("bool"), CompletionKind.keyword); auto int_ = allocate!ACSymbol(Mallocator.it, internString("int"), CompletionKind.keyword); diff --git a/src/autocomplete.d b/src/autocomplete.d index f975ff3..8b98316 100644 --- a/src/autocomplete.d +++ b/src/autocomplete.d @@ -680,7 +680,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, case tok!"ireal": case tok!"creal": case tok!"this": - symbols = symbols[0].getPartsByName(istring(str(tokens[i].type))); + symbols = symbols[0].getPartsByName(internString(str(tokens[i].type))); if (symbols.length == 0) break loop; break; @@ -695,7 +695,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, } // Log.trace("looking for ", tokens[i].text, " in ", symbols[0].name); - symbols = symbols[0].getPartsByName(istring(tokens[i].text)); + symbols = symbols[0].getPartsByName(internString(tokens[i].text)); if (symbols.length == 0) { // Log.trace("Couldn't find it."); @@ -751,9 +751,9 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, p.setTokens(tokens[h .. i].array()); ACSymbol*[] overloads; if (p.isSliceExpression()) - overloads = symbols[0].getPartsByName(istring("opSlice")); + overloads = symbols[0].getPartsByName(internString("opSlice")); else - overloads = symbols[0].getPartsByName(istring("opIndex")); + overloads = symbols[0].getPartsByName(internString("opIndex")); if (overloads.length > 0) { symbols = overloads[0].type is null ? [] : [overloads[0].type]; @@ -866,7 +866,7 @@ void setCompletions(T)(ref AutocompleteResponse response, if (symbols[0].kind == CompletionKind.structName || symbols[0].kind == CompletionKind.className) { - auto constructor = symbols[0].getPartsByName(internString("*constructor*")); + auto constructor = symbols[0].getPartsByName(CONSTRUCTOR_SYMBOL_NAME); if (constructor.length == 0) { // Build a call tip out of the struct fields @@ -1122,16 +1122,5 @@ string formatComment(string comment) istring stringToken()(auto ref const Token a) { - return a.text is null ? istring(str(a.type)) : istring(a.text); + return internString(a.text is null ? str(a.type) : a.text); } - -//unittest -//{ -// auto comment1 = "/**\n * This is some text\n */"; -// auto result1 = formatComment(comment1); -// assert (result1 == `This is some text\n\n`, result1); -// -// auto comment2 = "///some\n///text"; -// auto result2 = formatComment(comment2); -// assert (result2 == `some\ntext\n\n`, result2); -//} diff --git a/src/conversion/first.d b/src/conversion/first.d index 09a85ee..3dc3db2 100644 --- a/src/conversion/first.d +++ b/src/conversion/first.d @@ -82,7 +82,7 @@ final class FirstPass : ASTVisitor { // Create a dummy symbol because we don't want unit test symbols leaking // into the symbol they're declared in. - SemanticSymbol* s = allocateSemanticSymbol(internString("*unittest*"), + SemanticSymbol* s = allocateSemanticSymbol(UNITTEST_SYMBOL_NAME, CompletionKind.dummy, istring(null), 0); s.parent = currentSymbol; currentSymbol.addChild(s); @@ -130,7 +130,7 @@ final class FirstPass : ASTVisitor override void visit(const FunctionDeclaration dec) { // Log.trace(__FUNCTION__, " ", typeof(dec).stringof, " ", dec.name.text); - SemanticSymbol* symbol = allocateSemanticSymbol(istring(dec.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, CompletionKind.functionName, symbolFile, dec.name.index, dec.returnType); processParameters(symbol, dec.returnType, symbol.acSymbol.name, @@ -201,7 +201,7 @@ final class FirstPass : ASTVisitor foreach (declarator; dec.declarators) { SemanticSymbol* symbol = allocateSemanticSymbol( - istring(declarator.name.text), CompletionKind.variableName, + declarator.name.text, CompletionKind.variableName, symbolFile, declarator.name.index, t); symbol.protection = protection; symbol.parent = currentSymbol; @@ -213,7 +213,7 @@ final class FirstPass : ASTVisitor foreach (i, identifier; dec.autoDeclaration.identifiers) { SemanticSymbol* symbol = allocateSemanticSymbol( - istring(identifier.text), CompletionKind.variableName, + identifier.text, CompletionKind.variableName, symbolFile, identifier.index, null); populateInitializer(symbol, dec.autoDeclaration.initializers[i]); symbol.protection = protection; @@ -231,10 +231,7 @@ final class FirstPass : ASTVisitor foreach (name; aliasDeclaration.identifierList.identifiers) { SemanticSymbol* symbol = allocateSemanticSymbol( - istring(name.text), - CompletionKind.aliasName, - symbolFile, - name.index, + name.text, CompletionKind.aliasName, symbolFile, name.index, aliasDeclaration.type); symbol.protection = protection; symbol.parent = currentSymbol; @@ -247,11 +244,8 @@ final class FirstPass : ASTVisitor foreach (initializer; aliasDeclaration.initializers) { SemanticSymbol* symbol = allocateSemanticSymbol( - istring(initializer.name.text), - CompletionKind.aliasName, - symbolFile, - initializer.name.index, - initializer.type); + initializer.name.text, CompletionKind.aliasName, + symbolFile, initializer.name.index, initializer.type); symbol.protection = protection; symbol.parent = currentSymbol; symbol.acSymbol.doc = internString(aliasDeclaration.comment); @@ -289,7 +283,7 @@ final class FirstPass : ASTVisitor { // Log.trace(__FUNCTION__, " ", typeof(mod).stringof); // - currentSymbol = allocateSemanticSymbol(istring(null), CompletionKind.moduleName, + currentSymbol = allocateSemanticSymbol(null, CompletionKind.moduleName, symbolFile); rootSymbol = currentSymbol; currentScope = allocate!Scope(semanticAllocator, 0, size_t.max); @@ -305,7 +299,7 @@ final class FirstPass : ASTVisitor { assert (currentSymbol); // Log.trace(__FUNCTION__, " ", typeof(dec).stringof); - SemanticSymbol* symbol = allocateSemanticSymbol(istring(dec.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, CompletionKind.enumName, symbolFile, dec.name.index, dec.type); symbol.parent = currentSymbol; symbol.acSymbol.doc = internString(dec.comment); @@ -331,8 +325,8 @@ final class FirstPass : ASTVisitor Scope* s = allocate!Scope(semanticAllocator, structBody.startLocation, structBody.endLocation); // Log.trace("Added scope ", s.startLocation, " ", s.endLocation); - ACSymbol* thisSymbol = allocate!ACSymbol(symbolAllocator, internString("this"), - CompletionKind.variableName, currentSymbol.acSymbol); + ACSymbol* thisSymbol = allocate!ACSymbol(symbolAllocator, + THIS_SYMBOL_NAME, CompletionKind.variableName, currentSymbol.acSymbol); thisSymbol.location = s.startLocation; thisSymbol.symbolFile = symbolFile; s.symbols.insert(thisSymbol); @@ -456,7 +450,7 @@ final class FirstPass : ASTVisitor { // Log.trace("Handling foreachtype ", feType.identifier.text); SemanticSymbol* symbol = allocateSemanticSymbol( - istring(feType.identifier.text), CompletionKind.variableName, + feType.identifier.text, CompletionKind.variableName, symbolFile, feType.identifier.index, feType.type); if (symbol.type is null && feExpression !is null) { @@ -515,7 +509,7 @@ private: { // Log.trace(__FUNCTION__, " ", typeof(member).stringof); SemanticSymbol* symbol = allocateSemanticSymbol( - istring(member.name.text), CompletionKind.enumMember, symbolFile, + member.name.text, CompletionKind.enumMember, symbolFile, member.name.index, member.type); symbol.parent = currentSymbol; symbol.acSymbol.doc = internString(member.comment); @@ -531,7 +525,7 @@ private: dec.accept(this); return; } - SemanticSymbol* symbol = allocateSemanticSymbol(istring(dec.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, kind, symbolFile, dec.name.index); if (kind == CompletionKind.className) symbol.acSymbol.parts.insert(classSymbols[]); @@ -607,7 +601,7 @@ private: } void processParameters(SemanticSymbol* symbol, const Type returnType, - istring functionName, const Parameters parameters, + string functionName, const Parameters parameters, const TemplateParameters templateParameters) { processTemplateParameters(symbol, templateParameters); @@ -616,7 +610,7 @@ private: foreach (const Parameter p; parameters.parameters) { SemanticSymbol* parameter = allocateSemanticSymbol( - istring(p.name.text), CompletionKind.variableName, symbolFile, + p.name.text, CompletionKind.variableName, symbolFile, p.name.index, p.type); symbol.addChild(parameter); parameter.parent = symbol; @@ -646,25 +640,25 @@ private: { foreach (const TemplateParameter p; templateParameters.templateParameterList.items) { - istring name; + string name; CompletionKind kind; size_t index; Rebindable!(const(Type)) type; if (p.templateAliasParameter !is null) { - name = istring(p.templateAliasParameter.identifier.text); + name = p.templateAliasParameter.identifier.text; kind = CompletionKind.aliasName; index = p.templateAliasParameter.identifier.index; } else if (p.templateTypeParameter !is null) { - name = istring(p.templateTypeParameter.identifier.text); + name = p.templateTypeParameter.identifier.text; kind = CompletionKind.aliasName; index = p.templateTypeParameter.identifier.index; } else if (p.templateValueParameter !is null) { - name = istring(p.templateValueParameter.identifier.text); + name = p.templateValueParameter.identifier.text; kind = CompletionKind.variableName; index = p.templateValueParameter.identifier.index; type = p.templateValueParameter.type; @@ -679,7 +673,7 @@ private: } } - string formatCallTip(const Type returnType, istring name, + string formatCallTip(const Type returnType, string name, const Parameters parameters, const TemplateParameters templateParameters) { QuickAllocator!1024 q; @@ -707,7 +701,7 @@ private: visitor.visit(initializer); } - SemanticSymbol* allocateSemanticSymbol(istring name, CompletionKind kind, + SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind, istring symbolFile, size_t location = 0, const Type type = null) in { @@ -770,9 +764,9 @@ istring[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain foreach (i, ioti; iotc.identifiersOrTemplateInstances) { if (ioti.identifier != tok!"") - retVal[i] = istring(ioti.identifier.text); + retVal[i] = internString(ioti.identifier.text); else - retVal[i] = istring(ioti.templateInstance.identifier.text); + retVal[i] = internString(ioti.templateInstance.identifier.text); } return retVal; } @@ -805,7 +799,7 @@ class InitializerVisitor : ASTVisitor override void visit(const IdentifierOrTemplateInstance ioti) { if (on && ioti.identifier != tok!"") - semanticSymbol.initializer.insert(istring(ioti.identifier.text)); + semanticSymbol.initializer.insert(internString(ioti.identifier.text)); ioti.accept(this); } @@ -819,49 +813,49 @@ class InitializerVisitor : ASTVisitor if (on) switch (primary.primary.type) { case tok!"identifier": - semanticSymbol.initializer.insert(istring(primary.primary.text)); + semanticSymbol.initializer.insert(internString(primary.primary.text)); break; case tok!"doubleLiteral": - semanticSymbol.initializer.insert(istring("*double")); + semanticSymbol.initializer.insert(DOUBLE_LITERAL_SYMBOL_NAME); break; case tok!"floatLiteral": - semanticSymbol.initializer.insert(istring("*float")); + semanticSymbol.initializer.insert(FLOAT_LITERAL_SYMBOL_NAME); break; case tok!"idoubleLiteral": - semanticSymbol.initializer.insert(istring("*idouble")); + semanticSymbol.initializer.insert(IDOUBLE_LITERAL_SYMBOL_NAME); break; case tok!"ifloatLiteral": - semanticSymbol.initializer.insert(istring("*ifloat")); + semanticSymbol.initializer.insert(IFLOAT_LITERAL_SYMBOL_NAME); break; case tok!"intLiteral": - semanticSymbol.initializer.insert(istring("*int")); + semanticSymbol.initializer.insert(INT_LITERAL_SYMBOL_NAME); break; case tok!"longLiteral": - semanticSymbol.initializer.insert(istring("*long")); + semanticSymbol.initializer.insert(LONG_LITERAL_SYMBOL_NAME); break; case tok!"realLiteral": - semanticSymbol.initializer.insert(istring("*real")); + semanticSymbol.initializer.insert(REAL_LITERAL_SYMBOL_NAME); break; case tok!"irealLiteral": - semanticSymbol.initializer.insert(istring("*ireal")); + semanticSymbol.initializer.insert(IREAL_LITERAL_SYMBOL_NAME); break; case tok!"uintLiteral": - semanticSymbol.initializer.insert(istring("*uint")); + semanticSymbol.initializer.insert(UINT_LITERAL_SYMBOL_NAME); break; case tok!"ulongLiteral": - semanticSymbol.initializer.insert(istring("*ulong")); + semanticSymbol.initializer.insert(ULONG_LITERAL_SYMBOL_NAME); break; case tok!"characterLiteral": - semanticSymbol.initializer.insert(istring("*char")); + semanticSymbol.initializer.insert(CHAR_LITERAL_SYMBOL_NAME); break; case tok!"dstringLiteral": - semanticSymbol.initializer.insert(istring("*dstring")); + semanticSymbol.initializer.insert(DSTRING_LITERAL_SYMBOL_NAME); break; case tok!"stringLiteral": - semanticSymbol.initializer.insert(istring("*string")); + semanticSymbol.initializer.insert(STRING_LITERAL_SYMBOL_NAME); break; case tok!"wstringLiteral": - semanticSymbol.initializer.insert(istring("*wstring")); + semanticSymbol.initializer.insert(WSTRING_LITERAL_SYMBOL_NAME); break; default: break; @@ -873,7 +867,7 @@ class InitializerVisitor : ASTVisitor { unary.accept(this); if (unary.indexExpression) - semanticSymbol.initializer.insert(istring("[]")); + semanticSymbol.initializer.insert(internString("[]")); } override void visit(const ArgumentList) {} @@ -883,7 +877,7 @@ class InitializerVisitor : ASTVisitor on = true; initializer.accept(this); if (appendForeach) - semanticSymbol.initializer.insert(istring("foreach")); + semanticSymbol.initializer.insert(internString("foreach")); on = false; } diff --git a/src/semantic.d b/src/semantic.d index 80b94e2..181d5c2 100644 --- a/src/semantic.d +++ b/src/semantic.d @@ -24,6 +24,7 @@ import std.d.ast; import std.d.lexer; import stupidlog; import containers.unrolledlist; +import string_interning; /** * Intermediate form between ACSymbol and the AST classes. Stores enough @@ -122,7 +123,7 @@ static this() argumentsType.type2.symbol = allocate!Symbol(Mallocator.it); argumentsType.type2.symbol.identifierOrTemplateChain = allocate!IdentifierOrTemplateChain(Mallocator.it); IdentifierOrTemplateInstance i = allocate!IdentifierOrTemplateInstance(Mallocator.it); - i.identifier.text = "TypeInfo"; + i.identifier.text = internString("TypeInfo"); i.identifier.type = tok!"identifier"; argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances = cast(IdentifierOrTemplateInstance[]) Mallocator.it.allocate(IdentifierOrTemplateInstance.sizeof);