8 template <
bool DECADE_SYNTAX>
11 using enum nlohmann::json::value_t;
12 static constexpr nlohmann::json::value_t any = nlohmann::json::value_t::discarded;
15 using json_pointer = nlohmann::json::json_pointer;
17 static json_pointer make_pointer(json
const& index)
28 ptr /= make_pointer(
e);
33 throw std::runtime_error(std::format(
"invalid value index type '{}'", index.type_name()));
38 template <
bool DECADE_SYNTAX>
39 struct lib_core :
public base_lib<DECADE_SYNTAX>
41 using enum nlohmann::json::value_t;
44 using env_type = base_type::env_type;
45 using json_pointer = base_type::json_pointer;
47 static inline value if_then_else(env_type&
e, std::vector<value>
args)
49 e.assert_args(
args, 3);
50 if (
e.is_true(
e.eval_arg(
args, 1)))
51 return e.eval_arg(
args, 2);
52 return e.eval_arg(
args, 3);
55 struct e_break : env_type::e_scope_terminator {
virtual std::string_view type()
const noexcept override {
return "break"; } };
56 struct e_continue : env_type::e_scope_terminator {
virtual std::string_view type()
const noexcept override {
return "continue"; } };
58 static inline value while_do(env_type&
e, std::vector<value>
args)
60 e.assert_args(
args, 2);
61 value
last = null_json;
62 while (
e.is_true(
e.eval(
args[1])))
68 catch (e_break
const&
ex)
70 if (!
ex.result->is_discarded())
74 catch (e_continue
const&
ex)
76 if (!
ex.result->is_discarded())
84 static inline value while_do_rev(env_type&
e, std::vector<value>
args)
86 e.assert_args(
args, 2);
88 return while_do(
e, std::move(
args));
91 static inline value loop_break(env_type&
e, std::vector<value>
args)
93 e.assert_args(
args, 0, 1);
95 if (
args.size() == 2)
ex.result =
e.eval_arg(
args, 1);
99 static inline value var_get(env_type&
e, std::vector<value>
args)
101 auto name =
e.eval_arg(
args, 1,
string);
102 return e.user_var(*name);
105 static inline value var_set(env_type&
e, std::vector<value>
args)
109 return e.report_error(
"trying to assign to a non-variable");
110 var.lval() =
e.eval_arg(
args, 2).forward();
114 static inline value new_var(env_type&
e, std::vector<value>
args)
116 e.assert_args(
args, 2, 3);
117 auto name =
e.eval_arg(
args, 1,
string);
118 auto val =
args.size() == 3 ?
e.eval_arg(
args, 2) : value(null_json);
119 return &
e.set_user_var(*name, std::move(
val),
true);
122 static inline value get_of(env_type&
e, std::vector<value>
args)
126 e.eval_args(
args, 2);
127 const json_pointer index = base_type::make_pointer(
args[1]);
133 case 0:
return std::move(std::get<json>(
container.v).at(index));
134 case 1:
return &std::get<json*>(
container.v)->at(index);
135 case 2:
return &std::get<json const*>(
container.v)->at(index);
137 return e.report_error(
"internal error: container value is invalid");
140 static inline value get_of_inv(env_type&
e, std::vector<value>
args)
142 e.assert_args(
args, 2);
144 return get_of(
e, std::move(
args));
148 static inline value eval(env_type&
e, std::vector<value>
args)
150 value
last = null_json;
157 static inline value list(env_type&
e, std::vector<value>
args)
160 std::vector<json> result;
163 return value(std::move(result));
166 static inline value quote(env_type&
e, std::vector<value>
args) {
e.assert_args(
args, 1);
return std::move(
args[1]); }
168 static inline value op_eq(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] == *
args[2]; }
169 static inline value op_neq(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] != *
args[2]; }
170 static inline value op_gt(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] > *
args[2]; }
171 static inline value op_ge(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] >= *
args[2]; }
172 static inline value op_lt(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] < *
args[2]; }
173 static inline value op_le(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] <= *
args[2]; }
175 static inline value op_not(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 1);
return !
e.is_true(
args[1]); }
176 static inline value op_and(env_type&
e, std::vector<value>
args) {
177 e.assert_min_args(
args, 2);
179 for (
size_t i = 1;
i <
args.size(); ++
i)
182 if (!
e.is_true(
left))
187 static inline value op_or(env_type&
e, std::vector<value>
args) {
188 e.assert_min_args(
args, 2);
190 for (
size_t i = 1;
i <
args.size(); ++
i)
199 static inline value op_plus(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] + *
args[2]; }
200 static inline value op_minus(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] - *
args[2]; }
201 static inline value op_mul(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] * *
args[2]; }
202 static inline value op_div(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] / *
args[2]; }
203 static inline value op_mod(env_type&
e, std::vector<value>
args) {
e.eval_args(
args, 2);
return *
args[1] % *
args[2]; }
205 static inline value type_of(env_type&
e, std::vector<value>
args) {
206 const auto val =
e.eval_arg(
args, 1);
207 return val->type_name();
209 static inline value size_of(env_type&
e, std::vector<value>
args) {
210 const auto val =
e.eval_arg(
args, 1);
212 return j.is_string() ?
j.get_ref<json::string_t
const&>().size() :
j.size();
215 static inline std::string stringify(value
const&
arg, std::string_view
fmt =
"{}")
218 if constexpr (std::is_same_v<std::remove_cvref_t<decltype(val)>, nlohmann::json::array_t>)
219 return std::vformat(fmt, std::make_format_args(arg->dump()));
220 else if constexpr (std::is_same_v<std::remove_cvref_t<decltype(val)>, nlohmann::json::object_t>)
221 return std::vformat(fmt, std::make_format_args(arg->dump()));
222 else if constexpr (std::is_same_v<std::remove_cvref_t<decltype(val)>, nlohmann::json::binary_t>)
223 return std::vformat(fmt, std::make_format_args(arg->dump()));
224 else if constexpr (std::is_same_v<std::remove_cvref_t<decltype(val)>, nullptr_t>)
227 return std::vformat(fmt, std::make_format_args(val));
232 static inline value str(env_type&
e, std::vector<value>
args)
235 return stringify(
arg);
238 static inline value format(env_type&
e, std::vector<value>
args)
240 e.assert_min_args(
args, 1);
243 return string_ops::callback_format(
args[1].ref(), [&](
size_t index, std::string_view
fmt, std::string& output) {
245 output += stringify(
arg,
fmt);
249 static inline value print(env_type&
e, std::vector<value>
args)
251 e.assert_args(
args, 1);
257 static inline value println(env_type&
e, std::vector<value>
args)
259 e.assert_args(
args, 1);
265 static inline json prefix_macro_get(env_type
const&, std::vector<value>
args) {
266 return json{
"get", string_view{
args[0]}.substr(1) };
269 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")
279 static void import_to(env_type&
e)
281 e.funcs[
"list"] = list;
282 e.funcs[
"eval"] = eval;
283 e.funcs[
"break"] = loop_break;
284 set_macro_prefix_get(
e);
288 e.funcs[
"if:then:else:"] = if_then_else;
289 e.funcs[
":?:::"] = if_then_else;
290 e.funcs[
"while:do:"] = while_do;
291 e.funcs[
":while:"] = while_do_rev;
292 e.funcs[
"break:"] = loop_break;
294 e.funcs[
"get:"] = var_get;
295 e.funcs[
"get:of:"] = get_of;
296 e.funcs[
":@:"] = get_of_inv;
297 e.funcs[
":at:"] = get_of_inv;
298 e.funcs[
":=:"] = var_set;
299 e.funcs[
"var:"] = new_var;
300 e.funcs[
"var:=:"] = new_var;
301 e.funcs[
"list:"] = list;
302 e.funcs[
"list:,:"] = list;
303 e.funcs[
"list:,*:"] = list;
304 e.funcs[
"eval:"] = eval;
305 e.funcs[
"eval:,:"] = eval;
306 e.funcs[
"eval:,*:"] = eval;
307 e.funcs[
":==:"] = op_eq;
308 e.funcs[
":eq:"] = op_eq;
309 e.funcs[
":!=:"] = op_neq;
310 e.funcs[
":neq:"] = op_neq;
311 e.funcs[
":>:"] = op_gt;
312 e.funcs[
":gt:"] = op_gt;
313 e.funcs[
":>=:"] = op_ge;
314 e.funcs[
":ge:"] = op_ge;
315 e.funcs[
":<:"] = op_lt;
316 e.funcs[
":lt:"] = op_lt;
317 e.funcs[
":<=:"] = op_le;
318 e.funcs[
":le:"] = op_le;
319 e.funcs[
"not:"] = op_not;
320 e.funcs[
":and*:"] = op_and;
321 e.funcs[
":and:"] = op_and;
322 e.funcs[
":or:"] = op_or;
323 e.funcs[
":or*:"] = op_or;
324 e.funcs[
":+:"] = op_plus;
325 e.funcs[
"type-of:"] = type_of;
326 e.funcs[
"typeof:"] = type_of;
327 e.funcs[
"size-of:"] = size_of;
328 e.funcs[
"sizeof:"] = size_of;
329 e.funcs[
"#:"] = size_of;
331 e.funcs[
"str:"] = str;
333 e.funcs[
"format:"] = format;
334 e.funcs[
"format:,:"] = format;
335 e.funcs[
"format:,*:"] = format;
337 e.funcs[
"print:"] = print;
338 e.funcs[
"print:,:"] = print;
339 e.funcs[
"print:,*:"] = print;
341 e.funcs[
"println:"] = println;
342 e.funcs[
"println:,:"] = println;
343 e.funcs[
"println:,*:"] = println;
constexpr auto bit_count
Equal to the number of bits in the type.
auto visit(nlohmann::json const &j, VISIT_FUNC &&func)
Calls func with the actual value inside j; similar to std::visit
std::string_view prefix(std::string_view str, size_t count) noexcept
Returns a substring containing the count leftmost characters of str. Always valid,...