The Battle for Wesnoth  1.19.23+dev
function.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2025
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include "formula/callable.hpp"
19 #include "formula/formula.hpp"
20 
21 #include <set>
22 #include <string>
23 
24 namespace wfl
25 {
26 /** Helper macro to declare an associated class for a WFL function. */
27 #define DEFINE_WFL_FUNCTION(name, min_args, max_args) \
28  class name##_function : public function_expression \
29  { \
30  public: \
31  explicit name##_function(const args_list& args) \
32  : function_expression(#name, args, min_args, max_args) \
33  { \
34  } \
35  \
36  private: \
37  variant execute(const formula_callable& variables, formula_debugger* fdb) const; \
38  }; \
39  \
40  variant name##_function::execute( \
41  [[maybe_unused]] const formula_callable& variables, [[maybe_unused]] formula_debugger* fdb) const
42 
43 /**
44  * Declares a function `name` in the local function table `functions_table`.
45  * The function must be defined by a `name_function` class which is accessible in the current scope.
46  */
47 #define DECLARE_WFL_FUNCTION(name) \
48  functions_table.add_function(#name, std::make_shared<builtin_formula_function<name##_function>>(#name))
49 
50 /**
51  * Provides debugging information for error messages.
52  */
54 {
55  explicit call_stack_manager(const std::string& str);
59 
60  static std::string get();
61 };
62 
64 {
65 public:
66  explicit formula_expression(const std::string& name = "")
67  : name_(name)
68  {
69  }
70 
72  {
73  }
74 
75  variant evaluate(const formula_callable& variables, formula_debugger* fdb = nullptr) const
76  {
77  call_stack_manager manager(name_);
78 
79  if(fdb != nullptr) {
80  return evaluate_arg_callback(*fdb, *this, variables);
81  } else {
82  return execute(variables, fdb);
83  }
84  }
85 
86  std::string get_name() const
87  {
88  return name_;
89  }
90 
91  virtual std::string str() const = 0;
92 
93 private:
94  virtual variant execute(const formula_callable& variables, formula_debugger* fdb = nullptr) const = 0;
95 
96  const std::string name_;
97  friend class formula_debugger;
98 };
99 
100 typedef std::shared_ptr<formula_expression> expression_ptr;
101 
103 {
104 public:
105  typedef std::vector<expression_ptr> args_list;
106 
107  explicit function_expression(const std::string& name, const args_list& args, int min_args = -1, int max_args = -1)
108  : formula_expression(name)
109  , args_(args)
110  {
111  if(min_args >= 0 && args_.size() < static_cast<std::size_t>(min_args)) {
112  throw formula_error("Too few arguments", "", "", 0);
113  }
114 
115  if(max_args >= 0 && args_.size() > static_cast<std::size_t>(max_args)) {
116  throw formula_error("Too many arguments", "", "", 0);
117  }
118  }
119 
120  virtual std::string str() const;
121 
122 protected:
123  const args_list& args() const
124  {
125  return args_;
126  }
127 
128 private:
130 };
131 
133 {
134 public:
135  explicit key_value_pair(const variant& key, const variant& value)
136  : key_(key)
137  , value_(value)
138  {
139  }
140 
141  /** Inherited from formula_callable */
142  std::string serialize_to_string() const override;
143 
144 private:
147 
148  variant get_value(const std::string& key) const override;
149 
150  void get_inputs(formula_input_vector& inputs) const override;
151 };
152 
154 {
155 public:
156  explicit formula_function_expression(const std::string& name,
157  const args_list& args,
159  const_formula_ptr precondition,
160  const std::vector<std::string>& arg_names);
161 
162 private:
163  variant execute(const formula_callable& variables, formula_debugger* fdb) const;
164 
167 
168  std::vector<std::string> arg_names_;
169 
171 };
172 
173 typedef std::shared_ptr<function_expression> function_expression_ptr;
174 
176 {
177 public:
178  formula_function(const std::string name)
179  : name_(name)
180  {
181  }
182 
183  virtual function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const = 0;
184 
186  {
187  }
188 
189 protected:
190  std::string name_;
191 };
192 
194 {
195 public:
196  user_formula_function(const std::string& name,
198  const_formula_ptr precondition,
199  const std::vector<std::string>& args)
200  : formula_function(name)
201  , formula_(formula)
202  , precondition_(precondition)
203  , args_(args)
204  {
205  }
206 
207  function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const;
208 
209 private:
212  std::vector<std::string> args_;
213 };
214 
215 template<typename T>
217 {
218 public:
219  builtin_formula_function(const std::string& name)
220  : formula_function(name)
221  {
222  }
223 
224  function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const
225  {
226  return std::make_shared<T>(args);
227  }
228 };
229 
230 typedef std::shared_ptr<formula_function> formula_function_ptr;
231 typedef std::map<std::string, formula_function_ptr> functions_map;
232 
234 {
235 public:
236  explicit function_symbol_table(const std::shared_ptr<function_symbol_table>& parent = nullptr);
237 
238  void add_function(const std::string& name, formula_function_ptr&& fcn);
239 
240  expression_ptr create_function(const std::string& fn, const std::vector<expression_ptr>& args) const;
241 
242  std::set<std::string> get_function_names() const;
243 
244  bool empty() const
245  {
246  return custom_formulas_.empty() && (parent == nullptr || parent->empty());
247  }
248 
249  static std::shared_ptr<function_symbol_table> get_builtins();
250 
251 private:
252  std::shared_ptr<function_symbol_table> parent;
254 
257  {
258  }
259 };
260 
262 {
263 public:
264  action_function_symbol_table(const std::shared_ptr<function_symbol_table>& parent = nullptr);
265 };
266 
268 {
269 public:
271  : arg_()
272  {
273  }
274 
276  : formula_expression(arg ? arg->get_name() : "")
277  , arg_(arg)
278  {
279  }
280 
282  {
283  }
284 
285  virtual std::string str() const
286  {
287  if(arg_) {
288  return arg_->str();
289  } else {
290  return "";
291  }
292  }
293 
294 private:
295  virtual variant execute(const formula_callable& variables, formula_debugger* fdb = nullptr) const
296  {
297  if(arg_) {
298  return arg_->evaluate(variables, fdb);
299  } else {
300  return variant();
301  }
302  }
303 
305 };
306 } // end namespace wfl
action_function_symbol_table(const std::shared_ptr< function_symbol_table > &parent=nullptr)
Definition: function.cpp:1738
function_expression_ptr generate_function_expression(const std::vector< expression_ptr > &args) const
Definition: function.hpp:224
builtin_formula_function(const std::string &name)
Definition: function.hpp:219
formula_input_vector inputs() const
Definition: callable.hpp:63
std::string get_name() const
Definition: function.hpp:86
const std::string name_
Definition: function.hpp:96
virtual std::string str() const =0
virtual variant execute(const formula_callable &variables, formula_debugger *fdb=nullptr) const =0
variant evaluate(const formula_callable &variables, formula_debugger *fdb=nullptr) const
Definition: function.hpp:75
virtual ~formula_expression()
Definition: function.hpp:71
formula_expression(const std::string &name="")
Definition: function.hpp:66
formula_function_expression(const std::string &name, const args_list &args, const_formula_ptr formula, const_formula_ptr precondition, const std::vector< std::string > &arg_names)
Definition: function.cpp:1543
std::vector< std::string > arg_names_
Definition: function.hpp:168
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1563
const_formula_ptr precondition_
Definition: function.hpp:166
formula_function(const std::string name)
Definition: function.hpp:178
virtual ~formula_function()
Definition: function.hpp:185
virtual function_expression_ptr generate_function_expression(const std::vector< expression_ptr > &args) const =0
const args_list & args() const
Definition: function.hpp:123
virtual std::string str() const
Definition: function.cpp:75
std::vector< expression_ptr > args_list
Definition: function.hpp:105
function_expression(const std::string &name, const args_list &args, int min_args=-1, int max_args=-1)
Definition: function.hpp:107
static std::shared_ptr< function_symbol_table > get_builtins()
Definition: function.cpp:1650
expression_ptr create_function(const std::string &fn, const std::vector< expression_ptr > &args) const
Definition: function.cpp:1618
function_symbol_table(const std::shared_ptr< function_symbol_table > &parent=nullptr)
Definition: function.cpp:1608
void add_function(const std::string &name, formula_function_ptr &&fcn)
Definition: function.cpp:1613
std::set< std::string > get_function_names() const
Definition: function.cpp:1636
std::shared_ptr< function_symbol_table > parent
Definition: function.hpp:252
function_symbol_table(builtins_tag_t)
Definition: function.hpp:256
functions_map custom_formulas_
Definition: function.hpp:253
key_value_pair(const variant &key, const variant &value)
Definition: function.hpp:135
std::string serialize_to_string() const override
Inherited from formula_callable.
Definition: function.cpp:1532
variant get_value(const std::string &key) const override
Definition: function.cpp:1515
void get_inputs(formula_input_vector &inputs) const override
Definition: function.cpp:1526
function_expression_ptr generate_function_expression(const std::vector< expression_ptr > &args) const
Definition: function.cpp:1602
const_formula_ptr precondition_
Definition: function.hpp:211
user_formula_function(const std::string &name, const_formula_ptr formula, const_formula_ptr precondition, const std::vector< std::string > &args)
Definition: function.hpp:196
const_formula_ptr formula_
Definition: function.hpp:210
std::vector< std::string > args_
Definition: function.hpp:212
virtual variant execute(const formula_callable &variables, formula_debugger *fdb=nullptr) const
Definition: function.hpp:295
virtual std::string str() const
Definition: function.hpp:285
virtual ~wrapper_formula()
Definition: function.hpp:281
wrapper_formula(expression_ptr arg)
Definition: function.hpp:275
expression_ptr arg_
Definition: function.hpp:304
Definition: callable.hpp:26
std::vector< formula_input > formula_input_vector
std::shared_ptr< const formula > const_formula_ptr
Definition: formula_fwd.hpp:24
std::shared_ptr< formula_expression > expression_ptr
Definition: formula.hpp:29
std::map< std::string, formula_function_ptr > functions_map
Definition: function.hpp:231
variant evaluate_arg_callback(formula_debugger &fdb, const formula_expression &expression, const formula_callable &variables)
std::shared_ptr< function_expression > function_expression_ptr
Definition: function.hpp:173
std::shared_ptr< formula_function > formula_function_ptr
Definition: function.hpp:230
Provides debugging information for error messages.
Definition: function.hpp:54
call_stack_manager(const std::string &str)
Definition: function.cpp:53
static std::string get()
Definition: function.cpp:63
call_stack_manager & operator=(const call_stack_manager &)=delete
call_stack_manager(const call_stack_manager &)=delete