From 27aa3aec9e209bbaf67ff14dc1f12b14d500a282 Mon Sep 17 00:00:00 2001 From: heinezen Date: Mon, 22 May 2023 00:57:41 +0200 Subject: [PATCH 01/10] db: Check if namespace is already loaded before importing. --- nyan/database.cpp | 30 +++++++++++++++++++----------- nyan/meta_info.cpp | 23 ++++++++++++++++++++++- nyan/meta_info.h | 45 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/nyan/database.cpp b/nyan/database.cpp index a4d00dc..dc5744e 100644 --- a/nyan/database.cpp +++ b/nyan/database.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #include "database.h" @@ -90,13 +90,16 @@ void Database::load(const std::string &filename, // the location is the first request origin. std::unordered_map to_import; - // push the first namespace to import - to_import.insert( - { - Namespace::from_filename(filename), - Location{" -> requested by native call to Database::load()"} - } - ); + auto file_ns = Namespace::from_filename(filename); + if (not this->meta_info.has_namespace(file_ns.to_fqon())) { + // push the first namespace to import + to_import.insert( + { + file_ns, + Location{" -> requested by native call to Database::load()"} + } + ); + } // descend to all imports and load the files while (to_import.size() > 0) { @@ -147,15 +150,16 @@ void Database::load(const std::string &filename, } // check if this import was already requested or is known. - // todo: also check if that ns is already fully loaded in the db auto was_imported = imports.find(request); auto import_requested = to_import.find(request); if (was_imported == std::end(imports) and import_requested == std::end(to_import)) { - // add the request to the pending imports - to_import.insert({std::move(request), import.get()}); + if (not this->meta_info.has_namespace(request.to_fqon())) { + // add the request to the pending imports + to_import.insert({std::move(request), import.get()}); + } } } @@ -217,6 +221,10 @@ void Database::load(const std::string &filename, info->set_children(std::move(children)); } + for (auto loaded: imports) { + this->meta_info.add_namespace(loaded.first); + } + // TODO: check pending objectvalues (probably not needed as they're all loaded) } diff --git a/nyan/meta_info.cpp b/nyan/meta_info.cpp index 22bba8f..68fd470 100644 --- a/nyan/meta_info.cpp +++ b/nyan/meta_info.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #include "meta_info.h" @@ -50,6 +50,27 @@ bool MetaInfo::has_object(const fqon_t &name) const { return this->object_info.count(name) == 1; } +Namespace &MetaInfo::add_namespace(const Namespace &ns) { + auto ret = this->namespaces.insert({ns.to_fqon(), ns}); + + return ret.first->second; +} + +Namespace *MetaInfo::get_namespace(const fqon_t &name) { + return const_cast(std::as_const(*this).get_namespace(name)); +} + +const Namespace *MetaInfo::get_namespace(const fqon_t &name) const { + auto it = this->namespaces.find(name); + if (it == std::end(this->namespaces)) { + return nullptr; + } + return &it->second; +} + +bool MetaInfo::has_namespace(const fqon_t &name) const { + return this->namespaces.contains(name); +} std::string MetaInfo::str() const { std::ostringstream builder; diff --git a/nyan/meta_info.h b/nyan/meta_info.h index 7449350..bcf65c2 100644 --- a/nyan/meta_info.h +++ b/nyan/meta_info.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #pragma once #include @@ -7,6 +7,7 @@ #include "config.h" #include "object_info.h" +#include "namespace.h" namespace nyan { @@ -18,6 +19,7 @@ namespace nyan { class MetaInfo { public: using obj_info_t = std::unordered_map; + using ns_info_t = std::unordered_map; MetaInfo() = default; ~MetaInfo() = default; @@ -69,6 +71,42 @@ class MetaInfo { */ bool has_object(const fqon_t &name) const; + /** + * Add a namespace to the database. + * + * @param ns Namespace to add. + * + * @return The stored namespace. + */ + Namespace &add_namespace(const Namespace &ns); + + /** + * Get a namespace from the database. + * + * @param name Identifier of the namespace. + * + * @return The stored namespace. + */ + Namespace *get_namespace(const fqon_t &name); + + /** + * Get a namespace from the database. + * + * @param name Identifier of the namespace. + * + * @return The stored namespace. + */ + const Namespace *get_namespace(const fqon_t &name) const; + + /** + * Check if a namespace is in the database. + * + * @param name Identifier of the namespace. + * + * @return true if the namespace is in the database, else false. + */ + bool has_namespace(const fqon_t &name) const; + /** * Get a string representation of all metadata information objects. * @@ -82,6 +120,11 @@ class MetaInfo { * This is for displaying error messages and line information. */ obj_info_t object_info; + + /** + * Namespaces loaded in the database. + */ + ns_info_t namespaces; }; } // namespace nyan From 56c895d344b0d0f1be6ca56b2fba9eb6df40a53a Mon Sep 17 00:00:00 2001 From: heinezen Date: Thu, 25 May 2023 15:21:47 +0200 Subject: [PATCH 02/10] db: Check if member is prefixed with ancestor ID. --- nyan/ast.cpp | 6 ++++-- nyan/database.cpp | 30 +++++++++++++++++++++++++++--- test/test.nyan | 2 ++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/nyan/ast.cpp b/nyan/ast.cpp index 3b9767c..6da8174 100644 --- a/nyan/ast.cpp +++ b/nyan/ast.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2016-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #include "ast.h" @@ -301,7 +301,9 @@ void ASTObject::ast_members(TokenStream &tokens) { bool object_next = false; auto lookahead = tokens.next(); - if (lookahead->type == token_type::OPERATOR or lookahead->type == token_type::COLON) { + if (lookahead->type == token_type::OPERATOR // value assignment + or lookahead->type == token_type::COLON // type declaration + or lookahead->type == token_type::DOT) { // inherited member access (e.g. Parent.some_member) object_next = false; } else if (lookahead->type == token_type::LANGLE or lookahead->type == token_type::LBRACKET or lookahead->type == token_type::LPAREN) { diff --git a/nyan/database.cpp b/nyan/database.cpp index dc5744e..8a80e9d 100644 --- a/nyan/database.cpp +++ b/nyan/database.cpp @@ -375,6 +375,19 @@ void Database::find_member(bool skip_first, bool finished = false; + // if the member is inherited, it can be prefixed with the ID + // of the object it's inherited from, e.g. ParentObj.some_member + std::string member_name = member_id; + std::optional member_obj_id = std::nullopt; + std::vector member_parts = util::split(member_id, '.'); + if (member_parts.size() > 1) { + member_name = member_parts.back(); + member_parts.pop_back(); + + // TODO: we might need to resolve aliases here + member_obj_id = util::strjoin(".", member_parts); + } + // member doesn't have type yet. find it. for (auto &obj : search_objs) { @@ -385,14 +398,25 @@ void Database::find_member(bool skip_first, continue; } + // TODO: if the obj fqon is prefixed, we can skip objects that don't match + if (member_obj_id and member_obj_id != obj) { + // continue; + } + ObjectInfo *obj_info = this->meta_info.get_object(obj); if (unlikely(obj_info == nullptr)) { throw InternalError{"object information not retrieved"}; } - const MemberInfo *obj_member_info = obj_info->get_member(member_id); + const MemberInfo *obj_member_info = obj_info->get_member(member_name); // obj doesn't have this member if (not obj_member_info) { + // TODO: fail here if the member is prefixed with the parent fqon + // but the object doesn't have the member + // if (unlikely(member_obj_id)) { + // throw InternalError{"specified parent object doesn't have the member"}; + // } + continue; } @@ -400,7 +424,7 @@ void Database::find_member(bool skip_first, if (unlikely(par_state == nullptr)) { throw InternalError{"object state not retrieved"}; } - const Member *member = par_state->get(member_id); + const Member *member = par_state->get(member_name); finished = member_found(obj, *obj_member_info, member); @@ -420,7 +444,7 @@ void Database::find_member(bool skip_first, // recurse into the target. // check if the patch defines the member as well -> error. // otherwise, infer type from patch. - this->find_member(false, member_id, + this->find_member(false, member_name, obj_info->get_linearization(), *obj_info, member_found); } diff --git a/test/test.nyan b/test/test.nyan index 22eccb9..7030b09 100644 --- a/test/test.nyan +++ b/test/test.nyan @@ -12,6 +12,7 @@ First(): wat3 : optional(First) = Second wat4 : set(children(First)) = {Second} member : int = 15 + nice_member : bool = True test : text = "rofl lol" bla : file = "wtf.h4x" blub : int = inf @@ -25,6 +26,7 @@ FirstPatch(): Second(First): member *= 5.5 + First.nice_member = False # nap : int NestingBase(First): From 8a766b33d5cb89c61e97e5de6e7b19f43774655d Mon Sep 17 00:00:00 2001 From: heinezen Date: Thu, 25 May 2023 18:09:48 +0200 Subject: [PATCH 03/10] ast: Fix 'None' assignments to containers. --- nyan/value/value.cpp | 211 ++++++++++++++++++++++++------------------- test/test.nyan | 7 +- 2 files changed, 125 insertions(+), 93 deletions(-) diff --git a/nyan/value/value.cpp b/nyan/value/value.cpp index 1c12f14..41a7d44 100644 --- a/nyan/value/value.cpp +++ b/nyan/value/value.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2016-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #include "value.h" @@ -22,7 +22,6 @@ namespace nyan { - /** * Create a ValueHolder from an IDToken. * @@ -154,6 +153,30 @@ static std::vector value_from_value_token( } +/** + * Check if the value contained in a list of value tokens is 'None' (the value available + * for the optional type modifier). + * + * Can be used to check if a container is set to None. + * + * @param astvalues Value tokens of a member defiinition. + * @return true if the value is 'None', false otherwise. + */ +static bool check_container_none(const std::vector &astvalues) { + if (astvalues.size() == 1) { + auto &id_tokens = astvalues[0].get_value(); + if (id_tokens.size() == 1) { + auto &token_components = id_tokens[0].get_components(); + if (token_components.size() == 1 + and token_components[0].get() == "None") { + return true; + } + } + } + return false; +} + + ValueHolder Value::from_ast( const Type &target_type, const ASTMemberValue &astmembervalue, @@ -183,105 +206,111 @@ ValueHolder Value::from_ast( )[0]; } else { + // for optional types, we need to check if the member is set to None + if (target_type.has_modifier(modifier_t::OPTIONAL) + and check_container_none(astvalues)) { + value = None::value; + } + else { + // now for containers (dict, set, orderedset, ...) + composite_t composite_type = target_type.get_composite_type(); - // now for containers (dict, set, orderedset, ...) - composite_t composite_type = target_type.get_composite_type(); - - switch (composite_type) - { - case composite_t::ORDEREDSET: - case composite_t::SET: { - std::vector values; - - // process multi-value values (orderedsets etc) - values.reserve(astvalues.size()); - - // convert all tokens to values - const Type &element_type = target_type.get_element_type()[0]; - - for (auto &value_token : astvalues) { - ValueHolder value = value_from_value_token( - {element_type}, - value_token, - get_fqon - )[0]; - - if (auto error = value->compatible_with(element_type, get_obj_lin)) { - throw TypeError( - value_token.get_start_location(), - "set element type "s - + element_type.str() - + " can't be assigned a value of type " - + value->get_type().str() - + ": " + error->msg - ); + switch (composite_type) + { + case composite_t::ORDEREDSET: + case composite_t::SET: { + std::vector values; + + // process multi-value values (orderedsets etc) + values.reserve(astvalues.size()); + + // convert all tokens to values + const Type &element_type = target_type.get_element_type()[0]; + + for (auto &value_token : astvalues) { + ValueHolder value = value_from_value_token( + {element_type}, + value_token, + get_fqon + )[0]; + + if (auto error = value->compatible_with(element_type, get_obj_lin)) { + throw TypeError( + value_token.get_start_location(), + "set element type "s + + element_type.str() + + " can't be assigned a value of type " + + value->get_type().str() + + ": " + error->msg + ); + } + + values.push_back(value); } - values.push_back(value); - } - - switch (composite_type) { - case composite_t::SET: - // create a set from the value list - value = std::make_shared(std::move(values)); - break; + switch (composite_type) { + case composite_t::SET: + // create a set from the value list + value = std::make_shared(std::move(values)); + break; - case composite_t::ORDEREDSET: - value = std::make_shared(std::move(values)); - break; + case composite_t::ORDEREDSET: + value = std::make_shared(std::move(values)); + break; - default: - throw InternalError{"value creation for unhandled container type"}; - } - } break; - - case composite_t::DICT: { - std::unordered_map items; - - items.reserve(astvalues.size()); - - // convert all tokens to values - const std::vector &element_type = target_type.get_element_type(); - - const Type &key_type = element_type[0]; - const Type &value_type = element_type[1]; - - for (auto &value_token : astvalues) { - std::vector keyval = value_from_value_token( - element_type, - value_token, - get_fqon - ); - - if (auto error = keyval[0]->compatible_with(key_type, get_obj_lin)) { - throw TypeError( - value_token.get_start_location(), - "dict key type "s - + key_type.str() - + " can't be assigned a value of type " - + keyval[0]->get_type().str() - + ": " + error->msg - ); + default: + throw InternalError{"value creation for unhandled container type"}; } - if (auto error = keyval[1]->compatible_with(value_type, get_obj_lin)) { - throw TypeError( - value_token.get_start_location(), - "dict value type "s - + value_type.str() - + " can't be assigned a value of type " - + keyval[1]->get_type().str() - + ": " + error->msg + } break; + + case composite_t::DICT: { + std::unordered_map items; + + items.reserve(astvalues.size()); + + // convert all tokens to values + const std::vector &element_type = target_type.get_element_type(); + + const Type &key_type = element_type[0]; + const Type &value_type = element_type[1]; + + for (auto &value_token : astvalues) { + std::vector keyval = value_from_value_token( + element_type, + value_token, + get_fqon ); - } - items.insert(std::make_pair(keyval[0], keyval[1])); - } + if (auto error = keyval[0]->compatible_with(key_type, get_obj_lin)) { + throw TypeError( + value_token.get_start_location(), + "dict key type "s + + key_type.str() + + " can't be assigned a value of type " + + keyval[0]->get_type().str() + + ": " + error->msg + ); + } + if (auto error = keyval[1]->compatible_with(value_type, get_obj_lin)) { + throw TypeError( + value_token.get_start_location(), + "dict value type "s + + value_type.str() + + " can't be assigned a value of type " + + keyval[1]->get_type().str() + + ": " + error->msg + ); + } + + items.insert(std::make_pair(keyval[0], keyval[1])); + } - value = std::make_shared(std::move(items)); - } break; + value = std::make_shared(std::move(items)); + } break; - default: - throw InternalError{"value creation for unhandled container type"}; + default: + throw InternalError{"value creation for unhandled container type"}; + } } } diff --git a/test/test.nyan b/test/test.nyan index 7030b09..2f5793b 100644 --- a/test/test.nyan +++ b/test/test.nyan @@ -34,8 +34,6 @@ NestingBase(First): setmember : set(int) = {1,2,3,4, 5,6,7,} - dictmember : dict(int, text) = {2: "two", 4: "four"} - member = 2 SomeChild(Dummy): @@ -89,6 +87,11 @@ SetPatch(): member |= o{3,4,4} orderedmember += o{4} +DictTest(): + dictmember : dict(int, text) = {2: "two", 4: "four"} + dictmember2 : optional(dict(text, int)) = None + dictmember3 : optional(dict(text, int)) = {"two": 2, "four": 4} + # importing! import imported as imp import stuff.file From 0fcee65f034f4ba42c46f74e80ce4cc1b20b43e6 Mon Sep 17 00:00:00 2001 From: heinezen Date: Fri, 26 May 2023 00:55:58 +0200 Subject: [PATCH 04/10] ast: Fix parsing nested objects directly before EOF. --- nyan/ast.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nyan/ast.cpp b/nyan/ast.cpp index 6da8174..e937921 100644 --- a/nyan/ast.cpp +++ b/nyan/ast.cpp @@ -342,6 +342,10 @@ void ASTObject::ast_members(TokenStream &tokens) { token = tokens.next(); } + + if (token->type == token_type::ENDFILE) { + tokens.reinsert_last(); + } } From 6316283c33057bd6db337cdaac1ec61198810204 Mon Sep 17 00:00:00 2001 From: heinezen Date: Fri, 26 May 2023 03:29:14 +0200 Subject: [PATCH 05/10] db: More precise type info. --- nyan/database.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/nyan/database.cpp b/nyan/database.cpp index 8a80e9d..dad5f0d 100644 --- a/nyan/database.cpp +++ b/nyan/database.cpp @@ -377,7 +377,7 @@ void Database::find_member(bool skip_first, // if the member is inherited, it can be prefixed with the ID // of the object it's inherited from, e.g. ParentObj.some_member - std::string member_name = member_id; + memberid_t member_name = member_id; std::optional member_obj_id = std::nullopt; std::vector member_parts = util::split(member_id, '.'); if (member_parts.size() > 1) { @@ -814,12 +814,26 @@ void Database::check_hierarchy(const std::vector &new_objs, for (auto &it : state_members) { const memberid_t &member_id = it.first; + + // if the member is inherited, its ID can be prefixed with the ID + // of the object it's inherited from, e.g. ParentObj.some_member + memberid_t member_name = member_id; + std::optional member_obj_id = std::nullopt; + std::vector member_parts = util::split(member_id, '.'); + if (member_parts.size() > 1) { + member_name = member_parts.back(); + member_parts.pop_back(); + + // TODO: resolve aliases here + member_obj_id = util::strjoin(".", member_parts); + } + const Member &member = it.second; nyan_op op = member.get_operation(); // member has = operation, so it's no longer pending. if (op == nyan_op::ASSIGN) { - pending_members.erase(member_id); + pending_members.erase(member_name); } } } From 040a4a5446c8c23a6eb1461ba6ca418cc4d5d5cf Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 11 Jun 2023 16:40:52 +0200 Subject: [PATCH 06/10] db: Fix initial children not being stored correctly. --- nyan/database.cpp | 15 +++++++++------ nyan/object_info.cpp | 7 ++++++- nyan/object_info.h | 13 ++++++++++--- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/nyan/database.cpp b/nyan/database.cpp index dad5f0d..6b499e5 100644 --- a/nyan/database.cpp +++ b/nyan/database.cpp @@ -218,7 +218,7 @@ void Database::load(const std::string &filename, throw InternalError{"object info could not be retrieved"}; } - info->set_children(std::move(children)); + info->update_children(std::move(children)); } for (auto loaded: imports) { @@ -291,11 +291,14 @@ void Database::create_obj_content(std::vector *new_objs, fqon_t parent_id = scope.find(ns, parent, this->meta_info); // this object is therefore a child of the parent one. - auto ins = child_assignments->emplace( - parent_id, - std::unordered_set{} - ); - ins.first->second.insert(obj_fqon); + auto ins = child_assignments->find(parent_id); + if (ins == std::end(*child_assignments)) { + ins = child_assignments->emplace( + parent_id, + std::unordered_set{} + ).first; + } + ins->second.insert(obj_fqon); object_parents.push_back(std::move(parent_id)); } diff --git a/nyan/object_info.cpp b/nyan/object_info.cpp index fa26d71..cc2fd26 100644 --- a/nyan/object_info.cpp +++ b/nyan/object_info.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #include "object_info.h" @@ -104,6 +104,11 @@ const std::vector &ObjectInfo::get_linearization() const { } +void ObjectInfo::update_children(std::unordered_set &&children) { + this->initial_children.insert(children.begin(), children.end()); +} + + void ObjectInfo::set_children(std::unordered_set &&children) { this->initial_children = std::move(children); } diff --git a/nyan/object_info.h b/nyan/object_info.h index 5353f1d..4bc3234 100644 --- a/nyan/object_info.h +++ b/nyan/object_info.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #pragma once #include @@ -120,9 +120,16 @@ class ObjectInfo { const std::vector &get_linearization() const; /** - * Set the initial children of the object at load time. + * Update the children of the object. * - * @param children List of initial children of the object. + * @param children fqons of the child objects. + */ + void update_children(std::unordered_set &&children); + + /** + * Set the children of the object. + * + * @param children fqons of the child objects. */ void set_children(std::unordered_set &&children); From 33d05a64549f8683a8db48a71e6778a67999f705 Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 11 Jun 2023 17:47:47 +0200 Subject: [PATCH 07/10] ns: Sanitize filename when creating fqon. --- nyan/namespace.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/nyan/namespace.cpp b/nyan/namespace.cpp index 56648b4..c7ed081 100644 --- a/nyan/namespace.cpp +++ b/nyan/namespace.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2021 the nyan authors, LGPLv3+. See copying.md for legal info. +// Copyright 2016-2023 the nyan authors, LGPLv3+. See copying.md for legal info. #include "namespace.h" @@ -94,9 +94,30 @@ Namespace Namespace::from_filename(const std::string &filename) { throw APIError{"there's too many dots in the path"}; } - // strip off the file extension - std::string namespace_name{filename, 0, filename.size() - extension.size()}; - std::replace(namespace_name.begin(), namespace_name.end(), '/', '.'); + // sanitize the filename + // TODO: Do this via a file API + std::string namespace_name; + char prev_char; + char cur_char; + // condition strips off file extension + for (size_t i = 0; i < filename.size() - extension.size(); ++i) { + cur_char = filename[i]; + + // slashes get replaced with dots + if (cur_char == '/') { + // strip multiple slashes + if (prev_char == '/') { + continue; + } + namespace_name += '.'; + } + // normal chars get copied + else { + namespace_name += cur_char; + } + + prev_char = cur_char; + } // the fqon_t constructor. return Namespace{namespace_name}; From b61c087146a299dca1724b6ec669c62749fc99ac Mon Sep 17 00:00:00 2001 From: heinezen Date: Mon, 12 Jun 2023 21:54:13 +0200 Subject: [PATCH 08/10] db: Clarify why inherited member checks are deactivated for now. --- nyan/database.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nyan/database.cpp b/nyan/database.cpp index 6b499e5..441eacc 100644 --- a/nyan/database.cpp +++ b/nyan/database.cpp @@ -402,9 +402,10 @@ void Database::find_member(bool skip_first, } // TODO: if the obj fqon is prefixed, we can skip objects that don't match - if (member_obj_id and member_obj_id != obj) { - // continue; - } + // TODO: This requires that aliases and fqons are properly resolved + // if (member_obj_id and member_obj_id != obj) { + // continue; + // } ObjectInfo *obj_info = this->meta_info.get_object(obj); if (unlikely(obj_info == nullptr)) { @@ -416,6 +417,7 @@ void Database::find_member(bool skip_first, if (not obj_member_info) { // TODO: fail here if the member is prefixed with the parent fqon // but the object doesn't have the member + // TODO: This requires that aliases and fqons are properly resolved // if (unlikely(member_obj_id)) { // throw InternalError{"specified parent object doesn't have the member"}; // } From 0be3777b5eab4f9cfba2a6cc636449e3b65b7674 Mon Sep 17 00:00:00 2001 From: heinezen Date: Mon, 12 Jun 2023 22:00:38 +0200 Subject: [PATCH 09/10] ns: Add `fqnn_t` as an identifier for Namespaces. --- nyan/config.h | 3 +++ nyan/meta_info.cpp | 8 ++++---- nyan/meta_info.h | 8 ++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/nyan/config.h b/nyan/config.h index 97c7a97..73a8e80 100644 --- a/nyan/config.h +++ b/nyan/config.h @@ -29,6 +29,9 @@ constexpr const order_t LATEST_T = std::numeric_limits::max(); /** fully-qualified object name */ using fqon_t = std::string; +/** fully-qualified namespace name */ +using fqnn_t = fqon_t; + /** member name identifier type */ using memberid_t = std::string; diff --git a/nyan/meta_info.cpp b/nyan/meta_info.cpp index 68fd470..dc63f39 100644 --- a/nyan/meta_info.cpp +++ b/nyan/meta_info.cpp @@ -51,16 +51,16 @@ bool MetaInfo::has_object(const fqon_t &name) const { } Namespace &MetaInfo::add_namespace(const Namespace &ns) { - auto ret = this->namespaces.insert({ns.to_fqon(), ns}); + auto ret = this->namespaces.insert({fqnn_t(ns.to_fqon()), ns}); return ret.first->second; } -Namespace *MetaInfo::get_namespace(const fqon_t &name) { +Namespace *MetaInfo::get_namespace(const fqnn_t &name) { return const_cast(std::as_const(*this).get_namespace(name)); } -const Namespace *MetaInfo::get_namespace(const fqon_t &name) const { +const Namespace *MetaInfo::get_namespace(const fqnn_t &name) const { auto it = this->namespaces.find(name); if (it == std::end(this->namespaces)) { return nullptr; @@ -68,7 +68,7 @@ const Namespace *MetaInfo::get_namespace(const fqon_t &name) const { return &it->second; } -bool MetaInfo::has_namespace(const fqon_t &name) const { +bool MetaInfo::has_namespace(const fqnn_t &name) const { return this->namespaces.contains(name); } diff --git a/nyan/meta_info.h b/nyan/meta_info.h index bcf65c2..9edd852 100644 --- a/nyan/meta_info.h +++ b/nyan/meta_info.h @@ -19,7 +19,7 @@ namespace nyan { class MetaInfo { public: using obj_info_t = std::unordered_map; - using ns_info_t = std::unordered_map; + using ns_info_t = std::unordered_map; MetaInfo() = default; ~MetaInfo() = default; @@ -87,7 +87,7 @@ class MetaInfo { * * @return The stored namespace. */ - Namespace *get_namespace(const fqon_t &name); + Namespace *get_namespace(const fqnn_t &name); /** * Get a namespace from the database. @@ -96,7 +96,7 @@ class MetaInfo { * * @return The stored namespace. */ - const Namespace *get_namespace(const fqon_t &name) const; + const Namespace *get_namespace(const fqnn_t &name) const; /** * Check if a namespace is in the database. @@ -105,7 +105,7 @@ class MetaInfo { * * @return true if the namespace is in the database, else false. */ - bool has_namespace(const fqon_t &name) const; + bool has_namespace(const fqnn_t &name) const; /** * Get a string representation of all metadata information objects. From 05ab50b8ff09f61832b34bddc9d9dc795b830fe4 Mon Sep 17 00:00:00 2001 From: heinezen Date: Mon, 12 Jun 2023 22:03:32 +0200 Subject: [PATCH 10/10] db: Rename `update_children` to `add_children`. --- nyan/database.cpp | 2 +- nyan/object_info.cpp | 2 +- nyan/object_info.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nyan/database.cpp b/nyan/database.cpp index 441eacc..d3617c0 100644 --- a/nyan/database.cpp +++ b/nyan/database.cpp @@ -218,7 +218,7 @@ void Database::load(const std::string &filename, throw InternalError{"object info could not be retrieved"}; } - info->update_children(std::move(children)); + info->add_children(std::move(children)); } for (auto loaded: imports) { diff --git a/nyan/object_info.cpp b/nyan/object_info.cpp index cc2fd26..167824a 100644 --- a/nyan/object_info.cpp +++ b/nyan/object_info.cpp @@ -104,7 +104,7 @@ const std::vector &ObjectInfo::get_linearization() const { } -void ObjectInfo::update_children(std::unordered_set &&children) { +void ObjectInfo::add_children(std::unordered_set &&children) { this->initial_children.insert(children.begin(), children.end()); } diff --git a/nyan/object_info.h b/nyan/object_info.h index 4bc3234..e86cb2d 100644 --- a/nyan/object_info.h +++ b/nyan/object_info.h @@ -120,11 +120,11 @@ class ObjectInfo { const std::vector &get_linearization() const; /** - * Update the children of the object. + * Add children to the object. * - * @param children fqons of the child objects. + * @param children fqons of the added child objects. */ - void update_children(std::unordered_set &&children); + void add_children(std::unordered_set &&children); /** * Set the children of the object.