2023-05-09 14:55:04 +03:00
|
|
|
#include <optional>
|
|
|
|
|
#include <variant>
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
// for clangd
|
|
|
|
|
#include "../include/execute_visitor.hpp"
|
|
|
|
|
#include "../include/builtin_functions.hpp"
|
|
|
|
|
|
|
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
// TODO
|
|
|
|
|
|
|
|
|
|
namespace interpreter {
|
|
|
|
|
|
|
|
|
|
// Sources -----------------
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(SourceFile* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.SourceFile",
|
|
|
|
|
&node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Namespaces, partitions -----------------
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(NamespaceSources* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.NamespaceSources",
|
|
|
|
|
&node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(Namespace* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.Namespace",
|
|
|
|
|
&node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Definitions -----------------
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(ImportStatement* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.ImportStatement",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(AliasDefinitionStatement* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.AliasDefinitionStatement",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(VariableDefinitionStatement* node) {
|
2023-05-07 20:21:19 +03:00
|
|
|
Visitor::Visit(node->value);
|
2023-05-09 17:42:35 +03:00
|
|
|
|
|
|
|
|
is_const_definition_ = node->modifier;
|
|
|
|
|
Visitor::Visit(node->name); // current_type_ passed from value
|
|
|
|
|
is_const_definition_ = std::nullopt;
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(FunctionDeclaration* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.FunctionDeclaration",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-09 15:24:19 +03:00
|
|
|
void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { // visited on function call
|
2023-05-20 00:01:54 +03:00
|
|
|
context_manager_.EnterContext();
|
2023-05-20 20:18:49 +03:00
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
try {
|
|
|
|
|
Visitor::Visit(node->value);
|
|
|
|
|
} catch (utils::ValueReturnedMarker&) {}
|
2023-05-20 20:18:49 +03:00
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
// TODO: sometimes return references, choose by declaration
|
|
|
|
|
current_value_ = context_manager_.ToTemporaryValue(current_value_);
|
2023-05-20 20:18:49 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
context_manager_.ExitContext();
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(TypeDefinitionStatement* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.TypeDefinitionStatement",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.AbstractTypeDefinitionStatement",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(TypeclassDefinitionStatement* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.TypeclassDefinitionStatement",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-08 20:34:36 +03:00
|
|
|
void ExecuteVisitor::Visit(PartitionStatement* node) {
|
2023-05-07 22:58:15 +03:00
|
|
|
Visitor::Visit(node->value);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
// Flow control -----------------
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) { // handled in TypeConstructorPattern
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.TypeConstructorPatternParameter",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
// TODO: check
|
2023-05-07 20:21:19 +03:00
|
|
|
void ExecuteVisitor::Visit(TypeConstructorPattern* node) {
|
2023-05-10 23:13:50 +03:00
|
|
|
if (!node->constructor->constructor_id_.has_value()) { // checked in typeckeck visitor ??
|
|
|
|
|
error_handling::HandleRuntimeError("Type constructor pattern constructor name not found", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utils::IdType constructor_id = node->constructor->constructor_id_.value();
|
|
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
// only one has value inside
|
|
|
|
|
auto maybe_variant_value_info = context_manager_.GetValue<info::value::VariantValue>(current_value_);
|
|
|
|
|
auto maybe_tuple_value_info = context_manager_.GetValue<info::value::TupleValue>(current_value_);
|
2023-05-10 23:13:50 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
if (maybe_variant_value_info.has_value()) {
|
|
|
|
|
info::value::VariantValue* variant_value_info = maybe_variant_value_info.value();
|
|
|
|
|
|
|
|
|
|
if (constructor_id != variant_value_info->current_constructor) {
|
|
|
|
|
case_matched_ = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-05-10 23:13:50 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
// extract named parameters ??
|
|
|
|
|
for (size_t i = 0; i < node->parameters.size(); ++i) { // not visit if case not matched inside ??
|
|
|
|
|
current_value_ = variant_value_info->value.fields[i].second;
|
|
|
|
|
Visitor::Visit(node->parameters[i].value);
|
|
|
|
|
}
|
|
|
|
|
} else if (maybe_tuple_value_info.has_value()) {
|
|
|
|
|
info::value::TupleValue* tuple_value_info = maybe_tuple_value_info.value();
|
2023-05-10 23:13:50 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
// extract named parameters ??
|
|
|
|
|
for (size_t i = 0; i < node->parameters.size(); ++i) { // not visit if case not matched inside ??
|
|
|
|
|
current_value_ = tuple_value_info->fields[i].second;
|
|
|
|
|
Visitor::Visit(node->parameters[i].value);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
error_handling::HandleRuntimeError("Wrong value type for type constructor pattern (not variant or tuple)", node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(MatchCase* node) { // handeled in Match
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.MatchCase",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(Match* node) {
|
2023-05-09 23:36:47 +03:00
|
|
|
context_manager_.EnterContext();
|
|
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
Visitor::Visit(node->value);
|
2023-05-09 23:36:47 +03:00
|
|
|
|
|
|
|
|
utils::IdType value = current_value_;
|
|
|
|
|
|
|
|
|
|
bool case_choosen = false;
|
|
|
|
|
bool statement_visited = false;
|
2023-05-07 20:21:19 +03:00
|
|
|
for (auto& match_case : node->matches) {
|
2023-05-09 23:36:47 +03:00
|
|
|
if (case_choosen) {
|
|
|
|
|
if (match_case.statement.has_value()) {
|
|
|
|
|
Visitor::Visit(match_case.statement.value());
|
|
|
|
|
statement_visited = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
current_value_ = value;
|
|
|
|
|
case_matched_ = true;
|
|
|
|
|
|
|
|
|
|
context_manager_.EnterContext();
|
|
|
|
|
Visitor::Visit(node->value);
|
|
|
|
|
|
|
|
|
|
if (case_matched_ && (match_case.condition.has_value() ? HandleCondition(match_case.condition.value(), match_case.base) : true)) {
|
|
|
|
|
case_choosen = true;
|
|
|
|
|
if (match_case.statement.has_value()) {
|
|
|
|
|
Visitor::Visit(match_case.statement.value());
|
|
|
|
|
statement_visited = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
context_manager_.ExitContext();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 23:36:47 +03:00
|
|
|
|
|
|
|
|
if (case_choosen) {
|
|
|
|
|
context_manager_.ExitContext();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-13 22:40:33 +03:00
|
|
|
if (!statement_visited) {
|
|
|
|
|
error_handling::HandleRuntimeError("Value match option not found", node->base);
|
2023-05-09 23:36:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context_manager_.ExitContext();
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(Condition* node) {
|
2023-05-22 18:33:56 +03:00
|
|
|
bool branch_visited = false;
|
2023-05-07 20:21:19 +03:00
|
|
|
for (size_t i = 0; i < node->conditions.size(); ++i) {
|
2023-05-09 15:24:19 +03:00
|
|
|
if (HandleCondition(node->conditions[i], node->base)) {
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.EnterContext();
|
2023-05-07 20:21:19 +03:00
|
|
|
Visitor::Visit(node->statements[i]);
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.ExitContext();
|
2023-05-09 15:24:19 +03:00
|
|
|
|
|
|
|
|
if (node->statements.size() == node->conditions.size()) {
|
2023-05-22 18:33:56 +03:00
|
|
|
current_value_ = context_manager_.AddValue( // optional with "reference" to value
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::OptionalValue(current_value_, context_manager_.GetValueManager()),
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.GetValueType(current_value_));
|
2023-05-09 15:24:19 +03:00
|
|
|
}
|
2023-05-22 18:33:56 +03:00
|
|
|
branch_visited = true;
|
|
|
|
|
break;
|
2023-05-09 15:24:19 +03:00
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 23:36:47 +03:00
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
if (!branch_visited) {
|
|
|
|
|
if (node->statements.size() > node->conditions.size()) {
|
|
|
|
|
context_manager_.EnterContext();
|
|
|
|
|
Visitor::Visit(node->statements[node->conditions.size()]);
|
|
|
|
|
context_manager_.ExitContext();
|
|
|
|
|
} else {
|
|
|
|
|
current_value_ = context_manager_.AddValue( // optional with "reference" to value
|
|
|
|
|
info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()),
|
|
|
|
|
context_manager_.GetValueType(current_value_));
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(DoWhileLoop* node) {
|
2023-05-09 14:55:04 +03:00
|
|
|
std::vector<utils::IdType> result;
|
|
|
|
|
do {
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.EnterContext();
|
|
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
Visitor::Visit(node->statement);
|
|
|
|
|
if (active_loop_control_expression_.has_value()) {
|
|
|
|
|
if (active_loop_control_expression_.value() == LoopControlExpression::Break) {
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
}
|
2023-05-22 18:33:56 +03:00
|
|
|
result.push_back(context_manager_.ToTemporaryValue(current_value_));
|
|
|
|
|
|
|
|
|
|
context_manager_.ExitContext();
|
2023-05-09 14:55:04 +03:00
|
|
|
} while(HandleCondition(node->condition, node->base));
|
|
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
|
2023-05-09 14:55:04 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(WhileLoop* node) {
|
2023-05-09 14:55:04 +03:00
|
|
|
std::vector<utils::IdType> result;
|
|
|
|
|
while(HandleCondition(node->condition, node->base)) {
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.EnterContext();
|
|
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
Visitor::Visit(node->statement);
|
|
|
|
|
if (active_loop_control_expression_.has_value()) {
|
|
|
|
|
if (active_loop_control_expression_.value() == LoopControlExpression::Break) {
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
}
|
2023-05-22 18:33:56 +03:00
|
|
|
result.push_back(context_manager_.ToTemporaryValue(current_value_));
|
|
|
|
|
|
|
|
|
|
context_manager_.ExitContext();
|
2023-05-09 14:55:04 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
|
2023-05-09 14:55:04 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 23:36:47 +03:00
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
// TODO: extend to different interval types (not only array)
|
|
|
|
|
// TODO: assign to variable, instead of making new ??
|
|
|
|
|
void ExecuteVisitor::Visit(ForLoop* node) {
|
2023-05-09 14:55:04 +03:00
|
|
|
std::vector<utils::IdType> result;
|
|
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
Visitor::Visit(node->interval);
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::ArrayValue* interval = ExtractValue<info::value::ArrayValue>(current_value_, node->base);
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
for (auto& value : interval->elements) { // TODO: reference to element
|
|
|
|
|
context_manager_.EnterContext();
|
2023-05-20 00:01:54 +03:00
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
current_value_ = value;
|
2023-05-22 18:33:56 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
is_const_definition_ = node->variable_modifier;
|
2023-05-22 18:33:56 +03:00
|
|
|
Visitor::Visit(node->variable);
|
2023-05-20 00:01:54 +03:00
|
|
|
is_const_definition_ = std::nullopt;
|
2023-05-09 14:55:04 +03:00
|
|
|
|
|
|
|
|
Visitor::Visit(node->statement);
|
|
|
|
|
if (active_loop_control_expression_.has_value()) {
|
|
|
|
|
if (active_loop_control_expression_.value() == LoopControlExpression::Break) {
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
}
|
2023-05-22 18:33:56 +03:00
|
|
|
result.push_back(context_manager_.ToTemporaryValue(current_value_));
|
2023-05-20 00:01:54 +03:00
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.ExitContext();
|
2023-05-09 14:55:04 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
|
2023-05-09 14:55:04 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(LoopLoop* node) {
|
2023-05-09 14:55:04 +03:00
|
|
|
std::vector<utils::IdType> result;
|
|
|
|
|
while(true) {
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.EnterContext();
|
|
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
Visitor::Visit(node->statement);
|
|
|
|
|
if (active_loop_control_expression_.has_value()) {
|
|
|
|
|
if (active_loop_control_expression_.value() == LoopControlExpression::Break) {
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
active_loop_control_expression_ = std::nullopt;
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
}
|
2023-05-22 18:33:56 +03:00
|
|
|
result.push_back(context_manager_.ToTemporaryValue(current_value_));
|
|
|
|
|
|
|
|
|
|
context_manager_.ExitContext();
|
2023-05-09 14:55:04 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
|
2023-05-09 14:55:04 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Statements, expressions, blocks, etc. -----------------
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(Block* node) {
|
2023-05-09 15:24:19 +03:00
|
|
|
context_manager_.EnterContext();
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
bool value_brought = false;
|
|
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
for (auto& statement : node->statements) {
|
2023-05-21 11:58:23 +03:00
|
|
|
try {
|
|
|
|
|
Visitor::Visit(statement);
|
|
|
|
|
} catch (utils::ValueBroughtMarker&) { // current_value_ passed from ReturnExpression
|
|
|
|
|
value_brought = true;
|
2023-05-20 20:18:49 +03:00
|
|
|
break;
|
2023-05-09 14:55:04 +03:00
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-20 00:01:54 +03:00
|
|
|
|
2023-05-09 17:42:35 +03:00
|
|
|
context_manager_.ExitContext();
|
2023-05-09 15:24:19 +03:00
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
if (!value_brought) {
|
2023-05-20 20:18:49 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(ScopedStatement* node) {
|
2023-05-09 17:42:35 +03:00
|
|
|
Visitor::Visit(node->statement); // current_value_ passed from statement
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
void ExecuteVisitor::Visit(LoopControlExpression& node) {
|
|
|
|
|
active_loop_control_expression_ = node;
|
|
|
|
|
|
|
|
|
|
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()),
|
2023-05-20 20:18:49 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-09 14:55:04 +03:00
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
|
|
|
|
// Operators
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(ReferenceExpression* node) {
|
2023-05-09 17:42:35 +03:00
|
|
|
// TODO: check, that there is no references to "Tmp"??
|
2023-05-07 20:21:19 +03:00
|
|
|
Visit(node->expression.get());
|
2023-05-09 14:55:04 +03:00
|
|
|
|
|
|
|
|
utils::ValueType value_type = context_manager_.GetValueType(current_value_);
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
current_value_ = context_manager_.AddValue( // "reference" to type (save const / var)
|
2023-05-21 10:57:08 +03:00
|
|
|
info::value::ReferenceToValue({node->reference}, current_value_, context_manager_.GetValueManager()),
|
2023-05-09 14:55:04 +03:00
|
|
|
value_type);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 16:03:50 +03:00
|
|
|
// TODO: extend to other types
|
|
|
|
|
// TODO: string should be array
|
2023-05-07 20:21:19 +03:00
|
|
|
void ExecuteVisitor::Visit(AccessExpression* node) {
|
|
|
|
|
Visit(node->name.get());
|
2023-05-22 16:03:50 +03:00
|
|
|
utils::IdType array_value = current_value_;
|
|
|
|
|
utils::ValueType value_type = context_manager_.GetValueType(array_value);
|
2023-05-09 14:55:04 +03:00
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
Visitor::Visit(node->id);
|
2023-05-22 16:03:50 +03:00
|
|
|
int64_t index = *ExtractInternalValue<int64_t>(current_value_, node->base); // TODO: size_t
|
2023-05-09 14:55:04 +03:00
|
|
|
|
2023-05-22 16:03:50 +03:00
|
|
|
if (index < 0) {
|
|
|
|
|
error_handling::HandleRuntimeError("Access index is negative", node->base);
|
2023-05-09 14:55:04 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 16:03:50 +03:00
|
|
|
if (node->is_string_access_) {
|
|
|
|
|
std::string* string_value_info = ExtractInternalValue<std::string>(current_value_, node->base);
|
|
|
|
|
|
|
|
|
|
if (index >= (int64_t)string_value_info->size()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Access index is out of range (string)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
current_value_ = context_manager_.ToModifiedValue((*string_value_info)[index], utils::ValueType::Tmp);
|
2023-05-22 16:03:50 +03:00
|
|
|
} else {
|
|
|
|
|
info::value::ArrayValue* array_value_info = ExtractValue<info::value::ArrayValue>(current_value_, node->base);
|
|
|
|
|
|
|
|
|
|
if (index >= (int64_t)array_value_info->elements.size()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Access index is out of range (array)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_value_ = context_manager_.ToModifiedValue(array_value_info->elements[index], value_type);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Other Expressions
|
|
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
// TODO: refactor, separate to several functions
|
2023-05-07 20:21:19 +03:00
|
|
|
void ExecuteVisitor::Visit(FunctionCallExpression* node) {
|
2023-05-09 17:42:35 +03:00
|
|
|
context_manager_.EnterContext();
|
2023-05-18 22:27:55 +03:00
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
if (node->prefix.has_value()) {
|
|
|
|
|
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
|
|
|
|
|
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
|
2023-05-20 00:01:54 +03:00
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
if (context_manager_.GetValueType(current_value_) == utils::ValueType::Tmp) {
|
|
|
|
|
// temporary value can't be modified inside
|
|
|
|
|
context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
|
|
|
|
}
|
2023-05-20 00:01:54 +03:00
|
|
|
if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) {
|
|
|
|
|
error_handling::HandleRuntimeError("Variable redefinition (mathod caller var)", node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
|
2023-05-09 17:42:35 +03:00
|
|
|
TypeExpression& prefix = *std::get<std::unique_ptr<TypeExpression>>(node->prefix.value());
|
|
|
|
|
|
|
|
|
|
// TODO: abstract types, local abstract types, abstract types, ... as path entities
|
|
|
|
|
for (auto& path_type : prefix.path) {
|
|
|
|
|
CollectTypeContext(path_type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CollectTypeContext(prefix.type);
|
2023-05-07 20:21:19 +03:00
|
|
|
} else {
|
2023-05-20 00:01:54 +03:00
|
|
|
error_handling::HandleInternalError("Unexpected prefix type",
|
|
|
|
|
"ExecuteVisitor.FunctionCallExpression",
|
|
|
|
|
&node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-18 22:27:55 +03:00
|
|
|
} else {
|
|
|
|
|
if (node->is_method_of_first_argument_) {
|
|
|
|
|
Visitor::Visit(node->arguments[0]);
|
2023-05-22 18:33:56 +03:00
|
|
|
|
|
|
|
|
if (context_manager_.GetValueType(current_value_) == utils::ValueType::Tmp) {
|
|
|
|
|
// temporary value can't be modified inside
|
|
|
|
|
context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
|
|
|
|
}
|
2023-05-20 00:01:54 +03:00
|
|
|
if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) {
|
|
|
|
|
error_handling::HandleRuntimeError("Variable redefinition (mathod caller var)", node->base);
|
|
|
|
|
}
|
2023-05-18 22:27:55 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
FunctionDeclaration* function_declaration = nullptr;
|
|
|
|
|
FunctionDefinitionStatement* function_definition = nullptr;
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
if (node->function_id_.has_value()) {
|
|
|
|
|
auto maybe_function_declaration_info = global_info_.GetFunctionInfo(node->function_id_.value()).declaration;
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
if (!maybe_function_declaration_info.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Function declaration not found (for namespace function)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function_declaration = maybe_function_declaration_info.value().node;
|
|
|
|
|
|
|
|
|
|
auto maybe_function_definition_info = global_info_.GetFunctionInfo(node->function_id_.value()).definition;
|
|
|
|
|
|
|
|
|
|
if (!maybe_function_definition_info.has_value()) {
|
|
|
|
|
if (HandleBuiltinFunctionCall(node)) {
|
2023-05-22 16:03:50 +03:00
|
|
|
context_manager_.ExitContext();
|
2023-05-20 00:01:54 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function_definition = maybe_function_definition_info.value().node;
|
|
|
|
|
|
|
|
|
|
} else if (node->graph_id_.has_value()) {
|
|
|
|
|
std::optional<FunctionDefinitionStatement*> maybe_function_definition;
|
|
|
|
|
|
|
|
|
|
auto maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name,
|
|
|
|
|
node->graph_id_.value());
|
|
|
|
|
|
|
|
|
|
if (!maybe_function_graph_info.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Function info not found (by graph_id_)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function_declaration = maybe_function_graph_info.value()->declaration;
|
|
|
|
|
maybe_function_definition = maybe_function_graph_info.value()->definition;
|
|
|
|
|
|
|
|
|
|
if (!maybe_function_definition.has_value()) {
|
|
|
|
|
if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier == info::TypeclassGraph::Modifier::Type) {
|
2023-05-22 16:03:50 +03:00
|
|
|
auto maybe_internal_type = info::type::ToInternalType(typeclass_graph_.GetVertex(node->graph_id_.value()).name);
|
|
|
|
|
|
|
|
|
|
if (maybe_internal_type.has_value()) {
|
|
|
|
|
if (HandleBuiltinTypeFunctionCall(node, maybe_internal_type.value())) {
|
|
|
|
|
context_manager_.ExitContext();
|
2023-05-22 19:14:17 +03:00
|
|
|
return; // TODO: return from end of function
|
2023-05-22 16:03:50 +03:00
|
|
|
}
|
|
|
|
|
error_handling::HandleRuntimeError("Type function definition not found (builtin type)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
error_handling::HandleRuntimeError("Type function definition not found (by graph_id_)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!node->abstract_type_name_.has_value()) {
|
|
|
|
|
error_handling::HandleInternalError("Typeclass function's abstract_type_name_ has no value",
|
|
|
|
|
"ExecuteVisitor.FunctionCallExpression",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto maybe_type_id = context_manager_.FindLocalType(node->abstract_type_name_.value());
|
|
|
|
|
if (!maybe_type_id.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Function's abstract type not found (by abstract_type_name_)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(maybe_type_id.value());
|
|
|
|
|
|
|
|
|
|
if (!maybe_type_info.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Function's abstract type replacement defined type is not AnyType", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name, maybe_type_info.value()->type.node->graph_id_);
|
|
|
|
|
|
|
|
|
|
if (!maybe_function_graph_info.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Function info not found (by abstract type graph_id_)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maybe_function_definition = maybe_function_graph_info.value()->definition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!maybe_function_definition.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function_definition = maybe_function_definition.value();
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
for (size_t i = 0; i < node->parameters.size(); ++i) {
|
|
|
|
|
utils::IdType type_id = 0;
|
|
|
|
|
|
|
|
|
|
if (node->parameters[i]->type_id_.has_value()) {
|
|
|
|
|
type_id = node->parameters[i]->type_id_.value();
|
|
|
|
|
} else {
|
|
|
|
|
auto maybe_parameter_type_id = context_manager_.FindLocalType(node->parameters[i]->type.type);
|
|
|
|
|
|
|
|
|
|
if (!maybe_parameter_type_id.has_value()) {
|
|
|
|
|
error_handling::HandleInternalError("Parameter type not found",
|
|
|
|
|
"ExecuteVisitor.FunctionCallExpression",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-09 17:42:35 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
type_id = maybe_parameter_type_id.value();
|
2023-05-09 17:42:35 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
if (!context_manager_.DefineLocalType(function_declaration->parameters[i]->type, type_id)) {
|
2023-05-20 00:01:54 +03:00
|
|
|
error_handling::HandleRuntimeError("Type redefinition (function argument)", node->base);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = (node->is_method_of_first_argument_ ? 1 : 0); i < node->arguments.size(); ++i) {
|
|
|
|
|
Visitor::Visit(node->arguments[i]);
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
// function arguments can't be changed inside function
|
2023-05-20 00:01:54 +03:00
|
|
|
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
|
|
|
|
if (!context_manager_.DefineVariable(function_definition->definition->arguments[i],
|
|
|
|
|
current_value_)) {
|
|
|
|
|
error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 17:42:35 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
context_manager_.ChangeHidingOfCurrentContextTo(true);
|
|
|
|
|
Visit(function_definition);
|
|
|
|
|
|
2023-05-09 17:42:35 +03:00
|
|
|
context_manager_.ExitContext();
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(TupleExpression* node) {
|
2023-05-09 14:55:04 +03:00
|
|
|
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
|
|
|
|
|
fields.reserve(node->expressions.size());
|
2023-05-07 20:21:19 +03:00
|
|
|
for (auto& expression : node->expressions) {
|
|
|
|
|
Visitor::Visit(expression);
|
2023-05-22 18:33:56 +03:00
|
|
|
fields.push_back({std::nullopt, context_manager_.ToTemporaryValue(current_value_)});
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 14:55:04 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
|
2023-05-09 15:24:19 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
// TODO: handle tuples separately ??
|
2023-05-09 17:42:35 +03:00
|
|
|
void ExecuteVisitor::Visit(VariantExpression* node) {
|
2023-05-09 23:36:47 +03:00
|
|
|
for (size_t i = 0; i < node->expressions.size(); ++i) {
|
|
|
|
|
Visitor::Visit(node->expressions[i]);
|
2023-05-22 18:33:56 +03:00
|
|
|
current_value_ = context_manager_.ToTemporaryValue(current_value_);
|
|
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::OptionalValue* expression_value = ExtractValue<info::value::OptionalValue>(current_value_, node->base);
|
|
|
|
|
if (expression_value->value.has_value()) {
|
2023-05-10 23:13:50 +03:00
|
|
|
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields
|
2023-05-22 18:33:56 +03:00
|
|
|
{{std::nullopt, expression_value->value.value()}}; // TODO: any type instead tuple in variant type ??
|
2023-05-10 23:13:50 +03:00
|
|
|
|
|
|
|
|
info::value::TupleValue variant_tuple =
|
|
|
|
|
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager());
|
|
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-10 23:13:50 +03:00
|
|
|
info::value::VariantValue(std::move(variant_tuple), i),
|
2023-05-09 17:42:35 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-09 14:55:04 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::OptionalValue(current_value_, context_manager_.GetValueManager()),
|
2023-05-09 17:42:35 +03:00
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
return;
|
2023-05-09 14:55:04 +03:00
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 17:42:35 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-10 23:13:50 +03:00
|
|
|
info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()),
|
2023-05-09 17:42:35 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(ReturnExpression* node) {
|
|
|
|
|
Visitor::Visit(node->expression);
|
2023-05-20 20:18:49 +03:00
|
|
|
if (node->is_from_definition) {
|
2023-05-21 11:58:23 +03:00
|
|
|
throw utils::ValueReturnedMarker();
|
2023-05-20 20:18:49 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
throw utils::ValueBroughtMarker();
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(TypeConstructorParameter* node) { // handled in TypeConstructor
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.TypeConstructorParameter",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-09 23:36:47 +03:00
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
void ExecuteVisitor::Visit(TypeConstructor* node) {
|
2023-05-09 23:36:47 +03:00
|
|
|
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
|
|
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
if (!node->constructor->constructor_id_.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Type constructor name not found", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utils::IdType constructor_id = node->constructor->constructor_id_.value();
|
|
|
|
|
info::definition::Constructor constructor_info = global_info_.GetConstructorInfo(constructor_id);
|
|
|
|
|
|
2023-05-09 23:36:47 +03:00
|
|
|
fields.reserve(node->parameters.size());
|
2023-05-07 20:21:19 +03:00
|
|
|
for (auto& parameter : node->parameters) {
|
2023-05-09 23:36:47 +03:00
|
|
|
Visitor::Visit(parameter.value);
|
|
|
|
|
fields.push_back(
|
2023-05-13 13:11:12 +03:00
|
|
|
{ parameter.name.has_value() ? std::optional<std::string>(parameter.name.value()) : std::nullopt,
|
2023-05-22 18:33:56 +03:00
|
|
|
context_manager_.ToTemporaryValue(current_value_) });
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 23:36:47 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
if (constructor_info.order.has_value()) { // => variant
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::VariantValue(
|
|
|
|
|
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
|
|
|
|
|
constructor_info.order.value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else { // => tuple
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
// TODO
|
2023-05-20 00:01:54 +03:00
|
|
|
void ExecuteVisitor::Visit(LambdaFunction* node) {
|
2023-05-09 14:55:04 +03:00
|
|
|
error_handling::HandleInternalError("Lambda function are not implemented yet",
|
2023-05-20 00:01:54 +03:00
|
|
|
"ExecuteVisitor.LambdaFunction",
|
|
|
|
|
&node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(ArrayExpression* node) {
|
2023-05-09 15:24:19 +03:00
|
|
|
std::vector<utils::IdType> elements;
|
|
|
|
|
|
|
|
|
|
elements.reserve(node->elements.size());
|
2023-05-07 20:21:19 +03:00
|
|
|
for (auto& element : node->elements) {
|
|
|
|
|
Visitor::Visit(element);
|
2023-05-22 18:33:56 +03:00
|
|
|
elements.push_back(context_manager_.ToTemporaryValue(current_value_));
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 15:24:19 +03:00
|
|
|
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 23:36:47 +03:00
|
|
|
info::value::ArrayValue(std::move(elements), true, context_manager_.GetValueManager()), // maybe size not fixed??
|
2023-05-09 15:24:19 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Name
|
|
|
|
|
|
2023-05-09 17:47:43 +03:00
|
|
|
void ExecuteVisitor::Visit(NameExpression* node) { // TODO: check
|
2023-05-09 17:42:35 +03:00
|
|
|
if (node->names.empty()) {
|
2023-05-20 00:01:54 +03:00
|
|
|
error_handling::HandleInternalError("Names array is empty",
|
|
|
|
|
"ExecuteVisitor.NameExpression",
|
|
|
|
|
&node->base);
|
2023-05-09 17:42:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<utils::IdType> maybe_variable_value =
|
2023-05-20 00:01:54 +03:00
|
|
|
context_manager_.FindVariable(node->names[0]);
|
2023-05-09 17:42:35 +03:00
|
|
|
|
|
|
|
|
if (!maybe_variable_value.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Variable not found", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_value_ = maybe_variable_value.value();
|
|
|
|
|
|
|
|
|
|
if (node->names.size() > 1) {
|
|
|
|
|
utils::ValueType variable_value_type = context_manager_.GetValueType(current_value_);
|
|
|
|
|
|
|
|
|
|
for (size_t i = 1; i < node->names.size(); ++i) {
|
2023-05-22 18:33:56 +03:00
|
|
|
std::optional<utils::IdType> maybe_field_value = context_manager_.GetAnyValue(current_value_)->GetFieldValue(node->names[i]);
|
2023-05-09 17:42:35 +03:00
|
|
|
if (!maybe_field_value.has_value()) {
|
2023-05-13 13:11:12 +03:00
|
|
|
error_handling::HandleRuntimeError("Variable field not found", node->base);
|
2023-05-09 17:42:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_value_ = maybe_field_value.value();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_value_ = context_manager_.ToModifiedValue(current_value_, variable_value_type);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
void ExecuteVisitor::Visit(TupleName* node) {
|
2023-05-09 17:42:35 +03:00
|
|
|
utils::IdType value = current_value_;
|
|
|
|
|
|
|
|
|
|
std::optional<info::value::TupleValue*> maybe_tuple_value = context_manager_.GetValue<info::value::TupleValue>(value);
|
|
|
|
|
|
|
|
|
|
if (maybe_tuple_value.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Mismatched value types in tuple variable definition", node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (maybe_tuple_value.value()->fields.size() != node->names.size()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Mismatched field count in tuple variable definition", node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 17:42:35 +03:00
|
|
|
|
|
|
|
|
for (size_t i = 0; i < node->names.size(); ++i) {
|
|
|
|
|
current_value_ = maybe_tuple_value.value()->fields[i].second;
|
|
|
|
|
|
|
|
|
|
Visitor::Visit(node->names[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_value_ = value;
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-09 17:42:35 +03:00
|
|
|
// TODO
|
2023-05-09 23:36:47 +03:00
|
|
|
// TODO: make variant of TupleValue
|
2023-05-07 20:21:19 +03:00
|
|
|
void ExecuteVisitor::Visit(VariantName* node) {
|
2023-05-09 17:42:35 +03:00
|
|
|
utils::IdType value = current_value_;
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
auto value_type = context_manager_.GetValueType(value);
|
|
|
|
|
|
2023-05-09 17:42:35 +03:00
|
|
|
std::optional<info::value::VariantValue*> maybe_variant_value = context_manager_.GetValue<info::value::VariantValue>(value);
|
|
|
|
|
|
|
|
|
|
if (!maybe_variant_value.has_value()) {
|
|
|
|
|
error_handling::HandleRuntimeError("Mismatched value types in variant variable definition", node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
2023-05-09 17:42:35 +03:00
|
|
|
|
2023-05-09 23:36:47 +03:00
|
|
|
for (size_t i = 0; i < node->names.size(); ++i) {
|
|
|
|
|
if (i == maybe_variant_value.value()->current_constructor) {
|
2023-05-10 23:13:50 +03:00
|
|
|
if (maybe_variant_value.value()->value.fields.empty()) {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
2023-05-22 18:33:56 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-10 23:13:50 +03:00
|
|
|
} else {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
maybe_variant_value.value()->value,
|
2023-05-22 18:33:56 +03:00
|
|
|
value_type);
|
2023-05-10 23:13:50 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
current_value_ = context_manager_.AddValue( // make optional value "reference"
|
2023-05-10 23:13:50 +03:00
|
|
|
info::value::OptionalValue(current_value_, context_manager_.GetValueManager()),
|
2023-05-22 18:33:56 +03:00
|
|
|
value_type);
|
2023-05-09 23:36:47 +03:00
|
|
|
} else {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-10 23:13:50 +03:00
|
|
|
info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()),
|
2023-05-22 18:33:56 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-09 23:36:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Visitor::Visit(node->names[i]);
|
|
|
|
|
}
|
2023-05-09 17:42:35 +03:00
|
|
|
|
|
|
|
|
current_value_ = value;
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
// TODO: move, etc.
|
|
|
|
|
void ExecuteVisitor::Visit(AnnotatedName* node) {
|
2023-05-09 17:42:35 +03:00
|
|
|
if (!is_const_definition_.has_value()) {
|
|
|
|
|
error_handling::HandleInternalError("No value in is_const_definition_",
|
2023-05-20 00:01:54 +03:00
|
|
|
"TypeCheckVisitor.AnnotatedName",
|
|
|
|
|
&node->base);
|
2023-05-09 17:42:35 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
auto value_type = context_manager_.GetValueType(current_value_);
|
2023-05-22 16:03:50 +03:00
|
|
|
|
2023-05-22 18:33:56 +03:00
|
|
|
if (value_type == utils::ValueType::Tmp) {
|
|
|
|
|
// consume temporary value
|
|
|
|
|
context_manager_.ModifiyValue(current_value_, IsConstModifierToValueType(is_const_definition_.value()));
|
|
|
|
|
} else {
|
|
|
|
|
// make value copy
|
|
|
|
|
current_value_ = context_manager_.ToModifiedValueCopy(current_value_, IsConstModifierToValueType(is_const_definition_.value()));
|
|
|
|
|
}
|
2023-05-09 17:42:35 +03:00
|
|
|
|
|
|
|
|
if (!context_manager_.DefineVariable(node->name, current_value_)) {
|
|
|
|
|
error_handling::HandleRuntimeError("Variable name already present in context", node->base);
|
2023-05-07 20:21:19 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type, typeclass, etc. -----------------
|
|
|
|
|
|
|
|
|
|
// Type
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(FunctionType* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.FunctionType",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(TupleType* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.TupleType",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(VariantType* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.VariantType",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(TypeExpression* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.TypeExpression",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::Visit(ExtendedScopedAnyType* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.ExtendedScopedAnyType",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
|
|
|
|
// Typeclass
|
|
|
|
|
|
2023-05-21 11:58:23 +03:00
|
|
|
void ExecuteVisitor::Visit(ParametrizedTypeclass* node) {
|
|
|
|
|
error_handling::HandleInternalError("Should be unreachable",
|
|
|
|
|
"TypeCheckVisitor.ParametrizedTypeclass",
|
|
|
|
|
&node->base);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
|
|
|
|
// Typeclass & Type -----------------
|
|
|
|
|
|
2023-05-19 10:27:14 +03:00
|
|
|
void ExecuteVisitor::Visit(ParametrizedType*) {} // no value
|
2023-05-07 20:21:19 +03:00
|
|
|
|
|
|
|
|
// Identifiers, constants, etc. -----------------
|
|
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
void ExecuteVisitor::Visit(FloatNumberLiteral* node) {
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::InternalValue(node->value),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
void ExecuteVisitor::Visit(NumberLiteral* node) {
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::InternalValue(node->value),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
void ExecuteVisitor::Visit(StringLiteral* node) {
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::InternalValue(node->value),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
void ExecuteVisitor::Visit(CharLiteral* node) {
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::InternalValue(node->value),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-19 10:27:14 +03:00
|
|
|
void ExecuteVisitor::Visit(UnitLiteral*) {
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
void ExecuteVisitor::Visit(BoolLiteral* node) {
|
2023-05-18 20:56:03 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
2023-05-09 14:55:04 +03:00
|
|
|
info::value::InternalValue(node->value),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
2023-05-07 20:21:19 +03:00
|
|
|
|
2023-05-09 14:55:04 +03:00
|
|
|
bool ExecuteVisitor::HandleCondition(Expression& node, const BaseNode& base_node) {
|
|
|
|
|
Visitor::Visit(node);
|
|
|
|
|
return *ExtractInternalValue<bool>(current_value_, base_node);
|
|
|
|
|
}
|
2023-05-08 20:34:36 +03:00
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
// TODO: handle abstract types, handle local abstract types, etc. // partially done (check needed)
|
2023-05-09 17:42:35 +03:00
|
|
|
void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) {
|
2023-05-20 00:01:54 +03:00
|
|
|
utils::IdType type_id = 0;
|
|
|
|
|
|
2023-05-09 17:42:35 +03:00
|
|
|
if (!type.type_id_.has_value()) {
|
2023-05-20 00:01:54 +03:00
|
|
|
auto maybe_local_type_id = context_manager_.FindLocalType(type.type);
|
|
|
|
|
if (!maybe_local_type_id.has_value()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
type_id = maybe_local_type_id.value(); // TODO: check
|
|
|
|
|
} else {
|
|
|
|
|
type_id = type.type_id_.has_value();
|
2023-05-09 17:42:35 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(type_id);
|
2023-05-09 17:42:35 +03:00
|
|
|
|
|
|
|
|
if (!maybe_type_info.has_value()) {
|
2023-05-20 00:01:54 +03:00
|
|
|
error_handling::HandleInternalError("CollectTypeContext implemented only for AnyType",
|
|
|
|
|
"ExecuteVisitor.CollectTYpeContext",
|
|
|
|
|
std::nullopt);
|
2023-05-09 17:42:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info::definition::AnyType& type_info = *maybe_type_info.value(); // check, that has value ??
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < type.parameters.size(); ++i) {
|
|
|
|
|
if (type.parameters[i]->type_id_.has_value()) {
|
|
|
|
|
context_manager_.DefineLocalType(type_info.parameters[i].type,
|
|
|
|
|
type.parameters[i]->type_id_.value());
|
2023-05-09 23:36:47 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
|
|
|
|
|
utils::IdType value = current_value_;
|
|
|
|
|
|
|
|
|
|
switch (node.index()) {
|
|
|
|
|
case 0:
|
2023-05-22 18:33:56 +03:00
|
|
|
// always copy, because case can not match value
|
|
|
|
|
value = context_manager_.ToModifiedValueCopy(value, utils::ValueType::Const);
|
2023-05-13 13:11:12 +03:00
|
|
|
if (!context_manager_.DefineVariable(*std::get<std::unique_ptr<NameIdentifier>>(node),
|
2023-05-09 23:36:47 +03:00
|
|
|
value)) {
|
|
|
|
|
error_handling::HandleRuntimeError("Can't redifine variable", base_node);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
Visitor::Visit(*std::get<std::unique_ptr<Literal>>(node));
|
2023-05-18 20:56:03 +03:00
|
|
|
if (!context_manager_.EqualValues(current_value_, value)) {
|
2023-05-18 20:11:26 +03:00
|
|
|
case_matched_ = false;
|
|
|
|
|
}
|
2023-05-09 23:36:47 +03:00
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
Visit(std::get<std::unique_ptr<TypeConstructorPattern>>(node).get());
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
// error
|
|
|
|
|
break;
|
2023-05-09 17:42:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) {
|
|
|
|
|
if (node->name == "print") {
|
|
|
|
|
Visitor::Visit(node->arguments[0]);
|
|
|
|
|
info::builtin::Print(*ExtractInternalValue<std::string>(current_value_, node->base));
|
|
|
|
|
|
|
|
|
|
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
2023-05-21 14:58:18 +03:00
|
|
|
} else if (node->name == "scan") {
|
2023-05-20 00:01:54 +03:00
|
|
|
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::builtin::Read<std::string>()),
|
|
|
|
|
utils::ValueType::Tmp);
|
2023-05-22 18:33:56 +03:00
|
|
|
} else if (node->name == "random") { // TODO: different types, better random, seed, etc.
|
2023-05-22 16:03:50 +03:00
|
|
|
current_value_ = context_manager_.AddValue(info::value::InternalValue(rand()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
2023-05-20 00:01:54 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 16:03:50 +03:00
|
|
|
return true;
|
2023-05-20 00:01:54 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 16:03:50 +03:00
|
|
|
bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node,
|
|
|
|
|
info::type::InternalType type) {
|
|
|
|
|
const std::string& name = node->name;
|
|
|
|
|
|
2023-05-22 19:14:17 +03:00
|
|
|
error_handling::DebugPrint(name);
|
|
|
|
|
|
2023-05-22 16:03:50 +03:00
|
|
|
if (utils::IsBuiltinFunction(name)) {
|
|
|
|
|
std::vector<info::value::InternalValue*> arguments;
|
|
|
|
|
arguments.reserve(node->arguments.size());
|
|
|
|
|
|
|
|
|
|
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
|
|
|
|
|
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
|
|
|
|
|
arguments.push_back(ExtractValue<info::value::InternalValue>(current_value_, node->base));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& argument : node->arguments) {
|
|
|
|
|
Visitor::Visit(argument);
|
|
|
|
|
arguments.push_back(ExtractValue<info::value::InternalValue>(current_value_, node->base));
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-22 19:14:17 +03:00
|
|
|
error_handling::DebugPrint(info::type::ToString(type));
|
|
|
|
|
std::cout << std::endl;
|
2023-05-22 16:03:50 +03:00
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case info::type::InternalType::Float:
|
|
|
|
|
if (name == "show") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(std::to_string(*arguments[0]->GetValue<double>().value())),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "<") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<double>().value() < *arguments[1]->GetValue<double>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "==") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<double>().value() == *arguments[1]->GetValue<double>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "zero") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(0.0),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "one") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(1.0),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "+=") {
|
2023-05-22 19:14:17 +03:00
|
|
|
*arguments[0]->GetValue<double>().value() += *arguments[1]->GetValue<double>().value();
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "-=") {
|
|
|
|
|
*arguments[0]->GetValue<double>().value() -= *arguments[1]->GetValue<double>().value();
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "*=") {
|
|
|
|
|
*arguments[0]->GetValue<double>().value() *= *arguments[1]->GetValue<double>().value();
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "/=") {
|
|
|
|
|
*arguments[0]->GetValue<double>().value() /= *arguments[1]->GetValue<double>().value();
|
2023-05-22 16:03:50 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case info::type::InternalType::Int:
|
|
|
|
|
if (name == "show") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(std::to_string(*arguments[0]->GetValue<int64_t>().value())),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "<") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() < *arguments[1]->GetValue<int64_t>().value()),
|
2023-05-22 18:33:56 +03:00
|
|
|
utils::ValueType::Tmp);
|
2023-05-22 16:03:50 +03:00
|
|
|
} else if (name == "==") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() == *arguments[1]->GetValue<int64_t>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "div") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() / *arguments[1]->GetValue<int64_t>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
2023-05-22 19:14:17 +03:00
|
|
|
} else if (name == "mod") { // TODO: better implementation of mod (read % specification)
|
2023-05-22 16:03:50 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() % *arguments[1]->GetValue<int64_t>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "zero") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(0),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "one") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(1),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "+=") {
|
2023-05-22 19:14:17 +03:00
|
|
|
*arguments[0]->GetValue<int64_t>().value() += *arguments[1]->GetValue<int64_t>().value();
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "-=") {
|
|
|
|
|
*arguments[0]->GetValue<int64_t>().value() += *arguments[1]->GetValue<int64_t>().value();
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "*=") {
|
|
|
|
|
*arguments[0]->GetValue<int64_t>().value() += *arguments[1]->GetValue<int64_t>().value();
|
2023-05-22 16:03:50 +03:00
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(info::value::Unit()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case info::type::InternalType::String: // TODO: string is array ??
|
|
|
|
|
if (name == "show") { // do not copy ??
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<std::string>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "<") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<std::string>().value() < *arguments[1]->GetValue<std::string>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "==") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<std::string>().value() == *arguments[1]->GetValue<std::string>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "size") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(static_cast<int64_t>(arguments[0]->GetValue<std::string>().value()->size())),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "at") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue((*arguments[0]->GetValue<std::string>().value())[*arguments[1]->GetValue<int64_t>().value()]),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case info::type::InternalType::Char:
|
|
|
|
|
if (name == "show") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(std::string{*arguments[0]->GetValue<char>().value()}),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "<") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<char>().value() < *arguments[1]->GetValue<char>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else if (name == "==") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<char>().value() == *arguments[1]->GetValue<char>().value()),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case info::type::InternalType::Bool:
|
|
|
|
|
if (name == "show") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue(*arguments[0]->GetValue<bool>().value() ? "true" : "false"),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case info::type::InternalType::Unit:
|
|
|
|
|
if (name == "show") {
|
|
|
|
|
current_value_ = context_manager_.AddValue(
|
|
|
|
|
info::value::InternalValue("()"),
|
|
|
|
|
utils::ValueType::Tmp);
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
// error
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-20 00:01:54 +03:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-07 20:21:19 +03:00
|
|
|
} // namespace interpreter
|
|
|
|
|
|