diff --git a/include/global_info.hpp b/include/global_info.hpp index ddcab00..660400e 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -350,19 +350,19 @@ public: return &typeclass_graph_; } - std::unordered_set - GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node); - - std::vector - GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node); - - std::unordered_map - GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node, - const interpreter::tokens::BaseNode& base_node); - - std::vector> - GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node, - const interpreter::tokens::BaseNode& base_node); + // std::unordered_set + // GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node); + // + // std::vector + // GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node); + // + // std::unordered_map + // GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node, + // const interpreter::tokens::BaseNode& base_node); + // + // std::vector> + // GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node, + // const interpreter::tokens::BaseNode& base_node); std::unordered_map* ChooseNamespaces( utils::ClassInternalsModifier modifier, @@ -370,6 +370,9 @@ public: std::optional AddTypeclassToGraph(utils::IdType typeclass); + // function declarations & definitions should be added latter + std::optional AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node); + private: void CollectFunctionInfo( utils::IdType current_namespace, diff --git a/include/link_symbols_visitor.hpp b/include/link_symbols_visitor.hpp index 6adc3c9..5307396 100644 --- a/include/link_symbols_visitor.hpp +++ b/include/link_symbols_visitor.hpp @@ -17,9 +17,7 @@ public: void VisitSourceFile(SourceFile* source_file) override { Visitor::Visit(source_file); - if (!namespace_visitor_.GetTypeclassGraph()->CalculateGraph()) { - error_handling::HandleInternalError("Can't calculate typeclass graph", "LinkSymbolsVisitor.VisitSourceFile"); - } + namespace_visitor_.GetTypeclassGraph()->CalculateGraph(); } private: @@ -39,7 +37,7 @@ private: // // void Visit(VariableDefinitionStatement* node) override; // // void Visit(FunctionDeclaration* node) override; // // void Visit(FunctionDefinitionStatement* node) override; - // // void Visit(TypeDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; // // void Visit(AbstractTypeDefinitionStatement* node) override; void Visit(TypeclassDefinitionStatement* node) override; // // void Visit(PartitionStatement* node) override; diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp index 7c23d55..40b4806 100644 --- a/include/typeclass_graph.hpp +++ b/include/typeclass_graph.hpp @@ -12,57 +12,77 @@ namespace info { +// move constructor parameters ?? class TypeclassGraph { public: + enum class Modifier { + Typeclass = 0, + Type = 1, + }; + struct FunctionInfo { utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; interpreter::tokens::FunctionDeclaration* declaration = nullptr; std::optional definition; + bool is_defined_in_owner = false; }; - struct TypeclassVertex { + struct Vertex { // make constructor ?? std::string name; - interpreter::tokens::TypeclassDefinitionStatement* definition = nullptr; std::unordered_map functions; std::unordered_set dependencies; // TODO: parameters + interpreter::tokens::BaseNode* base_node; // for error handling + Modifier modifier; }; - std::optional AddTypeclass( // move parameters ?? + utils::IdType AddVertex( const std::string& name, - interpreter::tokens::TypeclassDefinitionStatement* definition, - const std::vector& dependencies, // TODO: parameters + const std::vector& dependencies, const std::vector>>& function_declarations, - const std::vector>& function_definitions); + const std::vector>& function_definitions, + interpreter::tokens::BaseNode* base_node, + Modifier modifier); 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; + bool IsFunctionInVertex(const std::string& name, utils::IdType vertex_id) { + return verticles_[vertex_id].functions.count(name) != 0; } + // if vertex_id == std::nullopt, info can be not complete std::optional GetFunctionInfo(const std::string& name, - std::optional typeclass_id); + std::optional vertex_id); - const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ?? - return typeclasses_.at(typeclass_id); + const Vertex& GetVertex(utils::IdType id) { + return verticles_.at(id); + } + + std::optional GetTypeVertex(utils::IdType id) { + if (verticles_.at(id).modifier == Modifier::Type) { + return &verticles_[id]; + } + return std::nullopt; } // cache ?? - std::vector GetTypeclassDependencies(utils::IdType id); + std::unordered_set GetDependenciesSet(utils::IdType id); + std::vector GetDependenciesVector(utils::IdType id); - // cache ?? - std::vector> GetTypeclassFunctions(utils::IdType id); + const std::unordered_map& GetVertexFunctions(utils::IdType id) { + return verticles_.at(id).functions; + } bool IsCalculated() { return is_calculated_; } - bool CalculateGraph(); + // can exit by typecheck error + void CalculateGraph(); private: - std::unordered_map method_to_typeclass_; + std::unordered_map method_to_vertex_; std::unordered_map name_to_typeclass_; - std::vector typeclasses_; + std::vector verticles_; bool is_calculated_ = true; }; diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index b40b91c..10191a4 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -49,6 +49,8 @@ void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) { info.type = std::move(alias_info); node->type_id_ = namespace_visitor_.AddType(node->type, std::move(info), node->base); + + Visitor::Visit(node->value.get()); // to visit all tree } void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { @@ -69,6 +71,8 @@ void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { info.node = node; node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name, std::move(info), node->base); + + Visitor::Visit(node->type.get()); // to visit all tree } void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) { @@ -84,6 +88,9 @@ void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) { info.node = node; node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info), node->base); + + Visitor::Visit(definition); // to visit all tree + Visitor::Visit(node->value); // to visit all tree } void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { @@ -113,6 +120,9 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { info.type = std::move(any_type_info); node->type_id_ = namespace_visitor_.AddType(type, std::move(info), node->base); + + // definition visited earlier + Visitor::Visit(node->value); // to visit all tree } void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) { @@ -153,10 +163,14 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId(); node->typeclass_id_ = namespace_visitor_.AddTypeclass(typeclass_name, std::move(info), node->base); + + // no need to visit definition->type, because it is typeclass } void FindSymbolsVisitor::Visit(PartitionStatement* node) { node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node, node->base); + + Visitor::Visit(node->value); // to visit all tree } // Definition parts @@ -171,8 +185,19 @@ void FindSymbolsVisitor::Visit(AnyAnnotatedType* node) { info.typeclass_nodes[i] = node->typeclasses[i].get(); } + for (auto& typeclass : node->typeclasses) { + Visitor::Visit(typeclass.get()); // to visit all tree + } + info.node = node; + auto maybe_graph_id = namespace_visitor_.GetGlobalInfo()->AddAnnotatedTypeToGraph(node); // definitions and declarations should be added latter + + if (!maybe_graph_id.has_value()) { + error_handling::HandleInternalError("Can't add annotated type to typeclass graph", + "FindSymbolsVisitor.AnyAnnotatedType"); + } + current_info_ = std::move(info); } diff --git a/src/global_info.cpp b/src/global_info.cpp index 456e460..e120cf4 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -460,79 +460,79 @@ std::optional GlobalInfo::NamespaceVisitor::FindNamespaceIn( // -// 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 // TODO: optimize, cache - GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node, - const interpreter::tokens::BaseNode& base_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) { - auto requirement_iter = functions.find(requirement.first); - if (requirement_iter == functions.end()) { - functions[requirement.first] = *requirement.second; - } else { - if (requirement_iter->second.definition.has_value()) { - if (requirement.second->definition.has_value()) { - error_handling::HandleTypecheckError("Function defined more then in one type requirement", base_node); - } - } else { - requirement_iter->second.definition = requirement.second->definition; - } - } - } - } - return functions; -} - -std::vector> // TODO: optimize, cache - GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node, - const interpreter::tokens::BaseNode& base_node) { - - auto functions_set = GetAnnotatedTypeFunctionsMap(node, base_node); - - std::vector> functions_vector; - functions_vector.reserve(functions_vector.size()); - for (auto& typeclass : functions_set) { - functions_vector.push_back(typeclass); - } - return functions_vector; -} +// // 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 // TODO: optimize, cache +// GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node, +// const interpreter::tokens::BaseNode& base_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) { +// auto requirement_iter = functions.find(requirement.first); +// if (requirement_iter == functions.end()) { +// functions[requirement.first] = *requirement.second; +// } else { +// if (requirement_iter->second.definition.has_value()) { +// if (requirement.second->definition.has_value()) { +// error_handling::HandleTypecheckError("Function defined more then in one type requirement", base_node); +// } +// } else { +// requirement_iter->second.definition = requirement.second->definition; +// } +// } +// } +// } +// return functions; +// } +// +// std::vector> // TODO: optimize, cache +// GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node, +// const interpreter::tokens::BaseNode& base_node) { +// +// auto functions_set = GetAnnotatedTypeFunctionsMap(node, base_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::ChooseNamespaces(utils::ClassInternalsModifier modifier, @@ -558,6 +558,7 @@ std::optional GlobalInfo::AddTypeclassToGraph(utils::IdType typec definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace); std::string name = typeclass_info->node->definition->type->type; + interpreter::tokens::BaseNode* base_node = &typeclass_info->node->base; std::vector dependencies; std::vector>> function_declarations; std::vector> function_definitions; @@ -566,7 +567,7 @@ std::optional GlobalInfo::AddTypeclassToGraph(utils::IdType typec std::string dependency = dependency_node->typeclass; if (dependency_node->parameters.size() > 0) { error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", - "TypeclassGraph.AddTypeclassByNode"); + "GlobalInfo.AddTypeclassToGraph"); } dependencies.push_back(dependency); } @@ -595,11 +596,34 @@ std::optional GlobalInfo::AddTypeclassToGraph(utils::IdType typec function_definitions); } - return typeclass_graph_.AddTypeclass(name, - typeclass_info->node, - dependencies, - function_declarations, - function_definitions); + return typeclass_graph_.AddVertex(name, + dependencies, + function_declarations, + function_definitions, + base_node, + TypeclassGraph::Modifier::Typeclass); +} + +std::optional GlobalInfo::AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node) { + std::string name = node->type; + interpreter::tokens::BaseNode* base_node = &node->base; + std::vector dependencies; + + for (auto& dependency_node : node->typeclasses) { + std::string dependency = dependency_node->typeclass; + if (dependency_node->parameters.size() > 0) { + error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", + "GlobalInfo.AddAnnotatedTypeToGraph"); + } + dependencies.push_back(dependency); + } + + return typeclass_graph_.AddVertex(name, + dependencies, + {}, + {}, + base_node, + TypeclassGraph::Modifier::Type); } void GlobalInfo::CollectFunctionInfo( diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index c8ab880..5eff807 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -47,6 +47,13 @@ void LinkSymbolsVisitor::Visit(Namespace* node) { // Definitions ----------------- +void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) { + Visitor::Visit(node->definition.get()); + Visitor::Visit(node->value); + + // TODO: add type declarations / definitions +} + void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { Visitor::Visit(node->definition.get()); for (auto& function_requirement : node->requirements) { diff --git a/src/typeclass_graph.cpp b/src/typeclass_graph.cpp index 4fb99ef..0fa996c 100644 --- a/src/typeclass_graph.cpp +++ b/src/typeclass_graph.cpp @@ -1,31 +1,41 @@ // for clangd #include "../include/typeclass_graph.hpp" +#include "../include/error_handling.hpp" namespace info { -std::optional TypeclassGraph::AddTypeclass( +utils::IdType TypeclassGraph::AddVertex( 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; + const std::vector>& function_definitions, + interpreter::tokens::BaseNode* base_node, + Modifier modifier) { + + if (name_to_typeclass_.count(name) != 0) { + error_handling::HandleTypecheckError("Typeclass \"" + name + "\" already defined (other type / typeclass can't have this name)", *base_node); + } + + if (modifier == Modifier::Typeclass) { + for (auto& method : function_declarations) { + if (method_to_vertex_.count(method.first) != 0) { + error_handling::HandleTypecheckError("Typeclass \"" + name + "\" method \"" + method.first + "\" already declaret in another typeclass", *base_node); + } } } is_calculated_ = false; - utils::IdType id = typeclasses_.size(); + utils::IdType id = verticles_.size(); - typeclasses_.emplace_back(); - TypeclassVertex& typeclass = typeclasses_.back(); - typeclass.name = name; - typeclass.definition = definition; + verticles_.emplace_back(); + Vertex& vertex = verticles_.back(); + vertex.name = name; + vertex.base_node = base_node; + vertex.modifier = modifier; for (auto& dependency : dependencies) { - typeclass.dependencies.insert(dependency); + vertex.dependencies.insert(dependency); } for (auto& method : function_declarations) { @@ -33,31 +43,37 @@ std::optional TypeclassGraph::AddTypeclass( function_info.modifier = method.second.first; function_info.declaration = method.second.second; - typeclass.functions[method.first] = function_info; + vertex.functions[method.first] = function_info; - method_to_typeclass_[method.first] = id; + if (modifier == Modifier::Typeclass) { + method_to_vertex_[method.first] = id; + } + } + if (modifier == Modifier::Typeclass) { + name_to_typeclass_[name] = id; } - name_to_typeclass_[name] = id; for (auto& method : function_definitions) { - typeclass.functions[method.first].definition = method.second; + FunctionInfo& function_info = vertex.functions[method.first]; + function_info.definition = method.second; + function_info.is_defined_in_owner = true; } 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()) { + auto function_iter = method_to_vertex_.find(name); + if (function_iter == method_to_vertex_.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]; + std::optional vertex_id) { + if (vertex_id.has_value()) { + return &verticles_[vertex_id.value()].functions[name]; } auto maybe_function_typeclass_id = FindFunctionTypeclass(name); @@ -66,47 +82,45 @@ std::optional TypeclassGraph::GetFunctionInfo(con return std::nullopt; } - return &typeclasses_[maybe_function_typeclass_id.value()].functions[name]; + return &verticles_[maybe_function_typeclass_id.value()].functions[name]; } -// cache ?? -std::vector TypeclassGraph::GetTypeclassDependencies(utils::IdType id) { +std::unordered_set TypeclassGraph::GetDependenciesSet(utils::IdType id) { + std::unordered_set dependencies; + + dependencies.reserve(verticles_.at(id).dependencies.size()); + for (auto& dependency : verticles_[id].dependencies) { + dependencies.insert(name_to_typeclass_[dependency]); + } + + return dependencies; +} + +std::vector TypeclassGraph::GetDependenciesVector(utils::IdType id) { std::vector dependencies; - dependencies.reserve(typeclasses_.at(id).dependencies.size()); - for (auto& dependency : typeclasses_[id].dependencies) { + dependencies.reserve(verticles_.at(id).dependencies.size()); + for (auto& dependency : verticles_[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() { +void TypeclassGraph::CalculateGraph() { if (is_calculated_) { - return true; + return; } - std::vector> edges(typeclasses_.size()); + std::vector> edges(verticles_.size()); - for (size_t i = 0; i < typeclasses_.size(); ++i) { - edges[i].reserve(typeclasses_[i].dependencies.size()); - for (auto& dependency :typeclasses_[i].dependencies) { + for (size_t i = 0; i < verticles_.size(); ++i) { + edges[i].reserve(verticles_[i].dependencies.size()); + for (auto& dependency : verticles_[i].dependencies) { auto dependency_iter = name_to_typeclass_.find(dependency); if (dependency_iter == name_to_typeclass_.end()) { - return false; + error_handling::HandleTypecheckError("Dependency typeclass \"" + dependency + "\" not found", *verticles_[i].base_node); } edges[i].push_back(dependency_iter->second); @@ -117,26 +131,28 @@ bool TypeclassGraph::CalculateGraph() { 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; + for (auto& dependency : verticles_[id].dependencies) { + for (auto& method : verticles_[name_to_typeclass_[dependency]].functions) { + auto function_iter = verticles_[id].functions.find(method.first); + if (function_iter == verticles_[id].functions.end()) { + verticles_[id].functions[method.first] = method.second; } else { if (!function_iter->second.definition.has_value()) { function_iter->second.definition = method.second.definition; + } else { + if (!function_iter->second.is_defined_in_owner) { + error_handling::HandleTypecheckError("Method \"" + method.first + "\" defined in more then one dependency of type / typeclass \"" + verticles_[id].name + "\"", *verticles_[id].base_node); + } } } } - for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) { - typeclasses_[id].dependencies.insert(inherited_dependency); + for (auto& inherited_dependency : verticles_[method_to_vertex_[dependency]].dependencies) { + verticles_[id].dependencies.insert(inherited_dependency); } } } is_calculated_ = true; - - return true; } } // namespace info