124 static constexpr bool decade_syntax = DECADE_SYNTAX;
125 static constexpr bool sexps_syntax = !DECADE_SYNTAX;
127 using eval_func = std::function<
value(self_type&, std::vector<value>)>;
129 self_type* parent_env =
nullptr;
130 std::map<std::string, eval_func, std::less<>>
funcs;
131 eval_func unknown_func_eval;
132 std::function<
value(self_type&, std::string_view)> unknown_var_eval;
133 std::function<void(std::string_view)> error_handler;
134 std::map<std::string, json, std::less<>> user_storage;
135 void* user_data =
nullptr;
136 std::map<std::string, eval_func, std::less<>> prefix_macros;
139 [[nodiscard]] self_type* get_root_env() const noexcept {
return parent_env ? parent_env->get_root_env() :
this; }
141 [[nodiscard]]
auto find_in_user_storage(std::string_view name)
143 return find_in_user_storage(*
this, name);
147 static auto find_in_user_storage(
auto& self, std::string_view name)
149 if (
auto it = self.user_storage.find(name); it != self.user_storage.end())
150 return std::pair{ &self, it };
152 return self.parent_env ? find_in_user_storage(*self.parent_env, name) : std::pair<decltype(&self), decltype(it)>{};
156 [[nodiscard]] value user_var(std::string_view name)
158 auto var = find_in_user_storage(name);
160 return &var.second->second;
161 return unknown_var_eval ? unknown_var_eval(*
this, name) : value(null_json);
164 json& set_user_var(std::string_view name, value val,
bool force_local =
false)
166 auto* storage = &user_storage;
169 auto [owning_store, it] = find_in_user_storage(name);
171 storage = &owning_store->user_storage;
173 auto it = storage->find(name);
174 if (it == storage->end())
175 return storage->emplace(name, val.forward()).first->second;
176 return it->second = val.forward();
179 [[nodiscard]] eval_func
const* find_unknown_func_eval() const noexcept
181 if (unknown_func_eval)
182 return &unknown_func_eval;
184 return parent_env->find_unknown_func_eval();
188 [[nodiscard]] eval_func
const* find_func(std::string_view name)
const
190 if (
auto it =
funcs.find(name); it !=
funcs.end())
193 return parent_env->find_func(name);
194 return find_unknown_func_eval();
197 template <
typename... ARGS>
198 json report_error(std::string_view fmt, ARGS&&... args)
200 auto errstr = std::vformat(fmt, std::make_format_args(args...));
203 error_handler(errstr);
206 throw std::runtime_error(std::move(errstr));
209 struct e_scope_terminator {
210 value result = json(json::value_t::discarded);
211 virtual std::string_view type() const noexcept = 0;
212 virtual ~e_scope_terminator() noexcept = default;
215 value eval_call(std::vector<value> args)
222 std::string funcname;
223 std::vector<value> arguments;
224 if constexpr (decade_syntax)
226 const auto args_count = args.size();
227 const bool infix = (args_count % 2) == 1;
232 arguments = std::move(args);
236 arguments.push_back({});
239 arguments.push_back(std::move(args[0]));
244 std::string last_function_identifier;
245 bool argument_variadic =
false;
246 for (
size_t i = infix; i < args_count; i += 2)
248 auto& function_identifier = args[i];
249 if (function_identifier->is_string() && !std::string_view{*function_identifier}.empty())
251 if (last_function_identifier == std::string_view{ *function_identifier })
253 if (!argument_variadic)
255 funcname.back() =
'*';
257 argument_variadic =
true;
262 argument_variadic =
false;
263 funcname += *function_identifier;
265 last_function_identifier = *function_identifier;
267 arguments.push_back(std::move(args[i + 1]));
270 return report_error(
"expected function name part, got: {}", function_identifier->dump());
273 arguments[0] = funcname;
278 auto& func = *args[0];
279 if (func.is_string())
280 funcname = func.get_ref<json::string_t
const&>();
281 else if (func.is_array())
283 auto eres = eval_args(func.get_ref<json::array_t
const&>());
284 if (eres.is_string())
285 funcname = eres.template get_ref<json::string_t const&>();
287 if (funcname.empty())
288 return report_error(
"first element of eval array must eval to a string func name, got: {}", func.dump());
291 if (eval_func
const* func = find_func(funcname))
292 return (*func)(*
this, std::move(arguments));
293 return report_error(
"func with name '{}' not found", funcname);
296 template <
typename V>
299 if constexpr (std::same_as<V, value const&>)
301 return eval(value{ val });
303 else if constexpr (std::same_as<std::remove_cvref_t<V>, json>)
305 return eval(value(std::forward<V>(val)));
307 else if constexpr (std::same_as<std::remove_cvref_t<V>, value>)
309 if (val->is_string())
311 if (
auto str = std::string_view{ *val }; !str.empty())
313 for (
auto& [prefix, macro] : prefix_macros)
315 if (str.starts_with(prefix))
316 return eval(macro(*
this, { std::move(val) }));
321 if (!val->is_array())
322 return std::move(val);
324 std::vector<value> args;
325 switch (val.v.index())
329 json::array_t arr = std::move(std::get<json>(val.v).template get_ref<json::array_t&>());
331 args.push_back(std::move(a));
336 json::array_t& arr = std::get<json*>(val.v)->template get_ref<json::array_t&>();
343 json::array_t
const& arr = std::get<json const*>(val.v)->template get_ref<json::array_t const&>();
344 for (
auto const& a : arr)
350 return eval_call(std::move(args));
354 template <
typename T>
355 json safe_eval(T&& value)
359 auto result = eval(value);
360 return result.forward();
362 catch (e_scope_terminator
const& e)
364 return report_error(
"'{}' not in loop", e.type());
368 [[nodiscard]]
inline bool is_true(json
const& val)
372 case json::value_t::boolean:
return bool(val);
373 case json::value_t::null:
return false;
378 [[nodiscard]]
inline bool is_true(value
const& val)
380 return is_true(*val);
383 static void assert_args(std::span<value const> args,
size_t arg_count)
385 if (args.size() != arg_count + 1)
386 throw std::runtime_error(std::format(
"function {} requires exactly {} arguments, {} given", args[0]->dump(), arg_count, args.size() - 1));
389 static void assert_args(std::span<value const> args,
size_t min_args,
size_t max_args)
391 if (args.size() < min_args + 1 && args.size() >= max_args + 1)
392 throw std::runtime_error(std::format(
"function {} requires between {} and {} arguments, {} given", args[0]->dump(), min_args, max_args, args.size() - 1));
395 static void assert_min_args(std::span<value const> args,
size_t arg_count)
397 if (args.size() < arg_count + 1)
398 throw std::runtime_error(std::format(
"function {} requires at least {} arguments, {} given", args[0]->dump(), arg_count, args.size() - 1));
401 static auto assert_arg(std::span<value const> args,
size_t arg_num, json::value_t type = json::value_t::discarded)
403 if (arg_num >= args.size())
404 throw std::runtime_error(std::format(
"function {} requires {} arguments, {} given", args[0]->dump(), arg_num, args.size() - 1));
406 if (type != json::value_t::discarded && args[arg_num]->type() != type)
408 throw std::runtime_error(std::format(
"argument #{} to function {} must be of type {}, {} given",
409 arg_num, args[0]->dump(), formats::json::type_name(type), formats::json::type_name(args[arg_num]->type())));
412 return args[arg_num]->type();
415 template <std::same_as<nlohmann::json::value_t>... T>
416 static void assert_args(std::vector<value> args, T... arg_types)
418 static constexpr size_t arg_count =
sizeof...(T);
419 assert_args(args, arg_count);
421 const auto types = std::array{ arg_types... };
422 for (
size_t i = 0; i < types.size(); ++i)
424 if (types[i] != json::value_t::discarded)
425 assert_arg(args, i + 1, types[i]);
429 value eval_arg(std::vector<value>& args,
size_t n, json::value_t type = json::value_t::discarded)
431 assert_arg(args, n, type);
432 return eval(std::move(args[n]));
435 void eval_args(std::vector<value>& args,
size_t n)
437 assert_args(args, n);
438 for (
auto& arg : std::span{ args }.subspan(1))
439 arg = eval(std::move(arg));
442 void eval_args(std::vector<value>& args)
444 eval_args(args, args.size() - 1);
447 template <
typename LIB_TYPE>
450 LIB_TYPE::import_to(*
this);
453 template <
template<
bool>
typename LIB_TYPE>
456 LIB_TYPE<decade_syntax>::import_to(*
this);