diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.cpp | 10 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.hpp | 2 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/NodeTools.cpp | 135 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/NodeTools.hpp | 24 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/Vic2PathSearch.cpp | 4 | ||||
-rw-r--r-- | src/openvic-simulation/misc/Modifier.cpp | 8 | ||||
-rw-r--r-- | src/openvic-simulation/utility/Getters.hpp | 147 |
7 files changed, 251 insertions, 79 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index dab479f..f42a518 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -204,7 +204,7 @@ template<std::derived_from<detail::BasicParser> 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<char>( [](void const* s, std::streamsize n, void* user_data) -> std::streamsize { if (s != nullptr && n > 0 && user_data != nullptr) { static_cast<std::string*>(user_data)->append(static_cast<char const*>(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<v2script::Parser, &_lua_parse>(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<csv::Windows1252Parser, &_csv_parse>(path); +csv::Parser Dataloader::parse_csv(fs::path const& path) { + return _run_ovdl_parser<csv::Parser, &_csv_parse>(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 <type_traits> + +#include <openvic-dataloader/detail/Utility.hpp> +#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> + +#include <dryad/node.hpp> + +#include <range/v3/iterator/operations.hpp> +#include <range/v3/view/enumerate.hpp> + #include "openvic-simulation/types/Colour.hpp" +#include "openvic-simulation/utility/Getters.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; template<typename T> -static NodeCallback auto _expect_type(Callback<T const&> auto callback) { +static NodeCallback auto _expect_type(Callback<T const*> auto callback) { return [callback](ast::NodeCPtr node) -> bool { if (node != nullptr) { - T const* cast_node = node->cast_to<T>(); + T const* cast_node = dryad::node_try_cast<T>(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<T>()); } else { - Logger::error("Null node when expecting ", T::get_type_static()); + Logger::error("Null node when expecting ", utility::type_name<T>()); } return false; }; } -template<std::derived_from<ast::AbstractStringNode> T> -static Callback<T const&> auto _abstract_string_node_callback(Callback<std::string_view> auto callback, bool allow_empty) { - return [callback, allow_empty](T const& node) -> bool { +using _NodeIterator = typename decltype(std::declval<ast::NodeCPtr>()->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<ast::FileTree>(node)) { + return callback(file_tree->statements()); + } + if (auto const* list_value = dryad::node_try_cast<ast::ListValue>(node)) { + return callback(list_value->statements()); + } + Logger::error( + "Invalid node type ", ast::get_type_name(node->kind()), " when expecting ", utility::type_name<ast::FileTree>(), " or ", + utility::type_name<ast::ListValue>() + ); + } else { + Logger::error( + "Null node when expecting ", utility::type_name<ast::FileTree>(), " or ", utility::type_name<ast::ListValue>() + ); + } + return false; + }; +} + +template<std::derived_from<ast::FlatValue> T> +static Callback<T const*> auto _abstract_string_node_callback(Callback<std::string_view> 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<T const&> auto _abstract_string_node_callback(Callback<std::stri } node_callback_t NodeTools::expect_identifier(callback_t<std::string_view> callback) { - return _expect_type<ast::IdentifierNode>(_abstract_string_node_callback<ast::IdentifierNode>(callback, false)); + return _expect_type<ast::IdentifierValue>(_abstract_string_node_callback<ast::IdentifierValue>(callback, false)); } node_callback_t NodeTools::expect_string(callback_t<std::string_view> callback, bool allow_empty) { - return _expect_type<ast::StringNode>(_abstract_string_node_callback<ast::StringNode>(callback, allow_empty)); + return _expect_type<ast::StringValue>(_abstract_string_node_callback<ast::StringValue>(callback, allow_empty)); } node_callback_t NodeTools::expect_identifier_or_string(callback_t<std::string_view> callback, bool allow_empty) { return [callback, allow_empty](ast::NodeCPtr node) -> bool { if (node != nullptr) { - ast::AbstractStringNode const* cast_node = node->cast_to<ast::IdentifierNode>(); - if (cast_node == nullptr) { - cast_node = node->cast_to<ast::StringNode>(); - } + auto const* cast_node = dryad::node_try_cast<ast::FlatValue>(node); if (cast_node != nullptr) { - return _abstract_string_node_callback<ast::AbstractStringNode>(callback, allow_empty)(*cast_node); + return _abstract_string_node_callback<ast::FlatValue>(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<ast::IdentifierValue>(), " or ", + utility::type_name<ast::StringValue>() ); } 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<ast::IdentifierValue>(), " or ", utility::type_name<ast::StringValue>() ); } return false; @@ -221,28 +254,42 @@ node_callback_t NodeTools::expect_fvec2(callback_t<fvec2_t> callback) { } node_callback_t NodeTools::expect_assign(key_value_callback_t callback) { - return _expect_type<ast::AssignNode>([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<ast::AssignStatement>([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<ast::AbstractListNode>([length_callback, callback](ast::AbstractListNode const& list_node) -> bool { - std::vector<ast::NodeUPtr> 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<ast::ValueStatement>(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<size_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<ast::AbstractListNode>( - [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<ast::NodeUPtr> const& list = list_node._statements; - for (ast::NodeUPtr const& sub_node : list_node._statements) { - ast::AssignNode const* assign_node = sub_node->cast_to<ast::AssignNode>(); - if (assign_node != nullptr && assign_node->_name == key) { + for (auto sub_node : list) { + auto const* assign_node = dryad::node_try_cast<ast::AssignStatement>(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<ast::Node>(); + 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::string>; 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<char>( [](void const* s, std::streamsize n, void* user_data) -> std::streamsize { if (s != nullptr && n > 0 && user_data != nullptr) { static_cast<std::string*>(user_data)->append(static_cast<char const*>(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 <string> +#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> + +#include <dryad/node.hpp> + #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<ast::IdentifierNode>()) { + if (effect != nullptr && dryad::node_has_kind<ast::IdentifierValue>(value)) { return add_modifier_cb(effect, value); - } else if (complex_modifiers.contains(key) && value->is_derived_from<ast::AbstractListNode>()) { + } else if (complex_modifiers.contains(key) && dryad::node_has_kind<ast::ListValue>(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 <array> #include <concepts> +#include <cstddef> #include <string> #include <string_view> +#include <type_traits> +#include <utility> -#include <openvic-dataloader/detail/SelfType.hpp> -#include <openvic-dataloader/detail/TypeName.hpp> +namespace OpenVic::utility { + template<std::size_t... Idxs> + constexpr auto substring_as_array(std::string_view str, std::index_sequence<Idxs...>) { + return std::array { str[Idxs]... }; + } + + template<typename T> + 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<name.size()> {}); + } + + template<typename T> + struct type_name_holder { + static inline constexpr auto value = type_name_array<T>(); + }; + + template<typename T> + constexpr auto type_name() -> std::string_view { + constexpr auto& value = type_name_holder<T>::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<typename T> + struct Reader { + friend auto adl_GetSelfType(Reader<T>); + }; + + template<typename T, typename U> + struct Writer { + friend auto adl_GetSelfType(Reader<T>) { + return U {}; + } + }; +#if !defined(_MSC_VER) +#pragma GCC diagnostic pop +#endif + + inline void adl_GetSelfType() {} + + template<typename T> + using Read = std::remove_pointer_t<decltype(adl_GetSelfType(Reader<T> {}))>; +} #define OV_DETAIL_GET_TYPE_BASE_CLASS(CLASS) \ - static constexpr std::string_view get_type_static() { return ::ovdl::detail::type_name<CLASS>(); } \ + static constexpr std::string_view get_type_static() { \ + return ::OpenVic::utility::type_name<CLASS>(); \ + } \ constexpr virtual std::string_view get_type() const = 0; \ - static constexpr std::string_view get_base_type_static() { return ::ovdl::detail::type_name<CLASS>(); } \ - constexpr virtual std::string_view get_base_type() const { return get_base_type_static(); } \ - template<typename T> constexpr bool is_type() const { \ - return get_type().compare(::ovdl::detail::type_name<T>()) == 0; } \ - template<typename T> constexpr bool is_derived_from() const { \ - return is_type<T>() || get_base_type().compare(::ovdl::detail::type_name<T>()) == 0; } \ - template<typename T> constexpr T* cast_to() { \ - if (is_derived_from<T>() || is_type<CLASS>()) return (static_cast<T*>(this)); \ - return nullptr; } \ - template<typename T> constexpr const T* const cast_to() const { \ - if (is_derived_from<T>() || is_type<CLASS>()) return (static_cast<const T*>(this)); \ - return nullptr; } + static constexpr std::string_view get_base_type_static() { \ + return ::OpenVic::utility::type_name<CLASS>(); \ + } \ + constexpr virtual std::string_view get_base_type() const { \ + return get_base_type_static(); \ + } \ + template<typename T> \ + constexpr bool is_type() const { \ + return get_type().compare(::OpenVic::utility::type_name<T>()) == 0; \ + } \ + template<typename T> \ + constexpr bool is_derived_from() const { \ + return is_type<T>() || get_base_type().compare(::OpenVic::utility::type_name<T>()) == 0; \ + } \ + template<typename T> \ + constexpr T* cast_to() { \ + if (is_derived_from<T>() || is_type<CLASS>()) \ + return (static_cast<T*>(this)); \ + return nullptr; \ + } \ + template<typename T> \ + constexpr const T* const cast_to() const { \ + if (is_derived_from<T>() || is_type<CLASS>()) \ + return (static_cast<const T*>(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<type>(); } \ + 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<type>(); \ + } \ constexpr std::string_view get_type() const override { \ - return ::ovdl::detail::type_name<std::decay_t<decltype(*this)>>(); } + return ::OpenVic::utility::type_name<std::decay_t<decltype(*this)>>(); \ + } #define OV_DETAIL_GET_BASE_TYPE(CLASS) \ - static constexpr std::string_view get_base_type_static() { return ::ovdl::detail::type_name<CLASS>(); } \ + static constexpr std::string_view get_base_type_static() { \ + return ::OpenVic::utility::type_name<CLASS>(); \ + } \ constexpr std::string_view get_base_type() const override { \ - return ::ovdl::detail::type_name<std::decay_t<decltype(*this)>>(); } + return ::OpenVic::utility::type_name<std::decay_t<decltype(*this)>>(); \ + } /* 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<T, std::string>) { /* Return std::string_view looking at std::string */ return std::string_view { property }; - } else if constexpr ( - std::integral<T> || std::floating_point<T> || std::is_enum_v<T> || ReturnByValue<T> - ) { + } else if constexpr (std::integral<T> || std::floating_point<T> || std::is_enum_v<T> || ReturnByValue<T>) { /* Return value */ return T { property }; } else if constexpr (std::is_pointer_v<T>) { @@ -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<decltype(NAME)>(NAME)) { \ return OpenVic::_get_property<decltype(NAME)>(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: |