1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
#pragma once
#include <concepts>
#include <cstdint>
#include <functional>
#include <map>
#include <type_traits>
#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
#include "openvic-simulation/types/Colour.hpp"
#include "openvic-simulation/types/Date.hpp"
#include "openvic-simulation/types/Vector.hpp"
namespace OpenVic {
namespace ast = ovdl::v2script::ast;
/* Template for map from strings to Ts, in which string_views can be
* searched for without needing to be copied into a string, */
template<typename T>
using string_map_t = std::map<std::string, T, std::less<void>>;
namespace NodeTools {
template<typename Fn, typename Return = void, typename ...Args>
concept Functor = requires(Fn&& fn, Args&& ...args) {
{ std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...) } -> std::same_as<Return>;
};
template<typename Fn, typename Return = void, typename ...Args>
concept FunctorConvertible = requires(Fn&& fn, Args&& ...args) {
{ std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...) } -> std::convertible_to<Return>;
};
template<typename Fn, typename ...Args>
concept Callback = Functor<Fn, bool, Args...>;
template<typename Fn>
concept NodeCallback = Callback<Fn, ast::NodeCPtr>;
template<typename Fn>
concept KeyValueCallback = Callback<Fn, std::string_view, ast::NodeCPtr>;
template<typename Fn>
concept LengthCallback = Functor<Fn, std::size_t, std::size_t>;
template<typename... Args>
using callback_t = std::function<bool(Args...)>;
using node_callback_t = callback_t<ast::NodeCPtr>;
constexpr bool success_callback(ast::NodeCPtr) { return true; }
using key_value_callback_t = callback_t<std::string_view, ast::NodeCPtr>;
constexpr bool key_value_success_callback(std::string_view, ast::NodeCPtr) { return true; }
inline bool key_value_invalid_callback(std::string_view key, ast::NodeCPtr) {
Logger::error("Invalid dictionary key: ", key);
return false;
}
node_callback_t expect_identifier(callback_t<std::string_view> callback);
node_callback_t expect_string(callback_t<std::string_view> callback, bool allow_empty = true);
node_callback_t expect_identifier_or_string(callback_t<std::string_view> callback, bool allow_empty = false);
node_callback_t expect_bool(callback_t<bool> callback);
node_callback_t expect_int_bool(callback_t<bool> callback);
node_callback_t expect_int64(callback_t<int64_t> callback);
node_callback_t expect_uint64(callback_t<uint64_t> callback);
template<std::signed_integral T>
NodeCallback auto expect_int(callback_t<T> callback) {
return expect_int64([callback](int64_t val) -> bool {
if (static_cast<int64_t>(std::numeric_limits<T>::lowest()) <= val &&
val <= static_cast<int64_t>(std::numeric_limits<T>::max())) {
return callback(val);
}
Logger::error("Invalid int: ", val, " (valid range: [",
static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ",
static_cast<int64_t>(std::numeric_limits<T>::max()), "])");
return false;
});
}
template<std::integral T>
NodeCallback auto expect_uint(callback_t<T> callback) {
return expect_uint64([callback](uint64_t val) -> bool {
if (val <= static_cast<uint64_t>(std::numeric_limits<T>::max())) {
return callback(val);
}
Logger::error("Invalid uint: ", val, " (valid range: [0, ",
static_cast<uint64_t>(std::numeric_limits<T>::max()), "])");
return false;
});
}
node_callback_t expect_fixed_point(callback_t<fixed_point_t> callback);
node_callback_t expect_colour(callback_t<colour_t> callback);
node_callback_t expect_date(callback_t<Date> callback);
node_callback_t expect_years(callback_t<Timespan> callback);
node_callback_t expect_months(callback_t<Timespan> callback);
node_callback_t expect_days(callback_t<Timespan> callback);
node_callback_t expect_ivec2(callback_t<ivec2_t> callback);
node_callback_t expect_fvec2(callback_t<fvec2_t> callback);
node_callback_t expect_assign(key_value_callback_t callback);
using length_callback_t = std::function<size_t(size_t)>;
constexpr size_t default_length_callback(size_t size) { return size; };
node_callback_t expect_list_and_length(length_callback_t length_callback, node_callback_t callback);
node_callback_t expect_list_of_length(size_t length, node_callback_t callback);
node_callback_t expect_list(node_callback_t callback);
node_callback_t expect_length(callback_t<size_t> callback);
node_callback_t expect_key(std::string_view key, node_callback_t callback, bool* key_found = nullptr);
node_callback_t expect_dictionary_and_length(length_callback_t length_callback, key_value_callback_t callback);
node_callback_t expect_dictionary(key_value_callback_t callback);
struct dictionary_entry_t {
const enum class expected_count_t : uint8_t {
_MUST_APPEAR = 0b01,
_CAN_REPEAT = 0b10,
ZERO_OR_ONE = 0,
ONE_EXACTLY = _MUST_APPEAR,
ZERO_OR_MORE = _CAN_REPEAT,
ONE_OR_MORE = _MUST_APPEAR | _CAN_REPEAT
} expected_count;
const node_callback_t callback;
size_t count;
dictionary_entry_t(expected_count_t new_expected_count, node_callback_t new_callback)
: expected_count { new_expected_count }, callback { new_callback }, count { 0 } {}
constexpr bool must_appear() const {
return static_cast<uint8_t>(expected_count) & static_cast<uint8_t>(expected_count_t::_MUST_APPEAR);
}
constexpr bool can_repeat() const {
return static_cast<uint8_t>(expected_count) & static_cast<uint8_t>(expected_count_t::_CAN_REPEAT);
}
};
using enum dictionary_entry_t::expected_count_t;
using key_map_t = string_map_t<dictionary_entry_t>;
bool add_key_map_entry(key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback);
bool remove_key_map_entry(key_map_t& key_map, std::string_view key);
key_value_callback_t dictionary_keys_callback(key_map_t& key_map, key_value_callback_t default_callback);
bool check_key_map_counts(key_map_t& key_map);
constexpr bool add_key_map_entries(key_map_t& key_map) { return true; }
template<typename... Args>
bool add_key_map_entries(key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, NodeCallback auto callback, Args... args) {
bool ret = add_key_map_entry(key_map, key, expected_count, callback);
ret &= add_key_map_entries(key_map, args...);
return ret;
}
node_callback_t expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback);
node_callback_t expect_dictionary_key_map_and_length(key_map_t key_map, length_callback_t length_callback);
node_callback_t expect_dictionary_key_map_and_default(key_map_t key_map, key_value_callback_t default_callback);
node_callback_t expect_dictionary_key_map(key_map_t key_map);
template<typename... Args>
NodeCallback auto expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback, Args... args) {
// TODO - pass return value back up (part of big key_map_t rewrite?)
add_key_map_entries(key_map, args...);
return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, default_callback);
}
template<typename... Args>
NodeCallback auto expect_dictionary_keys_and_length_and_default(LengthCallback auto length_callback, KeyValueCallback auto default_callback, Args... args) {
return expect_dictionary_key_map_and_length_and_default({}, length_callback, default_callback, args...);
}
template<typename... Args>
NodeCallback auto expect_dictionary_keys_and_length(LengthCallback auto length_callback, Args... args) {
return expect_dictionary_key_map_and_length_and_default({}, length_callback, key_value_invalid_callback, args...);
}
template<typename... Args>
NodeCallback auto expect_dictionary_keys_and_default(KeyValueCallback auto default_callback, Args... args) {
return expect_dictionary_key_map_and_length_and_default({}, default_length_callback, default_callback, args...);
}
template<typename... Args>
NodeCallback auto expect_dictionary_keys(Args... args) {
return expect_dictionary_key_map_and_length_and_default({}, default_length_callback, key_value_invalid_callback, args...);
}
template<typename T>
concept Reservable = requires(T& t) {
{ t.size() } -> std::same_as<size_t>;
t.reserve(size_t {});
};
template<Reservable T>
NodeCallback auto expect_list_reserve_length(T& t, NodeCallback auto callback) {
return expect_list_and_length(
[&t](size_t size) -> size_t {
t.reserve(t.size() + size);
return size;
},
callback
);
}
template<Reservable T>
NodeCallback auto expect_dictionary_reserve_length(T& t, KeyValueCallback auto callback) {
return expect_list_reserve_length(t, expect_assign(callback));
}
node_callback_t name_list_callback(callback_t<std::vector<std::string>&&> callback);
template<typename T>
Callback<std::string_view> auto expect_mapped_string(string_map_t<T> const& map, Callback<T> auto callback) {
return [&map, callback](std::string_view string) -> bool {
const typename string_map_t<T>::const_iterator it = map.find(string);
if (it != map.end()) {
return callback(it->second);
}
Logger::error("String not found in map: ", string);
return false;
};
}
template<typename T>
Callback<T> auto assign_variable_callback_cast(auto& var) {
return [&var](T val) -> bool {
var = val;
return true;
};
}
template<std::integral T>
callback_t<T> assign_variable_callback_cast(auto& var) {
return [&var](T val) -> bool {
var = val;
return true;
};
}
template<std::signed_integral T>
callback_t<T> assign_variable_callback_cast(auto& var) {
return [&var](T val) -> bool {
var = val;
return true;
};
}
template<typename T>
Callback<T> auto assign_variable_callback(T& var) {
return assign_variable_callback_cast<T, T>(var);
}
callback_t<std::string_view> assign_variable_callback_string(std::string& var);
template<typename T>
Callback<T&&> auto move_variable_callback(T& var) {
return [&var](T&& val) -> bool {
var = std::move(val);
return true;
};
}
template<typename T>
requires requires(T& t) {
t += T {};
}
Callback<T> auto add_variable_callback(T& var) {
return [&var](T val) -> bool {
var += val;
return true;
};
}
template<typename T>
requires requires(T& t) {
t++;
}
KeyValueCallback auto increment_callback(T& var) {
return [&var](std::string_view, ast::NodeCPtr) -> bool {
var++;
return true;
};
}
template<typename T>
Callback<T const&> auto assign_variable_callback_pointer(T const*& var) {
return [&var](T const& val) -> bool {
var = &val;
return true;
};
}
}
}
|