// for clangd #include "../include/execute_visitor.hpp" #include #include #include // TODO namespace interpreter { // Sources ----------------- void ExecuteVisitor::Visit(SourceFile* node) { // never used ?? for (auto& statement : node->statements) { Visitor::Visit(statement); } } // Namespaces, partitions ----------------- void ExecuteVisitor::Visit(NamespaceSources* node) { // never used ?? for (auto& statement : node->statements) { Visitor::Visit(statement); } } void ExecuteVisitor::Visit(Namespace* node) { // never used ?? // Visit(&node->type); Visit(&node->scope); } // Definitions ----------------- void ExecuteVisitor::Visit(ImportStatement* node) {} // no value void ExecuteVisitor::Visit(AliasDefinitionStatement* node) {} // no value void ExecuteVisitor::Visit(VariableDefinitionStatement* node) { // visited on function call Visitor::Visit(node->value); is_const_definition_ = node->modifier; Visitor::Visit(node->name); // current_type_ passed from value is_const_definition_ = std::nullopt; } void ExecuteVisitor::Visit(FunctionDeclaration* node) {} // no value void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { // visited on function call // Visit(node->definition.get()); Visitor::Visit(node->value); } void ExecuteVisitor::Visit(TypeDefinitionStatement* node) {} // no value void ExecuteVisitor::Visit(AbstractTypeDefinitionStatement* node) {} // no value void ExecuteVisitor::Visit(TypeclassDefinitionStatement* node) {} // no value void ExecuteVisitor::Visit(PartitionStatement* node) { Visitor::Visit(node->value); } // Flow control ----------------- void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern // TODO void ExecuteVisitor::Visit(TypeConstructorPattern* node) { // TODO: not only tuples Visit(node->constructor.get()); // TODO: ?? check is same constructor_id ?? for (auto& parameter : node->parameters) { // TODO: pass parameters separately Visitor::Visit(parameter.value); // handle TypeConstructorPatternParameter } } void ExecuteVisitor::Visit(MatchCase* node) {} // handeled in Match void ExecuteVisitor::Visit(Match* node) { context_manager_.EnterContext(); Visitor::Visit(node->value); utils::IdType value = current_value_; bool case_choosen = false; bool statement_visited = false; for (auto& match_case : node->matches) { 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(); } } } if (case_choosen) { context_manager_.ExitContext(); } if (statement_visited) { current_value_ = context_manager_.AddValue( info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), utils::ValueType::Tmp); } else { current_value_ = context_manager_.AddValue( info::value::OptionalValue(context_manager_.GetValueManager()), utils::ValueType::Tmp); } context_manager_.ExitContext(); } void ExecuteVisitor::Visit(Condition* node) { context_manager_.EnterContext(); for (size_t i = 0; i < node->conditions.size(); ++i) { if (HandleCondition(node->conditions[i], node->base)) { Visitor::Visit(node->statements[i]); if (node->statements.size() == node->conditions.size()) { current_value_ = context_manager_.AddValue( info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), utils::ValueType::Tmp); // take value type from current_value_ ?? } return; // current_value_ passed from statement } } if (node->statements.size() > node->conditions.size()) { Visitor::Visit(node->statements[node->conditions.size()]); } else { current_value_ = context_manager_.AddValue( info::value::OptionalValue(context_manager_.GetValueManager()), utils::ValueType::Tmp); } context_manager_.ExitContext(); } void ExecuteVisitor::Visit(DoWhileLoop* node) { context_manager_.EnterContext(); std::vector result; do { 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; } result.push_back(current_value_); } while(HandleCondition(node->condition, node->base)); current_value_ = context_manager_.AddValue( info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); context_manager_.ExitContext(); } void ExecuteVisitor::Visit(WhileLoop* node) { context_manager_.EnterContext(); std::vector result; while(HandleCondition(node->condition, node->base)) { 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; } result.push_back(current_value_); } current_value_ = context_manager_.AddValue( info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); context_manager_.ExitContext(); } void ExecuteVisitor::Visit(ForLoop* node) { context_manager_.EnterContext(); std::vector result; // TODO: extend to different interval types (not only array) Visitor::Visit(node->interval); info::value::ArrayValue* interval = ExtractValue(current_value_, node->base); for (auto& value : interval->elements) { current_value_ = value; Visitor::Visit(node->variable); 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; } result.push_back(current_value_); } current_value_ = context_manager_.AddValue( info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); context_manager_.ExitContext(); } void ExecuteVisitor::Visit(LoopLoop* node) { context_manager_.EnterContext(); std::vector result; while(true) { 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; } result.push_back(current_value_); } current_value_ = context_manager_.AddValue( info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); context_manager_.ExitContext(); } // Statements, expressions, blocks, etc. ----------------- void ExecuteVisitor::Visit(Block* node) { context_manager_.EnterContext(); for (auto& statement : node->statements) { return_value_ = std::nullopt; Visitor::Visit(statement); if (return_value_.has_value()) { current_value_ = return_value_.value(); return; } } context_manager_.ExitContext(); current_value_ = context_manager_.AddValue( info::value::InternalValue(info::value::Unit()), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(ScopedStatement* node) { Visitor::Visit(node->statement); // current_value_ passed from statement } void ExecuteVisitor::Visit(LoopControlExpression& node) { active_loop_control_expression_ = node; current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()), utils::ValueType::Tmp); // ?? } // Operators void ExecuteVisitor::Visit(BinaryOperatorExpression* node) { context_manager_.EnterContext(); auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition; if (maybe_function_definition.has_value()) { Visitor::Visit(node->left_expression); // TODO: custom argument value types, references, etc. current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); context_manager_.DefineVariable( node->is_method_ ? utils::ClassInternalVarName : maybe_function_definition.value().argument_names[0], current_value_); Visitor::Visit(node->left_expression); // TODO: custom argument value types, references, etc. current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); context_manager_.DefineVariable(maybe_function_definition.value().argument_names[node->is_method_ ? 0 : 1], current_value_); Visit(maybe_function_definition.value().node); } else { // TODO: builtin operators, etc. (imports?) error_handling::HandleRuntimeError("Binary operator definition not found", node->base); } context_manager_.ExitContext(); } // TODO: methods?? void ExecuteVisitor::Visit(UnaryOperatorExpression* node) { context_manager_.EnterContext(); auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition; if (maybe_function_definition.has_value()) { Visitor::Visit(node->expression); // TODO: custom argument value types, references, etc. current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); context_manager_.DefineVariable(maybe_function_definition.value().argument_names[0], current_value_); Visit(maybe_function_definition.value().node); } else { // TODO: builtin operators, etc. (imports?) error_handling::HandleRuntimeError("Unary operator definition not found", node->base); } context_manager_.ExitContext(); } void ExecuteVisitor::Visit(ReferenceExpression* node) { // TODO: check, that there is no references to "Tmp"?? Visit(node->expression.get()); utils::ValueType value_type = context_manager_.GetValueType(current_value_); current_value_ = context_manager_.AddValue( info::value::ReferenceToValue(node->references, current_value_, context_manager_.GetValueManager()), value_type); } void ExecuteVisitor::Visit(AccessExpression* node) { // TODO: extend to other types Visit(node->name.get()); info::value::ArrayValue* array_value = ExtractValue(current_value_, node->base); utils::ValueType value_type = context_manager_.GetValueType(current_value_); Visitor::Visit(node->id); long long index = *ExtractInternalValue(current_value_, node->base); // TODO: size_t if (index < 0 || index >= array_value->elements.size()) { error_handling::HandleRuntimeError("Access index out of range", node->base); } current_value_ = context_manager_.ToModifiedValue(array_value->elements[index], value_type); // needed ?? } // Other Expressions void ExecuteVisitor::Visit(FunctionCallExpression* node) { context_manager_.EnterContext(); if (node->prefix.has_value()) { if (std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); // modify value on const methods, etc. ?? context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_); } else if (std::holds_alternative>(node->prefix.value())) { TypeExpression& prefix = *std::get>(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); } else { // error } } auto function_declaration = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).declaration.value(); // checked in type_check_visitor for (size_t i = 0; i < node->parameters.size(); ++i) { // TODO: local bastract types, absract types, etc. context_manager_.DefineLocalType(function_declaration.parameters[i].type, node->parameters[i]->type_id_.value()); // TODO: check } auto maybe_function_definition = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_).definition; if (maybe_function_definition.has_value()) { for (size_t i = 0; i < node->arguments.size(); ++i) { Visitor::Visit(node->arguments[i]); // TODO: custom argument value types, references, etc. current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); context_manager_.DefineVariable(maybe_function_definition.value().argument_names[i], current_value_); } Visit(maybe_function_definition.value().node); } else { // TODO: builtin functions, etc. (imports?) error_handling::HandleRuntimeError("Function definition not found", node->base); } context_manager_.ExitContext(); } void ExecuteVisitor::Visit(TupleExpression* node) { std::vector, utils::IdType>> fields; fields.reserve(node->expressions.size()); for (auto& expression : node->expressions) { Visitor::Visit(expression); fields.push_back({std::nullopt, current_value_}); } current_value_ = context_manager_.AddValue( info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(VariantExpression* node) { // TODO: decide about return type (variant) for (size_t i = 0; i < node->expressions.size(); ++i) { Visitor::Visit(node->expressions[i]); info::value::OptionalValue* expression_value = ExtractValue(current_value_, node->base); if (expression_value->value.has_value()) { current_value_ = context_manager_.AddValue( info::value::VariantValue(expression_value->value.value(), i, context_manager_.GetValueManager()), utils::ValueType::Tmp); current_value_ = context_manager_.AddValue( info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), utils::ValueType::Tmp); return; } } current_value_ = context_manager_.AddValue( info::value::OptionalValue(context_manager_.GetValueManager()), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(ReturnExpression* node) { Visitor::Visit(node->expression); return_value_ = current_value_; } void ExecuteVisitor::Visit(TypeConstructorParameter* node) {} // handled in TypeConstructor void ExecuteVisitor::Visit(TypeConstructor* node) { // TODO: support for non-tuples std::vector, utils::IdType>> fields; // Visit(node->constructor.get()); // use parameters from type expression ?? fields.reserve(node->parameters.size()); for (auto& parameter : node->parameters) { Visitor::Visit(parameter.value); // TODO: copy/move parameters fields.push_back( { parameter.name.has_value() ? std::optional(parameter.name.value().name) : std::nullopt, current_value_ }); } current_value_ = context_manager_.AddValue( info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), utils::ValueType::Tmp); } // TODO void ExecuteVisitor::Visit(LambdaFunction* node) { error_handling::HandleInternalError("Lambda function are not implemented yet", "ExecuteVisitor.LambdaFunction"); } void ExecuteVisitor::Visit(ArrayExpression* node) { std::vector elements; elements.reserve(node->elements.size()); for (auto& element : node->elements) { Visitor::Visit(element); elements.push_back(current_value_); } current_value_ = context_manager_.AddValue( info::value::ArrayValue(std::move(elements), true, context_manager_.GetValueManager()), // maybe size not fixed?? utils::ValueType::Tmp); } // Name void ExecuteVisitor::Visit(NameExpression* node) { // TODO: check if (node->names.empty()) { error_handling::HandleInternalError("Names array is empty", "ExecuteVisitor.NameExpression"); } std::optional maybe_variable_value = context_manager_.GetVariableInfo(node->names[0].name); 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) { std::optional maybe_field_value = context_manager_.GetAnyValue(current_value_)->GetFieldValue(node->names[i].name); // TODO if (!maybe_field_value.has_value()) { error_handling::HandleRuntimeError("Variable field not found", node->names[i].base); } current_value_ = maybe_field_value.value(); } current_value_ = context_manager_.ToModifiedValue(current_value_, variable_value_type); } } void ExecuteVisitor::Visit(TupleName* node) { // TODO: check utils::IdType value = current_value_; std::optional maybe_tuple_value = context_manager_.GetValue(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); } if (!is_const_definition_.has_value()) { error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.TupleName"); } utils::ValueType value_type = context_manager_.GetValueType(value); if (value_type == utils::ValueType::Const && is_const_definition_.value() == utils::IsConstModifier::Var) { error_handling::HandleRuntimeError("TupleName: value type expression not match variable definition modifier", node->base); } for (size_t i = 0; i < node->names.size(); ++i) { current_value_ = maybe_tuple_value.value()->fields[i].second; if (value_type == utils::ValueType::Tmp) { // TODO: ?? current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Tmp); } Visitor::Visit(node->names[i]); } current_value_ = value; } // TODO // TODO: make variant of TupleValue void ExecuteVisitor::Visit(VariantName* node) { utils::IdType value = current_value_; std::optional maybe_variant_value = context_manager_.GetValue(value); if (!maybe_variant_value.has_value()) { error_handling::HandleRuntimeError("Mismatched value types in variant variable definition", node->base); } for (size_t i = 0; i < node->names.size(); ++i) { if (i == maybe_variant_value.value()->current_constructor) { // TODO if (fields_count.empty()) ... else ... current_value_ = context_manager_.AddValue( info::value::OptionalValue(maybe_variant_value.value()->value, context_manager_.GetValueManager()), utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? } else { current_value_ = context_manager_.AddValue( info::value::OptionalValue(context_manager_.GetValueManager()), utils::IsConstModifierToValueType(is_const_definition_.value())); } Visitor::Visit(node->names[i]); } // TODO: find out, which constructor used // set value to that constructor and None (empty OptionalValue) to others current_value_ = value; } void ExecuteVisitor::Visit(AnnotatedName* node) { // TODO: check utils::IdType value = current_value_; if (!is_const_definition_.has_value()) { error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.AnnotatedName"); } utils::ValueType value_type = context_manager_.GetValueType(current_value_); if (value_type == utils::ValueType::Const && is_const_definition_.value() == utils::IsConstModifier::Var) { error_handling::HandleRuntimeError("AnnotatedName: value type expression not match variable definition modifier", node->base); } current_value_ = context_manager_.ToModifiedValue(value, utils::IsConstModifierToValueType(is_const_definition_.value())); if (!context_manager_.DefineVariable(node->name, current_value_)) { error_handling::HandleRuntimeError("Variable name already present in context", node->base); } } // Type, typeclass, etc. ----------------- // Type void ExecuteVisitor::Visit(FunctionType* node) {} // no value void ExecuteVisitor::Visit(TupleType* node) {} // no value void ExecuteVisitor::Visit(VariantType* node) {} // no value void ExecuteVisitor::Visit(TypeExpression* node) {} // no value void ExecuteVisitor::Visit(ExtendedScopedAnyType* node) {} // no value // Typeclass void ExecuteVisitor::Visit(ParametrizedTypeclass* node) {} // no value // Typeclass & Type ----------------- void ExecuteVisitor::Visit(ParametrizedType* node) {} // no value // Identifiers, constants, etc. ----------------- // void ExecuteVisitor::Visit(ExtendedName* node) {} // void ExecuteVisitor::Visit(std::string* node) {} // std::string void ExecuteVisitor::Visit(FloatNumberLiteral* node) { current_value_ = context_manager_.AddValue( info::value::InternalValue(node->value), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(NumberLiteral* node) { current_value_ = context_manager_.AddValue( info::value::InternalValue(node->value), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(StringLiteral* node) { current_value_ = context_manager_.AddValue( info::value::InternalValue(node->value), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(CharLiteral* node) { current_value_ = context_manager_.AddValue( info::value::InternalValue(node->value), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(UnitLiteral* node) { current_value_ = context_manager_.AddValue( info::value::InternalValue(info::value::Unit()), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(BoolLiteral* node) { current_value_ = context_manager_.AddValue( info::value::InternalValue(node->value), utils::ValueType::Tmp); } // bool ExecuteVisitor::HandleCondition(Expression& node, const BaseNode& base_node) { Visitor::Visit(node); return *ExtractInternalValue(current_value_, base_node); } // TODO: handle abstract types, handle local abstract types, etc. void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { if (!type.type_id_.has_value()) { return; } auto maybe_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo(type.type_id_.value()); if (!maybe_type_info.has_value()) { error_handling::HandleInternalError("CollectTypeContext unimplemented anything except AnyType", "ExecuteVisitor.CollectTYpeContext"); } 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()); } } } // TODO void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { utils::IdType value = current_value_; switch (node.index()) { case 0: value = context_manager_.ToModifiedValue(value, utils::ValueType::Const); // ?? if (!context_manager_.DefineVariable(std::get>(node)->name, value)) { error_handling::HandleRuntimeError("Can't redifine variable", base_node); } break; case 1: Visitor::Visit(*std::get>(node)); if (!context_manager_.EqualValues(current_value_, value)) { // TODO case_matched_ = false; } break; case 2: Visit(std::get>(node).get()); break; default: // error break; } } } // namespace interpreter