From ce0ca2a5cbec2f57c13b4eabe2aac267a3b0a999 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Tue, 16 May 2023 16:16:14 +0300 Subject: [PATCH] check, that type satisfy typeclass requirements made in type_check_visitor --- include/global_info.hpp | 38 +++++------------ include/typeclass_graph.hpp | 16 +++++++- src/global_info.cpp | 81 ++++++++++++++++++++++++++++++++----- src/type_check_visitor.cpp | 23 ++++++++++- 4 files changed, 118 insertions(+), 40 deletions(-) diff --git a/include/global_info.hpp b/include/global_info.hpp index 1acb255..f2378be 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -267,10 +267,6 @@ public: std::optional FindNamespaceIn( utils::IdType current_namespace, const std::vector& path); - - std::unordered_map* - ChooseNamespaces(utils::ClassInternalsModifier modifier, - utils::IdType namespace_id); private: GlobalInfo& global_info_; @@ -339,33 +335,21 @@ public: return &typeclass_graph_; } - // cache ?? - std::unordered_set GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node) { - std::unordered_set typeclasses; + std::unordered_set + GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node); - for (auto& typeclass : node->typeclasses) { - utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_; + std::vector + GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node); - std::vector dependencies = typeclass_graph_.GetTypeclassDependencies(graph_id); - for (auto& dependency : dependencies) { - typeclasses.insert(dependency); - } + std::unordered_map + GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node); - typeclasses.insert(graph_id); - } - return typeclasses; - } + std::vector> + GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node); - 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 typeclasses_vector; - } + std::unordered_map* ChooseNamespaces( + utils::ClassInternalsModifier modifier, + definition::Namespace* current_namespace); std::optional AddTypeclassToGraph(utils::IdType typeclass); diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp index e5c0309..3533e75 100644 --- a/include/typeclass_graph.hpp +++ b/include/typeclass_graph.hpp @@ -15,7 +15,7 @@ namespace info { class TypeclassGraph { public: struct FunctionInfo { - utils::ClassInternalsModifier modifier; + utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; interpreter::tokens::FunctionDeclaration* declaration = nullptr; std::optional definition; }; @@ -100,7 +100,7 @@ public: } // cache ?? - const std::vector GetTypeclassDependencies(utils::IdType id) { + std::vector GetTypeclassDependencies(utils::IdType id) { std::vector dependencies; dependencies.reserve(typeclasses_.at(id).dependencies.size()); @@ -111,6 +111,18 @@ public: return dependencies; } + // cache ?? + std::vector> GetTypeclassFunctions(utils::IdType id) { + std::vector> functions; + + functions.reserve(typeclasses_.at(id).functions.size()); + for (auto& function : typeclasses_[id].functions) { + functions.push_back({function.first, function.second.modifier}); + } + + return functions; + } + bool IsCalculated() { return is_calculated_; } diff --git a/src/global_info.cpp b/src/global_info.cpp index 719b68c..f6a4dbd 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -25,7 +25,8 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, error_handling::HandleNamesError("Can't define basic type namespace", base_node); } - auto current_namespaces = ChooseNamespaces(modifier, namespace_stack_.back()); + auto current_namespaces = + global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[namespace_stack_.back()]); utils::IdType id = 0; @@ -57,7 +58,8 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name, utils::ClassInternalsModifier modifier) { for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { - auto current_namespaces = ChooseNamespaces(modifier, i); + auto current_namespaces = + global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[i]); auto namespace_iter = current_namespaces->find(name); if (namespace_iter != current_namespaces->end()) { namespace_stack_.push_back(namespace_iter->second); @@ -440,27 +442,88 @@ std::optional GlobalInfo::NamespaceVisitor::FindNamespaceIn( return next_namespace; } +// + +// cache ?? +std::unordered_set + GlobalInfo::GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node) { + + std::unordered_set typeclasses; + + for (auto& typeclass : node->typeclasses) { + utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_; + + std::vector dependencies = typeclass_graph_.GetTypeclassDependencies(graph_id); + for (auto& dependency : dependencies) { + typeclasses.insert(dependency); + } + + typeclasses.insert(graph_id); + } + return typeclasses; +} + +std::vector + GlobalInfo::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 typeclasses_vector; +} + +std::unordered_map + GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node) { + + std::unordered_map functions; + + for (auto& typeclass : node->typeclasses) { + utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_; + + auto requirements = typeclass_graph_.GetTypeclassFunctions(graph_id); + for (auto& requirement : requirements) { + functions[requirement.first] = requirement.second; + } + } + return functions; +} + +std::vector> + GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node) { + + std::unordered_map functions_set = GetAnnotatedTypeFunctionsMap(node); + + std::vector> functions_vector; + functions_vector.reserve(functions_vector.size()); + for (auto& typeclass : functions_set) { + functions_vector.push_back(typeclass); + } + return functions_vector; +} + std::unordered_map* - GlobalInfo::NamespaceVisitor::ChooseNamespaces(utils::ClassInternalsModifier modifier, - utils::IdType namespace_id) { + GlobalInfo::ChooseNamespaces(utils::ClassInternalsModifier modifier, + definition::Namespace* current_namespace) { std::unordered_map* current_namespaces = nullptr; switch (modifier) { case utils::ClassInternalsModifier::Const: - current_namespaces = &global_info_.namespaces_[namespace_id].const_namespaces; + current_namespaces = ¤t_namespace->const_namespaces; break; case utils::ClassInternalsModifier::Var: - current_namespaces = &global_info_.namespaces_[namespace_id].var_namespaces; + current_namespaces = ¤t_namespace->var_namespaces; break; case utils::ClassInternalsModifier::Static: - current_namespaces = &global_info_.namespaces_[namespace_id].namespaces; + current_namespaces = ¤t_namespace->namespaces; break; } return current_namespaces; } -// - std::optional GlobalInfo::AddTypeclassToGraph(utils::IdType typeclass) { definition::Typeclass* typeclass_info = &GetTypeclassInfo(typeclass); definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace); diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 7e437b5..deba86f 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -231,8 +231,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { for (size_t i = 0; i < node->definition->arguments.size(); ++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 + current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); // TODO: Var?? + if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) { error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base); } } @@ -255,6 +255,25 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) { is_in_statement_ = true; + + std::unordered_map required_functions = + global_info_.GetAnnotatedTypeFunctionsMap(node->definition->type.get()); + + std::string& type_name = node->definition->type->type; + + for (auto& function : required_functions) { // TODO: optimize + std::unordered_map* current_namespaces = + global_info_.ChooseNamespaces(function.second, namespace_visitor_.GetCurrentNamespace()); + + auto& type_functions = global_info_.GetNamespaceInfo((*current_namespaces)[type_name]).functions; + + auto function_iter = type_functions.find(function.first); + + if (function_iter == type_functions.end() || !global_info_.GetFunctionInfo(function_iter->second).definition.has_value()) { + error_handling::HandleTypecheckError("Type is not satisfy typeclass requirements: " + function.first + " is not defined", node->base); + } + } + current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); is_in_statement_ = false;