From 090f638e45f5d8b2ba4cb6ee7afa5f685a7e5322 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Tue, 16 May 2023 15:12:30 +0300 Subject: [PATCH] function declaration & definition statements for typeclasses and inherited classes in typecheck_visitor --- include/global_info.hpp | 17 +++++--- include/typeclass_graph.hpp | 26 ++++++++++-- src/type_check_visitor.cpp | 80 +++++++++++++++++++++++++++++++------ 3 files changed, 102 insertions(+), 21 deletions(-) diff --git a/include/global_info.hpp b/include/global_info.hpp index 2b64cd9..1acb255 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -340,7 +340,7 @@ public: } // cache ?? - std::vector GetAnnotatedTypeTypeclasses(interpreter::tokens::AnnotatedType* node) { + std::unordered_set GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node) { std::unordered_set typeclasses; for (auto& typeclass : node->typeclasses) { @@ -353,13 +353,18 @@ public: typeclasses.insert(graph_id); } + return typeclasses; + } - std::vector collected_typeclasses; - collected_typeclasses.reserve(typeclasses.size()); - for (auto& typeclass : typeclasses) { - collected_typeclasses.push_back(typeclass); + std::vector GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node) { + std::unordered_set typeclasses_set = GetAnnotatedTypeTypeclassesSet(node); + + std::vector typeclasses_vector; + typeclasses_vector.reserve(typeclasses_vector.size()); + for (auto& typeclass : typeclasses_set) { + typeclasses_vector.push_back(typeclass); } - return collected_typeclasses; + return typeclasses_vector; } std::optional AddTypeclassToGraph(utils::IdType typeclass); diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp index 9ca4448..e5c0309 100644 --- a/include/typeclass_graph.hpp +++ b/include/typeclass_graph.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -67,7 +68,7 @@ public: return typeclasses_.size() - 1; } - std::optional FindMethodTypeclass(const std::string& name) { + std::optional FindFunctionTypeclass(const std::string& name) { auto function_iter = method_to_typeclass_.find(name); if (function_iter == method_to_typeclass_.end()) { return std::nullopt; @@ -75,8 +76,27 @@ public: return function_iter->second; } - const TypeclassVertex& GetTypeclass(utils::IdType id) { // check, if calculated ?? - return typeclasses_.at(id); + bool IsFunctionInTypeclass(const std::string& name, utils::IdType typeclass_id) { + return typeclasses_[typeclass_id].functions.count(name) != 0; + } + + std::optional GetFunctionInfo(const std::string& name, + std::optional typeclass_id) { + if (typeclass_id.has_value()) { + return &typeclasses_[typeclass_id.value()].functions[name]; + } + + auto maybe_function_typeclass_id = FindFunctionTypeclass(name); + + if (!maybe_function_typeclass_id.has_value()) { + return std::nullopt; + } + + return &typeclasses_[maybe_function_typeclass_id.value()].functions[name]; + } + + const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ?? + return typeclasses_.at(typeclass_id); } // cache ?? diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 92a84cc..7e437b5 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -127,11 +127,19 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) { bool was_in_statement = is_in_statement_; is_in_statement_ = true; + if (!was_in_statement) { + if (namespace_visitor_.GetCurrentNamespaceTypeclassId().has_value()) { + error_handling::HandleTypecheckError("Can't declare functions in typeclass namespace", node->base); + } + if (typeclass_graph_.FindFunctionTypeclass(node->name).has_value()) { + error_handling::HandleTypecheckError("Can't redeclare functions, that are declared as typeclass functions", node->base); + } + } context_manager_.EnterContext(); for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed?? std::vector requirements = - global_info_.GetAnnotatedTypeTypeclasses(parameter.get()); + global_info_.GetAnnotatedTypeTypeclassesVector(parameter.get()); current_type_ = context_manager_.AddValue( info::type::AbstractType(utils::AbstractTypeModifier::Abstract, parameter->type, @@ -152,37 +160,84 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) { void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { is_in_statement_ = true; - context_manager_.EnterContext(); + + std::string& function_name = node->definition->name; info::definition::Function& function_info = global_info_.GetFunctionInfo(node->function_id_); - if (!function_info.declaration.has_value()) { - error_handling::HandleTypecheckError("Function defined, but not declared", node->base); + interpreter::tokens::FunctionDeclaration* declaration = nullptr; + if (function_info.declaration.has_value()) { + declaration = function_info.declaration.value().node; + } else { + auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(function_name); + + if (!maybe_typeclass_graph_id.has_value()) { + error_handling::HandleTypecheckError("Function defined, but not declared", node->base); + } + + auto maybe_curent_type = namespace_visitor_.GetCurrentNamespaceType(); // TODO: aliases + auto maybe_current_typeclass = namespace_visitor_.GetCurrentNamespaceTypeclass(); + + if (maybe_curent_type.has_value() && maybe_current_typeclass.has_value()) { + error_handling::HandleInternalError("Current namespace is belong to type and typeclass in same time", + "TypeCheckVisitor.FunctionDefinitionStatement"); + } + + if (!maybe_curent_type.has_value() && !maybe_current_typeclass.has_value()) { + error_handling::HandleTypecheckError("Function defined, but declared in typeclass and not belong to type or typeclass namespace", node->base); + } + + bool method_found_in_typeclass = false; + if (maybe_curent_type.has_value()) { // optiomize?? + auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(maybe_curent_type.value()->type.node); + + method_found_in_typeclass = (typeclasses.count(maybe_typeclass_graph_id.value()) != 0); + + } else if (maybe_current_typeclass.has_value()) { + method_found_in_typeclass = + typeclass_graph_.IsFunctionInTypeclass(function_name, maybe_current_typeclass.value()->graph_id_); + } + + if (!method_found_in_typeclass) { + error_handling::HandleTypecheckError("Function defined, but declared in different typeclass", node->base); + } + + auto maybe_function_info = typeclass_graph_.GetFunctionInfo(function_name, std::nullopt); + if (!maybe_function_info.has_value()) { + error_handling::HandleInternalError("FunctionInfo not found", + "TypeCheckVisitor.FunctionDefinitionStatement"); + } + + declaration = maybe_function_info.value()->declaration; // TODO: save declaration to global info ?? } - info::definition::FunctionDeclaration& declaration = function_info.declaration.value(); + context_manager_.EnterContext(); - for (auto parameter : declaration.parameters) { + if (declaration->type->types.size() != node->definition->arguments.size() + 1) { // + return type + error_handling::HandleTypecheckError("Wrong argument count in function definition", node->base); + } + + for (auto& parameter : declaration->parameters) { std::vector requirements = - global_info_.GetAnnotatedTypeTypeclasses(parameter.node); + global_info_.GetAnnotatedTypeTypeclassesVector(parameter.get()); current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, - parameter.type, + parameter->type, requirements), utils::ValueType::Tmp); - if (!context_manager_.DefineLocalType(parameter.type, current_type_)) { + if (!context_manager_.DefineLocalType(parameter->type, current_type_)) { error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base); } } for (size_t i = 0; i < node->definition->arguments.size(); ++i) { - Visitor::Visit(*declaration.argument_types[i]); + Visitor::Visit(declaration->type->types[i]); current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); // TODO: var function arguments?? if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) { // TODO: watch to reference error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base); } } - Visitor::Visit(*declaration.argument_types.back()); + Visitor::Visit(declaration->type->types.back()); utils::IdType return_type = current_type_; Visitor::Visit(node->value); @@ -191,6 +246,7 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { } context_manager_.ExitContext(); + current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); is_in_statement_ = false; @@ -209,7 +265,7 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { is_in_statement_ = true; std::vector requirements = - global_info_.GetAnnotatedTypeTypeclasses(node->type.get()); + global_info_.GetAnnotatedTypeTypeclassesVector(node->type.get()); current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements), utils::ValueType::Tmp); if (!context_manager_.DefineLocalType(node->type->type, current_type_)) {