The Battle for Wesnoth  1.19.5+dev
callable.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2024
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_fwd.hpp"
19 #include "formula/variant.hpp"
20 #include "log.hpp"
21 
22 #include <memory>
23 #include <set>
24 
25 namespace wfl
26 {
27 
28 // Interface for objects that can have formulae run on them
30 {
31 public:
32  explicit formula_callable(bool has_self = true) : type_(FORMULA_C), has_self_(has_self) {}
33 
34  virtual ~formula_callable() {
35  for(auto& d : dtor_notify) {
36  if(d) {
37  d->notify_dead();
38  }
39  }
40  }
41 
43  return formula_callable_ptr(this, [](const formula_callable*){});
44  }
45 
47  return const_formula_callable_ptr(this, [](const formula_callable*){});
48  }
49 
50  variant query_value(const std::string& key) const
51  {
52  if(has_self_ && key == "self") {
53  return variant(fake_ptr());
54  }
55  return get_value(key);
56  }
57 
58  void mutate_value(const std::string& key, const variant& value)
59  {
60  set_value(key, value);
61  }
62 
64  {
66  get_inputs(res);
67  return res;
68  }
69 
70  virtual void get_inputs(formula_input_vector& /*inputs*/) const {}
71 
72  bool equals(const formula_callable& other) const
73  {
74  return do_compare(&other) == 0;
75  }
76 
77  bool less(const formula_callable& other) const
78  {
79  return do_compare(&other) < 0;
80  }
81 
82  bool has_key(const std::string& key) const
83  {
84  return !query_value(key).is_null();
85  }
86 
87  // Note: this function should NOT overwrite str, but append text to it!
88  // TODO: return str instead of taking str.
89  void serialize(std::string& str) const
90  {
92  }
93 
95  dtor_notify.insert(d);
96  }
97 
99  dtor_notify.erase(d);
100  }
101 
102 protected:
103  template<typename T, typename K>
104  static variant convert_map(const std::map<T, K>& input_map)
105  {
106  std::map<variant,variant> tmp;
107  for(const auto& p : input_map) {
108  tmp[variant(p.first)] = variant(p.second);
109  }
110 
111  return variant(tmp);
112  }
113 
114  template<typename T>
115  static variant convert_set(const std::set<T>& input_set)
116  {
117  std::map<variant,variant> tmp;
118  for(const auto& elem : input_set) {
119  tmp[variant(elem)] = variant(1);
120  }
121 
122  return variant(tmp);
123  }
124 
125  template<typename T>
126  static variant convert_vector(const std::vector<T>& input_vector)
127  {
128  std::vector<variant> tmp;
129  for(const auto& elem : input_vector) {
130  tmp.emplace_back(elem);
131  }
132 
133  return variant(tmp);
134  }
135 
136  static inline void add_input(formula_input_vector& inputs, const std::string& key, formula_access access_type = formula_access::read_only)
137  {
138  inputs.emplace_back(key, access_type);
139  }
140 
141  virtual void set_value(const std::string& key, const variant& /*value*/)
142  {
143  PLAIN_LOG << "ERROR: cannot set key '" << key << "' on object";
144  }
145 
146  virtual int do_compare(const formula_callable* callable) const
147  {
148  if(type_ < callable->type_) {
149  return -1;
150  }
151 
152  if(type_ > callable->type_) {
153  return 1;
154  }
155 
156  return this < callable ? -1 : (this == callable ? 0 : 1);
157  }
158 
159  // Note: this function should NOT overwrite str, but append text to it!
160  // TODO: return string not take string
161  virtual void serialize_to_string(std::string& /*str*/) const
162  {
163  throw type_error("Tried to serialize type which cannot be serialized");
164  }
165 
166  // Priority for objects that are derived from this class, used in do_compare
167  // when comparing objects of different types.
168  // For example: formula_callable < terrain_callable < unit_type_callable ...
169  enum TYPE {
172  };
173 
175 
176  mutable std::set<callable_die_subscriber*> dtor_notify;
177 
178 private:
179  virtual variant get_value(const std::string& key) const = 0;
180  bool has_self_;
181 };
182 
184 {
185 public:
186  virtual variant execute_self(variant ctxt) = 0;
187 };
188 
190 {
191 public:
193  : formula_callable(false), main_(main), backup_(backup)
194  {}
195 
196 private:
197  variant get_value(const std::string& key) const override
198  {
199  variant var = main_.query_value(key);
200  if(var.is_null()) {
201  return backup_.query_value(key);
202  }
203 
204  return var;
205  }
206 
207  void get_inputs(formula_input_vector& inputs) const override
208  {
211  }
212 
215 };
216 
218 {
219 public:
221  : formula_callable(false), var_(var), backup_(backup)
222  {}
223 
224 private:
225  variant get_value(const std::string& key) const override
226  {
227  variant var = var_.get_member(key);
228  if(var.is_null()) {
229  return backup_.query_value(key);
230  }
231 
232  return var;
233  }
234 
235  void get_inputs(formula_input_vector& inputs) const override
236  {
238  }
239 
242 };
243 
245 {
246 public:
248  : formula_callable(false)
249  , values_()
250  , fallback_(fallback)
251  {}
252 
253  map_formula_callable& add(const std::string& key, const variant& value)
254  {
255  values_[key] = value;
256  return *this;
257  }
258 
259  map_formula_callable& add(const std::string& key, variant&& value)
260  {
261  values_[key] = std::move(value);
262  return *this;
263  }
264 
266  {
267  fallback_ = fallback;
268  }
269 
270  bool empty() const { return values_.empty(); }
271 
272  void clear() { values_.clear(); }
273 
274  typedef std::map<std::string,variant>::const_iterator const_iterator;
275 
276  const_iterator begin() const { return values_.begin(); }
277  const_iterator end() const { return values_.end(); }
278 
279 private:
280  void set_value(const std::string& key, const variant& value) override
281  {
282  values_[key] = value;
283  }
284 
285  variant get_value(const std::string& key) const override
286  {
287  auto it = values_.find(key);
288  if(it != values_.end()) {
289  return it->second;
290  } else if(fallback_) {
291  return fallback_->query_value(key);
292  }
293 
294  return variant();
295  }
296 
297  void get_inputs(formula_input_vector& inputs) const override
298  {
299  if(fallback_) {
300  fallback_->get_inputs(inputs);
301  }
302 
303  for(const auto& i : values_) {
305  }
306  }
307 
308  std::map<std::string, variant> values_;
310 };
311 
312 using map_formula_callable_ptr = std::shared_ptr<map_formula_callable>;
313 using const_map_formula_callable_ptr = std::shared_ptr<const map_formula_callable>;
314 
315 } // namespace wfl
virtual variant execute_self(variant ctxt)=0
const formula_callable & main_
Definition: callable.hpp:213
const formula_callable & backup_
Definition: callable.hpp:214
formula_callable_with_backup(const formula_callable &main, const formula_callable &backup)
Definition: callable.hpp:192
void get_inputs(formula_input_vector &inputs) const override
Definition: callable.hpp:207
variant get_value(const std::string &key) const override
Definition: callable.hpp:197
const_formula_callable_ptr fake_ptr() const
Definition: callable.hpp:46
formula_callable_ptr fake_ptr()
Definition: callable.hpp:42
variant query_value(const std::string &key) const
Definition: callable.hpp:50
void mutate_value(const std::string &key, const variant &value)
Definition: callable.hpp:58
void subscribe_dtor(callable_die_subscriber *d) const
Definition: callable.hpp:94
formula_input_vector inputs() const
Definition: callable.hpp:63
static variant convert_map(const std::map< T, K > &input_map)
Definition: callable.hpp:104
std::set< callable_die_subscriber * > dtor_notify
Definition: callable.hpp:176
static void add_input(formula_input_vector &inputs, const std::string &key, formula_access access_type=formula_access::read_only)
Definition: callable.hpp:136
void unsubscribe_dtor(callable_die_subscriber *d) const
Definition: callable.hpp:98
virtual int do_compare(const formula_callable *callable) const
Definition: callable.hpp:146
virtual void serialize_to_string(std::string &) const
Definition: callable.hpp:161
virtual void set_value(const std::string &key, const variant &)
Definition: callable.hpp:141
virtual ~formula_callable()
Definition: callable.hpp:34
bool less(const formula_callable &other) const
Definition: callable.hpp:77
void serialize(std::string &str) const
Definition: callable.hpp:89
virtual void get_inputs(formula_input_vector &) const
Definition: callable.hpp:70
static variant convert_vector(const std::vector< T > &input_vector)
Definition: callable.hpp:126
static variant convert_set(const std::set< T > &input_set)
Definition: callable.hpp:115
formula_callable(bool has_self=true)
Definition: callable.hpp:32
bool equals(const formula_callable &other) const
Definition: callable.hpp:72
virtual variant get_value(const std::string &key) const =0
bool has_key(const std::string &key) const
Definition: callable.hpp:82
formula_variant_callable_with_backup(const variant &var, const formula_callable &backup)
Definition: callable.hpp:220
variant get_value(const std::string &key) const override
Definition: callable.hpp:225
const formula_callable & backup_
Definition: callable.hpp:241
void get_inputs(formula_input_vector &inputs) const override
Definition: callable.hpp:235
map_formula_callable & add(const std::string &key, const variant &value)
Definition: callable.hpp:253
void set_value(const std::string &key, const variant &value) override
Definition: callable.hpp:280
variant get_value(const std::string &key) const override
Definition: callable.hpp:285
const_iterator end() const
Definition: callable.hpp:277
void get_inputs(formula_input_vector &inputs) const override
Definition: callable.hpp:297
const_formula_callable_ptr fallback_
Definition: callable.hpp:309
map_formula_callable & add(const std::string &key, variant &&value)
Definition: callable.hpp:259
std::map< std::string, variant > values_
Definition: callable.hpp:308
void set_fallback(const_formula_callable_ptr fallback)
Definition: callable.hpp:265
std::map< std::string, variant >::const_iterator const_iterator
Definition: callable.hpp:274
const_iterator begin() const
Definition: callable.hpp:276
map_formula_callable(const_formula_callable_ptr fallback=nullptr)
Definition: callable.hpp:247
variant get_member(const std::string &name) const
Definition: variant.cpp:276
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:62
std::size_t i
Definition: function.cpp:1028
Standard logging facilities (interface).
#define PLAIN_LOG
Definition: log.hpp:299
Definition: contexts.hpp:43
std::vector< formula_input > formula_input_vector
std::shared_ptr< map_formula_callable > map_formula_callable_ptr
Definition: callable.hpp:312
std::shared_ptr< const formula_callable > const_formula_callable_ptr
std::shared_ptr< formula_callable > formula_callable_ptr
formula_access
std::shared_ptr< const map_formula_callable > const_map_formula_callable_ptr
Definition: callable.hpp:313
int main(int, char **)
Definition: sdl2.cpp:25
mock_party p
#define d