diff --git a/actypes.d b/actypes.d index de44047..c52a150 100644 --- a/actypes.d +++ b/actypes.d @@ -23,19 +23,15 @@ import std.array; import std.container; import std.stdio; import std.typecons; +import std.allocator; -import stdx.d.lexer; +import containers.karytree; +import containers.unrolledlist; +import containers.slist; +import std.d.lexer; import messages; -/** - * Compares symbols by their name - */ -bool comparitor(const(ACSymbol)* a, const(ACSymbol)* b) pure nothrow -{ - return a.name < b.name; -} - /** * Any special information about a variable declaration symbol. */ @@ -67,7 +63,6 @@ public: this(string name) { this.name = name; - this.parts = new RedBlackTree!(ACSymbol*, comparitor, true); } /** @@ -79,7 +74,6 @@ public: { this.name = name; this.kind = kind; - this.parts = new RedBlackTree!(ACSymbol*, comparitor, true); } /** @@ -93,7 +87,15 @@ public: this.name = name; this.kind = kind; this.type = type; - this.parts = new RedBlackTree!(ACSymbol*, comparitor, true); + } + + int opCmp(ref const ACSymbol other) const + { + if (name < other.name) + return -1; + if (name > other.name) + return 1; + return 0; } /** @@ -101,16 +103,15 @@ public: */ ACSymbol*[] getPartsByName(string name) { - import std.range; ACSymbol s = ACSymbol(name); - return parts.equalRange(&s).array(); + return array(parts.equalRange(&s)); } /** * Symbols that compose this symbol, such as enum members, class variables, * methods, etc. */ - RedBlackTree!(ACSymbol*, comparitor, true) parts; + KAryTree!(ACSymbol*, true, "a < b", false) parts; /** * Symbol's name @@ -167,7 +168,14 @@ struct Scope { this.startLocation = begin; this.endLocation = end; - this.symbols = new RedBlackTree!(ACSymbol*, comparitor, true); + } + + ~this() + { + foreach (info; importInformation[]) + typeid(ImportInformation).destroy(info); + foreach (child; children[]) + typeid(Scope).destroy(child); } /** @@ -176,11 +184,11 @@ struct Scope * Returns: * the innermost scope that contains the given cursor position */ - Scope* getScopeByCursor(size_t cursorPosition) const + Scope* getScopeByCursor(size_t cursorPosition) { if (cursorPosition < startLocation) return null; if (cursorPosition > endLocation) return null; - foreach (child; children) + foreach (child; children[]) { auto childScope = child.getScopeByCursor(cursorPosition); if (childScope !is null) @@ -196,20 +204,20 @@ struct Scope * all symbols in the scope containing the cursor position, as well as * the symbols in parent scopes of that scope. */ - ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition) const + ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition) { auto s = getScopeByCursor(cursorPosition); if (s is null) return []; - auto symbols = s.symbols; + UnrolledList!(ACSymbol*) symbols; + symbols.insert(s.symbols[]); Scope* sc = s.parent; while (sc !is null) { - foreach (sym; sc.symbols) - symbols.insert(sym); + symbols.insert(sc.symbols[]); sc = sc.parent; } - return symbols.array(); + return array(symbols[]); } /** @@ -218,12 +226,16 @@ struct Scope * Returns: * all symbols in this scope or parent scopes with the given name */ - ACSymbol*[] getSymbolsByName(string name) const + ACSymbol*[] getSymbolsByName(string name) { import std.range; ACSymbol s = ACSymbol(name); - RedBlackTree!(ACSymbol*, comparitor, true) t = cast() symbols; - auto r = t.equalRange(&s).array(); + auto r = array(symbols.equalRange(&s)); + foreach (i; r) + { + import std.string; + assert (i.name == name, format("%s %s %d", i.name, name, r.length)); + } if (r.length > 0) return cast(typeof(return)) r; if (parent is null) @@ -239,7 +251,7 @@ struct Scope * all symbols with the given name in the scope containing the cursor * and its parent scopes */ - ACSymbol*[] getSymbolsByNameAndCursor(string name, size_t cursorPosition) const + ACSymbol*[] getSymbolsByNameAndCursor(string name, size_t cursorPosition) { auto s = getScopeByCursor(cursorPosition); if (s is null) @@ -248,13 +260,13 @@ struct Scope } /// Imports contained in this scope - ImportInformation[] importInformation; + UnrolledList!(ImportInformation*) importInformation; /// The scope that contains this one Scope* parent; /// Child scopes - Scope*[] children; + UnrolledList!(Scope*, false) children; /// Start location of this scope in bytes size_t startLocation; @@ -263,7 +275,7 @@ struct Scope size_t endLocation; /// Symbols contained in this scope - RedBlackTree!(ACSymbol*, comparitor, true) symbols; + KAryTree!(ACSymbol*, true, "a < b", false) symbols; } /** @@ -272,11 +284,11 @@ struct Scope struct ImportInformation { /// Import statement parts - string[] importParts; + UnrolledList!string importParts; /// module relative path string modulePath; /// symbols to import from this module - Tuple!(string, string)[] importedSymbols; + UnrolledList!(Tuple!(string, string), false) importedSymbols; /// true if the import is public bool isPublic; } @@ -285,91 +297,98 @@ struct ImportInformation /** * Symbols for the built in types */ -RedBlackTree!(ACSymbol*, comparitor, true) builtinSymbols; +KAryTree!(ACSymbol*, true) builtinSymbols; /** * Array properties */ -RedBlackTree!(ACSymbol*, comparitor, true) arraySymbols; +KAryTree!(ACSymbol*, true) arraySymbols; /** * Associative array properties */ -RedBlackTree!(ACSymbol*, comparitor, true) assocArraySymbols; +KAryTree!(ACSymbol*, true) assocArraySymbols; /** * Enum, union, class, and interface properties */ -RedBlackTree!(ACSymbol*, comparitor, true) aggregateSymbols; +KAryTree!(ACSymbol*, true) aggregateSymbols; /** * Class properties */ -RedBlackTree!(ACSymbol*, comparitor, true) classSymbols; +KAryTree!(ACSymbol*, true) classSymbols; /** * Initializes builtin types and the various properties of builtin types */ static this() { - auto bSym = new RedBlackTree!(ACSymbol*, comparitor, true); - auto arrSym = new RedBlackTree!(ACSymbol*, comparitor, true); - auto asarrSym = new RedBlackTree!(ACSymbol*, comparitor, true); - auto aggSym = new RedBlackTree!(ACSymbol*, comparitor, true); - auto clSym = new RedBlackTree!(ACSymbol*, comparitor, true); + auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword); + auto int_ = allocate!ACSymbol(Mallocator.it, "int", CompletionKind.keyword); + auto long_ = allocate!ACSymbol(Mallocator.it, "long", CompletionKind.keyword); + auto byte_ = allocate!ACSymbol(Mallocator.it, "byte", CompletionKind.keyword); + auto char_ = allocate!ACSymbol(Mallocator.it, "char", CompletionKind.keyword); + auto dchar_ = allocate!ACSymbol(Mallocator.it, "dchar", CompletionKind.keyword); + auto short_ = allocate!ACSymbol(Mallocator.it, "short", CompletionKind.keyword); + auto ubyte_ = allocate!ACSymbol(Mallocator.it, "ubyte", CompletionKind.keyword); + auto uint_ = allocate!ACSymbol(Mallocator.it, "uint", CompletionKind.keyword); + auto ulong_ = allocate!ACSymbol(Mallocator.it, "ulong", CompletionKind.keyword); + auto ushort_ = allocate!ACSymbol(Mallocator.it, "ushort", CompletionKind.keyword); + auto wchar_ = allocate!ACSymbol(Mallocator.it, "wchar", CompletionKind.keyword); - auto bool_ = new ACSymbol("bool", CompletionKind.keyword); - auto int_ = new ACSymbol("int", CompletionKind.keyword); - auto long_ = new ACSymbol("long", CompletionKind.keyword); - auto byte_ = new ACSymbol("byte", CompletionKind.keyword); - auto char_ = new ACSymbol("char", CompletionKind.keyword); - auto dchar_ = new ACSymbol("dchar", CompletionKind.keyword); - auto short_ = new ACSymbol("short", CompletionKind.keyword); - auto ubyte_ = new ACSymbol("ubyte", CompletionKind.keyword); - auto uint_ = new ACSymbol("uint", CompletionKind.keyword); - auto ulong_ = new ACSymbol("ulong", CompletionKind.keyword); - auto ushort_ = new ACSymbol("ushort", CompletionKind.keyword); - auto wchar_ = new ACSymbol("wchar", CompletionKind.keyword); + auto alignof_ = allocate!ACSymbol(Mallocator.it, "alignof", CompletionKind.keyword); + auto mangleof_ = allocate!ACSymbol(Mallocator.it, "mangleof", CompletionKind.keyword); + auto sizeof_ = allocate!ACSymbol(Mallocator.it, "sizeof", CompletionKind.keyword); + auto stringof_ = allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword); + auto init = allocate!ACSymbol(Mallocator.it, "stringof", CompletionKind.keyword); - auto alignof_ = new ACSymbol("alignof", CompletionKind.keyword, ulong_); - auto mangleof_ = new ACSymbol("mangleof", CompletionKind.keyword); - auto sizeof_ = new ACSymbol("sizeof", CompletionKind.keyword, ulong_); - auto stringof_ = new ACSymbol("init", CompletionKind.keyword); - auto init = new ACSymbol("stringof", CompletionKind.keyword); + arraySymbols.insert(alignof_); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "dup", CompletionKind.keyword)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "idup", CompletionKind.keyword)); + arraySymbols.insert(init); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "length", CompletionKind.keyword, ulong_)); + arraySymbols.insert(mangleof_); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "ptr", CompletionKind.keyword)); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "reverse", CompletionKind.keyword)); + arraySymbols.insert(sizeof_); + arraySymbols.insert(allocate!ACSymbol(Mallocator.it, "sort", CompletionKind.keyword)); + arraySymbols.insert(stringof_); - arrSym.insert(alignof_); - arrSym.insert(new ACSymbol("dup", CompletionKind.keyword)); - arrSym.insert(new ACSymbol("idup", CompletionKind.keyword)); - arrSym.insert(init); - arrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_)); - arrSym.insert(mangleof_); - arrSym.insert(new ACSymbol("ptr", CompletionKind.keyword)); - arrSym.insert(new ACSymbol("reverse", CompletionKind.keyword)); - arrSym.insert(sizeof_); - arrSym.insert(new ACSymbol("sort", CompletionKind.keyword)); - arrSym.insert(stringof_); + assocArraySymbols.insert(alignof_); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "byKey", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "byValue", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "dup", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "get", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "keys", CompletionKind.keyword)); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "length", CompletionKind.keyword, ulong_)); + assocArraySymbols.insert(mangleof_); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "rehash", CompletionKind.keyword)); + assocArraySymbols.insert(sizeof_); + assocArraySymbols.insert(stringof_); + assocArraySymbols.insert(init); + assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, "values", CompletionKind.keyword)); - asarrSym.insert(alignof_); - asarrSym.insert(new ACSymbol("byKey", CompletionKind.keyword)); - asarrSym.insert(new ACSymbol("byValue", CompletionKind.keyword)); - asarrSym.insert(new ACSymbol("dup", CompletionKind.keyword)); - asarrSym.insert(new ACSymbol("get", CompletionKind.keyword)); - asarrSym.insert(new ACSymbol("init", CompletionKind.keyword)); - asarrSym.insert(new ACSymbol("keys", CompletionKind.keyword)); - asarrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_)); - asarrSym.insert(mangleof_); - asarrSym.insert(new ACSymbol("rehash", CompletionKind.keyword)); - asarrSym.insert(sizeof_); - asarrSym.insert(stringof_); - asarrSym.insert(init); - asarrSym.insert(new ACSymbol("values", CompletionKind.keyword)); + ACSymbol*[11] integralTypeArray; + integralTypeArray[0] = bool_; + integralTypeArray[1] = int_; + integralTypeArray[2] = long_; + integralTypeArray[3] = byte_; + integralTypeArray[4] = char_; + integralTypeArray[4] = dchar_; + integralTypeArray[5] = short_; + integralTypeArray[6] = ubyte_; + integralTypeArray[7] = uint_; + integralTypeArray[8] = ulong_; + integralTypeArray[9] = ushort_; + integralTypeArray[10] = wchar_; - foreach (s; [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_, - ulong_, ushort_, wchar_]) + foreach (s; integralTypeArray) { - s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "min", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "max", CompletionKind.keyword, s)); s.parts.insert(alignof_); s.parts.insert(sizeof_); s.parts.insert(stringof_); @@ -377,74 +396,101 @@ static this() s.parts.insert(init); } - auto cdouble_ = new ACSymbol("cdouble", CompletionKind.keyword); - auto cent_ = new ACSymbol("cent", CompletionKind.keyword); - auto cfloat_ = new ACSymbol("cfloat", CompletionKind.keyword); - auto creal_ = new ACSymbol("creal", CompletionKind.keyword); - auto double_ = new ACSymbol("double", CompletionKind.keyword); - auto float_ = new ACSymbol("float", CompletionKind.keyword); - auto idouble_ = new ACSymbol("idouble", CompletionKind.keyword); - auto ifloat_ = new ACSymbol("ifloat", CompletionKind.keyword); - auto ireal_ = new ACSymbol("ireal", CompletionKind.keyword); - auto real_ = new ACSymbol("real", CompletionKind.keyword); - auto ucent_ = new ACSymbol("ucent", CompletionKind.keyword); + auto cdouble_ = allocate!ACSymbol(Mallocator.it, "cdouble", CompletionKind.keyword); + auto cent_ = allocate!ACSymbol(Mallocator.it, "cent", CompletionKind.keyword); + auto cfloat_ = allocate!ACSymbol(Mallocator.it, "cfloat", CompletionKind.keyword); + auto creal_ = allocate!ACSymbol(Mallocator.it, "creal", CompletionKind.keyword); + auto double_ = allocate!ACSymbol(Mallocator.it, "double", CompletionKind.keyword); + auto float_ = allocate!ACSymbol(Mallocator.it, "float", CompletionKind.keyword); + auto idouble_ = allocate!ACSymbol(Mallocator.it, "idouble", CompletionKind.keyword); + auto ifloat_ = allocate!ACSymbol(Mallocator.it, "ifloat", CompletionKind.keyword); + auto ireal_ = allocate!ACSymbol(Mallocator.it, "ireal", CompletionKind.keyword); + auto real_ = allocate!ACSymbol(Mallocator.it, "real", CompletionKind.keyword); + auto ucent_ = allocate!ACSymbol(Mallocator.it, "ucent", CompletionKind.keyword); - foreach (s; [cdouble_, cent_, cfloat_, creal_, double_, float_, - idouble_, ifloat_, ireal_, real_, ucent_]) + ACSymbol*[11] floatTypeArray; + floatTypeArray[0] = cdouble_; + floatTypeArray[1] = cent_; + floatTypeArray[2] = cfloat_; + floatTypeArray[3] = creal_; + floatTypeArray[4] = double_; + floatTypeArray[5] = float_; + floatTypeArray[6] = idouble_; + floatTypeArray[7] = ifloat_; + floatTypeArray[8] = ireal_; + floatTypeArray[9] = real_; + floatTypeArray[10] = ucent_; + + foreach (s; floatTypeArray) { s.parts.insert(alignof_); - s.parts.insert(new ACSymbol("dig", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("epsilon", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("infinity", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "dig", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "epsilon", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "infinity", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "init", CompletionKind.keyword, s)); s.parts.insert(mangleof_); - s.parts.insert(new ACSymbol("mant_dig", CompletionKind.keyword, int_)); - s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("max_10_exp", CompletionKind.keyword, int_)); - s.parts.insert(new ACSymbol("max_exp", CompletionKind.keyword, int_)); - s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("min_exp", CompletionKind.keyword, int_)); - s.parts.insert(new ACSymbol("min_10_exp", CompletionKind.keyword, int_)); - s.parts.insert(new ACSymbol("min_normal", CompletionKind.keyword, s)); - s.parts.insert(new ACSymbol("nan", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "mant_dig", CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "max", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "max_10_exp", CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "max_exp", CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "min", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_exp", CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_10_exp", CompletionKind.keyword, int_)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "min_normal", CompletionKind.keyword, s)); + s.parts.insert(allocate!ACSymbol(Mallocator.it, "nan", CompletionKind.keyword, s)); s.parts.insert(sizeof_); s.parts.insert(stringof_); } - aggSym.insert(new ACSymbol("tupleof", CompletionKind.variableName)); - aggSym.insert(mangleof_); - aggSym.insert(alignof_); - aggSym.insert(sizeof_); - aggSym.insert(stringof_); - aggSym.insert(init); + aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.variableName)); + aggregateSymbols.insert(mangleof_); + aggregateSymbols.insert(alignof_); + aggregateSymbols.insert(sizeof_); + aggregateSymbols.insert(stringof_); + aggregateSymbols.insert(init); - clSym.insert(new ACSymbol("classInfo", CompletionKind.variableName)); - clSym.insert(new ACSymbol("tupleof", CompletionKind.variableName)); - clSym.insert(new ACSymbol("__vptr", CompletionKind.variableName)); - clSym.insert(new ACSymbol("__monitor", CompletionKind.variableName)); - clSym.insert(mangleof_); - clSym.insert(alignof_); - clSym.insert(sizeof_); - clSym.insert(stringof_); - clSym.insert(init); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, "classInfo", CompletionKind.variableName)); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.variableName)); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, "__vptr", CompletionKind.variableName)); + classSymbols.insert(allocate!ACSymbol(Mallocator.it, "__monitor", CompletionKind.variableName)); + classSymbols.insert(mangleof_); + classSymbols.insert(alignof_); + classSymbols.insert(sizeof_); + classSymbols.insert(stringof_); + classSymbols.insert(init); - ireal_.parts.insert(new ACSymbol("im", CompletionKind.keyword, real_)); - ifloat_.parts.insert(new ACSymbol("im", CompletionKind.keyword, float_)); - idouble_.parts.insert(new ACSymbol("im", CompletionKind.keyword, double_)); - ireal_.parts.insert(new ACSymbol("re", CompletionKind.keyword, real_)); - ifloat_.parts.insert(new ACSymbol("re", CompletionKind.keyword, float_)); - idouble_.parts.insert(new ACSymbol("re", CompletionKind.keyword, double_)); + ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, real_)); + ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, float_)); + idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, "im", CompletionKind.keyword, double_)); + ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, real_)); + ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, float_)); + idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, "re", CompletionKind.keyword, double_)); - auto void_ = new ACSymbol("void", CompletionKind.keyword); + auto void_ = allocate!ACSymbol(Mallocator.it, "void", CompletionKind.keyword); - bSym.insert([bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_, - ulong_, ushort_, wchar_, cdouble_, cent_, cfloat_, creal_, double_, - float_, idouble_, ifloat_, ireal_, real_, ucent_, void_]); - - builtinSymbols = bSym; - arraySymbols = arrSym; - assocArraySymbols = asarrSym; - aggregateSymbols = aggSym; - classSymbols = clSym; + builtinSymbols.insert(bool_); + builtinSymbols.insert(int_); + builtinSymbols.insert(long_); + builtinSymbols.insert(byte_); + builtinSymbols.insert(char_); + builtinSymbols.insert(dchar_); + builtinSymbols.insert(short_); + builtinSymbols.insert(ubyte_); + builtinSymbols.insert(uint_); + builtinSymbols.insert(ulong_); + builtinSymbols.insert(ushort_); + builtinSymbols.insert(wchar_); + builtinSymbols.insert(cdouble_); + builtinSymbols.insert(cent_); + builtinSymbols.insert(cfloat_); + builtinSymbols.insert(creal_); + builtinSymbols.insert(double_); + builtinSymbols.insert(float_); + builtinSymbols.insert(idouble_); + builtinSymbols.insert(ifloat_); + builtinSymbols.insert(ireal_); + builtinSymbols.insert(real_); + builtinSymbols.insert(ucent_); + builtinSymbols.insert(void_); } diff --git a/autocomplete.d b/autocomplete.d index 95863c2..a67ceb9 100644 --- a/autocomplete.d +++ b/autocomplete.d @@ -26,10 +26,13 @@ import std.path; import std.range; import std.stdio; import std.uni; -import stdx.d.ast; -import stdx.d.lexer; -import stdx.d.parser; +import std.d.ast; +import std.d.lexer; +import std.d.parser; import std.string; +import std.typecons; +import memory.allocators; +import std.allocator; import messages; import actypes; @@ -49,7 +52,8 @@ AutocompleteResponse getDoc(const AutocompleteRequest request) { Log.trace("Getting doc comments"); AutocompleteResponse response; - ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.ddoc); + auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))(); + ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.ddoc, allocator); if (symbols.length == 0) Log.error("Could not find symbol"); else foreach (symbol; symbols) @@ -76,7 +80,8 @@ AutocompleteResponse findDeclaration(const AutocompleteRequest request) { Log.trace("Finding declaration"); AutocompleteResponse response; - ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.location); + auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))(); + ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.location, allocator); if (symbols.length > 0) { response.symbolLocation = symbols[0].location; @@ -120,7 +125,7 @@ AutocompleteResponse complete(const AutocompleteRequest request) tokenType = beforeTokens[$ - 2].type; else return response; - + auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))(); switch (tokenType) { case tok!"stringLiteral": @@ -160,8 +165,11 @@ AutocompleteResponse complete(const AutocompleteRequest request) case tok!")": case tok!"]": case tok!"this": - const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, - "stdin"); + auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16))); + shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount); + Scope* completionScope = generateAutocompleteTrees(tokenArray, + "stdin", allocator, semanticAllocator, cache); + scope(exit) typeid(Scope).destroy(completionScope); auto expression = getExpression(beforeTokens); response.setCompletions(completionScope, expression, request.cursorPosition, CompletionType.identifiers, partial); @@ -207,12 +215,16 @@ auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition, * the request's source code, cursor position, and completion type. */ ACSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request, - const CompletionType type) + const CompletionType type, CAllocator allocator) { const(Token)[] tokenArray; auto beforeTokens = getTokensBeforeCursor(request.sourceCode, request.cursorPosition, tokenArray); - const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, "stdin"); + auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16))); + shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount); + Scope* completionScope = generateAutocompleteTrees(tokenArray, + "stdin", allocator, semanticAllocator, cache); + scope(exit) typeid(Scope).destroy(completionScope); auto expression = getExpression(beforeTokens); return getSymbolsByTokenChain(completionScope, expression, request.cursorPosition, type); @@ -232,6 +244,7 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens, { AutocompleteResponse response; immutable(string)[] completions; + auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))(); switch (beforeTokens[$ - 2].type) { case tok!"__traits": @@ -259,8 +272,11 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens, case tok!"identifier": case tok!")": case tok!"]": - const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, - "stdin"); + auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16))); + shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount); + Scope* completionScope = generateAutocompleteTrees(tokenArray, + "stdin", allocator, semanticAllocator, cache); + scope(exit) typeid(Scope).destroy(completionScope); auto expression = getExpression(beforeTokens[0 .. $ - 1]); response.setCompletions(completionScope, expression, cursorPosition, CompletionType.calltips); @@ -274,16 +290,18 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens, /** * */ -ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope, +ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, T tokens, size_t cursorPosition, CompletionType completionType) { - Log.trace("Getting symbols from token chain", tokens.map!"a.text"); + import std.d.lexer; + Log.trace("Getting symbols from token chain", + tokens.map!stringToken); // Find the symbol corresponding to the beginning of the chain ACSymbol*[] symbols = completionScope.getSymbolsByNameAndCursor( - tokens[0].text, cursorPosition); + stringToken(tokens[0]), cursorPosition); if (symbols.length == 0) { - Log.error("Could not find declaration of ", tokens[0].text, + Log.error("Could not find declaration of ", stringToken(tokens[0]), " from position ", cursorPosition); return []; } @@ -437,7 +455,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope, * */ void setCompletions(T)(ref AutocompleteResponse response, - const(Scope)* completionScope, T tokens, size_t cursorPosition, + Scope* completionScope, T tokens, size_t cursorPosition, CompletionType completionType, string partial = null) { // Autocomplete module imports instead of symbols @@ -486,7 +504,7 @@ void setCompletions(T)(ref AutocompleteResponse response, && (partial is null ? true : a.name.toUpper().startsWith(partial.toUpper())) && !response.completions.canFind(a.name))) { - Log.trace("Adding ", s.name, " to the completion list"); +// Log.trace("Adding ", s.name, " to the completion list"); response.completionKinds ~= s.kind; response.completions ~= s.name; } @@ -733,6 +751,11 @@ string formatComment(string comment) .replaceAll(regex("\n"), `\n`).outdent(); } +string stringToken()(auto ref const Token a) +{ + return a.text is null ? str(a.type) : a.text; +} + //unittest //{ // auto comment1 = "/**\n * This is some text\n */"; diff --git a/build.bat b/build.bat index 6f3fd17..0acc23a 100644 --- a/build.bat +++ b/build.bat @@ -1,2 +1,3 @@ -dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -noboundscheck -O -ofdcd-client.exe -dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d dscanner/stdx/d/ast.d dscanner/stdx/d/entities.d dscanner/stdx/d/lexer.d dscanner/stdx/d/parser.d dscanner/stdx/lexer.d dscanner/stdx/allocator.d dscanner/formatter.d msgpack-d/src/msgpack.d -Imsgpack-d/src -Idscanner -wi -g -O -release -noboundscheck -inline -ofdcd-server.exe +dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -O -ofdcd-client + +dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d dscanner/std/d/ast.d dscanner/std/d/entities.d dscanner/std/d/lexer.d dscanner/std/d/parser.d dscanner/std/lexer.d dscanner/std/allocator.d dscanner/formatter.d containers/src/memory/allocators.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server diff --git a/build.sh b/build.sh index 7e1a9d8..87d8131 100755 --- a/build.sh +++ b/build.sh @@ -1,12 +1,15 @@ -dmd -wi client.d\ +rm -f containers/src/std/allocator.d + +dmd\ + client.d\ messages.d\ stupidlog.d\ msgpack-d/src/msgpack.d\ -Imsgpack-d/src\ - -release -inline -noboundscheck -O\ + -release -inline -O -wi\ -ofdcd-client -dmd \ +dmd\ actypes.d\ conversion/astconverter.d\ conversion/first.d\ @@ -19,18 +22,26 @@ dmd \ semantic.d\ server.d\ stupidlog.d\ - dscanner/stdx/d/ast.d\ - dscanner/stdx/d/entities.d\ - dscanner/stdx/d/lexer.d\ - dscanner/stdx/d/parser.d\ - dscanner/stdx/lexer.d\ - dscanner/stdx/allocator.d\ + dscanner/std/d/ast.d\ + dscanner/std/d/entities.d\ + dscanner/std/d/lexer.d\ + dscanner/std/d/parser.d\ + dscanner/std/lexer.d\ + dscanner/std/allocator.d\ dscanner/formatter.d\ + containers/src/memory/allocators.d\ + containers/src/memory/appender.d\ + containers/src/containers/dynamicarray.d\ + containers/src/containers/karytree.d\ + containers/src/containers/unrolledlist.d\ + containers/src/containers/hashset.d\ + containers/src/containers/internal/hash.d\ + containers/src/containers/slist.d\ msgpack-d/src/msgpack.d\ + -Icontainers/src\ -Imsgpack-d/src\ -Idscanner\ - -wi -g\ - -O -release -noboundscheck -inline\ + -wi -O -release -inline\ -ofdcd-server #gdc client.d\ diff --git a/client.d b/client.d index f795ce3..bb7a6d8 100644 --- a/client.d +++ b/client.d @@ -185,7 +185,7 @@ Options: Instructs the server to add PATH to its list of paths searced for imported modules. - --port PORTNUMBER | -pPORTNUMBER + --port PORTNUMBER | -p PORTNUMBER Uses PORTNUMBER to communicate with the server instead of the default port 9166.`, programName); } diff --git a/constants.d b/constants.d index d9b1ea2..8ea49bb 100644 --- a/constants.d +++ b/constants.d @@ -177,113 +177,83 @@ immutable string[] versions = [ "X86_64" ]; -/** - * Properties of class types - */ -immutable string[] classProperties = [ - "alignof", - "classinfo", - "init", - "mangleof", - "__monitor", - "sizeof", - "stringof", - "tupleof", - "__vptr", +immutable string[] predefinedVersions = [ + "AArch64", + "AIX", + "all", + "Alpha", + "Alpha_HardFloat", + "Alpha_SoftFloat", + "Android", + "ARM", + "ARM_HardFloat", + "ARM_SoftFloat", + "ARM_SoftFP", + "ARM_Thumb", + "assert", + "BigEndian", + "BSD", + "Cygwin", + "D_Coverage", + "D_Ddoc", + "D_HardFloat", + "DigitalMars", + "D_InlineAsm_X86", + "D_InlineAsm_X86_64", + "D_LP64", + "D_NoBoundsChecks", + "D_PIC", + "DragonFlyBSD", + "D_SIMD", + "D_SoftFloat", + "D_Version2", + "D_X32", + "FreeBSD", + "GNU", + "Haiku", + "HPPA", + "HPPA64", + "Hurd", + "IA64", + "LDC", + "linux", + "LittleEndian", + "MIPS32", + "MIPS64", + "MIPS_EABI", + "MIPS_HardFloat", + "MIPS_N32", + "MIPS_N64", + "MIPS_O32", + "MIPS_O64", + "MIPS_SoftFloat", + "NetBSD", + "none", + "OpenBSD", + "OSX", + "Posix", + "PPC", + "PPC64", + "PPC_HardFloat", + "PPC_SoftFloat", + "S390", + "S390X", + "SDC", + "SH", + "SH64", + "SkyOS", + "Solaris", + "SPARC", + "SPARC64", + "SPARC_HardFloat", + "SPARC_SoftFloat", + "SPARC_V8Plus", + "SysV3", + "SysV4", + "unittest", + "Win32", + "Win64", + "Windows", + "X86", + "X86_64", ]; - -/** - * Properties of struct types - */ -immutable string[] structProperties = [ - "alignof", - "tupleof", - "init", - "mangleof", - "sizeof", - "stringof" -]; - -immutable string[] predefinedVersions; - -static this() -{ - version(AArch64) predefinedVersions ~= "AArch64"; - version(AIX) predefinedVersions ~= "AIX"; - version(all) predefinedVersions ~= "all"; - version(Alpha) predefinedVersions ~= "Alpha"; - version(Alpha_HardFloat) predefinedVersions ~= "Alpha_HardFloat"; - version(Alpha_SoftFloat) predefinedVersions ~= "Alpha_SoftFloat"; - version(Android) predefinedVersions ~= "Android"; - version(ARM) predefinedVersions ~= "ARM"; - version(ARM_HardFloat) predefinedVersions ~= "ARM_HardFloat"; - version(ARM_SoftFloat) predefinedVersions ~= "ARM_SoftFloat"; - version(ARM_SoftFP) predefinedVersions ~= "ARM_SoftFP"; - version(ARM_Thumb) predefinedVersions ~= "ARM_Thumb"; - version(assert) predefinedVersions ~= "assert"; - version(BigEndian) predefinedVersions ~= "BigEndian"; - version(BSD) predefinedVersions ~= "BSD"; - version(Cygwin) predefinedVersions ~= "Cygwin"; - version(D_Coverage) predefinedVersions ~= "D_Coverage"; - version(D_Ddoc) predefinedVersions ~= "D_Ddoc"; - version(D_HardFloat) predefinedVersions ~= "D_HardFloat"; - version(DigitalMars) predefinedVersions ~= "DigitalMars"; - version(D_InlineAsm_X86) predefinedVersions ~= "D_InlineAsm_X86"; - version(D_InlineAsm_X86_64) predefinedVersions ~= "D_InlineAsm_X86_64"; - version(D_LP64) predefinedVersions ~= "D_LP64"; - version(D_NoBoundsChecks) predefinedVersions ~= "D_NoBoundsChecks"; - version(D_PIC) predefinedVersions ~= "D_PIC"; - version(DragonFlyBSD) predefinedVersions ~= "DragonFlyBSD"; - version(D_SIMD) predefinedVersions ~= "D_SIMD"; - version(D_SoftFloat) predefinedVersions ~= "D_SoftFloat"; - version(D_Version2) predefinedVersions ~= "D_Version2"; - version(D_X32) predefinedVersions ~= "D_X32"; - version(FreeBSD) predefinedVersions ~= "FreeBSD"; - version(GNU) predefinedVersions ~= "GNU"; - version(Haiku) predefinedVersions ~= "Haiku"; - version(HPPA) predefinedVersions ~= "HPPA"; - version(HPPA64) predefinedVersions ~= "HPPA64"; - version(Hurd) predefinedVersions ~= "Hurd"; - version(IA64) predefinedVersions ~= "IA64"; - version(LDC) predefinedVersions ~= "LDC"; - version(linux) predefinedVersions ~= "linux"; - version(LittleEndian) predefinedVersions ~= "LittleEndian"; - version(MIPS32) predefinedVersions ~= "MIPS32"; - version(MIPS64) predefinedVersions ~= "MIPS64"; - version(MIPS_EABI) predefinedVersions ~= "MIPS_EABI"; - version(MIPS_HardFloat) predefinedVersions ~= "MIPS_HardFloat"; - version(MIPS_N32) predefinedVersions ~= "MIPS_N32"; - version(MIPS_N64) predefinedVersions ~= "MIPS_N64"; - version(MIPS_O32) predefinedVersions ~= "MIPS_O32"; - version(MIPS_O64) predefinedVersions ~= "MIPS_O64"; - version(MIPS_SoftFloat) predefinedVersions ~= "MIPS_SoftFloat"; - version(NetBSD) predefinedVersions ~= "NetBSD"; - version(none) predefinedVersions ~= "none"; - version(OpenBSD) predefinedVersions ~= "OpenBSD"; - version(OSX) predefinedVersions ~= "OSX"; - version(Posix) predefinedVersions ~= "Posix"; - version(PPC) predefinedVersions ~= "PPC"; - version(PPC64) predefinedVersions ~= "PPC64"; - version(PPC_HardFloat) predefinedVersions ~= "PPC_HardFloat"; - version(PPC_SoftFloat) predefinedVersions ~= "PPC_SoftFloat"; - version(S390) predefinedVersions ~= "S390"; - version(S390X) predefinedVersions ~= "S390X"; - version(SDC) predefinedVersions ~= "SDC"; - version(SH) predefinedVersions ~= "SH"; - version(SH64) predefinedVersions ~= "SH64"; - version(SkyOS) predefinedVersions ~= "SkyOS"; - version(Solaris) predefinedVersions ~= "Solaris"; - version(SPARC) predefinedVersions ~= "SPARC"; - version(SPARC64) predefinedVersions ~= "SPARC64"; - version(SPARC_HardFloat) predefinedVersions ~= "SPARC_HardFloat"; - version(SPARC_SoftFloat) predefinedVersions ~= "SPARC_SoftFloat"; - version(SPARC_V8Plus) predefinedVersions ~= "SPARC_V8Plus"; - version(SysV3) predefinedVersions ~= "SysV3"; - version(SysV4) predefinedVersions ~= "SysV4"; - version(unittest) predefinedVersions ~= "unittest"; - version(Win32) predefinedVersions ~= "Win32"; - version(Win64) predefinedVersions ~= "Win64"; - version(Windows) predefinedVersions ~= "Windows"; - version(X86) predefinedVersions ~= "X86"; - version(X86_64) predefinedVersions ~= "X86_64"; -} diff --git a/conversion/astconverter.d b/conversion/astconverter.d index 9ce3b30..bec4688 100644 --- a/conversion/astconverter.d +++ b/conversion/astconverter.d @@ -18,22 +18,24 @@ module conversion.astconverter; -import stdx.d.lexer; -import stdx.d.ast; -import stdx.d.parser; - +import actypes; import conversion.first; import conversion.second; import conversion.third; -import actypes; +import memory.allocators; +import std.allocator; +import std.d.ast; +import std.d.lexer; +import std.d.parser; +import std.typecons; - -const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile) +Scope* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile, + CAllocator symbolAllocator, CAllocator semanticAllocator, + shared(StringCache)* cache) { - ParseAllocator p = new ParseAllocator; - Module m = parseModule(tokens, "editor buffer", p, &doesNothing); - shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount); - FirstPass first = new FirstPass(m, symbolFile, cache); + Module m = parseModule(tokens, "editor buffer", semanticAllocator, &doesNothing); + auto first = scoped!FirstPass(m, symbolFile, cache, symbolAllocator, + semanticAllocator); first.run(); SecondPass second = SecondPass(first); @@ -41,14 +43,13 @@ const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile ThirdPass third = ThirdPass(second); third.run(); - - p.deallocateAll(); - return cast(typeof(return)) third.moduleScope; + typeid(typeof(third.rootSymbol)).destroy(third.rootSymbol); + return third.moduleScope; } -Module parseModuleSimple(const(Token)[] tokens, string fileName, ParseAllocator p) +Module parseModuleSimple(const(Token)[] tokens, string fileName, CAllocator p) { - auto parser = new SimpleParser(); + auto parser = scoped!SimpleParser(); parser.fileName = fileName; parser.tokens = tokens; parser.messageFunction = &doesNothing; diff --git a/conversion/first.d b/conversion/first.d index becf889..3692a28 100644 --- a/conversion/first.d +++ b/conversion/first.d @@ -18,12 +18,18 @@ module conversion.first; -import stdx.d.ast; -import stdx.d.lexer; import actypes; -import semantic; +import formatter; +import std.allocator; +import memory.allocators; +import memory.appender; import messages; +import semantic; +import std.d.ast; +import std.d.lexer; +import std.typecons; import stupidlog; +import containers.unrolledlist; /** * First Pass handles the following: @@ -40,24 +46,31 @@ import stupidlog; */ final class FirstPass : ASTVisitor { - this(Module mod, string symbolFile, shared(StringCache)* stringCache) + this(Module mod, string symbolFile, shared(StringCache)* stringCache, + CAllocator symbolAllocator, CAllocator semanticAllocator) + in + { + assert (symbolAllocator); + } + body { - this.symbolFile = symbolFile; this.mod = mod; + this.symbolFile = symbolFile; this.stringCache = stringCache; + this.symbolAllocator = symbolAllocator; + this.semanticAllocator = semanticAllocator; } void run() { visit(mod); - mod = null; } override void visit(const Unittest u) { // Create a dummy symbol because we don't want unit test symbols leaking // into the symbol they're declared in. - SemanticSymbol* s = new SemanticSymbol("*unittest*", + SemanticSymbol* s = allocateSemanticSymbol("*unittest*", CompletionKind.dummy, null, 0); s.parent = currentSymbol; currentSymbol = s; @@ -86,7 +99,7 @@ final class FirstPass : ASTVisitor override void visit(const Destructor des) { // Log.trace(__FUNCTION__, " ", typeof(des).stringof); - visitDestructor(des.location, des.functionBody, des.comment); + visitDestructor(des.index, des.functionBody, des.comment); } override void visit(const SharedStaticDestructor des) @@ -103,9 +116,10 @@ final class FirstPass : ASTVisitor override void visit(const FunctionDeclaration dec) { -// Log.trace(__FUNCTION__, " ", typeof(dec).stringof); - SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(dec.name.text), - CompletionKind.functionName, symbolFile, dec.name.index, dec.returnType); +// Log.trace(__FUNCTION__, " ", typeof(dec).stringof, " ", dec.name.text); + SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, + CompletionKind.functionName, symbolFile, dec.name.index, + dec.returnType); processParameters(symbol, dec.returnType, symbol.acSymbol.name, dec.parameters, dec.comment); symbol.protection = protection; @@ -153,8 +167,8 @@ final class FirstPass : ASTVisitor override void visit(const BaseClass bc) { // Log.trace(__FUNCTION__, " ", typeof(bc).stringof); - currentSymbol.baseClasses ~= iotcToStringArray( - bc.identifierOrTemplateChain, stringCache); + currentSymbol.baseClasses.insert(iotcToStringArray(symbolAllocator, + bc.identifierOrTemplateChain, stringCache)); } override void visit(const VariableDeclaration dec) @@ -164,12 +178,9 @@ final class FirstPass : ASTVisitor const Type t = dec.type; foreach (declarator; dec.declarators) { - SemanticSymbol* symbol = new SemanticSymbol( - stringCache.intern(declarator.name.text), - CompletionKind.variableName, - symbolFile, - declarator.name.index, - t); + SemanticSymbol* symbol = allocateSemanticSymbol( + declarator.name.text, CompletionKind.variableName, + symbolFile, declarator.name.index, t); symbol.protection = protection; symbol.parent = currentSymbol; symbol.acSymbol.doc = dec.comment; @@ -179,10 +190,9 @@ final class FirstPass : ASTVisitor { foreach (identifier; dec.autoDeclaration.identifiers) { - SemanticSymbol* symbol = new SemanticSymbol( - stringCache.intern(identifier.text), - CompletionKind.variableName, symbolFile, identifier.index, - null); + SemanticSymbol* symbol = allocateSemanticSymbol( + identifier.text, CompletionKind.variableName, symbolFile, + identifier.index, null); symbol.protection = protection; symbol.parent = currentSymbol; symbol.acSymbol.doc = dec.comment; @@ -195,8 +205,8 @@ final class FirstPass : ASTVisitor { if (aliasDeclaration.initializers.length == 0) { - SemanticSymbol* symbol = new SemanticSymbol( - stringCache.intern(aliasDeclaration.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol( + aliasDeclaration.name.text, CompletionKind.aliasName, symbolFile, aliasDeclaration.name.index, @@ -210,8 +220,8 @@ final class FirstPass : ASTVisitor { foreach (initializer; aliasDeclaration.initializers) { - SemanticSymbol* symbol = new SemanticSymbol( - stringCache.intern(initializer.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol( + initializer.name.text, CompletionKind.aliasName, symbolFile, initializer.name.index, @@ -227,7 +237,7 @@ final class FirstPass : ASTVisitor override void visit(const AliasThisDeclaration dec) { // Log.trace(__FUNCTION__, " ", typeof(dec).stringof); - currentSymbol.aliasThis ~= stringCache.intern(dec.identifier.text); + currentSymbol.aliasThis.insert(stringCache.intern(dec.identifier.text)); } override void visit(const Declaration dec) @@ -253,23 +263,24 @@ final class FirstPass : ASTVisitor { // Log.trace(__FUNCTION__, " ", typeof(mod).stringof); // - currentSymbol = new SemanticSymbol(null, CompletionKind.moduleName, + currentSymbol = allocateSemanticSymbol(null, CompletionKind.moduleName, symbolFile); rootSymbol = currentSymbol; - currentScope = new Scope(0, size_t.max); - ImportInformation i; + currentScope = allocate!Scope(semanticAllocator, 0, size_t.max); + auto i = allocate!ImportInformation(semanticAllocator); i.modulePath = "object"; - i.importParts ~= "object"; - currentScope.importInformation ~= i; + i.importParts.insert("object"); + currentScope.importInformation.insert(i); moduleScope = currentScope; mod.accept(this); + assert (currentSymbol.acSymbol.name is null); } override void visit(const EnumDeclaration dec) { assert (currentSymbol); // Log.trace(__FUNCTION__, " ", typeof(dec).stringof); - SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(dec.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, CompletionKind.enumName, symbolFile, dec.name.index, dec.type); symbol.parent = currentSymbol; symbol.acSymbol.doc = dec.comment; @@ -283,7 +294,7 @@ final class FirstPass : ASTVisitor override void visit(const EnumMember member) { // Log.trace(__FUNCTION__, " ", typeof(member).stringof); - SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(member.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol(member.name.text, CompletionKind.enumMember, symbolFile, member.name.index, member.type); symbol.parent = currentSymbol; symbol.acSymbol.doc = member.comment; @@ -295,72 +306,75 @@ final class FirstPass : ASTVisitor // Log.trace(__FUNCTION__, " ", typeof(dec).stringof); foreach (identifier; moduleDeclaration.moduleName.identifiers) { - moduleName ~= stringCache.intern(identifier.text); + moduleName.insert(stringCache.intern(identifier.text)); } } - // creates scopes for override void visit(const StructBody structBody) { // Log.trace(__FUNCTION__, " ", typeof(structBody).stringof); - Scope* s = new Scope(structBody.startLocation, structBody.endLocation); + Scope* s = allocate!Scope(semanticAllocator, structBody.startLocation, structBody.endLocation); // Log.trace("Added scope ", s.startLocation, " ", s.endLocation); - ACSymbol* thisSymbol = new ACSymbol("this", CompletionKind.variableName, - currentSymbol.acSymbol); + ACSymbol* thisSymbol = allocate!ACSymbol(symbolAllocator, "this", + CompletionKind.variableName, currentSymbol.acSymbol); thisSymbol.location = s.startLocation; thisSymbol.symbolFile = symbolFile; - currentSymbol.acSymbol.parts.insert(thisSymbol); + s.symbols.insert(thisSymbol); s.parent = currentScope; currentScope = s; foreach (dec; structBody.declarations) visit(dec); currentScope = s.parent; - currentScope.children ~= s; + currentScope.children.insert(s); } override void visit(const ImportDeclaration importDeclaration) { import std.typecons; import std.algorithm; - import std.array; // Log.trace(__FUNCTION__, " ImportDeclaration"); foreach (single; importDeclaration.singleImports.filter!( a => a !is null && a.identifierChain !is null)) { - ImportInformation info; - info.importParts = single.identifierChain.identifiers.map!(a => stringCache.intern(a.text)).array; - info.modulePath = convertChainToImportPath(single.identifierChain); + auto info = allocate!ImportInformation(semanticAllocator); + foreach (identifier; single.identifierChain.identifiers) + info.importParts.insert(stringCache.intern(identifier.text)); + info.modulePath = convertChainToImportPath(stringCache, single.identifierChain); info.isPublic = protection == tok!"public"; - currentScope.importInformation ~= info; + currentScope.importInformation.insert(info); } if (importDeclaration.importBindings is null) return; if (importDeclaration.importBindings.singleImport.identifierChain is null) return; - ImportInformation info; - info.modulePath = convertChainToImportPath( + auto info = allocate!ImportInformation(semanticAllocator); + + info.modulePath = convertChainToImportPath(stringCache, importDeclaration.importBindings.singleImport.identifierChain); - info.importParts = importDeclaration.importBindings.singleImport - .identifierChain.identifiers.map!(a => stringCache.intern(a.text)).array; + foreach (identifier; importDeclaration.importBindings.singleImport + .identifierChain.identifiers) + { + info.importParts.insert(stringCache.intern(identifier.text)); + } foreach (bind; importDeclaration.importBindings.importBinds) { Tuple!(string, string) bindTuple; bindTuple[0] = stringCache.intern(bind.left.text); bindTuple[1] = bind.right == tok!"" ? null : stringCache.intern(bind.right.text); - info.importedSymbols ~= bindTuple; + info.importedSymbols.insert(bindTuple); } info.isPublic = protection == tok!"public"; - currentScope.importInformation ~= info; + currentScope.importInformation.insert(info); } // Create scope for block statements override void visit(const BlockStatement blockStatement) { // Log.trace(__FUNCTION__, " ", typeof(blockStatement).stringof); - Scope* s = new Scope(blockStatement.startLocation, + Scope* s = allocate!Scope(semanticAllocator, blockStatement.startLocation, blockStatement.endLocation); s.parent = currentScope; - currentScope.children ~= s; + currentScope.children.insert(s); if (currentSymbol.acSymbol.kind == CompletionKind.functionName) { @@ -400,12 +414,16 @@ final class FirstPass : ASTVisitor shared(StringCache)* stringCache; + CAllocator symbolAllocator; + + uint symbolsAllocated; + private: void visitAggregateDeclaration(AggType)(AggType dec, CompletionKind kind) { // Log.trace("visiting aggregate declaration ", dec.name.text); - SemanticSymbol* symbol = new SemanticSymbol(stringCache.intern(dec.name.text), + SemanticSymbol* symbol = allocateSemanticSymbol(dec.name.text, kind, symbolFile, dec.name.index); if (kind == CompletionKind.className) symbol.acSymbol.parts.insert(classSymbols[]); @@ -423,7 +441,7 @@ private: void visitConstructor(size_t location, const Parameters parameters, const FunctionBody functionBody, string doc) { - SemanticSymbol* symbol = new SemanticSymbol("*constructor*", + SemanticSymbol* symbol = allocateSemanticSymbol("*constructor*", CompletionKind.functionName, symbolFile, location); processParameters(symbol, null, "this", parameters, doc); symbol.protection = protection; @@ -440,7 +458,7 @@ private: void visitDestructor(size_t location, const FunctionBody functionBody, string doc) { - SemanticSymbol* symbol = new SemanticSymbol("~this", + SemanticSymbol* symbol = allocateSemanticSymbol("~this", CompletionKind.functionName, symbolFile, location); symbol.acSymbol.callTip = "~this()"; symbol.protection = protection; @@ -462,21 +480,20 @@ private: { foreach (const Parameter p; parameters.parameters) { - SemanticSymbol* parameter = new SemanticSymbol( - stringCache.intern(p.name.text), - CompletionKind.variableName, symbolFile, size_t.max, - p.type); + SemanticSymbol* parameter = allocateSemanticSymbol( + p.name.text, CompletionKind.variableName, symbolFile, + size_t.max, p.type); symbol.addChild(parameter); parameter.parent = symbol; } if (parameters.hasVarargs) { - SemanticSymbol* argptr = new SemanticSymbol("_argptr", + SemanticSymbol* argptr = allocateSemanticSymbol("_argptr", CompletionKind.variableName, null, size_t.max, argptrType); argptr.parent = symbol; symbol.addChild(argptr); - SemanticSymbol* arguments = new SemanticSymbol("_arguments", + SemanticSymbol* arguments = allocateSemanticSymbol("_arguments", CompletionKind.variableName, null, size_t.max, argumentsType); arguments.parent = symbol; symbol.addChild(arguments); @@ -486,22 +503,46 @@ private: parameters, doc); } - static string formatCallTip(const Type returnType, string name, + string formatCallTip(const Type returnType, string name, const Parameters parameters, string doc = null) { - import std.string; - string parameterString = parameters is null ? "()" - : formatNode(parameters); - if (returnType is null) - return "%s%s".format(name, parameterString); - return "%s %s%s".format(formatNode(returnType), name, parameterString); + QuickAllocator!1024 q; + auto app = Appender!(char, typeof(q), 1024)(q); + scope(exit) q.deallocate(app.mem); + if (returnType !is null) + { + app.formatNode(returnType); + app.put(' '); + } + app.put(name); + if (parameters is null) + app.put("()"); + else + app.formatNode(parameters); + return stringCache.intern(cast(ubyte[]) app[]); + } + + SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind, + string symbolFile, size_t location = 0, const Type type = null) + in + { + assert (symbolAllocator !is null); + } + body + { + ACSymbol* acSymbol = allocate!ACSymbol(symbolAllocator, + name is null ? name : stringCache.intern(name), kind); + acSymbol.location = location; + acSymbol.symbolFile = symbolFile; + symbolsAllocated++; + return allocate!SemanticSymbol(semanticAllocator, acSymbol, type); } /// Current protection type IdType protection; /// Package and module name - string[] moduleName; + UnrolledList!string moduleName; /// Current scope Scope* currentScope; @@ -513,41 +554,47 @@ private: string symbolFile; Module mod; + + CAllocator semanticAllocator; } -string formatNode(T)(const T node) +void formatNode(A, T)(ref A appender, const T node) { - import formatter; - import std.array; - import std.conv; - if (node is null) return ""; - auto app = appender!(char[])(); - auto f = new Formatter!(typeof(app))(app); + if (node is null) + return; + auto f = scoped!(Formatter!(A*))(&appender); f.format(node); - return to!string(app.data); } private: -string[] iotcToStringArray(const IdentifierOrTemplateChain iotc, +string[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc, shared(StringCache)* stringCache) { - string[] parts; - foreach (ioti; iotc.identifiersOrTemplateInstances) + string[] retVal = cast(string[]) allocator.allocate((string[]).sizeof + * iotc.identifiersOrTemplateInstances.length); + foreach (i, ioti; iotc.identifiersOrTemplateInstances) { if (ioti.identifier != tok!"") - parts ~= stringCache.intern(ioti.identifier.text); + retVal[i] = stringCache.intern(ioti.identifier.text); else - parts ~= stringCache.intern(ioti.templateInstance.identifier.text); + retVal[i] = stringCache.intern(ioti.templateInstance.identifier.text); } - return parts; + return retVal; } -private static string convertChainToImportPath(const IdentifierChain ic) +static string convertChainToImportPath(shared(StringCache)* stringCache, + const IdentifierChain ic) { - import std.conv; - import std.algorithm; - import std.range; import std.path; - return to!string(ic.identifiers.map!(a => cast() a.text).join(dirSeparator).array); + QuickAllocator!1024 q; + auto app = Appender!(char, typeof(q), 1024)(q); + scope(exit) q.deallocate(app.mem); + foreach (i, ident; ic.identifiers) + { + app.append(ident.text); + if (i + 1 < ic.identifiers.length) + app.append(dirSeparator); + } + return stringCache.intern(cast(string) app[]); } diff --git a/conversion/second.d b/conversion/second.d index 24fdc1d..8360cac 100644 --- a/conversion/second.d +++ b/conversion/second.d @@ -22,7 +22,9 @@ import conversion.first; import actypes; import semantic; import messages; -import stdx.lexer : StringCache; +import std.lexer : StringCache; +import std.allocator; +import stupidlog; /** * Second pass handles the following: @@ -35,11 +37,12 @@ struct SecondPass { public: - this(ref FirstPass first) + this(FirstPass first) { this.rootSymbol = first.rootSymbol; this.moduleScope = first.moduleScope; this.stringCache = first.stringCache; + this.symbolAllocator = first.symbolAllocator; } void run() @@ -48,6 +51,7 @@ public: resolveImports(moduleScope); } + CAllocator symbolAllocator; SemanticSymbol* rootSymbol; Scope* moduleScope; shared(StringCache)* stringCache; @@ -57,45 +61,74 @@ private: void assignToScopes(ACSymbol* currentSymbol) { Scope* s = moduleScope.getScopeByCursor(currentSymbol.location); - s.symbols.insert(currentSymbol); + if (currentSymbol.kind != CompletionKind.moduleName) + s.symbols.insert(currentSymbol); foreach (part; currentSymbol.parts[]) + { + std.utf.validate(part.name); assignToScopes(part); + } } - // This method is really ugly due to the casts... - static ACSymbol* createImportSymbols(ImportInformation info, - Scope* currentScope, ACSymbol*[] moduleSymbols) + ACSymbol* createImportSymbols(ImportInformation* info, Scope* currentScope, + ACSymbol*[] moduleSymbols) + in { - immutable string firstPart = info.importParts[0]; + assert (info !is null); + foreach (s; moduleSymbols) + assert (s !is null); + } + body + { + immutable string firstPart = info.importParts[].front; +// Log.trace("firstPart = ", firstPart); ACSymbol*[] symbols = currentScope.getSymbolsByName(firstPart); immutable bool found = symbols.length > 0; ACSymbol* firstSymbol = found - ? symbols[0] : new ACSymbol(firstPart, CompletionKind.packageName); + ? symbols[0] : allocate!ACSymbol(symbolAllocator, firstPart, + CompletionKind.packageName); if (!found) - { currentScope.symbols.insert(firstSymbol); - } - ACSymbol* currentSymbol = cast(ACSymbol*) firstSymbol; - foreach (size_t i, string importPart; info.importParts[1 .. $]) +// Log.trace(firstSymbol.name); + ACSymbol* currentSymbol = firstSymbol; + size_t i = 0; + foreach (string importPart; info.importParts[]) { + if (i++ == 0) + continue; symbols = currentSymbol.getPartsByName(importPart); ACSymbol* s = symbols.length > 0 - ? cast(ACSymbol*) symbols[0] : new ACSymbol(importPart, CompletionKind.packageName); + ? cast(ACSymbol*) symbols[0] : allocate!ACSymbol(symbolAllocator, + importPart, CompletionKind.packageName); currentSymbol.parts.insert(s); currentSymbol = s; } currentSymbol.kind = CompletionKind.moduleName; currentSymbol.parts.insert(moduleSymbols); +// Log.trace(currentSymbol.name); return currentSymbol; } void resolveImports(Scope* currentScope) { import modulecache; - foreach (importInfo; currentScope.importInformation) + import std.stdio; + foreach (importInfo; currentScope.importInformation[]) { string location = ModuleCache.resolveImportLoctation(importInfo.modulePath); ACSymbol*[] symbols = location is null ? [] : ModuleCache.getSymbolsInModule(location); + ////// + foreach (s; symbols) + { + try + std.utf.validate(s.name); + catch (Exception e) + { + writeln("Symbols in ", importInfo.modulePath, " are corrupted"); + throw e; + } + } + ////// ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbols); currentScope.symbols.insert(moduleSymbol); currentScope.symbols.insert(symbols); @@ -109,16 +142,16 @@ private: } symbolLoop: foreach (symbol; symbols) { - foreach (tup; importInfo.importedSymbols) + foreach (tup; importInfo.importedSymbols[]) { if (tup[0] != symbol.name) continue symbolLoop; if (tup[1] !is null) { - ACSymbol* s = new ACSymbol(tup[1], + ACSymbol* s = allocate!ACSymbol(symbolAllocator, tup[1], symbol.kind, symbol.type); // TODO: Compiler gets confused here, so cast the types. - s.parts = cast(typeof(s.parts)) symbol.parts; + s.parts.insert(symbol.parts[]); // TODO: Re-format callTip with new name? s.callTip = symbol.callTip; s.doc = symbol.doc; diff --git a/conversion/third.d b/conversion/third.d index f5f9c99..0f4b6bf 100644 --- a/conversion/third.d +++ b/conversion/third.d @@ -18,13 +18,13 @@ module conversion.third; -import stdx.d.ast; -import stdx.d.lexer; +import std.d.ast; +import std.d.lexer; import conversion.second; import semantic; import actypes; import messages; - +import std.allocator; /** * Third pass handles the following: @@ -45,6 +45,7 @@ public: this.moduleScope = second.moduleScope; this.stringCache = second.stringCache; this.name = name; + this.symbolAllocator = second.symbolAllocator; } string name; @@ -56,6 +57,7 @@ public: SemanticSymbol* rootSymbol; Scope* moduleScope; + CAllocator symbolAllocator; private: @@ -147,7 +149,11 @@ private: else if (t.type2.symbol !is null) { // TODO: global scoped symbol handling - string[] symbolParts = expandSymbol( + string[] symbolParts = cast(string[]) Mallocator.it.allocate( + t.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances.length + * string.sizeof); + scope(exit) Mallocator.it.deallocate(symbolParts); + expandSymbol(symbolParts, t.type2.symbol.identifierOrTemplateChain, stringCache, name); auto symbols = moduleScope.getSymbolsByNameAndCursor( symbolParts[0], location); @@ -168,12 +174,9 @@ private: return s; } - static string[] expandSymbol(const IdentifierOrTemplateChain chain, + static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain, shared(StringCache)* stringCache, string n) { - if (chain.identifiersOrTemplateInstances.length == 0) - return []; - string[] strings = new string[chain.identifiersOrTemplateInstances.length]; for (size_t i = 0; i < chain.identifiersOrTemplateInstances.length; ++i) { auto identOrTemplate = chain.identifiersOrTemplateInstances[i]; @@ -183,21 +186,18 @@ private: identOrTemplate.identifier.text : identOrTemplate.templateInstance.identifier.text); } - return strings; } - static ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix) + ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix) { - import std.container; import formatter; if (suffix.star) return symbol; if (suffix.array || suffix.type) { - ACSymbol* s = new ACSymbol(null); - s.parts = new RedBlackTree!(ACSymbol*, comparitor, true); - s.parts.insert(suffix.array ? (cast() arraySymbols)[] - : (cast() assocArraySymbols)[]); + ACSymbol* s = allocate!ACSymbol(symbolAllocator, null); + s.parts.insert(suffix.array ? arraySymbols[] + : assocArraySymbols[]); s.type = symbol; s.qualifier = suffix.array ? SymbolQualifier.array : SymbolQualifier.assocArray; return s; @@ -205,10 +205,17 @@ private: if (suffix.parameters) { import conversion.first; - ACSymbol* s = new ACSymbol(null); + import memory.allocators; + import memory.appender; + ACSymbol* s = allocate!ACSymbol(symbolAllocator, null); s.type = symbol; s.qualifier = SymbolQualifier.func; - s.callTip = suffix.delegateOrFunction.text ~ formatNode(suffix.parameters); + QuickAllocator!1024 q; + auto app = Appender!(char, typeof(q), 1024)(q); + scope(exit) q.deallocate(app.mem); + app.append(suffix.delegateOrFunction.text); + app.formatNode(suffix.parameters); + s.callTip = stringCache.intern(cast(ubyte[]) app[]); return s; } return null; @@ -219,9 +226,8 @@ private: string stringRepresentation = str(type2.builtinType); if (stringRepresentation is null) return null; // TODO: Make this use binary search instead - auto t = cast() builtinSymbols; ACSymbol s = ACSymbol(stringRepresentation); - return t.equalRange(&s).front(); + return builtinSymbols.equalRange(&s).front(); } shared(StringCache)* stringCache; diff --git a/dscanner b/dscanner index 3ddac78..017b90e 160000 --- a/dscanner +++ b/dscanner @@ -1 +1 @@ -Subproject commit 3ddac7885f373c0e5ce7ff1b2670d401d8d482d5 +Subproject commit 017b90e31f2d8bdc0181fa3ac0d6a0e3be0d480e diff --git a/modulecache.d b/modulecache.d index 23734bd..cb640d8 100644 --- a/modulecache.d +++ b/modulecache.d @@ -18,41 +18,49 @@ module modulecache; -import std.file; -import std.datetime; -import stdx.lexer; -import stdx.d.lexer; -import stdx.d.parser; -import stdx.d.ast; -import std.array; -import std.path; import std.algorithm; +import std.allocator; import std.conv; -import std.container; +import std.d.ast; +import std.datetime; +import std.d.lexer; +import std.d.parser; +import std.file; +import std.lexer; +import std.path; import actypes; import semantic; +import memory.allocators; +import containers.karytree; +import containers.hashset; +import containers.unrolledlist; import conversion.astconverter; import conversion.first; import conversion.second; import conversion.third; +import containers.dynamicarray; import stupidlog; - -bool cacheComparitor(CacheEntry* a, CacheEntry* b) pure nothrow -{ - return cast(ubyte[]) a.path < cast(ubyte[]) b.path; -} +import messages; private struct CacheEntry { ACSymbol*[] symbols; SysTime modificationTime; string path; + + int opCmp(ref const CacheEntry other) const + { + if (path < other.path) + return -1; + if (path > other.path) + return 1; + return 0; + } + void opAssign(ref const CacheEntry other) { - this.symbols = cast(typeof(symbols)) other.symbols; - this.path = other.path; - this.modificationTime = other.modificationTime; + assert(false); } } @@ -66,8 +74,8 @@ bool existanceCheck(A)(A path) static this() { - ModuleCache.cache = new RedBlackTree!(CacheEntry*, cacheComparitor); ModuleCache.stringCache = new shared StringCache(StringCache.defaultBucketCount); + ModuleCache.symbolAllocator = new CAllocatorImpl!(BlockAllocator!(1024 * 16)); } /** @@ -77,12 +85,8 @@ struct ModuleCache { @disable this(); - /** - * Clears the completion cache - */ static void clear() { - cache.clear(); } /** @@ -91,15 +95,13 @@ struct ModuleCache static void addImportPaths(string[] paths) { import core.memory; - string[] addedPaths = paths.filter!(a => existanceCheck(a)).array(); - importPaths ~= addedPaths; + foreach (path; paths.filter!(a => existanceCheck(a))) + importPaths.insert(path); - foreach (path; addedPaths) + foreach (path; importPaths[]) { foreach (fileName; dirEntries(path, "*.{d,di}", SpanMode.depth)) { - GC.disable(); - scope(exit) GC.enable(); getSymbolsInModule(fileName); } } @@ -126,29 +128,35 @@ struct ModuleCache Log.info("Getting symbols for ", location); - recursionGuard[location] = true; + recursionGuard.insert(location); ACSymbol*[] symbols; - try - { +// try +// { import core.memory; import std.stdio; + import std.typecons; File f = File(location); - ubyte[] source = (cast(ubyte*) GC.malloc(cast(size_t) f.size, - GC.BlkAttr.NO_SCAN | GC.BlkAttr.NO_MOVE))[0 .. cast(size_t)f.size]; + ubyte[] source = cast(ubyte[]) Mallocator.it.allocate(cast(size_t)f.size); f.rawRead(source); LexerConfig config; config.fileName = location; - shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount); - auto tokens = source.byToken(config, cache).array(); - source[] = 0; - GC.free(source.ptr); - ParseAllocator p = new ParseAllocator(location); - Module m = parseModuleSimple(tokens, location, p); + shared parseStringCache = shared StringCache(StringCache.defaultBucketCount); + auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 64))); + DynamicArray!(Token, false) tokens; + auto tokenRange = byToken( + (source.length >= 3 && source[0 .. 3] == "\xef\xbb\xbf"c) ? source[3 .. $] : source, + config, &parseStringCache); + foreach (t; tokenRange) + tokens.insert(t); + Mallocator.it.deallocate(source); - FirstPass first = new FirstPass(m, location, stringCache); + Module m = parseModuleSimple(tokens[], location, semanticAllocator); + + assert (symbolAllocator); + auto first = scoped!FirstPass(m, location, stringCache, + symbolAllocator, semanticAllocator); first.run(); - cache = null; SecondPass second = SecondPass(first); second.run(); @@ -156,21 +164,28 @@ struct ModuleCache ThirdPass third = ThirdPass(second, location); third.run(); - p.deallocateAll(); - p = null; - symbols = third.rootSymbol.acSymbol.parts.array(); - } - catch (Exception ex) - { - Log.error("Couln't parse ", location, " due to exception: ", ex.msg); - return []; - } + symbols = cast(ACSymbol*[]) Mallocator.it.allocate( + third.rootSymbol.acSymbol.parts.length * (ACSymbol*).sizeof); + size_t i = 0; + foreach (part; third.rootSymbol.acSymbol.parts[]) + symbols[i++] = part; + + typeid(Scope).destroy(third.moduleScope); + typeid(SemanticSymbol).destroy(third.rootSymbol); + symbolsAllocated += first.symbolsAllocated; +// } +// catch (Exception ex) +// { +// Log.error("Couln't parse ", location, " due to exception: ", ex.msg); +// return []; +// } SysTime access; SysTime modification; getTimes(location, access, modification); - CacheEntry* c = new CacheEntry(symbols, modification, location); + CacheEntry* c = allocate!CacheEntry(Mallocator.it, symbols, + modification, stringCache.intern(location)); cache.insert(c); - recursionGuard[location] = false; + recursionGuard.remove(location); return symbols; } @@ -188,39 +203,37 @@ struct ModuleCache string[] alternatives; foreach (path; importPaths) { - string filePath = buildPath(path, moduleName); - if (exists(filePath ~ ".d") && isFile(filePath ~ ".d")) - alternatives = (filePath ~ ".d") ~ alternatives; - else if (exists(filePath ~ ".di") && isFile(filePath ~ ".di")) - alternatives = (filePath ~ ".di") ~ alternatives; - else if (exists(filePath) && isDir(filePath)) + string dotDi = buildPath(path, moduleName) ~ ".di"; + string dotD = dotDi[0 .. $ - 1]; + string withoutSuffix = dotDi[0 .. $ - 2]; + if (exists(dotD) && isFile(dotD)) + alternatives = (dotD) ~ alternatives; + else if (exists(dotDi) && isFile(dotDi)) + alternatives ~= dotDi; + else if (exists(withoutSuffix) && isDir(withoutSuffix)) { - string packagePath = buildPath(filePath, "package.d"); + string packagePath = buildPath(withoutSuffix, "package.di"); if (exists(packagePath) && isFile(packagePath)) { alternatives ~= packagePath; continue; } - packagePath ~= "i"; - if (exists(packagePath) && isFile(packagePath)) - alternatives ~= packagePath; + if (exists(packagePath[0 .. $ - 1]) && isFile(packagePath[0 .. $ - 1])) + alternatives ~= packagePath[0 .. $ - 1]; } } return alternatives.length > 0 ? alternatives[0] : null; } - static const(string[]) getImportPaths() + static auto getImportPaths() { - return cast(const(string[])) importPaths; - } - - static string intern(string s) - { - return s is null || s.length == 0 ? "" : stringCache.intern(s); + return importPaths[]; } static shared(StringCache)* stringCache; + static uint symbolsAllocated; + private: /** @@ -231,9 +244,7 @@ private: */ static bool needsReparsing(string mod) { - if (mod !in recursionGuard) - return true; - if (recursionGuard[mod]) + if (recursionGuard.contains(mod)) return false; if (!exists(mod)) return true; @@ -249,10 +260,12 @@ private: } // Mapping of file paths to their cached symbols. - static RedBlackTree!(CacheEntry*, cacheComparitor) cache; + static KAryTree!(CacheEntry*) cache; - static bool[string] recursionGuard; + static HashSet!string recursionGuard; // Listing of paths to check for imports - static string[] importPaths; + static UnrolledList!string importPaths; + + static CAllocator symbolAllocator; } diff --git a/semantic.d b/semantic.d index 9b3b0ad..06ad3e3 100644 --- a/semantic.d +++ b/semantic.d @@ -20,9 +20,10 @@ module semantic; import messages; import actypes; -import stdx.d.ast; -import stdx.d.lexer; +import std.d.ast; +import std.d.lexer; import stupidlog; +import containers.unrolledlist; /** * Intermediate form between ACSymbol and the AST classes. Stores enough @@ -33,6 +34,7 @@ struct SemanticSymbol public: @disable this(); + @disable this(this); /** * Params: @@ -41,21 +43,24 @@ public: * symbolFile = the file name for this symbol * location = the location of this symbol */ - this(string name, CompletionKind kind, string symbolFile, - size_t location = size_t.max, const Type type = null) + this(ACSymbol* acSymbol, const Type type = null) { - acSymbol = new ACSymbol(name, kind); - acSymbol.location = location; - acSymbol.symbolFile = symbolFile; + this.acSymbol = acSymbol; this.type = type; } + ~this() + { + foreach (child; children[]) + typeid(typeof(*child)).destroy(child); + } + /** * Adds a child to the children field and updates the acSymbol's parts field */ void addChild(SemanticSymbol* child) { - children ~= child; + children.insert(child); acSymbol.parts.insert(child.acSymbol); } @@ -63,16 +68,16 @@ public: ACSymbol* acSymbol; /// Base classes - string[][] baseClasses; + UnrolledList!(string[]) baseClasses; /// Variable type or function return type const Type type; /// Alias this symbols - string[] aliasThis; + UnrolledList!(string) aliasThis; /// MixinTemplates - string[] mixinTemplates; + UnrolledList!(string) mixinTemplates; /// Protection level for this symobol IdType protection; @@ -81,7 +86,7 @@ public: SemanticSymbol* parent; /// Child symbols - SemanticSymbol*[] children; + UnrolledList!(SemanticSymbol*) children; } /** @@ -96,25 +101,29 @@ Type argumentsType; static this() { + import std.allocator; // _argptr has type void* - argptrType = new Type; - argptrType.type2 = new Type2; + argptrType = allocate!Type(Mallocator.it); + argptrType.type2 = allocate!Type2(Mallocator.it); argptrType.type2.builtinType = tok!"void"; - TypeSuffix argptrTypeSuffix = new TypeSuffix; + TypeSuffix argptrTypeSuffix = allocate!TypeSuffix(Mallocator.it); argptrTypeSuffix.star = true; - argptrType.typeSuffixes ~= argptrTypeSuffix; + argptrType.typeSuffixes = cast(TypeSuffix[]) Mallocator.it.allocate(TypeSuffix.sizeof); + argptrType.typeSuffixes[0] = argptrTypeSuffix; // _arguments has type TypeInfo[] - argumentsType = new Type; - argumentsType = new Type; - argumentsType.type2 = new Type2; - argumentsType.type2.symbol = new Symbol; - argumentsType.type2.symbol.identifierOrTemplateChain = new IdentifierOrTemplateChain; - IdentifierOrTemplateInstance i = new IdentifierOrTemplateInstance; + argumentsType = allocate!Type(Mallocator.it); + argumentsType.type2 = allocate!Type2(Mallocator.it); + argumentsType.type2.symbol = allocate!Symbol(Mallocator.it); + argumentsType.type2.symbol.identifierOrTemplateChain = allocate!IdentifierOrTemplateChain(Mallocator.it); + IdentifierOrTemplateInstance i = allocate!IdentifierOrTemplateInstance(Mallocator.it); i.identifier.text = "TypeInfo"; i.identifier.type = tok!"identifier"; - argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances ~= i; - TypeSuffix argumentsTypeSuffix = new TypeSuffix; + argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances = + cast(IdentifierOrTemplateInstance[]) Mallocator.it.allocate(IdentifierOrTemplateInstance.sizeof); + argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances[0] = i; + TypeSuffix argumentsTypeSuffix = allocate!TypeSuffix(Mallocator.it); argumentsTypeSuffix.array = true; - argumentsType.typeSuffixes ~= argptrTypeSuffix; + argumentsType.typeSuffixes = cast(TypeSuffix[]) Mallocator.it.allocate(TypeSuffix.sizeof); + argumentsType.typeSuffixes[0] = argptrTypeSuffix; } diff --git a/server.d b/server.d index 9acbe22..7d6082b 100644 --- a/server.d +++ b/server.d @@ -28,6 +28,9 @@ import std.array; import std.process; import std.datetime; import std.conv; +import std.allocator; + +import core.memory; import msgpack; @@ -92,12 +95,16 @@ int main(string[] args) ModuleCache.addImportPaths(importPaths); Log.info("Import directories: ", ModuleCache.getImportPaths()); - ubyte[] buffer = new ubyte[1024 * 1024 * 4]; // 4 megabytes should be enough for anybody... + ubyte[] buffer = cast(ubyte[]) Mallocator.it.allocate(1024 * 1024 * 4); // 4 megabytes should be enough for anybody... + scope(exit) Mallocator.it.deallocate(buffer); sw.stop(); Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds"); float internBytes = cast(float) ModuleCache.stringCache.allocated / (1024 * 1024); Log.info("String interning took up ", internBytes, " megabytes"); + float symbolMegs = (cast(float) (ACSymbol.sizeof * ModuleCache.symbolsAllocated)) / (1024f * 1024f); + Log.info(ModuleCache.symbolsAllocated, " symbols allocated, taking up ", + symbolMegs, " megabytes"); // No relative paths version (Posix) chdir("/"); @@ -153,17 +160,17 @@ int main(string[] args) Log.info("Shutting down."); break serverLoop; case RequestKind.autocomplete: - try - { +// try +// { AutocompleteResponse response = complete(request); ubyte[] responseBytes = msgpack.pack(response); s.send(responseBytes); - } - catch (Exception e) - { - Log.error("Could not handle autocomplete request due to an exception:", - e.msg); - } +// } +// catch (Exception e) +// { +// Log.error("Could not handle autocomplete request due to an exception:", +// e.msg); +// } break; case RequestKind.doc: try