Switch over to allocators from GC, dropping the memory usage by 70%

This commit is contained in:
Hackerpilot 2014-05-09 00:35:35 -07:00
parent 9e0ee133b5
commit 970310702d
14 changed files with 706 additions and 539 deletions

338
actypes.d
View File

@ -23,19 +23,15 @@ import std.array;
import std.container; import std.container;
import std.stdio; import std.stdio;
import std.typecons; import std.typecons;
import std.allocator;
import stdx.d.lexer; import containers.karytree;
import containers.unrolledlist;
import containers.slist;
import std.d.lexer;
import messages; import messages;
/**
* Compares symbols by their name
*/
bool comparitor(const(ACSymbol)* a, const(ACSymbol)* b) pure nothrow
{
return a.name < b.name;
}
/** /**
* Any special information about a variable declaration symbol. * Any special information about a variable declaration symbol.
*/ */
@ -67,7 +63,6 @@ public:
this(string name) this(string name)
{ {
this.name = name; this.name = name;
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
} }
/** /**
@ -79,7 +74,6 @@ public:
{ {
this.name = name; this.name = name;
this.kind = kind; this.kind = kind;
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
} }
/** /**
@ -93,7 +87,15 @@ public:
this.name = name; this.name = name;
this.kind = kind; this.kind = kind;
this.type = type; this.type = type;
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true); }
int opCmp(ref const ACSymbol other) const
{
if (name < other.name)
return -1;
if (name > other.name)
return 1;
return 0;
} }
/** /**
@ -101,16 +103,15 @@ public:
*/ */
ACSymbol*[] getPartsByName(string name) ACSymbol*[] getPartsByName(string name)
{ {
import std.range;
ACSymbol s = ACSymbol(name); ACSymbol s = ACSymbol(name);
return parts.equalRange(&s).array(); return array(parts.equalRange(&s));
} }
/** /**
* Symbols that compose this symbol, such as enum members, class variables, * Symbols that compose this symbol, such as enum members, class variables,
* methods, etc. * methods, etc.
*/ */
RedBlackTree!(ACSymbol*, comparitor, true) parts; KAryTree!(ACSymbol*, true, "a < b", false) parts;
/** /**
* Symbol's name * Symbol's name
@ -167,7 +168,14 @@ struct Scope
{ {
this.startLocation = begin; this.startLocation = begin;
this.endLocation = end; this.endLocation = end;
this.symbols = new RedBlackTree!(ACSymbol*, comparitor, true); }
~this()
{
foreach (info; importInformation[])
typeid(ImportInformation).destroy(info);
foreach (child; children[])
typeid(Scope).destroy(child);
} }
/** /**
@ -176,11 +184,11 @@ struct Scope
* Returns: * Returns:
* the innermost scope that contains the given cursor position * the innermost scope that contains the given cursor position
*/ */
Scope* getScopeByCursor(size_t cursorPosition) const Scope* getScopeByCursor(size_t cursorPosition)
{ {
if (cursorPosition < startLocation) return null; if (cursorPosition < startLocation) return null;
if (cursorPosition > endLocation) return null; if (cursorPosition > endLocation) return null;
foreach (child; children) foreach (child; children[])
{ {
auto childScope = child.getScopeByCursor(cursorPosition); auto childScope = child.getScopeByCursor(cursorPosition);
if (childScope !is null) if (childScope !is null)
@ -196,20 +204,20 @@ struct Scope
* all symbols in the scope containing the cursor position, as well as * all symbols in the scope containing the cursor position, as well as
* the symbols in parent scopes of that scope. * the symbols in parent scopes of that scope.
*/ */
ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition) const ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition)
{ {
auto s = getScopeByCursor(cursorPosition); auto s = getScopeByCursor(cursorPosition);
if (s is null) if (s is null)
return []; return [];
auto symbols = s.symbols; UnrolledList!(ACSymbol*) symbols;
symbols.insert(s.symbols[]);
Scope* sc = s.parent; Scope* sc = s.parent;
while (sc !is null) while (sc !is null)
{ {
foreach (sym; sc.symbols) symbols.insert(sc.symbols[]);
symbols.insert(sym);
sc = sc.parent; sc = sc.parent;
} }
return symbols.array(); return array(symbols[]);
} }
/** /**
@ -218,12 +226,16 @@ struct Scope
* Returns: * Returns:
* all symbols in this scope or parent scopes with the given name * all symbols in this scope or parent scopes with the given name
*/ */
ACSymbol*[] getSymbolsByName(string name) const ACSymbol*[] getSymbolsByName(string name)
{ {
import std.range; import std.range;
ACSymbol s = ACSymbol(name); ACSymbol s = ACSymbol(name);
RedBlackTree!(ACSymbol*, comparitor, true) t = cast() symbols; auto r = array(symbols.equalRange(&s));
auto r = t.equalRange(&s).array(); foreach (i; r)
{
import std.string;
assert (i.name == name, format("%s %s %d", i.name, name, r.length));
}
if (r.length > 0) if (r.length > 0)
return cast(typeof(return)) r; return cast(typeof(return)) r;
if (parent is null) if (parent is null)
@ -239,7 +251,7 @@ struct Scope
* all symbols with the given name in the scope containing the cursor * all symbols with the given name in the scope containing the cursor
* and its parent scopes * and its parent scopes
*/ */
ACSymbol*[] getSymbolsByNameAndCursor(string name, size_t cursorPosition) const ACSymbol*[] getSymbolsByNameAndCursor(string name, size_t cursorPosition)
{ {
auto s = getScopeByCursor(cursorPosition); auto s = getScopeByCursor(cursorPosition);
if (s is null) if (s is null)
@ -248,13 +260,13 @@ struct Scope
} }
/// Imports contained in this scope /// Imports contained in this scope
ImportInformation[] importInformation; UnrolledList!(ImportInformation*) importInformation;
/// The scope that contains this one /// The scope that contains this one
Scope* parent; Scope* parent;
/// Child scopes /// Child scopes
Scope*[] children; UnrolledList!(Scope*, false) children;
/// Start location of this scope in bytes /// Start location of this scope in bytes
size_t startLocation; size_t startLocation;
@ -263,7 +275,7 @@ struct Scope
size_t endLocation; size_t endLocation;
/// Symbols contained in this scope /// Symbols contained in this scope
RedBlackTree!(ACSymbol*, comparitor, true) symbols; KAryTree!(ACSymbol*, true, "a < b", false) symbols;
} }
/** /**
@ -272,11 +284,11 @@ struct Scope
struct ImportInformation struct ImportInformation
{ {
/// Import statement parts /// Import statement parts
string[] importParts; UnrolledList!string importParts;
/// module relative path /// module relative path
string modulePath; string modulePath;
/// symbols to import from this module /// symbols to import from this module
Tuple!(string, string)[] importedSymbols; UnrolledList!(Tuple!(string, string), false) importedSymbols;
/// true if the import is public /// true if the import is public
bool isPublic; bool isPublic;
} }
@ -285,91 +297,98 @@ struct ImportInformation
/** /**
* Symbols for the built in types * Symbols for the built in types
*/ */
RedBlackTree!(ACSymbol*, comparitor, true) builtinSymbols; KAryTree!(ACSymbol*, true) builtinSymbols;
/** /**
* Array properties * Array properties
*/ */
RedBlackTree!(ACSymbol*, comparitor, true) arraySymbols; KAryTree!(ACSymbol*, true) arraySymbols;
/** /**
* Associative array properties * Associative array properties
*/ */
RedBlackTree!(ACSymbol*, comparitor, true) assocArraySymbols; KAryTree!(ACSymbol*, true) assocArraySymbols;
/** /**
* Enum, union, class, and interface properties * Enum, union, class, and interface properties
*/ */
RedBlackTree!(ACSymbol*, comparitor, true) aggregateSymbols; KAryTree!(ACSymbol*, true) aggregateSymbols;
/** /**
* Class properties * Class properties
*/ */
RedBlackTree!(ACSymbol*, comparitor, true) classSymbols; KAryTree!(ACSymbol*, true) classSymbols;
/** /**
* Initializes builtin types and the various properties of builtin types * Initializes builtin types and the various properties of builtin types
*/ */
static this() static this()
{ {
auto bSym = new RedBlackTree!(ACSymbol*, comparitor, true); auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword);
auto arrSym = new RedBlackTree!(ACSymbol*, comparitor, true); auto int_ = allocate!ACSymbol(Mallocator.it, "int", CompletionKind.keyword);
auto asarrSym = new RedBlackTree!(ACSymbol*, comparitor, true); auto long_ = allocate!ACSymbol(Mallocator.it, "long", CompletionKind.keyword);
auto aggSym = new RedBlackTree!(ACSymbol*, comparitor, true); auto byte_ = allocate!ACSymbol(Mallocator.it, "byte", CompletionKind.keyword);
auto clSym = new RedBlackTree!(ACSymbol*, comparitor, true); 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_ = new ACSymbol("bool", CompletionKind.keyword); auto alignof_ = allocate!ACSymbol(Mallocator.it, "alignof", CompletionKind.keyword);
auto int_ = new ACSymbol("int", CompletionKind.keyword); auto mangleof_ = allocate!ACSymbol(Mallocator.it, "mangleof", CompletionKind.keyword);
auto long_ = new ACSymbol("long", CompletionKind.keyword); auto sizeof_ = allocate!ACSymbol(Mallocator.it, "sizeof", CompletionKind.keyword);
auto byte_ = new ACSymbol("byte", CompletionKind.keyword); auto stringof_ = allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword);
auto char_ = new ACSymbol("char", CompletionKind.keyword); auto init = allocate!ACSymbol(Mallocator.it, "stringof", CompletionKind.keyword);
auto dchar_ = new ACSymbol("dchar", CompletionKind.keyword);
auto short_ = new ACSymbol("short", CompletionKind.keyword);
auto ubyte_ = new ACSymbol("ubyte", CompletionKind.keyword);
auto uint_ = new ACSymbol("uint", CompletionKind.keyword);
auto ulong_ = new ACSymbol("ulong", CompletionKind.keyword);
auto ushort_ = new ACSymbol("ushort", CompletionKind.keyword);
auto wchar_ = new ACSymbol("wchar", CompletionKind.keyword);
auto alignof_ = new ACSymbol("alignof", CompletionKind.keyword, ulong_); arraySymbols.insert(alignof_);
auto mangleof_ = new ACSymbol("mangleof", CompletionKind.keyword); arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "dup", CompletionKind.keyword));
auto sizeof_ = new ACSymbol("sizeof", CompletionKind.keyword, ulong_); arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "idup", CompletionKind.keyword));
auto stringof_ = new ACSymbol("init", CompletionKind.keyword); arraySymbols.insert(init);
auto init = new ACSymbol("stringof", CompletionKind.keyword); arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "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(sizeof_);
arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "sort", CompletionKind.keyword));
arraySymbols.insert(stringof_);
arrSym.insert(alignof_); assocArraySymbols.insert(alignof_);
arrSym.insert(new ACSymbol("dup", CompletionKind.keyword)); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "byKey", CompletionKind.keyword));
arrSym.insert(new ACSymbol("idup", CompletionKind.keyword)); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "byValue", CompletionKind.keyword));
arrSym.insert(init); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "dup", CompletionKind.keyword));
arrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_)); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "get", CompletionKind.keyword));
arrSym.insert(mangleof_); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword));
arrSym.insert(new ACSymbol("ptr", CompletionKind.keyword)); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "keys", CompletionKind.keyword));
arrSym.insert(new ACSymbol("reverse", CompletionKind.keyword)); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "length", CompletionKind.keyword, ulong_));
arrSym.insert(sizeof_); assocArraySymbols.insert(mangleof_);
arrSym.insert(new ACSymbol("sort", CompletionKind.keyword)); assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "rehash", CompletionKind.keyword));
arrSym.insert(stringof_); assocArraySymbols.insert(sizeof_);
assocArraySymbols.insert(stringof_);
assocArraySymbols.insert(init);
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "values", CompletionKind.keyword));
asarrSym.insert(alignof_); ACSymbol*[11] integralTypeArray;
asarrSym.insert(new ACSymbol("byKey", CompletionKind.keyword)); integralTypeArray[0] = bool_;
asarrSym.insert(new ACSymbol("byValue", CompletionKind.keyword)); integralTypeArray[1] = int_;
asarrSym.insert(new ACSymbol("dup", CompletionKind.keyword)); integralTypeArray[2] = long_;
asarrSym.insert(new ACSymbol("get", CompletionKind.keyword)); integralTypeArray[3] = byte_;
asarrSym.insert(new ACSymbol("init", CompletionKind.keyword)); integralTypeArray[4] = char_;
asarrSym.insert(new ACSymbol("keys", CompletionKind.keyword)); integralTypeArray[4] = dchar_;
asarrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_)); integralTypeArray[5] = short_;
asarrSym.insert(mangleof_); integralTypeArray[6] = ubyte_;
asarrSym.insert(new ACSymbol("rehash", CompletionKind.keyword)); integralTypeArray[7] = uint_;
asarrSym.insert(sizeof_); integralTypeArray[8] = ulong_;
asarrSym.insert(stringof_); integralTypeArray[9] = ushort_;
asarrSym.insert(init); integralTypeArray[10] = wchar_;
asarrSym.insert(new ACSymbol("values", CompletionKind.keyword));
foreach (s; [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_, foreach (s; integralTypeArray)
ulong_, ushort_, wchar_])
{ {
s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "min", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "max", CompletionKind.keyword, s));
s.parts.insert(alignof_); s.parts.insert(alignof_);
s.parts.insert(sizeof_); s.parts.insert(sizeof_);
s.parts.insert(stringof_); s.parts.insert(stringof_);
@ -377,74 +396,101 @@ static this()
s.parts.insert(init); s.parts.insert(init);
} }
auto cdouble_ = new ACSymbol("cdouble", CompletionKind.keyword); auto cdouble_ = allocate!ACSymbol(Mallocator.it, "cdouble", CompletionKind.keyword);
auto cent_ = new ACSymbol("cent", CompletionKind.keyword); auto cent_ = allocate!ACSymbol(Mallocator.it, "cent", CompletionKind.keyword);
auto cfloat_ = new ACSymbol("cfloat", CompletionKind.keyword); auto cfloat_ = allocate!ACSymbol(Mallocator.it, "cfloat", CompletionKind.keyword);
auto creal_ = new ACSymbol("creal", CompletionKind.keyword); auto creal_ = allocate!ACSymbol(Mallocator.it, "creal", CompletionKind.keyword);
auto double_ = new ACSymbol("double", CompletionKind.keyword); auto double_ = allocate!ACSymbol(Mallocator.it, "double", CompletionKind.keyword);
auto float_ = new ACSymbol("float", CompletionKind.keyword); auto float_ = allocate!ACSymbol(Mallocator.it, "float", CompletionKind.keyword);
auto idouble_ = new ACSymbol("idouble", CompletionKind.keyword); auto idouble_ = allocate!ACSymbol(Mallocator.it, "idouble", CompletionKind.keyword);
auto ifloat_ = new ACSymbol("ifloat", CompletionKind.keyword); auto ifloat_ = allocate!ACSymbol(Mallocator.it, "ifloat", CompletionKind.keyword);
auto ireal_ = new ACSymbol("ireal", CompletionKind.keyword); auto ireal_ = allocate!ACSymbol(Mallocator.it, "ireal", CompletionKind.keyword);
auto real_ = new ACSymbol("real", CompletionKind.keyword); auto real_ = allocate!ACSymbol(Mallocator.it, "real", CompletionKind.keyword);
auto ucent_ = new ACSymbol("ucent", CompletionKind.keyword); auto ucent_ = allocate!ACSymbol(Mallocator.it, "ucent", CompletionKind.keyword);
foreach (s; [cdouble_, cent_, cfloat_, creal_, double_, float_, ACSymbol*[11] floatTypeArray;
idouble_, ifloat_, ireal_, real_, ucent_]) floatTypeArray[0] = cdouble_;
floatTypeArray[1] = cent_;
floatTypeArray[2] = cfloat_;
floatTypeArray[3] = creal_;
floatTypeArray[4] = double_;
floatTypeArray[5] = float_;
floatTypeArray[6] = idouble_;
floatTypeArray[7] = ifloat_;
floatTypeArray[8] = ireal_;
floatTypeArray[9] = real_;
floatTypeArray[10] = ucent_;
foreach (s; floatTypeArray)
{ {
s.parts.insert(alignof_); s.parts.insert(alignof_);
s.parts.insert(new ACSymbol("dig", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "dig", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("epsilon", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "epsilon", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("infinity", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "infinity", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword, s));
s.parts.insert(mangleof_); s.parts.insert(mangleof_);
s.parts.insert(new ACSymbol("mant_dig", CompletionKind.keyword, int_)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "mant_dig", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "max", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("max_10_exp", CompletionKind.keyword, int_)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "max_10_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("max_exp", CompletionKind.keyword, int_)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "max_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "min", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("min_exp", CompletionKind.keyword, int_)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("min_10_exp", CompletionKind.keyword, int_)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_10_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("min_normal", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_normal", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("nan", CompletionKind.keyword, s)); s.parts.insert(allocate!ACSymbol(Mallocator.it, "nan", CompletionKind.keyword, s));
s.parts.insert(sizeof_); s.parts.insert(sizeof_);
s.parts.insert(stringof_); s.parts.insert(stringof_);
} }
aggSym.insert(new ACSymbol("tupleof", CompletionKind.variableName)); aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.variableName));
aggSym.insert(mangleof_); aggregateSymbols.insert(mangleof_);
aggSym.insert(alignof_); aggregateSymbols.insert(alignof_);
aggSym.insert(sizeof_); aggregateSymbols.insert(sizeof_);
aggSym.insert(stringof_); aggregateSymbols.insert(stringof_);
aggSym.insert(init); aggregateSymbols.insert(init);
clSym.insert(new ACSymbol("classInfo", CompletionKind.variableName)); classSymbols.insert(allocate!ACSymbol(Mallocator.it, "classInfo", CompletionKind.variableName));
clSym.insert(new ACSymbol("tupleof", CompletionKind.variableName)); classSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.variableName));
clSym.insert(new ACSymbol("__vptr", CompletionKind.variableName)); classSymbols.insert(allocate!ACSymbol(Mallocator.it, "__vptr", CompletionKind.variableName));
clSym.insert(new ACSymbol("__monitor", CompletionKind.variableName)); classSymbols.insert(allocate!ACSymbol(Mallocator.it, "__monitor", CompletionKind.variableName));
clSym.insert(mangleof_); classSymbols.insert(mangleof_);
clSym.insert(alignof_); classSymbols.insert(alignof_);
clSym.insert(sizeof_); classSymbols.insert(sizeof_);
clSym.insert(stringof_); classSymbols.insert(stringof_);
clSym.insert(init); classSymbols.insert(init);
ireal_.parts.insert(new ACSymbol("im", CompletionKind.keyword, real_)); ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, real_));
ifloat_.parts.insert(new ACSymbol("im", CompletionKind.keyword, float_)); ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, float_));
idouble_.parts.insert(new ACSymbol("im", CompletionKind.keyword, double_)); idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, double_));
ireal_.parts.insert(new ACSymbol("re", CompletionKind.keyword, real_)); ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, real_));
ifloat_.parts.insert(new ACSymbol("re", CompletionKind.keyword, float_)); ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, float_));
idouble_.parts.insert(new ACSymbol("re", CompletionKind.keyword, double_)); idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, double_));
auto void_ = new ACSymbol("void", CompletionKind.keyword); auto void_ = allocate!ACSymbol(Mallocator.it, "void", CompletionKind.keyword);
bSym.insert([bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_, builtinSymbols.insert(bool_);
ulong_, ushort_, wchar_, cdouble_, cent_, cfloat_, creal_, double_, builtinSymbols.insert(int_);
float_, idouble_, ifloat_, ireal_, real_, ucent_, void_]); builtinSymbols.insert(long_);
builtinSymbols.insert(byte_);
builtinSymbols = bSym; builtinSymbols.insert(char_);
arraySymbols = arrSym; builtinSymbols.insert(dchar_);
assocArraySymbols = asarrSym; builtinSymbols.insert(short_);
aggregateSymbols = aggSym; builtinSymbols.insert(ubyte_);
classSymbols = clSym; builtinSymbols.insert(uint_);
builtinSymbols.insert(ulong_);
builtinSymbols.insert(ushort_);
builtinSymbols.insert(wchar_);
builtinSymbols.insert(cdouble_);
builtinSymbols.insert(cent_);
builtinSymbols.insert(cfloat_);
builtinSymbols.insert(creal_);
builtinSymbols.insert(double_);
builtinSymbols.insert(float_);
builtinSymbols.insert(idouble_);
builtinSymbols.insert(ifloat_);
builtinSymbols.insert(ireal_);
builtinSymbols.insert(real_);
builtinSymbols.insert(ucent_);
builtinSymbols.insert(void_);
} }

View File

@ -26,10 +26,13 @@ import std.path;
import std.range; import std.range;
import std.stdio; import std.stdio;
import std.uni; import std.uni;
import stdx.d.ast; import std.d.ast;
import stdx.d.lexer; import std.d.lexer;
import stdx.d.parser; import std.d.parser;
import std.string; import std.string;
import std.typecons;
import memory.allocators;
import std.allocator;
import messages; import messages;
import actypes; import actypes;
@ -49,7 +52,8 @@ AutocompleteResponse getDoc(const AutocompleteRequest request)
{ {
Log.trace("Getting doc comments"); Log.trace("Getting doc comments");
AutocompleteResponse response; AutocompleteResponse response;
ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.ddoc); auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.ddoc, allocator);
if (symbols.length == 0) if (symbols.length == 0)
Log.error("Could not find symbol"); Log.error("Could not find symbol");
else foreach (symbol; symbols) else foreach (symbol; symbols)
@ -76,7 +80,8 @@ AutocompleteResponse findDeclaration(const AutocompleteRequest request)
{ {
Log.trace("Finding declaration"); Log.trace("Finding declaration");
AutocompleteResponse response; AutocompleteResponse response;
ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.location); auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.location, allocator);
if (symbols.length > 0) if (symbols.length > 0)
{ {
response.symbolLocation = symbols[0].location; response.symbolLocation = symbols[0].location;
@ -120,7 +125,7 @@ AutocompleteResponse complete(const AutocompleteRequest request)
tokenType = beforeTokens[$ - 2].type; tokenType = beforeTokens[$ - 2].type;
else else
return response; return response;
auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
switch (tokenType) switch (tokenType)
{ {
case tok!"stringLiteral": case tok!"stringLiteral":
@ -160,8 +165,11 @@ AutocompleteResponse complete(const AutocompleteRequest request)
case tok!")": case tok!")":
case tok!"]": case tok!"]":
case tok!"this": case tok!"this":
const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
"stdin"); shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
Scope* completionScope = generateAutocompleteTrees(tokenArray,
"stdin", allocator, semanticAllocator, cache);
scope(exit) typeid(Scope).destroy(completionScope);
auto expression = getExpression(beforeTokens); auto expression = getExpression(beforeTokens);
response.setCompletions(completionScope, expression, response.setCompletions(completionScope, expression,
request.cursorPosition, CompletionType.identifiers, partial); request.cursorPosition, CompletionType.identifiers, partial);
@ -207,12 +215,16 @@ auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition,
* the request's source code, cursor position, and completion type. * the request's source code, cursor position, and completion type.
*/ */
ACSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request, ACSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request,
const CompletionType type) const CompletionType type, CAllocator allocator)
{ {
const(Token)[] tokenArray; const(Token)[] tokenArray;
auto beforeTokens = getTokensBeforeCursor(request.sourceCode, auto beforeTokens = getTokensBeforeCursor(request.sourceCode,
request.cursorPosition, tokenArray); request.cursorPosition, tokenArray);
const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, "stdin"); auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
Scope* completionScope = generateAutocompleteTrees(tokenArray,
"stdin", allocator, semanticAllocator, cache);
scope(exit) typeid(Scope).destroy(completionScope);
auto expression = getExpression(beforeTokens); auto expression = getExpression(beforeTokens);
return getSymbolsByTokenChain(completionScope, expression, return getSymbolsByTokenChain(completionScope, expression,
request.cursorPosition, type); request.cursorPosition, type);
@ -232,6 +244,7 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
{ {
AutocompleteResponse response; AutocompleteResponse response;
immutable(string)[] completions; immutable(string)[] completions;
auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
switch (beforeTokens[$ - 2].type) switch (beforeTokens[$ - 2].type)
{ {
case tok!"__traits": case tok!"__traits":
@ -259,8 +272,11 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
case tok!"identifier": case tok!"identifier":
case tok!")": case tok!")":
case tok!"]": case tok!"]":
const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
"stdin"); shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
Scope* completionScope = generateAutocompleteTrees(tokenArray,
"stdin", allocator, semanticAllocator, cache);
scope(exit) typeid(Scope).destroy(completionScope);
auto expression = getExpression(beforeTokens[0 .. $ - 1]); auto expression = getExpression(beforeTokens[0 .. $ - 1]);
response.setCompletions(completionScope, expression, response.setCompletions(completionScope, expression,
cursorPosition, CompletionType.calltips); cursorPosition, CompletionType.calltips);
@ -274,16 +290,18 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
/** /**
* *
*/ */
ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope, ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
T tokens, size_t cursorPosition, CompletionType completionType) T tokens, size_t cursorPosition, CompletionType completionType)
{ {
Log.trace("Getting symbols from token chain", tokens.map!"a.text"); import std.d.lexer;
Log.trace("Getting symbols from token chain",
tokens.map!stringToken);
// Find the symbol corresponding to the beginning of the chain // Find the symbol corresponding to the beginning of the chain
ACSymbol*[] symbols = completionScope.getSymbolsByNameAndCursor( ACSymbol*[] symbols = completionScope.getSymbolsByNameAndCursor(
tokens[0].text, cursorPosition); stringToken(tokens[0]), cursorPosition);
if (symbols.length == 0) if (symbols.length == 0)
{ {
Log.error("Could not find declaration of ", tokens[0].text, Log.error("Could not find declaration of ", stringToken(tokens[0]),
" from position ", cursorPosition); " from position ", cursorPosition);
return []; return [];
} }
@ -437,7 +455,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope,
* *
*/ */
void setCompletions(T)(ref AutocompleteResponse response, void setCompletions(T)(ref AutocompleteResponse response,
const(Scope)* completionScope, T tokens, size_t cursorPosition, Scope* completionScope, T tokens, size_t cursorPosition,
CompletionType completionType, string partial = null) CompletionType completionType, string partial = null)
{ {
// Autocomplete module imports instead of symbols // Autocomplete module imports instead of symbols
@ -486,7 +504,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
&& (partial is null ? true : a.name.toUpper().startsWith(partial.toUpper())) && (partial is null ? true : a.name.toUpper().startsWith(partial.toUpper()))
&& !response.completions.canFind(a.name))) && !response.completions.canFind(a.name)))
{ {
Log.trace("Adding ", s.name, " to the completion list"); // Log.trace("Adding ", s.name, " to the completion list");
response.completionKinds ~= s.kind; response.completionKinds ~= s.kind;
response.completions ~= s.name; response.completions ~= s.name;
} }
@ -733,6 +751,11 @@ string formatComment(string comment)
.replaceAll(regex("\n"), `\n`).outdent(); .replaceAll(regex("\n"), `\n`).outdent();
} }
string stringToken()(auto ref const Token a)
{
return a.text is null ? str(a.type) : a.text;
}
//unittest //unittest
//{ //{
// auto comment1 = "/**\n * This is some text\n */"; // auto comment1 = "/**\n * This is some text\n */";

View File

@ -1,2 +1,3 @@
dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -noboundscheck -O -ofdcd-client.exe dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -O -ofdcd-client
dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d dscanner/stdx/d/ast.d dscanner/stdx/d/entities.d dscanner/stdx/d/lexer.d dscanner/stdx/d/parser.d dscanner/stdx/lexer.d dscanner/stdx/allocator.d dscanner/formatter.d msgpack-d/src/msgpack.d -Imsgpack-d/src -Idscanner -wi -g -O -release -noboundscheck -inline -ofdcd-server.exe
dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d dscanner/std/d/ast.d dscanner/std/d/entities.d dscanner/std/d/lexer.d dscanner/std/d/parser.d dscanner/std/lexer.d dscanner/std/allocator.d dscanner/formatter.d containers/src/memory/allocators.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server

View File

@ -1,9 +1,12 @@
dmd -wi client.d\ rm -f containers/src/std/allocator.d
dmd\
client.d\
messages.d\ messages.d\
stupidlog.d\ stupidlog.d\
msgpack-d/src/msgpack.d\ msgpack-d/src/msgpack.d\
-Imsgpack-d/src\ -Imsgpack-d/src\
-release -inline -noboundscheck -O\ -release -inline -O -wi\
-ofdcd-client -ofdcd-client
dmd\ dmd\
@ -19,18 +22,26 @@ dmd \
semantic.d\ semantic.d\
server.d\ server.d\
stupidlog.d\ stupidlog.d\
dscanner/stdx/d/ast.d\ dscanner/std/d/ast.d\
dscanner/stdx/d/entities.d\ dscanner/std/d/entities.d\
dscanner/stdx/d/lexer.d\ dscanner/std/d/lexer.d\
dscanner/stdx/d/parser.d\ dscanner/std/d/parser.d\
dscanner/stdx/lexer.d\ dscanner/std/lexer.d\
dscanner/stdx/allocator.d\ dscanner/std/allocator.d\
dscanner/formatter.d\ dscanner/formatter.d\
containers/src/memory/allocators.d\
containers/src/memory/appender.d\
containers/src/containers/dynamicarray.d\
containers/src/containers/karytree.d\
containers/src/containers/unrolledlist.d\
containers/src/containers/hashset.d\
containers/src/containers/internal/hash.d\
containers/src/containers/slist.d\
msgpack-d/src/msgpack.d\ msgpack-d/src/msgpack.d\
-Icontainers/src\
-Imsgpack-d/src\ -Imsgpack-d/src\
-Idscanner\ -Idscanner\
-wi -g\ -wi -O -release -inline\
-O -release -noboundscheck -inline\
-ofdcd-server -ofdcd-server
#gdc client.d\ #gdc client.d\

View File

@ -177,113 +177,83 @@ immutable string[] versions = [
"X86_64" "X86_64"
]; ];
/** immutable string[] predefinedVersions = [
* Properties of class types "AArch64",
*/ "AIX",
immutable string[] classProperties = [ "all",
"alignof", "Alpha",
"classinfo", "Alpha_HardFloat",
"init", "Alpha_SoftFloat",
"mangleof", "Android",
"__monitor", "ARM",
"sizeof", "ARM_HardFloat",
"stringof", "ARM_SoftFloat",
"tupleof", "ARM_SoftFP",
"__vptr", "ARM_Thumb",
"assert",
"BigEndian",
"BSD",
"Cygwin",
"D_Coverage",
"D_Ddoc",
"D_HardFloat",
"DigitalMars",
"D_InlineAsm_X86",
"D_InlineAsm_X86_64",
"D_LP64",
"D_NoBoundsChecks",
"D_PIC",
"DragonFlyBSD",
"D_SIMD",
"D_SoftFloat",
"D_Version2",
"D_X32",
"FreeBSD",
"GNU",
"Haiku",
"HPPA",
"HPPA64",
"Hurd",
"IA64",
"LDC",
"linux",
"LittleEndian",
"MIPS32",
"MIPS64",
"MIPS_EABI",
"MIPS_HardFloat",
"MIPS_N32",
"MIPS_N64",
"MIPS_O32",
"MIPS_O64",
"MIPS_SoftFloat",
"NetBSD",
"none",
"OpenBSD",
"OSX",
"Posix",
"PPC",
"PPC64",
"PPC_HardFloat",
"PPC_SoftFloat",
"S390",
"S390X",
"SDC",
"SH",
"SH64",
"SkyOS",
"Solaris",
"SPARC",
"SPARC64",
"SPARC_HardFloat",
"SPARC_SoftFloat",
"SPARC_V8Plus",
"SysV3",
"SysV4",
"unittest",
"Win32",
"Win64",
"Windows",
"X86",
"X86_64",
]; ];
/**
* Properties of struct types
*/
immutable string[] structProperties = [
"alignof",
"tupleof",
"init",
"mangleof",
"sizeof",
"stringof"
];
immutable string[] predefinedVersions;
static this()
{
version(AArch64) predefinedVersions ~= "AArch64";
version(AIX) predefinedVersions ~= "AIX";
version(all) predefinedVersions ~= "all";
version(Alpha) predefinedVersions ~= "Alpha";
version(Alpha_HardFloat) predefinedVersions ~= "Alpha_HardFloat";
version(Alpha_SoftFloat) predefinedVersions ~= "Alpha_SoftFloat";
version(Android) predefinedVersions ~= "Android";
version(ARM) predefinedVersions ~= "ARM";
version(ARM_HardFloat) predefinedVersions ~= "ARM_HardFloat";
version(ARM_SoftFloat) predefinedVersions ~= "ARM_SoftFloat";
version(ARM_SoftFP) predefinedVersions ~= "ARM_SoftFP";
version(ARM_Thumb) predefinedVersions ~= "ARM_Thumb";
version(assert) predefinedVersions ~= "assert";
version(BigEndian) predefinedVersions ~= "BigEndian";
version(BSD) predefinedVersions ~= "BSD";
version(Cygwin) predefinedVersions ~= "Cygwin";
version(D_Coverage) predefinedVersions ~= "D_Coverage";
version(D_Ddoc) predefinedVersions ~= "D_Ddoc";
version(D_HardFloat) predefinedVersions ~= "D_HardFloat";
version(DigitalMars) predefinedVersions ~= "DigitalMars";
version(D_InlineAsm_X86) predefinedVersions ~= "D_InlineAsm_X86";
version(D_InlineAsm_X86_64) predefinedVersions ~= "D_InlineAsm_X86_64";
version(D_LP64) predefinedVersions ~= "D_LP64";
version(D_NoBoundsChecks) predefinedVersions ~= "D_NoBoundsChecks";
version(D_PIC) predefinedVersions ~= "D_PIC";
version(DragonFlyBSD) predefinedVersions ~= "DragonFlyBSD";
version(D_SIMD) predefinedVersions ~= "D_SIMD";
version(D_SoftFloat) predefinedVersions ~= "D_SoftFloat";
version(D_Version2) predefinedVersions ~= "D_Version2";
version(D_X32) predefinedVersions ~= "D_X32";
version(FreeBSD) predefinedVersions ~= "FreeBSD";
version(GNU) predefinedVersions ~= "GNU";
version(Haiku) predefinedVersions ~= "Haiku";
version(HPPA) predefinedVersions ~= "HPPA";
version(HPPA64) predefinedVersions ~= "HPPA64";
version(Hurd) predefinedVersions ~= "Hurd";
version(IA64) predefinedVersions ~= "IA64";
version(LDC) predefinedVersions ~= "LDC";
version(linux) predefinedVersions ~= "linux";
version(LittleEndian) predefinedVersions ~= "LittleEndian";
version(MIPS32) predefinedVersions ~= "MIPS32";
version(MIPS64) predefinedVersions ~= "MIPS64";
version(MIPS_EABI) predefinedVersions ~= "MIPS_EABI";
version(MIPS_HardFloat) predefinedVersions ~= "MIPS_HardFloat";
version(MIPS_N32) predefinedVersions ~= "MIPS_N32";
version(MIPS_N64) predefinedVersions ~= "MIPS_N64";
version(MIPS_O32) predefinedVersions ~= "MIPS_O32";
version(MIPS_O64) predefinedVersions ~= "MIPS_O64";
version(MIPS_SoftFloat) predefinedVersions ~= "MIPS_SoftFloat";
version(NetBSD) predefinedVersions ~= "NetBSD";
version(none) predefinedVersions ~= "none";
version(OpenBSD) predefinedVersions ~= "OpenBSD";
version(OSX) predefinedVersions ~= "OSX";
version(Posix) predefinedVersions ~= "Posix";
version(PPC) predefinedVersions ~= "PPC";
version(PPC64) predefinedVersions ~= "PPC64";
version(PPC_HardFloat) predefinedVersions ~= "PPC_HardFloat";
version(PPC_SoftFloat) predefinedVersions ~= "PPC_SoftFloat";
version(S390) predefinedVersions ~= "S390";
version(S390X) predefinedVersions ~= "S390X";
version(SDC) predefinedVersions ~= "SDC";
version(SH) predefinedVersions ~= "SH";
version(SH64) predefinedVersions ~= "SH64";
version(SkyOS) predefinedVersions ~= "SkyOS";
version(Solaris) predefinedVersions ~= "Solaris";
version(SPARC) predefinedVersions ~= "SPARC";
version(SPARC64) predefinedVersions ~= "SPARC64";
version(SPARC_HardFloat) predefinedVersions ~= "SPARC_HardFloat";
version(SPARC_SoftFloat) predefinedVersions ~= "SPARC_SoftFloat";
version(SPARC_V8Plus) predefinedVersions ~= "SPARC_V8Plus";
version(SysV3) predefinedVersions ~= "SysV3";
version(SysV4) predefinedVersions ~= "SysV4";
version(unittest) predefinedVersions ~= "unittest";
version(Win32) predefinedVersions ~= "Win32";
version(Win64) predefinedVersions ~= "Win64";
version(Windows) predefinedVersions ~= "Windows";
version(X86) predefinedVersions ~= "X86";
version(X86_64) predefinedVersions ~= "X86_64";
}

View File

@ -18,22 +18,24 @@
module conversion.astconverter; module conversion.astconverter;
import stdx.d.lexer; import actypes;
import stdx.d.ast;
import stdx.d.parser;
import conversion.first; import conversion.first;
import conversion.second; import conversion.second;
import conversion.third; import conversion.third;
import actypes; import memory.allocators;
import std.allocator;
import std.d.ast;
import std.d.lexer;
import std.d.parser;
import std.typecons;
Scope* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile,
const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile) CAllocator symbolAllocator, CAllocator semanticAllocator,
shared(StringCache)* cache)
{ {
ParseAllocator p = new ParseAllocator; Module m = parseModule(tokens, "editor buffer", semanticAllocator, &doesNothing);
Module m = parseModule(tokens, "editor buffer", p, &doesNothing); auto first = scoped!FirstPass(m, symbolFile, cache, symbolAllocator,
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount); semanticAllocator);
FirstPass first = new FirstPass(m, symbolFile, cache);
first.run(); first.run();
SecondPass second = SecondPass(first); SecondPass second = SecondPass(first);
@ -41,14 +43,13 @@ const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile
ThirdPass third = ThirdPass(second); ThirdPass third = ThirdPass(second);
third.run(); third.run();
typeid(typeof(third.rootSymbol)).destroy(third.rootSymbol);
p.deallocateAll(); return third.moduleScope;
return cast(typeof(return)) third.moduleScope;
} }
Module parseModuleSimple(const(Token)[] tokens, string fileName, ParseAllocator p) Module parseModuleSimple(const(Token)[] tokens, string fileName, CAllocator p)
{ {
auto parser = new SimpleParser(); auto parser = scoped!SimpleParser();
parser.fileName = fileName; parser.fileName = fileName;
parser.tokens = tokens; parser.tokens = tokens;
parser.messageFunction = &doesNothing; parser.messageFunction = &doesNothing;

View File

@ -18,12 +18,18 @@
module conversion.first; module conversion.first;
import stdx.d.ast;
import stdx.d.lexer;
import actypes; import actypes;
import semantic; import formatter;
import std.allocator;
import memory.allocators;
import memory.appender;
import messages; import messages;
import semantic;
import std.d.ast;
import std.d.lexer;
import std.typecons;
import stupidlog; import stupidlog;
import containers.unrolledlist;
/** /**
* First Pass handles the following: * First Pass handles the following:
@ -40,24 +46,31 @@ import stupidlog;
*/ */
final class FirstPass : ASTVisitor final class FirstPass : ASTVisitor
{ {
this(Module mod, string symbolFile, shared(StringCache)* stringCache) this(Module mod, string symbolFile, shared(StringCache)* stringCache,
CAllocator symbolAllocator, CAllocator semanticAllocator)
in
{
assert (symbolAllocator);
}
body
{ {
this.symbolFile = symbolFile;
this.mod = mod; this.mod = mod;
this.symbolFile = symbolFile;
this.stringCache = stringCache; this.stringCache = stringCache;
this.symbolAllocator = symbolAllocator;
this.semanticAllocator = semanticAllocator;
} }
void run() void run()
{ {
visit(mod); visit(mod);
mod = null;
} }
override void visit(const Unittest u) override void visit(const Unittest u)
{ {
// Create a dummy symbol because we don't want unit test symbols leaking // Create a dummy symbol because we don't want unit test symbols leaking
// into the symbol they're declared in. // into the symbol they're declared in.
SemanticSymbol* s = new SemanticSymbol("*unittest*", SemanticSymbol* s = allocateSemanticSymbol("*unittest*",
CompletionKind.dummy, null, 0); CompletionKind.dummy, null, 0);
s.parent = currentSymbol; s.parent = currentSymbol;
currentSymbol = s; currentSymbol = s;
@ -86,7 +99,7 @@ final class FirstPass : ASTVisitor
override void visit(const Destructor des) override void visit(const Destructor des)
{ {
// Log.trace(__FUNCTION__, " ", typeof(des).stringof); // Log.trace(__FUNCTION__, " ", typeof(des).stringof);
visitDestructor(des.location, des.functionBody, des.comment); visitDestructor(des.index, des.functionBody, des.comment);
} }
override void visit(const SharedStaticDestructor des) override void visit(const SharedStaticDestructor des)
@ -103,9 +116,10 @@ final class FirstPass : ASTVisitor
override void visit(const FunctionDeclaration dec) override void visit(const FunctionDeclaration dec)
{ {
// Log.trace(__FUNCTION__, " ", typeof(dec).stringof); // Log.trace(__FUNCTION__, " ", typeof(dec).stringof, " ", dec.name.text);
SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(dec.name.text), SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text,
CompletionKind.functionName, symbolFile, dec.name.index, dec.returnType); CompletionKind.functionName, symbolFile, dec.name.index,
dec.returnType);
processParameters(symbol, dec.returnType, symbol.acSymbol.name, processParameters(symbol, dec.returnType, symbol.acSymbol.name,
dec.parameters, dec.comment); dec.parameters, dec.comment);
symbol.protection = protection; symbol.protection = protection;
@ -153,8 +167,8 @@ final class FirstPass : ASTVisitor
override void visit(const BaseClass bc) override void visit(const BaseClass bc)
{ {
// Log.trace(__FUNCTION__, " ", typeof(bc).stringof); // Log.trace(__FUNCTION__, " ", typeof(bc).stringof);
currentSymbol.baseClasses ~= iotcToStringArray( currentSymbol.baseClasses.insert(iotcToStringArray(symbolAllocator,
bc.identifierOrTemplateChain, stringCache); bc.identifierOrTemplateChain, stringCache));
} }
override void visit(const VariableDeclaration dec) override void visit(const VariableDeclaration dec)
@ -164,12 +178,9 @@ final class FirstPass : ASTVisitor
const Type t = dec.type; const Type t = dec.type;
foreach (declarator; dec.declarators) foreach (declarator; dec.declarators)
{ {
SemanticSymbol* symbol = new SemanticSymbol( SemanticSymbol* symbol = allocateSemanticSymbol(
stringCache.intern(declarator.name.text), declarator.name.text, CompletionKind.variableName,
CompletionKind.variableName, symbolFile, declarator.name.index, t);
symbolFile,
declarator.name.index,
t);
symbol.protection = protection; symbol.protection = protection;
symbol.parent = currentSymbol; symbol.parent = currentSymbol;
symbol.acSymbol.doc = dec.comment; symbol.acSymbol.doc = dec.comment;
@ -179,10 +190,9 @@ final class FirstPass : ASTVisitor
{ {
foreach (identifier; dec.autoDeclaration.identifiers) foreach (identifier; dec.autoDeclaration.identifiers)
{ {
SemanticSymbol* symbol = new SemanticSymbol( SemanticSymbol* symbol = allocateSemanticSymbol(
stringCache.intern(identifier.text), identifier.text, CompletionKind.variableName, symbolFile,
CompletionKind.variableName, symbolFile, identifier.index, identifier.index, null);
null);
symbol.protection = protection; symbol.protection = protection;
symbol.parent = currentSymbol; symbol.parent = currentSymbol;
symbol.acSymbol.doc = dec.comment; symbol.acSymbol.doc = dec.comment;
@ -195,8 +205,8 @@ final class FirstPass : ASTVisitor
{ {
if (aliasDeclaration.initializers.length == 0) if (aliasDeclaration.initializers.length == 0)
{ {
SemanticSymbol* symbol = new SemanticSymbol( SemanticSymbol* symbol = allocateSemanticSymbol(
stringCache.intern(aliasDeclaration.name.text), aliasDeclaration.name.text,
CompletionKind.aliasName, CompletionKind.aliasName,
symbolFile, symbolFile,
aliasDeclaration.name.index, aliasDeclaration.name.index,
@ -210,8 +220,8 @@ final class FirstPass : ASTVisitor
{ {
foreach (initializer; aliasDeclaration.initializers) foreach (initializer; aliasDeclaration.initializers)
{ {
SemanticSymbol* symbol = new SemanticSymbol( SemanticSymbol* symbol = allocateSemanticSymbol(
stringCache.intern(initializer.name.text), initializer.name.text,
CompletionKind.aliasName, CompletionKind.aliasName,
symbolFile, symbolFile,
initializer.name.index, initializer.name.index,
@ -227,7 +237,7 @@ final class FirstPass : ASTVisitor
override void visit(const AliasThisDeclaration dec) override void visit(const AliasThisDeclaration dec)
{ {
// Log.trace(__FUNCTION__, " ", typeof(dec).stringof); // Log.trace(__FUNCTION__, " ", typeof(dec).stringof);
currentSymbol.aliasThis ~= stringCache.intern(dec.identifier.text); currentSymbol.aliasThis.insert(stringCache.intern(dec.identifier.text));
} }
override void visit(const Declaration dec) override void visit(const Declaration dec)
@ -253,23 +263,24 @@ final class FirstPass : ASTVisitor
{ {
// Log.trace(__FUNCTION__, " ", typeof(mod).stringof); // Log.trace(__FUNCTION__, " ", typeof(mod).stringof);
// //
currentSymbol = new SemanticSymbol(null, CompletionKind.moduleName, currentSymbol = allocateSemanticSymbol(null, CompletionKind.moduleName,
symbolFile); symbolFile);
rootSymbol = currentSymbol; rootSymbol = currentSymbol;
currentScope = new Scope(0, size_t.max); currentScope = allocate!Scope(semanticAllocator, 0, size_t.max);
ImportInformation i; auto i = allocate!ImportInformation(semanticAllocator);
i.modulePath = "object"; i.modulePath = "object";
i.importParts ~= "object"; i.importParts.insert("object");
currentScope.importInformation ~= i; currentScope.importInformation.insert(i);
moduleScope = currentScope; moduleScope = currentScope;
mod.accept(this); mod.accept(this);
assert (currentSymbol.acSymbol.name is null);
} }
override void visit(const EnumDeclaration dec) override void visit(const EnumDeclaration dec)
{ {
assert (currentSymbol); assert (currentSymbol);
// Log.trace(__FUNCTION__, " ", typeof(dec).stringof); // Log.trace(__FUNCTION__, " ", typeof(dec).stringof);
SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(dec.name.text), SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text,
CompletionKind.enumName, symbolFile, dec.name.index, dec.type); CompletionKind.enumName, symbolFile, dec.name.index, dec.type);
symbol.parent = currentSymbol; symbol.parent = currentSymbol;
symbol.acSymbol.doc = dec.comment; symbol.acSymbol.doc = dec.comment;
@ -283,7 +294,7 @@ final class FirstPass : ASTVisitor
override void visit(const EnumMember member) override void visit(const EnumMember member)
{ {
// Log.trace(__FUNCTION__, " ", typeof(member).stringof); // Log.trace(__FUNCTION__, " ", typeof(member).stringof);
SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(member.name.text), SemanticSymbol* symbol = allocateSemanticSymbol(member.name.text,
CompletionKind.enumMember, symbolFile, member.name.index, member.type); CompletionKind.enumMember, symbolFile, member.name.index, member.type);
symbol.parent = currentSymbol; symbol.parent = currentSymbol;
symbol.acSymbol.doc = member.comment; symbol.acSymbol.doc = member.comment;
@ -295,72 +306,75 @@ final class FirstPass : ASTVisitor
// Log.trace(__FUNCTION__, " ", typeof(dec).stringof); // Log.trace(__FUNCTION__, " ", typeof(dec).stringof);
foreach (identifier; moduleDeclaration.moduleName.identifiers) foreach (identifier; moduleDeclaration.moduleName.identifiers)
{ {
moduleName ~= stringCache.intern(identifier.text); moduleName.insert(stringCache.intern(identifier.text));
} }
} }
// creates scopes for
override void visit(const StructBody structBody) override void visit(const StructBody structBody)
{ {
// Log.trace(__FUNCTION__, " ", typeof(structBody).stringof); // Log.trace(__FUNCTION__, " ", typeof(structBody).stringof);
Scope* s = new Scope(structBody.startLocation, structBody.endLocation); Scope* s = allocate!Scope(semanticAllocator, structBody.startLocation, structBody.endLocation);
// Log.trace("Added scope ", s.startLocation, " ", s.endLocation); // Log.trace("Added scope ", s.startLocation, " ", s.endLocation);
ACSymbol* thisSymbol = new ACSymbol("this", CompletionKind.variableName, ACSymbol* thisSymbol = allocate!ACSymbol(symbolAllocator, "this",
currentSymbol.acSymbol); CompletionKind.variableName, currentSymbol.acSymbol);
thisSymbol.location = s.startLocation; thisSymbol.location = s.startLocation;
thisSymbol.symbolFile = symbolFile; thisSymbol.symbolFile = symbolFile;
currentSymbol.acSymbol.parts.insert(thisSymbol); s.symbols.insert(thisSymbol);
s.parent = currentScope; s.parent = currentScope;
currentScope = s; currentScope = s;
foreach (dec; structBody.declarations) foreach (dec; structBody.declarations)
visit(dec); visit(dec);
currentScope = s.parent; currentScope = s.parent;
currentScope.children ~= s; currentScope.children.insert(s);
} }
override void visit(const ImportDeclaration importDeclaration) override void visit(const ImportDeclaration importDeclaration)
{ {
import std.typecons; import std.typecons;
import std.algorithm; import std.algorithm;
import std.array;
// Log.trace(__FUNCTION__, " ImportDeclaration"); // Log.trace(__FUNCTION__, " ImportDeclaration");
foreach (single; importDeclaration.singleImports.filter!( foreach (single; importDeclaration.singleImports.filter!(
a => a !is null && a.identifierChain !is null)) a => a !is null && a.identifierChain !is null))
{ {
ImportInformation info; auto info = allocate!ImportInformation(semanticAllocator);
info.importParts = single.identifierChain.identifiers.map!(a => stringCache.intern(a.text)).array; foreach (identifier; single.identifierChain.identifiers)
info.modulePath = convertChainToImportPath(single.identifierChain); info.importParts.insert(stringCache.intern(identifier.text));
info.modulePath = convertChainToImportPath(stringCache, single.identifierChain);
info.isPublic = protection == tok!"public"; info.isPublic = protection == tok!"public";
currentScope.importInformation ~= info; currentScope.importInformation.insert(info);
} }
if (importDeclaration.importBindings is null) return; if (importDeclaration.importBindings is null) return;
if (importDeclaration.importBindings.singleImport.identifierChain is null) return; if (importDeclaration.importBindings.singleImport.identifierChain is null) return;
ImportInformation info; auto info = allocate!ImportInformation(semanticAllocator);
info.modulePath = convertChainToImportPath(
info.modulePath = convertChainToImportPath(stringCache,
importDeclaration.importBindings.singleImport.identifierChain); importDeclaration.importBindings.singleImport.identifierChain);
info.importParts = importDeclaration.importBindings.singleImport foreach (identifier; importDeclaration.importBindings.singleImport
.identifierChain.identifiers.map!(a => stringCache.intern(a.text)).array; .identifierChain.identifiers)
{
info.importParts.insert(stringCache.intern(identifier.text));
}
foreach (bind; importDeclaration.importBindings.importBinds) foreach (bind; importDeclaration.importBindings.importBinds)
{ {
Tuple!(string, string) bindTuple; Tuple!(string, string) bindTuple;
bindTuple[0] = stringCache.intern(bind.left.text); bindTuple[0] = stringCache.intern(bind.left.text);
bindTuple[1] = bind.right == tok!"" ? null : stringCache.intern(bind.right.text); bindTuple[1] = bind.right == tok!"" ? null : stringCache.intern(bind.right.text);
info.importedSymbols ~= bindTuple; info.importedSymbols.insert(bindTuple);
} }
info.isPublic = protection == tok!"public"; info.isPublic = protection == tok!"public";
currentScope.importInformation ~= info; currentScope.importInformation.insert(info);
} }
// Create scope for block statements // Create scope for block statements
override void visit(const BlockStatement blockStatement) override void visit(const BlockStatement blockStatement)
{ {
// Log.trace(__FUNCTION__, " ", typeof(blockStatement).stringof); // Log.trace(__FUNCTION__, " ", typeof(blockStatement).stringof);
Scope* s = new Scope(blockStatement.startLocation, Scope* s = allocate!Scope(semanticAllocator, blockStatement.startLocation,
blockStatement.endLocation); blockStatement.endLocation);
s.parent = currentScope; s.parent = currentScope;
currentScope.children ~= s; currentScope.children.insert(s);
if (currentSymbol.acSymbol.kind == CompletionKind.functionName) if (currentSymbol.acSymbol.kind == CompletionKind.functionName)
{ {
@ -400,12 +414,16 @@ final class FirstPass : ASTVisitor
shared(StringCache)* stringCache; shared(StringCache)* stringCache;
CAllocator symbolAllocator;
uint symbolsAllocated;
private: private:
void visitAggregateDeclaration(AggType)(AggType dec, CompletionKind kind) void visitAggregateDeclaration(AggType)(AggType dec, CompletionKind kind)
{ {
// Log.trace("visiting aggregate declaration ", dec.name.text); // Log.trace("visiting aggregate declaration ", dec.name.text);
SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(dec.name.text), SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text,
kind, symbolFile, dec.name.index); kind, symbolFile, dec.name.index);
if (kind == CompletionKind.className) if (kind == CompletionKind.className)
symbol.acSymbol.parts.insert(classSymbols[]); symbol.acSymbol.parts.insert(classSymbols[]);
@ -423,7 +441,7 @@ private:
void visitConstructor(size_t location, const Parameters parameters, void visitConstructor(size_t location, const Parameters parameters,
const FunctionBody functionBody, string doc) const FunctionBody functionBody, string doc)
{ {
SemanticSymbol* symbol = new SemanticSymbol("*constructor*", SemanticSymbol* symbol = allocateSemanticSymbol("*constructor*",
CompletionKind.functionName, symbolFile, location); CompletionKind.functionName, symbolFile, location);
processParameters(symbol, null, "this", parameters, doc); processParameters(symbol, null, "this", parameters, doc);
symbol.protection = protection; symbol.protection = protection;
@ -440,7 +458,7 @@ private:
void visitDestructor(size_t location, const FunctionBody functionBody, string doc) void visitDestructor(size_t location, const FunctionBody functionBody, string doc)
{ {
SemanticSymbol* symbol = new SemanticSymbol("~this", SemanticSymbol* symbol = allocateSemanticSymbol("~this",
CompletionKind.functionName, symbolFile, location); CompletionKind.functionName, symbolFile, location);
symbol.acSymbol.callTip = "~this()"; symbol.acSymbol.callTip = "~this()";
symbol.protection = protection; symbol.protection = protection;
@ -462,21 +480,20 @@ private:
{ {
foreach (const Parameter p; parameters.parameters) foreach (const Parameter p; parameters.parameters)
{ {
SemanticSymbol* parameter = new SemanticSymbol( SemanticSymbol* parameter = allocateSemanticSymbol(
stringCache.intern(p.name.text), p.name.text, CompletionKind.variableName, symbolFile,
CompletionKind.variableName, symbolFile, size_t.max, size_t.max, p.type);
p.type);
symbol.addChild(parameter); symbol.addChild(parameter);
parameter.parent = symbol; parameter.parent = symbol;
} }
if (parameters.hasVarargs) if (parameters.hasVarargs)
{ {
SemanticSymbol* argptr = new SemanticSymbol("_argptr", SemanticSymbol* argptr = allocateSemanticSymbol("_argptr",
CompletionKind.variableName, null, size_t.max, argptrType); CompletionKind.variableName, null, size_t.max, argptrType);
argptr.parent = symbol; argptr.parent = symbol;
symbol.addChild(argptr); symbol.addChild(argptr);
SemanticSymbol* arguments = new SemanticSymbol("_arguments", SemanticSymbol* arguments = allocateSemanticSymbol("_arguments",
CompletionKind.variableName, null, size_t.max, argumentsType); CompletionKind.variableName, null, size_t.max, argumentsType);
arguments.parent = symbol; arguments.parent = symbol;
symbol.addChild(arguments); symbol.addChild(arguments);
@ -486,22 +503,46 @@ private:
parameters, doc); parameters, doc);
} }
static string formatCallTip(const Type returnType, string name, string formatCallTip(const Type returnType, string name,
const Parameters parameters, string doc = null) const Parameters parameters, string doc = null)
{ {
import std.string; QuickAllocator!1024 q;
string parameterString = parameters is null ? "()" auto app = Appender!(char, typeof(q), 1024)(q);
: formatNode(parameters); scope(exit) q.deallocate(app.mem);
if (returnType is null) if (returnType !is null)
return "%s%s".format(name, parameterString); {
return "%s %s%s".format(formatNode(returnType), name, parameterString); app.formatNode(returnType);
app.put(' ');
}
app.put(name);
if (parameters is null)
app.put("()");
else
app.formatNode(parameters);
return stringCache.intern(cast(ubyte[]) app[]);
}
SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind,
string symbolFile, size_t location = 0, const Type type = null)
in
{
assert (symbolAllocator !is null);
}
body
{
ACSymbol* acSymbol = allocate!ACSymbol(symbolAllocator,
name is null ? name : stringCache.intern(name), kind);
acSymbol.location = location;
acSymbol.symbolFile = symbolFile;
symbolsAllocated++;
return allocate!SemanticSymbol(semanticAllocator, acSymbol, type);
} }
/// Current protection type /// Current protection type
IdType protection; IdType protection;
/// Package and module name /// Package and module name
string[] moduleName; UnrolledList!string moduleName;
/// Current scope /// Current scope
Scope* currentScope; Scope* currentScope;
@ -513,41 +554,47 @@ private:
string symbolFile; string symbolFile;
Module mod; Module mod;
CAllocator semanticAllocator;
} }
string formatNode(T)(const T node) void formatNode(A, T)(ref A appender, const T node)
{ {
import formatter; if (node is null)
import std.array; return;
import std.conv; auto f = scoped!(Formatter!(A*))(&appender);
if (node is null) return "";
auto app = appender!(char[])();
auto f = new Formatter!(typeof(app))(app);
f.format(node); f.format(node);
return to!string(app.data);
} }
private: private:
string[] iotcToStringArray(const IdentifierOrTemplateChain iotc, string[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc,
shared(StringCache)* stringCache) shared(StringCache)* stringCache)
{ {
string[] parts; string[] retVal = cast(string[]) allocator.allocate((string[]).sizeof
foreach (ioti; iotc.identifiersOrTemplateInstances) * iotc.identifiersOrTemplateInstances.length);
foreach (i, ioti; iotc.identifiersOrTemplateInstances)
{ {
if (ioti.identifier != tok!"") if (ioti.identifier != tok!"")
parts ~= stringCache.intern(ioti.identifier.text); retVal[i] = stringCache.intern(ioti.identifier.text);
else else
parts ~= stringCache.intern(ioti.templateInstance.identifier.text); retVal[i] = stringCache.intern(ioti.templateInstance.identifier.text);
} }
return parts; return retVal;
} }
private static string convertChainToImportPath(const IdentifierChain ic) static string convertChainToImportPath(shared(StringCache)* stringCache,
const IdentifierChain ic)
{ {
import std.conv;
import std.algorithm;
import std.range;
import std.path; import std.path;
return to!string(ic.identifiers.map!(a => cast() a.text).join(dirSeparator).array); QuickAllocator!1024 q;
auto app = Appender!(char, typeof(q), 1024)(q);
scope(exit) q.deallocate(app.mem);
foreach (i, ident; ic.identifiers)
{
app.append(ident.text);
if (i + 1 < ic.identifiers.length)
app.append(dirSeparator);
}
return stringCache.intern(cast(string) app[]);
} }

View File

@ -22,7 +22,9 @@ import conversion.first;
import actypes; import actypes;
import semantic; import semantic;
import messages; import messages;
import stdx.lexer : StringCache; import std.lexer : StringCache;
import std.allocator;
import stupidlog;
/** /**
* Second pass handles the following: * Second pass handles the following:
@ -35,11 +37,12 @@ struct SecondPass
{ {
public: public:
this(ref FirstPass first) this(FirstPass first)
{ {
this.rootSymbol = first.rootSymbol; this.rootSymbol = first.rootSymbol;
this.moduleScope = first.moduleScope; this.moduleScope = first.moduleScope;
this.stringCache = first.stringCache; this.stringCache = first.stringCache;
this.symbolAllocator = first.symbolAllocator;
} }
void run() void run()
@ -48,6 +51,7 @@ public:
resolveImports(moduleScope); resolveImports(moduleScope);
} }
CAllocator symbolAllocator;
SemanticSymbol* rootSymbol; SemanticSymbol* rootSymbol;
Scope* moduleScope; Scope* moduleScope;
shared(StringCache)* stringCache; shared(StringCache)* stringCache;
@ -57,45 +61,74 @@ private:
void assignToScopes(ACSymbol* currentSymbol) void assignToScopes(ACSymbol* currentSymbol)
{ {
Scope* s = moduleScope.getScopeByCursor(currentSymbol.location); Scope* s = moduleScope.getScopeByCursor(currentSymbol.location);
if (currentSymbol.kind != CompletionKind.moduleName)
s.symbols.insert(currentSymbol); s.symbols.insert(currentSymbol);
foreach (part; currentSymbol.parts[]) foreach (part; currentSymbol.parts[])
{
std.utf.validate(part.name);
assignToScopes(part); assignToScopes(part);
} }
}
// This method is really ugly due to the casts... ACSymbol* createImportSymbols(ImportInformation* info, Scope* currentScope,
static ACSymbol* createImportSymbols(ImportInformation info, ACSymbol*[] moduleSymbols)
Scope* currentScope, ACSymbol*[] moduleSymbols) in
{ {
immutable string firstPart = info.importParts[0]; assert (info !is null);
foreach (s; moduleSymbols)
assert (s !is null);
}
body
{
immutable string firstPart = info.importParts[].front;
// Log.trace("firstPart = ", firstPart);
ACSymbol*[] symbols = currentScope.getSymbolsByName(firstPart); ACSymbol*[] symbols = currentScope.getSymbolsByName(firstPart);
immutable bool found = symbols.length > 0; immutable bool found = symbols.length > 0;
ACSymbol* firstSymbol = found ACSymbol* firstSymbol = found
? symbols[0] : new ACSymbol(firstPart, CompletionKind.packageName); ? symbols[0] : allocate!ACSymbol(symbolAllocator, firstPart,
CompletionKind.packageName);
if (!found) if (!found)
{
currentScope.symbols.insert(firstSymbol); currentScope.symbols.insert(firstSymbol);
} // Log.trace(firstSymbol.name);
ACSymbol* currentSymbol = cast(ACSymbol*) firstSymbol; ACSymbol* currentSymbol = firstSymbol;
foreach (size_t i, string importPart; info.importParts[1 .. $]) size_t i = 0;
foreach (string importPart; info.importParts[])
{ {
if (i++ == 0)
continue;
symbols = currentSymbol.getPartsByName(importPart); symbols = currentSymbol.getPartsByName(importPart);
ACSymbol* s = symbols.length > 0 ACSymbol* s = symbols.length > 0
? cast(ACSymbol*) symbols[0] : new ACSymbol(importPart, CompletionKind.packageName); ? cast(ACSymbol*) symbols[0] : allocate!ACSymbol(symbolAllocator,
importPart, CompletionKind.packageName);
currentSymbol.parts.insert(s); currentSymbol.parts.insert(s);
currentSymbol = s; currentSymbol = s;
} }
currentSymbol.kind = CompletionKind.moduleName; currentSymbol.kind = CompletionKind.moduleName;
currentSymbol.parts.insert(moduleSymbols); currentSymbol.parts.insert(moduleSymbols);
// Log.trace(currentSymbol.name);
return currentSymbol; return currentSymbol;
} }
void resolveImports(Scope* currentScope) void resolveImports(Scope* currentScope)
{ {
import modulecache; import modulecache;
foreach (importInfo; currentScope.importInformation) import std.stdio;
foreach (importInfo; currentScope.importInformation[])
{ {
string location = ModuleCache.resolveImportLoctation(importInfo.modulePath); string location = ModuleCache.resolveImportLoctation(importInfo.modulePath);
ACSymbol*[] symbols = location is null ? [] : ModuleCache.getSymbolsInModule(location); ACSymbol*[] symbols = location is null ? [] : ModuleCache.getSymbolsInModule(location);
//////
foreach (s; symbols)
{
try
std.utf.validate(s.name);
catch (Exception e)
{
writeln("Symbols in ", importInfo.modulePath, " are corrupted");
throw e;
}
}
//////
ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbols); ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbols);
currentScope.symbols.insert(moduleSymbol); currentScope.symbols.insert(moduleSymbol);
currentScope.symbols.insert(symbols); currentScope.symbols.insert(symbols);
@ -109,16 +142,16 @@ private:
} }
symbolLoop: foreach (symbol; symbols) symbolLoop: foreach (symbol; symbols)
{ {
foreach (tup; importInfo.importedSymbols) foreach (tup; importInfo.importedSymbols[])
{ {
if (tup[0] != symbol.name) if (tup[0] != symbol.name)
continue symbolLoop; continue symbolLoop;
if (tup[1] !is null) if (tup[1] !is null)
{ {
ACSymbol* s = new ACSymbol(tup[1], ACSymbol* s = allocate!ACSymbol(symbolAllocator, tup[1],
symbol.kind, symbol.type); symbol.kind, symbol.type);
// TODO: Compiler gets confused here, so cast the types. // TODO: Compiler gets confused here, so cast the types.
s.parts = cast(typeof(s.parts)) symbol.parts; s.parts.insert(symbol.parts[]);
// TODO: Re-format callTip with new name? // TODO: Re-format callTip with new name?
s.callTip = symbol.callTip; s.callTip = symbol.callTip;
s.doc = symbol.doc; s.doc = symbol.doc;

View File

@ -18,13 +18,13 @@
module conversion.third; module conversion.third;
import stdx.d.ast; import std.d.ast;
import stdx.d.lexer; import std.d.lexer;
import conversion.second; import conversion.second;
import semantic; import semantic;
import actypes; import actypes;
import messages; import messages;
import std.allocator;
/** /**
* Third pass handles the following: * Third pass handles the following:
@ -45,6 +45,7 @@ public:
this.moduleScope = second.moduleScope; this.moduleScope = second.moduleScope;
this.stringCache = second.stringCache; this.stringCache = second.stringCache;
this.name = name; this.name = name;
this.symbolAllocator = second.symbolAllocator;
} }
string name; string name;
@ -56,6 +57,7 @@ public:
SemanticSymbol* rootSymbol; SemanticSymbol* rootSymbol;
Scope* moduleScope; Scope* moduleScope;
CAllocator symbolAllocator;
private: private:
@ -147,7 +149,11 @@ private:
else if (t.type2.symbol !is null) else if (t.type2.symbol !is null)
{ {
// TODO: global scoped symbol handling // TODO: global scoped symbol handling
string[] symbolParts = expandSymbol( string[] symbolParts = cast(string[]) Mallocator.it.allocate(
t.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances.length
* string.sizeof);
scope(exit) Mallocator.it.deallocate(symbolParts);
expandSymbol(symbolParts,
t.type2.symbol.identifierOrTemplateChain, stringCache, name); t.type2.symbol.identifierOrTemplateChain, stringCache, name);
auto symbols = moduleScope.getSymbolsByNameAndCursor( auto symbols = moduleScope.getSymbolsByNameAndCursor(
symbolParts[0], location); symbolParts[0], location);
@ -168,12 +174,9 @@ private:
return s; return s;
} }
static string[] expandSymbol(const IdentifierOrTemplateChain chain, static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain,
shared(StringCache)* stringCache, string n) shared(StringCache)* stringCache, string n)
{ {
if (chain.identifiersOrTemplateInstances.length == 0)
return [];
string[] strings = new string[chain.identifiersOrTemplateInstances.length];
for (size_t i = 0; i < chain.identifiersOrTemplateInstances.length; ++i) for (size_t i = 0; i < chain.identifiersOrTemplateInstances.length; ++i)
{ {
auto identOrTemplate = chain.identifiersOrTemplateInstances[i]; auto identOrTemplate = chain.identifiersOrTemplateInstances[i];
@ -183,21 +186,18 @@ private:
identOrTemplate.identifier.text identOrTemplate.identifier.text
: identOrTemplate.templateInstance.identifier.text); : identOrTemplate.templateInstance.identifier.text);
} }
return strings;
} }
static ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix) ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix)
{ {
import std.container;
import formatter; import formatter;
if (suffix.star) if (suffix.star)
return symbol; return symbol;
if (suffix.array || suffix.type) if (suffix.array || suffix.type)
{ {
ACSymbol* s = new ACSymbol(null); ACSymbol* s = allocate!ACSymbol(symbolAllocator, null);
s.parts = new RedBlackTree!(ACSymbol*, comparitor, true); s.parts.insert(suffix.array ? arraySymbols[]
s.parts.insert(suffix.array ? (cast() arraySymbols)[] : assocArraySymbols[]);
: (cast() assocArraySymbols)[]);
s.type = symbol; s.type = symbol;
s.qualifier = suffix.array ? SymbolQualifier.array : SymbolQualifier.assocArray; s.qualifier = suffix.array ? SymbolQualifier.array : SymbolQualifier.assocArray;
return s; return s;
@ -205,10 +205,17 @@ private:
if (suffix.parameters) if (suffix.parameters)
{ {
import conversion.first; import conversion.first;
ACSymbol* s = new ACSymbol(null); import memory.allocators;
import memory.appender;
ACSymbol* s = allocate!ACSymbol(symbolAllocator, null);
s.type = symbol; s.type = symbol;
s.qualifier = SymbolQualifier.func; s.qualifier = SymbolQualifier.func;
s.callTip = suffix.delegateOrFunction.text ~ formatNode(suffix.parameters); QuickAllocator!1024 q;
auto app = Appender!(char, typeof(q), 1024)(q);
scope(exit) q.deallocate(app.mem);
app.append(suffix.delegateOrFunction.text);
app.formatNode(suffix.parameters);
s.callTip = stringCache.intern(cast(ubyte[]) app[]);
return s; return s;
} }
return null; return null;
@ -219,9 +226,8 @@ private:
string stringRepresentation = str(type2.builtinType); string stringRepresentation = str(type2.builtinType);
if (stringRepresentation is null) return null; if (stringRepresentation is null) return null;
// TODO: Make this use binary search instead // TODO: Make this use binary search instead
auto t = cast() builtinSymbols;
ACSymbol s = ACSymbol(stringRepresentation); ACSymbol s = ACSymbol(stringRepresentation);
return t.equalRange(&s).front(); return builtinSymbols.equalRange(&s).front();
} }
shared(StringCache)* stringCache; shared(StringCache)* stringCache;

@ -1 +1 @@
Subproject commit 3ddac7885f373c0e5ce7ff1b2670d401d8d482d5 Subproject commit 017b90e31f2d8bdc0181fa3ac0d6a0e3be0d480e

View File

@ -18,41 +18,49 @@
module modulecache; module modulecache;
import std.file;
import std.datetime;
import stdx.lexer;
import stdx.d.lexer;
import stdx.d.parser;
import stdx.d.ast;
import std.array;
import std.path;
import std.algorithm; import std.algorithm;
import std.allocator;
import std.conv; import std.conv;
import std.container; import std.d.ast;
import std.datetime;
import std.d.lexer;
import std.d.parser;
import std.file;
import std.lexer;
import std.path;
import actypes; import actypes;
import semantic; import semantic;
import memory.allocators;
import containers.karytree;
import containers.hashset;
import containers.unrolledlist;
import conversion.astconverter; import conversion.astconverter;
import conversion.first; import conversion.first;
import conversion.second; import conversion.second;
import conversion.third; import conversion.third;
import containers.dynamicarray;
import stupidlog; import stupidlog;
import messages;
bool cacheComparitor(CacheEntry* a, CacheEntry* b) pure nothrow
{
return cast(ubyte[]) a.path < cast(ubyte[]) b.path;
}
private struct CacheEntry private struct CacheEntry
{ {
ACSymbol*[] symbols; ACSymbol*[] symbols;
SysTime modificationTime; SysTime modificationTime;
string path; string path;
int opCmp(ref const CacheEntry other) const
{
if (path < other.path)
return -1;
if (path > other.path)
return 1;
return 0;
}
void opAssign(ref const CacheEntry other) void opAssign(ref const CacheEntry other)
{ {
this.symbols = cast(typeof(symbols)) other.symbols; assert(false);
this.path = other.path;
this.modificationTime = other.modificationTime;
} }
} }
@ -66,8 +74,8 @@ bool existanceCheck(A)(A path)
static this() static this()
{ {
ModuleCache.cache = new RedBlackTree!(CacheEntry*, cacheComparitor);
ModuleCache.stringCache = new shared StringCache(StringCache.defaultBucketCount); ModuleCache.stringCache = new shared StringCache(StringCache.defaultBucketCount);
ModuleCache.symbolAllocator = new CAllocatorImpl!(BlockAllocator!(1024 * 16));
} }
/** /**
@ -77,12 +85,8 @@ struct ModuleCache
{ {
@disable this(); @disable this();
/**
* Clears the completion cache
*/
static void clear() static void clear()
{ {
cache.clear();
} }
/** /**
@ -91,15 +95,13 @@ struct ModuleCache
static void addImportPaths(string[] paths) static void addImportPaths(string[] paths)
{ {
import core.memory; import core.memory;
string[] addedPaths = paths.filter!(a => existanceCheck(a)).array(); foreach (path; paths.filter!(a => existanceCheck(a)))
importPaths ~= addedPaths; importPaths.insert(path);
foreach (path; addedPaths) foreach (path; importPaths[])
{ {
foreach (fileName; dirEntries(path, "*.{d,di}", SpanMode.depth)) foreach (fileName; dirEntries(path, "*.{d,di}", SpanMode.depth))
{ {
GC.disable();
scope(exit) GC.enable();
getSymbolsInModule(fileName); getSymbolsInModule(fileName);
} }
} }
@ -126,29 +128,35 @@ struct ModuleCache
Log.info("Getting symbols for ", location); Log.info("Getting symbols for ", location);
recursionGuard[location] = true; recursionGuard.insert(location);
ACSymbol*[] symbols; ACSymbol*[] symbols;
try // try
{ // {
import core.memory; import core.memory;
import std.stdio; import std.stdio;
import std.typecons;
File f = File(location); File f = File(location);
ubyte[] source = (cast(ubyte*) GC.malloc(cast(size_t) f.size, ubyte[] source = cast(ubyte[]) Mallocator.it.allocate(cast(size_t)f.size);
GC.BlkAttr.NO_SCAN | GC.BlkAttr.NO_MOVE))[0 .. cast(size_t)f.size];
f.rawRead(source); f.rawRead(source);
LexerConfig config; LexerConfig config;
config.fileName = location; config.fileName = location;
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount); shared parseStringCache = shared StringCache(StringCache.defaultBucketCount);
auto tokens = source.byToken(config, cache).array(); auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 64)));
source[] = 0; DynamicArray!(Token, false) tokens;
GC.free(source.ptr); auto tokenRange = byToken(
ParseAllocator p = new ParseAllocator(location); (source.length >= 3 && source[0 .. 3] == "\xef\xbb\xbf"c) ? source[3 .. $] : source,
Module m = parseModuleSimple(tokens, location, p); config, &parseStringCache);
foreach (t; tokenRange)
tokens.insert(t);
Mallocator.it.deallocate(source);
FirstPass first = new FirstPass(m, location, stringCache); Module m = parseModuleSimple(tokens[], location, semanticAllocator);
assert (symbolAllocator);
auto first = scoped!FirstPass(m, location, stringCache,
symbolAllocator, semanticAllocator);
first.run(); first.run();
cache = null;
SecondPass second = SecondPass(first); SecondPass second = SecondPass(first);
second.run(); second.run();
@ -156,21 +164,28 @@ struct ModuleCache
ThirdPass third = ThirdPass(second, location); ThirdPass third = ThirdPass(second, location);
third.run(); third.run();
p.deallocateAll(); symbols = cast(ACSymbol*[]) Mallocator.it.allocate(
p = null; third.rootSymbol.acSymbol.parts.length * (ACSymbol*).sizeof);
symbols = third.rootSymbol.acSymbol.parts.array(); size_t i = 0;
} foreach (part; third.rootSymbol.acSymbol.parts[])
catch (Exception ex) symbols[i++] = part;
{
Log.error("Couln't parse ", location, " due to exception: ", ex.msg); typeid(Scope).destroy(third.moduleScope);
return []; typeid(SemanticSymbol).destroy(third.rootSymbol);
} symbolsAllocated += first.symbolsAllocated;
// }
// catch (Exception ex)
// {
// Log.error("Couln't parse ", location, " due to exception: ", ex.msg);
// return [];
// }
SysTime access; SysTime access;
SysTime modification; SysTime modification;
getTimes(location, access, modification); getTimes(location, access, modification);
CacheEntry* c = new CacheEntry(symbols, modification, location); CacheEntry* c = allocate!CacheEntry(Mallocator.it, symbols,
modification, stringCache.intern(location));
cache.insert(c); cache.insert(c);
recursionGuard[location] = false; recursionGuard.remove(location);
return symbols; return symbols;
} }
@ -188,39 +203,37 @@ struct ModuleCache
string[] alternatives; string[] alternatives;
foreach (path; importPaths) foreach (path; importPaths)
{ {
string filePath = buildPath(path, moduleName); string dotDi = buildPath(path, moduleName) ~ ".di";
if (exists(filePath ~ ".d") && isFile(filePath ~ ".d")) string dotD = dotDi[0 .. $ - 1];
alternatives = (filePath ~ ".d") ~ alternatives; string withoutSuffix = dotDi[0 .. $ - 2];
else if (exists(filePath ~ ".di") && isFile(filePath ~ ".di")) if (exists(dotD) && isFile(dotD))
alternatives = (filePath ~ ".di") ~ alternatives; alternatives = (dotD) ~ alternatives;
else if (exists(filePath) && isDir(filePath)) else if (exists(dotDi) && isFile(dotDi))
alternatives ~= dotDi;
else if (exists(withoutSuffix) && isDir(withoutSuffix))
{ {
string packagePath = buildPath(filePath, "package.d"); string packagePath = buildPath(withoutSuffix, "package.di");
if (exists(packagePath) && isFile(packagePath)) if (exists(packagePath) && isFile(packagePath))
{ {
alternatives ~= packagePath; alternatives ~= packagePath;
continue; continue;
} }
packagePath ~= "i"; if (exists(packagePath[0 .. $ - 1]) && isFile(packagePath[0 .. $ - 1]))
if (exists(packagePath) && isFile(packagePath)) alternatives ~= packagePath[0 .. $ - 1];
alternatives ~= packagePath;
} }
} }
return alternatives.length > 0 ? alternatives[0] : null; return alternatives.length > 0 ? alternatives[0] : null;
} }
static const(string[]) getImportPaths() static auto getImportPaths()
{ {
return cast(const(string[])) importPaths; return importPaths[];
}
static string intern(string s)
{
return s is null || s.length == 0 ? "" : stringCache.intern(s);
} }
static shared(StringCache)* stringCache; static shared(StringCache)* stringCache;
static uint symbolsAllocated;
private: private:
/** /**
@ -231,9 +244,7 @@ private:
*/ */
static bool needsReparsing(string mod) static bool needsReparsing(string mod)
{ {
if (mod !in recursionGuard) if (recursionGuard.contains(mod))
return true;
if (recursionGuard[mod])
return false; return false;
if (!exists(mod)) if (!exists(mod))
return true; return true;
@ -249,10 +260,12 @@ private:
} }
// Mapping of file paths to their cached symbols. // Mapping of file paths to their cached symbols.
static RedBlackTree!(CacheEntry*, cacheComparitor) cache; static KAryTree!(CacheEntry*) cache;
static bool[string] recursionGuard; static HashSet!string recursionGuard;
// Listing of paths to check for imports // Listing of paths to check for imports
static string[] importPaths; static UnrolledList!string importPaths;
static CAllocator symbolAllocator;
} }

View File

@ -20,9 +20,10 @@ module semantic;
import messages; import messages;
import actypes; import actypes;
import stdx.d.ast; import std.d.ast;
import stdx.d.lexer; import std.d.lexer;
import stupidlog; import stupidlog;
import containers.unrolledlist;
/** /**
* Intermediate form between ACSymbol and the AST classes. Stores enough * Intermediate form between ACSymbol and the AST classes. Stores enough
@ -33,6 +34,7 @@ struct SemanticSymbol
public: public:
@disable this(); @disable this();
@disable this(this);
/** /**
* Params: * Params:
@ -41,21 +43,24 @@ public:
* symbolFile = the file name for this symbol * symbolFile = the file name for this symbol
* location = the location of this symbol * location = the location of this symbol
*/ */
this(string name, CompletionKind kind, string symbolFile, this(ACSymbol* acSymbol, const Type type = null)
size_t location = size_t.max, const Type type = null)
{ {
acSymbol = new ACSymbol(name, kind); this.acSymbol = acSymbol;
acSymbol.location = location;
acSymbol.symbolFile = symbolFile;
this.type = type; this.type = type;
} }
~this()
{
foreach (child; children[])
typeid(typeof(*child)).destroy(child);
}
/** /**
* Adds a child to the children field and updates the acSymbol's parts field * Adds a child to the children field and updates the acSymbol's parts field
*/ */
void addChild(SemanticSymbol* child) void addChild(SemanticSymbol* child)
{ {
children ~= child; children.insert(child);
acSymbol.parts.insert(child.acSymbol); acSymbol.parts.insert(child.acSymbol);
} }
@ -63,16 +68,16 @@ public:
ACSymbol* acSymbol; ACSymbol* acSymbol;
/// Base classes /// Base classes
string[][] baseClasses; UnrolledList!(string[]) baseClasses;
/// Variable type or function return type /// Variable type or function return type
const Type type; const Type type;
/// Alias this symbols /// Alias this symbols
string[] aliasThis; UnrolledList!(string) aliasThis;
/// MixinTemplates /// MixinTemplates
string[] mixinTemplates; UnrolledList!(string) mixinTemplates;
/// Protection level for this symobol /// Protection level for this symobol
IdType protection; IdType protection;
@ -81,7 +86,7 @@ public:
SemanticSymbol* parent; SemanticSymbol* parent;
/// Child symbols /// Child symbols
SemanticSymbol*[] children; UnrolledList!(SemanticSymbol*) children;
} }
/** /**
@ -96,25 +101,29 @@ Type argumentsType;
static this() static this()
{ {
import std.allocator;
// _argptr has type void* // _argptr has type void*
argptrType = new Type; argptrType = allocate!Type(Mallocator.it);
argptrType.type2 = new Type2; argptrType.type2 = allocate!Type2(Mallocator.it);
argptrType.type2.builtinType = tok!"void"; argptrType.type2.builtinType = tok!"void";
TypeSuffix argptrTypeSuffix = new TypeSuffix; TypeSuffix argptrTypeSuffix = allocate!TypeSuffix(Mallocator.it);
argptrTypeSuffix.star = true; argptrTypeSuffix.star = true;
argptrType.typeSuffixes ~= argptrTypeSuffix; argptrType.typeSuffixes = cast(TypeSuffix[]) Mallocator.it.allocate(TypeSuffix.sizeof);
argptrType.typeSuffixes[0] = argptrTypeSuffix;
// _arguments has type TypeInfo[] // _arguments has type TypeInfo[]
argumentsType = new Type; argumentsType = allocate!Type(Mallocator.it);
argumentsType = new Type; argumentsType.type2 = allocate!Type2(Mallocator.it);
argumentsType.type2 = new Type2; argumentsType.type2.symbol = allocate!Symbol(Mallocator.it);
argumentsType.type2.symbol = new Symbol; argumentsType.type2.symbol.identifierOrTemplateChain = allocate!IdentifierOrTemplateChain(Mallocator.it);
argumentsType.type2.symbol.identifierOrTemplateChain = new IdentifierOrTemplateChain; IdentifierOrTemplateInstance i = allocate!IdentifierOrTemplateInstance(Mallocator.it);
IdentifierOrTemplateInstance i = new IdentifierOrTemplateInstance;
i.identifier.text = "TypeInfo"; i.identifier.text = "TypeInfo";
i.identifier.type = tok!"identifier"; i.identifier.type = tok!"identifier";
argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances ~= i; argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances =
TypeSuffix argumentsTypeSuffix = new TypeSuffix; cast(IdentifierOrTemplateInstance[]) Mallocator.it.allocate(IdentifierOrTemplateInstance.sizeof);
argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances[0] = i;
TypeSuffix argumentsTypeSuffix = allocate!TypeSuffix(Mallocator.it);
argumentsTypeSuffix.array = true; argumentsTypeSuffix.array = true;
argumentsType.typeSuffixes ~= argptrTypeSuffix; argumentsType.typeSuffixes = cast(TypeSuffix[]) Mallocator.it.allocate(TypeSuffix.sizeof);
argumentsType.typeSuffixes[0] = argptrTypeSuffix;
} }

View File

@ -28,6 +28,9 @@ import std.array;
import std.process; import std.process;
import std.datetime; import std.datetime;
import std.conv; import std.conv;
import std.allocator;
import core.memory;
import msgpack; import msgpack;
@ -92,12 +95,16 @@ int main(string[] args)
ModuleCache.addImportPaths(importPaths); ModuleCache.addImportPaths(importPaths);
Log.info("Import directories: ", ModuleCache.getImportPaths()); Log.info("Import directories: ", ModuleCache.getImportPaths());
ubyte[] buffer = new ubyte[1024 * 1024 * 4]; // 4 megabytes should be enough for anybody... ubyte[] buffer = cast(ubyte[]) Mallocator.it.allocate(1024 * 1024 * 4); // 4 megabytes should be enough for anybody...
scope(exit) Mallocator.it.deallocate(buffer);
sw.stop(); sw.stop();
Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds"); Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds");
float internBytes = cast(float) ModuleCache.stringCache.allocated / (1024 * 1024); float internBytes = cast(float) ModuleCache.stringCache.allocated / (1024 * 1024);
Log.info("String interning took up ", internBytes, " megabytes"); Log.info("String interning took up ", internBytes, " megabytes");
float symbolMegs = (cast(float) (ACSymbol.sizeof * ModuleCache.symbolsAllocated)) / (1024f * 1024f);
Log.info(ModuleCache.symbolsAllocated, " symbols allocated, taking up ",
symbolMegs, " megabytes");
// No relative paths // No relative paths
version (Posix) chdir("/"); version (Posix) chdir("/");
@ -153,17 +160,17 @@ int main(string[] args)
Log.info("Shutting down."); Log.info("Shutting down.");
break serverLoop; break serverLoop;
case RequestKind.autocomplete: case RequestKind.autocomplete:
try // try
{ // {
AutocompleteResponse response = complete(request); AutocompleteResponse response = complete(request);
ubyte[] responseBytes = msgpack.pack(response); ubyte[] responseBytes = msgpack.pack(response);
s.send(responseBytes); s.send(responseBytes);
} // }
catch (Exception e) // catch (Exception e)
{ // {
Log.error("Could not handle autocomplete request due to an exception:", // Log.error("Could not handle autocomplete request due to an exception:",
e.msg); // e.msg);
} // }
break; break;
case RequestKind.doc: case RequestKind.doc:
try try