mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-01 21:17:44 -05:00
patterns: Rewrite evaluation engine (#306)
* patterns: Rewrite most of the evaluator to mainly use polymorphism instead of just RTTI * patterns: Fixed a couple of AST memory leaks * patterns: Parse string operations correctly * patterns: Various fixes and cleanup * patterns: Implement primitive function definitions Function parameters now need to provide their type in the definition * patterns: Added function variable definition and assignment * patterns: Added remaining function statements * patterns: Added unsized and while-sized arrays * patterns: Added multi variable declarations to functions * patterns: Added std::format built-in function * patterns: Allow passing custom types to functions * patterns: Added attributes and new "format" attribute * patterns: Use libfmt for std::print instead of custom version * patterns: Remove unnecessary string compare function * pattern: Fix preprocessor directives * patterns: Fix unit tests * patterns: Added cast expression * patterns: Handle endianess in function parameters * patterns: Added casting to different endian * patterns: Added 'str' type for functions
This commit is contained in:
@@ -6,8 +6,12 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class PatternData;
|
||||
|
||||
class Token {
|
||||
public:
|
||||
enum class Type : u64 {
|
||||
@@ -31,6 +35,7 @@ namespace hex::pl {
|
||||
If,
|
||||
Else,
|
||||
Parent,
|
||||
This,
|
||||
While,
|
||||
Function,
|
||||
Return,
|
||||
@@ -85,6 +90,7 @@ namespace hex::pl {
|
||||
Boolean = 0x14,
|
||||
Float = 0x42,
|
||||
Double = 0x82,
|
||||
String = 0x15,
|
||||
CustomType = 0x00,
|
||||
Padding = 0x1F,
|
||||
|
||||
@@ -108,8 +114,21 @@ namespace hex::pl {
|
||||
EndOfProgram
|
||||
};
|
||||
|
||||
using IntegerLiteral = std::variant<char, bool, u8, s8, u16, s16, u32, s32, u64, s64, u128, s128, float, double>;
|
||||
using ValueTypes = std::variant<Keyword, std::string, Operator, IntegerLiteral, ValueType, Separator>;
|
||||
struct Identifier {
|
||||
explicit Identifier(std::string identifier) : m_identifier(std::move(identifier)) { }
|
||||
|
||||
[[nodiscard]]
|
||||
const std::string &get() const { return this->m_identifier; }
|
||||
|
||||
auto operator<=>(const Identifier&) const = default;
|
||||
bool operator==(const Identifier&) const = default;
|
||||
|
||||
private:
|
||||
std::string m_identifier;
|
||||
};
|
||||
|
||||
using Literal = std::variant<char, bool, u128, s128, double, std::string, PatternData*>;
|
||||
using ValueTypes = std::variant<Keyword, Identifier, Operator, Literal, ValueType, Separator>;
|
||||
|
||||
Token(Type type, auto value, u32 lineNumber) : type(type), value(value), lineNumber(lineNumber) {
|
||||
|
||||
@@ -131,6 +150,58 @@ namespace hex::pl {
|
||||
return static_cast<u32>(type) >> 4;
|
||||
}
|
||||
|
||||
static u128 literalToUnsigned(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> u128 { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> u128 { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> u128 { return value; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static s128 literalToSigned(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> s128 { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> s128 { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> s128 { return value; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static double literalToFloatingPoint(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> double { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> double { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> double { return value; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static bool literalToBoolean(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> bool { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> bool { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> bool { return value != 0; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static std::string literalToString(const pl::Token::Literal &literal, bool cast) {
|
||||
if (!cast && std::get_if<std::string>(&literal) == nullptr)
|
||||
throw std::string("expected string type, got integral");
|
||||
|
||||
return std::visit(overloaded {
|
||||
[](std::string value) -> std::string { return value; },
|
||||
[](u128 value) -> std::string { return std::to_string(u64(value)); },
|
||||
[](s128 value) -> std::string { return std::to_string(s64(value)); },
|
||||
[](bool value) -> std::string { return value ? "true" : "false"; },
|
||||
[](char value) -> std::string { return std::string() + value; },
|
||||
[](PatternData*) -> std::string { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> std::string { return std::to_string(value); }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static auto getTypeName(const pl::Token::ValueType type) {
|
||||
switch (type) {
|
||||
case ValueType::Signed8Bit: return "s8";
|
||||
@@ -147,6 +218,7 @@ namespace hex::pl {
|
||||
case ValueType::Double: return "double";
|
||||
case ValueType::Character: return "char";
|
||||
case ValueType::Character16: return "char16";
|
||||
case ValueType::Padding: return "padding";
|
||||
default: return "< ??? >";
|
||||
}
|
||||
}
|
||||
@@ -204,14 +276,15 @@ namespace hex::pl {
|
||||
#define KEYWORD_IF COMPONENT(Keyword, If)
|
||||
#define KEYWORD_ELSE COMPONENT(Keyword, Else)
|
||||
#define KEYWORD_PARENT COMPONENT(Keyword, Parent)
|
||||
#define KEYWORD_THIS COMPONENT(Keyword, This)
|
||||
#define KEYWORD_WHILE COMPONENT(Keyword, While)
|
||||
#define KEYWORD_FUNCTION COMPONENT(Keyword, Function)
|
||||
#define KEYWORD_RETURN COMPONENT(Keyword, Return)
|
||||
#define KEYWORD_NAMESPACE COMPONENT(Keyword, Namespace)
|
||||
|
||||
#define INTEGER hex::pl::Token::Type::Integer, hex::pl::Token::IntegerLiteral(u64(0))
|
||||
#define INTEGER hex::pl::Token::Type::Integer, hex::pl::Token::Literal(u128(0))
|
||||
#define IDENTIFIER hex::pl::Token::Type::Identifier, ""
|
||||
#define STRING hex::pl::Token::Type::String, ""
|
||||
#define STRING hex::pl::Token::Type::String, hex::pl::Token::Literal("")
|
||||
|
||||
#define OPERATOR_AT COMPONENT(Operator, AtDeclaration)
|
||||
#define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment)
|
||||
|
||||
Reference in New Issue
Block a user