#pragma once #include #include #include #include #include #include #include #include #include namespace hex::lang { class LogConsole { public: enum Level { Debug, Info, Warning, Error }; const auto& getLog() { return this->m_consoleLog; } using EvaluateError = std::string; void log(Level level, std::string_view message) { switch (level) { default: case Level::Debug: this->m_consoleLog.emplace_back(level, "[-] " + std::string(message)); break; case Level::Info: this->m_consoleLog.emplace_back(level, "[i] " + std::string(message)); break; case Level::Warning: this->m_consoleLog.emplace_back(level, "[*] " + std::string(message)); break; case Level::Error: this->m_consoleLog.emplace_back(level, "[!] " + std::string(message)); break; } } [[noreturn]] void abortEvaluation(std::string_view message) { throw EvaluateError(message); } private: std::vector> m_consoleLog; }; class Evaluator { public: Evaluator(prv::Provider* &provider, std::endian defaultDataEndian); std::optional> evaluate(const std::vector& ast); LogConsole& getConsole() { return this->m_console; } private: std::map m_types; prv::Provider* &m_provider; std::endian m_defaultDataEndian; u64 m_currOffset = 0; std::vector m_endianStack; std::vector m_globalMembers; std::vector*> m_currMembers; LogConsole m_console; [[nodiscard]] std::endian getCurrentEndian() const { return this->m_endianStack.back(); } ASTNodeIntegerLiteral* evaluateScopeResolution(ASTNodeScopeResolution *node); ASTNodeIntegerLiteral* evaluateRValue(ASTNodeRValue *node); ASTNode* evaluateFunctionCall(ASTNodeFunctionCall *node); ASTNodeIntegerLiteral* evaluateOperator(ASTNodeIntegerLiteral *left, ASTNodeIntegerLiteral *right, Token::Operator op); ASTNodeIntegerLiteral* evaluateOperand(ASTNode *node); ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node); ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node); PatternData* patternFromName(const std::vector &name); PatternData* evaluateAttributes(ASTNode *currNode, PatternData *currPattern); PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node); void evaluateMember(ASTNode *node, std::vector &currMembers, bool increaseOffset); PatternData* evaluateStruct(ASTNodeStruct *node); PatternData* evaluateUnion(ASTNodeUnion *node); PatternData* evaluateEnum(ASTNodeEnum *node); PatternData* evaluateBitfield(ASTNodeBitfield *node); PatternData* evaluateType(ASTNodeTypeDecl *node); PatternData* evaluateVariable(ASTNodeVariableDecl *node); PatternData* evaluateArray(ASTNodeArrayVariableDecl *node); PatternData* evaluatePointer(ASTNodePointerVariableDecl *node); template T* asType(ASTNode *param) { if (auto evaluatedParam = dynamic_cast(param); evaluatedParam != nullptr) return evaluatedParam; else this->m_console.abortEvaluation("function got wrong type of parameter"); } void registerBuiltinFunctions(); #define BUILTIN_FUNCTION(name) ASTNodeIntegerLiteral* TOKEN_CONCAT(builtin_, name)(LogConsole &console, std::vector params) BUILTIN_FUNCTION(findSequence); BUILTIN_FUNCTION(readUnsigned); BUILTIN_FUNCTION(readSigned); BUILTIN_FUNCTION(assert); BUILTIN_FUNCTION(warnAssert); BUILTIN_FUNCTION(print); #undef BUILTIN_FUNCTION }; }