diff --git a/lib/libimhex/include/hex/pattern_language/ast_node.hpp b/lib/libimhex/include/hex/pattern_language/ast_node.hpp index b84dc62ac..9a9598f17 100644 --- a/lib/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/lib/libimhex/include/hex/pattern_language/ast_node.hpp @@ -127,6 +127,132 @@ namespace hex::pl { std::vector m_attributes; }; + + inline void applyTypeAttributes(Evaluator *evaluator, const ASTNode *node, PatternData *pattern) { + auto attributable = dynamic_cast(node); + if (attributable == nullptr) + LogConsole::abortEvaluation("attribute cannot be applied here", node); + + if (attributable->hasAttribute("inline", false)) { + auto inlinable = dynamic_cast(pattern); + + if (inlinable == nullptr) + LogConsole::abortEvaluation("inline attribute can only be applied to nested types", node); + else + inlinable->setInlined(true); + } + + if (auto value = attributable->getAttributeValue("format"); value) { + auto functions = evaluator->getCustomFunctions(); + if (!functions.contains(*value)) + LogConsole::abortEvaluation(hex::format("cannot find formatter function '{}'", *value), node); + + const auto &function = functions[*value]; + if (function.parameterCount != 1) + LogConsole::abortEvaluation("formatter function needs exactly one parameter", node); + + pattern->setFormatterFunction(function); + } + + if (auto value = attributable->getAttributeValue("format_entries"); value) { + auto functions = evaluator->getCustomFunctions(); + if (!functions.contains(*value)) + LogConsole::abortEvaluation(hex::format("cannot find formatter function '{}'", *value), node); + + const auto &function = functions[*value]; + if (function.parameterCount != 1) + LogConsole::abortEvaluation("formatter function needs exactly one parameter", node); + + auto array = dynamic_cast(pattern); + if (array == nullptr) + LogConsole::abortEvaluation("inline_array attribute can only be applied to array types", node); + + for (const auto &entry : array->getEntries()) { + entry->setFormatterFunction(function); + } + } + + if (auto value = attributable->getAttributeValue("transform"); value) { + auto functions = evaluator->getCustomFunctions(); + if (!functions.contains(*value)) + LogConsole::abortEvaluation(hex::format("cannot find transform function '{}'", *value), node); + + const auto &function = functions[*value]; + if (function.parameterCount != 1) + LogConsole::abortEvaluation("transform function needs exactly one parameter", node); + + pattern->setTransformFunction(function); + } + + if (auto value = attributable->getAttributeValue("pointer_base"); value) { + auto functions = evaluator->getCustomFunctions(); + if (!functions.contains(*value)) + LogConsole::abortEvaluation(hex::format("cannot find pointer base function '{}'", *value), node); + + const auto &function = functions[*value]; + if (function.parameterCount != 1) + LogConsole::abortEvaluation("pointer base function needs exactly one parameter", node); + + if (auto pointerPattern = dynamic_cast(pattern)) { + u128 pointerValue = pointerPattern->getPointedAtAddress(); + + auto result = function.func(evaluator, { pointerValue }); + + if (!result.has_value()) + LogConsole::abortEvaluation("pointer base function did not return a value", node); + + pointerPattern->setPointedAtAddress(Token::literalToUnsigned(result.value()) + pointerValue); + } else { + LogConsole::abortEvaluation("pointer_base attribute may only be applied to a pointer"); + } + } + + if (attributable->hasAttribute("hidden", false)) { + pattern->setHidden(true); + } + + if (!pattern->hasOverriddenColor()) { + if (auto value = attributable->getAttributeValue("color"); value) { + u32 color = strtoul(value->c_str(), nullptr, 16); + pattern->setColor(hex::changeEndianess(color, std::endian::big) >> 8); + } else if (auto value = attributable->hasAttribute("single_color", false); value) { + pattern->setColor(ContentRegistry::PatternLanguage::getNextColor()); + } + } + } + + inline void applyVariableAttributes(Evaluator *evaluator, const ASTNode *node, PatternData *pattern) { + auto attributable = dynamic_cast(node); + if (attributable == nullptr) + LogConsole::abortEvaluation("attribute cannot be applied here", node); + + auto endOffset = evaluator->dataOffset(); + evaluator->dataOffset() = pattern->getOffset(); + ON_SCOPE_EXIT { evaluator->dataOffset() = endOffset; }; + + applyTypeAttributes(evaluator, node, pattern); + + if (auto value = attributable->getAttributeValue("color"); value) { + u32 color = strtoul(value->c_str(), nullptr, 16); + pattern->setColor(hex::changeEndianess(color, std::endian::big) >> 8); + } else if (auto value = attributable->hasAttribute("single_color", false); value) { + pattern->setColor(ContentRegistry::PatternLanguage::getNextColor()); + } + + if (auto value = attributable->getAttributeValue("name"); value) { + pattern->setDisplayName(*value); + } + + if (auto value = attributable->getAttributeValue("comment"); value) { + pattern->setComment(*value); + } + + if (attributable->hasAttribute("no_unique_address", false)) { + endOffset -= pattern->getSize(); + } + } + + class ASTNodeLiteral : public ASTNode { public: explicit ASTNodeLiteral(Token::Literal literal) : ASTNode(), m_literal(std::move(literal)) { } @@ -503,6 +629,8 @@ namespace hex::pl { if (this->m_endian.has_value()) pattern->setEndian(this->m_endian.value()); + + applyTypeAttributes(evaluator, this, pattern); } return patterns; @@ -720,113 +848,6 @@ namespace hex::pl { ASTNode *m_postExpression; }; - inline void applyVariableAttributes(Evaluator *evaluator, const ASTNode *node, PatternData *pattern) { - auto attributable = dynamic_cast(node); - if (attributable == nullptr) - LogConsole::abortEvaluation("attribute cannot be applied here", node); - - auto endOffset = evaluator->dataOffset(); - evaluator->dataOffset() = pattern->getOffset(); - ON_SCOPE_EXIT { evaluator->dataOffset() = endOffset; }; - - if (auto value = attributable->getAttributeValue("color"); value) { - u32 color = strtoul(value->c_str(), nullptr, 16); - pattern->setColor(hex::changeEndianess(color, std::endian::big) >> 8); - } else if (auto value = attributable->hasAttribute("single_color", false); value) { - pattern->setColor(ContentRegistry::PatternLanguage::getNextColor()); - } - - if (auto value = attributable->getAttributeValue("name"); value) { - pattern->setDisplayName(*value); - } - - if (auto value = attributable->getAttributeValue("comment"); value) { - pattern->setComment(*value); - } - - if (auto value = attributable->getAttributeValue("format"); value) { - auto functions = evaluator->getCustomFunctions(); - if (!functions.contains(*value)) - LogConsole::abortEvaluation(hex::format("cannot find formatter function '{}'", *value), node); - - const auto &function = functions[*value]; - if (function.parameterCount != 1) - LogConsole::abortEvaluation("formatter function needs exactly one parameter", node); - - pattern->setFormatterFunction(function); - } - - if (auto value = attributable->getAttributeValue("transform"); value) { - auto functions = evaluator->getCustomFunctions(); - if (!functions.contains(*value)) - LogConsole::abortEvaluation(hex::format("cannot find transform function '{}'", *value), node); - - const auto &function = functions[*value]; - if (function.parameterCount != 1) - LogConsole::abortEvaluation("transform function needs exactly one parameter", node); - - pattern->setTransformFunction(function); - } - - if (auto value = attributable->getAttributeValue("pointer_base"); value) { - auto functions = evaluator->getCustomFunctions(); - if (!functions.contains(*value)) - LogConsole::abortEvaluation(hex::format("cannot find pointer base function '{}'", *value), node); - - const auto &function = functions[*value]; - if (function.parameterCount != 1) - LogConsole::abortEvaluation("pointer base function needs exactly one parameter", node); - - if (auto pointerPattern = dynamic_cast(pattern)) { - u128 pointerValue = pointerPattern->getPointedAtAddress(); - - auto result = function.func(evaluator, { pointerValue }); - - if (!result.has_value()) - LogConsole::abortEvaluation("pointer base function did not return a value", node); - - pointerPattern->setPointedAtAddress(Token::literalToUnsigned(result.value()) + pointerValue); - } else { - LogConsole::abortEvaluation("pointer_base attribute may only be applied to a pointer"); - } - } - - if (attributable->hasAttribute("hidden", false)) { - pattern->setHidden(true); - } - - if (attributable->hasAttribute("no_unique_address", false)) { - endOffset -= pattern->getSize(); - } - - if (attributable->hasAttribute("inline", false)) { - auto inlinable = dynamic_cast(pattern); - - if (inlinable == nullptr) - LogConsole::abortEvaluation("inline attribute can only be applied to nested types", node); - else - inlinable->setInlined(true); - } - - if (auto value = attributable->getAttributeValue("format_entries"); value) { - auto functions = evaluator->getCustomFunctions(); - if (!functions.contains(*value)) - LogConsole::abortEvaluation(hex::format("cannot find formatter function '{}'", *value), node); - - const auto &function = functions[*value]; - if (function.parameterCount != 1) - LogConsole::abortEvaluation("formatter function needs exactly one parameter", node); - - auto array = dynamic_cast(pattern); - if (array == nullptr) - LogConsole::abortEvaluation("inline_array attribute can only be applied to array types", node); - - for (const auto &entry : array->getEntries()) { - entry->setFormatterFunction(function); - } - } - } - class ASTNodeVariableDecl : public ASTNode, public Attributable { public: @@ -1409,14 +1430,7 @@ namespace hex::pl { structCleanup.release(); - if (!pattern->hasOverriddenColor()) { - if (auto value = getAttributeValue("color"); value) { - u32 color = strtoul(value->c_str(), nullptr, 16); - pattern->setColor(hex::changeEndianess(color, std::endian::big) >> 8); - } else if (auto value = hasAttribute("single_color", false); value) { - pattern->setColor(ContentRegistry::PatternLanguage::getNextColor()); - } - } + applyTypeAttributes(evaluator, this, pattern); return { pattern }; } @@ -1481,6 +1495,8 @@ namespace hex::pl { pattern->setMembers(memberPatterns); pattern->setSize(size); + applyTypeAttributes(evaluator, this, pattern); + unionCleanup.release(); return { pattern }; @@ -1534,6 +1550,8 @@ namespace hex::pl { pattern->setSize(underlying->getSize()); pattern->setEndian(underlying->getEndian()); + applyTypeAttributes(evaluator, this, pattern); + enumCleanup.release(); return { pattern }; @@ -1624,6 +1642,8 @@ namespace hex::pl { evaluator->dataOffset() += pattern->getSize(); + applyTypeAttributes(evaluator, this, pattern); + bitfieldCleanup.release(); return { pattern };