From 9aeba7b0de1da7ceebaeaaaf467ac1199fdd37c8 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Sun, 14 May 2023 13:05:46 +0300 Subject: [PATCH] part of typeclass_graph --- include/definitions.hpp | 6 ++- include/find_symbols_visitor.hpp | 1 + include/global_info.hpp | 20 +++++++- include/link_symbols_visitor.hpp | 2 +- include/typeclass_graph.hpp | 87 +++++++++++--------------------- src/find_symbols_visitor.cpp | 12 +++-- src/global_info.cpp | 82 ++++++++++++++++++++++++++++-- src/link_symbols_visitor.cpp | 12 +++++ 8 files changed, 154 insertions(+), 68 deletions(-) diff --git a/include/definitions.hpp b/include/definitions.hpp index 5eed539..821d4f0 100644 --- a/include/definitions.hpp +++ b/include/definitions.hpp @@ -80,6 +80,8 @@ struct Function { struct Typeclass { std::vector parameters; interpreter::tokens::TypeclassDefinitionStatement* node; + + utils::IdType parent_namespace; }; struct Import { @@ -98,8 +100,10 @@ struct Namespace { utils::IdType parent_namespace; - utils::ClassInternalsModifier modifier; + utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; std::string type_name; + + std::optional node; }; } // namespace info::definition diff --git a/include/find_symbols_visitor.hpp b/include/find_symbols_visitor.hpp index a5eeb17..ac9588a 100644 --- a/include/find_symbols_visitor.hpp +++ b/include/find_symbols_visitor.hpp @@ -4,6 +4,7 @@ #include // for clangd +#include "interpreter_tree.hpp" #include "visitor.hpp" #include "global_info.hpp" diff --git a/include/global_info.hpp b/include/global_info.hpp index 072c5b7..2e2aae4 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -41,6 +41,7 @@ public: void AddEnterNamespace(const std::string& name, utils::ClassInternalsModifier modifier, + std::optional node, const interpreter::tokens::BaseNode& base_node); void EnterNamespace(const std::string& name, @@ -204,9 +205,17 @@ public: return current_path_; } - utils::IdType GetCurrentNamespace() { + utils::IdType GetCurrentNamespaceId() { return namespace_stack_.back(); } + + definition::Namespace* GetCurrentNamespace() { + return &global_info_.namespaces_[GetCurrentNamespaceId()]; + } + + bool IsInGlobalNamespace() { + return namespace_stack_.size() == 1; + } private: NamespaceVisitor(GlobalInfo& global_info) : global_info_(global_info), namespace_stack_ {global_info.GlobalNamespaceId} {} @@ -291,6 +300,15 @@ public: return &typeclass_graph_; } + std::optional AddTypeclassToGraph(utils::IdType typeclass); + +private: + void CollectFunctionInfo( + utils::IdType current_namespace, + utils::ClassInternalsModifier modifier, + std::vector>>& function_declarations, + std::vector>& function_definitions); + private: const utils::IdType GlobalNamespaceId = 0; diff --git a/include/link_symbols_visitor.hpp b/include/link_symbols_visitor.hpp index ca36ef0..963796f 100644 --- a/include/link_symbols_visitor.hpp +++ b/include/link_symbols_visitor.hpp @@ -33,7 +33,7 @@ private: // // void Visit(FunctionDefinitionStatement* node) override; // // void Visit(TypeDefinitionStatement* node) override; // // void Visit(AbstractTypeDefinitionStatement* node) override; - // // void Visit(TypeclassDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; // // void Visit(PartitionStatement* node) override; // Definition parts diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp index 28c12b4..2440d94 100644 --- a/include/typeclass_graph.hpp +++ b/include/typeclass_graph.hpp @@ -4,76 +4,42 @@ #include #include -// for calngd +// for clangd +#include "error_handling.hpp" +#include "global_info.hpp" #include "utils.hpp" #include "interpreter_tree.hpp" +#include "definitions.hpp" namespace info { class TypeclassGraph { public: - struct MethodInfo { + struct FunctionInfo { + utils::ClassInternalsModifier modifier; interpreter::tokens::FunctionDeclaration* declaration = nullptr; - std::optional definition; + std::optional definition; }; struct ParametrizedTypeclass { std::string typeclass; - std::vector parameters; // only abstract types from owner - }; - - struct AnnotatedType { - std::string name; - std::vector requirements; + // TODO: parameters }; struct TypeclassVertex { std::string name; interpreter::tokens::TypeclassDefinitionStatement* definition = nullptr; - std::unordered_map methods; + std::unordered_map functions; std::vector dependencies; - - std::vector parameters; + // TODO: parameters }; -// // TODO: write + rewrite -// std::optional AddTypeclassByNode(interpreter::tokens::TypeclassDefinitionStatement* node) { -// std::string name = node->definition->type->type; -// std::vector dependencies; -// // std::vector> function_declarations; -// // std::vector> function_definitions; -// // std::vector parameters; -// -// for (auto& dependency_node : node->definition->type->typeclasses) { -// ParametrizedTypeclass dependency; -// dependency.typeclass = dependency_node->typeclass; -// for (auto& dependency_parameter_node : dependency_node->parameters) { // TODO: all types, etc. -// dependency.parameters.push_back(dependency_parameter_node->type.type); -// if (dependency_parameter_node->type_id_.has_value()) { // TODO: more checks -// error_handling::HandleInternalError("Typeclasses with non-abstract parameters unimplemented", -// "TypeclassGraph.AddTypeclassByDefinition"); -// } -// } -// dependencies.push_back(dependency); -// } -// -// // TODO -// -// return AddTypeclass(name, -// node, -// dependencies, -// function_declarations, -// function_definitions, -// parameters); -// } - std::optional AddTypeclass( // move parameters ?? const std::string& name, interpreter::tokens::TypeclassDefinitionStatement* definition, const std::vector& dependencies, - const std::vector>& function_declarations, - const std::vector>& function_definitions, - const std::vector& 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; @@ -87,27 +53,31 @@ public: typeclass.name = name; typeclass.definition = definition; typeclass.dependencies = dependencies; - typeclass.parameters = parameters; 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(); - typeclass.methods[method.first].declaration = method.second; } name_to_typeclass_[name] = typeclasses_.size() - 1; for (auto& method : function_definitions) { - typeclass.methods[method.first].definition = method.second; + typeclass.functions[method.first].definition = method.second; } return typeclasses_.size() - 1; } std::optional FindMethodTypeclass(const std::string& name) { - auto method_iter = method_to_typeclass_.find(name); - if (method_iter == method_to_typeclass_.end()) { + auto function_iter = method_to_typeclass_.find(name); + if (function_iter == method_to_typeclass_.end()) { return std::nullopt; } - return method_iter->second; + return function_iter->second; } const TypeclassVertex& GetTypeclass(utils::IdType id) { // check, if calculated ?? @@ -143,13 +113,13 @@ public: for (auto& id : sorted_verticles) { for (auto& dependency : typeclasses_[id].dependencies) { - for (auto& method : typeclasses_[name_to_typeclass_[dependency.typeclass]].methods) { - auto method_iter = typeclasses_[id].methods.find(method.first); - if (method_iter == typeclasses_[id].methods.end()) { - typeclasses_[id].methods[method.first] = method.second; + for (auto& method : typeclasses_[name_to_typeclass_[dependency.typeclass]].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 (!method_iter->second.definition.has_value()) { - method_iter->second.definition = method.second.definition; + if (!function_iter->second.definition.has_value()) { + function_iter->second.definition = method.second.definition; } } } @@ -160,6 +130,7 @@ public: return true; } + private: std::unordered_map method_to_typeclass_; std::unordered_map name_to_typeclass_; diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index 9b97e15..3c5d000 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -10,7 +10,7 @@ namespace interpreter { // Namespaces, partitions ----------------- void FindSymbolsVisitor::Visit(Namespace* node) { - namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node->base); + namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node, node->base); Visitor::Visit(&node->scope); @@ -44,6 +44,11 @@ void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) { } void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { + info::definition::Namespace* current_namespace = namespace_visitor_.GetCurrentNamespace(); + if (current_namespace->node.has_value() && current_namespace->node.value()->link_typeclass_id_.has_value()) { + error_handling::HandleTypecheckError("Can't declare typeclass methods not as requirements", node->base); + } + info::definition::FunctionDeclaration info; info.parameters.resize(node->parameters.size()); @@ -97,7 +102,7 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { } any_type_info.value = &node->value; - any_type_info.parent_namespace = namespace_visitor_.GetCurrentNamespace(); + any_type_info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId(); any_type_info.modifier = node->modifier; std::string type = any_type_info.type.type; @@ -136,12 +141,13 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { } for (size_t i = 0; i < node->requirements.size(); ++i) { - namespace_visitor_.AddEnterNamespace(type_name, node->requirements[i].first, node->base); + namespace_visitor_.AddEnterNamespace(type_name, node->requirements[i].first, std::nullopt, node->base); Visit(node->requirements[i].second.get()); namespace_visitor_.ExitNamespace(); } info.node = node; + info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId(); node->typeclass_id_ = namespace_visitor_.AddTypeclass(type_name, std::move(info), node->base); } diff --git a/src/global_info.cpp b/src/global_info.cpp index d95f3a9..17e902c 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -19,6 +19,7 @@ void GlobalInfo::NamespaceVisitor::AddImport(definition::Import&& import_info, void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, utils::ClassInternalsModifier modifier, + std::optional node, const interpreter::tokens::BaseNode& base_node) { if (type::ToInternalType(name).has_value()) { error_handling::HandleTypecheckError("Can't define basic type namespace", base_node); @@ -33,15 +34,14 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, id = global_info_.namespaces_.size(); (*current_namespaces)[name] = id; global_info_.namespaces_.emplace_back(); + + global_info_.namespaces_.back().modifier = modifier; + global_info_.namespaces_.back().node = node; } else { id = namespace_iter->second; } definition::Namespace* namespace_info = &global_info_.namespaces_[id]; - if (modifier != utils::ClassInternalsModifier::Static) { - namespace_info->modifier = modifier; - } - namespace_info->parent_namespace = namespace_stack_.back(); namespace_info->type_name = name; @@ -464,4 +464,78 @@ std::unordered_map* 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); + + std::string name = typeclass_info->node->definition->type->type; + std::vector dependencies; + std::vector>> function_declarations; + std::vector> function_definitions; + + for (auto& dependency_node : typeclass_info->node->definition->type->typeclasses) { + TypeclassGraph::ParametrizedTypeclass dependency; + dependency.typeclass = dependency_node->typeclass; + if (dependency_node->parameters.size() > 0) { + error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", + "TypeclassGraph.AddTypeclassByNode"); + } + dependencies.push_back(dependency); + } + + auto namespace_iter = parent_namespace->namespaces.find(name); + if (namespace_iter != parent_namespace->namespaces.end()) { + CollectFunctionInfo(namespace_iter->second, + utils::ClassInternalsModifier::Static, + function_declarations, + function_definitions); + } + + auto const_namespace_iter = parent_namespace->const_namespaces.find(name); + if (namespace_iter != parent_namespace->const_namespaces.end()) { + CollectFunctionInfo(namespace_iter->second, + utils::ClassInternalsModifier::Const, + function_declarations, + function_definitions); + } + + auto var_namespace_iter = parent_namespace->var_namespaces.find(name); + if (namespace_iter != parent_namespace->var_namespaces.end()) { + CollectFunctionInfo(namespace_iter->second, + utils::ClassInternalsModifier::Var, + function_declarations, + function_definitions); + } + + // TODO + + return typeclass_graph_.AddTypeclass(name, + typeclass_info->node, + dependencies, + function_declarations, + function_definitions); +} + +void GlobalInfo::CollectFunctionInfo( + utils::IdType current_namespace, + utils::ClassInternalsModifier modifier, + std::vector>>& function_declarations, + std::vector>& function_definitions) { + for (auto& function : GetNamespaceInfo(current_namespace).functions) { + definition::Function function_info = GetFunctionInfo(function.second); + + if (function_info.declaration.has_value()) { + function_declarations.push_back( + {function.first, + {modifier, function_info.declaration.value().node}}); + } + + if (function_info.definition.has_value()) { + function_definitions.push_back({function.first, function_info.definition.value().node}); + } + } +} + } // namespace info diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index aa2e9b6..57c79fa 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -37,6 +37,18 @@ void LinkSymbolsVisitor::Visit(Namespace* node) { namespace_visitor_.ExitNamespace(); } +// Definitions ----------------- + +// TODO: add to typeclass graph, etc. (+ check) +void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { + Visitor::Visit(node->definition.get()); + for (auto& function_requirement : node->requirements) { + Visitor::Visit(function_requirement.second.get()); + } + + namespace_visitor_.GetGlobalInfo()->AddTypeclassToGraph(node->typeclass_id_); +} + // Type, typeclass, etc. ----------------- // Type