Merge 2f63d750ba
into 09f4e7e932
This commit is contained in:
commit
855f5e87af
|
@ -39,6 +39,7 @@ import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||||
import std.experimental.logger;
|
import std.experimental.logger;
|
||||||
import std.meta : AliasSeq;
|
import std.meta : AliasSeq;
|
||||||
import std.typecons : Rebindable;
|
import std.typecons : Rebindable;
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First Pass handles the following:
|
* First Pass handles the following:
|
||||||
|
@ -239,9 +240,238 @@ final class FirstPass : ASTVisitor
|
||||||
symbol.acSymbol.protection = protection.current;
|
symbol.acSymbol.protection = protection.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void processIdentifierOrTemplate(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, IdentifierOrTemplateInstance ioti)
|
||||||
|
{
|
||||||
|
if (ioti.identifier != tok!"")
|
||||||
|
current.chain ~= ioti.identifier.text;
|
||||||
|
else if (ioti.templateInstance)
|
||||||
|
processTemplateInstance(symbol, lookup, ctx, current, ioti.templateInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void processTypeIdentifierPart(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TypeIdentifierPart tip)
|
||||||
|
{
|
||||||
|
if (tip.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
|
processIdentifierOrTemplate(symbol, lookup, ctx, current, tip.identifierOrTemplateInstance);
|
||||||
|
if (current)
|
||||||
|
{
|
||||||
|
current.calltip = buildCalltip(tip.identifierOrTemplateInstance.tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tip.typeIdentifierPart)
|
||||||
|
{
|
||||||
|
processTypeIdentifierPart(symbol, lookup, ctx, current, tip.typeIdentifierPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle `tip.dot` and `tip.indexer`
|
||||||
|
}
|
||||||
|
|
||||||
|
void processTemplateArguments(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateArguments targs)
|
||||||
|
{
|
||||||
|
if (targs.namedTemplateArgumentList)
|
||||||
|
{
|
||||||
|
foreach(i, targ; targs.namedTemplateArgumentList.items)
|
||||||
|
{
|
||||||
|
// TODO: handle targ.assignExpression
|
||||||
|
if (targ.type is null) continue;
|
||||||
|
if (targ.type.type2 is null) continue;
|
||||||
|
|
||||||
|
auto part = targ.type.type2.typeIdentifierPart;
|
||||||
|
if (part is null)
|
||||||
|
{
|
||||||
|
if (targ.type.type2.builtinType == tok!"") continue;
|
||||||
|
auto builtInName = getBuiltinTypeName(targ.type.type2.builtinType);
|
||||||
|
auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
newArg.chain ~= builtInName;
|
||||||
|
current.args ~= newArg;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
current.args ~= newArg;
|
||||||
|
|
||||||
|
if (part.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
|
processIdentifierOrTemplate(symbol, lookup, ctx, newArg, part.identifierOrTemplateInstance);
|
||||||
|
}
|
||||||
|
if (part.typeIdentifierPart)
|
||||||
|
{
|
||||||
|
if (part.typeIdentifierPart.identifierOrTemplateInstance)
|
||||||
|
processIdentifierOrTemplate(symbol, lookup, ctx, newArg, part.typeIdentifierPart.identifierOrTemplateInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(suffix; targ.type.typeSuffixes)
|
||||||
|
{
|
||||||
|
if (suffix.type)
|
||||||
|
current.calltip ~= "[.]";
|
||||||
|
else if (suffix.array)
|
||||||
|
current.calltip ~= "[]";
|
||||||
|
else if (suffix.star != tok!"")
|
||||||
|
current.calltip ~= "*";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (targs.templateSingleArgument)
|
||||||
|
{
|
||||||
|
auto singleArg = targs.templateSingleArgument;
|
||||||
|
auto arg = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
arg.name = singleArg.token.text;
|
||||||
|
arg.chain ~= arg.name;
|
||||||
|
current.args ~= arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processTemplateInstance(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateInstance ti)
|
||||||
|
{
|
||||||
|
if (ti.identifier != tok!"")
|
||||||
|
current.chain ~= ti.identifier.text;
|
||||||
|
|
||||||
|
if (ti.templateArguments)
|
||||||
|
processTemplateArguments(symbol, lookup, ctx, current, ti.templateArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
void buildChain(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, TypeIdentifierPart tip)
|
||||||
|
{
|
||||||
|
if (tip.identifierOrTemplateInstance)
|
||||||
|
buildChainTemplateOrIdentifier(symbol, lookup, ctx, tip.identifierOrTemplateInstance);
|
||||||
|
if (tip.typeIdentifierPart)
|
||||||
|
buildChain(symbol, lookup, ctx, tip.typeIdentifierPart);
|
||||||
|
// TODO: handle `tip.indexer`
|
||||||
|
}
|
||||||
|
|
||||||
|
void buildChainTemplateOrIdentifier(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, IdentifierOrTemplateInstance iot)
|
||||||
|
{
|
||||||
|
if (iot.templateInstance)
|
||||||
|
{
|
||||||
|
if (iot.templateInstance.identifier != tok!"")
|
||||||
|
lookup.breadcrumbs.insert(istring(iot.templateInstance.identifier.text));
|
||||||
|
|
||||||
|
// TODO: finish handling `iot.templateInstance.templateArguments`
|
||||||
|
if (iot.templateInstance.templateArguments)
|
||||||
|
{
|
||||||
|
if (iot.templateInstance.templateArguments.templateSingleArgument)
|
||||||
|
{
|
||||||
|
auto tsaTok = iot.templateInstance.templateArguments.templateSingleArgument.token;
|
||||||
|
if (tsaTok.text == "")
|
||||||
|
lookup.breadcrumbs.insert(istring(str(tsaTok.type)));
|
||||||
|
// TODO: investigate why this break everything
|
||||||
|
// else
|
||||||
|
// lookup.breadcrumbs.insert(istring(tsaTok.text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto crumb = iot.identifier;
|
||||||
|
lookup.breadcrumbs.insert(istring(crumb.text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string buildCalltip(const(Token)[] tokens)
|
||||||
|
{
|
||||||
|
string calltip;
|
||||||
|
foreach(tk; tokens)
|
||||||
|
{
|
||||||
|
if (tk == tok!"!")
|
||||||
|
calltip ~= "!";
|
||||||
|
else if (tk == tok!"(")
|
||||||
|
calltip ~= "(";
|
||||||
|
else if (tk == tok!")")
|
||||||
|
calltip ~= ")";
|
||||||
|
else if (tk == tok!"[")
|
||||||
|
calltip ~= "[";
|
||||||
|
else if (tk == tok!"]")
|
||||||
|
calltip ~= "]";
|
||||||
|
else if (tk == tok!",")
|
||||||
|
calltip ~= ",";
|
||||||
|
else if (tk == tok!"*")
|
||||||
|
calltip ~= "*";
|
||||||
|
else if (tk == tok!"")
|
||||||
|
calltip ~= " ";
|
||||||
|
else
|
||||||
|
calltip ~= tk.text;
|
||||||
|
}
|
||||||
|
return calltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
void traverseUnaryExpression(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, UnaryExpression ue)
|
||||||
|
{
|
||||||
|
if (PrimaryExpression pe = ue.primaryExpression)
|
||||||
|
{
|
||||||
|
if (pe.identifierOrTemplateInstance)
|
||||||
|
buildChainTemplateOrIdentifier(symbol, lookup, ctx, pe.identifierOrTemplateInstance);
|
||||||
|
|
||||||
|
if (pe.basicType != tok!"")
|
||||||
|
lookup.breadcrumbs.insert(internString(str(pe.basicType.type)));
|
||||||
|
switch (pe.primary.type)
|
||||||
|
{
|
||||||
|
case tok!"identifier":
|
||||||
|
lookup.breadcrumbs.insert(internString(pe.primary.text));
|
||||||
|
break;
|
||||||
|
case tok!"doubleLiteral":
|
||||||
|
lookup.breadcrumbs.insert(DOUBLE_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"floatLiteral":
|
||||||
|
lookup.breadcrumbs.insert(FLOAT_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"idoubleLiteral":
|
||||||
|
lookup.breadcrumbs.insert(IDOUBLE_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"ifloatLiteral":
|
||||||
|
lookup.breadcrumbs.insert(IFLOAT_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"intLiteral":
|
||||||
|
lookup.breadcrumbs.insert(INT_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"longLiteral":
|
||||||
|
lookup.breadcrumbs.insert(LONG_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"realLiteral":
|
||||||
|
lookup.breadcrumbs.insert(REAL_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"irealLiteral":
|
||||||
|
lookup.breadcrumbs.insert(IREAL_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"uintLiteral":
|
||||||
|
lookup.breadcrumbs.insert(UINT_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"ulongLiteral":
|
||||||
|
lookup.breadcrumbs.insert(ULONG_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"characterLiteral":
|
||||||
|
lookup.breadcrumbs.insert(CHAR_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"dstringLiteral":
|
||||||
|
lookup.breadcrumbs.insert(DSTRING_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"stringLiteral":
|
||||||
|
lookup.breadcrumbs.insert(STRING_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"wstringLiteral":
|
||||||
|
lookup.breadcrumbs.insert(WSTRING_LITERAL_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
case tok!"false":
|
||||||
|
case tok!"true":
|
||||||
|
lookup.breadcrumbs.insert(BOOL_VALUE_SYMBOL_NAME);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IdentifierOrTemplateInstance iot = ue.identifierOrTemplateInstance)
|
||||||
|
buildChainTemplateOrIdentifier(symbol, lookup, ctx, iot);
|
||||||
|
|
||||||
|
if(ue.unaryExpression)
|
||||||
|
traverseUnaryExpression(symbol, lookup, ctx, ue.unaryExpression);
|
||||||
|
}
|
||||||
|
|
||||||
override void visit(const VariableDeclaration dec)
|
override void visit(const VariableDeclaration dec)
|
||||||
{
|
{
|
||||||
assert (currentSymbol);
|
assert (currentSymbol);
|
||||||
|
|
||||||
foreach (declarator; dec.declarators)
|
foreach (declarator; dec.declarators)
|
||||||
{
|
{
|
||||||
SemanticSymbol* symbol = allocateSemanticSymbol(
|
SemanticSymbol* symbol = allocateSemanticSymbol(
|
||||||
|
@ -262,6 +492,29 @@ final class FirstPass : ASTVisitor
|
||||||
// TODO: remove this cast. See the note on structFieldTypes
|
// TODO: remove this cast. See the note on structFieldTypes
|
||||||
structFieldTypes.insert(cast() dec.type);
|
structFieldTypes.insert(cast() dec.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto lookup = symbol.typeLookups.front;
|
||||||
|
|
||||||
|
if (dec.type && dec.type.type2 && dec.type.type2.typeIdentifierPart)
|
||||||
|
{
|
||||||
|
TypeIdentifierPart typeIdentifierPart = cast(TypeIdentifierPart) dec.type.type2.typeIdentifierPart;
|
||||||
|
lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
|
||||||
|
if (typeIdentifierPart.identifierOrTemplateInstance)
|
||||||
|
lookup.ctx.calltip = buildCalltip(typeIdentifierPart.identifierOrTemplateInstance.tokens);
|
||||||
|
|
||||||
|
foreach(suffix; dec.type.typeSuffixes)
|
||||||
|
{
|
||||||
|
if (suffix.type)
|
||||||
|
lookup.ctx.calltip ~= "[.]";
|
||||||
|
else if (suffix.array)
|
||||||
|
lookup.ctx.calltip ~= "[]";
|
||||||
|
else if (suffix.star != tok!"")
|
||||||
|
lookup.ctx.calltip ~= "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
processTypeIdentifierPart(symbol, lookup, &lookup.ctx, lookup.ctx.root, typeIdentifierPart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (dec.autoDeclaration !is null)
|
if (dec.autoDeclaration !is null)
|
||||||
{
|
{
|
||||||
|
@ -284,6 +537,111 @@ final class FirstPass : ASTVisitor
|
||||||
// TODO: remove this cast. See the note on structFieldTypes
|
// TODO: remove this cast. See the note on structFieldTypes
|
||||||
structFieldTypes.insert(null);
|
structFieldTypes.insert(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto lookup = symbol.typeLookups.front;
|
||||||
|
|
||||||
|
istring[] original;
|
||||||
|
foreach(c; lookup.breadcrumbs[])
|
||||||
|
original ~= c;
|
||||||
|
writeln("## var: ", symbol.acSymbol.name);
|
||||||
|
writeln("## lookup breadcrumbs: ", lookup.breadcrumbs[]);
|
||||||
|
|
||||||
|
auto initializer = part.initializer.nonVoidInitializer;
|
||||||
|
if (initializer && initializer.assignExpression)
|
||||||
|
{
|
||||||
|
UnaryExpression unary = cast(UnaryExpression) initializer.assignExpression;
|
||||||
|
|
||||||
|
if (unary && (unary.newExpression || unary.indexExpression))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lookup.breadcrumbs.clear();
|
||||||
|
if (unary)
|
||||||
|
{
|
||||||
|
if (CastExpression castExpression = unary.castExpression)
|
||||||
|
{
|
||||||
|
if (castExpression.type && castExpression.type.type2)
|
||||||
|
{
|
||||||
|
Type2 t2 = castExpression.type.type2;
|
||||||
|
if (t2 && t2.typeIdentifierPart)
|
||||||
|
buildChain(symbol, lookup, &lookup.ctx, t2.typeIdentifierPart);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (FunctionCallExpression fc = unary.functionCallExpression)
|
||||||
|
unary = fc.unaryExpression;
|
||||||
|
// build chain
|
||||||
|
traverseUnaryExpression(symbol, lookup, &lookup.ctx, unary);
|
||||||
|
// needs to be reversed because it got added in order (right->left)
|
||||||
|
auto crumbs = &lookup.breadcrumbs;
|
||||||
|
istring[] result;
|
||||||
|
foreach(c; *crumbs)
|
||||||
|
result ~= c;
|
||||||
|
|
||||||
|
writeln("## result: ", result);
|
||||||
|
crumbs.clear();
|
||||||
|
foreach_reverse(c; result)
|
||||||
|
lookup.breadcrumbs.insert(c);
|
||||||
|
|
||||||
|
again:
|
||||||
|
|
||||||
|
// check template
|
||||||
|
if (IdentifierOrTemplateInstance iot = unary.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
|
if (iot.templateInstance)
|
||||||
|
{
|
||||||
|
lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
processTemplateInstance(symbol, lookup, &lookup.ctx, lookup.ctx.root, iot.templateInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeln("something else2; ", iot.identifier.text, " original: ", original);
|
||||||
|
|
||||||
|
if (original.length > 0 && original[$-1] == "*arr*")
|
||||||
|
{
|
||||||
|
lookup.breadcrumbs.clear();
|
||||||
|
foreach(c; original)
|
||||||
|
lookup.breadcrumbs.insert(c);
|
||||||
|
foreach_reverse(c; result)
|
||||||
|
lookup.breadcrumbs.insert(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PrimaryExpression pe = unary.primaryExpression)
|
||||||
|
{
|
||||||
|
if (pe.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
|
if (pe.identifierOrTemplateInstance.templateInstance)
|
||||||
|
{
|
||||||
|
lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
processTemplateInstance(symbol, lookup, &lookup.ctx, lookup.ctx.root, pe.identifierOrTemplateInstance.templateInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeln("something else2; ", pe.identifierOrTemplateInstance.identifier.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeln("something else other");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeln("something else final");
|
||||||
|
if (unary.unaryExpression)
|
||||||
|
{
|
||||||
|
unary = unary.unaryExpression;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach(c; original)
|
||||||
|
lookup.breadcrumbs.insert(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ import dparse.ast;
|
||||||
import dparse.lexer;
|
import dparse.lexer;
|
||||||
import std.algorithm : filter;
|
import std.algorithm : filter;
|
||||||
import std.range;
|
import std.range;
|
||||||
|
import std.stdio;
|
||||||
|
import io = std.stdio;
|
||||||
|
|
||||||
void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache)
|
void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +59,28 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac
|
||||||
resolveType(currentSymbol.acSymbol, currentSymbol.typeLookups,
|
resolveType(currentSymbol.acSymbol, currentSymbol.typeLookups,
|
||||||
moduleScope, cache);
|
moduleScope, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentSymbol.acSymbol.type && currentSymbol.typeLookups.length > 0)
|
||||||
|
{
|
||||||
|
foreach(lookup; currentSymbol.typeLookups[]) {
|
||||||
|
|
||||||
|
writeln("lookup: ", lookup.breadcrumbs[], " ctx: ", lookup.ctx.root);
|
||||||
|
if (lookup.ctx.root)
|
||||||
|
{
|
||||||
|
auto type = currentSymbol.acSymbol.type;
|
||||||
|
if (type.kind == structName || type.kind == className || type.kind == functionName || type.kind)
|
||||||
|
{
|
||||||
|
if (lookup.ctx.root.args.length > 0)
|
||||||
|
{
|
||||||
|
DSymbol*[string] mapping;
|
||||||
|
int depth;
|
||||||
|
resolveTemplate(currentSymbol.acSymbol, type, lookup, lookup.ctx.root, moduleScope, cache, depth, mapping);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case importSymbol:
|
case importSymbol:
|
||||||
if (currentSymbol.acSymbol.type is null)
|
if (currentSymbol.acSymbol.type is null)
|
||||||
|
@ -81,8 +105,22 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let's be methodic about the way we traverse symbols
|
||||||
|
// so that childs have access to resolved symbols
|
||||||
|
// functions should be last, because inside, there might be symbols that references
|
||||||
|
// code from the parent not yet resolved (templates)
|
||||||
foreach (child; currentSymbol.children)
|
foreach (child; currentSymbol.children)
|
||||||
secondPass(child, moduleScope, cache);
|
if (child.acSymbol.kind != CompletionKind.variableName && child.acSymbol.kind != CompletionKind.functionName)
|
||||||
|
secondPass(child, moduleScope, cache);
|
||||||
|
|
||||||
|
foreach (child; currentSymbol.children)
|
||||||
|
if (child.acSymbol.kind == CompletionKind.variableName)
|
||||||
|
secondPass(child, moduleScope, cache);
|
||||||
|
|
||||||
|
foreach (child; currentSymbol.children)
|
||||||
|
if (child.acSymbol.kind == CompletionKind.functionName)
|
||||||
|
secondPass(child, moduleScope, cache);
|
||||||
|
|
||||||
|
|
||||||
// Alias this and mixin templates are resolved after child nodes are
|
// Alias this and mixin templates are resolved after child nodes are
|
||||||
// resolved so that the correct symbol information will be available.
|
// resolved so that the correct symbol information will be available.
|
||||||
|
@ -100,6 +138,323 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Extract the return type from the callTip of a function symbol
|
||||||
|
*/
|
||||||
|
string extractReturnType(string callTip)
|
||||||
|
{
|
||||||
|
import std.string: indexOf;
|
||||||
|
|
||||||
|
auto spaceIndex = callTip.indexOf(" ");
|
||||||
|
if (spaceIndex <= 0) return "";
|
||||||
|
|
||||||
|
auto retPart = callTip[0 .. spaceIndex];
|
||||||
|
auto returnTypeConst = retPart.length > 6 ? retPart[0 .. 6] == "const(" : false;
|
||||||
|
auto returnTypeInout = retPart.length > 6 ? retPart[0 .. 6] == "inout(" : false;
|
||||||
|
if (returnTypeConst || returnTypeInout)
|
||||||
|
{
|
||||||
|
retPart = retPart[retPart.indexOf("(") + 1 .. $];
|
||||||
|
retPart = retPart[0 .. retPart.indexOf(")")];
|
||||||
|
}
|
||||||
|
auto returnTypePtr = retPart[$-1] == '*';
|
||||||
|
auto returnTypeArr = retPart[$-1] == ']';
|
||||||
|
if (returnTypePtr)
|
||||||
|
{
|
||||||
|
retPart = retPart[0 .. $-1];
|
||||||
|
}
|
||||||
|
return retPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a Type symbol with templates arguments
|
||||||
|
* Returns: Copy of Type symbol
|
||||||
|
*/
|
||||||
|
DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableContext.TypeInstance* ti, ref ModuleCache cache, Scope* moduleScope, ref int depth, DSymbol*[string] m)
|
||||||
|
{
|
||||||
|
assert(type);
|
||||||
|
DSymbol* newType = GCAllocator.instance.make!DSymbol("dummy", CompletionKind.dummy, null);
|
||||||
|
newType.name = ti ? istring(ti.calltip) : istring(lookup.ctx.calltip);
|
||||||
|
|
||||||
|
// TODO: need to set the name in first.d
|
||||||
|
if (newType.name.length == 0)
|
||||||
|
newType.name = type.name;
|
||||||
|
|
||||||
|
print_tab(depth); io.write(">>", type.name, " > ", newType.name, " ::", ti," args: ", ti.args.length, " ct: ", ti.calltip);
|
||||||
|
writeln();
|
||||||
|
|
||||||
|
newType.kind = type.kind;
|
||||||
|
newType.qualifier = type.qualifier;
|
||||||
|
newType.protection = type.protection;
|
||||||
|
newType.symbolFile = type.symbolFile;
|
||||||
|
newType.doc = type.doc;
|
||||||
|
newType.type = type.type;
|
||||||
|
DSymbol*[string] mapping;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
if (ti.args.length > 0)
|
||||||
|
{
|
||||||
|
foreach(part; type.opSlice())
|
||||||
|
{
|
||||||
|
if (part.kind == CompletionKind.typeTmpParam)
|
||||||
|
{
|
||||||
|
scope(exit) count++;
|
||||||
|
if (count >= ti.args.length)
|
||||||
|
{
|
||||||
|
print_tab(depth);writeln("too many T for args available, investigate");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto key = part.name;
|
||||||
|
|
||||||
|
print_tab(depth);writeln("> check template arg: ", key);
|
||||||
|
print_tab(depth);io.write("chain: ");
|
||||||
|
foreach(i, crumb; ti.args[count].chain)
|
||||||
|
{
|
||||||
|
io.write(crumb, ", ");
|
||||||
|
}
|
||||||
|
writeln("");
|
||||||
|
|
||||||
|
DSymbol* first;
|
||||||
|
bool isBuiltin;
|
||||||
|
foreach(i, crumb; ti.args[count].chain)
|
||||||
|
{
|
||||||
|
auto argName = crumb;
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
if (m && key in m)
|
||||||
|
{
|
||||||
|
argName = m[key].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if that's a built in type
|
||||||
|
// if it is, then use it and skip the type creation step
|
||||||
|
foreach(builtin; builtinSymbols)
|
||||||
|
{
|
||||||
|
if (builtin.name == crumb)
|
||||||
|
{
|
||||||
|
first = builtin;
|
||||||
|
isBuiltin = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto result = moduleScope.getSymbolsAtGlobalScope(istring(argName));
|
||||||
|
if (result.length == 0)
|
||||||
|
{
|
||||||
|
print_tab(depth);writeln("modulescope: symbol not found: ", argName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
first = result[0];
|
||||||
|
print_tab(depth);writeln("modulescope: symbol found: ", argName, " -> ", first.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first = first.getFirstPartNamed(istring(argName));
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
print_tab(depth);writeln("symbol found: ", argName, " -> ", first.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_tab(depth);writeln("symbol not found: ", argName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
print_tab(depth);writeln(">> ok");
|
||||||
|
auto ca = ti.args[count];
|
||||||
|
if (ca.chain.length > 0)
|
||||||
|
{
|
||||||
|
int indepth = depth + 1;
|
||||||
|
auto stomap = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, indepth, null);
|
||||||
|
mapping[key] = stomap;
|
||||||
|
|
||||||
|
print_tab(depth);writeln("mapping[",key,"] -> ", stomap.name, " builtin: ", isBuiltin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//writeln(">>>>>>>>>>>>>>> what: ", part.kind," ", part.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: to support functions with template arguments that return a generic type
|
||||||
|
// first.d in processParameters only store the function's return type in the callTip
|
||||||
|
// maybe it's time to properly handle it by creating a proper symbol, so we can have
|
||||||
|
// proper support for functions that return complex types such as templates
|
||||||
|
if (type.kind == CompletionKind.functionName)
|
||||||
|
{
|
||||||
|
auto callTip = type.callTip;
|
||||||
|
if (callTip && callTip.length > 1)
|
||||||
|
{
|
||||||
|
auto retType = extractReturnType(callTip);
|
||||||
|
if (retType in mapping)
|
||||||
|
{
|
||||||
|
auto result = mapping[retType];
|
||||||
|
newType.ownType = result.kind == CompletionKind.keyword ? false : true;
|
||||||
|
newType.type = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeln("-");
|
||||||
|
|
||||||
|
assert(newType);
|
||||||
|
string[] T_names;
|
||||||
|
foreach(part; type.opSlice())
|
||||||
|
{
|
||||||
|
if (part.kind == CompletionKind.typeTmpParam)
|
||||||
|
{
|
||||||
|
T_names ~= part.name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (part.type && part.type.kind == CompletionKind.typeTmpParam)
|
||||||
|
{
|
||||||
|
|
||||||
|
print_tab(depth); writeln("part: ", part.name,": ", part.type.name);
|
||||||
|
DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, null);
|
||||||
|
newPart.qualifier = part.qualifier;
|
||||||
|
newPart.protection = part.protection;
|
||||||
|
newPart.symbolFile = part.symbolFile;
|
||||||
|
newPart.doc = part.doc;
|
||||||
|
newPart.callTip = part.callTip;
|
||||||
|
|
||||||
|
if (part.type.name in mapping)
|
||||||
|
{
|
||||||
|
auto result = mapping[part.type.name];
|
||||||
|
newPart.ownType = result.kind == CompletionKind.keyword ? false : true;
|
||||||
|
newPart.type = result;
|
||||||
|
}
|
||||||
|
else if (m && part.type.name in m)
|
||||||
|
{
|
||||||
|
auto result = m[part.type.name];
|
||||||
|
newPart.ownType = result.kind == CompletionKind.keyword ? false : true;
|
||||||
|
newPart.type = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
newType.addChild(newPart, true);
|
||||||
|
}
|
||||||
|
else if (part.type && part.type.name == "*arr*" && part.type.type && part.type.type.kind == CompletionKind.typeTmpParam)
|
||||||
|
{
|
||||||
|
auto arrSymbol = part.type;
|
||||||
|
auto arrTypeTSymbol = arrSymbol.type;
|
||||||
|
|
||||||
|
print_tab(depth); writeln("array: ", part.name,": ", arrTypeTSymbol.name,"[]");
|
||||||
|
|
||||||
|
|
||||||
|
DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, null);
|
||||||
|
newPart.qualifier = part.qualifier;
|
||||||
|
newPart.protection = part.protection;
|
||||||
|
newPart.symbolFile = part.symbolFile;
|
||||||
|
newPart.doc = part.doc;
|
||||||
|
newPart.callTip = part.callTip;
|
||||||
|
|
||||||
|
// create new array shit
|
||||||
|
|
||||||
|
|
||||||
|
if (arrTypeTSymbol.name in mapping)
|
||||||
|
{
|
||||||
|
auto result = mapping[arrTypeTSymbol.name];
|
||||||
|
print_tab(depth); writeln(" ", arrTypeTSymbol.name, " =>: ", result.name);
|
||||||
|
|
||||||
|
auto newarr = GCAllocator.instance.make!DSymbol(arrSymbol.name , arrSymbol.kind, result);
|
||||||
|
newarr.ownType = false;
|
||||||
|
newPart.type = newarr;
|
||||||
|
newPart.ownType = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
newType.addChild(newPart, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
print_tab(depth); writeln("missing part: ", part.name,": ", part.type);
|
||||||
|
// BUG: doing it recursively messes with the mapping
|
||||||
|
// i need to debug this and figure out perhaps a better way to do this stuff
|
||||||
|
// maybe move the VariableContext to the symbol directly
|
||||||
|
// i'll need to experiemnt with it
|
||||||
|
|
||||||
|
//DSymbol* part_T;
|
||||||
|
//if (depth < 50)
|
||||||
|
//if (part.type && part.kind == CompletionKind.variableName)
|
||||||
|
//foreach(partPart; part.type.opSlice())
|
||||||
|
//{
|
||||||
|
// if (partPart.kind == CompletionKind.typeTmpParam)
|
||||||
|
// {
|
||||||
|
// part_T = part;
|
||||||
|
// foreach(arg; ti.args)
|
||||||
|
// {
|
||||||
|
// warning(" > ", arg.chain);
|
||||||
|
// foreach(aa; arg.args)
|
||||||
|
// warning(" > ", aa.chain);
|
||||||
|
// }
|
||||||
|
// int indepth = depth;
|
||||||
|
// warning("go agane ", part.name, " ", part.type.name, " with arg: ", ti.chain," Ts: ", T_names);
|
||||||
|
// resolveTemplate(part, part.type, lookup, ti, moduleScope, cache, indepth, mapping);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// //else if (partPart.type && partPart.type.kind == CompletionKind.typeTmpParam)
|
||||||
|
// //{
|
||||||
|
// // warning("here!".red," ", partPart.name," ", partPart.type.name);
|
||||||
|
// //}
|
||||||
|
//}
|
||||||
|
newType.addChild(part, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_tab(int index)
|
||||||
|
{
|
||||||
|
enum C = 4;
|
||||||
|
for(int i =0; i < index*4; i++) io.write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve template arguments
|
||||||
|
*/
|
||||||
|
void resolveTemplate(DSymbol* variableSym, DSymbol* type, TypeLookup* lookup, VariableContext.TypeInstance* current, Scope* moduleScope, ref ModuleCache cache, ref int depth, DSymbol*[string] mapping = null)
|
||||||
|
{
|
||||||
|
depth += 1;
|
||||||
|
|
||||||
|
if (variableSym is null || type is null) return;
|
||||||
|
if (current.chain.length == 0) return; // TODO: should not be empty, happens for simple stuff Inner inner; TODO: i forgot why, add a test
|
||||||
|
|
||||||
|
writeln("> Resolve template for: ",variableSym.name, ": ", type.name);
|
||||||
|
writeln("ctx callTip: ", lookup.ctx.calltip);
|
||||||
|
|
||||||
|
|
||||||
|
void printti(VariableContext.TypeInstance* it, ref int index)
|
||||||
|
{
|
||||||
|
print_tab(index); io.write("chain:", it.chain, "name: ", it.name, " ct: ", it.calltip, " args: ", it.args.length, "\n");
|
||||||
|
index += 1;
|
||||||
|
foreach(itt; it.args)
|
||||||
|
{
|
||||||
|
int inindex = index;
|
||||||
|
printti(itt, inindex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
printti(lookup.ctx.root, index);
|
||||||
|
|
||||||
|
writeln("");
|
||||||
|
writeln("");
|
||||||
|
DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping);
|
||||||
|
|
||||||
|
|
||||||
|
writeln("");
|
||||||
|
writeln("resolved:", variableSym.name, " > ", newType.name);
|
||||||
|
|
||||||
|
if (depth == 1)
|
||||||
|
{
|
||||||
|
newType.name = istring(lookup.ctx.calltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
variableSym.type = newType;
|
||||||
|
variableSym.ownType = true;
|
||||||
|
}
|
||||||
|
|
||||||
void resolveImport(DSymbol* acSymbol, ref TypeLookups typeLookups,
|
void resolveImport(DSymbol* acSymbol, ref TypeLookups typeLookups,
|
||||||
ref ModuleCache cache)
|
ref ModuleCache cache)
|
||||||
|
@ -281,10 +636,12 @@ do
|
||||||
if (lastSuffix !is null)
|
if (lastSuffix !is null)
|
||||||
{
|
{
|
||||||
assert(suffix !is null);
|
assert(suffix !is null);
|
||||||
|
typeSwap(currentSymbol);
|
||||||
suffix.type = currentSymbol;
|
suffix.type = currentSymbol;
|
||||||
suffix.ownType = false;
|
suffix.ownType = false;
|
||||||
symbol.type = lastSuffix;
|
symbol.type = lastSuffix;
|
||||||
symbol.ownType = true;
|
symbol.ownType = true;
|
||||||
|
|
||||||
if (currentSymbol is null && !remainingImports.empty)
|
if (currentSymbol is null && !remainingImports.empty)
|
||||||
{
|
{
|
||||||
// info("Deferring type resolution for ", symbol.name);
|
// info("Deferring type resolution for ", symbol.name);
|
||||||
|
@ -320,6 +677,9 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
auto crumbs = lookup.breadcrumbs[];
|
auto crumbs = lookup.breadcrumbs[];
|
||||||
|
|
||||||
|
writeln(">> crumbs: ", crumbs);
|
||||||
|
writeln(">> name: ", symbol.name);
|
||||||
foreach (crumb; crumbs)
|
foreach (crumb; crumbs)
|
||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
@ -328,7 +688,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
symbolNameToTypeName(crumb), symbol.location);
|
symbolNameToTypeName(crumb), symbol.location);
|
||||||
|
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
|
{
|
||||||
|
writeln("return 0");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (crumb == ARRAY_LITERAL_SYMBOL_NAME)
|
else if (crumb == ARRAY_LITERAL_SYMBOL_NAME)
|
||||||
{
|
{
|
||||||
|
@ -340,7 +703,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
{
|
{
|
||||||
typeSwap(currentSymbol);
|
typeSwap(currentSymbol);
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
|
{
|
||||||
|
writeln("return");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Index expressions can be on a pointer, an array or an AA
|
// Index expressions can be on a pointer, an array or an AA
|
||||||
if (currentSymbol.qualifier == SymbolQualifier.array
|
if (currentSymbol.qualifier == SymbolQualifier.array
|
||||||
|
@ -349,9 +715,15 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
|| currentSymbol.kind == CompletionKind.aliasName)
|
|| currentSymbol.kind == CompletionKind.aliasName)
|
||||||
{
|
{
|
||||||
if (currentSymbol.type !is null)
|
if (currentSymbol.type !is null)
|
||||||
|
{
|
||||||
|
writeln("here! ", currentSymbol.type.name);
|
||||||
currentSymbol = currentSymbol.type;
|
currentSymbol = currentSymbol.type;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
writeln("nope!");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -359,7 +731,11 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
if (opIndex !is null)
|
if (opIndex !is null)
|
||||||
currentSymbol = opIndex.type;
|
currentSymbol = opIndex.type;
|
||||||
else
|
else
|
||||||
return;
|
{
|
||||||
|
writeln("return weird");
|
||||||
|
writeln("s: ", currentSymbol.name, " ", currentSymbol.qualifier);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (crumb == "foreach")
|
else if (crumb == "foreach")
|
||||||
|
@ -388,18 +764,29 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
writeln("here");
|
||||||
typeSwap(currentSymbol);
|
typeSwap(currentSymbol);
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
|
{
|
||||||
|
|
||||||
|
writeln("return", i);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
|
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
|
{
|
||||||
|
writeln("return end", i);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
typeSwap(currentSymbol);
|
typeSwap(currentSymbol);
|
||||||
symbol.type = currentSymbol;
|
symbol.type = currentSymbol;
|
||||||
symbol.ownType = false;
|
symbol.ownType = false;
|
||||||
|
|
||||||
|
if (currentSymbol)
|
||||||
|
writeln(">> type: ", currentSymbol.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -199,7 +199,7 @@ unittest
|
||||||
};
|
};
|
||||||
ScopeSymbolPair pair = generateAutocompleteTrees(source, cache);
|
ScopeSymbolPair pair = generateAutocompleteTrees(source, cache);
|
||||||
DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife"));
|
DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife"));
|
||||||
assert(meaningOfLife.type.name == "*arr*");
|
assert(meaningOfLife.type.name == "int[]");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,4 +37,19 @@ struct TypeLookup
|
||||||
UnrolledList!istring breadcrumbs;
|
UnrolledList!istring breadcrumbs;
|
||||||
/// The kind of type lookup
|
/// The kind of type lookup
|
||||||
TypeLookupKind kind;
|
TypeLookupKind kind;
|
||||||
|
/// To store information about template instances
|
||||||
|
VariableContext ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VariableContext
|
||||||
|
{
|
||||||
|
struct TypeInstance
|
||||||
|
{
|
||||||
|
string[] chain;
|
||||||
|
TypeInstance*[] args;
|
||||||
|
string name;
|
||||||
|
string calltip;
|
||||||
|
}
|
||||||
|
TypeInstance* root;
|
||||||
|
string calltip;
|
||||||
}
|
}
|
2
dub.json
2
dub.json
|
@ -8,7 +8,7 @@
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
":dsymbol": "*",
|
":dsymbol": "*",
|
||||||
"libdparse": ">=0.23.0 <0.24.0",
|
"libdparse": ">=0.23.2 <0.24.0",
|
||||||
":common": "*",
|
":common": "*",
|
||||||
"emsi_containers": "~>0.9.0"
|
"emsi_containers": "~>0.9.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"versions": {
|
"versions": {
|
||||||
"dsymbol": "0.14.1",
|
"dsymbol": "0.14.1",
|
||||||
"emsi_containers": "0.9.0",
|
"emsi_containers": "0.9.0",
|
||||||
"libdparse": "0.23.0",
|
"libdparse": "0.23.2",
|
||||||
"msgpack-d": "1.0.4",
|
"msgpack-d": "1.0.4",
|
||||||
"stdx-allocator": "2.77.5"
|
"stdx-allocator": "2.77.5"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 86c9bf44c96e1666eb175c749cc26f62c2008979
|
Subproject commit 10658375b22f284e2fcb44074a862c213309cfb3
|
|
@ -1,7 +1,6 @@
|
||||||
identifiers
|
identifiers
|
||||||
C h
|
|
||||||
alignof k
|
alignof k
|
||||||
i v
|
i v int i stdin 21 int
|
||||||
init k
|
init k
|
||||||
mangleof k
|
mangleof k
|
||||||
sizeof k
|
sizeof k
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
set -e
|
set -e
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
../../bin/dcd-client $1 file.d -c66 > actual1.txt
|
../../bin/dcd-client $1 file.d --extended -c66 > actual1.txt
|
||||||
diff actual1.txt expected1.txt --strip-trailing-cr
|
diff actual1.txt expected1.txt --strip-trailing-cr
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
identifiers
|
identifiers
|
||||||
bar v foo bar stdin 92
|
bar v stdin 92
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
int inside_data;
|
||||||
|
Inner inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Inner
|
||||||
|
{
|
||||||
|
int inside_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AganeOne(T)
|
||||||
|
{
|
||||||
|
int inside_aganeone;
|
||||||
|
T yo;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AganeTwo(T, U)
|
||||||
|
{
|
||||||
|
int inside_aganetwo;
|
||||||
|
T yo_T;
|
||||||
|
U yo_U;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Other(T)
|
||||||
|
{
|
||||||
|
int inside_other;
|
||||||
|
T what;
|
||||||
|
AganeOne!(T) agane_T;
|
||||||
|
AganeOne!(Inner) agane_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct One(T){ T inside_one; }
|
||||||
|
|
||||||
|
struct Outter {
|
||||||
|
struct Two(T, U){ int inside_two; T agane_one; U agane_two; One!(T) one_agane_one; T get_T(T)(){return T.init;} U get_U(){return U.init;} }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A{ int inside_a;}
|
||||||
|
struct B{ int inside_b;}
|
||||||
|
struct C{ int inside_c;}
|
||||||
|
|
||||||
|
struct What
|
||||||
|
{
|
||||||
|
int inside_what;
|
||||||
|
const(V) get_it(T, U, V)() { return T.init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
auto from_auto = Outter.Two!(
|
||||||
|
AganeOne!(Other!(Data)),
|
||||||
|
AganeTwo!(A, B)
|
||||||
|
)();
|
||||||
|
|
||||||
|
Outter.Two!(
|
||||||
|
AganeOne!(Other!(Data)),
|
||||||
|
AganeTwo!(A, Other!(B))
|
||||||
|
) from_normal;
|
||||||
|
|
||||||
|
auto u = from_auto.get_U();
|
||||||
|
auto uuu = from_normal.agane_two;
|
||||||
|
|
||||||
|
auto v = from_normal.get_U();
|
||||||
|
|
||||||
|
What what;
|
||||||
|
auto it = what.get_it!(A, B, C)();
|
||||||
|
|
||||||
|
{
|
||||||
|
from_auto.agane_one.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
from_auto.agane_two.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
from_normal.agane_two.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
from_normal.agane_two.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
u.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
uuu.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
uuu.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
it.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
one_t v One!T one_t stdin 103 One!T
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_t v A value_t stdin 0 A
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_t v A value_t stdin 0 A
|
||||||
|
value_u v B value_u stdin 0 B
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
one_t v One!T one_t stdin 103 One!T
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_t v A value_t stdin 0 A
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_t v A value_t stdin 0 A
|
||||||
|
value_u v B value_u stdin 0 B
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_key v int value_key stdin 0 int
|
||||||
|
value_value v int value_value stdin 0 int
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_key v int value_key stdin 0 int
|
||||||
|
value_value v int value_value stdin 0 int
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_key v int value_key stdin 0 int
|
||||||
|
value_value v int value_value stdin 0 int
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
value_key v int value_key stdin 0 int
|
||||||
|
value_value v int value_value stdin 0 int
|
|
@ -0,0 +1,8 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k int
|
||||||
|
mangleof k
|
||||||
|
max k int
|
||||||
|
min k int
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
|
@ -0,0 +1,9 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_aganeone v int inside_aganeone stdin 124 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
yo v Other yo stdin 0 Other
|
|
@ -0,0 +1,10 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_aganetwo v int inside_aganetwo stdin 186 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
yo_T v A yo_T stdin 0 A
|
||||||
|
yo_U v B yo_U stdin 0 B
|
|
@ -0,0 +1,10 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_aganetwo v int inside_aganetwo stdin 186 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
yo_T v A yo_T stdin 0 A
|
||||||
|
yo_U v Other yo_U stdin 0 Other
|
|
@ -0,0 +1,10 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_aganetwo v int inside_aganetwo stdin 186 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
yo_T v A yo_T stdin 0 A
|
||||||
|
yo_U v Other yo_U stdin 0 Other
|
|
@ -0,0 +1,10 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_aganetwo v int inside_aganetwo stdin 186 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
yo_T v A yo_T stdin 0 A
|
||||||
|
yo_U v B yo_U stdin 0 B
|
|
@ -0,0 +1,10 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_aganetwo v int inside_aganetwo stdin 186 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
yo_T v A yo_T stdin 0 A
|
||||||
|
yo_U v Other yo_U stdin 0 Other
|
|
@ -0,0 +1,10 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_aganetwo v int inside_aganetwo stdin 186 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
||||||
|
yo_T v A yo_T stdin 0 A
|
||||||
|
yo_U v Other yo_U stdin 0 Other
|
|
@ -0,0 +1,8 @@
|
||||||
|
identifiers
|
||||||
|
alignof k
|
||||||
|
init k
|
||||||
|
inside_c v int inside_c stdin 605 int
|
||||||
|
mangleof k
|
||||||
|
sizeof k
|
||||||
|
stringof k
|
||||||
|
tupleof k
|
|
@ -0,0 +1,2 @@
|
||||||
|
identifiers
|
||||||
|
read_test f void read_test() stdin 38 void
|
|
@ -0,0 +1,31 @@
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
int inside_a;
|
||||||
|
}
|
||||||
|
struct B
|
||||||
|
{
|
||||||
|
int inside_b;
|
||||||
|
}
|
||||||
|
struct One(T)
|
||||||
|
{
|
||||||
|
T value_t;
|
||||||
|
One!T one_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Two(T, U)
|
||||||
|
{
|
||||||
|
T value_t;
|
||||||
|
U value_u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
auto from_auto_one = One!(A)();
|
||||||
|
auto from_auto_two = Two!(A, B)();
|
||||||
|
{
|
||||||
|
from_auto_one.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
from_auto_two.
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
int inside_a;
|
||||||
|
}
|
||||||
|
struct B
|
||||||
|
{
|
||||||
|
int inside_b;
|
||||||
|
}
|
||||||
|
struct One(T)
|
||||||
|
{
|
||||||
|
T value_t;
|
||||||
|
One!T one_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Two(T, U)
|
||||||
|
{
|
||||||
|
T value_t;
|
||||||
|
U value_u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
One!A from_normal_one;
|
||||||
|
Two!(A, B) from_normal_two;
|
||||||
|
{
|
||||||
|
from_normal_one.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
from_normal_two.
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
struct TopHashMap(Key, Value)
|
||||||
|
{
|
||||||
|
Key value_key;
|
||||||
|
Value value_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
auto top = TopHashMap!(int, int)();
|
||||||
|
auto bottom = BottomHashMap!(int, int)();
|
||||||
|
{
|
||||||
|
top.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto copy = top;
|
||||||
|
copy.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bottom.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto copy = bottom;
|
||||||
|
copy.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto wf = WithFunction!(int, int)();
|
||||||
|
auto gkey = wf.get_key();
|
||||||
|
gkey.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BottomHashMap(Key, Value)
|
||||||
|
{
|
||||||
|
Key value_key;
|
||||||
|
Value value_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WithFunction(Key, Value)
|
||||||
|
{
|
||||||
|
Key get_key()
|
||||||
|
{
|
||||||
|
return Key.init;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value get_value()
|
||||||
|
{
|
||||||
|
return Value.init;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
struct ReaderTest(bool LE)
|
||||||
|
{
|
||||||
|
void read_test(){}
|
||||||
|
}
|
||||||
|
alias ReaderTestBE = ReaderTest!true;
|
||||||
|
struct Test
|
||||||
|
{
|
||||||
|
void read(ReaderTestBE* reader)
|
||||||
|
{
|
||||||
|
reader.re
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -u
|
||||||
|
|
||||||
|
MODE=$1
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
echo ":: :: check: $1 $2 $3"
|
||||||
|
../../bin/dcd-client.exe $MODE $1.d --extended -c $2 > $3.txt
|
||||||
|
diff $3.txt $4.txt --strip-trailing-cr
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#echo "extra"
|
||||||
|
check file4 165 actual_extra_1 expected_extra_1
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test1"
|
||||||
|
check file1 282 actual_1_1 expected_1_1
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test2"
|
||||||
|
check file1 317 actual_1_2 expected_1_2
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test3"
|
||||||
|
check file2 268 actual_2_1 expected_2_1
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test4"
|
||||||
|
check file2 305 actual_2_2 expected_2_2
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test5"
|
||||||
|
check file3 195 actual_3_1 expected_3_1
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test6"
|
||||||
|
check file3 246 actual_3_2 expected_3_2
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test7"
|
||||||
|
check file3 274 actual_3_3 expected_3_3
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test8"
|
||||||
|
check file3 328 actual_3_4 expected_3_4
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test9"
|
||||||
|
check file3 433 actual_3_5 expected_3_5
|
||||||
|
|
||||||
|
|
||||||
|
#echo "test complex"
|
||||||
|
check complex 1121 actual_complex_1 expected_complex_1
|
||||||
|
check complex 1162 actual_complex_2 expected_complex_2
|
||||||
|
check complex 1205 actual_complex_3 expected_complex_3
|
||||||
|
check complex 1248 actual_complex_4 expected_complex_4
|
||||||
|
check complex 1271 actual_complex_5 expected_complex_5
|
||||||
|
check complex 1296 actual_complex_6 expected_complex_6
|
||||||
|
check complex 1321 actual_complex_7 expected_complex_7
|
||||||
|
check complex 1345 actual_complex_8 expected_complex_8
|
Loading…
Reference in New Issue