From d236dcf30c001e540377184565f4d173ed56f76e Mon Sep 17 00:00:00 2001 From: Spartan322 Date: Sat, 6 Jul 2024 10:40:57 -0400 Subject: Optimize some string interning cases --- src/openvic-simulation/dataloader/Dataloader.cpp | 6 +- src/openvic-simulation/dataloader/NodeTools.cpp | 136 +++++++++++++++------- src/openvic-simulation/dataloader/NodeTools.hpp | 13 ++- src/openvic-simulation/economy/EconomyManager.hpp | 5 +- src/openvic-simulation/economy/ProductionType.cpp | 20 +++- src/openvic-simulation/economy/ProductionType.hpp | 4 +- src/openvic-simulation/military/UnitType.cpp | 14 ++- src/openvic-simulation/military/UnitType.hpp | 6 +- src/openvic-simulation/military/Wargoal.cpp | 21 +++- src/openvic-simulation/military/Wargoal.hpp | 4 +- 10 files changed, 158 insertions(+), 71 deletions(-) diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 4fbd86b..2058ce5 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -371,7 +371,7 @@ bool Dataloader::_load_units(DefinitionManager& definition_manager) const { definition_manager.get_economy_manager().get_good_definition_manager(), definition_manager.get_map_definition().get_terrain_type_manager(), definition_manager.get_modifier_manager(), - parse_defines(file).get_file_node() + parse_defines(file) ); } ); @@ -905,7 +905,7 @@ bool Dataloader::load_defines(DefinitionManager& definition_manager) { ret = false; } if (!definition_manager.get_economy_manager().load_production_types_file(definition_manager.get_pop_manager(), - parse_defines_cached(lookup_file(production_types_file)).get_file_node() + parse_defines_cached(lookup_file(production_types_file)) )) { Logger::error("Failed to load production types!"); ret = false; @@ -1001,7 +1001,7 @@ bool Dataloader::load_defines(DefinitionManager& definition_manager) { ret = false; } if (!definition_manager.get_military_manager().get_wargoal_type_manager().load_wargoal_file( - parse_defines_cached(lookup_file(cb_types_file)).get_file_node() + parse_defines_cached(lookup_file(cb_types_file)) )) { Logger::error("Failed to load wargoals!"); ret = false; diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp index 8ed82eb..25c5041 100644 --- a/src/openvic-simulation/dataloader/NodeTools.cpp +++ b/src/openvic-simulation/dataloader/NodeTools.cpp @@ -1,7 +1,9 @@ #include "NodeTools.hpp" -#include +#include +#include +#include #include #include @@ -61,13 +63,13 @@ static NodeCallback auto _abstract_statement_node_callback(Callback<_NodeStateme } template T> -static Callback auto _abstract_string_node_callback(Callback auto&& callback, bool allow_empty) { +static Callback auto _abstract_symbol_node_callback(Callback> auto&& callback, bool allow_empty) { return [callback = FWD(callback), allow_empty](T const* node) -> bool { if (allow_empty) { - return callback(node->value().view()); + return callback(node->value()); } else { if (node->value()) { - return callback(node->value().view()); + return callback(node->value()); } else { Logger::error("Invalid string value - empty!"); return false; @@ -76,14 +78,33 @@ static Callback auto _abstract_string_node_callback(Callback T> +static Callback auto _abstract_string_node_callback(Callback auto callback, bool allow_empty) { + return _abstract_symbol_node_callback( + [callback](ovdl::symbol symbol) -> bool { + return callback(symbol.view()); + }, + allow_empty + ); +} + node_callback_t NodeTools::expect_identifier(callback_t callback) { return _expect_type(_abstract_string_node_callback(callback, false)); } +static NodeCallback auto _expect_identifier(Callback> auto callback) { + return _expect_type(_abstract_symbol_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)); } +static NodeCallback auto _expect_string(Callback> auto callback, bool allow_empty) { + return _expect_type(_abstract_symbol_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) { @@ -335,48 +356,83 @@ 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 _abstract_statement_node_callback( - [key, callback, key_found, allow_duplicates](_NodeStatementRange list) -> bool { - bool ret = true; - size_t keys_found = 0; - 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->right()); - if (allow_duplicates) { - break; - } +template +static node_callback_t _expect_key(Key key, NodeCallback auto callback, bool* key_found, bool allow_duplicates) { + if constexpr (std::same_as>) { + if (!key) { + if (key_found != nullptr) { + *key_found = false; + } + return [](ast::NodeCPtr) -> bool { + Logger::error("Failed to find expected interned key."); + return false; + }; + } + } + + static constexpr auto assign_left = [](Key& left) { + if constexpr (std::same_as) { + return expect_identifier(assign_variable_callback(left)); + } else if (std::same_as>) { + return _expect_identifier(assign_variable_callback_cast>(left)); + } + }; + + return _abstract_statement_node_callback([key, callback, key_found, allow_duplicates](_NodeStatementRange list) -> bool { + bool ret = true; + size_t keys_found = 0; + for (auto sub_node : list) { + auto const* assign_node = dryad::node_try_cast(sub_node); + if (assign_node == nullptr) { + continue; + } + Key left; + if (!assign_left(left)(assign_node->left())) { + continue; + } + if (left == key) { + if (keys_found++ == 0) { + ret &= callback(assign_node->right()); + if (allow_duplicates) { + break; } } } - if (keys_found == 0) { - if (key_found != nullptr) { - *key_found = false; - } else { - Logger::error("Failed to find expected key: \"", key, "\""); - } - ret = false; + } + std::string_view key_str = [&] { + if constexpr (std::same_as) { + return key; } else { - if (key_found != nullptr) { - *key_found = true; - } - if (!allow_duplicates && keys_found > 1) { - Logger::error("Found ", keys_found, " instances of key: \"", key, "\" (expected 1)"); - ret = false; - } + return key.view(); + } + }(); + if (keys_found == 0) { + if (key_found != nullptr) { + *key_found = false; + } else { + Logger::error("Failed to find expected key: \"", key_str, "\""); + } + ret = false; + } else { + if (key_found != nullptr) { + *key_found = true; + } + if (!allow_duplicates && keys_found > 1) { + Logger::error("Found ", keys_found, " instances of key: \"", key_str, "\" (expected 1)"); + ret = false; } - return ret; } - ); + return ret; + }); +} + +node_callback_t NodeTools::expect_key(std::string_view key, node_callback_t callback, bool* key_found, bool allow_duplicates) { + return _expect_key(key, callback, key_found, allow_duplicates); +} + +node_callback_t +NodeTools::expect_key(ovdl::symbol key, node_callback_t callback, bool* key_found, bool allow_duplicates) { + return _expect_key(key, callback, key_found, allow_duplicates); } node_callback_t NodeTools::expect_dictionary_and_length(length_callback_t length_callback, key_value_callback_t callback) { diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index acf5a41..30cba65 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -172,6 +173,10 @@ namespace OpenVic { node_callback_t expect_list(node_callback_t callback); node_callback_t expect_length(callback_t callback); + node_callback_t expect_key( + ovdl::symbol key, node_callback_t callback, bool* key_found = nullptr, bool allow_duplicates = false + ); + node_callback_t expect_key( std::string_view key, node_callback_t callback, bool* key_found = nullptr, bool allow_duplicates = false ); @@ -269,14 +274,10 @@ namespace OpenVic { return ret; } - template - constexpr bool add_key_map_entries(template_key_map_t& key_map) { + template + constexpr bool add_key_map_entries(Map&& key_map) { return true; } - template - constexpr bool add_key_map_entries(template_key_map_t&& key_map) { - return add_key_map_entries(key_map); - } template bool add_key_map_entries( diff --git a/src/openvic-simulation/economy/EconomyManager.hpp b/src/openvic-simulation/economy/EconomyManager.hpp index 668774d..2464912 100644 --- a/src/openvic-simulation/economy/EconomyManager.hpp +++ b/src/openvic-simulation/economy/EconomyManager.hpp @@ -3,6 +3,7 @@ #include "openvic-simulation/economy/BuildingType.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" #include "openvic-simulation/economy/ProductionType.hpp" +#include "openvic-dataloader/v2script/Parser.hpp" namespace OpenVic { struct EconomyManager { @@ -12,8 +13,8 @@ namespace OpenVic { ProductionTypeManager PROPERTY_REF(production_type_manager); public: - inline bool load_production_types_file(PopManager const& pop_manager, ast::NodeCPtr root) { - return production_type_manager.load_production_types_file(good_definition_manager, pop_manager, root); + inline bool load_production_types_file(PopManager const& pop_manager, ovdl::v2script::Parser const& parser) { + return production_type_manager.load_production_types_file(good_definition_manager, pop_manager, parser); } inline bool load_buildings_file(ModifierManager& modifier_manager, ast::NodeCPtr root) { diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp index 9b5a42b..65f3eba 100644 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -1,5 +1,7 @@ #include "ProductionType.hpp" +#include + using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -176,21 +178,27 @@ bool ProductionTypeManager::add_production_type( } bool ProductionTypeManager::load_production_types_file( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ast::NodeCPtr root + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ovdl::v2script::Parser const& parser ) { + using namespace std::string_view_literals; + auto template_symbol = parser.find_intern("template"sv); + if (!template_symbol) { + Logger::error("template could not be interned."); + } + size_t expected_types = 0; /* Pass #1: find and store template identifiers */ ordered_set templates; ordered_map template_target_map; bool ret = expect_dictionary( - [this, &expected_types, &templates, &template_target_map](std::string_view key, ast::NodeCPtr value) -> bool { + [this, &expected_types, &templates, &template_target_map, &template_symbol](std::string_view key, ast::NodeCPtr value) -> bool { expected_types++; std::string_view template_id = ""; bool found_template = false; const bool ret = - expect_key("template", expect_identifier(assign_variable_callback(template_id)), &found_template)(value); + expect_key(template_symbol, expect_identifier(assign_variable_callback(template_id)), &found_template)(value); if (found_template) { if (ret) { templates.emplace(template_id); @@ -202,7 +210,7 @@ bool ProductionTypeManager::load_production_types_file( } return true; } - )(root); + )(parser.get_file_node()); /* Pass #2: create and populate the template map */ ordered_map template_node_map; @@ -214,7 +222,7 @@ bool ProductionTypeManager::load_production_types_file( } return true; } - )(root); + )(parser.get_file_node()); /* Pass #3: actually load production types */ reserve_more_production_types(expected_types); @@ -297,7 +305,7 @@ bool ProductionTypeManager::load_production_types_file( ); return ret; } - )(root); + )(parser.get_file_node()); production_types.lock(); diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp index ed3b84f..5394938 100644 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "openvic-simulation/economy/GoodDefinition.hpp" #include "openvic-simulation/pop/Pop.hpp" #include "openvic-simulation/scripts/ConditionScript.hpp" @@ -111,7 +113,7 @@ namespace OpenVic { ); bool load_production_types_file( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ast::NodeCPtr root + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ovdl::v2script::Parser const& parser ); bool parse_scripts(DefinitionManager const& definition_manager); diff --git a/src/openvic-simulation/military/UnitType.cpp b/src/openvic-simulation/military/UnitType.cpp index 7a582c8..fb65bf8 100644 --- a/src/openvic-simulation/military/UnitType.cpp +++ b/src/openvic-simulation/military/UnitType.cpp @@ -147,15 +147,21 @@ bool UnitTypeManager::add_ship_type( bool UnitTypeManager::load_unit_type_file( GoodDefinitionManager const& good_definition_manager, TerrainTypeManager const& terrain_type_manager, - ModifierManager const& modifier_manager, ast::NodeCPtr root + ModifierManager const& modifier_manager, ovdl::v2script::Parser const& parser ) { - return expect_dictionary([this, &good_definition_manager, &terrain_type_manager, &modifier_manager]( + using namespace std::string_view_literals; + auto type_symbol = parser.find_intern("type"sv); + if(!type_symbol) { + Logger::error("type could not be interned."); + } + + return expect_dictionary([this, &good_definition_manager, &terrain_type_manager, &modifier_manager, &type_symbol]( std::string_view key, ast::NodeCPtr value ) -> bool { UnitType::branch_t branch = INVALID_BRANCH; - bool ret = expect_key("type", expect_branch_identifier(assign_variable_callback(branch)))(value); + bool ret = expect_key(type_symbol, expect_branch_identifier(assign_variable_callback(branch)))(value); /* We shouldn't just check ret as it can be false even if branch was successfully parsed, * but more than one instance of the key was found. */ @@ -282,7 +288,7 @@ bool UnitTypeManager::load_unit_type_file( Logger::error("Unknown branch for unit ", key, ": ", static_cast(branch)); return false; } - })(root); + })(parser.get_file_node()); } bool UnitTypeManager::generate_modifiers(ModifierManager& modifier_manager) const { diff --git a/src/openvic-simulation/military/UnitType.hpp b/src/openvic-simulation/military/UnitType.hpp index 095a759..1642f22 100644 --- a/src/openvic-simulation/military/UnitType.hpp +++ b/src/openvic-simulation/military/UnitType.hpp @@ -3,9 +3,11 @@ #include #include -#include "openvic-simulation/misc/Modifier.hpp" +#include + #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" +#include "openvic-simulation/misc/Modifier.hpp" #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" @@ -191,7 +193,7 @@ namespace OpenVic { bool load_unit_type_file( GoodDefinitionManager const& good_definition_manager, TerrainTypeManager const& terrain_type_manager, - ModifierManager const& modifier_manager, ast::NodeCPtr root + ModifierManager const& modifier_manager, ovdl::v2script::Parser const& parser ); bool generate_modifiers(ModifierManager& modifier_manager) const; }; diff --git a/src/openvic-simulation/military/Wargoal.cpp b/src/openvic-simulation/military/Wargoal.cpp index afb1a24..773e791 100644 --- a/src/openvic-simulation/military/Wargoal.cpp +++ b/src/openvic-simulation/military/Wargoal.cpp @@ -1,5 +1,7 @@ #include "Wargoal.hpp" +#include + #include "openvic-simulation/dataloader/NodeTools.hpp" using namespace OpenVic; @@ -68,11 +70,18 @@ bool WargoalTypeManager::add_wargoal_type( }); } -bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) { +bool WargoalTypeManager::load_wargoal_file(ovdl::v2script::Parser const& parser) { + using namespace std::string_view_literals; + ovdl::symbol peace_order_symbol = parser.find_intern("peace_order"sv); + if (!peace_order_symbol) { + Logger::error("peace_order could not be interned."); + } + bool ret = expect_dictionary_reserve_length( wargoal_types, - [this](std::string_view identifier, ast::NodeCPtr value) -> bool { - if (identifier == "peace_order") { + [this, &peace_order_symbol](std::string_view identifier, ast::NodeCPtr value) -> bool { + // If peace_order_symbol is false, we know there is no peace_order string in the parser + if (peace_order_symbol && identifier == peace_order_symbol.c_str()) { return true; } @@ -187,11 +196,11 @@ bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) { ); return ret; } - )(root); + )(parser.get_file_node()); /* load order in which CBs are prioritised by AI */ ret &= expect_key( - "peace_order", + peace_order_symbol, expect_list( expect_wargoal_type_identifier( [this](WargoalType const& wargoal) -> bool { @@ -205,7 +214,7 @@ bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) { true // warn instead of error ) ) - )(root); + )(parser.get_file_node()); lock_wargoal_types(); return ret; diff --git a/src/openvic-simulation/military/Wargoal.hpp b/src/openvic-simulation/military/Wargoal.hpp index ecd8056..8387821 100644 --- a/src/openvic-simulation/military/Wargoal.hpp +++ b/src/openvic-simulation/military/Wargoal.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "openvic-simulation/scripts/ConditionScript.hpp" #include "openvic-simulation/scripts/EffectScript.hpp" #include "openvic-simulation/types/EnumBitfield.hpp" @@ -111,7 +113,7 @@ namespace OpenVic { ConditionScript&& allowed_countries, EffectScript&& on_add, EffectScript&& on_po_accepted ); - bool load_wargoal_file(ast::NodeCPtr root); + bool load_wargoal_file(ovdl::v2script::Parser const& parser); bool parse_scripts(DefinitionManager const& definition_manager); }; -- cgit v1.2.3-56-ga3b1