// for clangd #include "../include/global_info.hpp" #include "../include/error_handling.hpp" #include 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, const std::optional& modifier) { definition::Namespace* namespace_info = nullptr; if (modifier.has_value()) { namespace_info = &namespace_stack_.back()->variable_namespaces[name]; namespace_stack_.push_back(namespace_info); namespace_info->modifier = modifier; } else { namespace_info = &namespace_stack_.back()->namespaces[name]; namespace_stack_.push_back(namespace_info); } namespace_info->parent_namespace = namespace_stack_.back(); namespace_info->type_name = name; current_path_.push_back(name); } void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name) { for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { auto namespace_iter = namespace_stack_[i]->namespaces.find(name); if (namespace_iter != namespace_stack_[i]->namespaces.end()) { namespace_stack_.push_back(&namespace_iter->second); current_path_.push_back(name); return; } } error_handling::HandleInternalError("Can't find namespace", "GlobalInfo.NamespaceVisitor.EnterNamespace"); } 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, definition::FunctionDeclaration&& 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, definition::FunctionDefinition&& 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: internal types, etc. // TODO: extended constructor names (point separated names) utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, definition::Type&& type_info) { size_t id = 0; auto type_id_iter = namespace_stack_.back()->types.find(type); if (type_id_iter == namespace_stack_.back()->types.end()) { id = global_info_.types_.size(); namespace_stack_.back()->types[type] = id; global_info_.types_.push_back(std::move(type_info)); } else { error_handling::HandleTypecheckError("More then one type with the same name in namespace"); } definition::Type& moved_type_info = global_info_.types_.back(); // TODO: constructors for tuple types, function types (??), array types (??), ... if (std::holds_alternative(moved_type_info.type)) { 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 } constructor_info.name = constructor_name; AddConstructor(constructor_name, std::move(constructor_info)); } } } return id; } // TODO: link abstract type with let definitions utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& abstract_type, definition::AbstractType&& abstract_type_info) { if (!FindAbstractType(abstract_type).has_value()) { size_t 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)); } error_handling::HandleTypecheckError("More then one abstract type with the same name in namespace"); return 0; } utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass, definition::Typeclass&& typeclass_info) { if (!FindTypeclass(typeclass).has_value()) { size_t id = global_info_.typeclasses_.size(); global_info_.name_to_typeclass_[typeclass] = id; global_info_.typeclasses_.push_back(std::move(typeclass_info)); } error_handling::HandleTypecheckError("More then one typeclass with the same name in namespace"); return 0; } utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor, definition::Constructor&& constructor_info) { auto constructor_id_iter = namespace_stack_.back()->constructors.find(constructor); if (constructor_id_iter == namespace_stack_.back()->constructors.end()) { size_t id = global_info_.constructors_.size(); namespace_stack_.back()->constructors[constructor] = id; global_info_.constructors_.push_back(std::move(constructor_info)); } error_handling::HandleTypecheckError("More then one constructor with the same name in namespace"); return 0; } std::optional GlobalInfo::NamespaceVisitor::FindNamespace(const std::optional>& path) { return FindSomething(path, [] (definition::Namespace* current_namespace) -> std::optional { return current_namespace; }); } std::optional GlobalInfo::NamespaceVisitor::FindFunction( const std::optional>& path, const std::string& name) { return FindSomething(path, [name] (definition::Namespace* 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] (definition::Namespace* current_namespace) -> std::optional { auto variable_namespace_iter = current_namespace->variable_namespaces.find(type); if (variable_namespace_iter == current_namespace->variable_namespaces.end()) { return std::nullopt; } auto method_iter = variable_namespace_iter->second.functions.find(name); if (method_iter == variable_namespace_iter->second.functions.end()) { return std::nullopt; } return method_iter->second; }); } std::optional GlobalInfo::NamespaceVisitor::FindType( const std::optional>& path, const std::string& type) { return FindSomething(path, [type] (definition::Namespace* 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::FindLocalType(const std::string& type) { auto type_id_iter = namespace_stack_.back()->types.find(type); if (type_id_iter != namespace_stack_.back()->types.end()) { return type_id_iter->second; } return std::nullopt; } std::optional GlobalInfo::NamespaceVisitor::FindAbstractType(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::FindTypeclass(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::FindConstructor( const std::optional>& path, const std::string& constructor) { return FindSomething(path, [constructor] (definition::Namespace* current_namespace) -> std::optional { auto constructor_info_iter = current_namespace->constructors.find(constructor); if (constructor_info_iter == current_namespace->constructors.end()) { return std::nullopt; } return constructor_info_iter->second; }); } template std::optional GlobalInfo::NamespaceVisitor::FindSomething( const std::optional>& path, std::function(definition::Namespace*)> search_func) { for (ssize_t i = namespace_stack_.size() - 1; i >= 0; --i) { definition::Namespace* 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( definition::Namespace* current_namespace, const std::vector& path) { definition::Namespace* 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