Switch over to allocators from GC, dropping the memory usage by 70%
This commit is contained in:
parent
9e0ee133b5
commit
970310702d
338
actypes.d
338
actypes.d
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 */";
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
33
build.sh
33
build.sh
|
|
@ -1,12 +1,15 @@
|
||||||
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\
|
||||||
actypes.d\
|
actypes.d\
|
||||||
conversion/astconverter.d\
|
conversion/astconverter.d\
|
||||||
conversion/first.d\
|
conversion/first.d\
|
||||||
|
|
@ -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\
|
||||||
|
|
|
||||||
2
client.d
2
client.d
|
|
@ -185,7 +185,7 @@ Options:
|
||||||
Instructs the server to add PATH to its list of paths searced for
|
Instructs the server to add PATH to its list of paths searced for
|
||||||
imported modules.
|
imported modules.
|
||||||
|
|
||||||
--port PORTNUMBER | -pPORTNUMBER
|
--port PORTNUMBER | -p PORTNUMBER
|
||||||
Uses PORTNUMBER to communicate with the server instead of the default
|
Uses PORTNUMBER to communicate with the server instead of the default
|
||||||
port 9166.`, programName);
|
port 9166.`, programName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
188
constants.d
188
constants.d
|
|
@ -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";
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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[]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
2
dscanner
2
dscanner
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3ddac7885f373c0e5ce7ff1b2670d401d8d482d5
|
Subproject commit 017b90e31f2d8bdc0181fa3ac0d6a0e3be0d480e
|
||||||
161
modulecache.d
161
modulecache.d
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
semantic.d
59
semantic.d
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
server.d
25
server.d
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue