41 struct lib_core :
public base_lib<DECADE_SYNTAX>
43 using enum nlohmann::json::value_t;
45 using base_type = base_lib<DECADE_SYNTAX>;
46 using env_type = base_type::env_type;
47 using json_pointer = base_type::json_pointer;
51 static inline value if_then_else(env_type& e, std::vector<value> args)
53 e.assert_args(args, 3);
54 if (e.is_true(e.eval_arg(args, 1)))
55 return e.eval_arg(args, 2);
56 return e.eval_arg(args, 3);
59 struct e_break : env_type::e_scope_terminator {
virtual std::string_view type()
const noexcept override {
return "break"; } };
60 struct e_continue : env_type::e_scope_terminator {
virtual std::string_view type()
const noexcept override {
return "continue"; } };
62 static inline value while_do(env_type& e, std::vector<value> args)
64 e.assert_args(args, 2);
65 value last = null_json;
66 while (e.is_true(e.eval(args[1])))
70 last = e.eval(args[2]);
72 catch (e_break
const& ex)
74 if (!ex.result->is_discarded())
78 catch (e_continue
const& ex)
80 if (!ex.result->is_discarded())
88 static inline value while_do_rev(env_type& e, std::vector<value> args)
90 e.assert_args(args, 2);
91 std::swap(args[1], args[2]);
92 return while_do(e, std::move(args));
95 static inline value loop_break(env_type& e, std::vector<value> args)
97 e.assert_args(args, 0, 1);
99 if (args.size() == 2) ex.result = e.eval_arg(args, 1);
103 static inline value var_get(env_type& e, std::vector<value> args)
105 auto name = e.eval_arg(args, 1,
string);
106 return e.user_var(*name);
109 static inline value var_set(env_type& e, std::vector<value> args)
111 auto var = e.eval_arg(args, 1);
113 return e.report_error(
"trying to assign to a non-variable");
114 var.lval() = e.eval_arg(args, 2).forward();
118 static inline value new_var(env_type& e, std::vector<value> args)
120 e.assert_args(args, 2, 3);
121 auto name = e.eval_arg(args, 1,
string);
122 auto val = args.size() == 3 ? e.eval_arg(args, 2) :
value(null_json);
123 return &e.set_user_var(*name, std::move(val),
true);
126 static inline value get_of(env_type& e, std::vector<value> args)
130 e.eval_args(args, 2);
131 const json_pointer index = base_type::make_pointer(args[1]);
132 value& container = args[2];
133 if (!container->contains(index))
135 switch (container.v.index())
137 case 0:
return std::move(std::get<json>(container.v).at(index));
138 case 1:
return &std::get<json*>(container.v)->at(index);
139 case 2:
return &std::get<json const*>(container.v)->at(index);
141 return e.report_error(
"internal error: container value is invalid");
144 static inline value get_of_inv(env_type& e, std::vector<value> args)
146 e.assert_args(args, 2);
147 std::swap(args[1], args[2]);
148 return get_of(e, std::move(args));
152 static inline value eval(env_type& e, std::vector<value> args)
154 value last = null_json;
155 for (
auto& arg : std::span{ args }.subspan(1))
156 last = e.eval(std::move(arg));
161 static inline value list(env_type& e, std::vector<value> args)
164 std::vector<json> result;
165 for (
auto& arg : std::span{ args }.subspan(1))
166 result.push_back(arg.forward());
167 return value(std::move(result));
170 static inline value quote(env_type& e, std::vector<value> args) { e.assert_args(args, 1);
return std::move(args[1]); }
172 static inline value op_eq(env_type& e, std::vector<value> args) { e.eval_args(args, 2);
return *args[1] == *args[2]; }
173 static inline value op_neq(env_type& e, std::vector<value> args) { e.eval_args(args, 2);
return *args[1] != *args[2]; }
174 static inline value op_gt(env_type& e, std::vector<value> args) { e.eval_args(args, 2);
return *args[1] > *args[2]; }
175 static inline value op_ge(env_type& e, std::vector<value> args) { e.eval_args(args, 2);
return *args[1] >= *args[2]; }
176 static inline value op_lt(env_type& e, std::vector<value> args) { e.eval_args(args, 2);
return *args[1] < *args[2]; }
177 static inline value op_le(env_type& e, std::vector<value> args) { e.eval_args(args, 2);
return *args[1] <= *args[2]; }
179 static inline value op_not(env_type& e, std::vector<value> args) { e.eval_args(args, 1);
return !e.is_true(args[1]); }
180 static inline value op_and(env_type& e, std::vector<value> args) {
181 e.assert_min_args(args, 2);
183 for (
size_t i = 1; i < args.size(); ++i)
185 left = e.eval_arg(args, i);
186 if (!e.is_true(
left))
191 static inline value op_or(env_type& e, std::vector<value> args) {
192 e.assert_min_args(args, 2);
194 for (
size_t i = 1; i < args.size(); ++i)
196 left = e.eval_arg(args, i);
229 static inline value type_of(env_type& e, std::vector<value> args) {
230 const auto val = e.eval_arg(args, 1);
231 return val->type_name();
233 static inline value size_of(env_type& e, std::vector<value> args) {
234 const auto val = e.eval_arg(args, 1);
236 return j.is_string() ? j.get_ref<json::string_t
const&>().size() : j.size();
239 static inline std::string stringify(
value const& arg, std::string_view fmt =
"{}")
242 if constexpr (std::is_same_v<std::remove_cvref_t<decltype(val)>, nlohmann::json::array_t>)
244 auto dump = arg->dump();
245 return std::vformat(fmt, std::make_format_args(dump));
247 else if constexpr (std::is_same_v<std::remove_cvref_t<
decltype(val)>, nlohmann::json::object_t>)
249 auto dump = arg->dump();
250 return std::vformat(fmt, std::make_format_args(dump));
252 else if constexpr (std::is_same_v<std::remove_cvref_t<
decltype(val)>, nlohmann::json::binary_t>)
254 auto dump = arg->dump();
255 return std::vformat(fmt, std::make_format_args(dump));
257 else if constexpr (std::is_same_v<std::remove_cvref_t<
decltype(val)>, nullptr_t>)
258 return std::string{
"null" };
260 return std::vformat(fmt, std::make_format_args(val));
265 static inline value str(env_type& e, std::vector<value> args)
267 auto arg = e.eval_arg(args, 1);
268 return stringify(arg);
271 static inline value format(env_type& e, std::vector<value> args)
273 e.assert_min_args(args, 1);
276 return string_ops::callback_format(args[1].ref(), [&](
size_t index, std::string_view fmt, std::string& output) {
277 auto& arg = args[2 + index];
278 output += stringify(arg, fmt);
282 static inline value print(env_type& e, std::vector<value> args)
284 e.assert_args(args, 1);
285 auto fmted = format(e, std::move(args));
286 std::print(
"{}", fmted->template get_ref<nlohmann::json::string_t const&>());
290 static inline value println(env_type& e, std::vector<value> args)
292 e.assert_args(args, 1);
293 auto fmted = format(e, std::move(args));
294 std::println(
"{}", fmted->template get_ref<nlohmann::json::string_t const&>());
298 static inline json prefix_macro_get(env_type
const&, std::vector<value> args) {
299 return json{
"get", std::string_view{args[0].ref()}.substr(1)};
302 static inline void set_macro_prefix_get(env_type& e, std::string
const& prefix =
".", std::string
const& prefix_eval_func_name =
"dot", std::string
const& get_func_name =
"get")
304 e.prefix_macros[
prefix] = [get_func_name, prefix_size =
prefix.size()](env_type
const& e, std::vector<value> args) {
305 return json{ get_func_name, std::string{*args[0]}.substr(prefix_size) };
307 e.funcs[prefix_eval_func_name] = [
prefix](env_type
const& e, std::vector<value>) ->
value {
314 static void import_to(env_type& e)
316 e.funcs[
"list"] = list;
317 e.funcs[
"eval"] = eval;
318 e.funcs[
"break"] = loop_break;
319 set_macro_prefix_get(e);
321 if constexpr (DECADE_SYNTAX)
323 e.funcs[
"if:then:else:"] = if_then_else;
324 e.funcs[
":?:::"] = if_then_else;
325 e.funcs[
"while:do:"] = while_do;
326 e.funcs[
":while:"] = while_do_rev;
327 e.funcs[
"break:"] = loop_break;
329 e.funcs[
"get:"] = var_get;
330 e.funcs[
"get:of:"] = get_of;
331 e.funcs[
":@:"] = get_of_inv;
332 e.funcs[
":at:"] = get_of_inv;
333 e.funcs[
":=:"] = var_set;
334 e.funcs[
"var:"] = new_var;
335 e.funcs[
"var:=:"] = new_var;
336 e.funcs[
"list:"] = list;
337 e.funcs[
"list:,:"] = list;
338 e.funcs[
"list:,*:"] = list;
339 e.funcs[
"eval:"] = eval;
340 e.funcs[
"eval:,:"] = eval;
341 e.funcs[
"eval:,*:"] = eval;
342 e.funcs[
":==:"] = op_eq;
343 e.funcs[
":eq:"] = op_eq;
344 e.funcs[
":!=:"] = op_neq;
345 e.funcs[
":neq:"] = op_neq;
346 e.funcs[
":>:"] = op_gt;
347 e.funcs[
":gt:"] = op_gt;
348 e.funcs[
":>=:"] = op_ge;
349 e.funcs[
":ge:"] = op_ge;
350 e.funcs[
":<:"] = op_lt;
351 e.funcs[
":lt:"] = op_lt;
352 e.funcs[
":<=:"] = op_le;
353 e.funcs[
":le:"] = op_le;
354 e.funcs[
"not:"] = op_not;
355 e.funcs[
":and*:"] = op_and;
356 e.funcs[
":and:"] = op_and;
357 e.funcs[
":or:"] = op_or;
358 e.funcs[
":or*:"] = op_or;
360 e.funcs[
"type-of:"] = type_of;
361 e.funcs[
"typeof:"] = type_of;
362 e.funcs[
"size-of:"] = size_of;
363 e.funcs[
"sizeof:"] = size_of;
364 e.funcs[
"#:"] = size_of;
366 e.funcs[
"str:"] = str;
368 e.funcs[
"format:"] = format;
369 e.funcs[
"format:,:"] = format;
370 e.funcs[
"format:,*:"] = format;
372 e.funcs[
"print:"] = print;
373 e.funcs[
"print:,:"] = print;
374 e.funcs[
"print:,*:"] = print;
376 e.funcs[
"println:"] = println;
377 e.funcs[
"println:,:"] = println;
378 e.funcs[
"println:,*:"] = println;