#pragma once #include #include #include #include // for clangd #include "definitions.hpp" #include "interpreter_tree.hpp" #include "typeclass_graph.hpp" #include "utils.hpp" namespace info { // TODO: add classes / structs and functions module interface class GlobalInfo { friend class NamespaceVisitor; public: GlobalInfo() { namespaces_.emplace_back(); // global namespace } struct PartitionInfo { std::vector path; interpreter::tokens::PartitionStatement* node = nullptr; }; class NamespaceVisitor { friend GlobalInfo; NamespaceVisitor() = delete; public: struct Path { std::vector> path_types; definition::Namespace* result; }; void AddImport(definition::Import&& import_info, const std::optional& name = std::nullopt); void AddEnterNamespace(const std::string& name, utils::ClassInternalsModifier modifier, std::optional node, const interpreter::tokens::BaseNode& base_node); void EnterNamespace(const std::string& name, utils::ClassInternalsModifier modifier); void ExitNamespace(); void ToGlobalNamespace(); utils::IdType AddFunctionDeclaration(const std::string& name, definition::FunctionDeclaration&& function_declaration_info, const interpreter::tokens::BaseNode& base_node); utils::IdType AddFunctionDefinition(const std::string& name, definition::FunctionDefinition&& function_definition_info, const interpreter::tokens::BaseNode& base_node); utils::IdType AddType(const std::string& type, definition::Type&& type_info, const interpreter::tokens::BaseNode& base_node); utils::IdType AddAbstractType(const std::string& abstract_type, definition::AbstractType&& abstract_type_info, const interpreter::tokens::BaseNode& base_node); utils::IdType AddTypeclass(const std::string& typeclass, definition::Typeclass&& typeclass_info, const interpreter::tokens::BaseNode& base_node); utils::IdType AddConstructor(const std::string& constructor, definition::Constructor&& constructor_info, const interpreter::tokens::BaseNode& base_node); utils::IdType AddPartition(const std::vector& path, interpreter::tokens::PartitionStatement* node, const interpreter::tokens::BaseNode& base_node); std::optional FindNamespaceId(const std::optional>& path); std::optional FindFunctionId(const std::optional>& path, const std::string& name); std::optional FindMethodId(const std::optional>& path, const std::string& type, const std::string& name, utils::IsConstModifier modifier); std::optional FindTypeId(const std::optional>& path, const std::string& type); std::optional FindLocalTypeId(const std::string& type); std::optional FindAbstractTypeId(const std::string& abstract_type); std::optional FindTypeclassId(const std::string& typeclass); std::optional FindConstructorId(const std::optional>& path, const std::string& constructor); std::optional FindNamespace(const std::optional>& path) { std::optional id = FindNamespaceId(path); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetNamespaceInfo(id.value()); } std::optional FindFunction(const std::optional>& path, const std::string& name) { std::optional id = FindFunctionId(path, name); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetFunctionInfo(id.value()); } std::optional FindMethod(const std::optional>& path, const std::string& type, const std::string& name, utils::IsConstModifier modifier) { std::optional id = FindFunctionId(path, name); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetFunctionInfo(id.value()); } std::optional FindAnyType(const std::optional>& path, const std::string& type) { std::optional id = FindTypeId(path, type); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetAnyTypeInfo(id.value()); } template std::optional FindType(const std::optional>& path, const std::string& type) { std::optional id = FindTypeId(path, type); if (!id.has_value()) { return std::nullopt; } return global_info_.GetTypeInfo(id.value()); } std::optional FindAnyLocalType(const std::string& type) { std::optional id = FindLocalTypeId(type); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetAnyTypeInfo(id.value()); } template std::optional FindLocalType(const std::string& type) { std::optional id = FindLocalTypeId(type); if (!id.has_value()) { return std::nullopt; } return global_info_.GetTypeInfo(id.value()); } std::optional FindAbstractType(const std::string& abstract_type) { std::optional id = FindAbstractTypeId(abstract_type); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetAbstractTypeInfo(id.value()); } std::optional FindTypeclass(const std::string& typeclass) { std::optional id = FindTypeclassId(typeclass); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetTypeclassInfo(id.value()); } std::optional FindConstructor(const std::optional>& path, const std::string& constructor) { std::optional id = FindConstructorId(path, constructor); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetConstructorInfo(id.value()); } NamespaceVisitor CreateVisitor() { return global_info_.CreateVisitor(); } GlobalInfo* GetGlobalInfo() { return &global_info_; } TypeclassGraph* GetTypeclassGraph() { return global_info_.GetTypeclassGraph(); } const std::vector& GetCurrentPath() { return current_path_; } // use only after LinkSymbolsVisitor std::vector GetCurrentPathTypes() { std::vector types; types.reserve(namespace_stack_.size()); for (auto& namespace_id : namespace_stack_) { definition::Namespace& namespace_info = global_info_.GetNamespaceInfo(namespace_id); if (namespace_info.any_node.has_value() && namespace_info.any_node.value()->link_type_id_.has_value()) { types.push_back(namespace_info.any_node.value()->link_type_id_.value()); } } return types; } utils::IdType GetCurrentNamespaceId() { return namespace_stack_.back(); } definition::Namespace* GetCurrentNamespace() { return &global_info_.namespaces_[GetCurrentNamespaceId()]; } std::optional GetCurrentNamespaceTypeId() { if (!GetCurrentNamespace()->any_node.has_value()) { return std::nullopt; } return GetCurrentNamespace()->any_node.value()->link_type_id_; } std::optional GetCurrentNamespaceAnyType() { std::optional id = GetCurrentNamespaceTypeId(); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetAnyTypeInfo(id.value()); } template std::optional GetCurrentNamespaceType() { std::optional id = GetCurrentNamespaceTypeId(); if (!id.has_value()) { return std::nullopt; } return global_info_.GetTypeInfo(id.value()); } std::optional GetCurrentNamespaceTypeclassId() { if (!GetCurrentNamespace()->any_node.has_value()) { return std::nullopt; } return GetCurrentNamespace()->any_node.value()->link_typeclass_id_; } std::optional GetCurrentNamespaceTypeclass() { std::optional id = GetCurrentNamespaceTypeclassId(); if (!id.has_value()) { return std::nullopt; } return &global_info_.GetTypeclassInfo(id.value()); } bool IsInGlobalNamespace() { return namespace_stack_.size() == 1; } private: NamespaceVisitor(GlobalInfo& global_info) : global_info_(global_info), namespace_stack_ {global_info.GlobalNamespaceId} {} template std::optional FindSomething( const std::optional>& path, std::function(utils::IdType)> search_func); std::optional FindNamespaceIn( utils::IdType current_namespace, const std::vector& path); private: GlobalInfo& global_info_; std::vector namespace_stack_; std::vector current_path_; }; NamespaceVisitor CreateVisitor() { return NamespaceVisitor(*this); } definition::Function& GetFunctionInfo(utils::IdType id) { return functions_.at(id); } definition::Type& GetAnyTypeInfo(utils::IdType id) { return types_.at(id); } template std::optional GetTypeInfo(utils::IdType id) { if (!std::holds_alternative(types_.at(id).type)) { return std::nullopt; } return &std::get(types_[id].type); } definition::AbstractType& GetAbstractTypeInfo(utils::IdType id) { return abstract_types_.at(id); } definition::Typeclass& GetTypeclassInfo(utils::IdType id) { return typeclasses_.at(id); } definition::Constructor& GetConstructorInfo(utils::IdType id) { return constructors_.at(id); } definition::Namespace& GetNamespaceInfo(utils::IdType id) { return namespaces_.at(id); } PartitionInfo& GetPartitionInfo(utils::IdType id) { return partitions_.at(id); } std::optional FindPartition(const std::vector& path) { auto trie_ans = partitions_trie_.Find(path); return trie_ans.has_value() ? std::optional(*trie_ans.value()) : std::nullopt; } std::vector FindPartitionsByPrefix(const std::vector& path) { // optimize ?? auto trie_ans = partitions_trie_.FindByPrefix(path); std::vector ans(trie_ans.size()); for (size_t i = 0; i < ans.size(); ++i) { ans[i] = *trie_ans[i]; } return ans; } TypeclassGraph* GetTypeclassGraph() { 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_map* ChooseNamespaces( utils::ClassInternalsModifier modifier, definition::Namespace* current_namespace); 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; std::vector functions_; std::vector types_; std::vector abstract_types_; std::vector typeclasses_; std::vector constructors_; std::vector namespaces_; std::unordered_map name_to_typeclass_; std::unordered_map name_to_abstract_type_; std::vector partitions_; utils::Trie partitions_trie_; std::vector imports_; std::unordered_map usages_; TypeclassGraph typeclass_graph_; }; } // namespace info