From 35ab44f83d4b07b3f4e098bd5b4be7c8d8c4007b Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sat, 24 Jun 2023 20:58:54 +0200 Subject: [PATCH] implement typeof in types --- dsymbol/src/dsymbol/builtin/names.d | 14 +++++ dsymbol/src/dsymbol/conversion/first.d | 37 ++++++------ dsymbol/src/dsymbol/conversion/second.d | 75 +++++++++++++++++-------- dsymbol/src/dsymbol/conversion/third.d | 2 - dsymbol/src/dsymbol/type_lookup.d | 1 - tests/tc_typeof/expected1.txt | 20 +++++++ tests/tc_typeof/expected2.txt | 2 + tests/tc_typeof/expected3.txt | 8 +++ tests/tc_typeof/run.sh | 14 +++++ tests/tc_typeof/test1.d | 32 +++++++++++ tests/tc_typeof/test2.d | 15 +++++ tests/tc_typeof/test3.d | 10 ++++ 12 files changed, 187 insertions(+), 43 deletions(-) create mode 100644 tests/tc_typeof/expected1.txt create mode 100644 tests/tc_typeof/expected2.txt create mode 100644 tests/tc_typeof/expected3.txt create mode 100755 tests/tc_typeof/run.sh create mode 100644 tests/tc_typeof/test1.d create mode 100644 tests/tc_typeof/test2.d create mode 100644 tests/tc_typeof/test3.d diff --git a/dsymbol/src/dsymbol/builtin/names.d b/dsymbol/src/dsymbol/builtin/names.d index b91739f..9b87334 100644 --- a/dsymbol/src/dsymbol/builtin/names.d +++ b/dsymbol/src/dsymbol/builtin/names.d @@ -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 diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index c9ac1b6..7f391c6 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -270,7 +270,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); @@ -718,7 +718,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); } } @@ -737,7 +737,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); } @@ -755,7 +755,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); } @@ -1121,12 +1121,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 @@ -1149,22 +1156,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) { diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index a7b3580..d1220b0 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -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); diff --git a/dsymbol/src/dsymbol/conversion/third.d b/dsymbol/src/dsymbol/conversion/third.d index 1148dac..29aa91c 100644 --- a/dsymbol/src/dsymbol/conversion/third.d +++ b/dsymbol/src/dsymbol/conversion/third.d @@ -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: diff --git a/dsymbol/src/dsymbol/type_lookup.d b/dsymbol/src/dsymbol/type_lookup.d index 2260e57..8f69ceb 100644 --- a/dsymbol/src/dsymbol/type_lookup.d +++ b/dsymbol/src/dsymbol/type_lookup.d @@ -10,7 +10,6 @@ enum TypeLookupKind : ubyte { inherit, aliasThis, - initializer, mixinTemplate, varOrFunType, selectiveImport, diff --git a/tests/tc_typeof/expected1.txt b/tests/tc_typeof/expected1.txt new file mode 100644 index 0000000..3301724 --- /dev/null +++ b/tests/tc_typeof/expected1.txt @@ -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 diff --git a/tests/tc_typeof/expected2.txt b/tests/tc_typeof/expected2.txt new file mode 100644 index 0000000..293e517 --- /dev/null +++ b/tests/tc_typeof/expected2.txt @@ -0,0 +1,2 @@ +identifiers +test v Enum test stdin 121 Enum diff --git a/tests/tc_typeof/expected3.txt b/tests/tc_typeof/expected3.txt new file mode 100644 index 0000000..bcfd9d8 --- /dev/null +++ b/tests/tc_typeof/expected3.txt @@ -0,0 +1,8 @@ +identifiers +alignof k +init k +mangleof k +ok v bool ok stdin 16 bool +sizeof k +stringof k +tupleof k diff --git a/tests/tc_typeof/run.sh b/tests/tc_typeof/run.sh new file mode 100755 index 0000000..3fd2acd --- /dev/null +++ b/tests/tc_typeof/run.sh @@ -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 diff --git a/tests/tc_typeof/test1.d b/tests/tc_typeof/test1.d new file mode 100644 index 0000000..7fe98a0 --- /dev/null +++ b/tests/tc_typeof/test1.d @@ -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. + } +} diff --git a/tests/tc_typeof/test2.d b/tests/tc_typeof/test2.d new file mode 100644 index 0000000..9bc2f15 --- /dev/null +++ b/tests/tc_typeof/test2.d @@ -0,0 +1,15 @@ +struct MyTemplate(T) +{ + enum Enum { a, b } + + T member1; +} + +MyTemplate!long global2; + +void main() +{ + typeof(global2).Enum test; + test +} + diff --git a/tests/tc_typeof/test3.d b/tests/tc_typeof/test3.d new file mode 100644 index 0000000..9b85483 --- /dev/null +++ b/tests/tc_typeof/test3.d @@ -0,0 +1,10 @@ +struct S { bool ok; } + +S global3; + +void main() +{ + typeof(global3)[] test; + test[0]. +} +