resolve templates
This commit is contained in:
parent
1c54fc9873
commit
ce363bccae
|
|
@ -232,9 +232,167 @@ final class FirstPass : ASTVisitor
|
|||
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 (tip.typeIdentifierPart)
|
||||
processTypeIdentifierPart(symbol, lookup, ctx, current, tip.typeIdentifierPart);
|
||||
}
|
||||
|
||||
void processTemplateArguments(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateArguments targs)
|
||||
{
|
||||
if (targs.templateArgumentList)
|
||||
{
|
||||
foreach(i, targ; targs.templateArgumentList.items)
|
||||
{
|
||||
if (targ.type is null) continue;
|
||||
if (targ.type.type2 is null) continue;
|
||||
|
||||
auto part = targ.type.type2.typeIdentifierPart;
|
||||
if (part is null) continue;
|
||||
|
||||
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 (targs.templateSingleArgument)
|
||||
{
|
||||
auto singleArg = targs.templateSingleArgument;
|
||||
auto arg = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||
arg.parent = current;
|
||||
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);
|
||||
}
|
||||
|
||||
void buildChainTemplateOrIdentifier(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, IdentifierOrTemplateInstance iot)
|
||||
{
|
||||
auto crumb = iot.identifier;
|
||||
if (crumb != tok!"")
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
assert (currentSymbol);
|
||||
|
||||
foreach (declarator; dec.declarators)
|
||||
{
|
||||
SemanticSymbol* symbol = allocateSemanticSymbol(
|
||||
|
|
@ -255,6 +413,16 @@ final class FirstPass : ASTVisitor
|
|||
// TODO: remove this cast. See the note on structFieldTypes
|
||||
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)();
|
||||
processTypeIdentifierPart(symbol, lookup, &lookup.ctx, lookup.ctx.root, typeIdentifierPart);
|
||||
}
|
||||
}
|
||||
if (dec.autoDeclaration !is null)
|
||||
{
|
||||
|
|
@ -277,6 +445,66 @@ final class FirstPass : ASTVisitor
|
|||
// TODO: remove this cast. See the note on structFieldTypes
|
||||
structFieldTypes.insert(null);
|
||||
}
|
||||
|
||||
auto lookup = symbol.typeLookups.front;
|
||||
|
||||
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;
|
||||
|
||||
crumbs.clear();
|
||||
foreach_reverse(c; result)
|
||||
lookup.breadcrumbs.insert(c);
|
||||
|
||||
// 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,22 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac
|
|||
resolveType(currentSymbol.acSymbol, currentSymbol.typeLookups,
|
||||
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 || type.kind == functionName)
|
||||
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;
|
||||
case importSymbol:
|
||||
if (currentSymbol.acSymbol.type is null)
|
||||
|
|
@ -98,6 +114,198 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac
|
|||
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 = type.name;
|
||||
newType.kind = type.kind;
|
||||
newType.qualifier = type.qualifier;
|
||||
newType.protection = type.protection;
|
||||
newType.symbolFile = type.symbolFile;
|
||||
newType.doc = type.doc;
|
||||
newType.callTip = type.callTip;
|
||||
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)
|
||||
{
|
||||
// warning("too many T for args available, investigate");
|
||||
continue;
|
||||
}
|
||||
auto key = part.name;
|
||||
|
||||
DSymbol* first;
|
||||
foreach(i, crumb; ti.args[count].chain)
|
||||
{
|
||||
auto argName = crumb;
|
||||
if (i == 0)
|
||||
{
|
||||
|
||||
if (m)
|
||||
if (key in m)
|
||||
{
|
||||
argName = m[key].name;
|
||||
}
|
||||
|
||||
auto result = moduleScope.getSymbolsAtGlobalScope(istring(argName));
|
||||
if (result.length == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
first = result[0];
|
||||
}
|
||||
else
|
||||
first = first.getFirstPartNamed(istring(argName));
|
||||
}
|
||||
|
||||
if (first is null)
|
||||
continue;
|
||||
|
||||
auto ca = ti.args[count];
|
||||
if (ca.chain.length > 0)
|
||||
mapping[key] = createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
newType.type = mapping[retType];
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
newPart.ownType = true;
|
||||
newPart.type = mapping[part.type.name];
|
||||
}
|
||||
else if (m && part.type.name in m)
|
||||
{
|
||||
newPart.ownType = true;
|
||||
newPart.type = m[part.type.name];
|
||||
}
|
||||
|
||||
newType.addChild(newPart, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
// }
|
||||
// warning("go agane ".blue, part.name, " ", part.type.name, " with arg: ", ti.chain," Ts: ", T_names);
|
||||
// resolveTemplate(part, part.type, lookup, ti, moduleScope, cache, depth, 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping);
|
||||
|
||||
variableSym.type = newType;
|
||||
variableSym.ownType = true;
|
||||
}
|
||||
|
||||
void resolveImport(DSymbol* acSymbol, ref TypeLookups typeLookups,
|
||||
ref ModuleCache cache)
|
||||
|
|
|
|||
|
|
@ -37,4 +37,19 @@ struct TypeLookup
|
|||
UnrolledList!istring breadcrumbs;
|
||||
/// The kind of type lookup
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
identifiers
|
||||
C h
|
||||
alignof k
|
||||
i v
|
||||
i v int i stdin 21
|
||||
init k
|
||||
mangleof k
|
||||
sizeof k
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
set -e
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 one_t stdin 103
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
value_t v A value_t stdin 0
|
||||
|
|
@ -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
|
||||
value_u v B value_u stdin 0
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
mangleof k
|
||||
one_t v One one_t stdin 103
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
value_t v A value_t stdin 0
|
||||
|
|
@ -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
|
||||
value_u v B value_u stdin 0
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_aganeone v int inside_aganeone stdin 124
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
yo v Other yo stdin 0
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_aganetwo v int inside_aganetwo stdin 186
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
yo_T v A yo_T stdin 0
|
||||
yo_U v B yo_U stdin 0
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_aganetwo v int inside_aganetwo stdin 186
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
yo_T v A yo_T stdin 0
|
||||
yo_U v Other yo_U stdin 0
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_aganetwo v int inside_aganetwo stdin 186
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
yo_T v A yo_T stdin 0
|
||||
yo_U v Other yo_U stdin 0
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_aganetwo v int inside_aganetwo stdin 186
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
yo_T v A yo_T stdin 0
|
||||
yo_U v B yo_U stdin 0
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_aganetwo v int inside_aganetwo stdin 186
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
yo_T v A yo_T stdin 0
|
||||
yo_U v Other yo_U stdin 0
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_aganetwo v int inside_aganetwo stdin 186
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
yo_T v A yo_T stdin 0
|
||||
yo_U v Other yo_U stdin 0
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
inside_c v int inside_c stdin 605
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
|
|
@ -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 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
MODE=$1
|
||||
|
||||
|
||||
# ../../bin/dcd-client $1 file1.d --extended -c 270
|
||||
|
||||
function check () {
|
||||
echo "$1 $2"
|
||||
../../bin/dcd-client $MODE $1.d --extended -c $2 > $3.txt
|
||||
diff $3.txt $4.txt --strip-trailing-cr
|
||||
}
|
||||
|
||||
|
||||
#echo "test1"
|
||||
../../bin/dcd-client $1 file1.d --extended -c 280 > actual_1_1.txt
|
||||
diff actual_1_1.txt expected_1_1.txt --strip-trailing-cr
|
||||
|
||||
|
||||
#echo "test2"
|
||||
../../bin/dcd-client $1 file1.d --extended -c 315 > actual_1_2.txt
|
||||
diff actual_1_2.txt expected_1_2.txt --strip-trailing-cr
|
||||
|
||||
|
||||
|
||||
#echo "test3"
|
||||
../../bin/dcd-client $1 file2.d --extended -c 268 > actual_2_1.txt
|
||||
diff actual_2_1.txt expected_2_1.txt --strip-trailing-cr
|
||||
|
||||
|
||||
#echo "test4"
|
||||
../../bin/dcd-client $1 file2.d --extended -c 305 > actual_2_2.txt
|
||||
diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr
|
||||
|
||||
|
||||
|
||||
#echo "test c omplex"
|
||||
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