// for clangd #include "../include/global_info.hpp" #include "../include/error_handling.hpp" namespace info { void GlobalInfo::NamespaceVisitor::AddImport(ImportInfo&& 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, const std::optional& modifier, const std::optional& variable) { NamespaceInfo* namespace_info = nullptr; if (variable.has_value()) { namespace_info = &namespace_stack_.back()->variable_namespaces[name].emplace_back(); namespace_stack_.push_back(namespace_info); namespace_info->modifier = modifier; namespace_info->variable = variable; } else { namespace_info = &namespace_stack_.back()->namespaces[name]; namespace_stack_.push_back(namespace_info); } namespace_info->type_name = name; current_path_.push_back(name); } void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name) { // TODO: enter sibling namespace, etc. namespace_stack_.push_back(&namespace_stack_.back()->namespaces[name]); current_path_.push_back(name); } void GlobalInfo::NamespaceVisitor::ExitNamespace() { if (namespace_stack_.size() <= 1) { // error 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_.global_namespace_); } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration(const std::string& name, FunctionDeclarationInfo&& function_declaration_info) { size_t id = 0; auto function_id_iter = namespace_stack_.back()->functions.find(name); if (function_id_iter == namespace_stack_.back()->functions.end()) { id = global_info_.functions_.size(); namespace_stack_.back()->functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size(); global_info_.functions_.back().declaration = std::move(function_declaration_info); } else { id = function_id_iter->second; if (global_info_.functions_.back().argument_count != function_declaration_info.argument_types.size()) { error_handling::HandleInternalError("Not same argument count in function definition and declaration", "GlobalInfo"); } global_info_.functions_[id].declaration = std::move(function_declaration_info); } return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::string& name, FunctionDefinitionInfo&& function_definition_info) { size_t id = 0; auto function_id_iter = namespace_stack_.back()->functions.find(name); if (function_id_iter == namespace_stack_.back()->functions.end()) { id = global_info_.functions_.size(); namespace_stack_.back()->functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_definition_info.argument_names.size(); global_info_.functions_.back().definition = std::move(function_definition_info); } else { id = function_id_iter->second; if (global_info_.functions_.back().argument_count != function_definition_info.argument_names.size()) { error_handling::HandleInternalError("Not same argument count in function definition and declaration", "GlobalInfo"); } global_info_.functions_[id].definition = std::move(function_definition_info); } return id; } // TODO - find constructors, etc. utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, TypeInfo&& type_info) { size_t id = 0; auto function_id_iter = namespace_stack_.back()->functions.find(type); if (function_id_iter == namespace_stack_.back()->functions.end()) { id = global_info_.types_.size(); namespace_stack_.back()->functions[type] = id; global_info_.types_.push_back(std::move(type_info)); } else { // error } return id; } utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass, TypeclassInfo&& typeclass_info) { size_t id = 0; auto function_id_iter = namespace_stack_.back()->functions.find(typeclass); if (function_id_iter == namespace_stack_.back()->functions.end()) { id = global_info_.typeclasses_.size(); namespace_stack_.back()->functions[typeclass] = id; global_info_.typeclasses_.push_back(std::move(typeclass_info)); } else { // error } return id; } std::optional GlobalInfo::NamespaceVisitor::FindNamespace(const std::optional>& path) { return FindSomething(path, [] (NamespaceInfo* current_namespace) -> std::optional { return current_namespace; }); } std::optional> GlobalInfo::NamespaceVisitor::FindFunction( const std::optional>& path, const std::string& name) { return FindSomething(path, [name] (NamespaceInfo* current_namespace) -> std::optional { auto function_info_iter = current_namespace->functions.find(name); if (function_info_iter == current_namespace->functions.end()) { return std::nullopt; } return function_info_iter->second; }); } std::optional> GlobalInfo::NamespaceVisitor::FindMethod( const std::optional>& path, const std::string& type, const std::string& name) { // TODO: remove overhead return GlobalInfo::NamespaceVisitor::FindSomething(path, [type, name] (NamespaceInfo* current_namespace) -> std::optional { auto variable_namespaces_iter = current_namespace->variable_namespaces.find(type); if (variable_namespaces_iter == current_namespace->variable_namespaces.end()) { return std::nullopt; } for (auto& variable_namespace : variable_namespaces_iter->second) { auto method_iter = variable_namespace.functions.find(name); if (method_iter == variable_namespace.functions.end()) { continue; } return method_iter->second; } return std::nullopt; }); } std::optional> GlobalInfo::NamespaceVisitor::FindType( const std::optional>& path, const std::string type) { return FindSomething(path, [type] (NamespaceInfo* current_namespace) -> std::optional { auto type_info_iter = current_namespace->types.find(type); if (type_info_iter == current_namespace->types.end()) { return std::nullopt; } return type_info_iter->second; }); } std::optional> GlobalInfo::NamespaceVisitor::FindTypeclass( const std::optional>& path, const std::string typeclass) { return FindSomething(path, [typeclass] (NamespaceInfo* current_namespace) -> std::optional { auto typeclass_info_iter = current_namespace->typeclasses.find(typeclass); if (typeclass_info_iter == current_namespace->typeclasses.end()) { return std::nullopt; } return typeclass_info_iter->second; }); } template std::optional GlobalInfo::NamespaceVisitor::FindSomething( const std::optional>& path, std::function(NamespaceInfo*)> search_func) { for (ssize_t i = namespace_stack_.size() - 1; i >= 0; --i) { NamespaceInfo* current_namespace = nullptr; if (path.has_value()) { auto maybe_namespace = FindNamespaceIn(namespace_stack_[i], path.value()); if (!maybe_namespace.has_value()) { continue; } } 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( NamespaceInfo* current_namespace, const std::vector& path) { NamespaceInfo* next_namespace = current_namespace; for (auto& name : path) { auto next_namespace_iter = next_namespace->namespaces.find(name); if (next_namespace_iter == next_namespace->namespaces.end()) { return std::nullopt; } next_namespace = &next_namespace_iter->second; } return next_namespace; } } // namespace info