Skip to content

Commit

Permalink
parser/evaluator: Don't re-evaluate enum values at every use
Browse files Browse the repository at this point in the history
Fixes #88
  • Loading branch information
WerWolv committed Jul 11, 2024
1 parent 8909b96 commit c20dac9
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 21 deletions.
4 changes: 4 additions & 0 deletions lib/include/pl/core/ast/ast_node_enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <pl/core/ast/ast_node.hpp>
#include <pl/core/ast/ast_node_attribute.hpp>

#include <pl/patterns/pattern_enum.hpp>

#include <map>

namespace pl::core::ast {
Expand All @@ -29,6 +31,8 @@ namespace pl::core::ast {
private:
std::map<std::string, std::pair<std::unique_ptr<ASTNode>, std::unique_ptr<ASTNode>>> m_entries;
std::unique_ptr<ASTNode> m_underlyingType;

mutable std::vector<ptrn::PatternEnum::EnumValue> m_cachedEnumValues;
};

}
42 changes: 23 additions & 19 deletions lib/source/pl/core/ast/ast_node_enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ namespace pl::core::ast {

ASTNodeEnum::ASTNodeEnum(const ASTNodeEnum &other) : ASTNode(other), Attributable(other) {
for (const auto &[name, expr] : other.getEntries()) {
this->m_entries[name] = { expr.first->clone(), expr.second->clone() };
auto &[min, max] = expr;
this->m_entries[name] = { min->clone(), max == nullptr ? nullptr : max->clone() };
}
this->m_underlyingType = other.m_underlyingType->clone();

this->m_cachedEnumValues = other.m_cachedEnumValues;
}

[[nodiscard]] std::vector<std::shared_ptr<ptrn::Pattern>> ASTNodeEnum::createPatterns(Evaluator *evaluator) const {
Expand All @@ -32,31 +35,32 @@ namespace pl::core::ast {

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

std::vector<ptrn::PatternEnum::EnumValue> enumEntries;
for (const auto &[name, expr] : this->m_entries) {
auto &[min, max] = expr;
if (m_cachedEnumValues.empty()) {
for (const auto &[name, expr] : this->m_entries) {
auto &[min, max] = expr;

const auto minNode = min->evaluate(evaluator);
const auto maxNode = max->evaluate(evaluator);
const auto minNode = min->evaluate(evaluator);
const auto maxNode = max == nullptr ? minNode->clone() : max->evaluate(evaluator);

const auto minLiteral = dynamic_cast<ASTNodeLiteral *>(minNode.get());
const auto maxLiteral = dynamic_cast<ASTNodeLiteral *>(maxNode.get());
const auto minLiteral = dynamic_cast<ASTNodeLiteral *>(minNode.get());
const auto maxLiteral = dynamic_cast<ASTNodeLiteral *>(maxNode.get());

if (minLiteral == nullptr || maxLiteral == nullptr)
err::E0010.throwError("Cannot use void expression as enum value.", {}, this->getLocation());
if (minLiteral == nullptr || maxLiteral == nullptr)
err::E0010.throwError("Cannot use void expression as enum value.", {}, this->getLocation());

// Check that the enum values can be converted to integers
(void)minLiteral->getValue().toUnsigned();
(void)maxLiteral->getValue().toUnsigned();
// Check that the enum values can be converted to integers
(void)minLiteral->getValue().toUnsigned();
(void)maxLiteral->getValue().toUnsigned();

enumEntries.push_back(ptrn::PatternEnum::EnumValue{
minLiteral->getValue(),
maxLiteral->getValue(),
name
});
m_cachedEnumValues.push_back(ptrn::PatternEnum::EnumValue{
minLiteral->getValue(),
maxLiteral->getValue(),
name
});
}
}

pattern->setEnumValues(enumEntries);
pattern->setEnumValues(m_cachedEnumValues);

pattern->setSize(underlying->getSize());
pattern->setEndian(underlying->getEndian());
Expand Down
3 changes: 1 addition & 2 deletions lib/source/pl/core/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1992,8 +1992,7 @@ namespace pl::core {

enumNode->addEntry(name, std::move(enumValue), std::move(endExpr));
} else {
auto clonedExpr = enumValue->clone();
enumNode->addEntry(name, std::move(enumValue), std::move(clonedExpr));
enumNode->addEntry(name, std::move(enumValue), nullptr);
}

if (!sequence(tkn::Separator::Comma)) {
Expand Down

0 comments on commit c20dac9

Please sign in to comment.