Skip to content

Commit

Permalink
Handle public imports MUCH more efficiently. Fixes #160
Browse files Browse the repository at this point in the history
  • Loading branch information
Hackerpilot committed Sep 3, 2014
1 parent dcd01fb commit 0783d92
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 78 deletions.
14 changes: 14 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

all: dmd
dmd: dmdserver dmdclient
debug: dmdclient debugserver
gdc: gdcserver gdcclient
ldc: ldcserver ldcclient

Expand Down Expand Up @@ -83,6 +84,13 @@ DMD_SERVER_FLAGS = -Icontainers/src\
-inline\
-ofbin/dcd-server

DEBUG_SERVER_FLAGS = -Icontainers/src\
-Imsgpack-d/src\
-Ilibdparse/src\
-wi\
-g\
-ofbin/dcd-server

GDC_SERVER_FLAGS = -Icontainers/src\
-Imsgpack-d/src\
-Ilibdparse/src\
Expand All @@ -108,6 +116,12 @@ dmdserver:
rm -f containers/src/std/allocator.d
${DMD} ${SERVER_SRC} ${DMD_SERVER_FLAGS}

debugserver:
mkdir -p bin
rm -f containers/src/std/allocator.d
${DMD} ${SERVER_SRC} ${DEBUG_SERVER_FLAGS}


gdcclient:
mkdir -p bin
rm -f containers/src/std/allocator.d
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ sonar.projectKey=dcd
sonar.projectName=DCD
sonar.projectVersion=1.0
sonar.sourceEncoding=UTF-8
sonar.sources=.
sonar.sources=src
59 changes: 49 additions & 10 deletions src/actypes.d
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ module actypes;
import std.algorithm;
import std.array;
import std.container;
//import std.stdio;
import std.typecons;
import std.allocator;

Expand Down Expand Up @@ -55,6 +54,9 @@ struct ACSymbol
{
public:

/**
* Copying is disabled.
*/
@disable this();

/**
Expand Down Expand Up @@ -115,12 +117,18 @@ public:
*/
ACSymbol*[] getPartsByName(string name)
{
import std.range : chain;
ACSymbol s = ACSymbol(name);
auto er = parts.equalRange(&s);
if (er.empty)
return array(aliasThisParts.equalRange(&s));
else
return array(er);
ACSymbol p = ACSymbol(IMPORT_SYMBOL_NAME);
auto app = appender!(ACSymbol*[])();
foreach (part; parts.equalRange(&s))
app.put(part);
foreach (extra; extraSymbols.equalRange(&s))
app.put(extra.getPartsByName(name));
foreach (im; parts.equalRange(&p))
foreach (part; im.type.parts.equalRange(&s))
app.put(part);
return app.data();
}

/**
Expand Down Expand Up @@ -231,11 +239,16 @@ struct Scope
if (s is null)
return [];
UnrolledList!(ACSymbol*) symbols;
symbols.insert(s.symbols[]);
Scope* sc = s.parent;
Scope* sc = s;
while (sc !is null)
{
symbols.insert(sc.symbols[]);
foreach (item; sc.symbols[])
{
if (item.kind == CompletionKind.importSymbol) foreach (i; item.type.parts[])
symbols.insert(i);
else
symbols.insert(item);
}
sc = sc.parent;
}
return array(symbols[]);
Expand All @@ -253,7 +266,18 @@ struct Scope
ACSymbol s = ACSymbol(name);
auto er = symbols.equalRange(&s);
if (!er.empty)
return cast(typeof(return)) array(er);
return array(er);
ACSymbol ir = ACSymbol(IMPORT_SYMBOL_NAME);
auto r = symbols.equalRange(&ir);
if (!r.empty)
{
auto app = appender!(ACSymbol*[])();
foreach (e; r)
foreach (importedSymbol; e.type.parts.equalRange(&s))
app.put(importedSymbol);
if (app.data.length > 0)
return app.data;
}
if (parent is null)
return [];
return parent.getSymbolsByName(name);
Expand All @@ -275,6 +299,9 @@ struct Scope
return s.getSymbolsByName(name);
}

/**
* Returns an array of symbols that are present at global scope
*/
ACSymbol*[] getSymbolsAtGlobalScope(string name)
{
if (parent !is null)
Expand Down Expand Up @@ -344,6 +371,16 @@ TTree!(ACSymbol*, true, "a < b", false) classSymbols;

private immutable(string[24]) builtinTypeNames;

/**
* Name given to the public import symbol. Its value is "public" because this
* is not a valid identifier. This is initialized to an interned string during
* static construction.
*/
immutable string IMPORT_SYMBOL_NAME;

/**
* Translates the IDs for built-in types into an interned string.
*/
string getBuiltinTypeName(IdType id)
{
switch (id)
Expand Down Expand Up @@ -407,6 +444,8 @@ static this()
builtinTypeNames[22] = internString("cfloat");
builtinTypeNames[23] = internString("creal");

IMPORT_SYMBOL_NAME = internString("public");


auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword);
auto int_ = allocate!ACSymbol(Mallocator.it, "int", CompletionKind.keyword);
Expand Down
6 changes: 4 additions & 2 deletions src/autocomplete.d
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,

bool isSelectiveImport(T)(T tokens)
{
assert (tokens.length > 1);
size_t i = tokens.length - 1;
if (!(tokens[i] == tok!":" || tokens[i] == tok!","))
return false;
Expand Down Expand Up @@ -391,7 +392,7 @@ body
auto symbols = ModuleCache.getSymbolsInModule(ModuleCache.resolveImportLoctation(path));
import containers.hashset;
HashSet!string h;
foreach (s; symbols)
foreach (s; symbols.parts[])
{
auto a = ACSymbol(s.name);
if (!builtinSymbols.contains(&a) && !h.contains(s.name))
Expand Down Expand Up @@ -630,7 +631,8 @@ void setCompletions(T)(ref AutocompleteResponse response,
}
TTree!(ACSymbol*, true, "a < b", false) parts;
parts.insert(symbols[0].parts[]);
parts.insert(symbols[0].aliasThisParts[]);
foreach (s; symbols[0].extraSymbols[])
parts.insert(s.parts[]);
foreach (s; parts[].filter!(a => a.name !is null
&& a.name.length > 0 && a.name[0] != '*'
&& (partial is null ? true : a.name.toUpper().startsWith(partial.toUpper()))
Expand Down
13 changes: 3 additions & 10 deletions src/conversion/first.d
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,11 @@ final class FirstPass : ASTVisitor
rootSymbol = currentSymbol;
currentScope = allocate!Scope(semanticAllocator, 0, size_t.max);
auto i = allocate!ImportInformation(semanticAllocator);
i.modulePath = "object";
i.importParts.insert("object");
i.modulePath = internString("object");
i.importParts.insert(i.modulePath);
currentScope.importInformation.insert(i);
moduleScope = currentScope;
mod.accept(this);
assert (currentSymbol.acSymbol.name is null);
}

override void visit(const EnumDeclaration dec)
Expand Down Expand Up @@ -328,10 +327,7 @@ final class FirstPass : ASTVisitor
override void visit(const ModuleDeclaration moduleDeclaration)
{
// Log.trace(__FUNCTION__, " ", typeof(dec).stringof);
foreach (identifier; moduleDeclaration.moduleName.identifiers)
{
moduleName.insert(internString(identifier.text));
}
rootSymbol.acSymbol.name = internString(moduleDeclaration.moduleName.identifiers[$ - 1].text);
}

override void visit(const StructBody structBody)
Expand Down Expand Up @@ -616,9 +612,6 @@ private:
/// Current protection type
IdType protection;

/// Package and module name
UnrolledList!string moduleName;

/// Current scope
Scope* currentScope;

Expand Down
64 changes: 33 additions & 31 deletions src/conversion/second.d
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import semantic;
import messages;
import std.allocator;
import stupidlog;
import string_interning;

/**
* Second pass handles the following:
Expand Down Expand Up @@ -68,42 +69,43 @@ private:
}
}

/**
* Creates package symbols as necessary to contain the given module symbol
*/
ACSymbol* createImportSymbols(ImportInformation* info, Scope* currentScope,
ACSymbol*[] moduleSymbols)
ACSymbol* moduleSymbol)
in
{
assert (info !is null);
foreach (s; moduleSymbols)
assert (s !is null);
assert (moduleSymbol !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] : allocate!ACSymbol(symbolAllocator, firstPart,
ACSymbol* firstSymbol = void;
if (symbols.length > 0)
firstSymbol = symbols[0];
else
firstSymbol = allocate!ACSymbol(symbolAllocator, firstPart,
CompletionKind.packageName);
if (!found)
currentScope.symbols.insert(firstSymbol);
// Log.trace(firstSymbol.name);
currentScope.symbols.insert(firstSymbol);
ACSymbol* currentSymbol = firstSymbol;
size_t i = 0;
foreach (string importPart; info.importParts[])
{
if (i++ == 0)
continue;
if (i + 2 >= info.importParts.length) // Skip the last item as it's the module name
break;
symbols = currentSymbol.getPartsByName(importPart);
ACSymbol* s = symbols.length > 0
? 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);
currentSymbol.parts.insert(moduleSymbol);
return currentSymbol;
}

Expand All @@ -114,19 +116,21 @@ private:
foreach (importInfo; currentScope.importInformation[])
{
string location = ModuleCache.resolveImportLoctation(importInfo.modulePath);
ACSymbol*[] symbols = location is null ? [] : ModuleCache.getSymbolsInModule(location);
ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbols);
currentScope.symbols.insert(moduleSymbol);
currentScope.symbols.insert(symbols);
ACSymbol* symbol = location is null ? null : ModuleCache.getSymbolsInModule(location);
if (symbol is null)
continue;
ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbol);
currentScope.symbols.insert(symbol.parts[]);
if (importInfo.importedSymbols.length == 0)
{
if (importInfo.isPublic && currentScope.parent is null)
{
rootSymbol.acSymbol.parts.insert(symbols);
rootSymbol.acSymbol.parts.insert(allocate!ACSymbol(symbolAllocator,
IMPORT_SYMBOL_NAME, CompletionKind.importSymbol, symbol));
}
continue;
}
symbolLoop: foreach (symbol; symbols)
symbolLoop: foreach (sym; symbol.parts[])
{
foreach (tup; importInfo.importedSymbols[])
{
Expand All @@ -135,26 +139,24 @@ private:
if (tup[1] !is null)
{
ACSymbol* s = allocate!ACSymbol(symbolAllocator, tup[1],
symbol.kind, symbol.type);
// TODO: Compiler gets confused here, so cast the types.
s.parts.insert(symbol.parts[]);
// TODO: Re-format callTip with new name?
s.callTip = symbol.callTip;
s.doc = symbol.doc;
s.qualifier = symbol.qualifier;
s.location = symbol.location;
s.symbolFile = symbol.symbolFile;
sym.kind, sym.type);
s.parts.insert(sym.parts[]);
s.callTip = sym.callTip;
s.doc = sym.doc;
s.qualifier = sym.qualifier;
s.location = sym.location;
s.symbolFile = sym.symbolFile;
currentScope.symbols.insert(s);
moduleSymbol.parts.insert(s);
if (importInfo.isPublic && currentScope.parent is null)
rootSymbol.acSymbol.parts.insert(s);
}
else
{
moduleSymbol.parts.insert(symbol);
currentScope.symbols.insert(symbol);
moduleSymbol.parts.insert(sym);
currentScope.symbols.insert(sym);
if (importInfo.isPublic && currentScope.parent is null)
rootSymbol.acSymbol.parts.insert(symbol);
rootSymbol.acSymbol.parts.insert(sym);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/conversion/third.d
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private:
case assocArray:
case templateName:
case mixinTemplateName:
case importSymbol:
break;
}

Expand Down Expand Up @@ -145,7 +146,7 @@ private:
auto parts = currentSymbol.acSymbol.getPartsByName(aliasThis);
if (parts.length == 0 || parts[0].type is null)
continue;
currentSymbol.acSymbol.aliasThisParts.insert(parts[0].type.parts[]);
currentSymbol.acSymbol.aliasThisParts.insert(parts[0].type);
}
}

Expand Down
Loading

0 comments on commit 0783d92

Please sign in to comment.