Use string interning for a very nice speed boost
This commit is contained in:
parent
7eb952e0e5
commit
ae91019ab4
97
actypes.d
97
actypes.d
|
|
@ -21,16 +21,17 @@ module actypes;
|
||||||
import std.algorithm;
|
import std.algorithm;
|
||||||
import std.array;
|
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 std.allocator;
|
||||||
|
|
||||||
import containers.karytree;
|
import containers.ttree;
|
||||||
import containers.unrolledlist;
|
import containers.unrolledlist;
|
||||||
import containers.slist;
|
import containers.slist;
|
||||||
import std.d.lexer;
|
import std.d.lexer;
|
||||||
|
|
||||||
import messages;
|
import messages;
|
||||||
|
import string_interning;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any special information about a variable declaration symbol.
|
* Any special information about a variable declaration symbol.
|
||||||
|
|
@ -62,7 +63,7 @@ public:
|
||||||
*/
|
*/
|
||||||
this(string name)
|
this(string name)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name is null ? name : internString(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,7 +73,7 @@ public:
|
||||||
*/
|
*/
|
||||||
this(string name, CompletionKind kind)
|
this(string name, CompletionKind kind)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name is null ? name : internString(name);
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,16 +85,18 @@ public:
|
||||||
*/
|
*/
|
||||||
this(string name, CompletionKind kind, ACSymbol* type)
|
this(string name, CompletionKind kind, ACSymbol* type)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name is null ? name : internString(name);
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opCmp(ref const ACSymbol other) const
|
int opCmp(ref const ACSymbol other) const
|
||||||
{
|
{
|
||||||
if (name < other.name)
|
// Compare the pointers because the strings have been interned.
|
||||||
|
// Identical strings MUST have the same address
|
||||||
|
if (name.ptr < other.name.ptr)
|
||||||
return -1;
|
return -1;
|
||||||
if (name > other.name)
|
if (name.ptr > other.name.ptr)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +114,7 @@ public:
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
KAryTree!(ACSymbol*, true, "a < b", false) parts;
|
TTree!(ACSymbol*, true, "a < b", false) parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbol's name
|
* Symbol's name
|
||||||
|
|
@ -275,7 +278,7 @@ struct Scope
|
||||||
size_t endLocation;
|
size_t endLocation;
|
||||||
|
|
||||||
/// Symbols contained in this scope
|
/// Symbols contained in this scope
|
||||||
KAryTree!(ACSymbol*, true, "a < b", false) symbols;
|
TTree!(ACSymbol*, true, "a < b", false) symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -297,33 +300,94 @@ struct ImportInformation
|
||||||
/**
|
/**
|
||||||
* Symbols for the built in types
|
* Symbols for the built in types
|
||||||
*/
|
*/
|
||||||
KAryTree!(ACSymbol*, true) builtinSymbols;
|
TTree!(ACSymbol*, true, "a < b", false) builtinSymbols;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array properties
|
* Array properties
|
||||||
*/
|
*/
|
||||||
KAryTree!(ACSymbol*, true) arraySymbols;
|
TTree!(ACSymbol*, true, "a < b", false) arraySymbols;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associative array properties
|
* Associative array properties
|
||||||
*/
|
*/
|
||||||
KAryTree!(ACSymbol*, true) assocArraySymbols;
|
TTree!(ACSymbol*, true, "a < b", false) assocArraySymbols;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum, union, class, and interface properties
|
* Enum, union, class, and interface properties
|
||||||
*/
|
*/
|
||||||
KAryTree!(ACSymbol*, true) aggregateSymbols;
|
TTree!(ACSymbol*, true, "a < b", false) aggregateSymbols;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class properties
|
* Class properties
|
||||||
*/
|
*/
|
||||||
KAryTree!(ACSymbol*, true) classSymbols;
|
TTree!(ACSymbol*, true, "a < b", false) classSymbols;
|
||||||
|
|
||||||
|
private immutable(string[24]) builtinTypeNames;
|
||||||
|
|
||||||
|
string getBuiltinTypeName(IdType id)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case tok!"int": return builtinTypeNames[0];
|
||||||
|
case tok!"uint": return builtinTypeNames[1];
|
||||||
|
case tok!"double": return builtinTypeNames[2];
|
||||||
|
case tok!"idouble": return builtinTypeNames[3];
|
||||||
|
case tok!"float": return builtinTypeNames[4];
|
||||||
|
case tok!"ifloat": return builtinTypeNames[5];
|
||||||
|
case tok!"short": return builtinTypeNames[6];
|
||||||
|
case tok!"ushort": return builtinTypeNames[7];
|
||||||
|
case tok!"long": return builtinTypeNames[8];
|
||||||
|
case tok!"ulong": return builtinTypeNames[9];
|
||||||
|
case tok!"char": return builtinTypeNames[10];
|
||||||
|
case tok!"wchar": return builtinTypeNames[11];
|
||||||
|
case tok!"dchar": return builtinTypeNames[12];
|
||||||
|
case tok!"bool": return builtinTypeNames[13];
|
||||||
|
case tok!"void": return builtinTypeNames[14];
|
||||||
|
case tok!"cent": return builtinTypeNames[15];
|
||||||
|
case tok!"ucent": return builtinTypeNames[16];
|
||||||
|
case tok!"real": return builtinTypeNames[17];
|
||||||
|
case tok!"ireal": return builtinTypeNames[18];
|
||||||
|
case tok!"byte": return builtinTypeNames[19];
|
||||||
|
case tok!"ubyte": return builtinTypeNames[20];
|
||||||
|
case tok!"cdouble": return builtinTypeNames[21];
|
||||||
|
case tok!"cfloat": return builtinTypeNames[22];
|
||||||
|
case tok!"creal": return builtinTypeNames[23];
|
||||||
|
default: assert (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes builtin types and the various properties of builtin types
|
* Initializes builtin types and the various properties of builtin types
|
||||||
*/
|
*/
|
||||||
static this()
|
static this()
|
||||||
{
|
{
|
||||||
|
builtinTypeNames[0] = internString("int");
|
||||||
|
builtinTypeNames[1] = internString("uint");
|
||||||
|
builtinTypeNames[2] = internString("double");
|
||||||
|
builtinTypeNames[3] = internString("idouble");
|
||||||
|
builtinTypeNames[4] = internString("float");
|
||||||
|
builtinTypeNames[5] = internString("ifloat");
|
||||||
|
builtinTypeNames[6] = internString("short");
|
||||||
|
builtinTypeNames[7] = internString("ushort");
|
||||||
|
builtinTypeNames[8] = internString("long");
|
||||||
|
builtinTypeNames[9] = internString("ulong");
|
||||||
|
builtinTypeNames[10] = internString("char");
|
||||||
|
builtinTypeNames[11] = internString("wchar");
|
||||||
|
builtinTypeNames[12] = internString("dchar");
|
||||||
|
builtinTypeNames[13] = internString("bool");
|
||||||
|
builtinTypeNames[14] = internString("void");
|
||||||
|
builtinTypeNames[15] = internString("cent");
|
||||||
|
builtinTypeNames[16] = internString("ucent");
|
||||||
|
builtinTypeNames[17] = internString("real");
|
||||||
|
builtinTypeNames[18] = internString("ireal");
|
||||||
|
builtinTypeNames[19] = internString("byte");
|
||||||
|
builtinTypeNames[20] = internString("ubyte");
|
||||||
|
builtinTypeNames[21] = internString("cdouble");
|
||||||
|
builtinTypeNames[22] = internString("cfloat");
|
||||||
|
builtinTypeNames[23] = internString("creal");
|
||||||
|
|
||||||
|
|
||||||
auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword);
|
auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword);
|
||||||
auto int_ = allocate!ACSymbol(Mallocator.it, "int", CompletionKind.keyword);
|
auto int_ = allocate!ACSymbol(Mallocator.it, "int", CompletionKind.keyword);
|
||||||
auto long_ = allocate!ACSymbol(Mallocator.it, "long", CompletionKind.keyword);
|
auto long_ = allocate!ACSymbol(Mallocator.it, "long", CompletionKind.keyword);
|
||||||
|
|
@ -492,5 +556,10 @@ static this()
|
||||||
builtinSymbols.insert(real_);
|
builtinSymbols.insert(real_);
|
||||||
builtinSymbols.insert(ucent_);
|
builtinSymbols.insert(ucent_);
|
||||||
builtinSymbols.insert(void_);
|
builtinSymbols.insert(void_);
|
||||||
|
|
||||||
|
// writeln(">>Builtin symbols");
|
||||||
|
// foreach (symbol; builtinSymbols[])
|
||||||
|
// writeln(symbol.name, " ", symbol.name.ptr);
|
||||||
|
// writeln("<<Builtin symbols");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -166,12 +166,10 @@ AutocompleteResponse complete(const AutocompleteRequest request)
|
||||||
case tok!"]":
|
case tok!"]":
|
||||||
case tok!"this":
|
case tok!"this":
|
||||||
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
|
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
|
||||||
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
|
|
||||||
Scope* completionScope = generateAutocompleteTrees(tokenArray,
|
Scope* completionScope = generateAutocompleteTrees(tokenArray,
|
||||||
"stdin", allocator, semanticAllocator, cache);
|
"stdin", allocator, semanticAllocator);
|
||||||
scope(exit) typeid(Scope).destroy(completionScope);
|
scope(exit) typeid(Scope).destroy(completionScope);
|
||||||
auto expression = getExpression(beforeTokens);
|
response.setCompletions(completionScope, getExpression(beforeTokens),
|
||||||
response.setCompletions(completionScope, expression,
|
|
||||||
request.cursorPosition, CompletionType.identifiers, partial);
|
request.cursorPosition, CompletionType.identifiers, partial);
|
||||||
break;
|
break;
|
||||||
case tok!"(":
|
case tok!"(":
|
||||||
|
|
@ -199,7 +197,7 @@ auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition,
|
||||||
{
|
{
|
||||||
LexerConfig config;
|
LexerConfig config;
|
||||||
config.fileName = "stdin";
|
config.fileName = "stdin";
|
||||||
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
|
StringCache* cache = new StringCache(StringCache.defaultBucketCount);
|
||||||
auto tokens = byToken(cast(ubyte[]) sourceCode, config, cache);
|
auto tokens = byToken(cast(ubyte[]) sourceCode, config, cache);
|
||||||
tokenArray = tokens.array();
|
tokenArray = tokens.array();
|
||||||
auto sortedTokens = assumeSorted(tokenArray);
|
auto sortedTokens = assumeSorted(tokenArray);
|
||||||
|
|
@ -221,9 +219,8 @@ ACSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request,
|
||||||
auto beforeTokens = getTokensBeforeCursor(request.sourceCode,
|
auto beforeTokens = getTokensBeforeCursor(request.sourceCode,
|
||||||
request.cursorPosition, tokenArray);
|
request.cursorPosition, tokenArray);
|
||||||
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
|
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
|
||||||
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
|
|
||||||
Scope* completionScope = generateAutocompleteTrees(tokenArray,
|
Scope* completionScope = generateAutocompleteTrees(tokenArray,
|
||||||
"stdin", allocator, semanticAllocator, cache);
|
"stdin", allocator, semanticAllocator);
|
||||||
scope(exit) typeid(Scope).destroy(completionScope);
|
scope(exit) typeid(Scope).destroy(completionScope);
|
||||||
auto expression = getExpression(beforeTokens);
|
auto expression = getExpression(beforeTokens);
|
||||||
return getSymbolsByTokenChain(completionScope, expression,
|
return getSymbolsByTokenChain(completionScope, expression,
|
||||||
|
|
@ -273,9 +270,8 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
||||||
case tok!")":
|
case tok!")":
|
||||||
case tok!"]":
|
case tok!"]":
|
||||||
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
|
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
|
||||||
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
|
|
||||||
Scope* completionScope = generateAutocompleteTrees(tokenArray,
|
Scope* completionScope = generateAutocompleteTrees(tokenArray,
|
||||||
"stdin", allocator, semanticAllocator, cache);
|
"stdin", allocator, semanticAllocator);
|
||||||
scope(exit) typeid(Scope).destroy(completionScope);
|
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,
|
||||||
|
|
@ -587,7 +583,7 @@ T getExpression(T)(T beforeTokens)
|
||||||
case tok!"identifier":
|
case tok!"identifier":
|
||||||
if (hasSpecialPrefix)
|
if (hasSpecialPrefix)
|
||||||
i++;
|
i++;
|
||||||
break expressionLoop;
|
break;
|
||||||
case tok!".":
|
case tok!".":
|
||||||
break;
|
break;
|
||||||
case tok!"*":
|
case tok!"*":
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -O -ofdcd-client
|
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/appender.d containers/src/memory/allocators.d containers/src/containers/dynamicarray.d containers/src/containers/karytree.d containers/src/containers/hashset.d containers/src/containers/unrolledlist.d containers/src/containers/internal/hash.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server
|
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 string_interning.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/appender.d containers/src/memory/allocators.d containers/src/containers/dynamicarray.d containers/src/containers/karytree.d containers/src/containers/hashset.d containers/src/containers/unrolledlist.d containers/src/containers/internal/hash.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server
|
||||||
|
|
|
||||||
5
build.sh
5
build.sh
|
|
@ -22,6 +22,7 @@ dmd\
|
||||||
semantic.d\
|
semantic.d\
|
||||||
server.d\
|
server.d\
|
||||||
stupidlog.d\
|
stupidlog.d\
|
||||||
|
string_interning.d\
|
||||||
dscanner/std/d/ast.d\
|
dscanner/std/d/ast.d\
|
||||||
dscanner/std/d/entities.d\
|
dscanner/std/d/entities.d\
|
||||||
dscanner/std/d/lexer.d\
|
dscanner/std/d/lexer.d\
|
||||||
|
|
@ -32,7 +33,7 @@ dmd\
|
||||||
containers/src/memory/allocators.d\
|
containers/src/memory/allocators.d\
|
||||||
containers/src/memory/appender.d\
|
containers/src/memory/appender.d\
|
||||||
containers/src/containers/dynamicarray.d\
|
containers/src/containers/dynamicarray.d\
|
||||||
containers/src/containers/karytree.d\
|
containers/src/containers/ttree.d\
|
||||||
containers/src/containers/unrolledlist.d\
|
containers/src/containers/unrolledlist.d\
|
||||||
containers/src/containers/hashset.d\
|
containers/src/containers/hashset.d\
|
||||||
containers/src/containers/internal/hash.d\
|
containers/src/containers/internal/hash.d\
|
||||||
|
|
@ -41,7 +42,7 @@ dmd\
|
||||||
-Icontainers/src\
|
-Icontainers/src\
|
||||||
-Imsgpack-d/src\
|
-Imsgpack-d/src\
|
||||||
-Idscanner\
|
-Idscanner\
|
||||||
-wi -O -release -inline\
|
-wi -O -release\
|
||||||
-ofdcd-server
|
-ofdcd-server
|
||||||
|
|
||||||
#gdc client.d\
|
#gdc client.d\
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 819133564a8ebb99672d08774e6731e860e2d103
|
Subproject commit dfb5bec85daad42752074b5206f5f78c03147c97
|
||||||
|
|
@ -30,11 +30,10 @@ import std.d.parser;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
|
|
||||||
Scope* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile,
|
Scope* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile,
|
||||||
CAllocator symbolAllocator, CAllocator semanticAllocator,
|
CAllocator symbolAllocator, CAllocator semanticAllocator)
|
||||||
shared(StringCache)* cache)
|
|
||||||
{
|
{
|
||||||
Module m = parseModule(tokens, "editor buffer", semanticAllocator, &doesNothing);
|
Module m = parseModule(tokens, "editor buffer", semanticAllocator, &doesNothing);
|
||||||
auto first = scoped!FirstPass(m, symbolFile, cache, symbolAllocator,
|
auto first = scoped!FirstPass(m, symbolFile, symbolAllocator,
|
||||||
semanticAllocator);
|
semanticAllocator);
|
||||||
first.run();
|
first.run();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import std.d.lexer;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import stupidlog;
|
import stupidlog;
|
||||||
import containers.unrolledlist;
|
import containers.unrolledlist;
|
||||||
|
import string_interning;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First Pass handles the following:
|
* First Pass handles the following:
|
||||||
|
|
@ -46,8 +47,8 @@ import containers.unrolledlist;
|
||||||
*/
|
*/
|
||||||
final class FirstPass : ASTVisitor
|
final class FirstPass : ASTVisitor
|
||||||
{
|
{
|
||||||
this(Module mod, string symbolFile, shared(StringCache)* stringCache,
|
this(Module mod, string symbolFile, CAllocator symbolAllocator,
|
||||||
CAllocator symbolAllocator, CAllocator semanticAllocator)
|
CAllocator semanticAllocator)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert (symbolAllocator);
|
assert (symbolAllocator);
|
||||||
|
|
@ -56,7 +57,6 @@ final class FirstPass : ASTVisitor
|
||||||
{
|
{
|
||||||
this.mod = mod;
|
this.mod = mod;
|
||||||
this.symbolFile = symbolFile;
|
this.symbolFile = symbolFile;
|
||||||
this.stringCache = stringCache;
|
|
||||||
this.symbolAllocator = symbolAllocator;
|
this.symbolAllocator = symbolAllocator;
|
||||||
this.semanticAllocator = semanticAllocator;
|
this.semanticAllocator = semanticAllocator;
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +168,7 @@ final class FirstPass : ASTVisitor
|
||||||
{
|
{
|
||||||
// Log.trace(__FUNCTION__, " ", typeof(bc).stringof);
|
// Log.trace(__FUNCTION__, " ", typeof(bc).stringof);
|
||||||
currentSymbol.baseClasses.insert(iotcToStringArray(symbolAllocator,
|
currentSymbol.baseClasses.insert(iotcToStringArray(symbolAllocator,
|
||||||
bc.identifierOrTemplateChain, stringCache));
|
bc.identifierOrTemplateChain));
|
||||||
}
|
}
|
||||||
|
|
||||||
override void visit(const VariableDeclaration dec)
|
override void visit(const VariableDeclaration dec)
|
||||||
|
|
@ -237,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.insert(stringCache.intern(dec.identifier.text));
|
currentSymbol.aliasThis.insert(internString(dec.identifier.text));
|
||||||
}
|
}
|
||||||
|
|
||||||
override void visit(const Declaration dec)
|
override void visit(const Declaration dec)
|
||||||
|
|
@ -306,7 +306,7 @@ 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.insert(stringCache.intern(identifier.text));
|
moduleName.insert(internString(identifier.text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,8 +340,8 @@ final class FirstPass : ASTVisitor
|
||||||
{
|
{
|
||||||
auto info = allocate!ImportInformation(semanticAllocator);
|
auto info = allocate!ImportInformation(semanticAllocator);
|
||||||
foreach (identifier; single.identifierChain.identifiers)
|
foreach (identifier; single.identifierChain.identifiers)
|
||||||
info.importParts.insert(stringCache.intern(identifier.text));
|
info.importParts.insert(internString(identifier.text));
|
||||||
info.modulePath = convertChainToImportPath(stringCache, single.identifierChain);
|
info.modulePath = convertChainToImportPath(single.identifierChain);
|
||||||
info.isPublic = protection == tok!"public";
|
info.isPublic = protection == tok!"public";
|
||||||
currentScope.importInformation.insert(info);
|
currentScope.importInformation.insert(info);
|
||||||
}
|
}
|
||||||
|
|
@ -349,18 +349,18 @@ final class FirstPass : ASTVisitor
|
||||||
if (importDeclaration.importBindings.singleImport.identifierChain is null) return;
|
if (importDeclaration.importBindings.singleImport.identifierChain is null) return;
|
||||||
auto info = allocate!ImportInformation(semanticAllocator);
|
auto info = allocate!ImportInformation(semanticAllocator);
|
||||||
|
|
||||||
info.modulePath = convertChainToImportPath(stringCache,
|
info.modulePath = convertChainToImportPath(
|
||||||
importDeclaration.importBindings.singleImport.identifierChain);
|
importDeclaration.importBindings.singleImport.identifierChain);
|
||||||
foreach (identifier; importDeclaration.importBindings.singleImport
|
foreach (identifier; importDeclaration.importBindings.singleImport
|
||||||
.identifierChain.identifiers)
|
.identifierChain.identifiers)
|
||||||
{
|
{
|
||||||
info.importParts.insert(stringCache.intern(identifier.text));
|
info.importParts.insert(internString(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] = internString(bind.left.text);
|
||||||
bindTuple[1] = bind.right == tok!"" ? null : stringCache.intern(bind.right.text);
|
bindTuple[1] = bind.right == tok!"" ? null : internString(bind.right.text);
|
||||||
info.importedSymbols.insert(bindTuple);
|
info.importedSymbols.insert(bindTuple);
|
||||||
}
|
}
|
||||||
info.isPublic = protection == tok!"public";
|
info.isPublic = protection == tok!"public";
|
||||||
|
|
@ -412,8 +412,6 @@ final class FirstPass : ASTVisitor
|
||||||
/// The module
|
/// The module
|
||||||
SemanticSymbol* rootSymbol;
|
SemanticSymbol* rootSymbol;
|
||||||
|
|
||||||
shared(StringCache)* stringCache;
|
|
||||||
|
|
||||||
CAllocator symbolAllocator;
|
CAllocator symbolAllocator;
|
||||||
|
|
||||||
uint symbolsAllocated;
|
uint symbolsAllocated;
|
||||||
|
|
@ -431,7 +429,7 @@ private:
|
||||||
symbol.acSymbol.parts.insert(aggregateSymbols[]);
|
symbol.acSymbol.parts.insert(aggregateSymbols[]);
|
||||||
symbol.parent = currentSymbol;
|
symbol.parent = currentSymbol;
|
||||||
symbol.protection = protection;
|
symbol.protection = protection;
|
||||||
symbol.acSymbol.doc = stringCache.intern(dec.comment);
|
symbol.acSymbol.doc = internString(dec.comment);
|
||||||
currentSymbol = symbol;
|
currentSymbol = symbol;
|
||||||
dec.accept(this);
|
dec.accept(this);
|
||||||
currentSymbol = symbol.parent;
|
currentSymbol = symbol.parent;
|
||||||
|
|
@ -446,7 +444,7 @@ private:
|
||||||
processParameters(symbol, null, "this", parameters, doc);
|
processParameters(symbol, null, "this", parameters, doc);
|
||||||
symbol.protection = protection;
|
symbol.protection = protection;
|
||||||
symbol.parent = currentSymbol;
|
symbol.parent = currentSymbol;
|
||||||
symbol.acSymbol.doc = stringCache.intern(doc);
|
symbol.acSymbol.doc = internString(doc);
|
||||||
currentSymbol.addChild(symbol);
|
currentSymbol.addChild(symbol);
|
||||||
if (functionBody !is null)
|
if (functionBody !is null)
|
||||||
{
|
{
|
||||||
|
|
@ -463,7 +461,7 @@ private:
|
||||||
symbol.acSymbol.callTip = "~this()";
|
symbol.acSymbol.callTip = "~this()";
|
||||||
symbol.protection = protection;
|
symbol.protection = protection;
|
||||||
symbol.parent = currentSymbol;
|
symbol.parent = currentSymbol;
|
||||||
symbol.acSymbol.doc = stringCache.intern(doc);
|
symbol.acSymbol.doc = internString(doc);
|
||||||
currentSymbol.addChild(symbol);
|
currentSymbol.addChild(symbol);
|
||||||
if (functionBody !is null)
|
if (functionBody !is null)
|
||||||
{
|
{
|
||||||
|
|
@ -519,7 +517,7 @@ private:
|
||||||
app.put("()");
|
app.put("()");
|
||||||
else
|
else
|
||||||
app.formatNode(parameters);
|
app.formatNode(parameters);
|
||||||
return stringCache.intern(cast(ubyte[]) app[]);
|
return internString(cast(string) app[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind,
|
SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind,
|
||||||
|
|
@ -530,8 +528,7 @@ private:
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
ACSymbol* acSymbol = allocate!ACSymbol(symbolAllocator,
|
ACSymbol* acSymbol = allocate!ACSymbol(symbolAllocator, name, kind);
|
||||||
name is null ? name : stringCache.intern(name), kind);
|
|
||||||
acSymbol.location = location;
|
acSymbol.location = location;
|
||||||
acSymbol.symbolFile = symbolFile;
|
acSymbol.symbolFile = symbolFile;
|
||||||
symbolsAllocated++;
|
symbolsAllocated++;
|
||||||
|
|
@ -568,23 +565,21 @@ void formatNode(A, T)(ref A appender, const T node)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
string[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc,
|
string[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc)
|
||||||
shared(StringCache)* stringCache)
|
|
||||||
{
|
{
|
||||||
string[] retVal = cast(string[]) allocator.allocate((string[]).sizeof
|
string[] retVal = cast(string[]) allocator.allocate((string[]).sizeof
|
||||||
* iotc.identifiersOrTemplateInstances.length);
|
* iotc.identifiersOrTemplateInstances.length);
|
||||||
foreach (i, ioti; iotc.identifiersOrTemplateInstances)
|
foreach (i, ioti; iotc.identifiersOrTemplateInstances)
|
||||||
{
|
{
|
||||||
if (ioti.identifier != tok!"")
|
if (ioti.identifier != tok!"")
|
||||||
retVal[i] = stringCache.intern(ioti.identifier.text);
|
retVal[i] = internString(ioti.identifier.text);
|
||||||
else
|
else
|
||||||
retVal[i] = stringCache.intern(ioti.templateInstance.identifier.text);
|
retVal[i] = internString(ioti.templateInstance.identifier.text);
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string convertChainToImportPath(shared(StringCache)* stringCache,
|
static string convertChainToImportPath(const IdentifierChain ic)
|
||||||
const IdentifierChain ic)
|
|
||||||
{
|
{
|
||||||
import std.path;
|
import std.path;
|
||||||
QuickAllocator!1024 q;
|
QuickAllocator!1024 q;
|
||||||
|
|
@ -596,5 +591,5 @@ static string convertChainToImportPath(shared(StringCache)* stringCache,
|
||||||
if (i + 1 < ic.identifiers.length)
|
if (i + 1 < ic.identifiers.length)
|
||||||
app.append(dirSeparator);
|
app.append(dirSeparator);
|
||||||
}
|
}
|
||||||
return stringCache.intern(cast(string) app[]);
|
return internString(cast(string) app[]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import conversion.first;
|
||||||
import actypes;
|
import actypes;
|
||||||
import semantic;
|
import semantic;
|
||||||
import messages;
|
import messages;
|
||||||
import std.lexer : StringCache;
|
|
||||||
import std.allocator;
|
import std.allocator;
|
||||||
import stupidlog;
|
import stupidlog;
|
||||||
|
|
||||||
|
|
@ -41,7 +40,6 @@ public:
|
||||||
{
|
{
|
||||||
this.rootSymbol = first.rootSymbol;
|
this.rootSymbol = first.rootSymbol;
|
||||||
this.moduleScope = first.moduleScope;
|
this.moduleScope = first.moduleScope;
|
||||||
this.stringCache = first.stringCache;
|
|
||||||
this.symbolAllocator = first.symbolAllocator;
|
this.symbolAllocator = first.symbolAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,7 +52,6 @@ public:
|
||||||
CAllocator symbolAllocator;
|
CAllocator symbolAllocator;
|
||||||
SemanticSymbol* rootSymbol;
|
SemanticSymbol* rootSymbol;
|
||||||
Scope* moduleScope;
|
Scope* moduleScope;
|
||||||
shared(StringCache)* stringCache;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
@ -117,18 +114,6 @@ private:
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import semantic;
|
||||||
import actypes;
|
import actypes;
|
||||||
import messages;
|
import messages;
|
||||||
import std.allocator;
|
import std.allocator;
|
||||||
|
import string_interning;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Third pass handles the following:
|
* Third pass handles the following:
|
||||||
|
|
@ -43,7 +44,6 @@ public:
|
||||||
{
|
{
|
||||||
this.rootSymbol = second.rootSymbol;
|
this.rootSymbol = second.rootSymbol;
|
||||||
this.moduleScope = second.moduleScope;
|
this.moduleScope = second.moduleScope;
|
||||||
this.stringCache = second.stringCache;
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.symbolAllocator = second.symbolAllocator;
|
this.symbolAllocator = second.symbolAllocator;
|
||||||
}
|
}
|
||||||
|
|
@ -153,8 +153,7 @@ private:
|
||||||
t.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances.length
|
t.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances.length
|
||||||
* string.sizeof);
|
* string.sizeof);
|
||||||
scope(exit) Mallocator.it.deallocate(symbolParts);
|
scope(exit) Mallocator.it.deallocate(symbolParts);
|
||||||
expandSymbol(symbolParts,
|
expandSymbol(symbolParts, t.type2.symbol.identifierOrTemplateChain);
|
||||||
t.type2.symbol.identifierOrTemplateChain, stringCache);
|
|
||||||
auto symbols = moduleScope.getSymbolsByNameAndCursor(
|
auto symbols = moduleScope.getSymbolsByNameAndCursor(
|
||||||
symbolParts[0], location);
|
symbolParts[0], location);
|
||||||
if (symbols.length == 0)
|
if (symbols.length == 0)
|
||||||
|
|
@ -174,15 +173,14 @@ private:
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain,
|
static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain)
|
||||||
shared(StringCache)* stringCache)
|
|
||||||
{
|
{
|
||||||
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];
|
||||||
if (identOrTemplate is null)
|
if (identOrTemplate is null)
|
||||||
continue;
|
continue;
|
||||||
strings[i] = stringCache.intern(identOrTemplate.templateInstance is null ?
|
strings[i] = internString(identOrTemplate.templateInstance is null ?
|
||||||
identOrTemplate.identifier.text
|
identOrTemplate.identifier.text
|
||||||
: identOrTemplate.templateInstance.identifier.text);
|
: identOrTemplate.templateInstance.identifier.text);
|
||||||
}
|
}
|
||||||
|
|
@ -215,20 +213,20 @@ private:
|
||||||
scope(exit) q.deallocate(app.mem);
|
scope(exit) q.deallocate(app.mem);
|
||||||
app.append(suffix.delegateOrFunction.text);
|
app.append(suffix.delegateOrFunction.text);
|
||||||
app.formatNode(suffix.parameters);
|
app.formatNode(suffix.parameters);
|
||||||
s.callTip = stringCache.intern(cast(ubyte[]) app[]);
|
s.callTip = internString(cast(string) app[]);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ACSymbol* convertBuiltinType(const Type2 type2)
|
ACSymbol* convertBuiltinType(const Type2 type2)
|
||||||
{
|
{
|
||||||
string stringRepresentation = str(type2.builtinType);
|
import std.stdio;
|
||||||
if (stringRepresentation is null) return null;
|
string stringRepresentation = getBuiltinTypeName(type2.builtinType);
|
||||||
// TODO: Make this use binary search instead
|
// writefln(">> %s %016X", stringRepresentation, stringRepresentation.ptr);
|
||||||
ACSymbol s = ACSymbol(stringRepresentation);
|
ACSymbol s = ACSymbol(stringRepresentation);
|
||||||
|
assert(s.name.ptr == stringRepresentation.ptr);
|
||||||
|
// writefln(">> %s %016X", s.name, s.name.ptr);
|
||||||
return builtinSymbols.equalRange(&s).front();
|
return builtinSymbols.equalRange(&s).front();
|
||||||
}
|
}
|
||||||
|
|
||||||
shared(StringCache)* stringCache;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
dscanner
2
dscanner
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8b4b2b342f4e3c8dbead90353c6f7aa4800c2ce4
|
Subproject commit 19dc7c707f857b104144e909d77543b2db1521b8
|
||||||
|
|
@ -32,7 +32,7 @@ import std.path;
|
||||||
import actypes;
|
import actypes;
|
||||||
import semantic;
|
import semantic;
|
||||||
import memory.allocators;
|
import memory.allocators;
|
||||||
import containers.karytree;
|
import containers.ttree;
|
||||||
import containers.hashset;
|
import containers.hashset;
|
||||||
import containers.unrolledlist;
|
import containers.unrolledlist;
|
||||||
import conversion.astconverter;
|
import conversion.astconverter;
|
||||||
|
|
@ -74,7 +74,6 @@ bool existanceCheck(A)(A path)
|
||||||
|
|
||||||
static this()
|
static this()
|
||||||
{
|
{
|
||||||
ModuleCache.stringCache = new shared StringCache(StringCache.defaultBucketCount);
|
|
||||||
ModuleCache.symbolAllocator = new CAllocatorImpl!(BlockAllocator!(1024 * 16));
|
ModuleCache.symbolAllocator = new CAllocatorImpl!(BlockAllocator!(1024 * 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,6 +114,7 @@ struct ModuleCache
|
||||||
*/
|
*/
|
||||||
static ACSymbol*[] getSymbolsInModule(string location)
|
static ACSymbol*[] getSymbolsInModule(string location)
|
||||||
{
|
{
|
||||||
|
import string_interning;
|
||||||
assert (location !is null);
|
assert (location !is null);
|
||||||
if (!needsReparsing(location))
|
if (!needsReparsing(location))
|
||||||
{
|
{
|
||||||
|
|
@ -126,7 +126,7 @@ struct ModuleCache
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
string cachedLocation = stringCache.intern(location);
|
string cachedLocation = internString(location);
|
||||||
|
|
||||||
Log.info("Getting symbols for ", cachedLocation);
|
Log.info("Getting symbols for ", cachedLocation);
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ struct ModuleCache
|
||||||
f.rawRead(source);
|
f.rawRead(source);
|
||||||
LexerConfig config;
|
LexerConfig config;
|
||||||
config.fileName = cachedLocation;
|
config.fileName = cachedLocation;
|
||||||
shared parseStringCache = shared StringCache(StringCache.defaultBucketCount);
|
auto parseStringCache = StringCache(StringCache.defaultBucketCount);
|
||||||
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 64)));
|
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 64)));
|
||||||
DynamicArray!(Token, false) tokens;
|
DynamicArray!(Token, false) tokens;
|
||||||
auto tokenRange = byToken(
|
auto tokenRange = byToken(
|
||||||
|
|
@ -158,8 +158,8 @@ struct ModuleCache
|
||||||
Module m = parseModuleSimple(tokens[], cachedLocation, semanticAllocator);
|
Module m = parseModuleSimple(tokens[], cachedLocation, semanticAllocator);
|
||||||
|
|
||||||
assert (symbolAllocator);
|
assert (symbolAllocator);
|
||||||
auto first = scoped!FirstPass(m, cachedLocation, stringCache,
|
auto first = scoped!FirstPass(m, cachedLocation, symbolAllocator,
|
||||||
symbolAllocator, semanticAllocator);
|
semanticAllocator);
|
||||||
first.run();
|
first.run();
|
||||||
|
|
||||||
SecondPass second = SecondPass(first);
|
SecondPass second = SecondPass(first);
|
||||||
|
|
@ -234,8 +234,6 @@ struct ModuleCache
|
||||||
return importPaths[];
|
return importPaths[];
|
||||||
}
|
}
|
||||||
|
|
||||||
static shared(StringCache)* stringCache;
|
|
||||||
|
|
||||||
static uint symbolsAllocated;
|
static uint symbolsAllocated;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -264,7 +262,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mapping of file paths to their cached symbols.
|
// Mapping of file paths to their cached symbols.
|
||||||
static KAryTree!(CacheEntry*) cache;
|
static TTree!(CacheEntry*) cache;
|
||||||
|
|
||||||
static HashSet!string recursionGuard;
|
static HashSet!string recursionGuard;
|
||||||
|
|
||||||
|
|
|
||||||
8
server.d
8
server.d
|
|
@ -100,11 +100,9 @@ int main(string[] args)
|
||||||
|
|
||||||
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 symbolMegs = (cast(float) (ACSymbol.sizeof * ModuleCache.symbolsAllocated)) / (1024f * 1024f);
|
||||||
Log.info("String interning took up ", internBytes, " megabytes");
|
// Log.info(ModuleCache.symbolsAllocated, " symbols allocated, taking up ",
|
||||||
float symbolMegs = (cast(float) (ACSymbol.sizeof * ModuleCache.symbolsAllocated)) / (1024f * 1024f);
|
// symbolMegs, " megabytes");
|
||||||
Log.info(ModuleCache.symbolsAllocated, " symbols allocated, taking up ",
|
|
||||||
symbolMegs, " megabytes");
|
|
||||||
|
|
||||||
// No relative paths
|
// No relative paths
|
||||||
version (Posix) chdir("/");
|
version (Posix) chdir("/");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* This file is part of DCD, a development tool for the D programming language.
|
||||||
|
* Copyright (C) 2014 Brian Schott
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module string_interning;
|
||||||
|
|
||||||
|
import std.lexer;
|
||||||
|
|
||||||
|
string internString(string s)
|
||||||
|
{
|
||||||
|
// import std.stdio;
|
||||||
|
// import std.string;
|
||||||
|
// size_t* p = s in dupCheck;
|
||||||
|
// auto r = stringCache.intern(s);
|
||||||
|
return stringCache.intern(s);
|
||||||
|
// if (p !is null)
|
||||||
|
// assert (*p == cast(size_t) r.ptr, format("%s, %016x, %016x", s, *p, r.ptr));
|
||||||
|
// else
|
||||||
|
// dupCheck[s] = cast(size_t) r.ptr;
|
||||||
|
// stderr.writefln("%s\t%016x", r, r.ptr);
|
||||||
|
// return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static this()
|
||||||
|
{
|
||||||
|
stringCache = StringCache(StringCache.defaultBucketCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//private size_t[string] dupCheck;
|
||||||
|
private StringCache stringCache = void;
|
||||||
Loading…
Reference in New Issue