diff --git a/include/error_handling.hpp b/include/error_handling.hpp index 868e320..fad9af1 100644 --- a/include/error_handling.hpp +++ b/include/error_handling.hpp @@ -42,6 +42,14 @@ inline void HandleTypecheckError(const std::string& message, exit(1); } +inline void HandleRuntimeError(const std::string& message, + const interpreter::tokens::BaseNode& node) { // TODO: place in code + std::cout << "Runtime Error: " << message << " at "; + PrintPosition(std::cout, node.start_position, node.end_position); + std::cout << ".\n"; + exit(1); +} + // ... } // namespace error_handling diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index 1a454a5..d18c4e4 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -7,6 +7,8 @@ #include "global_info.hpp" #include "interpreter_tree.hpp" #include "type_info_contexts.hpp" +#include "utils.hpp" +#include "values.hpp" #include "visitor.hpp" #include "error_handling.hpp" @@ -54,9 +56,9 @@ private: // Definition parts - void Visit(FunctionDefinition* node) override; - void Visit(TypeDefinition* node) override; - void Visit(AnyAnnotatedType* node) override; + // // void Visit(FunctionDefinition* node) override; + // // void Visit(TypeDefinition* node) override; + // // void Visit(AnyAnnotatedType* node) override; // Flow control ----------------- @@ -99,7 +101,7 @@ private: // Name - void Visit(PartitionName* node) override; + // // void Visit(PartitionName* node) override; void Visit(NameExpression* node) override; void Visit(TupleName* node) override; void Visit(VariantName* node) override; @@ -126,9 +128,9 @@ private: // Identifiers, constants, etc. ----------------- - void Visit(ExtendedName* node) override; + // // void Visit(ExtendedName* node) override; - void Visit(std::string* node) override; // std::string + // // void Visit(std::string* node) override; // std::string void Visit(FloatNumberLiteral* node) override; void Visit(NumberLiteral* node) override; @@ -137,10 +139,34 @@ private: void Visit(UnitLiteral* node) override; void Visit(BoolLiteral* node) override; + bool HandleCondition(Expression& condition, const BaseNode& base_node); + + template + T* ExtractValue(utils::IdType value, const BaseNode& base_node) { + std::optional maybe_value_info = context_manager_.GetValue(value); + if (!maybe_value_info.has_value()) { + error_handling::HandleRuntimeError("Value has value class that is different from exprected one", base_node); + } + return maybe_value_info.value(); + } + + template + T* ExtractInternalValue(utils::IdType value, const BaseNode& base_node) { + info::value::InternalValue* value_info = ExtractValue(value, base_node); + std::optional maybe_internal_value_info = value_info->GetValue(); + if (!maybe_internal_value_info.has_value()) { + error_handling::HandleRuntimeError("Value has internal value class that is different from exprected one", base_node); + } + return maybe_internal_value_info.value(); + } private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; info::TypeInfoContextManager& type_info_context_manager_; info::ContextManager& context_manager_; + + utils::IdType current_value_; + std::optional active_loop_control_expression_; + std::optional return_value_; // TODO: work outside block ?? }; } // namespace interpreter diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 8753808..7cf3dbd 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -499,6 +499,8 @@ struct BinaryOperatorExpression { OperatorIdentifier operator_name; SubExpression left_expression; SubExpression right_expression; + + utils::IdType function_id_; }; struct UnaryOperatorExpression { @@ -506,6 +508,8 @@ struct UnaryOperatorExpression { OperatorIdentifier operator_name; Expression expression; + + utils::IdType function_id_; }; struct ReferenceExpression { @@ -532,6 +536,8 @@ struct FunctionCallExpression { ExtendedName name; std::vector> parameters; std::vector arguments; + + utils::IdType function_id_; }; struct TupleExpression { diff --git a/include/values.hpp b/include/values.hpp index 10ab0b0..07ace42 100644 --- a/include/values.hpp +++ b/include/values.hpp @@ -18,13 +18,20 @@ struct Unit {}; struct InternalValue { public: InternalValue() = default; - InternalValue(std::variant&& value) : value(std::move(value)) {} + explicit InternalValue(std::variant&& value) : value(std::move(value)) {} + template + std::optional GetValue() { + if (!std::holds_alternative(value)) { + return std::nullopt; + } + return std::get(value); + } public: std::variant&& fields) : fields(fields) {} + explicit TupleValue(std::vector, utils::IdType>>&& fields) : fields(std::move(fields)) {} public: - std::unordered_map fields; + std::vector, utils::IdType>> fields; }; struct VariantValue { public: VariantValue() = default; - VariantValue(size_t constructor, TupleValue value) - : constructor(constructor), value(value) {} + VariantValue(TupleValue value) // TODO: add type & constructor?? + : value(value) {} public: - size_t constructor; TupleValue value; }; @@ -58,7 +64,7 @@ struct ReferenceToValue { public: ReferenceToValue() = default; ReferenceToValue(const std::vector& references, - utils::IdType value) + utils::IdType value) : references(references), value(value) {} public: @@ -70,7 +76,7 @@ struct FunctionValue { public: FunctionValue() = default; FunctionValue(std::variant function) + interpreter::tokens::LambdaFunction*> function) : function(function) {} public: @@ -82,17 +88,19 @@ public: struct ArrayValue { public: ArrayValue() = default; - ArrayValue(const std::vector& elements) - : elements(elements) {} + explicit ArrayValue(const std::vector& elements, + bool is_constant_size) + : elements(elements), is_constant_size(is_constant_size) {} public: std::vector elements; + bool is_constant_size = false; }; struct OptionalValue { public: OptionalValue() = default; - OptionalValue(utils::IdType value) : value(value) {} + explicit OptionalValue(utils::IdType value) : value(value) {} public: std::optional value; diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index 286ed7e..14e3cee 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -1,5 +1,8 @@ // for clangd #include "../include/execute_visitor.hpp" +#include +#include +#include // TODO @@ -7,7 +10,7 @@ namespace interpreter { // Sources ----------------- -void ExecuteVisitor::Visit(SourceFile* node) { +void ExecuteVisitor::Visit(SourceFile* node) { // never used ?? for (auto& statement : node->statements) { Visitor::Visit(statement); } @@ -15,97 +18,48 @@ void ExecuteVisitor::Visit(SourceFile* node) { // Namespaces, partitions ----------------- -void ExecuteVisitor::Visit(NamespaceSources* node) { +void ExecuteVisitor::Visit(NamespaceSources* node) { // never used ?? for (auto& statement : node->statements) { Visitor::Visit(statement); } } -void ExecuteVisitor::Visit(Namespace* node) { - Visit(&node->type); +void ExecuteVisitor::Visit(Namespace* node) { // never used ?? + // Visit(&node->type); Visit(&node->scope); } // Definitions ----------------- -void ExecuteVisitor::Visit(ImportStatement* node) { - for (auto& symbol : node->symbols) { - Visit(&symbol); - } -} - -void ExecuteVisitor::Visit(AliasDefinitionStatement* node) { - Visit(&node->type); - Visit(node->value.get()); -} +void ExecuteVisitor::Visit(ImportStatement* node) {} // no value +void ExecuteVisitor::Visit(AliasDefinitionStatement* node) {} // no value void ExecuteVisitor::Visit(VariableDefinitionStatement* node) { Visitor::Visit(node->name); Visitor::Visit(node->value); } -void ExecuteVisitor::Visit(FunctionDeclaration* node) { - Visit(&node->name); - for (auto& parameter : node->parameters) { - Visit(parameter.get()); - } - Visit(node->type.get()); -} +void ExecuteVisitor::Visit(FunctionDeclaration* node) {} // no value void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { - Visit(node->definition.get()); + // Visit(node->definition.get()); Visitor::Visit(node->value); } -void ExecuteVisitor::Visit(TypeDefinitionStatement* node) { - 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(AbstractTypeDefinitionStatement* node) { - Visit(node->type.get()); -} - -void ExecuteVisitor::Visit(TypeclassDefinitionStatement* node) { - Visit(node->definition.get()); - for (auto& requirement : node->requirements) { - Visit(requirement.get()); - } -} +void ExecuteVisitor::Visit(TypeclassDefinitionStatement* node) {} // no value void ExecuteVisitor::Visit(PartitionStatement* node) { - Visit(&node->name); Visitor::Visit(node->value); } -// Definition parts - -void ExecuteVisitor::Visit(FunctionDefinition* node) { - Visit(&node->name); - for (auto& argument : node->arguments) { - Visit(&argument); - } -} - -void ExecuteVisitor::Visit(TypeDefinition* node) { - Visit(node->type.get()); - for (auto& parameter : node->parameters) { - Visit(parameter.get()); - } -} - -void ExecuteVisitor::Visit(AnyAnnotatedType* node) { - Visit(&node->type); - for (auto& typeclass : node->typeclasses) { - Visit(typeclass.get()); - } -} - // Flow control ----------------- void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) { if (node->name.has_value()) { - Visit(&node->name.value()); + // Visit(&node->name.value()); } Visitor::Visit(node->value); } @@ -145,37 +99,122 @@ void ExecuteVisitor::Visit(Condition* node) { } void ExecuteVisitor::Visit(DoWhileLoop* node) { - Visitor::Visit(node->statement); - Visitor::Visit(node->condition); + 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(result, false), + utils::ValueType::Tmp); } void ExecuteVisitor::Visit(WhileLoop* node) { - Visitor::Visit(node->condition); - Visitor::Visit(node->statement); + 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(result, false), + utils::ValueType::Tmp); } void ExecuteVisitor::Visit(ForLoop* node) { - Visitor::Visit(node->variable); + std::vector result; + + // TODO: extend on different interval types (not only array) Visitor::Visit(node->interval); - Visitor::Visit(node->statement); + 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(result, false), + utils::ValueType::Tmp); } void ExecuteVisitor::Visit(LoopLoop* node) { - Visitor::Visit(node->statement); + 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(result, false), + utils::ValueType::Tmp); } // Statements, expressions, blocks, etc. ----------------- void ExecuteVisitor::Visit(Block* node) { for (auto& statement : node->statements) { + return_value_ = std::nullopt; Visitor::Visit(statement); + if (return_value_.has_value()) { + current_value_ = return_value_.value(); + return; + } } + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); } void ExecuteVisitor::Visit(ScopedStatement* node) { Visitor::Visit(node->statement); } -void ExecuteVisitor::Visit(LoopControlExpression& node) {} // enum +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 @@ -186,17 +225,35 @@ void ExecuteVisitor::Visit(BinaryOperatorExpression* node) { } void ExecuteVisitor::Visit(UnaryOperatorExpression* node) { - Visit(&node->operator_name); + // Visit(&node->operator_name); Visitor::Visit(node->expression); } void ExecuteVisitor::Visit(ReferenceExpression* node) { + // TODO: check, that therie 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_), + 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 @@ -212,7 +269,7 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { } } - Visit(&node->name); + // Visit(&node->name); for (auto& parameter : node->parameters) { Visit(parameter.get()); @@ -224,24 +281,37 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) { } 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)), + utils::ValueType::Tmp); } -void ExecuteVisitor::Visit(VariantExpression* node) { +// TODO +void ExecuteVisitor::Visit(VariantExpression* node) { // ?? for (auto& expression : node->expressions) { Visitor::Visit(expression); + info::value::OptionalValue* expression_value = ExtractValue(current_value_, node->base); + if (expression_value->value.has_value()) { + + break; + } } } void ExecuteVisitor::Visit(ReturnExpression* node) { Visitor::Visit(node->expression); + return_value_ = current_value_; } void ExecuteVisitor::Visit(TypeConstructorParameter* node) { if (node->name.has_value()) { - Visit(&node->name.value()); + // Visit(&node->name.value()); } Visitor::Visit(node->value); } @@ -253,14 +323,10 @@ void ExecuteVisitor::Visit(TypeConstructor* node) { } } +// TODO void ExecuteVisitor::Visit(LambdaFunction* node) { - for (auto& parameter : node->parameters) { - Visit(parameter.get()); - } - for (auto& argument : node->arguments) { - Visit(&argument); - } - Visitor::Visit(node->expression); + error_handling::HandleInternalError("Lambda function are not implemented yet", + "ExecuteVisitor.LambdaFunction"); } void ExecuteVisitor::Visit(ArrayExpression* node) { @@ -271,17 +337,9 @@ void ExecuteVisitor::Visit(ArrayExpression* node) { // Name -void ExecuteVisitor::Visit(PartitionName* node) { - for (auto& path_namespace : node->path) { - Visit(&path_namespace); - } - - Visit(&node->name); -} - void ExecuteVisitor::Visit(NameExpression* node) { for (auto& name : node->names) { - Visit(&name); + // Visit(&name); } } @@ -298,7 +356,7 @@ void ExecuteVisitor::Visit(VariantName* node) { } void ExecuteVisitor::Visit(AnnotatedName* node) { - Visit(&node->name); + // Visit(&node->name); if (node->type.has_value()) { Visitor::Visit(node->type.value()); } @@ -308,85 +366,68 @@ void ExecuteVisitor::Visit(AnnotatedName* node) { // Type -void ExecuteVisitor::Visit(FunctionType* node) { - for (auto& type : node->types) { - Visitor::Visit(type); - } -} - -void ExecuteVisitor::Visit(TupleType* node) { - if (node->type.has_value()) { - Visit(&node->type.value()); - } - for (auto& entity : node->entities) { - if (entity.first.has_value()) { - Visit(&entity.first.value()); - } - Visit(entity.second.get()); - } -} - -void ExecuteVisitor::Visit(VariantType* node) { - if (node->type.has_value()) { - Visit(&node->type.value()); - } - for (auto& constructor : node->constructors) { - if (std::holds_alternative(constructor)) { - Visit(&std::get(constructor)); - } else if (std::holds_alternative>(constructor)) { - Visit(std::get>(constructor).get()); - } else { - // error - } - } -} - -void ExecuteVisitor::Visit(TypeExpression* node) { - for (auto& type : node->path) { - Visit(&type); - } - Visit(&node->type); -} - -void ExecuteVisitor::Visit(ExtendedScopedAnyType* node) { - Visitor::Visit(node->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) { - Visit(&node->typeclass); - for (auto& parameter : node->parameters) { - Visit(parameter.get()); - } -} +void ExecuteVisitor::Visit(ParametrizedTypeclass* node) {} // no value // Typeclass & Type ----------------- -void ExecuteVisitor::Visit(ParametrizedType* node) { - Visit(&node->type); - for (auto& parameter : node->parameters) { - Visit(parameter.get()); - } -} +void ExecuteVisitor::Visit(ParametrizedType* node) {} // no value // Identifiers, constants, etc. ----------------- -void ExecuteVisitor::Visit(ExtendedName* node) {} +// void ExecuteVisitor::Visit(ExtendedName* node) {} -void ExecuteVisitor::Visit(std::string* node) {} // std::string +// void ExecuteVisitor::Visit(std::string* node) {} // std::string -void ExecuteVisitor::Visit(FloatNumberLiteral* node) {} +void ExecuteVisitor::Visit(FloatNumberLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} -void ExecuteVisitor::Visit(NumberLiteral* node) {} +void ExecuteVisitor::Visit(NumberLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} -void ExecuteVisitor::Visit(StringLiteral* node) {} +void ExecuteVisitor::Visit(StringLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} -void ExecuteVisitor::Visit(CharLiteral* node) {} +void ExecuteVisitor::Visit(CharLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} -void ExecuteVisitor::Visit(UnitLiteral* node) {} +void ExecuteVisitor::Visit(UnitLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); +} -void ExecuteVisitor::Visit(BoolLiteral* node) {} +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); +} } // namespace interpreter diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index a10e86e..0b0bab8 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -541,6 +541,7 @@ void TypeCheckVisitor::Visit(Block* node) { error_handling::HandleTypecheckError("Different return types in block", node->base); } } + // returned_type_ = std::nullopt; // not needed } } context_manager_.EnterContext(); @@ -571,27 +572,28 @@ void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { // TODO: Check, that type is not abstract ?? auto maybe_operator_id = namespace_visitor_.FindFunction(std::nullopt, node->operator_name); + const info::definition::Function* operator_info = nullptr; if (maybe_operator_id.has_value()) { - const info::definition::Function& operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); + operator_info = &namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); - if (!operator_info.declaration.has_value()) { + if (!operator_info->declaration.has_value()) { error_handling::HandleTypecheckError("Operator declaration not found", node->base); } - if (!operator_info.definition.has_value()) { // TODO: builtin, etc. + if (!operator_info->definition.has_value()) { // TODO: builtin, etc. error_handling::HandleTypecheckError("Operator definition not found", node->base); } - if (operator_info.argument_count != 3) { // 2 + return type + if (operator_info->argument_count != 3) { // 2 + return type error_handling::HandleTypecheckError("Operator wrong argument count", node->base); } - if (operator_info.declaration->parameters.size() > 0) { + if (operator_info->declaration->parameters.size() > 0) { error_handling::HandleTypecheckError("Operator with parameters", node->base); } - Visitor::Visit(*operator_info.declaration.value().argument_types[0]); + Visitor::Visit(*operator_info->declaration.value().argument_types[0]); utils::IdType left_expression_type = current_type_; // TODO: type in context of deduced types Visitor::Visit(node->left_expression); @@ -599,82 +601,82 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { error_handling::HandleTypecheckError("Operator left expression has wrong type", node->base); } - Visitor::Visit(*operator_info.declaration.value().argument_types[1]); + Visitor::Visit(*operator_info->declaration.value().argument_types[1]); utils::IdType right_expression_type = current_type_; // TODO: type in context of deduced types Visitor::Visit(node->right_expression); if (!context_manager_.AddTypeRequirement(current_type_, right_expression_type)) { error_handling::HandleTypecheckError("Operator right expression has wrong type", node->base); } + } else { - Visitor::Visit(*operator_info.declaration.value().argument_types.back()); - return; + Visitor::Visit(node->left_expression); + auto maybe_left_type = context_manager_.GetType(current_type_); + + utils::ValueType left_value_type = context_manager_.GetValueType(current_type_); + + if (!maybe_left_type.has_value()) { + error_handling::HandleTypecheckError("Operator not found (type is not DefinedType)", node->base); + } + + auto maybe_left_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo(maybe_left_type.value()->GetTypeId()); + + std::string left_type_name = maybe_left_type_info.value()->type.type; + + auto maybe_const_operator_id = namespace_visitor_.FindMethod(std::nullopt, + left_type_name, + node->operator_name, + utils::IsConstModifier::Const); + + if (left_value_type != utils::ValueType::Const) { + maybe_operator_id = namespace_visitor_.FindMethod(std::nullopt, + left_type_name, + node->operator_name, + utils::IsConstModifier::Var); + } + + if (!maybe_operator_id.has_value() && !maybe_const_operator_id.has_value()) { + error_handling::HandleTypecheckError("Operator not found (method name not found)", node->base); + } + + if (maybe_operator_id.has_value() && maybe_const_operator_id.has_value()) { + error_handling::HandleTypecheckError("Ambigious operator (const and var method)", node->base); + } + + if (!maybe_operator_id.has_value()) { + maybe_operator_id = maybe_const_operator_id; + } + + operator_info = &namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); + + if (!operator_info->declaration.has_value()) { + error_handling::HandleTypecheckError("Operator declaration not found", node->base); + } + + if (!operator_info->definition.has_value()) { // TODO: builtin, etc. + error_handling::HandleTypecheckError("Operator definition not found", node->base); + } + + if (operator_info->argument_count != 2) { // argument + return type + error_handling::HandleTypecheckError("Operator wrong argument count", node->base); + } + + if (operator_info->declaration->parameters.size() > 0) { + error_handling::HandleTypecheckError("Operator with parameters", node->base); + } + + Visitor::Visit(*operator_info->declaration.value().argument_types[9]); + utils::IdType right_expression_type = current_type_; // TODO: type in context of deduced types + + Visitor::Visit(node->right_expression); + if (!context_manager_.AddTypeRequirement(current_type_, right_expression_type)) { + error_handling::HandleTypecheckError("Operator right expression has wrong type", node->base); + } } - Visitor::Visit(node->left_expression); - auto maybe_left_type = context_manager_.GetType(current_type_); + node->function_id_ = maybe_operator_id.value(); // IMPORTANT - utils::ValueType left_value_type = context_manager_.GetValueType(current_type_); - - if (!maybe_left_type.has_value()) { - error_handling::HandleTypecheckError("Operator not found (type is not DefinedType)", node->base); - } - - auto maybe_left_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo(maybe_left_type.value()->GetTypeId()); - - std::string left_type_name = maybe_left_type_info.value()->type.type; - - auto maybe_const_operator_id = namespace_visitor_.FindMethod(std::nullopt, - left_type_name, - node->operator_name, - utils::IsConstModifier::Const); - - if (left_value_type != utils::ValueType::Const) { - maybe_operator_id = namespace_visitor_.FindMethod(std::nullopt, - left_type_name, - node->operator_name, - utils::IsConstModifier::Var); - } - - if (!maybe_operator_id.has_value() && !maybe_const_operator_id.has_value()) { - error_handling::HandleTypecheckError("Operator not found (method name not found)", node->base); - } - - if (maybe_operator_id.has_value() && maybe_const_operator_id.has_value()) { - error_handling::HandleTypecheckError("Ambigious operator (const and var method)", node->base); - } - - if (!maybe_operator_id.has_value()) { - maybe_operator_id = maybe_const_operator_id; - } - - const info::definition::Function& operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); - - if (!operator_info.declaration.has_value()) { - error_handling::HandleTypecheckError("Operator declaration not found", node->base); - } - - if (!operator_info.definition.has_value()) { // TODO: builtin, etc. - error_handling::HandleTypecheckError("Operator definition not found", node->base); - } - - if (operator_info.argument_count != 2) { // argument + return type - error_handling::HandleTypecheckError("Operator wrong argument count", node->base); - } - - if (operator_info.declaration->parameters.size() > 0) { - error_handling::HandleTypecheckError("Operator with parameters", node->base); - } - - Visitor::Visit(*operator_info.declaration.value().argument_types[9]); - utils::IdType right_expression_type = current_type_; // TODO: type in context of deduced types - - Visitor::Visit(node->right_expression); - if (!context_manager_.AddTypeRequirement(current_type_, right_expression_type)) { - error_handling::HandleTypecheckError("Operator right expression has wrong type", node->base); - } - - Visitor::Visit(*operator_info.declaration.value().argument_types.back()); + Visitor::Visit(*operator_info->declaration.value().argument_types.back()); node->base.type_ = current_type_; } @@ -714,6 +716,8 @@ void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) { error_handling::HandleTypecheckError("Operator expression has wrong type", node->base); } + node->function_id_ = maybe_operator_id.value(); // IMPORTANT + Visitor::Visit(*operator_info.declaration.value().argument_types.back()); node->base.type_ = current_type_; @@ -867,6 +871,8 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { context_manager_.AddTypeRequirement(current_type_, argument_type); } + node->function_id_ = maybe_function_id.value(); // IMPORTANT + Visitor::Visit(*function_declaration.argument_types.back()); current_type_ = TypeInContext(current_type_, context); } @@ -899,6 +905,9 @@ void TypeCheckVisitor::Visit(VariantExpression* node) { } + current_type_ = context_manager_.AddType(info::type::VariantType(std::nullopt, constructors, -1), + utils::ValueType::Tmp); + current_type_ = context_manager_.AddType(info::type::VariantType(std::nullopt, constructors, -1), utils::ValueType::Tmp);