From b723fd6a65c70bc9759bd30854d9b57ae0b83cf5 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Wed, 17 May 2023 17:57:56 +0300 Subject: [PATCH] fixes, build_visitor TupleType and VariantType fix --- CMakeLists.txt | 2 +- include/contexts.hpp | 4 +- include/definitions.hpp | 12 +-- include/typeclass_graph.hpp | 126 ++----------------------------- include/types.hpp | 5 +- include/utils.hpp | 6 +- src/build_visitor.cpp | 48 ++++++------ src/execute_visitor.cpp | 7 +- src/global_info.cpp | 68 ++++++++++------- src/link_symbols_visitor.cpp | 2 + src/type_check_visitor.cpp | 140 ++++++++++++++++++++-------------- src/typeclass_graph.cpp | 142 +++++++++++++++++++++++++++++++++++ 12 files changed, 321 insertions(+), 241 deletions(-) create mode 100644 src/typeclass_graph.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 41dfcff..f09ef35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ add_executable(lang_interpreter src/main.cpp src/types.cpp src/values.cpp src/global_info.cpp - include/definitions.hpp + src/typeclass_graph.cpp src/visitor.cpp src/build_visitor.cpp src/print_visitor.cpp diff --git a/include/contexts.hpp b/include/contexts.hpp index 487153b..3993ea0 100644 --- a/include/contexts.hpp +++ b/include/contexts.hpp @@ -132,7 +132,7 @@ private: return true; } - if (variables_.count(name) > 0) { + if (variables_.count(name) != 0) { return false; } variables_[name] = value_id; @@ -140,7 +140,7 @@ private: } bool DefineLocalType(const std::string& name, utils::IdType type_id) { - if (local_types_.count(name) > 0) { + if (local_types_.count(name) != 0) { return false; } local_types_[name] = type_id; diff --git a/include/definitions.hpp b/include/definitions.hpp index 6445bc3..7b91036 100644 --- a/include/definitions.hpp +++ b/include/definitions.hpp @@ -48,7 +48,7 @@ struct AnyType { interpreter::tokens::AnyType* value; utils::ClassModifier modifier; - utils::IdType parent_namespace; + utils::IdType parent_namespace = 0; }; struct Type { @@ -57,8 +57,8 @@ struct Type { struct Constructor { std::string name; - size_t order; - utils::IdType type_id; + std::optional order; // no order for tuple types + utils::IdType type_id = 0; std::optional constructor_tuple_node; }; @@ -83,9 +83,9 @@ struct Typeclass { std::vector parameters; interpreter::tokens::TypeclassDefinitionStatement* node; - utils::IdType parent_namespace; + utils::IdType parent_namespace = 0; - utils::IdType graph_id_; // TODO: make safe?? + utils::IdType graph_id_ = 0; // TODO: make safe?? }; struct Import { @@ -101,7 +101,7 @@ struct Namespace { std::unordered_map var_namespaces; std::unordered_map const_namespaces; - utils::IdType parent_namespace; + utils::IdType parent_namespace = 0; utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; std::string type_name; diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp index e7614be..7c23d55 100644 --- a/include/typeclass_graph.hpp +++ b/include/typeclass_graph.hpp @@ -32,146 +32,32 @@ public: interpreter::tokens::TypeclassDefinitionStatement* definition, const std::vector& dependencies, // TODO: parameters const std::vector>>& function_declarations, - const std::vector>& function_definitions) { - for (auto& method : function_declarations) { - if (method_to_typeclass_.count(method.first) != 0) { - return std::nullopt; - } - } + const std::vector>& function_definitions); - is_calculated_ = false; - - typeclasses_.emplace_back(); - TypeclassVertex& typeclass = typeclasses_.back(); - typeclass.name = name; - typeclass.definition = definition; - - for (auto& dependency : dependencies) { - typeclass.dependencies.insert(dependency); - } - - for (auto& method : function_declarations) { - FunctionInfo function_info; - function_info.modifier = method.second.first; - function_info.declaration = method.second.second; - - typeclass.functions[method.first] = function_info; - - method_to_typeclass_[method.first] = typeclasses_.size(); - } - name_to_typeclass_[name] = typeclasses_.size() - 1; - - for (auto& method : function_definitions) { - typeclass.functions[method.first].definition = method.second; - } - - return typeclasses_.size() - 1; - } - - 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; - } - return function_iter->second; - } + std::optional FindFunctionTypeclass(const std::string& name); 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]; - } + std::optional typeclass_id); const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ?? return typeclasses_.at(typeclass_id); } // cache ?? - std::vector GetTypeclassDependencies(utils::IdType id) { - std::vector dependencies; - - dependencies.reserve(typeclasses_.at(id).dependencies.size()); - for (auto& dependency : typeclasses_[id].dependencies) { - dependencies.push_back(name_to_typeclass_[dependency]); - } - - return dependencies; - } + std::vector GetTypeclassDependencies(utils::IdType id); // 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}); - } - - return functions; - } + std::vector> GetTypeclassFunctions(utils::IdType id); bool IsCalculated() { return is_calculated_; } - bool CalculateGraph() { - if (is_calculated_) { - return true; - } - - std::vector> edges(typeclasses_.size()); - - for (size_t i = 0; i < typeclasses_.size(); ++i) { - edges[i].reserve(typeclasses_[i].dependencies.size()); - for (auto& dependency :typeclasses_[i].dependencies) { - auto dependency_iter = name_to_typeclass_.find(dependency); - - if (dependency_iter == name_to_typeclass_.end()) { - return false; - } - - edges[i].push_back(dependency_iter->second); - } - } - - std::vector sorted_verticles = utils::BackTopSort(edges); - std::reverse(sorted_verticles.begin(), sorted_verticles.end()); - - for (auto& id : sorted_verticles) { - for (auto& dependency : typeclasses_[id].dependencies) { - for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) { - auto function_iter = typeclasses_[id].functions.find(method.first); - if (function_iter == typeclasses_[id].functions.end()) { - typeclasses_[id].functions[method.first] = method.second; - } else { - if (!function_iter->second.definition.has_value()) { - function_iter->second.definition = method.second.definition; - } - } - } - for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) { - typeclasses_[id].dependencies.insert(inherited_dependency); - } - } - } - - is_calculated_ = true; - - return true; - } + bool CalculateGraph(); private: std::unordered_map method_to_typeclass_; diff --git a/include/types.hpp b/include/types.hpp index ac3429d..4ed3403 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -8,6 +8,7 @@ #include // for clangd +#include "error_handling.hpp" #include "utils.hpp" namespace info::type { @@ -24,8 +25,8 @@ public: const std::vector& requirement_graph_ids) : modifier_(modifier), name_(name) { - for (auto& typeclass : requirement_graph_ids) { - requirement_graph_ids_.insert(typeclass); + for (auto& requirement_graph_id : requirement_graph_ids) { + requirement_graph_ids_.insert(requirement_graph_id); } } diff --git a/include/utils.hpp b/include/utils.hpp index 3f6008e..a475682 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -228,7 +228,8 @@ private: std::vector ranks_; }; -static void BackVisitDfs(size_t id, +// move to .cpp ?? +inline void BackVisitDfs(size_t id, std::vector& verticles, std::vector& marks, const std::vector>& edges, @@ -245,7 +246,8 @@ static void BackVisitDfs(size_t id, } } -static std::vector BackTopSort(const std::vector>& edges_) { +// move to .cpp ?? +inline std::vector BackTopSort(const std::vector>& edges_) { std::vector sorted_verticles; std::vector marks(edges_.size(), 0); diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 947357c..49c0cd6 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -1292,32 +1292,32 @@ void BuildVisitor::Visit(TupleType* node) { auto parse_node = current_node_; - size_t current_node_n = 0; + size_t current_child = 0; - current_node_ = parse_node.NthNamedChild(current_node_n); + current_node_ = parse_node.NthNamedChild(current_child); - if (current_node_.GetType() == parser::tokens::Constructor) { + if (parse_node.NthChild(0).GetValue() != "&") { node->type = current_node_.GetValue(); - ++current_node_n; - current_node_ = parse_node.NthNamedChild(current_node_n); + ++current_child; + current_node_ = parse_node.NthNamedChild(current_child); } - while (current_node_n < parse_node.NamedChildCount()) { + while (current_child < parse_node.NamedChildCount()) { node->entities.emplace_back(); if (current_node_.GetType() == parser::tokens::NameIdentifier) { node->entities.back().first = current_node_.GetValue(); - ++current_node_n; - current_node_ = parse_node.NthNamedChild(current_node_n); + ++current_child; + current_node_ = parse_node.NthNamedChild(current_child); } node->entities.back().second = std::make_unique(); Visit(node->entities.back().second.get()); - ++current_node_n; - current_node_ = parse_node.NthNamedChild(current_node_n); + ++current_child; + current_node_ = parse_node.NthNamedChild(current_child); } current_node_ = parse_node; @@ -1328,33 +1328,31 @@ void BuildVisitor::Visit(VariantType* node) { auto parse_node = current_node_; - size_t current_node_n = 0; + size_t excluded_child_count = 0; - current_node_ = parse_node.NthNamedChild(current_node_n); + size_t child_count = parse_node.NamedChildCount(); - if (current_node_.GetType() == parser::tokens::Constructor) { - node->type = current_node_.GetValue(); + if (parse_node.NthChild(0).GetValue() != "|") { + node->type = parse_node.NthNamedChild(0).GetValue(); - ++current_node_n; - current_node_ = parse_node.NthNamedChild(current_node_n); + ++excluded_child_count; } - while (current_node_n < parse_node.NamedChildCount()) { + + node->constructors.resize(child_count - excluded_child_count); + for (size_t i = 0; i < node->constructors.size(); ++i) { + current_node_ = parse_node.NthNamedChild(i + excluded_child_count); + std::string current_node_type = current_node_.GetType(); - node->constructors.emplace_back(); - if (current_node_type == parser::tokens::Constructor) { - node->constructors.back() = current_node_.GetValue(); + node->constructors[i] = current_node_.GetValue(); } else if (current_node_type == parser::tokens::TupleType) { - node->constructors.back() = std::make_unique(); - Visit(std::get>(node->constructors.back()).get()); + node->constructors[i] = std::make_unique(); + Visit(std::get>(node->constructors[i]).get()); } else { // error } - - ++current_node_n; - current_node_ = parse_node.NthNamedChild(current_node_n); } current_node_ = parse_node; diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp index f64c98a..39a2bf1 100644 --- a/src/execute_visitor.cpp +++ b/src/execute_visitor.cpp @@ -63,6 +63,7 @@ void ExecuteVisitor::Visit(PartitionStatement* node) { void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern // TODO +// TODO: tuples // TODO: non-variant constructor patterns void ExecuteVisitor::Visit(TypeConstructorPattern* node) { if (!node->constructor->constructor_id_.has_value()) { // checked in typeckeck visitor ?? @@ -475,7 +476,7 @@ void ExecuteVisitor::Visit(ReturnExpression* node) { void ExecuteVisitor::Visit(TypeConstructorParameter* node) {} // handled in TypeConstructor - +// TODO: variants, etc. void ExecuteVisitor::Visit(TypeConstructor* node) { // TODO: support for non-tuples std::vector, utils::IdType>> fields; @@ -493,6 +494,10 @@ void ExecuteVisitor::Visit(TypeConstructor* node) { current_value_ = context_manager_.AddValue( info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), utils::ValueType::Tmp); + + // if (constructor_info.order.has_value()) { + // // TODO: construct variant value + // } } // TODO diff --git a/src/global_info.cpp b/src/global_info.cpp index c90482b..5d3a461 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -167,42 +167,56 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, definition::Type& moved_type_info = global_info_.types_.back(); - // TODO: constructors for tuple types, function types (??), array types (??), ... + if (!std::holds_alternative(moved_type_info.type)) { + error_handling::HandleInternalError("Not AnyType constructor search is not implemented yet", + "GlobalInfo.NamespaceVisitor.AddType"); + } - if (std::holds_alternative(moved_type_info.type)) { - definition::AnyType& any_type_info = std::get(moved_type_info.type); - if (std::holds_alternative>(*any_type_info.value)) { - interpreter::tokens::VariantType& variant_type_info = *std::get>(*any_type_info.value); - for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) { - std::string constructor_name; - definition::Constructor constructor_info; + definition::AnyType& any_type_info = std::get(moved_type_info.type); + if (std::holds_alternative>(*any_type_info.value)) { + interpreter::tokens::VariantType& variant_type_info = *std::get>(*any_type_info.value); + for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) { + std::string constructor_name; + definition::Constructor constructor_info; - constructor_info.type_id = id; - constructor_info.order = i; + constructor_info.type_id = id; + constructor_info.order = i; - if (std::holds_alternative(variant_type_info.constructors[i])) { - constructor_name = std::get(variant_type_info.constructors[i]); - } else if (std::holds_alternative< - std::unique_ptr>(variant_type_info.constructors[i])) { - constructor_info.constructor_tuple_node = - std::get>(variant_type_info.constructors[i]).get(); + if (std::holds_alternative(variant_type_info.constructors[i])) { + constructor_name = std::get(variant_type_info.constructors[i]); + } else if (std::holds_alternative< + std::unique_ptr>(variant_type_info.constructors[i])) { + constructor_info.constructor_tuple_node = + std::get>(variant_type_info.constructors[i]).get(); - auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type; + auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type; - if (maybe_constructor_name.has_value()) { - constructor_name = maybe_constructor_name.value(); - } else { - constructor_name = type; - } + if (maybe_constructor_name.has_value()) { + constructor_name = maybe_constructor_name.value(); } else { - // error + constructor_name = type; } - - constructor_info.name = constructor_name; - - AddConstructor(constructor_name, std::move(constructor_info), base_node); + } else { + error_handling::HandleInternalError("Unexprected VariantType constructor node type", + "GlobalInfo.NamespaceVisitor.AddType"); } + + constructor_info.name = constructor_name; + + AddConstructor(constructor_name, std::move(constructor_info), base_node); } + } else if (std::holds_alternative>(*any_type_info.value)) { + definition::Constructor constructor_info; + constructor_info.type_id = id; + // constructor_info.order = std::nullopt; + constructor_info.name = type; + constructor_info.constructor_tuple_node = std::get>(*any_type_info.value).get(); + + AddConstructor(type, std::move(constructor_info), base_node); + } else { + // TODO: constructors for function types (??), array types (??), ... + error_handling::HandleInternalError("Not VariantType constructor search is not implemented yet", + "GlobalInfo.NamespaceVisitor.AddType"); } return id; diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 0c0ab08..c8ab880 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -1,3 +1,4 @@ +#include #include // for clangd @@ -26,6 +27,7 @@ void LinkSymbolsVisitor::Visit(Namespace* node) { if (maybe_type.has_value()) { node->link_type_id_ = maybe_type.value(); } + if (maybe_typeclass.has_value()) { node->link_typeclass_id_ = maybe_typeclass.value(); if (!namespace_visitor_.IsInGlobalNamespace()) { diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 6bbff14..b7e5ca5 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -36,10 +36,12 @@ void TypeCheckVisitor::Visit(Namespace* node) { if (node->link_typeclass_id_.has_value()) { utils::IdType graph_id = global_info_.GetTypeclassInfo(node->link_typeclass_id_.value()).graph_id_; - std::vector requirements = typeclass_graph_.GetTypeclassDependencies(graph_id); - requirements.push_back(graph_id); + std::vector requirement_graph_ids = typeclass_graph_.GetTypeclassDependencies(graph_id); + requirement_graph_ids.push_back(graph_id); utils::IdType abstract_type = context_manager_.AddValue( - info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements), + info::type::AbstractType(utils::AbstractTypeModifier::Abstract, + node->type, + requirement_graph_ids), ClassInternalsModifierToValueType(node->modifier)); if (node->modifier != utils::ClassInternalsModifier::Static) { @@ -48,29 +50,42 @@ void TypeCheckVisitor::Visit(Namespace* node) { } else { context_manager_.EnterContext(); } - context_manager_.DefineLocalType(node->type, abstract_type); + + // including namespace typeclass + // define typeclasses local types as namespace typeclass + for (auto& requirement_graph_id : requirement_graph_ids) { + context_manager_.DefineLocalType(typeclass_graph_.GetTypeclass(requirement_graph_id).name, abstract_type); + } } else if (node->link_type_id_.has_value()) { + auto maybe_type_info = global_info_.GetTypeInfo(node->link_type_id_.value()); + + if (!maybe_type_info.has_value()) { + error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base); + } + + info::definition::AnyType* type_info = maybe_type_info.value(); + + Visitor::Visit(*type_info->value); + utils::IdType type = context_manager_.AddValue( + info::type::DefinedType(node->link_type_id_.value(), + current_type_, + type_info->modifier, + context_manager_.GetValueManager()), + ClassInternalsModifierToValueType(node->modifier)); + if (node->modifier != utils::ClassInternalsModifier::Static) { - auto maybe_type_info = global_info_.GetTypeInfo(node->link_type_id_.value()); - - if (!maybe_type_info.has_value()) { - error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base); - } - - Visitor::Visit(*maybe_type_info.value()->value); // handle error? - - context_manager_.EnterVariableContext( - utils::ClassInternalVarName, - context_manager_.AddValue( - info::type::DefinedType(node->link_type_id_.value(), - current_type_, - maybe_type_info.value()->modifier, - context_manager_.GetValueManager()), - ClassInternalsModifierToValueType(node->modifier))); + context_manager_.EnterVariableContext(utils::ClassInternalVarName, type); } else { context_manager_.EnterContext(); } + // better decision ?? + // define typeclasses local types as namespace type + auto typeclass_graph_ids = global_info_.GetAnnotatedTypeTypeclassesVector(type_info->type.node); + for (auto& typeclass_graph_id : typeclass_graph_ids) { + context_manager_.DefineLocalType(typeclass_graph_.GetTypeclass(typeclass_graph_id).name, type); + } + if (type_namespaces_.count(node->link_type_id_.value()) != 0) { error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base); } @@ -344,6 +359,7 @@ void TypeCheckVisitor::Visit(AnyAnnotatedType* node) { void TypeCheckVisitor::Visit(TypeConstructorPatternParameter* node) {} // Handled in TypeConstructorPattern // TODO +// TODO: check for tuples void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match named constructor if (!node->constructor->constructor_id_.has_value()) { error_handling::HandleTypecheckError("Type constructor pattern constructor name not found", node->base); @@ -815,6 +831,7 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) { void TypeCheckVisitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit +// TODO: check for tuples void TypeCheckVisitor::Visit(TypeConstructor* node) { if (!node->constructor->constructor_id_.has_value()) { error_handling::HandleTypecheckError("Type constructor name not found", node->base); @@ -884,10 +901,15 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { std::optional maybe_variant_type = context_manager_.GetValue(current_type_); - if (maybe_type_info.has_value()) { - maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order); + if (maybe_variant_type.has_value()) { + if (!constructor_info.order.has_value()) { + error_handling::HandleInternalError("No order found in constructor of VariantType", "TypeCheckVisitor.TypeConstructor"); + } + maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order.value()); } + // if it is tuple, order not required + current_type_ = TypeInContext(current_type_, context); node->base.type_ = current_type_; @@ -1405,7 +1427,7 @@ std::optional } // TODO: internal types ?? -// TODO: abstract types, typeclasses +// TODO: handle abstract defined types ?? std::optional TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node, TypeExpression* type_node, @@ -1540,26 +1562,30 @@ std::optional auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); if (!maybe_typeclass_graph_id.has_value()) { - error_handling::HandleTypecheckError("Typeclass function not found", node->base); + return std::nullopt; + // error_handling::HandleTypecheckError("Typeclass function not found", node->base); } auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, maybe_typeclass_graph_id.value()); - if (abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) { - if (!maybe_typeclass_function_info.has_value()) { - error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)", - "TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate"); - } - - if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) { - return std::nullopt; - } - - node->typeclass_graph_id_ = maybe_typeclass_graph_id; - maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; + if (!abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) { + error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (abstract type)", node->base); } + if (!maybe_typeclass_function_info.has_value()) { + error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)", + "TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate"); + } + + // TODO: check that const functions not called on var expressions + if ((maybe_typeclass_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) { + error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); + } + + node->typeclass_graph_id_ = maybe_typeclass_graph_id; + maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; + return maybe_function_declaration; } @@ -1571,27 +1597,31 @@ std::optional std::optional maybe_function_declaration; auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); - if (maybe_typeclass_graph_id.has_value()) { - auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node); - auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value()); - - if (function_typeclass_iter != typeclasses.end()) { - auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, - maybe_typeclass_graph_id.value()); - if (!maybe_typeclass_function_info.has_value()) { - error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (definied type)", - "TypeCheckVisitor.FindDefinedTypeTypeclassFunctionAndUpdate"); - } - - if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) { - return std::nullopt; - } - - node->typeclass_graph_id_ = maybe_typeclass_graph_id; - maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; - } + if (!maybe_typeclass_graph_id.has_value()) { + return std::nullopt; } + auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node); + auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value()); + + if (function_typeclass_iter == typeclasses.end()) { + error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (defined type)", node->base); + } + + auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, + maybe_typeclass_graph_id.value()); + if (!maybe_typeclass_function_info.has_value()) { + error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (definied type)", + "TypeCheckVisitor.FindDefinedTypeTypeclassFunctionAndUpdate"); + } + + if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) { + return std::nullopt; + } + + node->typeclass_graph_id_ = maybe_typeclass_graph_id; + maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; + return maybe_function_declaration; } diff --git a/src/typeclass_graph.cpp b/src/typeclass_graph.cpp new file mode 100644 index 0000000..4fb99ef --- /dev/null +++ b/src/typeclass_graph.cpp @@ -0,0 +1,142 @@ +// for clangd +#include "../include/typeclass_graph.hpp" + +namespace info { + +std::optional TypeclassGraph::AddTypeclass( + const std::string& name, + interpreter::tokens::TypeclassDefinitionStatement* definition, + const std::vector& dependencies, // TODO: parameters + const std::vector>>& function_declarations, + const std::vector>& function_definitions) { + for (auto& method : function_declarations) { + if (method_to_typeclass_.count(method.first) != 0) { + return std::nullopt; + } + } + + is_calculated_ = false; + + utils::IdType id = typeclasses_.size(); + + typeclasses_.emplace_back(); + TypeclassVertex& typeclass = typeclasses_.back(); + typeclass.name = name; + typeclass.definition = definition; + + for (auto& dependency : dependencies) { + typeclass.dependencies.insert(dependency); + } + + for (auto& method : function_declarations) { + FunctionInfo function_info; + function_info.modifier = method.second.first; + function_info.declaration = method.second.second; + + typeclass.functions[method.first] = function_info; + + method_to_typeclass_[method.first] = id; + } + name_to_typeclass_[name] = id; + + for (auto& method : function_definitions) { + typeclass.functions[method.first].definition = method.second; + } + + return id; +} + +std::optional TypeclassGraph::FindFunctionTypeclass(const std::string& name) { + auto function_iter = method_to_typeclass_.find(name); + if (function_iter == method_to_typeclass_.end()) { + return std::nullopt; + } + return function_iter->second; +} + +std::optional TypeclassGraph::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]; +} + +// cache ?? +std::vector TypeclassGraph::GetTypeclassDependencies(utils::IdType id) { + std::vector dependencies; + + dependencies.reserve(typeclasses_.at(id).dependencies.size()); + for (auto& dependency : typeclasses_[id].dependencies) { + dependencies.push_back(name_to_typeclass_[dependency]); + } + + return dependencies; +} + +// cache ?? +std::vector> TypeclassGraph::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}); + } + + return functions; +} + +bool TypeclassGraph::CalculateGraph() { + if (is_calculated_) { + return true; + } + + std::vector> edges(typeclasses_.size()); + + for (size_t i = 0; i < typeclasses_.size(); ++i) { + edges[i].reserve(typeclasses_[i].dependencies.size()); + for (auto& dependency :typeclasses_[i].dependencies) { + auto dependency_iter = name_to_typeclass_.find(dependency); + + if (dependency_iter == name_to_typeclass_.end()) { + return false; + } + + edges[i].push_back(dependency_iter->second); + } + } + + std::vector sorted_verticles = utils::BackTopSort(edges); + std::reverse(sorted_verticles.begin(), sorted_verticles.end()); + + for (auto& id : sorted_verticles) { + for (auto& dependency : typeclasses_[id].dependencies) { + for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) { + auto function_iter = typeclasses_[id].functions.find(method.first); + if (function_iter == typeclasses_[id].functions.end()) { + typeclasses_[id].functions[method.first] = method.second; + } else { + if (!function_iter->second.definition.has_value()) { + function_iter->second.definition = method.second.definition; + } + } + } + for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) { + typeclasses_[id].dependencies.insert(inherited_dependency); + } + } + } + + is_calculated_ = true; + + return true; +} + +} // namespace info