From 6127511daf9fc1b69aef8c957d89fba2f1853358 Mon Sep 17 00:00:00 2001 From: Aki <75532970+AkiSakurai@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:03:50 +0800 Subject: [PATCH] evaluator: fix type name for non-placement template variablesFix type name for non-placement template variables Fix the result of the type name for non-placement variables with template types. We still need to evaluate the arguments of the template before setting the type name. For typeNameOf the type, we can skip creating the pattern as only the arguments matter. --- .../pl/core/ast/ast_node_type_application.cpp | 2 ++ .../pl/core/ast/ast_node_type_operator.cpp | 19 +++++++-------- .../pl/core/ast/ast_node_variable_decl.cpp | 7 +++--- lib/source/pl/core/parser.cpp | 2 +- .../test_patterns/test_pattern_typenameof.hpp | 23 +++++++++++++++++++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/source/pl/core/ast/ast_node_type_application.cpp b/lib/source/pl/core/ast/ast_node_type_application.cpp index a2215d30..b458f3ee 100644 --- a/lib/source/pl/core/ast/ast_node_type_application.cpp +++ b/lib/source/pl/core/ast/ast_node_type_application.cpp @@ -25,6 +25,8 @@ namespace pl::core::ast { } } else if (auto typeNode = dynamic_cast(templateArgument.get()); typeNode != nullptr) { templateTypeString += fmt::format("{}, ", typeNode->getTypeName()); + } else { + templateTypeString += ", "; } } diff --git a/lib/source/pl/core/ast/ast_node_type_operator.cpp b/lib/source/pl/core/ast/ast_node_type_operator.cpp index 036247d0..f00a6105 100644 --- a/lib/source/pl/core/ast/ast_node_type_operator.cpp +++ b/lib/source/pl/core/ast/ast_node_type_operator.cpp @@ -43,6 +43,14 @@ namespace pl::core::ast { }; std::vector> patterns; + if (this->getOperator() == Token::Operator::TypeNameOf) { + if (auto typeApp = dynamic_cast(this->m_expression.get()); typeApp != nullptr) { + auto evaluatedType = typeApp->evaluate(evaluator); + result = dynamic_cast(evaluatedType.get())->getTypeName(); + return std::unique_ptr(new ASTNodeLiteral(result)); + } + } + this->m_expression->createPatterns(evaluator, patterns); if (patterns.empty()) err::E0005.throwError("'auto' can only be used with parameters.", { }, this->getLocation()); @@ -56,16 +64,9 @@ namespace pl::core::ast { case Token::Operator::SizeOf: result = u128(pattern->getSize()); break; - case Token::Operator::TypeNameOf: { - if (auto typeApp = dynamic_cast(this->m_expression.get()); typeApp != nullptr) { - auto evaluatedType = typeApp->evaluate(evaluator); - result = dynamic_cast(evaluatedType.get())->getTypeName(); - } else { - result = pattern->getTypeName(); - } - + case Token::Operator::TypeNameOf: + result = pattern->getTypeName(); break; - } default: err::E0001.throwError("Invalid type operation.", {}, this->getLocation()); } diff --git a/lib/source/pl/core/ast/ast_node_variable_decl.cpp b/lib/source/pl/core/ast/ast_node_variable_decl.cpp index 8e73416b..4fb3d2b4 100644 --- a/lib/source/pl/core/ast/ast_node_variable_decl.cpp +++ b/lib/source/pl/core/ast/ast_node_variable_decl.cpp @@ -128,13 +128,14 @@ namespace pl::core::ast { auto startOffset = evaluator->getBitwiseReadOffset(); - evaluator->createVariable(this->getName(), this->getType().get(), { }, this->m_outVariable, false, false, this->m_constant); + auto evaluatedType = std::unique_ptr(dynamic_cast(this->getType()->evaluate(evaluator).release())); + evaluator->createVariable(this->getName(), evaluatedType.get(), { }, this->m_outVariable, false, false, this->m_constant); auto &variable = evaluator->getScope(0).scope->back(); std::vector> initValues; if (this->m_placementOffset == nullptr) { evaluator->pushSectionId(ptrn::Pattern::InstantiationSectionId); - this->getType()->createPatterns(evaluator, initValues); + evaluatedType->createPatterns(evaluator, initValues); evaluator->popSectionId(); } else { evaluator->pushSectionId(this->m_placementSection == nullptr ? ptrn::Pattern::MainSectionId : evaluator->getSectionId()); @@ -143,7 +144,7 @@ namespace pl::core::ast { ON_SCOPE_EXIT { evaluator->setBitwiseReadOffset(currOffset); }; evaluator->setReadOffset(u64(this->evaluatePlacementOffset(evaluator))); - this->getType()->createPatterns(evaluator, initValues); + evaluatedType->createPatterns(evaluator, initValues); evaluator->popSectionId(); } diff --git a/lib/source/pl/core/parser.cpp b/lib/source/pl/core/parser.cpp index 41482d08..54c0a40f 100644 --- a/lib/source/pl/core/parser.cpp +++ b/lib/source/pl/core/parser.cpp @@ -1310,7 +1310,7 @@ namespace pl::core { size_t index = 0; for (const auto &templateParameter : this->m_currTemplateType.front()->getTemplateParameters()) { if (const auto templateType = dynamic_cast(templateParameter.get()); templateType != nullptr){ - if (templateType->getName().get() == baseTypeName) { + if (templateType->getName().get() == baseTypeName && templateType->isType()) { auto type = create(nullptr); type->setTemplateParameterIndex(index); return type; diff --git a/tests/include/test_patterns/test_pattern_typenameof.hpp b/tests/include/test_patterns/test_pattern_typenameof.hpp index 51f9d6b6..1fa4291e 100644 --- a/tests/include/test_patterns/test_pattern_typenameof.hpp +++ b/tests/include/test_patterns/test_pattern_typenameof.hpp @@ -25,12 +25,35 @@ namespace pl::test { }; u32 P = 16; + A q @ 0; + B r; TypeName a @ 0; TypeName b @ 0; TypeName, "B"> c @ 0; TypeName, 2>, "B, 2>"> d @ 0; TypeName , "TypeName"> e @ 0; + TypeName, "B"> f @ 0; std::assert(typenameof(B, 2>) == "B, 2>", "type name should match"); + std::assert(typenameof(B) == "B", "type name should match"); + + B t; + std::assert(typenameof(t) == "B", "type name should match"); + + struct S { + u32 e = 16; + B a = t; + str typename = typenameof(a); + }; + + S s @ 0; + std::assert(s.typename == "B", "type name should match"); + + struct U { + u8 size; + u32 value[size]; + }; + + std::assert(typenameof(U) == "U", "type name should match"); )"; } };