// for clangd #include "../include/global_info.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; } void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name) { // TODO: enter sibling namespace, etc. namespace_stack_.push_back(&namespace_stack_.back()->namespaces[name]); } void GlobalInfo::NamespaceVisitor::ExitNamespace() { if (namespace_stack_.size() <= 1) { // error return; } namespace_stack_.pop_back(); } void GlobalInfo::NamespaceVisitor::ToGlobalNamespace() { namespace_stack_.clear(); namespace_stack_.push_back(&global_info_.global_namespace_); } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration(const std::string& name, FunctionDeclarationInfo&& function_declaration_info) { FunctionInfo* function_info = &namespace_stack_.back()->functions[name]; function_info->declaration = std::move(function_declaration_info); return global_info_.functions_.GetId(function_info); } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::string& name, FunctionDefinitionInfo&& function_definition_info) { FunctionInfo* function_info = &namespace_stack_.back()->functions[name]; function_info->definition = std::move(function_definition_info); return global_info_.functions_.GetId(function_info); } utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, TypeInfo&& type_info) { namespace_stack_.back()->types[type] = std::move(type_info); } utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass, TypeclassInfo&& typeclass_info) { namespace_stack_.back()->typeclasses[typeclass] = std::move(typeclass_info); return global_info_.functions_.GetId(typeclass_info); } 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) { auto result = 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; }); if (result.has_value()) { return global_info_.functions_.GetId(result.value()); } else { return std::nullopt; } } std::optional GlobalInfo::NamespaceVisitor::FindMethod( const std::optional>& path, const std::string& type, const std::string& name) { // TODO: remove overhead auto result = 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; }); if (result.has_value()) { return global_info_.functions_.GetId(result.value()); } else { return std::nullopt; } } std::optional GlobalInfo::NamespaceVisitor::FindType( const std::optional>& path, const std::string type) { auto result = 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; }); if (result.has_value()) { return global_info_.types_.GetId(result.value()); } else { return std::nullopt; } } std::optional GlobalInfo::NamespaceVisitor::FindTypeclass( const std::optional>& path, const std::string typeclass) { auto result = 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; }); if (result.has_value()) { return global_info_.typeclasses_.GetId(result.value()); } else { return std::nullopt; } } 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