From b5b0d0adf523be366b1c2e9948d07afead49d91c Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Tue, 23 Mar 2021 02:43:00 +0100 Subject: [PATCH] move some public state api into cs_state, separate lib_base --- src/cs_state.cc | 159 +++++++++++++++ src/cubescript.cc | 481 ---------------------------------------------- src/lib_base.cc | 344 +++++++++++++++++++++++++++++++++ src/meson.build | 1 + 4 files changed, 504 insertions(+), 481 deletions(-) create mode 100644 src/lib_base.cc diff --git a/src/cs_state.cc b/src/cs_state.cc index bc94ef5..dba595f 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -3,6 +3,7 @@ #include "cs_bcode.hh" #include "cs_state.hh" #include "cs_strman.hh" +#include "cs_vm.hh" // FIXME, only Max Arguments namespace cscript { @@ -28,4 +29,162 @@ void *cs_shared_state::alloc(void *ptr, size_t os, size_t ns) { return p; } +static void *cs_default_alloc(void *, void *p, size_t, size_t ns) { + if (!ns) { + std::free(p); + return nullptr; + } + return std::realloc(p, ns); +} + +void cs_init_lib_base(cs_state &cs); +void cs_init_lib_math(cs_state &cs); +void cs_init_lib_string(cs_state &cs); +void cs_init_lib_list(cs_state &cs); + +/* public interfaces */ + +cs_state::cs_state(): cs_state{cs_default_alloc, nullptr} {} + +cs_state::cs_state(cs_alloc_cb func, void *data): + p_state{nullptr}, p_callhook{} +{ + cs_command *p; + + if (!func) { + func = cs_default_alloc; + } + /* allocator is not set up yet, use func directly */ + p_state = static_cast( + func(data, nullptr, 0, sizeof(cs_shared_state)) + ); + /* allocator will be set up in the constructor */ + new (p_state) cs_shared_state{func, data}; + p_owner = true; + + /* will be used as message storage for errors */ + p_errbuf = p_state->create(*this); + + for (int i = 0; i < MaxArguments; ++i) { + char buf[32]; + snprintf(buf, sizeof(buf), "arg%d", i + 1); + new_ident(static_cast(buf), CS_IDF_ARG); + } + + cs_ident *id = new_ident("//dummy"); + if (id->get_index() != DummyIdx) { + throw cs_internal_error{"invalid dummy index"}; + } + + id = new_ivar("numargs", MaxArguments, 0, 0); + if (id->get_index() != NumargsIdx) { + throw cs_internal_error{"invalid numargs index"}; + } + + id = new_ivar("dbgalias", 0, 1000, 4); + if (id->get_index() != DbgaliasIdx) { + throw cs_internal_error{"invalid dbgalias index"}; + } + + p = new_command("do", "e", [](auto &cs, auto args, auto &res) { + cs.run(args[0].get_code(), res); + }); + static_cast(p)->p_type = ID_DO; + + p = new_command("doargs", "e", [](auto &cs, auto args, auto &res) { + cs_do_args(cs, [&cs, &res, &args]() { + cs.run(args[0].get_code(), res); + }); + }); + static_cast(p)->p_type = ID_DOARGS; + + p = new_command("if", "tee", [](auto &cs, auto args, auto &res) { + cs.run((args[0].get_bool() ? args[1] : args[2]).get_code(), res); + }); + static_cast(p)->p_type = ID_IF; + + p = new_command("result", "t", [](auto &, auto args, auto &res) { + res = std::move(args[0]); + }); + static_cast(p)->p_type = ID_RESULT; + + p = new_command("!", "t", [](auto &, auto args, auto &res) { + res.set_int(!args[0].get_bool()); + }); + static_cast(p)->p_type = ID_NOT; + + p = new_command("&&", "E1V", [](auto &cs, auto args, auto &res) { + if (args.empty()) { + res.set_int(1); + } else { + for (size_t i = 0; i < args.size(); ++i) { + cs_bcode *code = args[i].get_code(); + if (code) { + cs.run(code, res); + } else { + res = std::move(args[i]); + } + if (!res.get_bool()) { + break; + } + } + } + }); + static_cast(p)->p_type = ID_AND; + + p = new_command("||", "E1V", [](auto &cs, auto args, auto &res) { + if (args.empty()) { + res.set_int(0); + } else { + for (size_t i = 0; i < args.size(); ++i) { + cs_bcode *code = args[i].get_code(); + if (code) { + cs.run(code, res); + } else { + res = std::move(args[i]); + } + if (res.get_bool()) { + break; + } + } + } + }); + static_cast(p)->p_type = ID_OR; + + p = new_command("local", "", nullptr); + static_cast(p)->p_type = ID_LOCAL; + + p = new_command("break", "", [](auto &cs, auto, auto &) { + if (cs.is_in_loop()) { + throw CsBreakException(); + } else { + throw cs_error(cs, "no loop to break"); + } + }); + static_cast(p)->p_type = ID_BREAK; + + p = new_command("continue", "", [](auto &cs, auto, auto &) { + if (cs.is_in_loop()) { + throw CsContinueException(); + } else { + throw cs_error(cs, "no loop to continue"); + } + }); + static_cast(p)->p_type = ID_CONTINUE; + + cs_init_lib_base(*this); +} + +LIBCUBESCRIPT_EXPORT void cs_state::init_libs(int libs) { + if (libs & CS_LIB_MATH) { + cs_init_lib_math(*this); + } + if (libs & CS_LIB_STRING) { + cs_init_lib_string(*this); + } + if (libs & CS_LIB_LIST) { + cs_init_lib_list(*this); + } +} + } /* namespace cscript */ diff --git a/src/cubescript.cc b/src/cubescript.cc index d017c90..a1e2685 100644 --- a/src/cubescript.cc +++ b/src/cubescript.cc @@ -30,136 +30,6 @@ static void *cs_default_alloc(void *, void *p, size_t, size_t ns) { return std::realloc(p, ns); } -cs_state::cs_state(): cs_state{cs_default_alloc, nullptr} {} - -cs_state::cs_state(cs_alloc_cb func, void *data): - p_state(nullptr), p_callhook() -{ - cs_command *p; - - if (!func) { - func = cs_default_alloc; - } - /* allocator is not set up yet, use func directly */ - p_state = static_cast( - func(data, nullptr, 0, sizeof(cs_shared_state)) - ); - /* allocator will be set up in the constructor */ - new (p_state) cs_shared_state{func, data}; - p_owner = true; - - /* will be used as message storage for errors */ - p_errbuf = p_state->create(*this); - - for (int i = 0; i < MaxArguments; ++i) { - char buf[32]; - snprintf(buf, sizeof(buf), "arg%d", i + 1); - new_ident(static_cast(buf), CS_IDF_ARG); - } - cs_ident *id = new_ident("//dummy"); - if (id->get_index() != DummyIdx) { - throw cs_internal_error{"invalid dummy index"}; - } - - id = new_ivar("numargs", MaxArguments, 0, 0); - if (id->get_index() != NumargsIdx) { - throw cs_internal_error{"invalid numargs index"}; - } - - id = new_ivar("dbgalias", 0, 1000, 4); - if (id->get_index() != DbgaliasIdx) { - throw cs_internal_error{"invalid dbgalias index"}; - } - - p = new_command("do", "e", [](auto &cs, auto args, auto &res) { - cs.run(args[0].get_code(), res); - }); - static_cast(p)->p_type = ID_DO; - - p = new_command("doargs", "e", [](auto &cs, auto args, auto &res) { - cs_do_args(cs, [&cs, &res, &args]() { - cs.run(args[0].get_code(), res); - }); - }); - static_cast(p)->p_type = ID_DOARGS; - - p = new_command("if", "tee", [](auto &cs, auto args, auto &res) { - cs.run((args[0].get_bool() ? args[1] : args[2]).get_code(), res); - }); - static_cast(p)->p_type = ID_IF; - - p = new_command("result", "t", [](auto &, auto args, auto &res) { - res = std::move(args[0]); - }); - static_cast(p)->p_type = ID_RESULT; - - p = new_command("!", "t", [](auto &, auto args, auto &res) { - res.set_int(!args[0].get_bool()); - }); - static_cast(p)->p_type = ID_NOT; - - p = new_command("&&", "E1V", [](auto &cs, auto args, auto &res) { - if (args.empty()) { - res.set_int(1); - } else { - for (size_t i = 0; i < args.size(); ++i) { - cs_bcode *code = args[i].get_code(); - if (code) { - cs.run(code, res); - } else { - res = std::move(args[i]); - } - if (!res.get_bool()) { - break; - } - } - } - }); - static_cast(p)->p_type = ID_AND; - - p = new_command("||", "E1V", [](auto &cs, auto args, auto &res) { - if (args.empty()) { - res.set_int(0); - } else { - for (size_t i = 0; i < args.size(); ++i) { - cs_bcode *code = args[i].get_code(); - if (code) { - cs.run(code, res); - } else { - res = std::move(args[i]); - } - if (res.get_bool()) { - break; - } - } - } - }); - static_cast(p)->p_type = ID_OR; - - p = new_command("local", "", nullptr); - static_cast(p)->p_type = ID_LOCAL; - - p = new_command("break", "", [](auto &cs, auto, auto &) { - if (cs.is_in_loop()) { - throw CsBreakException(); - } else { - throw cs_error(cs, "no loop to break"); - } - }); - static_cast(p)->p_type = ID_BREAK; - - p = new_command("continue", "", [](auto &cs, auto, auto &) { - if (cs.is_in_loop()) { - throw CsContinueException(); - } else { - throw cs_error(cs, "no loop to continue"); - } - }); - static_cast(p)->p_type = ID_CONTINUE; - - cs_init_lib_base(*this); -} - LIBCUBESCRIPT_EXPORT cs_state::~cs_state() { destroy(); } @@ -792,355 +662,4 @@ LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command( return cmd; } -static inline void cs_do_loop( - cs_state &cs, cs_ident &id, cs_int offset, cs_int n, cs_int step, - cs_bcode *cond, cs_bcode *body -) { - cs_stacked_value idv{cs, &id}; - if (n <= 0 || !idv.has_alias()) { - return; - } - for (cs_int i = 0; i < n; ++i) { - idv.set_int(offset + i * step); - idv.push(); - if (cond && !cs.run(cond).get_bool()) { - break; - } - switch (cs.run_loop(body)) { - case cs_loop_state::BREAK: - goto end; - default: /* continue and normal */ - break; - } - } -end: - return; -} - -static inline void cs_loop_conc( - cs_state &cs, cs_value &res, cs_ident &id, cs_int offset, cs_int n, - cs_int step, cs_bcode *body, bool space -) { - cs_stacked_value idv{cs, &id}; - if (n <= 0 || !idv.has_alias()) { - return; - } - cs_charbuf s{cs}; - for (cs_int i = 0; i < n; ++i) { - idv.set_int(offset + i * step); - idv.push(); - cs_value v{cs}; - switch (cs.run_loop(body, v)) { - case cs_loop_state::BREAK: - goto end; - case cs_loop_state::CONTINUE: - continue; - default: - break; - } - if (space && i) { - s.push_back(' '); - } - s.append(v.get_str()); - } -end: - res.set_str(s.str()); -} - -void cs_init_lib_base(cs_state &gcs) { - gcs.new_command("error", "s", [](auto &cs, auto args, auto &) { - throw cs_error(cs, args[0].get_str()); - }); - - gcs.new_command("pcall", "err", [](auto &cs, auto args, auto &ret) { - cs_alias *cret = args[1].get_ident()->get_alias(), - *css = args[2].get_ident()->get_alias(); - if (!cret || !css) { - ret.set_int(0); - return; - } - cs_value result{cs}, tback{cs}; - bool rc = true; - try { - cs.run(args[0].get_code(), result); - } catch (cs_error const &e) { - result.set_str(e.what()); - if (e.get_stack().get()) { - cs_charbuf buf{cs}; - cs_print_stack(std::back_inserter(buf), e.get_stack()); - tback.set_str(buf.str()); - } - rc = false; - } - ret.set_int(rc); - static_cast(cret)->set_alias(cs, result); - static_cast(css)->set_alias(cs, tback); - }); - - gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) { - if (args[0].get_bool()) { - res = args[1]; - } else { - res = args[2]; - } - }); - - gcs.new_command("cond", "ee2V", [](auto &cs, auto args, auto &res) { - for (size_t i = 0; i < args.size(); i += 2) { - if ((i + 1) < args.size()) { - if (cs.run(args[i].get_code()).get_bool()) { - cs.run(args[i + 1].get_code(), res); - break; - } - } else { - cs.run(args[i].get_code(), res); - break; - } - } - }); - - gcs.new_command("case", "ite2V", [](auto &cs, auto args, auto &res) { - cs_int val = args[0].get_int(); - for (size_t i = 1; (i + 1) < args.size(); i += 2) { - if ( - (args[i].get_type() == cs_value_type::NONE) || - (args[i].get_int() == val) - ) { - cs.run(args[i + 1].get_code(), res); - return; - } - } - }); - - gcs.new_command("casef", "fte2V", [](auto &cs, auto args, auto &res) { - cs_float val = args[0].get_float(); - for (size_t i = 1; (i + 1) < args.size(); i += 2) { - if ( - (args[i].get_type() == cs_value_type::NONE) || - (args[i].get_float() == val) - ) { - cs.run(args[i + 1].get_code(), res); - return; - } - } - }); - - gcs.new_command("cases", "ste2V", [](auto &cs, auto args, auto &res) { - cs_strref val = args[0].get_str(); - for (size_t i = 1; (i + 1) < args.size(); i += 2) { - if ( - (args[i].get_type() == cs_value_type::NONE) || - (args[i].get_str() == val) - ) { - cs.run(args[i + 1].get_code(), res); - return; - } - } - }); - - gcs.new_command("pushif", "rte", [](auto &cs, auto args, auto &res) { - cs_stacked_value idv{cs, args[0].get_ident()}; - if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) { - return; - } - if (args[1].get_bool()) { - idv = args[1]; - idv.push(); - cs.run(args[2].get_code(), res); - } - }); - - gcs.new_command("loop", "rie", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), 0, args[1].get_int(), 1, nullptr, - args[2].get_code() - ); - }); - - gcs.new_command("loop+", "riie", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1, - nullptr, args[3].get_code() - ); - }); - - gcs.new_command("loop*", "riie", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), 0, args[1].get_int(), args[2].get_int(), - nullptr, args[3].get_code() - ); - }); - - gcs.new_command("loop+*", "riiie", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), args[1].get_int(), args[3].get_int(), - args[2].get_int(), nullptr, args[4].get_code() - ); - }); - - gcs.new_command("loopwhile", "riee", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), 0, args[1].get_int(), 1, - args[2].get_code(), args[3].get_code() - ); - }); - - gcs.new_command("loopwhile+", "riiee", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1, - args[3].get_code(), args[4].get_code() - ); - }); - - gcs.new_command("loopwhile*", "riiee", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), 0, args[2].get_int(), args[1].get_int(), - args[3].get_code(), args[4].get_code() - ); - }); - - gcs.new_command("loopwhile+*", "riiiee", [](auto &cs, auto args, auto &) { - cs_do_loop( - cs, *args[0].get_ident(), args[1].get_int(), args[3].get_int(), - args[2].get_int(), args[4].get_code(), args[5].get_code() - ); - }); - - gcs.new_command("while", "ee", [](auto &cs, auto args, auto &) { - cs_bcode *cond = args[0].get_code(), *body = args[1].get_code(); - while (cs.run(cond).get_bool()) { - switch (cs.run_loop(body)) { - case cs_loop_state::BREAK: - goto end; - default: /* continue and normal */ - break; - } - } -end: - return; - }); - - gcs.new_command("loopconcat", "rie", [](auto &cs, auto args, auto &res) { - cs_loop_conc( - cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1, - args[2].get_code(), true - ); - }); - - gcs.new_command("loopconcat+", "riie", [](auto &cs, auto args, auto &res) { - cs_loop_conc( - cs, res, *args[0].get_ident(), args[1].get_int(), - args[2].get_int(), 1, args[3].get_code(), true - ); - }); - - gcs.new_command("loopconcat*", "riie", [](auto &cs, auto args, auto &res) { - cs_loop_conc( - cs, res, *args[0].get_ident(), 0, args[2].get_int(), - args[1].get_int(), args[3].get_code(), true - ); - }); - - gcs.new_command("loopconcat+*", "riiie", [](auto &cs, auto args, auto &res) { - cs_loop_conc( - cs, res, *args[0].get_ident(), args[1].get_int(), - args[3].get_int(), args[2].get_int(), args[4].get_code(), true - ); - }); - - gcs.new_command("loopconcatword", "rie", [](auto &cs, auto args, auto &res) { - cs_loop_conc( - cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1, - args[2].get_code(), false - ); - }); - - gcs.new_command("loopconcatword+", "riie", []( - auto &cs, auto args, auto &res - ) { - cs_loop_conc( - cs, res, *args[0].get_ident(), args[1].get_int(), - args[2].get_int(), 1, args[3].get_code(), false - ); - }); - - gcs.new_command("loopconcatword*", "riie", []( - auto &cs, auto args, auto &res - ) { - cs_loop_conc( - cs, res, *args[0].get_ident(), 0, args[2].get_int(), - args[1].get_int(), args[3].get_code(), false - ); - }); - - gcs.new_command("loopconcatword+*", "riiie", []( - auto &cs, auto args, auto &res - ) { - cs_loop_conc( - cs, res, *args[0].get_ident(), args[1].get_int(), args[3].get_int(), - args[2].get_int(), args[4].get_code(), false - ); - }); - - gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) { - cs_stacked_value idv{cs, args[0].get_ident()}; - if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) { - return; - } - idv = args[1]; - idv.push(); - cs.run(args[2].get_code(), res); - }); - - gcs.new_command("resetvar", "s", [](auto &cs, auto args, auto &) { - cs.reset_var(args[0].get_str()); - }); - - gcs.new_command("alias", "st", [](auto &cs, auto args, auto &) { - cs.set_alias(args[0].get_str(), args[1]); - }); - - gcs.new_command("getvarmin", "s", [](auto &cs, auto args, auto &res) { - res.set_int(cs.get_var_min_int(args[0].get_str()).value_or(0)); - }); - gcs.new_command("getvarmax", "s", [](auto &cs, auto args, auto &res) { - res.set_int(cs.get_var_max_int(args[0].get_str()).value_or(0)); - }); - gcs.new_command("getfvarmin", "s", [](auto &cs, auto args, auto &res) { - res.set_float(cs.get_var_min_float(args[0].get_str()).value_or(0.0f)); - }); - gcs.new_command("getfvarmax", "s", [](auto &cs, auto args, auto &res) { - res.set_float(cs.get_var_max_float(args[0].get_str()).value_or(0.0f)); - }); - - gcs.new_command("identexists", "s", [](auto &cs, auto args, auto &res) { - res.set_int(cs.have_ident(args[0].get_str())); - }); - - gcs.new_command("getalias", "s", [](auto &cs, auto args, auto &res) { - auto s0 = cs.get_alias_val(args[0].get_str()); - if (s0) { - res.set_str(*s0); - } else { - res.set_str(""); - } - }); -} - -void cs_init_lib_math(cs_state &cs); -void cs_init_lib_string(cs_state &cs); -void cs_init_lib_list(cs_state &cs); - -LIBCUBESCRIPT_EXPORT void cs_state::init_libs(int libs) { - if (libs & CS_LIB_MATH) { - cs_init_lib_math(*this); - } - if (libs & CS_LIB_STRING) { - cs_init_lib_string(*this); - } - if (libs & CS_LIB_LIST) { - cs_init_lib_list(*this); - } -} - } /* namespace cscript */ diff --git a/src/lib_base.cc b/src/lib_base.cc new file mode 100644 index 0000000..e602c10 --- /dev/null +++ b/src/lib_base.cc @@ -0,0 +1,344 @@ +#include + +#include "cs_std.hh" +#include "cs_ident.hh" +#include "cs_vm.hh" // FIXME, only Max Arguments + +namespace cscript { + +static inline void cs_do_loop( + cs_state &cs, cs_ident &id, cs_int offset, cs_int n, cs_int step, + cs_bcode *cond, cs_bcode *body +) { + cs_stacked_value idv{cs, &id}; + if (n <= 0 || !idv.has_alias()) { + return; + } + for (cs_int i = 0; i < n; ++i) { + idv.set_int(offset + i * step); + idv.push(); + if (cond && !cs.run(cond).get_bool()) { + break; + } + switch (cs.run_loop(body)) { + case cs_loop_state::BREAK: + goto end; + default: /* continue and normal */ + break; + } + } +end: + return; +} + +static inline void cs_loop_conc( + cs_state &cs, cs_value &res, cs_ident &id, cs_int offset, cs_int n, + cs_int step, cs_bcode *body, bool space +) { + cs_stacked_value idv{cs, &id}; + if (n <= 0 || !idv.has_alias()) { + return; + } + cs_charbuf s{cs}; + for (cs_int i = 0; i < n; ++i) { + idv.set_int(offset + i * step); + idv.push(); + cs_value v{cs}; + switch (cs.run_loop(body, v)) { + case cs_loop_state::BREAK: + goto end; + case cs_loop_state::CONTINUE: + continue; + default: + break; + } + if (space && i) { + s.push_back(' '); + } + s.append(v.get_str()); + } +end: + res.set_str(s.str()); +} + +void cs_init_lib_base(cs_state &gcs) { + gcs.new_command("error", "s", [](auto &cs, auto args, auto &) { + throw cs_error(cs, args[0].get_str()); + }); + + gcs.new_command("pcall", "err", [](auto &cs, auto args, auto &ret) { + cs_alias *cret = args[1].get_ident()->get_alias(), + *css = args[2].get_ident()->get_alias(); + if (!cret || !css) { + ret.set_int(0); + return; + } + cs_value result{cs}, tback{cs}; + bool rc = true; + try { + cs.run(args[0].get_code(), result); + } catch (cs_error const &e) { + result.set_str(e.what()); + if (e.get_stack().get()) { + cs_charbuf buf{cs}; + cs_print_stack(std::back_inserter(buf), e.get_stack()); + tback.set_str(buf.str()); + } + rc = false; + } + ret.set_int(rc); + static_cast(cret)->set_alias(cs, result); + static_cast(css)->set_alias(cs, tback); + }); + + gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) { + if (args[0].get_bool()) { + res = args[1]; + } else { + res = args[2]; + } + }); + + gcs.new_command("cond", "ee2V", [](auto &cs, auto args, auto &res) { + for (size_t i = 0; i < args.size(); i += 2) { + if ((i + 1) < args.size()) { + if (cs.run(args[i].get_code()).get_bool()) { + cs.run(args[i + 1].get_code(), res); + break; + } + } else { + cs.run(args[i].get_code(), res); + break; + } + } + }); + + gcs.new_command("case", "ite2V", [](auto &cs, auto args, auto &res) { + cs_int val = args[0].get_int(); + for (size_t i = 1; (i + 1) < args.size(); i += 2) { + if ( + (args[i].get_type() == cs_value_type::NONE) || + (args[i].get_int() == val) + ) { + cs.run(args[i + 1].get_code(), res); + return; + } + } + }); + + gcs.new_command("casef", "fte2V", [](auto &cs, auto args, auto &res) { + cs_float val = args[0].get_float(); + for (size_t i = 1; (i + 1) < args.size(); i += 2) { + if ( + (args[i].get_type() == cs_value_type::NONE) || + (args[i].get_float() == val) + ) { + cs.run(args[i + 1].get_code(), res); + return; + } + } + }); + + gcs.new_command("cases", "ste2V", [](auto &cs, auto args, auto &res) { + cs_strref val = args[0].get_str(); + for (size_t i = 1; (i + 1) < args.size(); i += 2) { + if ( + (args[i].get_type() == cs_value_type::NONE) || + (args[i].get_str() == val) + ) { + cs.run(args[i + 1].get_code(), res); + return; + } + } + }); + + gcs.new_command("pushif", "rte", [](auto &cs, auto args, auto &res) { + cs_stacked_value idv{cs, args[0].get_ident()}; + if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) { + return; + } + if (args[1].get_bool()) { + idv = args[1]; + idv.push(); + cs.run(args[2].get_code(), res); + } + }); + + gcs.new_command("loop", "rie", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), 0, args[1].get_int(), 1, nullptr, + args[2].get_code() + ); + }); + + gcs.new_command("loop+", "riie", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1, + nullptr, args[3].get_code() + ); + }); + + gcs.new_command("loop*", "riie", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), 0, args[1].get_int(), args[2].get_int(), + nullptr, args[3].get_code() + ); + }); + + gcs.new_command("loop+*", "riiie", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), args[1].get_int(), args[3].get_int(), + args[2].get_int(), nullptr, args[4].get_code() + ); + }); + + gcs.new_command("loopwhile", "riee", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), 0, args[1].get_int(), 1, + args[2].get_code(), args[3].get_code() + ); + }); + + gcs.new_command("loopwhile+", "riiee", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1, + args[3].get_code(), args[4].get_code() + ); + }); + + gcs.new_command("loopwhile*", "riiee", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), 0, args[2].get_int(), args[1].get_int(), + args[3].get_code(), args[4].get_code() + ); + }); + + gcs.new_command("loopwhile+*", "riiiee", [](auto &cs, auto args, auto &) { + cs_do_loop( + cs, *args[0].get_ident(), args[1].get_int(), args[3].get_int(), + args[2].get_int(), args[4].get_code(), args[5].get_code() + ); + }); + + gcs.new_command("while", "ee", [](auto &cs, auto args, auto &) { + cs_bcode *cond = args[0].get_code(), *body = args[1].get_code(); + while (cs.run(cond).get_bool()) { + switch (cs.run_loop(body)) { + case cs_loop_state::BREAK: + goto end; + default: /* continue and normal */ + break; + } + } +end: + return; + }); + + gcs.new_command("loopconcat", "rie", [](auto &cs, auto args, auto &res) { + cs_loop_conc( + cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1, + args[2].get_code(), true + ); + }); + + gcs.new_command("loopconcat+", "riie", [](auto &cs, auto args, auto &res) { + cs_loop_conc( + cs, res, *args[0].get_ident(), args[1].get_int(), + args[2].get_int(), 1, args[3].get_code(), true + ); + }); + + gcs.new_command("loopconcat*", "riie", [](auto &cs, auto args, auto &res) { + cs_loop_conc( + cs, res, *args[0].get_ident(), 0, args[2].get_int(), + args[1].get_int(), args[3].get_code(), true + ); + }); + + gcs.new_command("loopconcat+*", "riiie", [](auto &cs, auto args, auto &res) { + cs_loop_conc( + cs, res, *args[0].get_ident(), args[1].get_int(), + args[3].get_int(), args[2].get_int(), args[4].get_code(), true + ); + }); + + gcs.new_command("loopconcatword", "rie", [](auto &cs, auto args, auto &res) { + cs_loop_conc( + cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1, + args[2].get_code(), false + ); + }); + + gcs.new_command("loopconcatword+", "riie", []( + auto &cs, auto args, auto &res + ) { + cs_loop_conc( + cs, res, *args[0].get_ident(), args[1].get_int(), + args[2].get_int(), 1, args[3].get_code(), false + ); + }); + + gcs.new_command("loopconcatword*", "riie", []( + auto &cs, auto args, auto &res + ) { + cs_loop_conc( + cs, res, *args[0].get_ident(), 0, args[2].get_int(), + args[1].get_int(), args[3].get_code(), false + ); + }); + + gcs.new_command("loopconcatword+*", "riiie", []( + auto &cs, auto args, auto &res + ) { + cs_loop_conc( + cs, res, *args[0].get_ident(), args[1].get_int(), args[3].get_int(), + args[2].get_int(), args[4].get_code(), false + ); + }); + + gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) { + cs_stacked_value idv{cs, args[0].get_ident()}; + if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) { + return; + } + idv = args[1]; + idv.push(); + cs.run(args[2].get_code(), res); + }); + + gcs.new_command("resetvar", "s", [](auto &cs, auto args, auto &) { + cs.reset_var(args[0].get_str()); + }); + + gcs.new_command("alias", "st", [](auto &cs, auto args, auto &) { + cs.set_alias(args[0].get_str(), args[1]); + }); + + gcs.new_command("getvarmin", "s", [](auto &cs, auto args, auto &res) { + res.set_int(cs.get_var_min_int(args[0].get_str()).value_or(0)); + }); + gcs.new_command("getvarmax", "s", [](auto &cs, auto args, auto &res) { + res.set_int(cs.get_var_max_int(args[0].get_str()).value_or(0)); + }); + gcs.new_command("getfvarmin", "s", [](auto &cs, auto args, auto &res) { + res.set_float(cs.get_var_min_float(args[0].get_str()).value_or(0.0f)); + }); + gcs.new_command("getfvarmax", "s", [](auto &cs, auto args, auto &res) { + res.set_float(cs.get_var_max_float(args[0].get_str()).value_or(0.0f)); + }); + + gcs.new_command("identexists", "s", [](auto &cs, auto args, auto &res) { + res.set_int(cs.have_ident(args[0].get_str())); + }); + + gcs.new_command("getalias", "s", [](auto &cs, auto args, auto &res) { + auto s0 = cs.get_alias_val(args[0].get_str()); + if (s0) { + res.set_str(*s0); + } else { + res.set_str(""); + } + }); +} + +} /* namespace cscript */ diff --git a/src/meson.build b/src/meson.build index 9960f48..855a2c5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -15,6 +15,7 @@ libcubescript_src = [ 'cs_val.cc', 'cs_vm.cc', 'cubescript.cc', + 'lib_base.cc', 'lib_list.cc', 'lib_math.cc', 'lib_str.cc'