Skip to content

Commit

Permalink
evaluator: Cache enum values when the enum is defined
Browse files Browse the repository at this point in the history
  • Loading branch information
WerWolv committed Jul 11, 2024
1 parent c20dac9 commit bca031c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 18 deletions.
3 changes: 3 additions & 0 deletions lib/include/pl/core/ast/ast_node_enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ namespace pl::core::ast {
}

[[nodiscard]] std::vector<std::shared_ptr<ptrn::Pattern>> createPatterns(Evaluator *evaluator) const override;
std::unique_ptr<ASTNode> evaluate(Evaluator *evaluator) const override;

[[nodiscard]] const std::map<std::string, std::pair<std::unique_ptr<ASTNode>, std::unique_ptr<ASTNode>>> &getEntries() const { return this->m_entries; }
[[nodiscard]] const std::vector<ptrn::PatternEnum::EnumValue>& getEnumValues(Evaluator *evaluator) const;
void addEntry(const std::string &name, std::unique_ptr<ASTNode> &&minExpr, std::unique_ptr<ASTNode> &&maxExpr) {
this->m_entries[name] = { std::move(minExpr), std::move(maxExpr) };
this->m_cachedEnumValues.clear();
}

[[nodiscard]] const std::unique_ptr<ASTNode> &getUnderlyingType() { return this->m_underlyingType; }
Expand Down
42 changes: 27 additions & 15 deletions lib/source/pl/core/ast/ast_node_enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,7 @@ namespace pl::core::ast {
this->m_cachedEnumValues = other.m_cachedEnumValues;
}

[[nodiscard]] std::vector<std::shared_ptr<ptrn::Pattern>> 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<ptrn::PatternEnum>(evaluator, underlying->getOffset(), 0, getLocation().line);

pattern->setSection(evaluator->getSectionId());

const std::vector<ptrn::PatternEnum::EnumValue>& ASTNodeEnum::getEnumValues(Evaluator *evaluator) const {
if (m_cachedEnumValues.empty()) {
for (const auto &[name, expr] : this->m_entries) {
auto &[min, max] = expr;
Expand All @@ -60,7 +47,25 @@ namespace pl::core::ast {
}
}

pattern->setEnumValues(m_cachedEnumValues);
return m_cachedEnumValues;
}


[[nodiscard]] std::vector<std::shared_ptr<ptrn::Pattern>> 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<ptrn::PatternEnum>(evaluator, underlying->getOffset(), 0, getLocation().line);

pattern->setSection(evaluator->getSectionId());

pattern->setEnumValues(getEnumValues(evaluator));

pattern->setSize(underlying->getSize());
pattern->setEndian(underlying->getEndian());
Expand All @@ -70,4 +75,11 @@ namespace pl::core::ast {
return hlp::moveToVector<std::shared_ptr<ptrn::Pattern>>(std::move(pattern));
}

std::unique_ptr<ASTNode> ASTNodeEnum::evaluate(Evaluator *evaluator) const {
wolv::util::unused(this->getEnumValues(evaluator));

return this->clone();
}


}
7 changes: 4 additions & 3 deletions lib/source/pl/core/ast/ast_node_scope_resolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <pl/patterns/pattern.hpp>

#include <pl/core/ast/ast_node_enum.hpp>
#include <pl/core/ast/ast_node_literal.hpp>

namespace pl::core::ast {

Expand All @@ -22,9 +23,9 @@ namespace pl::core::ast {
auto type = this->m_type->evaluate(evaluator);

if (auto enumType = dynamic_cast<ASTNodeEnum *>(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<ASTNodeLiteral>(min);
}
} else {
err::E0004.throwError("Invalid scope resolution. This cannot be accessed using the scope resolution operator.", {}, this->getLocation());
Expand All @@ -33,4 +34,4 @@ namespace pl::core::ast {
err::E0004.throwError(fmt::format("Cannot find constant '{}' in this type.", this->m_name), {}, this->getLocation());
}

}
}

0 comments on commit bca031c

Please sign in to comment.