save progress
This commit is contained in:
parent
220dcb0445
commit
f34407ce31
|
|
@ -232,9 +232,127 @@ 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 processTemplateInstance(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateInstance ti)
|
||||||
|
{
|
||||||
|
if (ti.identifier != tok!"")
|
||||||
|
{
|
||||||
|
current.chain ~= ti.identifier.text;
|
||||||
|
warning("type: ", ti.identifier.text);
|
||||||
|
}
|
||||||
|
else assert(0, "templateinstance type missing");
|
||||||
|
|
||||||
|
if (ti.templateArguments)
|
||||||
|
{
|
||||||
|
if (ti.templateArguments.templateArgumentList)
|
||||||
|
{
|
||||||
|
foreach(i, targ; ti.templateArguments.templateArgumentList.items)
|
||||||
|
{
|
||||||
|
if (targ.type is null) continue;
|
||||||
|
if (targ.type.type2 is null) continue;
|
||||||
|
|
||||||
|
auto part = targ.type.type2.typeIdentifierPart;
|
||||||
|
auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
newArg.parent = current;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ti.templateArguments.templateSingleArgument)
|
||||||
|
{
|
||||||
|
auto singleArg = ti.templateArguments.templateSingleArgument;
|
||||||
|
symbol.acSymbol.tmplArgNames ~= istring(singleArg.token.text);
|
||||||
|
|
||||||
|
auto arg = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
arg.parent = current;
|
||||||
|
arg.name = singleArg.token.text;
|
||||||
|
arg.chain ~= arg.name;
|
||||||
|
current.args ~= arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void buildChainTemplateOrIdentifier(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, IdentifierOrTemplateInstance iot)
|
||||||
|
{
|
||||||
|
auto crumb = iot.identifier;
|
||||||
|
if (crumb != tok!"")
|
||||||
|
{
|
||||||
|
warning(" c: ", crumb.text);
|
||||||
|
lookup.breadcrumbs.insert(istring(crumb.text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iot.templateInstance)
|
||||||
|
{
|
||||||
|
if (iot.templateInstance.identifier != tok!"")
|
||||||
|
lookup.breadcrumbs.insert(istring(iot.templateInstance.identifier.text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void traverseUnaryExpression( SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, UnaryExpression ue)
|
||||||
|
{
|
||||||
|
warning("traverse unary");
|
||||||
|
if (PrimaryExpression pe = ue.primaryExpression)
|
||||||
|
{
|
||||||
|
warning("primary expression");
|
||||||
|
if (pe.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
|
buildChainTemplateOrIdentifier(symbol, lookup, ctx, pe.identifierOrTemplateInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IdentifierOrTemplateInstance iot = ue.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
|
warning("has iot");
|
||||||
|
|
||||||
|
auto crumb = iot.identifier;
|
||||||
|
if (crumb != tok!"")
|
||||||
|
{
|
||||||
|
warning(": ", crumb.text);
|
||||||
|
lookup.breadcrumbs.insert(istring(crumb.text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
warning("current: ", currentSymbol.acSymbol.name);
|
||||||
|
|
||||||
foreach (declarator; dec.declarators)
|
foreach (declarator; dec.declarators)
|
||||||
{
|
{
|
||||||
SemanticSymbol* symbol = allocateSemanticSymbol(
|
SemanticSymbol* symbol = allocateSemanticSymbol(
|
||||||
|
|
@ -262,14 +380,35 @@ final class FirstPass : ASTVisitor
|
||||||
typeIdentifierPart.identifierOrTemplateInstance.templateInstance)
|
typeIdentifierPart.identifierOrTemplateInstance.templateInstance)
|
||||||
{
|
{
|
||||||
auto templateInstance = typeIdentifierPart.identifierOrTemplateInstance.templateInstance;
|
auto templateInstance = typeIdentifierPart.identifierOrTemplateInstance.templateInstance;
|
||||||
if (templateInstance.templateArguments.templateArgumentList)
|
|
||||||
|
// if template
|
||||||
|
// allocate symbol
|
||||||
|
// set kind to TypeArg
|
||||||
|
// set index
|
||||||
|
// for each argument
|
||||||
|
// create child symbol
|
||||||
|
// set kind to TypeArg
|
||||||
|
// set index
|
||||||
|
|
||||||
|
// to resolve:
|
||||||
|
// get item.type
|
||||||
|
// copy symbol
|
||||||
|
// traverse and replace parts
|
||||||
|
|
||||||
|
if (!templateInstance.templateArguments)
|
||||||
|
{}
|
||||||
|
else if (templateInstance.templateArguments.templateArgumentList)
|
||||||
{
|
{
|
||||||
foreach(i, targ; templateInstance.templateArguments.templateArgumentList.items)
|
foreach(i, targ; templateInstance.templateArguments.templateArgumentList.items)
|
||||||
{
|
{
|
||||||
|
if (targ.type is null) continue;
|
||||||
// TODO: support template with multiple arguments
|
// TODO: support template with multiple arguments
|
||||||
|
auto tokens = targ.type.type2.tokens;
|
||||||
|
warning(" tokens: ", tokens[0].text);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (typeIdentifierPart.identifierOrTemplateInstance.templateInstance.templateArguments.templateSingleArgument)
|
else if (templateInstance.templateArguments.templateSingleArgument)
|
||||||
{
|
{
|
||||||
auto singleArg = typeIdentifierPart.identifierOrTemplateInstance.templateInstance.templateArguments.templateSingleArgument;
|
auto singleArg = typeIdentifierPart.identifierOrTemplateInstance.templateInstance.templateArguments.templateSingleArgument;
|
||||||
symbol.acSymbol.tmplArgNames ~= istring(singleArg.token.text);
|
symbol.acSymbol.tmplArgNames ~= istring(singleArg.token.text);
|
||||||
|
|
@ -279,11 +418,13 @@ final class FirstPass : ASTVisitor
|
||||||
}
|
}
|
||||||
if (dec.autoDeclaration !is null)
|
if (dec.autoDeclaration !is null)
|
||||||
{
|
{
|
||||||
|
warning("is auto!");
|
||||||
foreach (part; dec.autoDeclaration.parts)
|
foreach (part; dec.autoDeclaration.parts)
|
||||||
{
|
{
|
||||||
SemanticSymbol* symbol = allocateSemanticSymbol(
|
SemanticSymbol* symbol = allocateSemanticSymbol(
|
||||||
part.identifier.text, CompletionKind.variableName,
|
part.identifier.text, CompletionKind.variableName,
|
||||||
symbolFile, part.identifier.index);
|
symbolFile, part.identifier.index);
|
||||||
|
symbol.acSymbol.isAutoDeclaration = true;
|
||||||
symbol.parent = currentSymbol;
|
symbol.parent = currentSymbol;
|
||||||
populateInitializer(symbol, part.initializer);
|
populateInitializer(symbol, part.initializer);
|
||||||
symbol.acSymbol.protection = protection.current;
|
symbol.acSymbol.protection = protection.current;
|
||||||
|
|
@ -291,6 +432,80 @@ final class FirstPass : ASTVisitor
|
||||||
currentSymbol.addChild(symbol, true);
|
currentSymbol.addChild(symbol, true);
|
||||||
currentScope.addSymbol(symbol.acSymbol, false);
|
currentScope.addSymbol(symbol.acSymbol, false);
|
||||||
|
|
||||||
|
warning(" part: ", symbol.acSymbol.name);
|
||||||
|
scope(exit) warning("crumbs: ", symbol.typeLookups.front.breadcrumbs[]);
|
||||||
|
|
||||||
|
// for auto declaration, we'll properly traverse the initializer
|
||||||
|
// and set the proper crumbs instead of using just the first one
|
||||||
|
// so we can handle things like cast/templates
|
||||||
|
auto lookup = symbol.typeLookups.front;
|
||||||
|
lookup.breadcrumbs.clear();
|
||||||
|
|
||||||
|
auto initializer = part.initializer.nonVoidInitializer;
|
||||||
|
if (initializer && initializer.assignExpression)
|
||||||
|
{
|
||||||
|
UnaryExpression unary = cast(UnaryExpression) initializer.assignExpression;
|
||||||
|
if (unary)
|
||||||
|
{
|
||||||
|
if (CastExpression castExpression = unary.castExpression)
|
||||||
|
{
|
||||||
|
warning("cast expression");
|
||||||
|
if (castExpression.type && castExpression.type.type2)
|
||||||
|
{
|
||||||
|
Type2 t2 = castExpression.type.type2;
|
||||||
|
if (t2 && t2.typeIdentifierPart)
|
||||||
|
{
|
||||||
|
buildChain(symbol, lookup, &lookup.ctx, t2.typeIdentifierPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FunctionCallExpression fc = unary.functionCallExpression)
|
||||||
|
{
|
||||||
|
warning("functioncall expression ", fc.type, " ", fc.unaryExpression," ", fc.templateArguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unary)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
crumbs.clear();
|
||||||
|
foreach_reverse(c; result)
|
||||||
|
{
|
||||||
|
lookup.breadcrumbs.insert(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check template
|
||||||
|
if (IdentifierOrTemplateInstance iot = unary.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto crumb = iot.identifier;
|
||||||
|
if (crumb != tok!"")
|
||||||
|
{
|
||||||
|
lookup.breadcrumbs.insert(istring(crumb.text));
|
||||||
|
}
|
||||||
|
else if (iot.templateInstance)
|
||||||
|
{
|
||||||
|
auto tic = iot.templateInstance.identifier;
|
||||||
|
warning("template! ", tic.text);
|
||||||
|
lookup.breadcrumbs.insert(istring(tic.text));
|
||||||
|
|
||||||
|
lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
assert(lookup.ctx.root != null);
|
||||||
|
processTemplateInstance(symbol, lookup, &lookup.ctx, lookup.ctx.root, iot.templateInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (currentSymbol.acSymbol.kind == CompletionKind.structName
|
if (currentSymbol.acSymbol.kind == CompletionKind.structName
|
||||||
|| currentSymbol.acSymbol.kind == CompletionKind.unionName)
|
|| currentSymbol.acSymbol.kind == CompletionKind.unionName)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,25 @@ 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)
|
||||||
|
{
|
||||||
|
TypeLookup* lookup = currentSymbol.typeLookups.front;
|
||||||
|
if (lookup.ctx.root)
|
||||||
|
{
|
||||||
|
auto type = currentSymbol.acSymbol.type;
|
||||||
|
if (type.kind == structName || type.kind == className)
|
||||||
|
{
|
||||||
|
int depth;
|
||||||
|
resolveTemplate(currentSymbol.acSymbol, type, lookup, lookup.ctx.root, moduleScope, cache, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
warning("no type: ", currentSymbol.acSymbol.name," ", currentSymbol.acSymbol.kind);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case importSymbol:
|
case importSymbol:
|
||||||
if (currentSymbol.acSymbol.type is null)
|
if (currentSymbol.acSymbol.type is null)
|
||||||
|
|
@ -76,6 +95,7 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac
|
||||||
case dummy:
|
case dummy:
|
||||||
case templateName:
|
case templateName:
|
||||||
case mixinTemplateName:
|
case mixinTemplateName:
|
||||||
|
case argTmpParam:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,40 +114,15 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac
|
||||||
resolveMixinTemplates(currentSymbol.acSymbol, currentSymbol.typeLookups,
|
resolveMixinTemplates(currentSymbol.acSymbol, currentSymbol.typeLookups,
|
||||||
moduleScope, cache);
|
moduleScope, cache);
|
||||||
break;
|
break;
|
||||||
case variableName:
|
|
||||||
case functionName:
|
|
||||||
if (currentSymbol.acSymbol.tmplArgNames.length > 0 && currentSymbol.acSymbol.type)
|
|
||||||
{
|
|
||||||
auto tArgNames = currentSymbol.acSymbol.tmplArgNames;
|
|
||||||
auto type = currentSymbol.acSymbol.type;
|
|
||||||
if (type.kind == structName || type.kind == className)
|
|
||||||
{
|
|
||||||
int depth;
|
|
||||||
resolveTemplate(currentSymbol.acSymbol, type, tArgNames, moduleScope, cache, depth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
warning("no type: ", currentSymbol.acSymbol.name," ", currentSymbol.acSymbol.kind);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve template arguments
|
DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableContext.TypeInstance* ti, ref ModuleCache cache, Scope* moduleScope, ref int depth, DSymbol*[string] m = null)
|
||||||
*/
|
|
||||||
void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgNames, Scope* moduleScope, ref ModuleCache cache, ref int depth)
|
|
||||||
{
|
{
|
||||||
depth += 1;
|
warning("processing type: ", type.name, " ", ti.chain, " ", ti.args);
|
||||||
if (tmplArgNames.length > 1) return;
|
|
||||||
auto argName = tmplArgNames[0];
|
|
||||||
auto result = moduleScope.getSymbolsAtGlobalScope(argName);
|
|
||||||
if (result.length > 0)
|
|
||||||
{
|
|
||||||
auto argSymbol = result[0];
|
|
||||||
DSymbol* newType = GCAllocator.instance.make!DSymbol("", CompletionKind.dummy, null);
|
DSymbol* newType = GCAllocator.instance.make!DSymbol("", CompletionKind.dummy, null);
|
||||||
newType.name = type.name;
|
newType.name = type.name;
|
||||||
newType.kind = type.kind;
|
newType.kind = type.kind;
|
||||||
|
|
@ -136,51 +131,145 @@ void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgN
|
||||||
newType.symbolFile = type.symbolFile;
|
newType.symbolFile = type.symbolFile;
|
||||||
newType.doc = type.doc;
|
newType.doc = type.doc;
|
||||||
newType.callTip = type.callTip;
|
newType.callTip = type.callTip;
|
||||||
|
DSymbol*[string] mapping;
|
||||||
|
|
||||||
DSymbol* currentT = null;
|
if (m)
|
||||||
|
foreach(k,v; m)
|
||||||
|
{
|
||||||
|
mapping[k] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int[string] mapping_index;
|
||||||
|
int count = 0;
|
||||||
|
if (ti.args.length > 0)
|
||||||
|
{
|
||||||
|
warning("hard args, build mapping");
|
||||||
foreach(part; type.opSlice())
|
foreach(part; type.opSlice())
|
||||||
{
|
{
|
||||||
if (part.kind == CompletionKind.typeTmpParam)
|
if (part.kind == CompletionKind.typeTmpParam)
|
||||||
{
|
{
|
||||||
currentT = part;
|
scope(exit) count++;
|
||||||
|
|
||||||
|
warning("building mapping for: ", part.name, " chain: ", ti.args[count].chain);
|
||||||
|
auto key = part.name;
|
||||||
|
|
||||||
|
DSymbol* first;
|
||||||
|
foreach(i, crumb; ti.args[count].chain)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
auto result = moduleScope.getSymbolsAtGlobalScope(istring(crumb));
|
||||||
|
if (result.length == 0)
|
||||||
|
{
|
||||||
|
error("can't find symbol: ", crumb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
first = result[0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
first = first.getFirstPartNamed(istring(crumb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping_index[key] = count;
|
||||||
|
if (first is null)
|
||||||
|
{
|
||||||
|
error("can't find type for mapping: ", part.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
warning(" map: ", key ,"->", first.name);
|
||||||
|
|
||||||
|
mapping[key] = createTypeWithTemplateArgs(first, lookup, ti.args[count], cache, moduleScope, depth, m ? m : mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string[] T_names;
|
||||||
|
|
||||||
|
foreach(part; type.opSlice())
|
||||||
|
{
|
||||||
|
if (part.kind == CompletionKind.typeTmpParam)
|
||||||
|
{
|
||||||
|
warning(" #", count, " ", part.name);
|
||||||
|
T_names ~= part.name;
|
||||||
}
|
}
|
||||||
else if (part.type && part.type.kind == CompletionKind.typeTmpParam)
|
else if (part.type && part.type.kind == CompletionKind.typeTmpParam)
|
||||||
{
|
{
|
||||||
DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, argSymbol);
|
DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, null);
|
||||||
newPart.qualifier = part.qualifier;
|
newPart.qualifier = part.qualifier;
|
||||||
newPart.protection = part.protection;
|
newPart.protection = part.protection;
|
||||||
newPart.symbolFile = part.symbolFile;
|
newPart.symbolFile = part.symbolFile;
|
||||||
newPart.doc = part.doc;
|
newPart.doc = part.doc;
|
||||||
newPart.callTip = part.callTip;
|
newPart.callTip = part.callTip;
|
||||||
newPart.type = argSymbol;
|
newPart.ownType = true;
|
||||||
if (part.kind == CompletionKind.functionName)
|
|
||||||
|
if (part.type.name in mapping)
|
||||||
{
|
{
|
||||||
if (part.type && part.type.kind == CompletionKind.typeTmpParam)
|
newPart.type = mapping[part.type.name];
|
||||||
|
warning(" mapping found: ", part.type.name," -> ", newPart.type.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (m && part.type.name in m)
|
||||||
{
|
{
|
||||||
newPart.type = argSymbol;
|
newPart.type = m[part.type.name];
|
||||||
}
|
warning(" mapping found: ", part.type.name," -> ", newPart.type.name);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
error(" mapping not found: ", part.type.name);
|
||||||
|
|
||||||
newType.addChild(newPart, true);
|
newType.addChild(newPart, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (part.tmplArgNames.length > 0)
|
|
||||||
{
|
|
||||||
auto innerArg = part.tmplArgNames[0];
|
|
||||||
if (innerArg == currentT.name)
|
|
||||||
{
|
{
|
||||||
if (depth < 50)
|
if (depth < 50)
|
||||||
resolveTemplate(part, part.type, [argName], moduleScope, cache, depth);
|
if (part.type && part.kind == CompletionKind.variableName)
|
||||||
|
foreach(partPart; part.type.opSlice())
|
||||||
|
{
|
||||||
|
if (partPart.kind == CompletionKind.typeTmpParam)
|
||||||
|
{
|
||||||
|
|
||||||
|
warning("go agane ", part.name, " ", part.type.name, " with arg: ", ti.chain," Ts: ", T_names);
|
||||||
|
|
||||||
|
foreach(arg; ti.args)
|
||||||
|
{
|
||||||
|
warning(" >", arg.chain, " ", arg.args);
|
||||||
|
}
|
||||||
|
//resolveTemplate(part, part.type, lookup, ti, moduleScope, cache, depth, mapping);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newType.addChild(part, false);
|
newType.addChild(part, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym.type = newType;
|
return newType;
|
||||||
sym.ownType = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
|
||||||
|
warning("resolving template for var: ", variableSym.name, " type: ", type.name, "depth: ", depth);
|
||||||
|
warning("current args: ");
|
||||||
|
foreach(i, arg; current.args)
|
||||||
|
warning(" i: ", i, " ", arg.chain);
|
||||||
|
DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
in
|
in
|
||||||
|
|
@ -521,13 +610,17 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
auto crumbs = lookup.breadcrumbs[];
|
auto crumbs = lookup.breadcrumbs[];
|
||||||
foreach (crumb; crumbs)
|
foreach (crumb; crumbs)
|
||||||
{
|
{
|
||||||
|
warning("search: ", crumb);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
currentSymbol = moduleScope.getFirstSymbolByNameAndCursor(
|
currentSymbol = moduleScope.getFirstSymbolByNameAndCursor(
|
||||||
symbolNameToTypeName(crumb), symbol.location);
|
symbolNameToTypeName(crumb), symbol.location);
|
||||||
|
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
|
{
|
||||||
|
warning("return 0");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (crumb == ARRAY_LITERAL_SYMBOL_NAME)
|
if (crumb == ARRAY_LITERAL_SYMBOL_NAME)
|
||||||
|
|
@ -589,13 +682,19 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
{
|
{
|
||||||
typeSwap(currentSymbol);
|
typeSwap(currentSymbol);
|
||||||
if (currentSymbol is null )
|
if (currentSymbol is null )
|
||||||
|
{
|
||||||
|
warning("return ", i);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
|
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
|
{
|
||||||
|
warning("return ", i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
typeSwap(currentSymbol);
|
typeSwap(currentSymbol);
|
||||||
symbol.type = currentSymbol;
|
symbol.type = currentSymbol;
|
||||||
symbol.ownType = false;
|
symbol.ownType = false;
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,9 @@ enum CompletionKind : char
|
||||||
|
|
||||||
/// type template parameter when no constraint
|
/// type template parameter when no constraint
|
||||||
typeTmpParam = 'h',
|
typeTmpParam = 'h',
|
||||||
|
|
||||||
|
/// type template argument when no constraint
|
||||||
|
argTmpParam = 'H',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -386,6 +389,11 @@ struct DSymbol
|
||||||
*/
|
*/
|
||||||
istring[] tmplArgNames;
|
istring[] tmplArgNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template arguments symbols
|
||||||
|
*/
|
||||||
|
DSymbol*[] tmplArgs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function parameter symbols
|
* Function parameter symbols
|
||||||
*/
|
*/
|
||||||
|
|
@ -431,7 +439,8 @@ struct DSymbol
|
||||||
mixin(bitfields!(bool, "ownType", 1,
|
mixin(bitfields!(bool, "ownType", 1,
|
||||||
bool, "skipOver", 1,
|
bool, "skipOver", 1,
|
||||||
bool, "isPointer", 1,
|
bool, "isPointer", 1,
|
||||||
ubyte, "", 5));
|
bool, "isAutoDeclaration", 1,
|
||||||
|
ubyte, "", 4));
|
||||||
// dfmt on
|
// dfmt on
|
||||||
|
|
||||||
/// Protection level for this symbol
|
/// Protection level for this symbol
|
||||||
|
|
|
||||||
|
|
@ -37,4 +37,20 @@ 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;
|
||||||
|
TypeInstance* parent;
|
||||||
|
}
|
||||||
|
TypeInstance* root;
|
||||||
|
int num;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
identifiers
|
||||||
|
yo v Inner yo stdin 0
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
identifiers
|
||||||
|
yo_T v A yo_T stdin 0
|
||||||
|
yo_U v B yo_U stdin 0
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
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; }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A{ int inside_a;}
|
||||||
|
struct B{ int inside_b;}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
auto from_auto = Outter.Two!(
|
||||||
|
AganeOne!(Other!(Data)),
|
||||||
|
AganeTwo!(A, B)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
import std;
|
||||||
|
writeln(typeid(from_auto.agane_one.yo.agane_inner.yo));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
float inside_data;
|
||||||
|
Inner inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Inner
|
||||||
|
{
|
||||||
|
float inside_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AganeOne(T)
|
||||||
|
{
|
||||||
|
T yo;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AganeTwo(T, U)
|
||||||
|
{
|
||||||
|
T yo_T;
|
||||||
|
U yo_U;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Other(T)
|
||||||
|
{
|
||||||
|
T what;
|
||||||
|
AganeOne!(T) agane_T;
|
||||||
|
AganeOne!(Inner) agane_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct One(T){ T inside_one; }
|
||||||
|
|
||||||
|
struct Outter {
|
||||||
|
struct Two(T, U){ T agane_one; U agane_two; One!(T) one_agane_one; }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A{ int inside_a;}
|
||||||
|
struct B{ int inside_b;}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
auto from_auto = Outter.Two!(
|
||||||
|
AganeOne!(Other!Data),
|
||||||
|
AganeTwo!(A, B)
|
||||||
|
);
|
||||||
|
from_auto.agane_two.yo
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
float inside_data;
|
||||||
|
Inner inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Inner
|
||||||
|
{
|
||||||
|
float inside_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct AganeOne(T)
|
||||||
|
{
|
||||||
|
T yo;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AganeTwo(T, U)
|
||||||
|
{
|
||||||
|
T yo_T;
|
||||||
|
U yo_U;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Other(T)
|
||||||
|
{
|
||||||
|
T what;
|
||||||
|
AganeOne!(T) agane_T;
|
||||||
|
AganeOne!(Inner) agane_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct MyTemplate(T)
|
||||||
|
{
|
||||||
|
T T_value;
|
||||||
|
Other!(T) other;
|
||||||
|
|
||||||
|
T get_this_value(T)()
|
||||||
|
{
|
||||||
|
return T_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct Fat
|
||||||
|
{
|
||||||
|
struct Outter
|
||||||
|
{
|
||||||
|
struct Inner(T)
|
||||||
|
{
|
||||||
|
T from_inner_T;
|
||||||
|
}
|
||||||
|
int from_outter;
|
||||||
|
}
|
||||||
|
struct Other
|
||||||
|
{
|
||||||
|
int from_other;
|
||||||
|
}
|
||||||
|
struct Agane
|
||||||
|
{
|
||||||
|
int from_agane;
|
||||||
|
}
|
||||||
|
int from_fat;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct One(T){ T inside_one; }
|
||||||
|
|
||||||
|
struct Outter {
|
||||||
|
struct Two(T, U){ T agane_one; U agane_two; One!(T) one_agane_one; }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A{ int inside_a;}
|
||||||
|
struct B{ int inside_b;}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
auto from_auto = Outter.Two!(
|
||||||
|
AganeOne!(Other!Data),
|
||||||
|
AganeTwo!(A, B)
|
||||||
|
);
|
||||||
|
|
||||||
|
// import std;
|
||||||
|
from_auto.agane_one.yo.agane_inner.y;
|
||||||
|
|
||||||
|
//writeln(typeid(from_auto.agane_one.yo.agane_inner));
|
||||||
|
//writeln(typeid(from_auto.agane_one.yo.agane_T));
|
||||||
|
//writeln(typeid(from_auto.agane_one.yo.what));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Inner(IdentifierOrTemplateInstance)
|
||||||
|
|
||||||
|
[One, Two]
|
||||||
|
[Fat, Outter] [A, B]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
set -e
|
||||||
|
set -u
|
||||||
|
|
||||||
|
../../bin/dcd-client $1 file1.d --extended -c 688 > actual_1.txt
|
||||||
|
diff actual_1.txt expected_1.txt --strip-trailing-cr
|
||||||
|
|
||||||
|
|
||||||
|
../../bin/dcd-client $1 file2.d --extended -c 674 > actual_2.txt
|
||||||
|
diff actual_2.txt expected_2.txt --strip-trailing-cr
|
||||||
|
|
||||||
Loading…
Reference in New Issue