The Battle for Wesnoth  1.17.0-dev
function.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
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(const formula_callable& variables, formula_debugger* fdb) const
41 
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);
56  call_stack_manager(const call_stack_manager&) = delete;
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  {
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:
129  args_list args_;
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  void serialize_to_string(std::string& str) const override;
142 
143 private:
146 
147  variant get_value(const std::string& key) const override;
148 
149  void get_inputs(formula_input_vector& inputs) const override;
150 };
151 
153 {
154 public:
155  explicit formula_function_expression(const std::string& name,
156  const args_list& args,
158  const_formula_ptr precondition,
159  const std::vector<std::string>& arg_names);
160 
161 private:
162  variant execute(const formula_callable& variables, formula_debugger* fdb) const;
163 
166 
167  std::vector<std::string> arg_names_;
168 
170 };
171 
172 typedef std::shared_ptr<function_expression> function_expression_ptr;
173 
175 {
176 public:
177  formula_function(const std::string name)
178  : name_(name)
179  {
180  }
181 
182  virtual function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const = 0;
183 
185  {
186  }
187 
188 protected:
189  std::string name_;
190 };
191 
193 {
194 public:
195  user_formula_function(const std::string& name,
197  const_formula_ptr precondition,
198  const std::vector<std::string>& args)
199  : formula_function(name)
200  , formula_(formula)
201  , precondition_(precondition)
202  , args_(args)
203  {
204  }
205 
206  function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const;
207 
208 private:
211  std::vector<std::string> args_;
212 };
213 
214 template<typename T>
216 {
217 public:
218  builtin_formula_function(const std::string& name)
219  : formula_function(name)
220  {
221  }
222 
223  function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const
224  {
225  return std::make_shared<T>(args);
226  }
227 };
228 
229 typedef std::shared_ptr<formula_function> formula_function_ptr;
230 typedef std::map<std::string, formula_function_ptr> functions_map;
231 
233 {
234 public:
235  explicit function_symbol_table(std::shared_ptr<function_symbol_table> parent = nullptr);
236 
237  void add_function(const std::string& name, formula_function_ptr&& fcn);
238 
239  expression_ptr create_function(const std::string& fn, const std::vector<expression_ptr>& args) const;
240 
241  std::set<std::string> get_function_names() const;
242 
243  bool empty() const
244  {
245  return custom_formulas_.empty() && (parent == nullptr || parent->empty());
246  }
247 
248  static std::shared_ptr<function_symbol_table> get_builtins();
249 
250 private:
251  std::shared_ptr<function_symbol_table> parent;
252  functions_map custom_formulas_;
253 
254  enum builtins_tag_t { builtins_tag };
256  {
257  }
258 };
259 
261 {
262 public:
263  action_function_symbol_table(std::shared_ptr<function_symbol_table> parent = nullptr);
264 };
265 
267 {
268 public:
270  : arg_()
271  {
272  }
273 
274  wrapper_formula(expression_ptr arg)
275  : formula_expression(arg ? arg->get_name() : "")
276  , arg_(arg)
277  {
278  }
279 
281  {
282  }
283 
284  virtual std::string str() const
285  {
286  if(arg_) {
287  return arg_->str();
288  } else {
289  return "";
290  }
291  }
292 
293 private:
294  virtual variant execute(const formula_callable& variables, formula_debugger* fdb = nullptr) const
295  {
296  if(arg_) {
297  return arg_->evaluate(variables, fdb);
298  } else {
299  return variant();
300  }
301  }
302 
303  expression_ptr arg_;
304 };
305 } // end namespace wfl
const_formula_ptr formula_
Definition: function.hpp:209
virtual ~wrapper_formula()
Definition: function.hpp:280
wrapper_formula(expression_ptr arg)
Definition: function.hpp:274
virtual ~formula_expression()
Definition: function.hpp:71
key_value_pair(const variant &key, const variant &value)
Definition: function.hpp:135
std::vector< expression_ptr > args_list
Definition: function.hpp:105
virtual std::string str() const
Definition: function.hpp:284
std::vector< formula_input > formula_input_vector
Class that manages AIs for all sides and manages AI redeployment.
Definition: manager.hpp:113
std::shared_ptr< formula_function > formula_function_ptr
Definition: function.hpp:229
builtin_formula_function(const std::string &name)
Definition: function.hpp:218
std::shared_ptr< formula_expression > expression_ptr
Definition: formula.hpp:29
function_expression(const std::string &name, const args_list &args, int min_args=-1, int max_args=-1)
Definition: function.hpp:107
user_formula_function(const std::string &name, const_formula_ptr formula, const_formula_ptr precondition, const std::vector< std::string > &args)
Definition: function.hpp:195
call_stack_manager(const std::string &str)
Definition: function.cpp:49
Provides debugging information for error messages.
Definition: function.hpp:53
variant evaluate(const formula_callable &variables, formula_debugger *fdb=nullptr) const
Definition: function.hpp:75
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:172
function_expression_ptr generate_function_expression(const std::vector< expression_ptr > &args) const
Definition: function.hpp:223
formula_expression(const std::string &name="")
Definition: function.hpp:66
virtual variant execute(const formula_callable &variables, formula_debugger *fdb=nullptr) const
Definition: function.hpp:294
const_formula_ptr precondition_
Definition: function.hpp:210
std::shared_ptr< function_symbol_table > parent
Definition: function.hpp:251
call_stack_manager & operator=(const call_stack_manager &)=delete
const_formula_ptr precondition_
Definition: function.hpp:165
expression_ptr arg_
Definition: function.hpp:303
std::shared_ptr< const formula > const_formula_ptr
Definition: formula_fwd.hpp:24
std::vector< std::string > arg_names_
Definition: function.hpp:167
const std::string name_
Definition: function.hpp:96
function_symbol_table(builtins_tag_t)
Definition: function.hpp:255
const args_list & args() const
Definition: function.hpp:123
Definition: contexts.hpp:44
formula_function(const std::string name)
Definition: function.hpp:177
virtual ~formula_function()
Definition: function.hpp:184
std::map< std::string, formula_function_ptr > functions_map
Definition: function.hpp:230
functions_map custom_formulas_
Definition: function.hpp:252
std::string get_name() const
Definition: function.hpp:86
std::vector< std::string > args_
Definition: function.hpp:211