diff --git a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp index 29bc4d110..df6134548 100644 --- a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp @@ -324,6 +324,8 @@ namespace hex::pl { pattern = new PatternDataPadding(offset, 1); else if (this->m_type == Token::ValueType::String) pattern = new PatternDataString(offset, 1); + else if (this->m_type == Token::ValueType::Auto) + return { nullptr }; else LogConsole::abortEvaluation("invalid built-in type", this); @@ -371,6 +373,9 @@ namespace hex::pl { auto patterns = this->m_type->createPatterns(evaluator); for (auto &pattern : patterns) { + if (pattern == nullptr) + continue; + if (!this->m_name.empty()) pattern->setTypeName(this->m_name); pattern->setEndian(this->m_endian.value_or(evaluator->getDefaultEndian())); @@ -1799,7 +1804,7 @@ namespace hex::pl { u32 paramIndex = 0; for (const auto &[name, type] : this->m_params) { - ctx->createVariable(name, type); + ctx->createVariable(name, type, params[paramIndex]); ctx->setVariable(name, params[paramIndex]); paramIndex++; diff --git a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp index c8280ca0c..b7ab3ce21 100644 --- a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp +++ b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp @@ -105,7 +105,7 @@ namespace hex::pl { return this->m_stack; } - void createVariable(const std::string &name, ASTNode *type); + void createVariable(const std::string &name, ASTNode *type, const std::optional &value = std::nullopt); void setVariable(const std::string &name, const Token::Literal& value); diff --git a/plugins/libimhex/include/hex/pattern_language/parser.hpp b/plugins/libimhex/include/hex/pattern_language/parser.hpp index a24e156c1..4b5adfbf9 100644 --- a/plugins/libimhex/include/hex/pattern_language/parser.hpp +++ b/plugins/libimhex/include/hex/pattern_language/parser.hpp @@ -99,7 +99,7 @@ namespace hex::pl { void parseAttribute(Attributable *currNode); ASTNode* parseConditional(); ASTNode* parseWhileStatement(); - ASTNodeTypeDecl* parseType(bool allowString = false); + ASTNodeTypeDecl* parseType(bool allowFunctionTypes = false); ASTNode* parseUsingDeclaration(); ASTNode* parsePadding(); ASTNode* parseMemberVariable(ASTNodeTypeDecl *type); diff --git a/plugins/libimhex/include/hex/pattern_language/token.hpp b/plugins/libimhex/include/hex/pattern_language/token.hpp index 990b0f4ca..fa8b7bd7b 100644 --- a/plugins/libimhex/include/hex/pattern_language/token.hpp +++ b/plugins/libimhex/include/hex/pattern_language/token.hpp @@ -91,6 +91,7 @@ namespace hex::pl { Float = 0x42, Double = 0x82, String = 0x15, + Auto = 0x16, CustomType = 0x00, Padding = 0x1F, diff --git a/plugins/libimhex/source/pattern_language/evaluator.cpp b/plugins/libimhex/source/pattern_language/evaluator.cpp index 241c8efd1..307d6317c 100644 --- a/plugins/libimhex/source/pattern_language/evaluator.cpp +++ b/plugins/libimhex/source/pattern_language/evaluator.cpp @@ -3,7 +3,7 @@ namespace hex::pl { - void Evaluator::createVariable(const std::string &name, ASTNode *type) { + void Evaluator::createVariable(const std::string &name, ASTNode *type, const std::optional &value) { auto &variables = *this->getScope(0).scope; for (auto &variable : variables) { if (variable->getVariableName() == name) { @@ -13,6 +13,27 @@ namespace hex::pl { auto pattern = type->createPatterns(this).front(); + if (pattern == nullptr) { + // Handle auto variables + if (!value.has_value()) + LogConsole::abortEvaluation("cannot determine type of auto variable", type); + + if (std::get_if(&*value) != nullptr) + pattern = new PatternDataUnsigned(0, sizeof(u128)); + else if (std::get_if(&*value) != nullptr) + pattern = new PatternDataSigned(0, sizeof(s128)); + else if (std::get_if(&*value) != nullptr) + pattern = new PatternDataFloat(0, sizeof(double)); + else if (std::get_if(&*value) != nullptr) + pattern = new PatternDataBoolean(0, sizeof(bool)); + else if (std::get_if(&*value) != nullptr) + pattern = new PatternDataCharacter(0, sizeof(char)); + else if (std::get_if(&*value) != nullptr) + pattern = std::get(*value)->clone(); + else if (std::get_if(&*value) != nullptr) + pattern = new PatternDataString(0, 1); + } + pattern->setVariableName(name); pattern->setOffset(this->getStack().size()); pattern->setLocal(true); diff --git a/plugins/libimhex/source/pattern_language/lexer.cpp b/plugins/libimhex/source/pattern_language/lexer.cpp index 8529a5050..ce856e0a1 100644 --- a/plugins/libimhex/source/pattern_language/lexer.cpp +++ b/plugins/libimhex/source/pattern_language/lexer.cpp @@ -450,6 +450,8 @@ namespace hex::pl { tokens.emplace_back(TOKEN(ValueType, String)); else if (identifier == "padding") tokens.emplace_back(TOKEN(ValueType, Padding)); + else if (identifier == "auto") + tokens.emplace_back(TOKEN(ValueType, Auto)); // If it's not a keyword and a builtin type, it has to be an identifier diff --git a/plugins/libimhex/source/pattern_language/parser.cpp b/plugins/libimhex/source/pattern_language/parser.cpp index a43ae0678..19025bc36 100644 --- a/plugins/libimhex/source/pattern_language/parser.cpp +++ b/plugins/libimhex/source/pattern_language/parser.cpp @@ -645,7 +645,7 @@ namespace hex::pl { /* Type declarations */ // [be|le] - ASTNodeTypeDecl* Parser::parseType(bool allowString) { + ASTNodeTypeDecl* Parser::parseType(bool allowFunctionTypes) { std::optional endian; if (MATCHES(sequence(KEYWORD_LE))) @@ -665,8 +665,12 @@ namespace hex::pl { } else if (MATCHES(sequence(VALUETYPE_ANY))) { // Builtin type auto type = getValue(-1); - if (!allowString && type == Token::ValueType::String) - throwParseError("cannot use 'str' in this context. Use a character array instead"); + if (!allowFunctionTypes) { + if (type == Token::ValueType::String) + throwParseError("cannot use 'str' in this context. Use a character array instead"); + else if (type == Token::ValueType::Auto) + throwParseError("cannot use 'auto' in this context"); + } return create(new ASTNodeTypeDecl({ }, new ASTNodeBuiltinType(type), endian)); } else throwParseError("failed to parse type. Expected identifier or builtin type"); diff --git a/source/views/view_pattern_editor.cpp b/source/views/view_pattern_editor.cpp index 1715901cf..e22ee5989 100644 --- a/source/views/view_pattern_editor.cpp +++ b/source/views/view_pattern_editor.cpp @@ -32,7 +32,7 @@ namespace hex { "u8", "u16", "u32", "u64", "u128", "s8", "s16", "s32", "s64", "s128", "float", "double", "char", "char16", - "bool", "padding", "str" + "bool", "padding", "str", "auto" }; for (const auto name : builtInTypes) {