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.stdio;
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;
/**
* 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.
*/
@ -67,7 +63,6 @@ public:
this(string name)
{
this.name = name;
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
}
/**
@ -79,7 +74,6 @@ public:
{
this.name = name;
this.kind = kind;
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
}
/**
@ -93,7 +87,15 @@ public:
this.name = name;
this.kind = kind;
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)
{
import std.range;
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,
* methods, etc.
*/
RedBlackTree!(ACSymbol*, comparitor, true) parts;
KAryTree!(ACSymbol*, true, "a < b", false) parts;
/**
* Symbol's name
@ -167,7 +168,14 @@ struct Scope
{
this.startLocation = begin;
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:
* 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 > endLocation) return null;
foreach (child; children)
foreach (child; children[])
{
auto childScope = child.getScopeByCursor(cursorPosition);
if (childScope !is null)
@ -196,20 +204,20 @@ struct Scope
* all symbols in the scope containing the cursor position, as well as
* the symbols in parent scopes of that scope.
*/
ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition) const
ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition)
{
auto s = getScopeByCursor(cursorPosition);
if (s is null)
return [];
auto symbols = s.symbols;
UnrolledList!(ACSymbol*) symbols;
symbols.insert(s.symbols[]);
Scope* sc = s.parent;
while (sc !is null)
{
foreach (sym; sc.symbols)
symbols.insert(sym);
symbols.insert(sc.symbols[]);
sc = sc.parent;
}
return symbols.array();
return array(symbols[]);
}
/**
@ -218,12 +226,16 @@ struct Scope
* Returns:
* all symbols in this scope or parent scopes with the given name
*/
ACSymbol*[] getSymbolsByName(string name) const
ACSymbol*[] getSymbolsByName(string name)
{
import std.range;
ACSymbol s = ACSymbol(name);
RedBlackTree!(ACSymbol*, comparitor, true) t = cast() symbols;
auto r = t.equalRange(&s).array();
auto r = array(symbols.equalRange(&s));
foreach (i; r)
{
import std.string;
assert (i.name == name, format("%s %s %d", i.name, name, r.length));
}
if (r.length > 0)
return cast(typeof(return)) r;
if (parent is null)
@ -239,7 +251,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(string name, size_t cursorPosition)
{
auto s = getScopeByCursor(cursorPosition);
if (s is null)
@ -248,13 +260,13 @@ struct Scope
}
/// Imports contained in this scope
ImportInformation[] importInformation;
UnrolledList!(ImportInformation*) importInformation;
/// The scope that contains this one
Scope* parent;
/// Child scopes
Scope*[] children;
UnrolledList!(Scope*, false) children;
/// Start location of this scope in bytes
size_t startLocation;
@ -263,7 +275,7 @@ struct Scope
size_t endLocation;
/// 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
{
/// Import statement parts
string[] importParts;
UnrolledList!string importParts;
/// module relative path
string modulePath;
/// symbols to import from this module
Tuple!(string, string)[] importedSymbols;
UnrolledList!(Tuple!(string, string), false) importedSymbols;
/// true if the import is public
bool isPublic;
}
@ -285,91 +297,98 @@ struct ImportInformation
/**
* Symbols for the built in types
*/
RedBlackTree!(ACSymbol*, comparitor, true) builtinSymbols;
KAryTree!(ACSymbol*, true) builtinSymbols;
/**
* Array properties
*/
RedBlackTree!(ACSymbol*, comparitor, true) arraySymbols;
KAryTree!(ACSymbol*, true) arraySymbols;
/**
* Associative array properties
*/
RedBlackTree!(ACSymbol*, comparitor, true) assocArraySymbols;
KAryTree!(ACSymbol*, true) assocArraySymbols;
/**
* Enum, union, class, and interface properties
*/
RedBlackTree!(ACSymbol*, comparitor, true) aggregateSymbols;
KAryTree!(ACSymbol*, true) aggregateSymbols;
/**
* Class properties
*/
RedBlackTree!(ACSymbol*, comparitor, true) classSymbols;
KAryTree!(ACSymbol*, true) classSymbols;
/**
* Initializes builtin types and the various properties of builtin types
*/
static this()
{
auto bSym = new RedBlackTree!(ACSymbol*, comparitor, true);
auto arrSym = new RedBlackTree!(ACSymbol*, comparitor, true);
auto asarrSym = new RedBlackTree!(ACSymbol*, comparitor, true);
auto aggSym = new RedBlackTree!(ACSymbol*, comparitor, true);
auto clSym = new RedBlackTree!(ACSymbol*, comparitor, true);
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_ = new ACSymbol("bool", CompletionKind.keyword);
auto int_ = new ACSymbol("int", CompletionKind.keyword);
auto long_ = new ACSymbol("long", CompletionKind.keyword);
auto byte_ = new ACSymbol("byte", CompletionKind.keyword);
auto char_ = new ACSymbol("char", 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_ = 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_ = new ACSymbol("alignof", CompletionKind.keyword, ulong_);
auto mangleof_ = new ACSymbol("mangleof", CompletionKind.keyword);
auto sizeof_ = new ACSymbol("sizeof", CompletionKind.keyword, ulong_);
auto stringof_ = new ACSymbol("init", CompletionKind.keyword);
auto init = new ACSymbol("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(init);
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_);
arrSym.insert(new ACSymbol("dup", CompletionKind.keyword));
arrSym.insert(new ACSymbol("idup", CompletionKind.keyword));
arrSym.insert(init);
arrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_));
arrSym.insert(mangleof_);
arrSym.insert(new ACSymbol("ptr", CompletionKind.keyword));
arrSym.insert(new ACSymbol("reverse", CompletionKind.keyword));
arrSym.insert(sizeof_);
arrSym.insert(new ACSymbol("sort", CompletionKind.keyword));
arrSym.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(mangleof_);
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "rehash", CompletionKind.keyword));
assocArraySymbols.insert(sizeof_);
assocArraySymbols.insert(stringof_);
assocArraySymbols.insert(init);
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "values", CompletionKind.keyword));
asarrSym.insert(alignof_);
asarrSym.insert(new ACSymbol("byKey", CompletionKind.keyword));
asarrSym.insert(new ACSymbol("byValue", CompletionKind.keyword));
asarrSym.insert(new ACSymbol("dup", CompletionKind.keyword));
asarrSym.insert(new ACSymbol("get", CompletionKind.keyword));
asarrSym.insert(new ACSymbol("init", CompletionKind.keyword));
asarrSym.insert(new ACSymbol("keys", CompletionKind.keyword));
asarrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_));
asarrSym.insert(mangleof_);
asarrSym.insert(new ACSymbol("rehash", CompletionKind.keyword));
asarrSym.insert(sizeof_);
asarrSym.insert(stringof_);
asarrSym.insert(init);
asarrSym.insert(new ACSymbol("values", CompletionKind.keyword));
ACSymbol*[11] integralTypeArray;
integralTypeArray[0] = bool_;
integralTypeArray[1] = int_;
integralTypeArray[2] = long_;
integralTypeArray[3] = byte_;
integralTypeArray[4] = char_;
integralTypeArray[4] = dchar_;
integralTypeArray[5] = short_;
integralTypeArray[6] = ubyte_;
integralTypeArray[7] = uint_;
integralTypeArray[8] = ulong_;
integralTypeArray[9] = ushort_;
integralTypeArray[10] = wchar_;
foreach (s; [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_,
ulong_, ushort_, wchar_])
foreach (s; integralTypeArray)
{
s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s));
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(alignof_);
s.parts.insert(sizeof_);
s.parts.insert(stringof_);
@ -377,74 +396,101 @@ static this()
s.parts.insert(init);
}
auto cdouble_ = new ACSymbol("cdouble", CompletionKind.keyword);
auto cent_ = new ACSymbol("cent", CompletionKind.keyword);
auto cfloat_ = new ACSymbol("cfloat", CompletionKind.keyword);
auto creal_ = new ACSymbol("creal", CompletionKind.keyword);
auto double_ = new ACSymbol("double", CompletionKind.keyword);
auto float_ = new ACSymbol("float", CompletionKind.keyword);
auto idouble_ = new ACSymbol("idouble", CompletionKind.keyword);
auto ifloat_ = new ACSymbol("ifloat", CompletionKind.keyword);
auto ireal_ = new ACSymbol("ireal", CompletionKind.keyword);
auto real_ = new ACSymbol("real", CompletionKind.keyword);
auto ucent_ = new ACSymbol("ucent", CompletionKind.keyword);
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);
foreach (s; [cdouble_, cent_, cfloat_, creal_, double_, float_,
idouble_, ifloat_, ireal_, real_, ucent_])
ACSymbol*[11] floatTypeArray;
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(new ACSymbol("dig", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("epsilon", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("infinity", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s));
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(mangleof_);
s.parts.insert(new ACSymbol("mant_dig", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("max_10_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("max_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("min_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("min_10_exp", CompletionKind.keyword, int_));
s.parts.insert(new ACSymbol("min_normal", CompletionKind.keyword, s));
s.parts.insert(new ACSymbol("nan", CompletionKind.keyword, s));
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(sizeof_);
s.parts.insert(stringof_);
}
aggSym.insert(new ACSymbol("tupleof", CompletionKind.variableName));
aggSym.insert(mangleof_);
aggSym.insert(alignof_);
aggSym.insert(sizeof_);
aggSym.insert(stringof_);
aggSym.insert(init);
aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.variableName));
aggregateSymbols.insert(mangleof_);
aggregateSymbols.insert(alignof_);
aggregateSymbols.insert(sizeof_);
aggregateSymbols.insert(stringof_);
aggregateSymbols.insert(init);
clSym.insert(new ACSymbol("classInfo", CompletionKind.variableName));
clSym.insert(new ACSymbol("tupleof", CompletionKind.variableName));
clSym.insert(new ACSymbol("__vptr", CompletionKind.variableName));
clSym.insert(new ACSymbol("__monitor", CompletionKind.variableName));
clSym.insert(mangleof_);
clSym.insert(alignof_);
clSym.insert(sizeof_);
clSym.insert(stringof_);
clSym.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(mangleof_);
classSymbols.insert(alignof_);
classSymbols.insert(sizeof_);
classSymbols.insert(stringof_);
classSymbols.insert(init);
ireal_.parts.insert(new ACSymbol("im", CompletionKind.keyword, real_));
ifloat_.parts.insert(new ACSymbol("im", CompletionKind.keyword, float_));
idouble_.parts.insert(new ACSymbol("im", CompletionKind.keyword, double_));
ireal_.parts.insert(new ACSymbol("re", CompletionKind.keyword, real_));
ifloat_.parts.insert(new ACSymbol("re", CompletionKind.keyword, float_));
idouble_.parts.insert(new ACSymbol("re", CompletionKind.keyword, double_));
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_));
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_,
ulong_, ushort_, wchar_, cdouble_, cent_, cfloat_, creal_, double_,
float_, idouble_, ifloat_, ireal_, real_, ucent_, void_]);
builtinSymbols = bSym;
arraySymbols = arrSym;
assocArraySymbols = asarrSym;
aggregateSymbols = aggSym;
classSymbols = clSym;
builtinSymbols.insert(bool_);
builtinSymbols.insert(int_);
builtinSymbols.insert(long_);
builtinSymbols.insert(byte_);
builtinSymbols.insert(char_);
builtinSymbols.insert(dchar_);
builtinSymbols.insert(short_);
builtinSymbols.insert(ubyte_);
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.stdio;
import std.uni;
import stdx.d.ast;
import stdx.d.lexer;
import stdx.d.parser;
import std.d.ast;
import std.d.lexer;
import std.d.parser;
import std.string;
import std.typecons;
import memory.allocators;
import std.allocator;
import messages;
import actypes;
@ -49,7 +52,8 @@ AutocompleteResponse getDoc(const AutocompleteRequest request)
{
Log.trace("Getting doc comments");
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)
Log.error("Could not find symbol");
else foreach (symbol; symbols)
@ -76,7 +80,8 @@ AutocompleteResponse findDeclaration(const AutocompleteRequest request)
{
Log.trace("Finding declaration");
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)
{
response.symbolLocation = symbols[0].location;
@ -120,7 +125,7 @@ AutocompleteResponse complete(const AutocompleteRequest request)
tokenType = beforeTokens[$ - 2].type;
else
return response;
auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
switch (tokenType)
{
case tok!"stringLiteral":
@ -160,8 +165,11 @@ AutocompleteResponse complete(const AutocompleteRequest request)
case tok!")":
case tok!"]":
case tok!"this":
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);
response.setCompletions(completionScope, expression,
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.
*/
ACSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request,
const CompletionType type)
const CompletionType type, CAllocator allocator)
{
const(Token)[] tokenArray;
auto beforeTokens = getTokensBeforeCursor(request.sourceCode,
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);
return getSymbolsByTokenChain(completionScope, expression,
request.cursorPosition, type);
@ -232,6 +244,7 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
{
AutocompleteResponse response;
immutable(string)[] completions;
auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
switch (beforeTokens[$ - 2].type)
{
case tok!"__traits":
@ -259,8 +272,11 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
case tok!"identifier":
case tok!")":
case tok!"]":
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[0 .. $ - 1]);
response.setCompletions(completionScope, expression,
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)
{
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
ACSymbol*[] symbols = completionScope.getSymbolsByNameAndCursor(
tokens[0].text, cursorPosition);
stringToken(tokens[0]), cursorPosition);
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);
return [];
}
@ -437,7 +455,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope,
*
*/
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)
{
// 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()))
&& !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.completions ~= s.name;
}
@ -733,6 +751,11 @@ string formatComment(string comment)
.replaceAll(regex("\n"), `\n`).outdent();
}
string stringToken()(auto ref const Token a)
{
return a.text is null ? str(a.type) : a.text;
}
//unittest
//{
// 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 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 -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/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,12 +1,15 @@
dmd -wi client.d\
rm -f containers/src/std/allocator.d
dmd\
client.d\
messages.d\
stupidlog.d\
msgpack-d/src/msgpack.d\
-Imsgpack-d/src\
-release -inline -noboundscheck -O\
-release -inline -O -wi\
-ofdcd-client
dmd \
dmd\
actypes.d\
conversion/astconverter.d\
conversion/first.d\
@ -19,18 +22,26 @@ dmd \
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/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\
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\
-Icontainers/src\
-Imsgpack-d/src\
-Idscanner\
-wi -g\
-O -release -noboundscheck -inline\
-wi -O -release -inline\
-ofdcd-server
#gdc client.d\

View File

@ -185,7 +185,7 @@ Options:
Instructs the server to add PATH to its list of paths searced for
imported modules.
--port PORTNUMBER | -pPORTNUMBER
--port PORTNUMBER | -p PORTNUMBER
Uses PORTNUMBER to communicate with the server instead of the default
port 9166.`, programName);
}

View File

@ -177,113 +177,83 @@ immutable string[] versions = [
"X86_64"
];
/**
* Properties of class types
*/
immutable string[] classProperties = [
"alignof",
"classinfo",
"init",
"mangleof",
"__monitor",
"sizeof",
"stringof",
"tupleof",
"__vptr",
immutable string[] predefinedVersions = [
"AArch64",
"AIX",
"all",
"Alpha",
"Alpha_HardFloat",
"Alpha_SoftFloat",
"Android",
"ARM",
"ARM_HardFloat",
"ARM_SoftFloat",
"ARM_SoftFP",
"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;
import stdx.d.lexer;
import stdx.d.ast;
import stdx.d.parser;
import actypes;
import conversion.first;
import conversion.second;
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;
const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile)
Scope* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile,
CAllocator symbolAllocator, CAllocator semanticAllocator,
shared(StringCache)* cache)
{
ParseAllocator p = new ParseAllocator;
Module m = parseModule(tokens, "editor buffer", p, &doesNothing);
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
FirstPass first = new FirstPass(m, symbolFile, cache);
Module m = parseModule(tokens, "editor buffer", semanticAllocator, &doesNothing);
auto first = scoped!FirstPass(m, symbolFile, cache, symbolAllocator,
semanticAllocator);
first.run();
SecondPass second = SecondPass(first);
@ -41,14 +43,13 @@ const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile
ThirdPass third = ThirdPass(second);
third.run();
p.deallocateAll();
return cast(typeof(return)) third.moduleScope;
typeid(typeof(third.rootSymbol)).destroy(third.rootSymbol);
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.tokens = tokens;
parser.messageFunction = &doesNothing;

View File

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

View File

@ -18,13 +18,13 @@
module conversion.third;
import stdx.d.ast;
import stdx.d.lexer;
import std.d.ast;
import std.d.lexer;
import conversion.second;
import semantic;
import actypes;
import messages;
import std.allocator;
/**
* Third pass handles the following:
@ -45,6 +45,7 @@ public:
this.moduleScope = second.moduleScope;
this.stringCache = second.stringCache;
this.name = name;
this.symbolAllocator = second.symbolAllocator;
}
string name;
@ -56,6 +57,7 @@ public:
SemanticSymbol* rootSymbol;
Scope* moduleScope;
CAllocator symbolAllocator;
private:
@ -147,7 +149,11 @@ private:
else if (t.type2.symbol !is null)
{
// 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);
auto symbols = moduleScope.getSymbolsByNameAndCursor(
symbolParts[0], location);
@ -168,12 +174,9 @@ private:
return s;
}
static string[] expandSymbol(const IdentifierOrTemplateChain chain,
static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain,
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)
{
auto identOrTemplate = chain.identifiersOrTemplateInstances[i];
@ -183,21 +186,18 @@ private:
identOrTemplate.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;
if (suffix.star)
return symbol;
if (suffix.array || suffix.type)
{
ACSymbol* s = new ACSymbol(null);
s.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
s.parts.insert(suffix.array ? (cast() arraySymbols)[]
: (cast() assocArraySymbols)[]);
ACSymbol* s = allocate!ACSymbol(symbolAllocator, null);
s.parts.insert(suffix.array ? arraySymbols[]
: assocArraySymbols[]);
s.type = symbol;
s.qualifier = suffix.array ? SymbolQualifier.array : SymbolQualifier.assocArray;
return s;
@ -205,10 +205,17 @@ private:
if (suffix.parameters)
{
import conversion.first;
ACSymbol* s = new ACSymbol(null);
import memory.allocators;
import memory.appender;
ACSymbol* s = allocate!ACSymbol(symbolAllocator, null);
s.type = symbol;
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 null;
@ -219,9 +226,8 @@ private:
string stringRepresentation = str(type2.builtinType);
if (stringRepresentation is null) return null;
// TODO: Make this use binary search instead
auto t = cast() builtinSymbols;
ACSymbol s = ACSymbol(stringRepresentation);
return t.equalRange(&s).front();
return builtinSymbols.equalRange(&s).front();
}
shared(StringCache)* stringCache;

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

View File

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

View File

@ -20,9 +20,10 @@ module semantic;
import messages;
import actypes;
import stdx.d.ast;
import stdx.d.lexer;
import std.d.ast;
import std.d.lexer;
import stupidlog;
import containers.unrolledlist;
/**
* Intermediate form between ACSymbol and the AST classes. Stores enough
@ -33,6 +34,7 @@ struct SemanticSymbol
public:
@disable this();
@disable this(this);
/**
* Params:
@ -41,21 +43,24 @@ public:
* symbolFile = the file name for this symbol
* location = the location of this symbol
*/
this(string name, CompletionKind kind, string symbolFile,
size_t location = size_t.max, const Type type = null)
this(ACSymbol* acSymbol, const Type type = null)
{
acSymbol = new ACSymbol(name, kind);
acSymbol.location = location;
acSymbol.symbolFile = symbolFile;
this.acSymbol = acSymbol;
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
*/
void addChild(SemanticSymbol* child)
{
children ~= child;
children.insert(child);
acSymbol.parts.insert(child.acSymbol);
}
@ -63,16 +68,16 @@ public:
ACSymbol* acSymbol;
/// Base classes
string[][] baseClasses;
UnrolledList!(string[]) baseClasses;
/// Variable type or function return type
const Type type;
/// Alias this symbols
string[] aliasThis;
UnrolledList!(string) aliasThis;
/// MixinTemplates
string[] mixinTemplates;
UnrolledList!(string) mixinTemplates;
/// Protection level for this symobol
IdType protection;
@ -81,7 +86,7 @@ public:
SemanticSymbol* parent;
/// Child symbols
SemanticSymbol*[] children;
UnrolledList!(SemanticSymbol*) children;
}
/**
@ -96,25 +101,29 @@ Type argumentsType;
static this()
{
import std.allocator;
// _argptr has type void*
argptrType = new Type;
argptrType.type2 = new Type2;
argptrType = allocate!Type(Mallocator.it);
argptrType.type2 = allocate!Type2(Mallocator.it);
argptrType.type2.builtinType = tok!"void";
TypeSuffix argptrTypeSuffix = new TypeSuffix;
TypeSuffix argptrTypeSuffix = allocate!TypeSuffix(Mallocator.it);
argptrTypeSuffix.star = true;
argptrType.typeSuffixes ~= argptrTypeSuffix;
argptrType.typeSuffixes = cast(TypeSuffix[]) Mallocator.it.allocate(TypeSuffix.sizeof);
argptrType.typeSuffixes[0] = argptrTypeSuffix;
// _arguments has type TypeInfo[]
argumentsType = new Type;
argumentsType = new Type;
argumentsType.type2 = new Type2;
argumentsType.type2.symbol = new Symbol;
argumentsType.type2.symbol.identifierOrTemplateChain = new IdentifierOrTemplateChain;
IdentifierOrTemplateInstance i = new IdentifierOrTemplateInstance;
argumentsType = allocate!Type(Mallocator.it);
argumentsType.type2 = allocate!Type2(Mallocator.it);
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.type = tok!"identifier";
argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances ~= i;
TypeSuffix argumentsTypeSuffix = new TypeSuffix;
argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances =
cast(IdentifierOrTemplateInstance[]) Mallocator.it.allocate(IdentifierOrTemplateInstance.sizeof);
argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances[0] = i;
TypeSuffix argumentsTypeSuffix = allocate!TypeSuffix(Mallocator.it);
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.datetime;
import std.conv;
import std.allocator;
import core.memory;
import msgpack;
@ -92,12 +95,16 @@ int main(string[] args)
ModuleCache.addImportPaths(importPaths);
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();
Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds");
float internBytes = cast(float) ModuleCache.stringCache.allocated / (1024 * 1024);
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
version (Posix) chdir("/");
@ -153,17 +160,17 @@ int main(string[] args)
Log.info("Shutting down.");
break serverLoop;
case RequestKind.autocomplete:
try
{
// try
// {
AutocompleteResponse response = complete(request);
ubyte[] responseBytes = msgpack.pack(response);
s.send(responseBytes);
}
catch (Exception e)
{
Log.error("Could not handle autocomplete request due to an exception:",
e.msg);
}
// }
// catch (Exception e)
// {
// Log.error("Could not handle autocomplete request due to an exception:",
// e.msg);
// }
break;
case RequestKind.doc:
try