From 71b846dc5dd1ac49626c8b479571050224a4cca1 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Wed, 15 May 2024 10:57:21 +0200 Subject: Update OpenVicProject/OpenVic-Dataloader@4a49007 Update .clang-format categories Move type_name and SelfType functioanlity to utility/Getters --- .clang-format | 10 +- deps/openvic-dataloader | 2 +- src/openvic-simulation/dataloader/Dataloader.cpp | 10 +- src/openvic-simulation/dataloader/Dataloader.hpp | 2 +- src/openvic-simulation/dataloader/NodeTools.cpp | 135 +++++++++++++------ src/openvic-simulation/dataloader/NodeTools.hpp | 24 +++- .../dataloader/Vic2PathSearch.cpp | 4 +- src/openvic-simulation/misc/Modifier.cpp | 8 +- src/openvic-simulation/utility/Getters.hpp | 147 +++++++++++++++++---- 9 files changed, 260 insertions(+), 82 deletions(-) diff --git a/.clang-format b/.clang-format index 5a9553b..6546979 100644 --- a/.clang-format +++ b/.clang-format @@ -82,7 +82,13 @@ IncludeCategories: Priority: 4 - Regex: ^ Parser, bool (*parse_func)(Parse static Parser _run_ovdl_parser(fs::path const& path) { Parser parser; std::string buffer; - auto error_log_stream = detail::CallbackStream { + auto error_log_stream = detail::make_callback_stream( [](void const* s, std::streamsize n, void* user_data) -> std::streamsize { if (s != nullptr && n > 0 && user_data != nullptr) { static_cast(user_data)->append(static_cast(s), n); @@ -215,7 +215,7 @@ static Parser _run_ovdl_parser(fs::path const& path) { } }, &buffer - }; + ); parser.set_error_log_to(error_log_stream); parser.load_from_file(path); if (!buffer.empty()) { @@ -255,12 +255,12 @@ v2script::Parser Dataloader::parse_lua_defines(fs::path const& path) { return _run_ovdl_parser(path); } -static bool _csv_parse(csv::Windows1252Parser& parser) { +static bool _csv_parse(csv::Parser& parser) { return parser.parse_csv(); } -csv::Windows1252Parser Dataloader::parse_csv(fs::path const& path) { - return _run_ovdl_parser(path); +csv::Parser Dataloader::parse_csv(fs::path const& path) { + return _run_ovdl_parser(path); } v2script::Parser& Dataloader::parse_defines_cached(fs::path const& path) { diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp index b114eda..3c77cab 100644 --- a/src/openvic-simulation/dataloader/Dataloader.hpp +++ b/src/openvic-simulation/dataloader/Dataloader.hpp @@ -47,7 +47,7 @@ namespace OpenVic { public: static ovdl::v2script::Parser parse_defines(fs::path const& path); static ovdl::v2script::Parser parse_lua_defines(fs::path const& path); - static ovdl::csv::Windows1252Parser parse_csv(fs::path const& path); + static ovdl::csv::Parser parse_csv(fs::path const& path); /* Cache the Parser so it won't be freed until free_cache is called. This is used to preserve condition and effect * script Nodes until all defines are loaded and the scripts can be parsed. The reference returned by this function diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp index 297937a..3843459 100644 --- a/src/openvic-simulation/dataloader/NodeTools.cpp +++ b/src/openvic-simulation/dataloader/NodeTools.cpp @@ -1,34 +1,70 @@ #include "NodeTools.hpp" +#include + +#include +#include + +#include + +#include +#include + #include "openvic-simulation/types/Colour.hpp" +#include "openvic-simulation/utility/Getters.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; template -static NodeCallback auto _expect_type(Callback auto callback) { +static NodeCallback auto _expect_type(Callback auto callback) { return [callback](ast::NodeCPtr node) -> bool { if (node != nullptr) { - T const* cast_node = node->cast_to(); + T const* cast_node = dryad::node_try_cast(node); if (cast_node != nullptr) { - return callback(*cast_node); + return callback(cast_node); } - Logger::error("Invalid node type ", node->get_type(), " when expecting ", T::get_type_static()); + Logger::error("Invalid node type ", ast::get_type_name(node->kind()), " when expecting ", utility::type_name()); } else { - Logger::error("Null node when expecting ", T::get_type_static()); + Logger::error("Null node when expecting ", utility::type_name()); } return false; }; } -template T> -static Callback auto _abstract_string_node_callback(Callback auto callback, bool allow_empty) { - return [callback, allow_empty](T const& node) -> bool { +using _NodeIterator = typename decltype(std::declval()->children())::iterator; +using _NodeStatementRange = dryad::node_range<_NodeIterator, ast::Statement>; + +static NodeCallback auto _abstract_statement_node_callback(Callback<_NodeStatementRange> auto callback) { + return [callback](ast::NodeCPtr node) -> bool { + if (node != nullptr) { + if (auto const* file_tree = dryad::node_try_cast(node)) { + return callback(file_tree->statements()); + } + if (auto const* list_value = dryad::node_try_cast(node)) { + return callback(list_value->statements()); + } + Logger::error( + "Invalid node type ", ast::get_type_name(node->kind()), " when expecting ", utility::type_name(), " or ", + utility::type_name() + ); + } else { + Logger::error( + "Null node when expecting ", utility::type_name(), " or ", utility::type_name() + ); + } + return false; + }; +} + +template T> +static Callback auto _abstract_string_node_callback(Callback auto callback, bool allow_empty) { + return [callback, allow_empty](T const* node) -> bool { if (allow_empty) { - return callback(node._name); + return callback(node->value().view()); } else { - if (!node._name.empty()) { - return callback(node._name); + if (node->value()) { + return callback(node->value().view()); } else { Logger::error("Invalid string value - empty!"); return false; @@ -38,30 +74,27 @@ static Callback auto _abstract_string_node_callback(Callback callback) { - return _expect_type(_abstract_string_node_callback(callback, false)); + return _expect_type(_abstract_string_node_callback(callback, false)); } node_callback_t NodeTools::expect_string(callback_t callback, bool allow_empty) { - return _expect_type(_abstract_string_node_callback(callback, allow_empty)); + return _expect_type(_abstract_string_node_callback(callback, allow_empty)); } node_callback_t NodeTools::expect_identifier_or_string(callback_t callback, bool allow_empty) { return [callback, allow_empty](ast::NodeCPtr node) -> bool { if (node != nullptr) { - ast::AbstractStringNode const* cast_node = node->cast_to(); - if (cast_node == nullptr) { - cast_node = node->cast_to(); - } + auto const* cast_node = dryad::node_try_cast(node); if (cast_node != nullptr) { - return _abstract_string_node_callback(callback, allow_empty)(*cast_node); + return _abstract_string_node_callback(callback, allow_empty)(cast_node); } Logger::error( - "Invalid node type ", node->get_type(), " when expecting ", ast::IdentifierNode::get_type_static(), " or ", - ast::StringNode::get_type_static() + "Invalid node type ", ast::get_type_name(node->kind()), " when expecting ", utility::type_name(), " or ", + utility::type_name() ); } else { Logger::error( - "Null node when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static() + "Null node when expecting ", utility::type_name(), " or ", utility::type_name() ); } return false; @@ -221,28 +254,42 @@ node_callback_t NodeTools::expect_fvec2(callback_t callback) { } node_callback_t NodeTools::expect_assign(key_value_callback_t callback) { - return _expect_type([callback](ast::AssignNode const& assign_node) -> bool { - const bool ret = callback(assign_node._name, assign_node._initializer.get()); - if (!ret) { - Logger::error("Callback failed for assign node with key: ", assign_node._name); + return _expect_type([callback](ast::AssignStatement const* assign_node) -> bool { + std::string_view left; + bool ret = expect_identifier(assign_variable_callback(left))(assign_node->left()); + if (ret) { + ret &= callback(left, assign_node->right()); + if (!ret) { + Logger::error("Callback failed for assign node with key: ", left); + } + } else { + Logger::error("Callback key failed for assign node with key: ", left); } return ret; }); } node_callback_t NodeTools::expect_list_and_length(length_callback_t length_callback, node_callback_t callback) { - return _expect_type([length_callback, callback](ast::AbstractListNode const& list_node) -> bool { - std::vector const& list = list_node._statements; + return _abstract_statement_node_callback([length_callback, callback](_NodeStatementRange list) -> bool { bool ret = true; - size_t size = length_callback(list.size()); - if (size > list.size()) { - Logger::error("Trying to read more values than the list contains: ", size, " > ", list.size()); - size = list.size(); + auto dist = ranges::distance(list); + size_t size = length_callback(dist); + + if (size > dist) { + Logger::error("Trying to read more values than the list contains: ", size, " > ", dist); + size = dist; ret = false; } - std::for_each(list.begin(), list.begin() + size, [callback, &ret](ast::NodeUPtr const& sub_node) -> void { - ret &= callback(sub_node.get()); - }); + for (auto [index, sub_node] : list | ranges::views::enumerate) { + if (index >= size) { + break; + } + if (auto const* value = dryad::node_try_cast(sub_node)) { + ret &= callback(value->value()); + continue; + } + ret &= callback(sub_node); + } return ret; }); } @@ -286,16 +333,22 @@ node_callback_t NodeTools::expect_length(callback_t callback) { } node_callback_t NodeTools::expect_key(std::string_view key, node_callback_t callback, bool* key_found, bool allow_duplicates) { - return _expect_type( - [key, callback, key_found, allow_duplicates](ast::AbstractListNode const& list_node) -> bool { + return _abstract_statement_node_callback( + [key, callback, key_found, allow_duplicates](_NodeStatementRange list) -> bool { bool ret = true; size_t keys_found = 0; - std::vector const& list = list_node._statements; - for (ast::NodeUPtr const& sub_node : list_node._statements) { - ast::AssignNode const* assign_node = sub_node->cast_to(); - if (assign_node != nullptr && assign_node->_name == key) { + for (auto sub_node : list) { + auto const* assign_node = dryad::node_try_cast(sub_node); + if (assign_node == nullptr) { + continue; + } + std::string_view left; + if (!expect_identifier(assign_variable_callback(left))(assign_node->left())) { + continue; + } + if (left == key) { if (keys_found++ == 0) { - ret &= callback(&*assign_node->_initializer); + ret &= callback(assign_node->right()); if (allow_duplicates) { break; } diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index 92682e7..b0bb723 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -14,10 +14,32 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/Vector.hpp" +#include "openvic-simulation/utility/Getters.hpp" #include "openvic-simulation/utility/TslHelper.hpp" namespace OpenVic { - namespace ast = ovdl::v2script::ast; + namespace ast { + using namespace ovdl::v2script::ast; + using NodeCPtr = const Node*; + + constexpr std::string_view get_type_name(NodeKind kind) { +#define NODE_CASE(Node) \ + case Node: return OpenVic::utility::type_name(); + switch (kind) { + using enum NodeKind; + NODE_CASE(FileTree); + NODE_CASE(IdentifierValue); + NODE_CASE(StringValue); + NODE_CASE(ListValue); + NODE_CASE(NullValue); + NODE_CASE(EventStatement); + NODE_CASE(AssignStatement); + NODE_CASE(ValueStatement); + default: ovdl::detail::unreachable(); + } + } +#undef NODE_CASE + } using name_list_t = std::vector; std::ostream& operator<<(std::ostream& stream, name_list_t const& name_list); diff --git a/src/openvic-simulation/dataloader/Vic2PathSearch.cpp b/src/openvic-simulation/dataloader/Vic2PathSearch.cpp index dd36f28..bc30b6e 100644 --- a/src/openvic-simulation/dataloader/Vic2PathSearch.cpp +++ b/src/openvic-simulation/dataloader/Vic2PathSearch.cpp @@ -182,7 +182,7 @@ static fs::path _search_for_game_path(fs::path hint_path = {}) { lexy_vdf::Parser parser; std::string buffer; - auto error_log_stream = detail::CallbackStream { + auto error_log_stream = detail::make_callback_stream( [](void const* s, std::streamsize n, void* user_data) -> std::streamsize { if (s != nullptr && n > 0 && user_data != nullptr) { static_cast(user_data)->append(static_cast(s), n); @@ -193,7 +193,7 @@ static fs::path _search_for_game_path(fs::path hint_path = {}) { } }, &buffer - }; + ); parser.set_error_log_to(error_log_stream); parser.load_from_file(current_path); diff --git a/src/openvic-simulation/misc/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp index d4aaee2..25d0cf9 100644 --- a/src/openvic-simulation/misc/Modifier.cpp +++ b/src/openvic-simulation/misc/Modifier.cpp @@ -2,6 +2,10 @@ #include +#include + +#include + #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/utility/TslHelper.hpp" @@ -403,9 +407,9 @@ key_value_callback_t ModifierManager::_modifier_effect_callback( std::string_view key, ast::NodeCPtr value ) -> bool { ModifierEffect const* effect = get_modifier_effect_by_identifier(key); - if (effect != nullptr && value->is_type()) { + if (effect != nullptr && dryad::node_has_kind(value)) { return add_modifier_cb(effect, value); - } else if (complex_modifiers.contains(key) && value->is_derived_from()) { + } else if (complex_modifiers.contains(key) && dryad::node_has_kind(value)) { if (key == "rebel_org_gain") { //because of course there's a special one std::string_view faction_identifier; ast::NodeCPtr value_node = nullptr; diff --git a/src/openvic-simulation/utility/Getters.hpp b/src/openvic-simulation/utility/Getters.hpp index 0a6917c..5d06a8d 100644 --- a/src/openvic-simulation/utility/Getters.hpp +++ b/src/openvic-simulation/utility/Getters.hpp @@ -1,46 +1,140 @@ #pragma once +#include #include +#include #include #include +#include +#include -#include -#include +namespace OpenVic::utility { + template + constexpr auto substring_as_array(std::string_view str, std::index_sequence) { + return std::array { str[Idxs]... }; + } + + template + constexpr auto type_name_array() { +#if defined(__clang__) + constexpr auto prefix = std::string_view { "[T = " }; + constexpr auto suffix = std::string_view { "]" }; + constexpr auto function = std::string_view { __PRETTY_FUNCTION__ }; +#elif defined(__GNUC__) + constexpr auto prefix = std::string_view { "with T = " }; + constexpr auto suffix = std::string_view { "]" }; + constexpr auto function = std::string_view { __PRETTY_FUNCTION__ }; +#elif defined(_MSC_VER) + constexpr auto prefix = std::string_view { "type_name_array<" }; + constexpr auto suffix = std::string_view { ">(void)" }; + constexpr auto function = std::string_view { __FUNCSIG__ }; +#else +#error Unsupported compiler +#endif + + constexpr auto start = function.find(prefix) + prefix.size(); + constexpr auto end = function.rfind(suffix); + + static_assert(start < end); + + constexpr auto name = function.substr(start, (end - start)); + return substring_as_array(name, std::make_index_sequence {}); + } + + template + struct type_name_holder { + static inline constexpr auto value = type_name_array(); + }; + + template + constexpr auto type_name() -> std::string_view { + constexpr auto& value = type_name_holder::value; + return std::string_view { value.data(), value.size() }; + } + +#if !defined(_MSC_VER) +#pragma GCC diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma GCC diagnostic ignored "-Wnon-template-friend" +#endif + template + struct Reader { + friend auto adl_GetSelfType(Reader); + }; + + template + struct Writer { + friend auto adl_GetSelfType(Reader) { + return U {}; + } + }; +#if !defined(_MSC_VER) +#pragma GCC diagnostic pop +#endif + + inline void adl_GetSelfType() {} + + template + using Read = std::remove_pointer_t {}))>; +} #define OV_DETAIL_GET_TYPE_BASE_CLASS(CLASS) \ - static constexpr std::string_view get_type_static() { return ::ovdl::detail::type_name(); } \ + static constexpr std::string_view get_type_static() { \ + return ::OpenVic::utility::type_name(); \ + } \ constexpr virtual std::string_view get_type() const = 0; \ - static constexpr std::string_view get_base_type_static() { return ::ovdl::detail::type_name(); } \ - constexpr virtual std::string_view get_base_type() const { return get_base_type_static(); } \ - template constexpr bool is_type() const { \ - return get_type().compare(::ovdl::detail::type_name()) == 0; } \ - template constexpr bool is_derived_from() const { \ - return is_type() || get_base_type().compare(::ovdl::detail::type_name()) == 0; } \ - template constexpr T* cast_to() { \ - if (is_derived_from() || is_type()) return (static_cast(this)); \ - return nullptr; } \ - template constexpr const T* const cast_to() const { \ - if (is_derived_from() || is_type()) return (static_cast(this)); \ - return nullptr; } + static constexpr std::string_view get_base_type_static() { \ + return ::OpenVic::utility::type_name(); \ + } \ + constexpr virtual std::string_view get_base_type() const { \ + return get_base_type_static(); \ + } \ + template \ + constexpr bool is_type() const { \ + return get_type().compare(::OpenVic::utility::type_name()) == 0; \ + } \ + template \ + constexpr bool is_derived_from() const { \ + return is_type() || get_base_type().compare(::OpenVic::utility::type_name()) == 0; \ + } \ + template \ + constexpr T* cast_to() { \ + if (is_derived_from() || is_type()) \ + return (static_cast(this)); \ + return nullptr; \ + } \ + template \ + constexpr const T* const cast_to() const { \ + if (is_derived_from() || is_type()) \ + return (static_cast(this)); \ + return nullptr; \ + } #define OV_DETAIL_GET_TYPE \ struct _self_type_tag {}; \ - constexpr auto _self_type_helper()->decltype(::ovdl::detail::Writer<_self_type_tag, decltype(this)> {}); \ - using type = ::ovdl::detail::Read<_self_type_tag>; \ - static constexpr std::string_view get_type_static() { return ::ovdl::detail::type_name(); } \ + constexpr auto _self_type_helper() -> decltype(::OpenVic::utility::Writer<_self_type_tag, decltype(this)> {}); \ + using type = ::OpenVic::utility::Read<_self_type_tag>; \ + static constexpr std::string_view get_type_static() { \ + return ::OpenVic::utility::type_name(); \ + } \ constexpr std::string_view get_type() const override { \ - return ::ovdl::detail::type_name>(); } + return ::OpenVic::utility::type_name>(); \ + } #define OV_DETAIL_GET_BASE_TYPE(CLASS) \ - static constexpr std::string_view get_base_type_static() { return ::ovdl::detail::type_name(); } \ + static constexpr std::string_view get_base_type_static() { \ + return ::OpenVic::utility::type_name(); \ + } \ constexpr std::string_view get_base_type() const override { \ - return ::ovdl::detail::type_name>(); } + return ::OpenVic::utility::type_name>(); \ + } /* Create const and non-const reference getters for a variable, applied to its name in its declaration, e * for example: GameManager PROPERTY_REF(game_manager); */ #define PROPERTY_REF(NAME) PROPERTY_REF_FULL(NAME, private) #define PROPERTY_REF_FULL(NAME, ACCESS) \ NAME; \ +\ public: \ constexpr decltype(NAME)& get_##NAME() { \ return NAME; \ @@ -48,7 +142,7 @@ public: \ constexpr decltype(NAME) const& get_##NAME() const { \ return NAME; \ } \ -ACCESS: + ACCESS: namespace OpenVic { /* Any struct tagged with ov_return_by_value will be returned by value by PROPERTY-generated getter functions, @@ -73,9 +167,7 @@ namespace OpenVic { } else if constexpr (std::same_as) { /* Return std::string_view looking at std::string */ return std::string_view { property }; - } else if constexpr ( - std::integral || std::floating_point || std::is_enum_v || ReturnByValue - ) { + } else if constexpr (std::integral || std::floating_point || std::is_enum_v || ReturnByValue) { /* Return value */ return T { property }; } else if constexpr (std::is_pointer_v) { @@ -108,11 +200,12 @@ namespace OpenVic { #define PROPERTY_ACCESS(NAME, ACCESS) PROPERTY_FULL(NAME, get_##NAME, ACCESS) #define PROPERTY_FULL(NAME, GETTER_NAME, ACCESS) \ NAME; \ +\ public: \ constexpr auto GETTER_NAME() const -> decltype(OpenVic::_get_property(NAME)) { \ return OpenVic::_get_property(NAME); \ } \ -ACCESS: + ACCESS: // TODO: Special logic to decide argument type and control assignment. #define PROPERTY_RW(NAME) PROPERTY_RW_ACCESS(NAME, private) @@ -124,4 +217,4 @@ public: \ constexpr void SETTER_NAME(decltype(NAME) new_##NAME) { \ NAME = new_##NAME; \ } \ -ACCESS: + ACCESS: -- cgit v1.2.3-56-ga3b1