The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
callable.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2017 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "formula/callable_fwd.hpp"
18 #include "formula/variant.hpp"
19 
20 #include <iostream>
21 #include <memory>
22 #include <set>
23 
24 namespace wfl
25 {
26 
27 // Interface for objects that can have formulae run on them
29 {
30 public:
31  explicit formula_callable(bool has_self = true) : type_(FORMULA_C), has_self_(has_self) {}
32 
33  virtual ~formula_callable() {
34  for(auto& d : dtor_notify) {
35  if(d) {
36  d->notify_dead();
37  }
38  }
39  }
40 
42  return formula_callable_ptr(this, [](const formula_callable*){});
43  }
44 
46  return const_formula_callable_ptr(this, [](const formula_callable*){});
47  }
48 
49  variant query_value(const std::string& key) const
50  {
51  if(has_self_ && key == "self") {
52  return variant(fake_ptr());
53  }
54  return get_value(key);
55  }
56 
57  void mutate_value(const std::string& key, const variant& value)
58  {
59  set_value(key, value);
60  }
61 
63  {
65  get_inputs(res);
66  return res;
67  }
68 
69  virtual void get_inputs(formula_input_vector& /*inputs*/) const {}
70 
71  bool equals(const formula_callable& other) const
72  {
73  return do_compare(&other) == 0;
74  }
75 
76  bool less(const formula_callable& other) const
77  {
78  return do_compare(&other) < 0;
79  }
80 
81  bool has_key(const std::string& key) const
82  {
83  return !query_value(key).is_null();
84  }
85 
86  // Note: this function should NOT overwrite str, but append text to it!
87  // TODO: return str instead of taking str.
88  void serialize(std::string& str) const
89  {
91  }
92 
94  dtor_notify.insert(d);
95  }
96 
98  dtor_notify.erase(d);
99  }
100 
101 protected:
102  template<typename T, typename K>
103  static variant convert_map(const std::map<T, K>& input_map)
104  {
105  std::map<variant,variant> tmp;
106  for(const auto& p : input_map) {
107  tmp[variant(p.first)] = variant(p.second);
108  }
109 
110  return variant(tmp);
111  }
112 
113  template<typename T>
114  static variant convert_set(const std::set<T>& input_set)
115  {
116  std::map<variant,variant> tmp;
117  for(const auto& elem : input_set) {
118  tmp[variant(elem)] = variant(1);
119  }
120 
121  return variant(tmp);
122  }
123 
124  template<typename T>
125  static variant convert_vector(const std::vector<T>& input_vector)
126  {
127  std::vector<variant> tmp;
128  for(const auto& elem : input_vector) {
129  tmp.emplace_back(elem);
130  }
131 
132  return variant(tmp);
133  }
134 
136  {
137  inputs.emplace_back(key, access_type);
138  }
139 
140  virtual void set_value(const std::string& key, const variant& /*value*/)
141  {
142  std::cerr << "ERROR: cannot set key '" << key << "' on object" << std::endl;
143  }
144 
145  virtual int do_compare(const formula_callable* callable) const
146  {
147  if(type_ < callable->type_) {
148  return -1;
149  }
150 
151  if(type_ > callable->type_) {
152  return 1;
153  }
154 
155  return this < callable ? -1 : (this == callable ? 0 : 1);
156  }
157 
158  // Note: this function should NOT overwrite str, but append text to it!
159  // TODO: return string not take string
160  virtual void serialize_to_string(std::string& /*str*/) const
161  {
162  throw type_error("Tried to serialize type which cannot be serialized");
163  }
164 
165  // Priority for objects that are derived from this class, used in do_compare
166  // when comparing objects of different types.
167  // For example: formula_callable < terrain_callable < unit_type_callable ...
168  enum TYPE {
171  };
172 
174 
175  mutable std::set<callable_die_subscriber*> dtor_notify;
176 
177 private:
178  virtual variant get_value(const std::string& key) const = 0;
179  bool has_self_;
180 };
181 
183 {
184 public:
185  virtual variant execute_self(variant ctxt) = 0;
186 };
187 
189 {
190 public:
192  : formula_callable(false), main_(main), backup_(backup)
193  {}
194 
195 private:
196  variant get_value(const std::string& key) const override
197  {
198  variant var = main_.query_value(key);
199  if(var.is_null()) {
200  return backup_.query_value(key);
201  }
202 
203  return var;
204  }
205 
206  void get_inputs(formula_input_vector& inputs) const override
207  {
208  main_.get_inputs(inputs);
209  backup_.get_inputs(inputs);
210  }
211 
214 };
215 
217 {
218 public:
220  : formula_callable(false), var_(var), backup_(backup)
221  {}
222 
223 private:
224  variant get_value(const std::string& key) const override
225  {
226  variant var = var_.get_member(key);
227  if(var.is_null()) {
228  return backup_.query_value(key);
229  }
230 
231  return var;
232  }
233 
234  void get_inputs(formula_input_vector& inputs) const override
235  {
236  backup_.get_inputs(inputs);
237  }
238 
241 };
242 
244 {
245 public:
247  : formula_callable(false)
248  , values_()
249  , fallback_(fallback)
250  {}
251 
252  map_formula_callable& add(const std::string& key, const variant& value)
253  {
254  values_[key] = value;
255  return *this;
256  }
257 
259  {
260  fallback_ = fallback;
261  }
262 
263  bool empty() const { return values_.empty(); }
264 
265  void clear() { values_.clear(); }
266 
267  typedef std::map<std::string,variant>::const_iterator const_iterator;
268 
269  const_iterator begin() const { return values_.begin(); }
270  const_iterator end() const { return values_.end(); }
271 
272 private:
273  void set_value(const std::string& key, const variant& value) override
274  {
275  values_[key] = value;
276  }
277 
278  variant get_value(const std::string& key) const override
279  {
280  auto it = values_.find(key);
281  if(it != values_.end()) {
282  return it->second;
283  } else if(fallback_) {
284  return fallback_->query_value(key);
285  }
286 
287  return variant();
288  }
289 
290  void get_inputs(formula_input_vector& inputs) const override
291  {
292  if(fallback_) {
293  fallback_->get_inputs(inputs);
294  }
295 
296  for(const auto& i : values_) {
297  add_input(inputs, i.first, FORMULA_READ_WRITE);
298  }
299  }
300 
301  std::map<std::string, variant> values_;
303 };
304 
305 using map_formula_callable_ptr = std::shared_ptr<map_formula_callable>;
306 using const_map_formula_callable_ptr = std::shared_ptr<const map_formula_callable>;
307 
308 } // namespace wfl
formula_callable_with_backup(const formula_callable &main, const formula_callable &backup)
Definition: callable.hpp:191
void set_value(const std::string &key, const variant &value) override
Definition: callable.hpp:273
std::vector< char_t > string
virtual void set_value(const std::string &key, const variant &)
Definition: callable.hpp:140
virtual void serialize_to_string(std::string &) const
Definition: callable.hpp:160
formula_callable(bool has_self=true)
Definition: callable.hpp:31
void get_inputs(formula_input_vector &inputs) const override
Definition: callable.hpp:206
void set_fallback(const_formula_callable_ptr fallback)
Definition: callable.hpp:258
void serialize(std::string &str) const
Definition: callable.hpp:88
std::vector< formula_input > formula_input_vector
formula_input_vector inputs() const
Definition: callable.hpp:62
static variant convert_set(const std::set< T > &input_set)
Definition: callable.hpp:114
std::set< callable_die_subscriber * > dtor_notify
Definition: callable.hpp:175
void unsubscribe_dtor(callable_die_subscriber *d) const
Definition: callable.hpp:97
#define d
variant get_member(const std::string &name) const
Definition: variant.cpp:285
const_iterator end() const
Definition: callable.hpp:270
std::map< std::string, variant > values_
Definition: callable.hpp:301
map_formula_callable & add(const std::string &key, const variant &value)
Definition: callable.hpp:252
const formula_callable & backup_
Definition: callable.hpp:240
const formula_callable & main_
Definition: callable.hpp:212
virtual void get_inputs(formula_input_vector &) const
Definition: callable.hpp:69
bool has_key(const std::string &key) const
Definition: callable.hpp:81
variant get_value(const std::string &key) const override
Definition: callable.hpp:278
variant get_value(const std::string &key) const override
Definition: callable.hpp:224
bool equals(const formula_callable &other) const
Definition: callable.hpp:71
virtual int do_compare(const formula_callable *callable) const
Definition: callable.hpp:145
const formula_callable & backup_
Definition: callable.hpp:213
std::shared_ptr< formula_callable > formula_callable_ptr
const_formula_callable_ptr fake_ptr() const
Definition: callable.hpp:45
std::shared_ptr< const map_formula_callable > const_map_formula_callable_ptr
Definition: callable.hpp:306
void get_inputs(formula_input_vector &inputs) const override
Definition: callable.hpp:290
formula_callable_ptr fake_ptr()
Definition: callable.hpp:41
virtual ~formula_callable()
Definition: callable.hpp:33
FORMULA_ACCESS_TYPE
mock_party p
virtual variant get_value(const std::string &key) const =0
int main()
bool less(const formula_callable &other) const
Definition: callable.hpp:76
size_t i
Definition: function.cpp:933
std::shared_ptr< const formula_callable > const_formula_callable_ptr
map_formula_callable(const_formula_callable_ptr fallback=nullptr)
Definition: callable.hpp:246
void get_inputs(formula_input_vector &inputs) const override
Definition: callable.hpp:234
void subscribe_dtor(callable_die_subscriber *d) const
Definition: callable.hpp:93
static variant convert_map(const std::map< T, K > &input_map)
Definition: callable.hpp:103
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:58
void mutate_value(const std::string &key, const variant &value)
Definition: callable.hpp:57
std::map< std::string, variant >::const_iterator const_iterator
Definition: callable.hpp:267
variant query_value(const std::string &key) const
Definition: callable.hpp:49
Definition: contexts.hpp:42
const_formula_callable_ptr fallback_
Definition: callable.hpp:302
virtual variant execute_self(variant ctxt)=0
variant get_value(const std::string &key) const override
Definition: callable.hpp:196
static variant convert_vector(const std::vector< T > &input_vector)
Definition: callable.hpp:125
formula_variant_callable_with_backup(const variant &var, const formula_callable &backup)
Definition: callable.hpp:219
static void add_input(formula_input_vector &inputs, const std::string &key, FORMULA_ACCESS_TYPE access_type=FORMULA_READ_ONLY)
Definition: callable.hpp:135
const_iterator begin() const
Definition: callable.hpp:269
std::shared_ptr< map_formula_callable > map_formula_callable_ptr
Definition: callable.hpp:305