1
0
mirror of synced 2024-11-24 15:50:16 +01:00

Added print & warnAssert functions and a colored console

This commit is contained in:
WerWolv 2021-01-09 23:48:42 +01:00
parent e54dbcf574
commit 7a8e923b41
5 changed files with 161 additions and 72 deletions

View File

@ -16,12 +16,12 @@ namespace hex::lang {
class Evaluator {
public:
Evaluator(prv::Provider* &provider, std::endian defaultDataEndian);
std::optional<std::vector<PatternData*>> evaluate(const std::vector<ASTNode*>& ast);
const std::pair<u32, std::string>& getError() { return this->m_error; }
enum ConsoleLogLevel {
Debug,
Info,
Warning,
Error
};
struct Function {
constexpr static u32 UnlimitedParameters = 0xFFFF'FFFF;
@ -33,6 +33,11 @@ namespace hex::lang {
std::function<ASTNodeIntegerLiteral*(std::vector<ASTNode*>)> func;
};
Evaluator(prv::Provider* &provider, std::endian defaultDataEndian);
std::optional<std::vector<PatternData*>> evaluate(const std::vector<ASTNode*>& ast);
const auto& getConsoleLog() { return this->m_consoleLog; }
private:
std::map<std::string, ASTNode*> m_types;
prv::Provider* &m_provider;
@ -43,12 +48,24 @@ namespace hex::lang {
std::vector<std::vector<PatternData*>*> m_currMembers;
std::map<std::string, Function> m_functions;
std::pair<u32, std::string> m_error;
std::vector<std::pair<ConsoleLogLevel, std::string>> m_consoleLog;
using EvaluateError = std::pair<u32, std::string>;
using EvaluateError = std::string;
[[noreturn]] static void throwEvaluateError(std::string_view error, u32 lineNumber) {
throw EvaluateError(lineNumber, "Evaluator: " + std::string(error));
void emmitDebugInfo(std::string_view message) {
this->m_consoleLog.emplace_back(ConsoleLogLevel::Debug, "[-] " + std::string(message));
}
void emmitInfo(std::string_view message) {
this->m_consoleLog.emplace_back(ConsoleLogLevel::Info, "[i] " + std::string(message));
}
void emmitWaring(std::string_view message) {
this->m_consoleLog.emplace_back(ConsoleLogLevel::Warning, "[*] " + std::string(message));
}
[[noreturn]] static void throwEvaluateError(std::string_view message) {
throw EvaluateError("[!] " + std::string(message));
}
[[nodiscard]] std::endian getCurrentEndian() const {
@ -57,7 +74,7 @@ namespace hex::lang {
void addFunction(std::string_view name, u32 parameterCount, std::function<ASTNodeIntegerLiteral*(std::vector<ASTNode*>)> func) {
if (this->m_functions.contains(name.data()))
throwEvaluateError(hex::format("redefinition of function '%s'", name.data()), 1);
throwEvaluateError(hex::format("redefinition of function '%s'", name.data()));
this->m_functions[name.data()] = { parameterCount, func };
}
@ -87,7 +104,7 @@ namespace hex::lang {
if (auto evaluatedParam = dynamic_cast<T*>(param); evaluatedParam != nullptr)
return evaluatedParam;
else
throwEvaluateError("function got wrong type of parameter", 1);
throwEvaluateError("function got wrong type of parameter");
}
@ -99,6 +116,8 @@ namespace hex::lang {
BUILTIN_FUNCTION(readSigned);
BUILTIN_FUNCTION(assert);
BUILTIN_FUNCTION(warnAssert);
BUILTIN_FUNCTION(print);
#undef BUILTIN_FUNCTION
};

View File

@ -1,9 +1,8 @@
#pragma once
#include "lang/ast_node.hpp"
#include "views/view.hpp"
#include "lang/pattern_data.hpp"
#include "lang/evaluator.hpp"
#include "providers/provider.hpp"
@ -29,7 +28,7 @@ namespace hex {
std::filesystem::path m_possiblePatternFile;
TextEditor m_textEditor;
std::vector<std::string> m_console;
std::vector<std::pair<lang::Evaluator::ConsoleLogLevel, std::string>> m_console;
imgui_addons::ImGuiFileBrowser m_fileBrowser;
void loadPatternFile(std::string path);

View File

@ -14,7 +14,7 @@ namespace hex::lang {
if (value <= 0xFF)
return value;
else
throwEvaluateError("sequence bytes need to fit into 1 byte", 1);
throwEvaluateError("sequence bytes need to fit into 1 byte");
}, asType<ASTNodeIntegerLiteral>(params[i])->getValue()));
}
@ -33,7 +33,7 @@ namespace hex::lang {
}
}
throwEvaluateError("failed to find sequence", 1);
throwEvaluateError("failed to find sequence");
}
BUILTIN_FUNCTION(readUnsigned) {
@ -41,11 +41,11 @@ namespace hex::lang {
auto size = asType<ASTNodeIntegerLiteral>(params[1])->getValue();
if (LITERAL_COMPARE(address, address >= this->m_provider->getActualSize()))
throwEvaluateError("address out of range", 1);
throwEvaluateError("address out of range");
return std::visit([this](auto &&address, auto &&size) {
if (size <= 0 || size > 16)
throwEvaluateError("invalid read size", 1);
throwEvaluateError("invalid read size");
u8 value[(u8)size];
this->m_provider->read(address, value, size);
@ -56,7 +56,7 @@ namespace hex::lang {
case 4: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned32Bit, hex::changeEndianess(*reinterpret_cast<u32*>(value), 4, this->getCurrentEndian()) });
case 8: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, hex::changeEndianess(*reinterpret_cast<u64*>(value), 8, this->getCurrentEndian()) });
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned128Bit, hex::changeEndianess(*reinterpret_cast<u128*>(value), 16, this->getCurrentEndian()) });
default: throwEvaluateError("invalid read size", 1);
default: throwEvaluateError("invalid read size");
}
}, address, size);
}
@ -66,11 +66,11 @@ namespace hex::lang {
auto size = asType<ASTNodeIntegerLiteral>(params[1])->getValue();
if (LITERAL_COMPARE(address, address >= this->m_provider->getActualSize()))
throwEvaluateError("address out of range", 1);
throwEvaluateError("address out of range");
return std::visit([this](auto &&address, auto &&size) {
if (size <= 0 || size > 16)
throwEvaluateError("invalid read size", 1);
throwEvaluateError("invalid read size");
u8 value[(u8)size];
this->m_provider->read(address, value, size);
@ -81,17 +81,59 @@ namespace hex::lang {
case 4: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed32Bit, hex::changeEndianess(*reinterpret_cast<s32*>(value), 4, this->getCurrentEndian()) });
case 8: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed64Bit, hex::changeEndianess(*reinterpret_cast<s64*>(value), 8, this->getCurrentEndian()) });
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed128Bit, hex::changeEndianess(*reinterpret_cast<s128*>(value), 16, this->getCurrentEndian()) });
default: throwEvaluateError("invalid read size", 1);
default: throwEvaluateError("invalid read size");
}
}, address, size);
}
BUILTIN_FUNCTION(assert) {
auto condition = asType<ASTNodeIntegerLiteral>(params[0])->getValue();
auto error = asType<ASTNodeStringLiteral>(params[1])->getString();
auto message = asType<ASTNodeStringLiteral>(params[1])->getString();
if (LITERAL_COMPARE(condition, condition == 0))
throwEvaluateError(hex::format("assertion failed: '%s'", error.data()), 1);
throwEvaluateError(hex::format("assert failed \"%s\"", message.data()));
return nullptr;
}
BUILTIN_FUNCTION(warnAssert) {
auto condition = asType<ASTNodeIntegerLiteral>(params[0])->getValue();
auto message = asType<ASTNodeStringLiteral>(params[1])->getString();
if (LITERAL_COMPARE(condition, condition == 0))
this->emmitWaring(hex::format("assert failed \"%s\"", message.data()));
return nullptr;
}
BUILTIN_FUNCTION(print) {
std::string message;
for (auto& param : params) {
if (auto integerLiteral = dynamic_cast<ASTNodeIntegerLiteral*>(param); integerLiteral != nullptr) {
switch (integerLiteral->getType()) {
case Token::ValueType::Character: message += std::get<s8>(integerLiteral->getValue()); break;
case Token::ValueType::Unsigned8Bit: message += std::to_string(std::get<u8>(integerLiteral->getValue())); break;
case Token::ValueType::Signed8Bit: message += std::to_string(std::get<s8>(integerLiteral->getValue())); break;
case Token::ValueType::Unsigned16Bit: message += std::to_string(std::get<u16>(integerLiteral->getValue())); break;
case Token::ValueType::Signed16Bit: message += std::to_string(std::get<s16>(integerLiteral->getValue())); break;
case Token::ValueType::Unsigned32Bit: message += std::to_string(std::get<u32>(integerLiteral->getValue())); break;
case Token::ValueType::Signed32Bit: message += std::to_string(std::get<s32>(integerLiteral->getValue())); break;
case Token::ValueType::Unsigned64Bit: message += std::to_string(std::get<u64>(integerLiteral->getValue())); break;
case Token::ValueType::Signed64Bit: message += std::to_string(std::get<s64>(integerLiteral->getValue())); break;
//case Token::ValueType::Unsigned128Bit: message += std::to_string(std::get<u128>(integerLiteral->getValue())); break;
//case Token::ValueType::Signed128Bit: message += std::to_string(std::get<s128>(integerLiteral->getValue())); break;
case Token::ValueType::Float: message += std::to_string(std::get<float>(integerLiteral->getValue())); break;
case Token::ValueType::Double: message += std::to_string(std::get<double>(integerLiteral->getValue())); break;
case Token::ValueType::Boolean: message += std::get<u8>(integerLiteral->getValue()) ? "true" : "false"; break;
case Token::ValueType::CustomType: message += "< Custom Type >"; break;
}
}
else if (auto stringLiteral = dynamic_cast<ASTNodeStringLiteral*>(param); stringLiteral != nullptr)
message += stringLiteral->getString();
}
this->emmitInfo(message);
return nullptr;
}

View File

@ -28,6 +28,14 @@ namespace hex::lang {
this->addFunction("assert", 2, [this](auto params) {
return this->builtin_assert(params);
});
this->addFunction("warnAssert", 2, [this](auto params) {
return this->builtin_warnAssert(params);
});
this->addFunction("print", Function::MoreParametersThan | 0, [this](auto params) {
return this->builtin_print(params);
});
}
ASTNodeIntegerLiteral* Evaluator::evaluateScopeResolution(ASTNodeScopeResolution *node) {
@ -46,12 +54,12 @@ namespace hex::lang {
}
}
throwEvaluateError("failed to find identifier", node->getLineNumber());
throwEvaluateError("failed to find identifier");
}
ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) {
if (this->m_currMembers.empty() && this->m_globalMembers.empty())
throwEvaluateError("no variables available", node->getLineNumber());
throwEvaluateError("no variables available");
std::vector<PatternData*> currMembers;
@ -74,7 +82,7 @@ namespace hex::lang {
continue;
}
else if (currPattern != nullptr)
throwEvaluateError("tried to access member of a non-struct/union type", node->getLineNumber());
throwEvaluateError("tried to access member of a non-struct/union type");
auto candidate = std::find_if(currMembers.begin(), currMembers.end(), [&](auto member) {
return member->getVariableName() == identifier;
@ -83,7 +91,7 @@ namespace hex::lang {
if (candidate != currMembers.end())
currPattern = *candidate;
else
throwEvaluateError(hex::format("could not find identifier '%s'", identifier.c_str()), node->getLineNumber());
throwEvaluateError(hex::format("could not find identifier '%s'", identifier.c_str()));
}
if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(currPattern); pointerPattern != nullptr)
@ -99,7 +107,7 @@ namespace hex::lang {
case 4: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned32Bit, hex::changeEndianess(*reinterpret_cast<u32*>(value), 4, this->getCurrentEndian()) });
case 8: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, hex::changeEndianess(*reinterpret_cast<u64*>(value), 8, this->getCurrentEndian()) });
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned128Bit, hex::changeEndianess(*reinterpret_cast<u128*>(value), 16, this->getCurrentEndian()) });
default: throwEvaluateError("invalid rvalue size", node->getLineNumber());
default: throwEvaluateError("invalid rvalue size");
}
} else if (auto signedPattern = dynamic_cast<PatternDataSigned*>(currPattern); signedPattern != nullptr) {
u8 value[unsignedPattern->getSize()];
@ -111,7 +119,7 @@ namespace hex::lang {
case 4: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed32Bit, hex::changeEndianess(*reinterpret_cast<s32*>(value), 4, this->getCurrentEndian()) });
case 8: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed64Bit, hex::changeEndianess(*reinterpret_cast<s64*>(value), 8, this->getCurrentEndian()) });
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed128Bit, hex::changeEndianess(*reinterpret_cast<s128*>(value), 16, this->getCurrentEndian()) });
default: throwEvaluateError("invalid rvalue size", node->getLineNumber());
default: throwEvaluateError("invalid rvalue size");
}
} else if (auto enumPattern = dynamic_cast<PatternDataEnum*>(currPattern); enumPattern != nullptr) {
u8 value[enumPattern->getSize()];
@ -123,10 +131,10 @@ namespace hex::lang {
case 4: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned32Bit, hex::changeEndianess(*reinterpret_cast<u32*>(value), 4, this->getCurrentEndian()) });
case 8: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, hex::changeEndianess(*reinterpret_cast<u64*>(value), 8, this->getCurrentEndian()) });
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned128Bit, hex::changeEndianess(*reinterpret_cast<u128*>(value), 16, this->getCurrentEndian()) });
default: throwEvaluateError("invalid rvalue size", node->getLineNumber());
default: throwEvaluateError("invalid rvalue size");
}
} else
throwEvaluateError("tried to use non-integer value in numeric expression", node->getLineNumber());
throwEvaluateError("tried to use non-integer value in numeric expression");
}
ASTNodeIntegerLiteral* Evaluator::evaluateFunctionCall(ASTNodeFunctionCall *node) {
@ -144,7 +152,7 @@ namespace hex::lang {
}
if (!this->m_functions.contains(node->getFunctionName().data()))
throwEvaluateError(hex::format("no function named '%s' found", node->getFunctionName().data()), node->getLineNumber());
throwEvaluateError(hex::format("no function named '%s' found", node->getFunctionName().data()));
auto &function = this->m_functions[node->getFunctionName().data()];
@ -153,12 +161,12 @@ namespace hex::lang {
}
else if (function.parameterCount & Function::LessParametersThan) {
if (evaluatedParams.size() >= (function.parameterCount & ~Function::LessParametersThan))
throwEvaluateError(hex::format("too many parameters for function '%s'. Expected %d", node->getFunctionName().data(), function.parameterCount & ~Function::LessParametersThan), node->getLineNumber());
throwEvaluateError(hex::format("too many parameters for function '%s'. Expected %d", node->getFunctionName().data(), function.parameterCount & ~Function::LessParametersThan));
} else if (function.parameterCount & Function::MoreParametersThan) {
if (evaluatedParams.size() <= (function.parameterCount & ~Function::MoreParametersThan))
throwEvaluateError(hex::format("too few parameters for function '%s'. Expected %d", node->getFunctionName().data(), function.parameterCount & ~Function::MoreParametersThan), node->getLineNumber());
throwEvaluateError(hex::format("too few parameters for function '%s'. Expected %d", node->getFunctionName().data(), function.parameterCount & ~Function::MoreParametersThan));
} else if (function.parameterCount != evaluatedParams.size()) {
throwEvaluateError(hex::format("invalid number of parameters for function '%s'. Expected %d", node->getFunctionName().data(), function.parameterCount), node->getLineNumber());
throwEvaluateError(hex::format("invalid number of parameters for function '%s'. Expected %d", node->getFunctionName().data(), function.parameterCount));
}
return function.func(evaluatedParams);
@ -266,12 +274,12 @@ namespace hex::lang {
case Token::Operator::BoolNot:
return new ASTNodeIntegerLiteral({ newType, !rightValue });
default:
throwEvaluateError("invalid operator used in mathematical expression", left->getLineNumber());
throwEvaluateError("invalid operator used in mathematical expression");
}
}, left->getValue(), right->getValue());
} catch (std::runtime_error &e) {
throwEvaluateError("bitwise operations on floating point numbers are forbidden", left->getLineNumber());
throwEvaluateError("bitwise operations on floating point numbers are forbidden");
}
}
@ -290,12 +298,12 @@ namespace hex::lang {
auto returnValue = evaluateFunctionCall(exprFunctionCall);
if (returnValue == nullptr)
throwEvaluateError("function returning void used in expression", node->getLineNumber());
throwEvaluateError("function returning void used in expression");
else
return returnValue;
}
else
throwEvaluateError("invalid operand", node->getLineNumber());
throwEvaluateError("invalid operand");
}
ASTNodeIntegerLiteral* Evaluator::evaluateTernaryExpression(ASTNodeTernaryExpression *node) {
@ -310,7 +318,7 @@ namespace hex::lang {
return this->evaluateOperand(node->getThirdOperand());
}
default:
throwEvaluateError("invalid operator used in ternary expression", node->getLineNumber());
throwEvaluateError("invalid operator used in ternary expression");
}
}
@ -338,7 +346,7 @@ namespace hex::lang {
else if (Token::isFloatingPoint(type))
pattern = new PatternDataFloat(this->m_currOffset, typeSize);
else
throwEvaluateError("invalid builtin type", node->getLineNumber());
throwEvaluateError("invalid builtin type");
this->m_currOffset += typeSize;
@ -376,7 +384,7 @@ namespace hex::lang {
return patterns;
}
else
throwEvaluateError("invalid struct member", node->getLineNumber());
throwEvaluateError("invalid struct member");
}
PatternData* Evaluator::evaluateStruct(ASTNodeStruct *node) {
@ -418,7 +426,7 @@ namespace hex::lang {
for (auto &[name, value] : node->getEntries()) {
auto expression = dynamic_cast<ASTNodeNumericExpression*>(value);
if (expression == nullptr)
throwEvaluateError("invalid expression in enum value", value->getLineNumber());
throwEvaluateError("invalid expression in enum value");
auto valueNode = evaluateMathematicalExpression(expression);
SCOPE_EXIT( delete valueNode; );
@ -430,7 +438,7 @@ namespace hex::lang {
if (auto underlyingType = dynamic_cast<const ASTNodeBuiltinType*>(node->getUnderlyingType()); underlyingType != nullptr)
size = Token::getTypeSize(underlyingType->getType());
else
throwEvaluateError("invalid enum underlying type", node->getLineNumber());
throwEvaluateError("invalid enum underlying type");
return new PatternDataEnum(startOffset, size, entryPatterns);
}
@ -443,19 +451,19 @@ namespace hex::lang {
for (auto &[name, value] : node->getEntries()) {
auto expression = dynamic_cast<ASTNodeNumericExpression*>(value);
if (expression == nullptr)
throwEvaluateError("invalid expression in bitfield field size", value->getLineNumber());
throwEvaluateError("invalid expression in bitfield field size");
auto valueNode = evaluateMathematicalExpression(expression);
SCOPE_EXIT( delete valueNode; );
auto fieldBits = std::visit([node, type = valueNode->getType()] (auto &&value) {
if (Token::isFloatingPoint(type))
throwEvaluateError("bitfield entry size must be an integer value", node->getLineNumber());
throwEvaluateError("bitfield entry size must be an integer value");
return static_cast<s128>(value);
}, valueNode->getValue());
if (fieldBits > 64 || fieldBits <= 0)
throwEvaluateError("bitfield entry must occupy between 1 and 64 bits", value->getLineNumber());
throwEvaluateError("bitfield entry must occupy between 1 and 64 bits");
bits += fieldBits;
@ -485,7 +493,7 @@ namespace hex::lang {
else if (auto bitfieldNode = dynamic_cast<ASTNodeBitfield*>(type); bitfieldNode != nullptr)
pattern = this->evaluateBitfield(bitfieldNode);
else
throwEvaluateError("type could not be evaluated", node->getLineNumber());
throwEvaluateError("type could not be evaluated");
if (!node->getName().empty())
pattern->setTypeName(node->getName().data());
@ -505,12 +513,12 @@ namespace hex::lang {
this->m_currOffset = std::visit([node, type = valueNode->getType()] (auto &&value) {
if (Token::isFloatingPoint(type))
throwEvaluateError("placement offset must be an integer value", node->getLineNumber());
throwEvaluateError("placement offset must be an integer value");
return static_cast<u64>(value);
}, valueNode->getValue());
}
if (this->m_currOffset >= this->m_provider->getActualSize())
throwEvaluateError("variable placed out of range", node->getLineNumber());
throwEvaluateError("variable placed out of range");
PatternData *pattern;
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr)
@ -518,7 +526,7 @@ namespace hex::lang {
else if (auto builtinTypeDecl = dynamic_cast<ASTNodeBuiltinType*>(node->getType()); builtinTypeDecl != nullptr)
pattern = this->evaluateBuiltinType(builtinTypeDecl);
else
throwEvaluateError("ASTNodeVariableDecl had an invalid type. This is a bug!", 1);
throwEvaluateError("ASTNodeVariableDecl had an invalid type. This is a bug!");
pattern->setVariableName(node->getName().data());
@ -533,7 +541,7 @@ namespace hex::lang {
this->m_currOffset = std::visit([node, type = valueNode->getType()] (auto &&value) {
if (Token::isFloatingPoint(type))
throwEvaluateError("placement offset must be an integer value", node->getLineNumber());
throwEvaluateError("placement offset must be an integer value");
return static_cast<u64>(value);
}, valueNode->getValue());
}
@ -547,13 +555,13 @@ namespace hex::lang {
if (auto sizeNumericExpression = dynamic_cast<ASTNodeNumericExpression*>(node->getSize()); sizeNumericExpression != nullptr)
valueNode = evaluateMathematicalExpression(sizeNumericExpression);
else
throwEvaluateError("array size not a numeric expression", node->getLineNumber());
throwEvaluateError("array size not a numeric expression");
SCOPE_EXIT( delete valueNode; );
arraySize = std::visit([node, type = valueNode->getType()] (auto &&value) {
if (Token::isFloatingPoint(type))
throwEvaluateError("array size must be an integer value", node->getLineNumber());
throwEvaluateError("array size must be an integer value");
return static_cast<u64>(value);
}, valueNode->getValue());
@ -586,7 +594,7 @@ namespace hex::lang {
entry = this->evaluateBuiltinType(builtinTypeDecl);
}
else
throwEvaluateError("ASTNodeVariableDecl had an invalid type. This is a bug!", 1);
throwEvaluateError("ASTNodeVariableDecl had an invalid type. This is a bug!");
entry->setVariableName(hex::format("[%llu]", (u64)i));
entry->setEndian(this->getCurrentEndian());
@ -598,7 +606,7 @@ namespace hex::lang {
entries.push_back(entry);
if (this->m_currOffset >= this->m_provider->getActualSize())
throwEvaluateError("array exceeds size of file", node->getLineNumber());
throwEvaluateError("array exceeds size of file");
}
PatternData *pattern;
@ -609,7 +617,7 @@ namespace hex::lang {
pattern = new PatternDataString(startOffset, (this->m_currOffset - startOffset), color.value_or(0));
else {
if (node->getSize() == nullptr)
throwEvaluateError("no bounds provided for array", node->getLineNumber());
throwEvaluateError("no bounds provided for array");
pattern = new PatternDataArray(startOffset, (this->m_currOffset - startOffset), entries, color.value_or(0));
}
@ -626,7 +634,7 @@ namespace hex::lang {
pointerOffset = std::visit([node, type = valueNode->getType()] (auto &&value) {
if (Token::isFloatingPoint(type))
throwEvaluateError("pointer offset must be an integer value", node->getLineNumber());
throwEvaluateError("pointer offset must be an integer value");
return static_cast<s128>(value);
}, valueNode->getValue());
this->m_currOffset = pointerOffset;
@ -638,12 +646,12 @@ namespace hex::lang {
auto underlyingType = dynamic_cast<ASTNodeTypeDecl*>(node->getSizeType());
if (underlyingType == nullptr)
throwEvaluateError("underlying type is not ASTNodeTypeDecl. This is a bug", node->getLineNumber());
throwEvaluateError("underlying type is not ASTNodeTypeDecl. This is a bug");
if (auto builtinTypeNode = dynamic_cast<ASTNodeBuiltinType*>(underlyingType->getType()); builtinTypeNode != nullptr) {
sizeType = evaluateBuiltinType(builtinTypeNode);
} else
throwEvaluateError("pointer size is not a builtin type", node->getLineNumber());
throwEvaluateError("pointer size is not a builtin type");
size_t pointerSize = sizeType->getSize();
@ -655,7 +663,7 @@ namespace hex::lang {
if (this->m_currOffset > this->m_provider->getActualSize())
throwEvaluateError("pointer points past the end of the data", 1);
throwEvaluateError("pointer points past the end of the data");
PatternData *pointedAt;
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr)
@ -663,7 +671,7 @@ namespace hex::lang {
else if (auto builtinTypeDecl = dynamic_cast<ASTNodeBuiltinType*>(node->getType()); builtinTypeDecl != nullptr)
pointedAt = this->evaluateBuiltinType(builtinTypeDecl);
else
throwEvaluateError("ASTNodeVariableDecl had an invalid type. This is a bug!", 1);
throwEvaluateError("ASTNodeVariableDecl had an invalid type. This is a bug!");
this->m_currOffset = pointerOffset + pointerSize;
@ -697,7 +705,7 @@ namespace hex::lang {
this->m_endianStack.pop_back();
}
} catch (EvaluateError &e) {
this->m_error = e;
this->m_consoleLog.emplace_back(ConsoleLogLevel::Error, e);
this->m_endianStack.clear();
return { };

View File

@ -28,6 +28,7 @@ namespace hex {
{ "s8", 1 }, { "s16", 2 }, { "s32", 4 }, { "s64", 8 }, { "s128", 16 },
{ "float", 4 }, { "double", 8 }, { "char", 1 }, { "bool", 1 }, { "padding", 1 }
};
for (const auto &[name, size] : builtInTypes) {
TextEditor::Identifier id;
id.mDeclaration = std::to_string(size);
@ -52,6 +53,8 @@ namespace hex {
paletteIndex = TextEditor::PaletteIndex::Number;
else if (TokenizeCStyleCharacterLiteral(inBegin, inEnd, outBegin, outEnd))
paletteIndex = TextEditor::PaletteIndex::CharLiteral;
else if (TokenizeCStyleString(inBegin, inEnd, outBegin, outEnd))
paletteIndex = TextEditor::PaletteIndex::String;
return paletteIndex != TextEditor::PaletteIndex::Max;
};
@ -191,15 +194,33 @@ namespace hex {
auto consoleSize = ImGui::GetContentRegionAvail();
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.0, 0.0, 0.0, 1.0));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0, 1.0, 1.0, 1.0));
if (ImGui::BeginChild("##console", consoleSize, true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
for (auto &line : this->m_console)
ImGui::TextUnformatted(line.c_str());
for (auto &[level, message] : this->m_console) {
switch (level) {
case lang::Evaluator::ConsoleLogLevel::Debug:
ImGui::PushStyleColor(ImGuiCol_Text, ImColor(0x1F, 0xA9, 0x49, 0xFF).Value);
break;
case lang::Evaluator::ConsoleLogLevel::Info:
ImGui::PushStyleColor(ImGuiCol_Text, ImColor(0x00, 0x70, 0xB4, 0xFF).Value);
break;
case lang::Evaluator::ConsoleLogLevel::Warning:
ImGui::PushStyleColor(ImGuiCol_Text, ImColor(0xFF, 0xC8, 0x01, 0xFF).Value);
break;
case lang::Evaluator::ConsoleLogLevel::Error:
ImGui::PushStyleColor(ImGuiCol_Text, ImColor(0xAE, 0x0C, 0x00, 0xFF).Value);
break;
default: continue;
}
ImGui::TextUnformatted(message.c_str());
ImGui::PopStyleColor();
}
}
ImGui::EndChild();
ImGui::PopStyleColor(2);
ImGui::PopStyleColor(1);
if (this->m_textEditor.IsTextChanged()) {
this->parsePattern(this->m_textEditor.GetText().data());
@ -320,11 +341,11 @@ namespace hex {
auto provider = *SharedData::get().currentProvider;
hex::lang::Evaluator evaluator(provider, defaultDataEndianess);
auto patternData = evaluator.evaluate(ast.value());
if (!patternData.has_value()) {
this->m_console.push_back(evaluator.getError().second);
this->m_console = evaluator.getConsoleLog();
if (!patternData.has_value())
return;
}
this->m_patternData = patternData.value();
this->postEvent(Events::PatternChanged);