From bca031c749992c9e1a236c3a6a254df49790536d Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 11 Jul 2024 18:02:34 +0200 Subject: [PATCH] evaluator: Cache enum values when the enum is defined --- lib/include/pl/core/ast/ast_node_enum.hpp | 3 ++ lib/source/pl/core/ast/ast_node_enum.cpp | 42 ++++++++++++------- .../pl/core/ast/ast_node_scope_resolution.cpp | 7 ++-- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/lib/include/pl/core/ast/ast_node_enum.hpp b/lib/include/pl/core/ast/ast_node_enum.hpp index fa515cc2..8167684c 100644 --- a/lib/include/pl/core/ast/ast_node_enum.hpp +++ b/lib/include/pl/core/ast/ast_node_enum.hpp @@ -20,10 +20,13 @@ namespace pl::core::ast { } [[nodiscard]] std::vector> createPatterns(Evaluator *evaluator) const override; + std::unique_ptr evaluate(Evaluator *evaluator) const override; [[nodiscard]] const std::map, std::unique_ptr>> &getEntries() const { return this->m_entries; } + [[nodiscard]] const std::vector& getEnumValues(Evaluator *evaluator) const; void addEntry(const std::string &name, std::unique_ptr &&minExpr, std::unique_ptr &&maxExpr) { this->m_entries[name] = { std::move(minExpr), std::move(maxExpr) }; + this->m_cachedEnumValues.clear(); } [[nodiscard]] const std::unique_ptr &getUnderlyingType() { return this->m_underlyingType; } diff --git a/lib/source/pl/core/ast/ast_node_enum.cpp b/lib/source/pl/core/ast/ast_node_enum.cpp index ce081e2a..c2749008 100644 --- a/lib/source/pl/core/ast/ast_node_enum.cpp +++ b/lib/source/pl/core/ast/ast_node_enum.cpp @@ -21,20 +21,7 @@ namespace pl::core::ast { this->m_cachedEnumValues = other.m_cachedEnumValues; } - [[nodiscard]] std::vector> ASTNodeEnum::createPatterns(Evaluator *evaluator) const { - [[maybe_unused]] auto context = evaluator->updateRuntime(this); - - evaluator->alignToByte(); - - const auto nodes = this->m_underlyingType->createPatterns(evaluator); - if (nodes.empty()) - err::E0005.throwError("'auto' can only be used with parameters.", { }, this->getLocation()); - auto &underlying = nodes.front(); - - auto pattern = std::make_shared(evaluator, underlying->getOffset(), 0, getLocation().line); - - pattern->setSection(evaluator->getSectionId()); - + const std::vector& ASTNodeEnum::getEnumValues(Evaluator *evaluator) const { if (m_cachedEnumValues.empty()) { for (const auto &[name, expr] : this->m_entries) { auto &[min, max] = expr; @@ -60,7 +47,25 @@ namespace pl::core::ast { } } - pattern->setEnumValues(m_cachedEnumValues); + return m_cachedEnumValues; + } + + + [[nodiscard]] std::vector> ASTNodeEnum::createPatterns(Evaluator *evaluator) const { + [[maybe_unused]] auto context = evaluator->updateRuntime(this); + + evaluator->alignToByte(); + + const auto nodes = this->m_underlyingType->createPatterns(evaluator); + if (nodes.empty()) + err::E0005.throwError("'auto' can only be used with parameters.", { }, this->getLocation()); + auto &underlying = nodes.front(); + + auto pattern = std::make_shared(evaluator, underlying->getOffset(), 0, getLocation().line); + + pattern->setSection(evaluator->getSectionId()); + + pattern->setEnumValues(getEnumValues(evaluator)); pattern->setSize(underlying->getSize()); pattern->setEndian(underlying->getEndian()); @@ -70,4 +75,11 @@ namespace pl::core::ast { return hlp::moveToVector>(std::move(pattern)); } + std::unique_ptr ASTNodeEnum::evaluate(Evaluator *evaluator) const { + wolv::util::unused(this->getEnumValues(evaluator)); + + return this->clone(); + } + + } \ No newline at end of file diff --git a/lib/source/pl/core/ast/ast_node_scope_resolution.cpp b/lib/source/pl/core/ast/ast_node_scope_resolution.cpp index 6af77689..9fb72db1 100644 --- a/lib/source/pl/core/ast/ast_node_scope_resolution.cpp +++ b/lib/source/pl/core/ast/ast_node_scope_resolution.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace pl::core::ast { @@ -22,9 +23,9 @@ namespace pl::core::ast { auto type = this->m_type->evaluate(evaluator); if (auto enumType = dynamic_cast(type.get())) { - for (auto &[name, values] : enumType->getEntries()) { + for (auto &[min, max, name] : enumType->getEnumValues(evaluator)) { if (name == this->m_name) - return values.first->evaluate(evaluator); + return std::make_unique(min); } } else { err::E0004.throwError("Invalid scope resolution. This cannot be accessed using the scope resolution operator.", {}, this->getLocation()); @@ -33,4 +34,4 @@ namespace pl::core::ast { err::E0004.throwError(fmt::format("Cannot find constant '{}' in this type.", this->m_name), {}, this->getLocation()); } -} \ No newline at end of file +}