18 #include "formula/callable_objects.hpp"
25 #include <boost/math/constants/constants.hpp>
28 #ifdef HAVE_VISUAL_LEAK_DETECTOR
34 #define DBG_NG LOG_STREAM(debug, log_engine)
36 #define LOG_SF LOG_STREAM(info, log_scripting_formula)
37 #define WRN_SF LOG_STREAM(warn, log_scripting_formula)
38 #define ERR_SF LOG_STREAM(err, log_scripting_formula)
47 bool first_arg =
true;
64 explicit debug_function(
const args_list& args)
68 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
70 bool need_wrapper =
false;
78 if (args().size()==1) {
80 return args()[0]->evaluate(variables,fdb);
82 return wrapper_formula(args()[0]).evaluate(variables,fdb);
85 return wrapper_formula().evaluate(variables,fdb);
91 class dir_function :
public function_expression {
93 explicit dir_function(
const args_list& args)
94 : function_expression(
"dir", args, 1, 1)
98 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
99 variant var = args()[0]->evaluate(variables, fdb);
100 const formula_callable* callable = var.
as_callable();
102 std::vector<formula_input> inputs = callable->inputs();
103 std::vector<variant>
res;
104 for(
size_t i=0;
i<inputs.size(); ++
i) {
105 const formula_input&
input = inputs[
i];
106 res.push_back(
variant(input.name));
113 class if_function :
public function_expression {
115 explicit if_function(
const args_list& args)
116 : function_expression(
"if", args, 2, -1)
120 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
121 for(
size_t n = 0;
n < args().size()-1;
n += 2) {
122 if( args()[
n]->evaluate(variables,fdb).as_bool() ) {
123 return args()[
n+1]->evaluate(variables,fdb);
127 if((args().
size()%2) != 0) {
128 return args().back()->evaluate(variables,fdb);
136 class switch_function :
public function_expression {
138 explicit switch_function(
const args_list& args)
139 : function_expression(
"switch", args, 3, -1)
143 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
144 variant var = args()[0]->evaluate(variables,fdb);
145 for(
size_t n = 1;
n < args().size()-1;
n += 2) {
148 return args()[
n+1]->evaluate(variables,fdb);
152 if((args().
size()%2) == 0) {
153 return args().back()->evaluate(variables,fdb);
160 class abs_function :
public function_expression {
162 explicit abs_function(
const args_list& args)
163 : function_expression(
"abs", args, 1, 1)
167 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
168 const variant input = args()[0]->evaluate(variables,fdb);
173 const int n = input.
as_int();
174 return variant(n >= 0 ? n : -n);
179 class min_function :
public function_expression {
181 explicit min_function(
const args_list& args)
182 : function_expression(
"min", args, 1, -1)
186 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
189 for(
size_t n = 0;
n != args().size(); ++
n) {
190 const variant v = args()[
n]->evaluate(variables,fdb);
193 if(!found || v[
m] < res) {
199 if(!found || v < res) {
210 class max_function :
public function_expression {
212 explicit max_function(
const args_list& args)
213 : function_expression(
"max", args, 1, -1)
217 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
220 for(
size_t n = 0;
n != args().size(); ++
n) {
221 const variant v = args()[
n]->evaluate(variables,fdb);
224 if(!found || v[
m] > res) {
230 if(!found || v > res) {
241 class debug_float_function :
public function_expression {
243 explicit debug_float_function(
const args_list& args)
244 : function_expression(
"debug_float", args, 2, 3)
248 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
249 const args_list& arguments = args();
250 const variant var0 = arguments[0]->evaluate(variables,fdb);
251 const variant var1 = arguments[1]->evaluate(variables,fdb);
256 if(arguments.size() == 2) {
258 display_float(location,text);
261 const variant var2 = arguments[2]->evaluate(variables,fdb);
263 display_float(location,text);
275 class debug_print_function :
public function_expression {
277 explicit debug_print_function(
const args_list& args)
278 : function_expression(
"debug_print", args, 1, 2)
282 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
283 const variant var1 = args()[0]->evaluate(variables,fdb);
287 if( args().
size() == 1)
290 LOG_SF << str1 << std::endl;
297 const variant var2 = args()[1]->evaluate(variables,fdb);
299 LOG_SF << str1 << str2 << std::endl;
308 class debug_profile_function :
public function_expression {
310 explicit debug_profile_function(
const args_list& args)
311 : function_expression(
"debug_profile", args, 1, 2)
315 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
318 if(args().
size() == 2) {
319 speaker = args()[0]->evaluate(variables, fdb).string_cast();
323 const variant value = args()[i_value]->evaluate(variables,fdb);
325 for(
int i = 1;
i < 1000;
i++) {
326 const long start = SDL_GetTicks();
327 args()[i_value]->evaluate(variables,fdb);
328 run_time += SDL_GetTicks() -
start;
331 std::ostringstream str;
332 str <<
"Evaluated in " << (run_time / 1000.0) <<
" ms on average";
333 LOG_SF << speaker <<
": " << str.str() << std::endl;
341 class keys_function :
public function_expression {
343 explicit keys_function(
const args_list& args)
344 : function_expression(
"keys", args, 1, 1)
348 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
349 const variant map = args()[0]->evaluate(variables,fdb);
354 class values_function :
public function_expression {
356 explicit values_function(
const args_list& args)
357 : function_expression(
"values", args, 1, 1)
361 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
362 const variant map = args()[0]->evaluate(variables,fdb);
367 class tolist_function :
public function_expression {
369 explicit tolist_function(
const args_list& args)
370 : function_expression(
"tolist", args, 1, 1)
374 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
375 const variant var = args()[0]->evaluate(variables,fdb);
377 std::vector<variant> tmp;
380 tmp.push_back( *it );
387 class tomap_function :
public function_expression {
389 explicit tomap_function(
const args_list& args)
390 : function_expression(
"tomap", args, 1, 2)
394 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
395 const variant var_1 = args()[0]->evaluate(variables,fdb);
397 std::map<variant, variant> tmp;
399 if (args().
size() == 2)
401 const variant var_2 = args()[1]->evaluate(variables,fdb);
405 tmp[ var_1[
i] ] = var_2[
i];
409 if (key_value_pair* kv = (*it).try_convert<key_value_pair>())
410 tmp[kv->query_value(
"key")] = kv->query_value(
"value");
413 if (map_it == tmp.end()) {
416 map_it->second =
variant(map_it->second.as_int() + 1);
426 class substring_function :
public function_expression {
428 explicit substring_function(
const args_list& args)
429 : function_expression(
"substring", args, 2, 3)
432 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
436 int offset = args()[1]->evaluate(variables, fdb).as_int();
438 offset += result.size();
443 if(static_cast<size_t>(offset) >= result.size()) {
448 if(args().
size() > 2) {
449 int size = args()[2]->evaluate(variables, fdb).as_int();
452 offset = std::max(0, offset - size + 1);
454 return variant(result.substr(offset, size));
456 return variant(result.substr(offset));
461 class replace_function :
public function_expression {
463 explicit replace_function(
const args_list& args)
464 : function_expression(
"replace", args, 3, 4)
467 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
469 std::string result = args()[0]->evaluate(variables, fdb).as_string();
470 std::string replacement = args().back()->evaluate(variables, fdb).as_string();
472 int offset = args()[1]->evaluate(variables, fdb).as_int();
474 offset += result.size();
479 if(static_cast<size_t>(offset) >= result.size()) {
484 if(args().
size() > 3) {
485 int size = args()[2]->evaluate(variables, fdb).as_int();
488 offset = std::max(0, offset - size + 1);
490 return variant(result.replace(offset, size, replacement));
492 return variant(result.replace(offset, std::string::npos, replacement));
497 class length_function :
public function_expression {
499 explicit length_function(
const args_list& args)
500 : function_expression(
"length", args, 1, 1)
503 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
504 return variant(args()[0]->evaluate(variables, fdb).as_string().
length());
508 class concatenate_function :
public function_expression {
510 explicit concatenate_function(
const args_list& args)
511 : function_expression(
"concatenate", args, 1, -1)
514 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
518 result += arg->evaluate(variables, fdb).string_cast();
525 class sin_function :
public function_expression {
527 explicit sin_function(
const args_list& args)
528 : function_expression(
"sin", args, 1, 1)
531 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
532 const double angle = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
533 const double result = sin(angle * pi<double>() / 180.0);
538 class cos_function :
public function_expression {
540 explicit cos_function(
const args_list& args)
541 : function_expression(
"cos", args, 1, 1)
544 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
545 const double angle = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
546 const double result = cos(angle * pi<double>() / 180.0);
551 class tan_function :
public function_expression {
553 explicit tan_function(
const args_list& args)
554 : function_expression(
"tan", args, 1, 1)
557 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
558 const double angle = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
559 const double result = tan(angle * pi<double>() / 180.0);
567 class asin_function :
public function_expression {
569 explicit asin_function(
const args_list& args)
570 : function_expression(
"asin", args, 1, 1)
574 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
575 const double num = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
576 const double result = asin(num) * 180.0 / pi<double>();
577 if(result != result) {
584 class acos_function :
public function_expression {
586 explicit acos_function(
const args_list& args)
587 : function_expression(
"acos", args, 1, 1)
590 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
591 const double num = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
592 const double result = acos(num) * 180.0 / pi<double>();
593 if(result != result) {
600 class atan_function :
public function_expression {
602 explicit atan_function(
const args_list& args)
603 : function_expression(
"acos", args, 1, 1)
606 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
607 const double num = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
608 const double result = atan(num) * 180.0 / pi<double>();
613 class sqrt_function :
public function_expression {
615 explicit sqrt_function(
const args_list& args)
616 : function_expression(
"sqrt", args, 1, 1)
619 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
620 const double num = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
621 const double result = sqrt(num);
622 if(result != result) {
629 class cbrt_function :
public function_expression {
631 explicit cbrt_function(
const args_list& args)
632 : function_expression(
"cbrt", args, 1, 1)
635 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
636 const double num = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
637 const double result = num < 0 ? -pow(-num, 1.0 / 3.0) : pow(num, 1.0 / 3.0);
642 class root_function :
public function_expression {
644 explicit root_function(
const args_list& args)
645 : function_expression(
"root", args, 2, 2)
648 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
649 const double base = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
650 const double root = args()[1]->evaluate(variables,fdb).as_decimal() / 1000.0;
651 const double result = base < 0 && fmod(root,2) == 1 ? -pow(-base, 1.0 / root) : pow(base, 1.0 / root);
652 if(result != result) {
659 class log_function :
public function_expression {
661 explicit log_function(
const args_list& args)
662 : function_expression(
"log", args, 1, 2)
665 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
666 const double num = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
667 if(args().
size() == 1) {
668 const double result = log(num);
669 if(result != result) {
674 const double base = args()[1]->evaluate(variables,fdb).as_decimal() / 1000.0;
675 const double result = log(num) / log(base);
676 if(result != result) {
684 class exp_function :
public function_expression {
686 explicit exp_function(
const args_list& args)
687 : function_expression(
"exp", args, 1, 1)
690 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
691 const double num = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
692 const double result = exp(num);
693 if(result == 0 || result >= INT_MAX) {
702 class pi_function :
public function_expression {
704 explicit pi_function(
const args_list& args)
705 : function_expression(
"pi", args, 0, 0)
708 variant execute(
const formula_callable&, formula_debugger*)
const {
713 class hypot_function :
public function_expression {
715 explicit hypot_function(
const args_list& args)
716 : function_expression(
"hypot", args, 2, 2)
719 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
720 const double x = args()[0]->evaluate(variables,fdb).
as_decimal() / 1000.0;
721 const double y = args()[1]->evaluate(variables,fdb).as_decimal() / 1000.0;
726 class index_of_function :
public function_expression {
728 explicit index_of_function(
const args_list& args)
729 : function_expression(
"index_of", args, 2, 2)
733 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
734 const variant value = args()[0]->evaluate(variables,fdb);
735 const variant list = args()[1]->evaluate(variables,fdb);
738 if( list[
i] == value) {
748 class choose_function :
public function_expression {
750 explicit choose_function(
const args_list& args)
751 : function_expression(
"choose", args, 2, 3)
755 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
756 const variant items = args()[0]->evaluate(variables,fdb);
760 if(args().
size() == 2) {
762 const variant val = args().back()->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
769 map_formula_callable self_callable;
770 self_callable.add_ref();
771 const std::string self = args()[1]->evaluate(variables,fdb).as_string();
773 self_callable.add(
self, *it);
774 const variant val = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
790 class wave_function :
public function_expression {
792 explicit wave_function(
const args_list& args)
793 : function_expression(
"wave", args, 1, 1)
797 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
798 const int value = args()[0]->evaluate(variables,fdb).
as_int()%1000;
799 const double angle = 2.0 * pi<double>() * (static_cast<double>(value) / 1000.0);
800 return variant(static_cast<int>(sin(angle)*1000.0));
805 class variant_comparator :
public formula_callable {
812 }
else if(key ==
"b") {
815 return fallback_->query_value(key);
819 void get_inputs(std::vector<formula_input>* inputs)
const {
820 fallback_->get_inputs(inputs);
825 fallback_(&fallback),
833 return expr_->evaluate(*this).as_bool();
838 class sort_function :
public function_expression {
840 explicit sort_function(
const args_list& args)
841 : function_expression(
"sort", args, 1, 2)
845 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
846 variant list = args()[0]->evaluate(variables,fdb);
847 std::vector<variant> vars;
850 vars.push_back(list[
n]);
853 if(args().
size() == 1) {
856 std::sort(vars.begin(), vars.end(), variant_comparator(args()[1], variables));
863 class reverse_function :
public function_expression {
865 explicit reverse_function(
const args_list& args)
866 : function_expression(
"reverse", args, 1, 1)
870 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
871 const variant& arg = args()[0]->evaluate(variables,fdb);
873 std::string str = args()[0]->evaluate(variables,fdb).as_string();
874 std::reverse(str.begin(), str.end());
877 std::vector<variant> list = args()[0]->evaluate(variables,fdb).
as_list();
878 std::reverse(list.begin(), list.end());
885 class contains_string_function :
public function_expression {
887 explicit contains_string_function(
const args_list& args)
888 : function_expression(
"contains_string", args, 2, 2)
892 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
893 std::string str = args()[0]->evaluate(variables,fdb).as_string();
894 std::string key = args()[1]->evaluate(variables,fdb).as_string();
896 return variant(str.find(key) != std::string::npos);
900 class find_string_function :
public function_expression {
902 explicit find_string_function(
const args_list& args)
903 : function_expression(
"find_string", args, 2, 2)
907 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
908 const std::string str = args()[0]->evaluate(variables,fdb).as_string();
909 const std::string key = args()[1]->evaluate(variables,fdb).as_string();
911 size_t pos = str.find(key);
912 return variant(static_cast<int>(pos));
916 class filter_function :
public function_expression {
918 explicit filter_function(
const args_list& args)
919 : function_expression(
"filter", args, 2, 3)
922 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
923 std::vector<variant> list_vars;
924 std::map<variant,variant> map_vars;
926 const variant items = args()[0]->evaluate(variables,fdb);
928 if(args().
size() == 2) {
930 const variant val = args()[1]->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
933 map_vars[ (*it).get_member(
"key") ] = (*it).get_member(
"value");
935 list_vars.push_back(*it);
939 map_formula_callable self_callable;
940 self_callable.add_ref();
941 const std::string self = args()[1]->evaluate(variables,fdb).as_string();
943 self_callable.add(
self, *it);
944 const variant val = args()[2]->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
947 map_vars[ (*it).get_member(
"key") ] = (*it).get_member(
"value");
949 list_vars.push_back(*it);
959 class find_function :
public function_expression {
961 explicit find_function(
const args_list& args)
962 : function_expression(
"find", args, 2, 3)
966 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
967 const variant items = args()[0]->evaluate(variables,fdb);
969 if(args().
size() == 2) {
971 const variant val = args()[1]->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
977 map_formula_callable self_callable;
978 self_callable.add_ref();
979 const std::string self = args()[1]->evaluate(variables,fdb).as_string();
981 self_callable.add(
self, *it);
982 const variant val = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
993 class map_function :
public function_expression {
995 explicit map_function(
const args_list& args)
996 : function_expression(
"map", args, 2, 3)
999 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1000 std::vector<variant> list_vars;
1001 std::map<variant,variant> map_vars;
1002 const variant items = args()[0]->evaluate(variables,fdb);
1004 if(args().
size() == 2) {
1006 const variant val = args().back()->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
1008 map_vars[ (*it).get_member(
"key") ] =
val;
1010 list_vars.push_back(val);
1013 map_formula_callable self_callable;
1014 self_callable.add_ref();
1015 const std::string self = args()[1]->evaluate(variables,fdb).as_string();
1017 self_callable.add(
self, *it);
1018 const variant val = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
1020 map_vars[ (*it).get_member(
"key") ] =
val;
1022 list_vars.push_back(val);
1031 class take_while_function :
public function_expression {
1033 explicit take_while_function(
const args_list& args)
1034 : function_expression(
"take_while", args, 2, 2)
1037 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1038 const variant& items = args()[0]->evaluate(variables, fdb);
1040 for(; it != items.
end(); ++it) {
1041 const variant matches = args().back()->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
1050 class zip_function :
public function_expression {
1052 explicit zip_function(
const args_list& args)
1053 : function_expression(
"zip", args, 1, -1)
1058 explicit indexer(
size_t i) : i(i) {}
1072 std::vector<variant> get_input(
const formula_callable& variables, formula_debugger* fdb)
const {
1073 if(args().
size() == 1) {
1074 const variant list = args()[0]->evaluate(variables, fdb);
1075 return std::vector<variant>(list.
begin(), list.
end());
1077 std::vector<variant>
input;
1078 input.reserve(args().
size());
1080 input.push_back(
expr->evaluate(variables, fdb));
1085 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1086 const std::vector<variant> input = get_input(variables, fdb);
1087 std::vector<variant>
output;
1090 size_t max_i = std::max_element(input.begin(), input.end(), comparator())->num_elements();
1091 output.reserve(max_i);
1092 for(
size_t i = 0; i < max_i; i++) {
1093 std::vector<variant> elem(input.size());
1094 std::transform(input.begin(), input.end(), elem.begin(), indexer(i));
1095 output.push_back(
variant(&elem));
1101 class reduce_function :
public function_expression {
1103 explicit reduce_function(
const args_list& args)
1104 : function_expression(
"reduce", args, 2, 3)
1107 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1108 const variant items = args()[0]->evaluate(variables,fdb);
1109 const variant initial = args().size() == 2 ?
variant() : args()[1]->evaluate(variables,fdb);
1116 if(res != initial) {
1119 map_formula_callable self_callable;
1120 self_callable.add_ref();
1121 for(; it != items.
end(); ++it) {
1122 self_callable.add(
"a", res);
1123 self_callable.add(
"b", *it);
1124 res = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
1130 class sum_function :
public function_expression {
1132 explicit sum_function(
const args_list& args)
1133 : function_expression(
"sum", args, 1, 2)
1136 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1138 const variant items = args()[0]->evaluate(variables,fdb);
1141 if (items[0].is_list() )
1143 std::vector<variant> tmp;
1145 if(args().
size() >= 2) {
1146 res = args()[1]->evaluate(variables,fdb);
1150 }
else if( items[0].is_map() )
1152 std::map<variant,variant> tmp;
1154 if(args().
size() >= 2) {
1155 res = args()[1]->evaluate(variables,fdb);
1161 if(args().size() >= 2) {
1162 res = args()[1]->evaluate(variables,fdb);
1168 res = res + items[
n];
1175 class head_function :
public function_expression {
1177 explicit head_function(
const args_list& args)
1178 : function_expression(
"head", args, 1, 2)
1181 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1182 const variant items = args()[0]->evaluate(variables,fdb);
1184 if(it == items.
end()) {
1187 if(args().
size() == 1) {
1190 const int n = items.
num_elements(), req = args()[1]->evaluate(variables,fdb).as_int();
1191 const int count = req < 0 ? n - std::min(-req, n) :
std::min(req, n);
1193 std::advance(end, count);
1194 std::vector<variant>
res;
1195 std::copy(it, end, std::back_inserter(res));
1200 class tail_function :
public function_expression {
1202 explicit tail_function(
const args_list& args)
1203 : function_expression(
"tail", args, 1, 2)
1206 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1207 const variant items = args()[0]->evaluate(variables,fdb);
1209 if(it == items.
begin()) {
1212 if(args().
size() == 1) {
1215 const int n = items.
num_elements(), req = args()[1]->evaluate(variables,fdb).as_int();
1216 const int count = req < 0 ? n - std::min(-req, n) :
std::min(req, n);
1217 std::advance(it, -count);
1218 std::vector<variant>
res;
1219 std::copy(it, items.
end(), std::back_inserter(res));
1224 class size_function :
public function_expression {
1226 explicit size_function(
const args_list& args)
1227 : function_expression(
"size", args, 1, 1)
1230 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1231 const variant items = args()[0]->evaluate(variables,fdb);
1236 class null_function :
public function_expression {
1238 explicit null_function(
const args_list& args)
1239 : function_expression(
"null", args, 0, -1)
1242 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1243 if( args().
size() != 0 ) {
1244 for(
size_t i = 0; i < args().size() ; ++
i)
1245 args()[
i]->evaluate(variables,fdb);
1253 class ceil_function :
public function_expression {
1255 explicit ceil_function(
const args_list& args)
1256 : function_expression(
"ceil", args, 1, 1)
1259 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1260 variant decimal = args()[0]->evaluate(variables,fdb);
1264 if( (d>=0) && (d%1000 != 0) ) {
1274 class round_function :
public function_expression {
1276 explicit round_function(
const args_list& args)
1277 : function_expression(
"round", args, 1, 1)
1280 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1281 variant decimal = args()[0]->evaluate(variables,fdb);
1290 }
else if( f <= -500 ) {
1300 class floor_function :
public function_expression {
1302 explicit floor_function(
const args_list& args)
1303 : function_expression(
"floor", args, 1, 1)
1306 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1307 variant decimal = args()[0]->evaluate(variables,fdb);
1311 if( (d<0) && (d%1000 != 0) ) {
1321 class trunc_function :
public function_expression {
1323 explicit trunc_function(
const args_list& args)
1324 : function_expression(
"trunc", args, 1, 1)
1327 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1328 variant decimal = args()[0]->evaluate(variables,fdb);
1330 int d = decimal.
as_int();
1336 class frac_function :
public function_expression {
1338 explicit frac_function(
const args_list& args)
1339 : function_expression(
"frac", args, 1, 1)
1342 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1343 variant decimal = args()[0]->evaluate(variables,fdb);
1352 class sgn_function :
public function_expression {
1354 explicit sgn_function(
const args_list& args)
1355 : function_expression(
"sgn", args, 1, 1)
1358 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1359 variant decimal = args()[0]->evaluate(variables,fdb);
1371 class as_decimal_function :
public function_expression {
1373 explicit as_decimal_function(
const args_list& args)
1374 : function_expression(
"as_decimal", args, 1, 1)
1377 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1378 variant decimal = args()[0]->evaluate(variables,fdb);
1387 class refcount_function :
public function_expression {
1389 explicit refcount_function(
const args_list& args)
1390 : function_expression(
"refcount", args, 1, 1)
1393 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1394 return variant(args()[0]->evaluate(variables,fdb).refcount());
1398 class loc_function :
public function_expression {
1400 explicit loc_function(
const args_list& args)
1401 : function_expression(
"loc", args, 2, 2)
1404 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1406 args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"loc:x")).as_int()-1,
1407 args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"loc:y")).as_int()-1)));
1411 class pair_function :
public function_expression {
1413 explicit pair_function(
const args_list& args)
1414 : function_expression(
"pair", args, 2, 2)
1417 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1418 return variant(
new key_value_pair(
1420 args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"pair_value"))
1425 class distance_between_function :
public function_expression {
1427 explicit distance_between_function(
const args_list& args)
1428 : function_expression(
"distance_between", args, 2, 2)
1432 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1433 const map_location loc1 = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"distance_between:location_A")))->loc();
1434 const map_location loc2 = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"distance_between:location_B")))->loc();
1440 class type_function :
public function_expression {
1442 explicit type_function(
const args_list& args)
1443 : function_expression(
"type", args, 1, 1)
1446 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1447 const variant& v = args()[0]->evaluate(variables, fdb);
1467 void key_value_pair::get_inputs(std::vector<game_logic::formula_input>* inputs)
const {
1475 key_.serialize_to_string(str);
1477 value_.serialize_to_string(str);
1483 formula_(formula), precondition_(precondition), arg_names_(arg_names), star_arg_(-1)
1487 arg_names_[
n].resize(arg_names_[n].
size()-1);
1499 const int begin_time = SDL_GetTicks();
1511 DBG_NG <<
"FAILED function precondition for function '" <<
formula_->str() <<
"' with arguments: ";
1513 DBG_NG <<
" arg " << (n+1) <<
": " <<
args()[
n]->evaluate(variables,fdb).to_debug_string() <<
"\n";
1519 const int taken = SDL_GetTicks() - begin_time;
1520 DBG_NG << indent <<
"returning: " << taken <<
"\n";
1521 indent.resize(indent.size() - 2);
1540 return i->second->generate_function_expression(args);
1548 std::vector<std::string>
res;
1550 res.push_back((*iter).first);
1560 if(functions_table.
empty()) {
1561 #define FUNCTION(name) functions_table.add_function(#name, \
1562 formula_function_ptr(new builtin_formula_function<name##_function>(#name)))
1627 return functions_table;
1633 const std::vector<expression_ptr>& args,
1653 return get_functions_map().get_function_names();
size_t num_elements() const
static lg::log_domain log_engine("engine")
SDL_Color create_color(const unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
void add_function(const std::string &name, formula_function_ptr fcn)
GLuint GLuint GLsizei GLenum type
GLenum GLenum GLenum input
functions_map custom_formulas_
const game_logic::formula_callable * as_callable() const
void float_label(const map_location &loc, const std::string &text, const SDL_Color &color)
Function to float a label above a tile.
static lg::log_domain log_scripting_formula("scripting/formula")
GLuint const GLfloat * val
expression_ptr create_function(const std::string &fn, const std::vector< expression_ptr > &args, const function_symbol_table *symbols)
variant_iterator end() const
GLint GLint GLint GLint GLint GLint y
const std::vector< std::string > items
std::vector< std::string > get_function_names() const
GLboolean GLenum GLenum GLvoid * values
GLuint GLsizei GLsizei * length
GLdouble GLdouble GLdouble b
GLuint GLenum GLenum transform
std::vector< std::string > builtin_function_names()
int floor(tfloat< T, S > lhs)
size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
GLsizei const GLfloat * value
formula_debugger * add_debug_info(formula_debugger *fdb, int arg_number, const std::string &f_name)
GLboolean GLboolean GLboolean GLboolean a
std::string string_cast() const
Iterator class for the variant.
GLuint GLuint GLsizei count
boost::shared_ptr< function_expression > function_expression_ptr
Encapsulates the map of the game.
static const char * output
variant_iterator begin() const
boost::shared_ptr< formula_expression > expression_ptr
const args_list & args() const
static void expr(LexState *ls, expdesc *v)
GLint GLint GLint GLint GLint x
static int sort(lua_State *L)
std::string replace(std::string str, const std::string &src, const std::string &dst)
Replace all instances of src in str with dst.
GLuint const GLchar * name
const formula_callable * fallback_
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
display_chat_manager & get_chat_manager()
std::string to_debug_string(std::vector< const game_logic::formula_callable * > *seen=nullptr, bool verbose=false) const
bool find(E event, F functor)
Tests whether an event handler is available.
expression_ptr create_function(const std::string &fn, const std::vector< expression_ptr > &args) const
variant get_values() const
const std::vector< variant > & as_list() const
Standard logging facilities (interface).
void add_chat_message(const time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
GLsizei const GLcharARB ** string
std::string type_string() const
static game_display * get_singleton()
std::vector< expression_ptr > args_list