#include // for clangd #include "../include/global_info.hpp" #include "../include/types.hpp" #include "../include/error_handling.hpp" namespace info { void GlobalInfo::NamespaceVisitor::AddImport(definition::Import&& import_info, const std::optional& name) { if (name.has_value()) { global_info_.usages_[name.value()] = std::move(import_info); } else { global_info_.imports_.push_back(std::move(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::HandleNamesError("Can't define basic type namespace", base_node); } auto current_namespaces = global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[namespace_stack_.back()]); utils::IdType id = 0; auto namespace_iter = current_namespaces->find(name); if (namespace_iter == current_namespaces->end()) { id = global_info_.namespaces_.size(); (*current_namespaces)[name] = id; global_info_.namespaces_.emplace_back(); global_info_.namespaces_.back().modifier = modifier; } else { id = namespace_iter->second; } definition::Namespace* namespace_info = &global_info_.namespaces_[id]; if (!namespace_info->any_node.has_value()) { // ?? namespace_info->any_node = node; } namespace_info->parent_namespace = namespace_stack_.back(); namespace_info->type_name = name; namespace_stack_.push_back(id); current_path_.push_back(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 = 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); current_path_.push_back(name); return; } } error_handling::HandleInternalError("Can't find namespace " + name, "GlobalInfo.NamespaceVisitor.EnterNamespace"); } void GlobalInfo::NamespaceVisitor::ExitNamespace() { if (namespace_stack_.size() <= 1) { error_handling::HandleInternalError("Can't exit from global namespace", "GlobalInfo.NamespaceVisitor.ExitNamespace"); return; } namespace_stack_.pop_back(); current_path_.pop_back(); } void GlobalInfo::NamespaceVisitor::ToGlobalNamespace() { namespace_stack_.clear(); current_path_.clear(); namespace_stack_.push_back(global_info_.GlobalNamespaceId); } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration( const std::string& name, definition::FunctionDeclaration&& function_declaration_info, const interpreter::tokens::BaseNode& base_node) { utils::IdType id = 0; auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { id = global_info_.functions_.size(); global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size(); // add return type } else { id = function_id_iter->second; if (global_info_.functions_[id].argument_count != function_declaration_info.argument_types.size()) { error_handling::HandleNamesError("Function declaration: not same argument count in function definition and declaration", base_node); } } if (global_info_.functions_[id].declaration.has_value()) { error_handling::HandleNamesError("Second function declaration", base_node); } global_info_.functions_[id].declaration = std::move(function_declaration_info); return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition( const std::string& name, definition::FunctionDefinition&& function_definition_info, const interpreter::tokens::BaseNode& base_node) { utils::IdType id = 0; auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { id = global_info_.functions_.size(); global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_definition_info.argument_names.size() + 1; } else { id = function_id_iter->second; if (global_info_.functions_[id].argument_count != function_definition_info.argument_names.size() + 1) { error_handling::HandleNamesError("Function definition: not same argument count in function definition and declaration", base_node); } } if (global_info_.functions_[id].definition.has_value()) { error_handling::HandleNamesError("Second function definition", base_node); } global_info_.functions_[id].definition = std::move(function_definition_info); return id; } // TODO: internal types, etc. // TODO: extended constructor names (point separated names) utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, definition::Type&& type_info, const interpreter::tokens::BaseNode& base_node) { if (type::ToInternalType(type).has_value()) { error_handling::HandleNamesError("Can't redefine basic type", base_node); } utils::IdType id = 0; auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type); if (type_id_iter == global_info_.namespaces_[namespace_stack_.back()].types.end()) { id = global_info_.types_.size(); global_info_.namespaces_[namespace_stack_.back()].types[type] = id; global_info_.types_.push_back(std::move(type_info)); } else { error_handling::HandleNamesError("More then one type with the same name in namespace", base_node); } definition::Type& moved_type_info = global_info_.types_.back(); if (!std::holds_alternative(moved_type_info.type)) { error_handling::HandleInternalError("Not AnyType constructor search is not implemented yet", "GlobalInfo.NamespaceVisitor.AddType"); } 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; 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; if (maybe_constructor_name.has_value()) { constructor_name = maybe_constructor_name.value(); } else { constructor_name = type; } } 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; } // TODO: link abstract type with let definitions utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& abstract_type, definition::AbstractType&& abstract_type_info, const interpreter::tokens::BaseNode& base_node) { if (type::ToInternalType(abstract_type).has_value()) { error_handling::HandleNamesError("Can't redefine basic type as abstract type", base_node); } if (FindAbstractType(abstract_type).has_value()) { error_handling::HandleNamesError("More then one abstract type with the same name in namespace", base_node); } utils::IdType id = global_info_.abstract_types_.size(); global_info_.name_to_abstract_type_[abstract_type] = id; global_info_.abstract_types_.push_back(std::move(abstract_type_info)); return id; } // TODO: which info needed ?? utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass, definition::Typeclass&& typeclass_info, const interpreter::tokens::BaseNode& base_node) { if (type::ToInternalType(typeclass).has_value()) { error_handling::HandleNamesError("Can't redefine basic type as typeclass", base_node); } if (FindTypeclass(typeclass).has_value()) { error_handling::HandleNamesError("More then one typeclass with the same name", base_node); } utils::IdType id = global_info_.typeclasses_.size(); global_info_.name_to_typeclass_[typeclass] = id; global_info_.typeclasses_.push_back(std::move(typeclass_info)); return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor, definition::Constructor&& constructor_info, const interpreter::tokens::BaseNode& base_node) { if (type::ToInternalType(constructor).has_value()) { error_handling::HandleNamesError("Can't redefine basic type as constructor", base_node); } auto constructor_id_iter = global_info_.namespaces_[namespace_stack_.back()].constructors.find(constructor); if (constructor_id_iter != global_info_.namespaces_[namespace_stack_.back()].constructors.end()) { error_handling::HandleNamesError("More then one constructor with the same name in namespace", base_node); } utils::IdType id = global_info_.constructors_.size(); global_info_.namespaces_[namespace_stack_.back()].constructors[constructor] = id; global_info_.constructors_.push_back(std::move(constructor_info)); return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddPartition(const std::vector& path, interpreter::tokens::PartitionStatement* node, const interpreter::tokens::BaseNode& base_node) { PartitionInfo partition; partition.path.reserve(current_path_.size() + path.size()); partition.path = current_path_; for (auto& path_name : path) { partition.path.push_back(path_name); } partition.node = node; utils::IdType id = global_info_.partitions_.size(); global_info_.partitions_.push_back(partition); if (!global_info_.partitions_trie_.Insert(partition.path, id)) { error_handling::HandleNamesError("Partition with this name already exists", base_node); } return id; } std::optional GlobalInfo::NamespaceVisitor::FindNamespaceId(const std::optional>& path) { return FindSomething(path, [] (utils::IdType current_namespace) -> std::optional { return current_namespace; }); } std::optional GlobalInfo::NamespaceVisitor::FindFunctionId( const std::optional>& path, const std::string& name) { return FindSomething(path, [name, this] (utils::IdType current_namespace) -> std::optional { auto function_info_iter = global_info_.namespaces_[current_namespace].functions.find(name); if (function_info_iter == global_info_.namespaces_[current_namespace].functions.end()) { return std::nullopt; } return function_info_iter->second; }); } std::optional GlobalInfo::NamespaceVisitor::FindMethodId( const std::optional>& path, const std::string& type, const std::string& name, utils::IsConstModifier modifier) { return GlobalInfo::NamespaceVisitor::FindSomething(path, [type, name, modifier, this] (utils::IdType current_namespace) -> std::optional { auto variable_namespace_iter = (modifier == utils::IsConstModifier::Const ? global_info_.namespaces_[current_namespace].const_namespaces.find(type) : global_info_.namespaces_[current_namespace].var_namespaces.find(type)); if (variable_namespace_iter == (modifier == utils::IsConstModifier::Const ? global_info_.namespaces_[current_namespace].const_namespaces.end() : global_info_.namespaces_[current_namespace].var_namespaces.end())) { return std::nullopt; } auto method_iter = global_info_.namespaces_[variable_namespace_iter->second].functions.find(name); if (method_iter == global_info_.namespaces_[variable_namespace_iter->second].functions.end()) { return std::nullopt; } return method_iter->second; }); } std::optional GlobalInfo::NamespaceVisitor::FindTypeId( const std::optional>& path, const std::string& type) { return FindSomething(path, [type, this] (utils::IdType current_namespace) -> std::optional { auto type_info_iter = global_info_.namespaces_[current_namespace].types.find(type); if (type_info_iter == global_info_.namespaces_[current_namespace].types.end()) { return std::nullopt; } return type_info_iter->second; }); } std::optional GlobalInfo::NamespaceVisitor::FindLocalTypeId(const std::string& type) { auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type); if (type_id_iter != global_info_.namespaces_[namespace_stack_.back()].types.end()) { return type_id_iter->second; } return std::nullopt; } std::optional GlobalInfo::NamespaceVisitor::FindAbstractTypeId(const std::string& abstract_type) { auto abstract_type_id_iter = global_info_.name_to_abstract_type_.find(abstract_type); if (abstract_type_id_iter != global_info_.name_to_abstract_type_.end()) { return abstract_type_id_iter->second; } return std::nullopt; } std::optional GlobalInfo::NamespaceVisitor::FindTypeclassId(const std::string& typeclass) { auto typeclass_id_iter = global_info_.name_to_typeclass_.find(typeclass); if (typeclass_id_iter != global_info_.name_to_typeclass_.end()) { return typeclass_id_iter->second; } return std::nullopt; } std::optional GlobalInfo::NamespaceVisitor::FindConstructorId( const std::optional>& path, const std::string& constructor) { return FindSomething(path, [constructor, this] (utils::IdType current_namespace) -> std::optional { auto constructor_info_iter = global_info_.namespaces_[current_namespace].constructors.find(constructor); if (constructor_info_iter == global_info_.namespaces_[current_namespace].constructors.end()) { return std::nullopt; } return constructor_info_iter->second; }); } template std::optional GlobalInfo::NamespaceVisitor::FindSomething( const std::optional>& path, std::function(utils::IdType)> search_func) { for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { utils::IdType current_namespace = 0; if (path.has_value()) { auto maybe_namespace = FindNamespaceIn(namespace_stack_[i], path.value()); if (!maybe_namespace.has_value()) { continue; } current_namespace = maybe_namespace.value(); } else { current_namespace = namespace_stack_[i]; } std::optional result = search_func(current_namespace); if (result.has_value()) { return result.value(); } } return std::nullopt; } std::optional GlobalInfo::NamespaceVisitor::FindNamespaceIn( utils::IdType current_namespace, const std::vector& path) { utils::IdType next_namespace = current_namespace; for (auto& name : path) { auto next_namespace_iter = global_info_.namespaces_[next_namespace].namespaces.find(name); if (next_namespace_iter == global_info_.namespaces_[next_namespace].namespaces.end()) { return std::nullopt; } next_namespace = next_namespace_iter->second; } 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 // 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, definition::Namespace* current_namespace) { std::unordered_map* current_namespaces = nullptr; switch (modifier) { case utils::ClassInternalsModifier::Const: current_namespaces = ¤t_namespace->const_namespaces; break; case utils::ClassInternalsModifier::Var: current_namespaces = ¤t_namespace->var_namespaces; break; case utils::ClassInternalsModifier::Static: 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); 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; for (auto& dependency_node : typeclass_info->node->definition->type->typeclasses) { std::string dependency = dependency_node->typeclass; if (dependency_node->parameters.size() > 0) { error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", "GlobalInfo.AddTypeclassToGraph"); } 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 (const_namespace_iter != parent_namespace->const_namespaces.end()) { CollectFunctionInfo(const_namespace_iter->second, utils::ClassInternalsModifier::Const, function_declarations, function_definitions); } auto var_namespace_iter = parent_namespace->var_namespaces.find(name); if (var_namespace_iter != parent_namespace->var_namespaces.end()) { CollectFunctionInfo(var_namespace_iter->second, utils::ClassInternalsModifier::Var, 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( 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