Added addressof, sizeof and nextAfter builtin functions.

Resolves #144
This commit is contained in:
WerWolv 2021-01-20 22:54:46 +01:00
parent b2648afc7b
commit 78a87baa94
4 changed files with 58 additions and 6 deletions

View file

@ -158,6 +158,21 @@ namespace hex {
return T(1) << bit_width(T(x - 1));
}
inline std::vector<std::string> splitString(std::string_view string, std::string_view delimiter) {
size_t start = 0, end;
std::string token;
std::vector<std::string> res;
while ((end = string.find (delimiter, start)) != std::string::npos) {
token = string.substr(start, end - start);
start = end + delimiter.length();
res.push_back(token);
}
res.push_back(std::string(string.substr(start)));
return res;
}
inline std::string toEngineeringString(double value) {
constexpr std::array prefixes = { "a", "f", "p", "n", "u", "m", "", "k", "M", "G", "T", "P", "E" };

View file

@ -69,6 +69,7 @@ namespace hex::lang {
ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node);
ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node);
PatternData* patternFromName(const std::vector<std::string> &name);
PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node);
void evaluateMember(ASTNode *node, std::vector<PatternData*> &currMembers, bool increaseOffset);
PatternData* evaluateStruct(ASTNodeStruct *node);

View file

@ -138,6 +138,33 @@ namespace hex::lang {
return nullptr;
});
ContentRegistry::PatternLanguageFunctions::add("addressof", 1, [this](auto params) -> ASTNode* {
auto name = asType<ASTNodeStringLiteral>(params[0])->getString();
std::vector<std::string> path = splitString(name, ".");
auto pattern = this->patternFromName(path);
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getOffset() });
});
ContentRegistry::PatternLanguageFunctions::add("sizeof", 1, [this](auto params) -> ASTNode* {
auto name = asType<ASTNodeStringLiteral>(params[0])->getString();
std::vector<std::string> path = splitString(name, ".");
auto pattern = this->patternFromName(path);
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getSize() });
});
ContentRegistry::PatternLanguageFunctions::add("nextAfter", 1, [this](auto params) -> ASTNode* {
auto name = asType<ASTNodeStringLiteral>(params[0])->getString();
std::vector<std::string> path = splitString(name, ".");
auto pattern = this->patternFromName(path);
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getOffset() + pattern->getSize() });
});
}
}

View file

@ -36,10 +36,7 @@ namespace hex::lang {
throwEvaluateError("failed to find identifier");
}
ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) {
if (this->m_currMembers.empty() && this->m_globalMembers.empty())
throwEvaluateError("no variables available");
PatternData* Evaluator::patternFromName(const std::vector<std::string> &path) {
std::vector<PatternData*> currMembers;
if (!this->m_currMembers.empty())
@ -48,8 +45,8 @@ namespace hex::lang {
std::copy(this->m_globalMembers.begin(), this->m_globalMembers.end(), std::back_inserter(currMembers));
PatternData *currPattern = nullptr;
for (u32 i = 0; i < node->getPath().size(); i++) {
const auto &identifier = node->getPath()[i];
for (u32 i = 0; i < path.size(); i++) {
const auto &identifier = path[i];
if (auto structPattern = dynamic_cast<PatternDataStruct*>(currPattern); structPattern != nullptr)
currMembers = structPattern->getMembers();
@ -76,6 +73,18 @@ namespace hex::lang {
if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(currPattern); pointerPattern != nullptr)
currPattern = pointerPattern->getPointedAtPattern();
return currPattern;
}
ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) {
if (this->m_currMembers.empty() && this->m_globalMembers.empty())
throwEvaluateError("no variables available");
if (node->getPath().size() == 1 && node->getPath()[0] == "$")
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, this->m_currOffset });
auto currPattern = this->patternFromName(node->getPath());
if (auto unsignedPattern = dynamic_cast<PatternDataUnsigned*>(currPattern); unsignedPattern != nullptr) {
u8 value[unsignedPattern->getSize()];
this->m_provider->read(unsignedPattern->getOffset(), value, unsignedPattern->getSize());