From 5c9923dabaf2806e0ba45708a958f64f94f9a316 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sat, 2 Apr 2016 08:27:15 -0400 Subject: [PATCH] Formula engine: Add pair() function --- changelog | 4 ++++ src/formula/function.cpp | 43 +++++++++++++++++++++++++++++++--------- src/formula/function.hpp | 2 ++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/changelog b/changelog index 913b712b57ee..57f61852ffe5 100644 --- a/changelog +++ b/changelog @@ -214,6 +214,7 @@ Version 1.13.4+dev: This counts backwards from the specified offset A size of -1 is the same as 1. * if() can take two arguments; returns null if the condition is false + * tolist() will now invert the effect of tomap() * debug_print() now shows in console if debug mode is on * New core functions: * Trig functions tan, acos, asin, atan have been added. (Sin and cos @@ -230,6 +231,9 @@ Version 1.13.4+dev: * replace() replaces a sequence within a string * type() function checks the type of a formula result * distance_between() - this was promoted from FormulaAI to core + * pair() function that produces a key-value pair suitable for + passing to tomap() - this also means key-value pairs are now + serializable (relevant in FormulaAI) * Bugfixes: * Dice operator is now synced (where possible) * Modulus (%) operator now works on decimal numbers diff --git a/src/formula/function.cpp b/src/formula/function.cpp index a8f69f4d677e..565fac7252fc 100644 --- a/src/formula/function.cpp +++ b/src/formula/function.cpp @@ -406,11 +406,16 @@ class tomap_function : public function_expression { } else { for(variant_iterator it = var_1.begin(); it != var_1.end(); ++it) { - std::map::iterator map_it = tmp.find( *it ); - if (map_it == tmp.end()) - tmp[ *it ] = variant( 1 ); - else - map_it->second = variant(map_it->second.as_int() + 1); + if (key_value_pair* kv = (*it).try_convert()) + tmp[kv->query_value("key")] = kv->query_value("value"); + else { + std::map::iterator map_it = tmp.find( *it ); + if (map_it == tmp.end()) { + tmp[*it] = variant(1); + } else { + map_it->second = variant(map_it->second.as_int() + 1); + } + } } } @@ -1355,6 +1360,20 @@ class loc_function : public function_expression { } }; +class pair_function : public function_expression { +public: + explicit pair_function(const args_list& args) + : function_expression("pair", args, 2, 2) + {} +private: + variant execute(const formula_callable& variables, formula_debugger *fdb) const { + return variant(new key_value_pair( + args()[0]->evaluate(variables,add_debug_info(fdb,0,"pair:key")), + args()[1]->evaluate(variables,add_debug_info(fdb,1,"pair_value")) + )); + } +}; + class distance_between_function : public function_expression { public: explicit distance_between_function(const args_list& args) @@ -1402,6 +1421,15 @@ void key_value_pair::get_inputs(std::vector* inputs) inputs->push_back(game_logic::formula_input("value", game_logic::FORMULA_READ_ONLY)); } + +void key_value_pair::serialize_to_string(std::string& str) const { + str += "pair("; + key_.serialize_to_string(str); + str += ","; + value_.serialize_to_string(str); + str += ")"; +} + formula_function_expression::formula_function_expression(const std::string& name, const args_list& args, const_formula_ptr formula, const_formula_ptr precondition, const std::vector& arg_names) : function_expression(name, args, arg_names.size(), arg_names.size()), formula_(formula), precondition_(precondition), arg_names_(arg_names), star_arg_(-1) @@ -1516,6 +1544,7 @@ function_symbol_table& get_functions_map() { FUNCTION(round); FUNCTION(as_decimal); FUNCTION(refcount); + FUNCTION(pair); FUNCTION(loc); FUNCTION(distance_between); FUNCTION(index_of); @@ -1544,10 +1573,6 @@ function_symbol_table& get_functions_map() { #undef FUNCTION } -#ifdef HAVE_VISUAL_LEAK_DETECTOR - VLDEnable(); -#endif - return functions_table; } diff --git a/src/formula/function.hpp b/src/formula/function.hpp index 32e407e20783..4d72351768f6 100644 --- a/src/formula/function.hpp +++ b/src/formula/function.hpp @@ -80,6 +80,8 @@ class key_value_pair : public formula_callable { void get_inputs(std::vector* inputs) const; public: explicit key_value_pair(const variant& key, const variant& value) : key_(key), value_(value) {} + + void serialize_to_string(std::string& str) const; }; class formula_function_expression : public function_expression {