#include #include namespace hex::pl { 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) { LogConsole::abortEvaluation(hex::format("variable with name '{}' already exists", name)); } } 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); this->getStack().emplace_back(); variables.push_back(pattern); } void Evaluator::setVariable(const std::string &name, const Token::Literal& value) { PatternData *pattern = nullptr; auto &variables = *this->getScope(0).scope; for (auto &variable : variables) { if (variable->getVariableName() == name) { pattern = variable; break; } } if (pattern == nullptr) LogConsole::abortEvaluation(hex::format("no variable with name '{}' found", name)); Token::Literal castedLiteral = std::visit(overloaded { [&](double &value) -> Token::Literal { if (dynamic_cast(pattern)) return u128(value); else if (dynamic_cast(pattern)) return s128(value); else if (dynamic_cast(pattern)) return value; else LogConsole::abortEvaluation(hex::format("cannot cast type 'double' to type '{}'", pattern->getTypeName())); }, [&](const std::string &value) -> Token::Literal { if (dynamic_cast(pattern)) return value; else LogConsole::abortEvaluation(hex::format("cannot cast type 'string' to type '{}'", pattern->getTypeName())); }, [&](PatternData * const &value) -> Token::Literal { if (value->getTypeName() == pattern->getTypeName()) return value; else LogConsole::abortEvaluation(hex::format("cannot cast type '{}' to type '{}'", value->getTypeName(), pattern->getTypeName())); }, [&](auto &&value) -> Token::Literal { if (dynamic_cast(pattern)) return u128(value); else if (dynamic_cast(pattern)) return s128(value); else if (dynamic_cast(pattern)) return char(value); else if (dynamic_cast(pattern)) return bool(value); else if (dynamic_cast(pattern)) return double(value); else LogConsole::abortEvaluation(hex::format("cannot cast type 'string' to type '{}'", pattern->getTypeName())); } }, value); this->getStack().back() = castedLiteral; } std::optional> Evaluator::evaluate(const std::vector &ast) { this->m_stack.clear(); this->m_customFunctions.clear(); this->m_scopes.clear(); for (auto &func : this->m_customFunctionDefinitions) delete func; this->m_customFunctionDefinitions.clear(); std::vector patterns; try { pushScope(nullptr, patterns); for (auto node : ast) { if (dynamic_cast(node)) { ;// Don't create patterns from type declarations } else if (dynamic_cast(node)) { delete node->evaluate(this); } else if (dynamic_cast(node)) { this->m_customFunctionDefinitions.push_back(node->evaluate(this)); } else { auto newPatterns = node->createPatterns(this); patterns.insert(patterns.end(), newPatterns.begin(), newPatterns.end()); } } popScope(); } catch (const LogConsole::EvaluateError &error) { this->m_console.log(LogConsole::Level::Error, error.second); if (error.first != 0) this->m_console.setHardError(error); for (auto &pattern : patterns) delete pattern; patterns.clear(); return std::nullopt; } return patterns; } }