implement typeof in types
This commit is contained in:
parent
25139a8833
commit
fe6ce04720
|
@ -165,6 +165,20 @@ package istring[24] builtinTypeNames;
|
|||
* class. DSymbol child of the class type, with the baseClass as its child type.
|
||||
*/
|
||||
@("super") istring SUPER_SYMBOL_NAME;
|
||||
/**
|
||||
* This symbol name may appear at the start of breadcrumbs meaning the remaining
|
||||
* breadcrumbs up until the matching $(LREF TYPEOF_END_SYMBOL_NAME) are an
|
||||
* initializer or typeof expression. Pointer/Array suffixes are parsed
|
||||
* beforehand, using popBack to remove them from the breadcrumbs.
|
||||
*
|
||||
* See_Also: $(LREF TYPEOF_END_SYMBOL_NAME)
|
||||
*/
|
||||
@("typeof(") istring TYPEOF_SYMBOL_NAME;
|
||||
/**
|
||||
* This symbol always appears in pairs with TYPEOF_SYMBOL_NAME, designates the
|
||||
* end of the typeof expression in the breadcrumbs.
|
||||
*/
|
||||
@(")/*typeof*/") istring TYPEOF_END_SYMBOL_NAME;
|
||||
|
||||
/**
|
||||
* Breadcrumb part in initializer type generation for literal values in the
|
||||
|
|
|
@ -271,7 +271,7 @@ final class FirstPass : ASTVisitor
|
|||
part.identifier.text, CompletionKind.variableName,
|
||||
symbolFile, part.identifier.index);
|
||||
symbol.parent = currentSymbol;
|
||||
populateInitializer(symbol, part.initializer);
|
||||
populateInitializer(symbol.typeLookups, part.initializer);
|
||||
symbol.acSymbol.protection = protection.current;
|
||||
symbol.acSymbol.doc = makeDocumentation(dec.comment);
|
||||
currentSymbol.addChild(symbol, true);
|
||||
|
@ -719,7 +719,7 @@ final class FirstPass : ASTVisitor
|
|||
currentSymbol.addChild(symbol, true);
|
||||
currentScope.addSymbol(symbol.acSymbol, true);
|
||||
if (symbol.typeLookups.empty && feExpression !is null)
|
||||
populateInitializer(symbol, feExpression, true);
|
||||
populateInitializer(symbol.typeLookups, feExpression, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -738,7 +738,7 @@ final class FirstPass : ASTVisitor
|
|||
currentSymbol.addChild(symbol, true);
|
||||
currentScope.addSymbol(symbol.acSymbol, true);
|
||||
if (symbol.typeLookups.empty && ifs.condition !is null && ifs.condition.expression !is null)
|
||||
populateInitializer(symbol, ifs.condition.expression, false);
|
||||
populateInitializer(symbol.typeLookups, ifs.condition.expression, false);
|
||||
}
|
||||
ifs.accept(this);
|
||||
}
|
||||
|
@ -756,7 +756,7 @@ final class FirstPass : ASTVisitor
|
|||
currentScope.startLocation, null);
|
||||
scope(exit) popSymbol();
|
||||
|
||||
populateInitializer(currentSymbol, withStatement.expression, false);
|
||||
populateInitializer(currentSymbol.typeLookups, withStatement.expression, false);
|
||||
withStatement.accept(this);
|
||||
|
||||
}
|
||||
|
@ -1127,12 +1127,19 @@ private:
|
|||
return istring(app.data);
|
||||
}
|
||||
|
||||
void populateInitializer(T)(SemanticSymbol* symbol, const T initializer,
|
||||
bool appendForeach = false)
|
||||
void populateInitializer(T)(ref TypeLookups lookups, const T initializer,
|
||||
bool appendForeach = false, TypeLookup* l = null)
|
||||
{
|
||||
auto lookup = TypeLookupsAllocator.instance.make!TypeLookup(TypeLookupKind.initializer);
|
||||
auto lookup = l ? l : TypeLookupsAllocator.instance.make!TypeLookup(TypeLookupKind.varOrFunType);
|
||||
|
||||
lookup.breadcrumbs.insert(TYPEOF_SYMBOL_NAME);
|
||||
scope (exit)
|
||||
lookup.breadcrumbs.insert(TYPEOF_END_SYMBOL_NAME);
|
||||
scope visitor = new InitializerVisitor(lookup, appendForeach, this);
|
||||
symbol.typeLookups.insert(lookup);
|
||||
|
||||
if (l is null)
|
||||
lookups.insert(lookup);
|
||||
|
||||
static if (is(T == typeof(feExpression)))
|
||||
visitor.dynamicDispatch(initializer);
|
||||
else
|
||||
|
@ -1155,22 +1162,20 @@ private:
|
|||
auto lookup = l !is null ? l : TypeLookupsAllocator.instance.make!TypeLookup(
|
||||
TypeLookupKind.varOrFunType);
|
||||
auto t2 = type.type2;
|
||||
if (t2.type !is null)
|
||||
addTypeToLookups(lookups, t2.type, lookup);
|
||||
if (t2.typeofExpression !is null)
|
||||
populateInitializer(lookups, t2.typeofExpression, false, lookup);
|
||||
else if (t2.superOrThis is tok!"this")
|
||||
lookup.breadcrumbs.insert(internString("this"));
|
||||
else if (t2.superOrThis is tok!"super")
|
||||
lookup.breadcrumbs.insert(internString("super"));
|
||||
|
||||
if (t2.type !is null)
|
||||
addTypeToLookups(lookups, t2.type, lookup);
|
||||
else if (t2.builtinType !is tok!"")
|
||||
lookup.breadcrumbs.insert(getBuiltinTypeName(t2.builtinType));
|
||||
else if (t2.typeIdentifierPart !is null)
|
||||
writeIotcTo(t2.typeIdentifierPart, lookup.breadcrumbs);
|
||||
else
|
||||
{
|
||||
// TODO: Add support for typeof expressions
|
||||
// TODO: Add support for __vector
|
||||
// warning("typeof() and __vector are not yet supported");
|
||||
}
|
||||
// TODO: support __vector, traits and mixin
|
||||
|
||||
foreach (suffix; type.typeSuffixes)
|
||||
{
|
||||
|
|
|
@ -237,10 +237,27 @@ do
|
|||
}
|
||||
|
||||
// Follow all the names and try to resolve them
|
||||
size_t i = 0;
|
||||
foreach (part; lookup.breadcrumbs[])
|
||||
bool first = true;
|
||||
auto breadcrumbs = lookup.breadcrumbs[];
|
||||
|
||||
while (!breadcrumbs.empty)
|
||||
{
|
||||
if (i == 0)
|
||||
auto part = breadcrumbs.front;
|
||||
breadcrumbs.popFront();
|
||||
scope (exit)
|
||||
first = false;
|
||||
|
||||
if (part == TYPEOF_SYMBOL_NAME)
|
||||
{
|
||||
if (currentSymbol !is null)
|
||||
{
|
||||
warning("Invalid breadcrumbs, found `Type.typeof(...)`");
|
||||
return;
|
||||
}
|
||||
resolveTypeFromInitializer(symbol, lookup, moduleScope, cache,
|
||||
breadcrumbs, currentSymbol);
|
||||
}
|
||||
else if (first)
|
||||
{
|
||||
if (moduleScope is null)
|
||||
getSymbolFromImports(imports, part);
|
||||
|
@ -273,7 +290,6 @@ do
|
|||
return;
|
||||
currentSymbol = currentSymbol.getFirstPartNamed(part);
|
||||
}
|
||||
++i;
|
||||
if (currentSymbol is null)
|
||||
return;
|
||||
}
|
||||
|
@ -311,19 +327,32 @@ do
|
|||
}
|
||||
}
|
||||
|
||||
void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||
Scope* moduleScope, ref ModuleCache cache)
|
||||
private void resolveTypeFromInitializer(R)(DSymbol* symbol, TypeLookup* lookup,
|
||||
Scope* moduleScope, ref ModuleCache cache,
|
||||
ref R breadcrumbs, ref DSymbol* currentSymbol)
|
||||
{
|
||||
if (lookup.breadcrumbs.length == 0)
|
||||
if (breadcrumbs.empty)
|
||||
return;
|
||||
DSymbol* currentSymbol = null;
|
||||
size_t i = 0;
|
||||
|
||||
auto crumbs = lookup.breadcrumbs[];
|
||||
foreach (crumb; crumbs)
|
||||
bool first = true;
|
||||
while (!breadcrumbs.empty)
|
||||
{
|
||||
if (i == 0)
|
||||
auto crumb = breadcrumbs.front;
|
||||
breadcrumbs.popFront();
|
||||
if (crumb == TYPEOF_SYMBOL_NAME)
|
||||
{
|
||||
resolveTypeFromInitializer(symbol, lookup, moduleScope, cache,
|
||||
breadcrumbs, currentSymbol);
|
||||
if (currentSymbol is null)
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
if (crumb == TYPEOF_END_SYMBOL_NAME)
|
||||
break;
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
currentSymbol = moduleScope.getFirstSymbolByNameAndCursor(
|
||||
symbolNameToTypeName(crumb), symbol.location);
|
||||
|
||||
|
@ -348,18 +377,21 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
|||
|| currentSymbol.qualifier == SymbolQualifier.pointer
|
||||
|| currentSymbol.kind == CompletionKind.aliasName)
|
||||
{
|
||||
if (currentSymbol.type !is null)
|
||||
currentSymbol = currentSymbol.type;
|
||||
else
|
||||
return;
|
||||
// may become null, returns later
|
||||
currentSymbol = currentSymbol.type;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto opIndex = currentSymbol.getFirstPartNamed(internString("opIndex"));
|
||||
if (opIndex !is null)
|
||||
{
|
||||
currentSymbol = opIndex.type;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSymbol = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (crumb == "foreach")
|
||||
|
@ -371,19 +403,19 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
|||
|| currentSymbol.qualifier == SymbolQualifier.assocArray)
|
||||
{
|
||||
currentSymbol = currentSymbol.type;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
auto front = currentSymbol.getFirstPartNamed(internString("front"));
|
||||
if (front !is null)
|
||||
{
|
||||
currentSymbol = front.type;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
auto opApply = currentSymbol.getFirstPartNamed(internString("opApply"));
|
||||
if (opApply !is null)
|
||||
{
|
||||
currentSymbol = opApply.type;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -393,13 +425,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
|||
return;
|
||||
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
|
||||
}
|
||||
++i;
|
||||
if (currentSymbol is null)
|
||||
return;
|
||||
}
|
||||
typeSwap(currentSymbol);
|
||||
symbol.type = currentSymbol;
|
||||
symbol.ownType = false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -506,8 +535,6 @@ void resolveType(DSymbol* symbol, ref TypeLookups typeLookups,
|
|||
foreach(lookup; typeLookups) {
|
||||
if (lookup.kind == TypeLookupKind.varOrFunType)
|
||||
resolveTypeFromType(symbol, lookup, moduleScope, cache, null);
|
||||
else if (lookup.kind == TypeLookupKind.initializer)
|
||||
resolveTypeFromInitializer(symbol, lookup, moduleScope, cache);
|
||||
// issue 94
|
||||
else if (lookup.kind == TypeLookupKind.inherit)
|
||||
resolveInheritance(symbol, typeLookups, moduleScope, cache);
|
||||
|
|
|
@ -64,8 +64,6 @@ void checkMissingTypes(SemanticSymbol* currentSymbol, Scope* moduleScope, ref Mo
|
|||
auto lookup = currentSymbol.typeLookups.front;
|
||||
if (lookup.kind == TypeLookupKind.varOrFunType)
|
||||
resolveTypeFromType(currentSymbol.acSymbol, lookup, moduleScope, cache, null);
|
||||
else if (lookup.kind == TypeLookupKind.initializer)
|
||||
resolveTypeFromInitializer(currentSymbol.acSymbol, lookup, moduleScope, cache);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -10,7 +10,6 @@ enum TypeLookupKind : ubyte
|
|||
{
|
||||
inherit,
|
||||
aliasThis,
|
||||
initializer,
|
||||
mixinTemplate,
|
||||
varOrFunType,
|
||||
selectiveImport,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
identifiers
|
||||
getMember f typeof(member) getMember() stdin 78 Result
|
||||
identifiers
|
||||
staticMember f typeof(S.member) staticMember() stdin 133 Result
|
||||
identifiers
|
||||
alignof k
|
||||
expected v int expected stdin 21 int
|
||||
init k
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
||||
identifiers
|
||||
alignof k
|
||||
expected v int expected stdin 21 int
|
||||
init k
|
||||
mangleof k
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
|
@ -0,0 +1,2 @@
|
|||
identifiers
|
||||
test v Enum test stdin 121 Enum
|
|
@ -0,0 +1,8 @@
|
|||
identifiers
|
||||
alignof k
|
||||
init k
|
||||
mangleof k
|
||||
ok v bool ok stdin 16 bool
|
||||
sizeof k
|
||||
stringof k
|
||||
tupleof k
|
|
@ -0,0 +1,14 @@
|
|||
set -e
|
||||
set -u
|
||||
|
||||
../../bin/dcd-client $1 test1.d -x -c213 > actual1.txt
|
||||
../../bin/dcd-client $1 test1.d -x -c239 >> actual1.txt
|
||||
../../bin/dcd-client $1 test1.d -x -c254 >> actual1.txt
|
||||
../../bin/dcd-client $1 test1.d -x -c265 >> actual1.txt
|
||||
diff actual1.txt expected1.txt --strip-trailing-cr
|
||||
|
||||
../../bin/dcd-client $1 test2.d -x -c132 > actual2.txt
|
||||
diff actual2.txt expected2.txt --strip-trailing-cr
|
||||
|
||||
../../bin/dcd-client $1 test3.d -x -c83 > actual3.txt
|
||||
diff actual3.txt expected3.txt --strip-trailing-cr
|
|
@ -0,0 +1,32 @@
|
|||
struct Result
|
||||
{
|
||||
int expected;
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
Result member;
|
||||
|
||||
typeof(member) getMember()
|
||||
{
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
typeof(S.member) staticMember()
|
||||
{
|
||||
return S.init.member;
|
||||
}
|
||||
|
||||
void test()
|
||||
{
|
||||
S s;
|
||||
auto a = S.getMember();
|
||||
auto b = staticMember();
|
||||
{
|
||||
a.
|
||||
}
|
||||
{
|
||||
b.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
struct MyTemplate(T)
|
||||
{
|
||||
enum Enum { a, b }
|
||||
|
||||
T member1;
|
||||
}
|
||||
|
||||
MyTemplate!long global2;
|
||||
|
||||
void main()
|
||||
{
|
||||
typeof(global2).Enum test;
|
||||
test
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
struct S { bool ok; }
|
||||
|
||||
S global3;
|
||||
|
||||
void main()
|
||||
{
|
||||
typeof(global3)[] test;
|
||||
test[0].
|
||||
}
|
||||
|
Loading…
Reference in New Issue