diff --git a/include/lang/evaluator.hpp b/include/lang/evaluator.hpp index 441e46c79..a79190266 100644 --- a/include/lang/evaluator.hpp +++ b/include/lang/evaluator.hpp @@ -37,7 +37,7 @@ namespace hex::lang { prv::Provider* &m_provider; std::endian m_defaultDataEndian; u64 m_currOffset = 0; - std::optional m_currEndian; + std::vector m_endianStack; std::vector*> m_currMembers; std::map m_functions; @@ -50,7 +50,7 @@ namespace hex::lang { } [[nodiscard]] std::endian getCurrentEndian() const { - return this->m_currEndian.value_or(this->m_defaultDataEndian); + return this->m_endianStack.back(); } void addFunction(std::string_view name, u32 parameterCount, std::function)> func) { diff --git a/source/lang/evaluator.cpp b/source/lang/evaluator.cpp index 0a7e4412e..a7c1c09e1 100644 --- a/source/lang/evaluator.cpp +++ b/source/lang/evaluator.cpp @@ -314,13 +314,12 @@ namespace hex::lang { this->m_currOffset += typeSize; pattern->setTypeName(Token::getTypeName(type)); + pattern->setEndian(this->getCurrentEndian()); return pattern; } std::vector Evaluator::evaluateMember(ASTNode *node) { - this->m_currEndian.reset(); - if (auto memberVariableNode = dynamic_cast(node); memberVariableNode != nullptr) return { this->evaluateVariable(memberVariableNode) }; else if (auto memberArrayNode = dynamic_cast(node); memberArrayNode != nullptr) @@ -440,8 +439,7 @@ namespace hex::lang { PatternData* Evaluator::evaluateType(ASTNodeTypeDecl *node) { auto type = node->getType(); - if (!this->m_currEndian.has_value()) - this->m_currEndian = node->getEndian(); + this->m_endianStack.push_back(node->getEndian().value_or(this->m_defaultDataEndian)); PatternData *pattern; @@ -463,6 +461,8 @@ namespace hex::lang { if (!node->getName().empty()) pattern->setTypeName(node->getName().data()); + this->m_endianStack.pop_back(); + return pattern; } @@ -491,7 +491,6 @@ namespace hex::lang { pattern->setVariableName(node->getName().data()); pattern->setEndian(this->getCurrentEndian()); - this->m_currEndian.reset(); return pattern; } @@ -572,8 +571,6 @@ namespace hex::lang { throwEvaluateError("array exceeds size of file", node->getLineNumber()); } - this->m_currEndian.reset(); - PatternData *pattern; if (entries.empty()) { pattern = new PatternDataPadding(startOffset, 0); @@ -619,11 +616,27 @@ namespace hex::lang { u128 pointedAtOffset = 0; this->m_provider->read(pointerOffset, &pointedAtOffset, pointerSize); - this->m_currOffset = pointedAtOffset; - auto pointedAt = evaluateType(dynamic_cast(node->getType())); + this->m_currOffset = hex::changeEndianess(pointedAtOffset, 1, this->getCurrentEndian()); + + if (this->m_currOffset > this->m_provider->getActualSize()) + throwEvaluateError("pointer points past the end of the data", 1); + + PatternData *pointedAt; + if (auto typeDecl = dynamic_cast(node->getType()); typeDecl != nullptr) + pointedAt = this->evaluateType(typeDecl); + else if (auto builtinTypeDecl = dynamic_cast(node->getType()); builtinTypeDecl != nullptr) + pointedAt = this->evaluateBuiltinType(builtinTypeDecl); + else + throwEvaluateError("ASTNodeVariableDecl had an invalid type. This is a bug!", 1); + this->m_currOffset = pointerOffset + pointerSize; - return new PatternDataPointer(pointerOffset, pointerSize, pointedAt); + auto pattern = new PatternDataPointer(pointerOffset, pointerSize, pointedAt); + + pattern->setVariableName(node->getName().data()); + pattern->setEndian(this->getCurrentEndian()); + + return pattern; } std::optional> Evaluator::evaluate(const std::vector &ast) { @@ -632,7 +645,7 @@ namespace hex::lang { try { for (const auto& node : ast) { - this->m_currEndian.reset(); + this->m_endianStack.push_back(this->m_defaultDataEndian); if (auto variableDeclNode = dynamic_cast(node); variableDeclNode != nullptr) { patterns.push_back(this->evaluateVariable(variableDeclNode)); @@ -644,12 +657,16 @@ namespace hex::lang { this->m_types[typeDeclNode->getName().data()] = typeDeclNode->getType(); } + this->m_endianStack.pop_back(); } } catch (EvaluateError &e) { this->m_error = e; + this->m_endianStack.clear(); + return { }; } + this->m_endianStack.clear(); return patterns; }