implement typeof in types
This commit is contained in:
parent
1c60c5480f
commit
35ab44f83d
|
@ -165,6 +165,20 @@ package istring[24] builtinTypeNames;
|
||||||
* class. DSymbol child of the class type, with the baseClass as its child type.
|
* class. DSymbol child of the class type, with the baseClass as its child type.
|
||||||
*/
|
*/
|
||||||
@("super") istring SUPER_SYMBOL_NAME;
|
@("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
|
* Breadcrumb part in initializer type generation for literal values in the
|
||||||
|
|
|
@ -270,7 +270,7 @@ final class FirstPass : ASTVisitor
|
||||||
part.identifier.text, CompletionKind.variableName,
|
part.identifier.text, CompletionKind.variableName,
|
||||||
symbolFile, part.identifier.index);
|
symbolFile, part.identifier.index);
|
||||||
symbol.parent = currentSymbol;
|
symbol.parent = currentSymbol;
|
||||||
populateInitializer(symbol, part.initializer);
|
populateInitializer(symbol.typeLookups, part.initializer);
|
||||||
symbol.acSymbol.protection = protection.current;
|
symbol.acSymbol.protection = protection.current;
|
||||||
symbol.acSymbol.doc = makeDocumentation(dec.comment);
|
symbol.acSymbol.doc = makeDocumentation(dec.comment);
|
||||||
currentSymbol.addChild(symbol, true);
|
currentSymbol.addChild(symbol, true);
|
||||||
|
@ -718,7 +718,7 @@ final class FirstPass : ASTVisitor
|
||||||
currentSymbol.addChild(symbol, true);
|
currentSymbol.addChild(symbol, true);
|
||||||
currentScope.addSymbol(symbol.acSymbol, true);
|
currentScope.addSymbol(symbol.acSymbol, true);
|
||||||
if (symbol.typeLookups.empty && feExpression !is null)
|
if (symbol.typeLookups.empty && feExpression !is null)
|
||||||
populateInitializer(symbol, feExpression, true);
|
populateInitializer(symbol.typeLookups, feExpression, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,7 +737,7 @@ final class FirstPass : ASTVisitor
|
||||||
currentSymbol.addChild(symbol, true);
|
currentSymbol.addChild(symbol, true);
|
||||||
currentScope.addSymbol(symbol.acSymbol, true);
|
currentScope.addSymbol(symbol.acSymbol, true);
|
||||||
if (symbol.typeLookups.empty && ifs.condition !is null && ifs.condition.expression !is null)
|
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);
|
ifs.accept(this);
|
||||||
}
|
}
|
||||||
|
@ -755,7 +755,7 @@ final class FirstPass : ASTVisitor
|
||||||
currentScope.startLocation, null);
|
currentScope.startLocation, null);
|
||||||
scope(exit) popSymbol();
|
scope(exit) popSymbol();
|
||||||
|
|
||||||
populateInitializer(currentSymbol, withStatement.expression, false);
|
populateInitializer(currentSymbol.typeLookups, withStatement.expression, false);
|
||||||
withStatement.accept(this);
|
withStatement.accept(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1121,12 +1121,19 @@ private:
|
||||||
return istring(app.data);
|
return istring(app.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void populateInitializer(T)(SemanticSymbol* symbol, const T initializer,
|
void populateInitializer(T)(ref TypeLookups lookups, const T initializer,
|
||||||
bool appendForeach = false)
|
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);
|
scope visitor = new InitializerVisitor(lookup, appendForeach, this);
|
||||||
symbol.typeLookups.insert(lookup);
|
|
||||||
|
if (l is null)
|
||||||
|
lookups.insert(lookup);
|
||||||
|
|
||||||
static if (is(T == typeof(feExpression)))
|
static if (is(T == typeof(feExpression)))
|
||||||
visitor.dynamicDispatch(initializer);
|
visitor.dynamicDispatch(initializer);
|
||||||
else
|
else
|
||||||
|
@ -1149,22 +1156,20 @@ private:
|
||||||
auto lookup = l !is null ? l : TypeLookupsAllocator.instance.make!TypeLookup(
|
auto lookup = l !is null ? l : TypeLookupsAllocator.instance.make!TypeLookup(
|
||||||
TypeLookupKind.varOrFunType);
|
TypeLookupKind.varOrFunType);
|
||||||
auto t2 = type.type2;
|
auto t2 = type.type2;
|
||||||
if (t2.type !is null)
|
if (t2.typeofExpression !is null)
|
||||||
addTypeToLookups(lookups, t2.type, lookup);
|
populateInitializer(lookups, t2.typeofExpression, false, lookup);
|
||||||
else if (t2.superOrThis is tok!"this")
|
else if (t2.superOrThis is tok!"this")
|
||||||
lookup.breadcrumbs.insert(internString("this"));
|
lookup.breadcrumbs.insert(internString("this"));
|
||||||
else if (t2.superOrThis is tok!"super")
|
else if (t2.superOrThis is tok!"super")
|
||||||
lookup.breadcrumbs.insert(internString("super"));
|
lookup.breadcrumbs.insert(internString("super"));
|
||||||
|
|
||||||
|
if (t2.type !is null)
|
||||||
|
addTypeToLookups(lookups, t2.type, lookup);
|
||||||
else if (t2.builtinType !is tok!"")
|
else if (t2.builtinType !is tok!"")
|
||||||
lookup.breadcrumbs.insert(getBuiltinTypeName(t2.builtinType));
|
lookup.breadcrumbs.insert(getBuiltinTypeName(t2.builtinType));
|
||||||
else if (t2.typeIdentifierPart !is null)
|
else if (t2.typeIdentifierPart !is null)
|
||||||
writeIotcTo(t2.typeIdentifierPart, lookup.breadcrumbs);
|
writeIotcTo(t2.typeIdentifierPart, lookup.breadcrumbs);
|
||||||
else
|
// TODO: support __vector, traits and mixin
|
||||||
{
|
|
||||||
// TODO: Add support for typeof expressions
|
|
||||||
// TODO: Add support for __vector
|
|
||||||
// warning("typeof() and __vector are not yet supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (suffix; type.typeSuffixes)
|
foreach (suffix; type.typeSuffixes)
|
||||||
{
|
{
|
||||||
|
|
|
@ -237,10 +237,27 @@ do
|
||||||
}
|
}
|
||||||
|
|
||||||
// Follow all the names and try to resolve them
|
// Follow all the names and try to resolve them
|
||||||
size_t i = 0;
|
bool first = true;
|
||||||
foreach (part; lookup.breadcrumbs[])
|
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)
|
if (moduleScope is null)
|
||||||
getSymbolFromImports(imports, part);
|
getSymbolFromImports(imports, part);
|
||||||
|
@ -273,7 +290,6 @@ do
|
||||||
return;
|
return;
|
||||||
currentSymbol = currentSymbol.getFirstPartNamed(part);
|
currentSymbol = currentSymbol.getFirstPartNamed(part);
|
||||||
}
|
}
|
||||||
++i;
|
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -311,19 +327,32 @@ do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
private void resolveTypeFromInitializer(R)(DSymbol* symbol, TypeLookup* lookup,
|
||||||
Scope* moduleScope, ref ModuleCache cache)
|
Scope* moduleScope, ref ModuleCache cache,
|
||||||
|
ref R breadcrumbs, ref DSymbol* currentSymbol)
|
||||||
{
|
{
|
||||||
if (lookup.breadcrumbs.length == 0)
|
if (breadcrumbs.empty)
|
||||||
return;
|
return;
|
||||||
DSymbol* currentSymbol = null;
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
auto crumbs = lookup.breadcrumbs[];
|
bool first = true;
|
||||||
foreach (crumb; crumbs)
|
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(
|
currentSymbol = moduleScope.getFirstSymbolByNameAndCursor(
|
||||||
symbolNameToTypeName(crumb), symbol.location);
|
symbolNameToTypeName(crumb), symbol.location);
|
||||||
|
|
||||||
|
@ -348,20 +377,23 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
|| currentSymbol.qualifier == SymbolQualifier.pointer
|
|| currentSymbol.qualifier == SymbolQualifier.pointer
|
||||||
|| currentSymbol.kind == CompletionKind.aliasName)
|
|| currentSymbol.kind == CompletionKind.aliasName)
|
||||||
{
|
{
|
||||||
if (currentSymbol.type !is null)
|
// may become null, returns later
|
||||||
currentSymbol = currentSymbol.type;
|
currentSymbol = currentSymbol.type;
|
||||||
else
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto opIndex = currentSymbol.getFirstPartNamed(internString("opIndex"));
|
auto opIndex = currentSymbol.getFirstPartNamed(internString("opIndex"));
|
||||||
if (opIndex !is null)
|
if (opIndex !is null)
|
||||||
|
{
|
||||||
currentSymbol = opIndex.type;
|
currentSymbol = opIndex.type;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
currentSymbol = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (crumb == "foreach")
|
else if (crumb == "foreach")
|
||||||
{
|
{
|
||||||
typeSwap(currentSymbol);
|
typeSwap(currentSymbol);
|
||||||
|
@ -371,19 +403,19 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
|| currentSymbol.qualifier == SymbolQualifier.assocArray)
|
|| currentSymbol.qualifier == SymbolQualifier.assocArray)
|
||||||
{
|
{
|
||||||
currentSymbol = currentSymbol.type;
|
currentSymbol = currentSymbol.type;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
auto front = currentSymbol.getFirstPartNamed(internString("front"));
|
auto front = currentSymbol.getFirstPartNamed(internString("front"));
|
||||||
if (front !is null)
|
if (front !is null)
|
||||||
{
|
{
|
||||||
currentSymbol = front.type;
|
currentSymbol = front.type;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
auto opApply = currentSymbol.getFirstPartNamed(internString("opApply"));
|
auto opApply = currentSymbol.getFirstPartNamed(internString("opApply"));
|
||||||
if (opApply !is null)
|
if (opApply !is null)
|
||||||
{
|
{
|
||||||
currentSymbol = opApply.type;
|
currentSymbol = opApply.type;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -393,13 +425,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
|
||||||
return;
|
return;
|
||||||
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
|
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
|
||||||
}
|
}
|
||||||
++i;
|
|
||||||
if (currentSymbol is null)
|
if (currentSymbol is null)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
typeSwap(currentSymbol);
|
typeSwap(currentSymbol);
|
||||||
symbol.type = currentSymbol;
|
|
||||||
symbol.ownType = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -506,8 +535,6 @@ void resolveType(DSymbol* symbol, ref TypeLookups typeLookups,
|
||||||
foreach(lookup; typeLookups) {
|
foreach(lookup; typeLookups) {
|
||||||
if (lookup.kind == TypeLookupKind.varOrFunType)
|
if (lookup.kind == TypeLookupKind.varOrFunType)
|
||||||
resolveTypeFromType(symbol, lookup, moduleScope, cache, null);
|
resolveTypeFromType(symbol, lookup, moduleScope, cache, null);
|
||||||
else if (lookup.kind == TypeLookupKind.initializer)
|
|
||||||
resolveTypeFromInitializer(symbol, lookup, moduleScope, cache);
|
|
||||||
// issue 94
|
// issue 94
|
||||||
else if (lookup.kind == TypeLookupKind.inherit)
|
else if (lookup.kind == TypeLookupKind.inherit)
|
||||||
resolveInheritance(symbol, typeLookups, moduleScope, cache);
|
resolveInheritance(symbol, typeLookups, moduleScope, cache);
|
||||||
|
|
|
@ -64,8 +64,6 @@ void checkMissingTypes(SemanticSymbol* currentSymbol, Scope* moduleScope, ref Mo
|
||||||
auto lookup = currentSymbol.typeLookups.front;
|
auto lookup = currentSymbol.typeLookups.front;
|
||||||
if (lookup.kind == TypeLookupKind.varOrFunType)
|
if (lookup.kind == TypeLookupKind.varOrFunType)
|
||||||
resolveTypeFromType(currentSymbol.acSymbol, lookup, moduleScope, cache, null);
|
resolveTypeFromType(currentSymbol.acSymbol, lookup, moduleScope, cache, null);
|
||||||
else if (lookup.kind == TypeLookupKind.initializer)
|
|
||||||
resolveTypeFromInitializer(currentSymbol.acSymbol, lookup, moduleScope, cache);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -10,7 +10,6 @@ enum TypeLookupKind : ubyte
|
||||||
{
|
{
|
||||||
inherit,
|
inherit,
|
||||||
aliasThis,
|
aliasThis,
|
||||||
initializer,
|
|
||||||
mixinTemplate,
|
mixinTemplate,
|
||||||
varOrFunType,
|
varOrFunType,
|
||||||
selectiveImport,
|
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