diff --git a/include/cubescript/cubescript/callable.hh b/include/cubescript/cubescript/callable.hh index e7ab86f..24a8dd7 100644 --- a/include/cubescript/cubescript/callable.hh +++ b/include/cubescript/cubescript/callable.hh @@ -31,7 +31,7 @@ private: base() {} virtual ~base() {} virtual void move_to(base *) = 0; - virtual R operator()(A &&...args) = 0; + virtual R operator()(A &&...args) const = 0; }; template @@ -42,9 +42,9 @@ private: ::new (p) store{std::move(p_stor)}; } - virtual R operator()(A &&...args) { + virtual R operator()(A &&...args) const { return std::invoke(*std::launder( - reinterpret_cast(&p_stor) + reinterpret_cast(&p_stor) ), std::forward(args)...); } @@ -184,25 +184,25 @@ public: f.p_func = as_base(&f.p_stor); } else if (small_storage()) { /* copy allocator address/size */ - memcpy(&tmp_stor, &f.p_stor, sizeof(tmp_stor)); + std::memcpy(&tmp_stor, &f.p_stor, sizeof(tmp_stor)); p_func->move_to(as_base(&f.p_stor)); p_func->~base(); p_func = f.p_func; f.p_func = as_base(&f.p_stor); - memcpy(&p_stor, &tmp_stor, sizeof(tmp_stor)); + std::memcpy(&p_stor, &tmp_stor, sizeof(tmp_stor)); } else if (f.small_storage()) { /* copy allocator address/size */ - memcpy(&tmp_stor, &p_stor, sizeof(tmp_stor)); + std::memcpy(&tmp_stor, &p_stor, sizeof(tmp_stor)); f.p_func->move_to(as_base(&p_stor)); f.p_func->~base(); f.p_func = p_func; p_func = as_base(&p_stor); - memcpy(&f.p_stor, &tmp_stor, sizeof(tmp_stor)); + std::memcpy(&f.p_stor, &tmp_stor, sizeof(tmp_stor)); } else { /* copy allocator address/size */ - memcpy(&tmp_stor, &p_stor, sizeof(tmp_stor)); - memcpy(&p_stor, &f.p_stor, sizeof(tmp_stor)); - memcpy(&f.p_stor, &tmp_stor, sizeof(tmp_stor)); + std::memcpy(&tmp_stor, &p_stor, sizeof(tmp_stor)); + std::memcpy(&p_stor, &f.p_stor, sizeof(tmp_stor)); + std::memcpy(&f.p_stor, &tmp_stor, sizeof(tmp_stor)); std::swap(p_func, f.p_func); } } @@ -211,7 +211,7 @@ public: return !!p_func; } - R operator()(A ...args) { + R operator()(A ...args) const { return (*p_func)(std::forward(args)...); } }; diff --git a/include/cubescript/cubescript/ident.hh b/include/cubescript/cubescript/ident.hh index b32e59c..1eb7a1a 100644 --- a/include/cubescript/cubescript/ident.hh +++ b/include/cubescript/cubescript/ident.hh @@ -132,10 +132,26 @@ struct LIBCUBESCRIPT_EXPORT ident { */ bool is_persistent(state &cs) const; + /** @brief Call the ident. + * + * The default implementation just throws a cubescript::error, since it + * is not callable. It can be overridden as needed. + * + * If a command, it will simply be executed with the given arguments, + * ensuring that missing ones are filled in and types are set properly. + * If a builtin variable, the appropriate handler will be called. If + * an alias, the value of it will be compiled and executed. Any other + * ident type will simply do nothing. + * + * @return the return value + */ + virtual any_value call(span_type args, state &cs); + protected: friend struct ident_p; ident() = default; + virtual ~ident(); struct ident_impl *p_impl{}; }; @@ -195,6 +211,16 @@ struct LIBCUBESCRIPT_EXPORT global_var: ident { */ void save(state &cs); + /** @brief Call the variable. + * + * While variables are not callable by themselves, this acts like + * if calling the variable in the language. By default, that means + * doing it with zero arguments retrieves its value, while passing + * arguments will set its value. The actual semantics depend on how + * the handler is set up for each variable type. + */ + any_value call(span_type args, state &cs); + protected: global_var() = default; }; @@ -229,6 +255,9 @@ struct LIBCUBESCRIPT_EXPORT integer_var: global_var { */ void set_raw_value(integer_type val); + /** @brief Call override for integer vars. */ + any_value call(span_type args, state &cs); + protected: integer_var() = default; }; @@ -263,6 +292,9 @@ struct LIBCUBESCRIPT_EXPORT float_var: global_var { */ void set_raw_value(float_type val); + /** @brief Call override for float vars. */ + any_value call(span_type args, state &cs); + protected: float_var() = default; }; @@ -297,6 +329,9 @@ struct LIBCUBESCRIPT_EXPORT string_var: global_var { */ void set_raw_value(string_ref val); + /** @brief Call override for string vars. */ + any_value call(span_type args, state &cs); + protected: string_var() = default; }; @@ -324,6 +359,12 @@ struct LIBCUBESCRIPT_EXPORT alias: ident { /** @brief Set the value of the alias for the given thread. */ void set_value(state &cs, any_value v); + /** @brief Call an alias. + * + * The alias will be called like if it was called in the language. + */ + any_value call(span_type args, state &cs); + protected: alias() = default; }; @@ -345,6 +386,12 @@ struct LIBCUBESCRIPT_EXPORT command: ident { */ int get_num_args() const; + /** @brief Call a command. + * + * The command will be called like if it was called in the language. + */ + any_value call(span_type args, state &cs); + protected: command() = default; }; diff --git a/include/cubescript/cubescript/state.hh b/include/cubescript/cubescript/state.hh index 2c8c013..16e171b 100644 --- a/include/cubescript/cubescript/state.hh +++ b/include/cubescript/cubescript/state.hh @@ -71,16 +71,6 @@ using command_func = internal::callable< void, state &, span_type, any_value & >; -/** @brief The loop state - * - * This is returned by state::call_loop(). - */ -enum class loop_state { - NORMAL = 0, /**< @brief The iteration ended normally. */ - BREAK, /**< @brief The iteration was broken out of. */ - CONTINUE /**< @brief The iteration ended early. */ -}; - /** @brief The Cubescript thread * * Represents a Cubescript thread, either the main thread or a side thread @@ -377,59 +367,17 @@ struct LIBCUBESCRIPT_EXPORT state { /** @brief Get a span of all idents */ span_type get_idents() const; - /** @brief Execute the given bytecode reference + /** @brief Compile a string. * - * @return the return value + * This compiles the given string, optionally using `source` as a filename + * for debug information (useful when implementing file I/O functions). + * + * @return a bytecode reference + * @throw cubescript::error on compilation failure */ - any_value call(bcode_ref const &code); - - /** @brief Execute the given string as code - * - * @return the return value - */ - any_value call(std::string_view code); - - /** @brief Execute the given string as code - * - * This variant takes a file name to be included in debug information. - * While the library provides no way to deal with file I/O, this is a - * support function to make implementing these better. - * - * @param source a source file name - * - * @return the return value - */ - any_value call(std::string_view code, std::string_view source); - - /** @brief Execute the given ident - * - * If a command, it will simply be executed with the given arguments, - * ensuring that missing ones are filled in and types are set properly. - * If a builtin variable, the appropriate handler will be called. If - * an alias, the value of it will be compiled and executed. Any other - * ident type will simply do nothing. - * - * @return the return value - */ - any_value call(ident &id, span_type args); - - /** @brief Execute a loop body - * - * This exists to implement custom loop commands. A loop command will - * consist of your desired loop and will take a body as an argument - * (with bytecode type); this body will be run using this API. The - * return value can be used to check if the loop was broken out of - * or continued, and take steps accordingly. - * - * Some loops may evaluate to values, while others may not. - */ - loop_state call_loop(bcode_ref const &code, any_value &ret); - - /** @brief Execute a loop body - * - * This version ignores the return value of the body. - */ - loop_state call_loop(bcode_ref const &code); + bcode_ref compile( + std::string_view v, std::string_view source = std::string_view{} + ); /** @brief Get if the thread is in override mode * diff --git a/include/cubescript/cubescript/value.hh b/include/cubescript/cubescript/value.hh index 316e78b..bda79c9 100644 --- a/include/cubescript/cubescript/value.hh +++ b/include/cubescript/cubescript/value.hh @@ -20,6 +20,17 @@ namespace cubescript { struct ident; +struct any_value; + +/** @brief The loop state + * + * This is returned by state::call_loop(). + */ +enum class loop_state { + NORMAL = 0, /**< @brief The iteration ended normally. */ + BREAK, /**< @brief The iteration was broken out of. */ + CONTINUE /**< @brief The iteration ended early. */ +}; /** @brief Bytecode reference. * @@ -100,6 +111,30 @@ struct LIBCUBESCRIPT_EXPORT bcode_ref { */ explicit operator bool() const; + /** @brief Execute the bytecode + * + * @return the return value + */ + any_value call(state &cs) const; + + /** @brief Execute the bytecode as a loop body + * + * This exists to implement custom loop commands. A loop command will + * consist of your desired loop and will take a body as an argument + * (with bytecode type); this body will be run using this API. The + * return value can be used to check if the loop was broken out of + * or continued, and take steps accordingly. + * + * Some loops may evaluate to values, while others may not. + */ + loop_state call_loop(state &cs, any_value &ret) const; + + /** @brief Execute the byctecode as a loop body + * + * This version ignores the return value of the body. + */ + loop_state call_loop(state &cs) const; + private: friend struct bcode_p; @@ -447,11 +482,13 @@ struct LIBCUBESCRIPT_EXPORT any_value { * * If the contained value is already bytecode, nothing happens. Otherwise * the value is converted to a string (like get_string()) and this string - * is compiled as bytecode. + * is compiled as bytecode (as if using state::compile()) * * @return A bytecode reference. */ - bcode_ref force_code(state &cs); + bcode_ref force_code( + state &cs, std::string_view source = std::string_view{} + ); /** @brief Force the type to value_type::IDENT. * diff --git a/src/cs_bcode.cc b/src/cs_bcode.cc index 086d87a..511f655 100644 --- a/src/cs_bcode.cc +++ b/src/cs_bcode.cc @@ -1,5 +1,6 @@ #include "cs_bcode.hh" #include "cs_state.hh" +#include "cs_vm.hh" namespace cubescript { @@ -45,6 +46,37 @@ LIBCUBESCRIPT_EXPORT bcode_ref::operator bool() const { return p_code != nullptr; } +LIBCUBESCRIPT_EXPORT any_value bcode_ref::call(state &cs) const { + any_value ret{}; + vm_exec(state_p{cs}.ts(), p_code->get_raw(), ret); + return ret; +} + +LIBCUBESCRIPT_EXPORT loop_state bcode_ref::call_loop( + state &cs, any_value &ret +) const { + auto &ts = state_p{cs}.ts(); + ++ts.loop_level; + try { + ret = call(cs); + } catch (break_exception) { + --ts.loop_level; + return loop_state::BREAK; + } catch (continue_exception) { + --ts.loop_level; + return loop_state::CONTINUE; + } catch (...) { + --ts.loop_level; + throw; + } + return loop_state::NORMAL; +} + +LIBCUBESCRIPT_EXPORT loop_state bcode_ref::call_loop(state &cs) const { + any_value ret{}; + return call_loop(cs, ret); +} + /* private funcs */ struct bcode_hdr { diff --git a/src/cs_ident.cc b/src/cs_ident.cc index b50db78..d14f3a5 100644 --- a/src/cs_ident.cc +++ b/src/cs_ident.cc @@ -2,6 +2,7 @@ #include "cs_bcode.hh" #include "cs_thread.hh" +#include "cs_vm.hh" namespace cubescript { @@ -106,7 +107,7 @@ void svar_impl::save_val() { void command_impl::call( thread_state &ts, span_type args, any_value &ret -) { +) const { auto idstsz = ts.idstack.size(); try { p_cb_cftv(*ts.pstate, args, ret); @@ -117,7 +118,7 @@ void command_impl::call( ts.idstack.resize(idstsz); } -bool ident_is_used_arg(ident *id, thread_state &ts) { +bool ident_is_used_arg(ident const *id, thread_state &ts) { if (!ts.callstack) { return true; } @@ -155,6 +156,8 @@ void alias_stack::set_alias(alias *a, thread_state &ts, any_value &v) { /* public interface */ +LIBCUBESCRIPT_EXPORT ident::~ident() {} + LIBCUBESCRIPT_EXPORT ident_type ident::get_type() const { if (p_impl->p_type > ID_ALIAS) { return ident_type::SPECIAL; @@ -246,6 +249,10 @@ LIBCUBESCRIPT_EXPORT bool ident::is_persistent(state &cs) const { return false; } +LIBCUBESCRIPT_EXPORT any_value ident::call(span_type, state &cs) { + throw error{cs, "this ident type is not callable"}; +} + LIBCUBESCRIPT_EXPORT bool global_var::is_read_only() const { return (p_impl->p_flags & IDENT_FLAG_READONLY); } @@ -282,6 +289,12 @@ LIBCUBESCRIPT_EXPORT void global_var::save(state &cs) { } } +LIBCUBESCRIPT_EXPORT any_value global_var::call( + span_type args, state &cs +) { + return ident::call(args, cs); +} + LIBCUBESCRIPT_EXPORT integer_type integer_var::get_value() const { return static_cast(this)->p_storage; } @@ -308,6 +321,32 @@ LIBCUBESCRIPT_EXPORT void integer_var::set_raw_value(integer_type val) { static_cast(this)->p_storage = val; } +inline any_value call_var( + ident &id, command *hid, span_type &args, state &cs +) { + any_value ret{}; + auto &ts = state_p{cs}.ts(); + auto *cimp = static_cast(hid); + auto &targs = ts.vmstack; + auto osz = targs.size(); + auto anargs = std::size_t(cimp->get_num_args()); + auto nargs = args.size(); + targs.resize( + osz + std::max(args.size(), anargs + 1) + ); + for (std::size_t i = 0; i < nargs; ++i) { + targs[osz + i + 1] = args[i]; + } + exec_command(ts, cimp, &id, &targs[osz], ret, nargs + 1, false); + return ret; +} + +LIBCUBESCRIPT_EXPORT any_value integer_var::call( + span_type args, state &cs +) { + return call_var(*this, state_p{cs}.ts().istate->cmd_ivar, args, cs); +} + LIBCUBESCRIPT_EXPORT float_type float_var::get_value() const { return static_cast(this)->p_storage; } @@ -334,6 +373,12 @@ LIBCUBESCRIPT_EXPORT void float_var::set_raw_value(float_type val) { static_cast(this)->p_storage = val; } +LIBCUBESCRIPT_EXPORT any_value float_var::call( + span_type args, state &cs +) { + return call_var(*this, state_p{cs}.ts().istate->cmd_fvar, args, cs); +} + LIBCUBESCRIPT_EXPORT string_ref string_var::get_value() const { return static_cast(this)->p_storage; } @@ -360,6 +405,12 @@ LIBCUBESCRIPT_EXPORT void string_var::set_raw_value(string_ref val) { static_cast(this)->p_storage = val; } +LIBCUBESCRIPT_EXPORT any_value string_var::call( + span_type args, state &cs +) { + return call_var(*this, state_p{cs}.ts().istate->cmd_svar, args, cs); +} + LIBCUBESCRIPT_EXPORT any_value alias::get_value(state &cs) const { return state_p{cs}.ts().get_astack(this).node->val_s; } @@ -377,6 +428,19 @@ LIBCUBESCRIPT_EXPORT bool alias::is_arg() const { return (static_cast(this)->p_flags & IDENT_FLAG_ARG); } +LIBCUBESCRIPT_EXPORT any_value alias::call( + span_type args, state &cs +) { + any_value ret{}; + auto &ts = state_p{cs}.ts(); + if (is_arg() && !ident_is_used_arg(this, ts)) { + return ret; + } + auto nargs = args.size(); + exec_alias(ts, this, &args[0], ret, nargs, nargs, 0, 0, BC_RET_NULL, true); + return ret; +} + LIBCUBESCRIPT_EXPORT std::string_view command::get_args() const { return static_cast(this)->p_cargs; } @@ -385,6 +449,31 @@ LIBCUBESCRIPT_EXPORT int command::get_num_args() const { return static_cast(this)->p_numargs; } +LIBCUBESCRIPT_EXPORT any_value command::call( + span_type args, state &cs +) { + any_value ret{}; + auto &cimpl = static_cast(*this); + if (!cimpl.p_cb_cftv) { + return ret; + } + auto nargs = args.size(); + auto &ts = state_p{cs}.ts(); + if (nargs < std::size_t(cimpl.get_num_args())) { + stack_guard s{ts}; /* restore after call */ + auto &targs = ts.vmstack; + auto osz = targs.size(); + targs.resize(osz + cimpl.get_num_args()); + for (std::size_t i = 0; i < nargs; ++i) { + targs[osz + i] = args[i]; + } + exec_command(ts, &cimpl, this, &targs[osz], ret, nargs, false); + } else { + exec_command(ts, &cimpl, this, &args[0], ret, nargs, false); + } + return ret; +} + /* external API for alias stack management */ LIBCUBESCRIPT_EXPORT alias_local::alias_local(state &cs, ident &a) { diff --git a/src/cs_ident.hh b/src/cs_ident.hh index d8a676c..eed5c1b 100644 --- a/src/cs_ident.hh +++ b/src/cs_ident.hh @@ -44,7 +44,7 @@ struct alias_stack { }; struct ident_link { - ident *id; + ident const *id; ident_link *next; std::bitset usedargs; }; @@ -126,14 +126,16 @@ struct command_impl: ident_impl, command { string_ref name, string_ref args, int numargs, command_func func ); - void call(thread_state &ts, span_type args, any_value &ret); + void call( + thread_state &ts, span_type args, any_value &ret + ) const; string_ref p_cargs; command_func p_cb_cftv; int p_numargs; }; -bool ident_is_used_arg(ident *id, thread_state &ts); +bool ident_is_used_arg(ident const *id, thread_state &ts); struct ident_p { ident_p(ident &id): ip{&id} {} diff --git a/src/cs_state.cc b/src/cs_state.cc index 620f5c1..bcfa0d1 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -173,19 +173,19 @@ state::state(alloc_func func, void *data) { /* builtins */ p = &new_command("do", "b", [](auto &cs, auto args, auto &res) { - res = cs.call(args[0].get_code()); + res = args[0].get_code().call(cs); }); static_cast(p)->p_type = ID_DO; p = &new_command("doargs", "b", [](auto &cs, auto args, auto &res) { call_with_args(*cs.p_tstate, [&cs, &res, &args]() { - res = cs.call(args[0].get_code()); + res = args[0].get_code().call(cs); }); }); static_cast(p)->p_type = ID_DOARGS; p = &new_command("if", "abb", [](auto &cs, auto args, auto &res) { - res = cs.call((args[0].get_bool() ? args[1] : args[2]).get_code()); + res = (args[0].get_bool() ? args[1] : args[2]).get_code().call(cs); }); static_cast(p)->p_type = ID_IF; @@ -206,7 +206,7 @@ state::state(alloc_func func, void *data) { for (size_t i = 0; i < args.size(); ++i) { auto code = args[i].get_code(); if (code) { - res = cs.call(code); + res = code.call(cs); } else { res = std::move(args[i]); } @@ -225,7 +225,7 @@ state::state(alloc_func func, void *data) { for (size_t i = 0; i < args.size(); ++i) { auto code = args[i].get_code(); if (code) { - res = cs.call(code); + res = code.call(cs); } else { res = std::move(args[i]); } @@ -485,7 +485,7 @@ LIBCUBESCRIPT_EXPORT void state::assign_value( case ident_type::IVAR: case ident_type::FVAR: case ident_type::SVAR: - call(id->get(), span_type{&v, 1}); + id->get().call(span_type{&v, 1}, *this); break; default: throw error{ @@ -693,154 +693,12 @@ do_add: return *cmd; } -LIBCUBESCRIPT_EXPORT any_value state::call(bcode_ref const &code) { - any_value ret{}; - vm_exec(*p_tstate, bcode_p{code}.get()->get_raw(), ret); - return ret; -} - -static any_value do_call( - thread_state &ts, std::string_view file, std::string_view code +LIBCUBESCRIPT_EXPORT bcode_ref state::compile( + std::string_view v, std::string_view source ) { - any_value ret{}; - gen_state gs{ts}; - gs.gen_main(code, file); - auto cref = gs.steal_ref(); - vm_exec(ts, bcode_p{cref}.get()->get_raw(), ret); - return ret; -} - -LIBCUBESCRIPT_EXPORT any_value state::call(std::string_view code) { - return do_call(*p_tstate, std::string_view{}, code); -} - -LIBCUBESCRIPT_EXPORT any_value state::call( - std::string_view code, std::string_view source -) { - return do_call(*p_tstate, source, code); -} - -LIBCUBESCRIPT_EXPORT any_value state::call( - ident &id, span_type args -) { - any_value ret{}; - std::size_t nargs = args.size(); - call_depth_guard level{*p_tstate}; /* incr and decr on scope exit */ - switch (id.get_type()) { - default: - if (!ident_is_callable(&id)) { - break; - } - /* fallthrough */ - case ident_type::COMMAND: { - auto &cimpl = static_cast(id); - if (nargs < std::size_t(cimpl.get_num_args())) { - stack_guard s{*p_tstate}; /* restore after call */ - auto &targs = p_tstate->vmstack; - auto osz = targs.size(); - targs.resize(osz + cimpl.get_num_args()); - for (std::size_t i = 0; i < nargs; ++i) { - targs[osz + i] = args[i]; - } - exec_command( - *p_tstate, &cimpl, &id, &targs[osz], ret, nargs, false - ); - } else { - exec_command( - *p_tstate, &cimpl, &id, &args[0], ret, nargs, false - ); - } - nargs = 0; - break; - } - case ident_type::IVAR: { - auto *hid = p_tstate->istate->cmd_ivar; - auto *cimp = static_cast(hid); - auto &targs = p_tstate->vmstack; - auto osz = targs.size(); - auto anargs = std::size_t(cimp->get_num_args()); - targs.resize( - osz + std::max(args.size(), anargs + 1) - ); - for (std::size_t i = 0; i < nargs; ++i) { - targs[osz + i + 1] = args[i]; - } - exec_command( - *p_tstate, cimp, &id, &targs[osz], ret, nargs + 1, false - ); - break; - } - case ident_type::FVAR: { - auto *hid = p_tstate->istate->cmd_fvar; - auto *cimp = static_cast(hid); - auto &targs = p_tstate->vmstack; - auto osz = targs.size(); - auto anargs = std::size_t(cimp->get_num_args()); - targs.resize( - osz + std::max(args.size(), anargs + 1) - ); - for (std::size_t i = 0; i < nargs; ++i) { - targs[osz + i + 1] = args[i]; - } - exec_command( - *p_tstate, cimp, &id, &targs[osz], ret, nargs + 1, false - ); - break; - } - case ident_type::SVAR: { - auto *hid = p_tstate->istate->cmd_svar; - auto *cimp = static_cast(hid); - auto &targs = p_tstate->vmstack; - auto osz = targs.size(); - auto anargs = std::size_t(cimp->get_num_args()); - targs.resize( - osz + std::max(args.size(), anargs + 1) - ); - for (std::size_t i = 0; i < nargs; ++i) { - targs[osz + i + 1] = args[i]; - } - exec_command( - *p_tstate, cimp, &id, &targs[osz], ret, nargs + 1, false - ); - break; - } - case ident_type::ALIAS: { - alias &a = static_cast(id); - if (a.is_arg() && !ident_is_used_arg(&a, *p_tstate)) { - break; - } - exec_alias( - *p_tstate, &a, &args[0], ret, nargs, nargs, 0, 0, - BC_RET_NULL, true - ); - break; - } - } - return ret; -} - -LIBCUBESCRIPT_EXPORT loop_state state::call_loop( - bcode_ref const &code, any_value &ret -) { - ++p_tstate->loop_level; - try { - ret = call(code); - } catch (break_exception) { - --p_tstate->loop_level; - return loop_state::BREAK; - } catch (continue_exception) { - --p_tstate->loop_level; - return loop_state::CONTINUE; - } catch (...) { - --p_tstate->loop_level; - throw; - } - return loop_state::NORMAL; -} - -LIBCUBESCRIPT_EXPORT loop_state state::call_loop(bcode_ref const &code) { - any_value ret{}; - return call_loop(code, ret); + gen_state gs{*p_tstate}; + gs.gen_main(v, source); + return gs.steal_ref(); } LIBCUBESCRIPT_EXPORT bool state::get_override_mode() const { diff --git a/src/cs_thread.cc b/src/cs_thread.cc index 2304902..8477a65 100644 --- a/src/cs_thread.cc +++ b/src/cs_thread.cc @@ -15,17 +15,16 @@ hook_func thread_state::set_hook(hook_func f) { return hk; } -alias_stack &thread_state::get_astack(alias *a) { +alias_stack &thread_state::get_astack(alias const *a) { auto it = astacks.try_emplace(a->get_index()); if (it.second) { - it.first->second.node = &static_cast(a)->p_initial; - it.first->second.flags = static_cast(a)->p_flags; + auto *imp = const_cast( + static_cast(a) + ); + it.first->second.node = &imp->p_initial; + it.first->second.flags = imp->p_flags; } return it.first->second; } -alias_stack const &thread_state::get_astack(alias const *a) { - return get_astack(const_cast(a)); -} - } /* namespace cubescript */ diff --git a/src/cs_thread.hh b/src/cs_thread.hh index e50dbe1..e64605a 100644 --- a/src/cs_thread.hh +++ b/src/cs_thread.hh @@ -52,8 +52,7 @@ struct thread_state { hook_func &get_hook() { return call_hook; } hook_func const &get_hook() const { return call_hook; } - alias_stack &get_astack(alias *a); - alias_stack const &get_astack(alias const *a); + alias_stack &get_astack(alias const *a); }; } /* namespace cubescript */ diff --git a/src/cs_val.cc b/src/cs_val.cc index b94081b..22d16d9 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -246,7 +246,7 @@ std::string_view any_value::force_string(state &cs) { return str_managed_view(csv_get(&p_stor)); } -bcode_ref any_value::force_code(state &cs) { +bcode_ref any_value::force_code(state &cs, std::string_view source) { switch (get_type()) { case value_type::CODE: return bcode_p::make_ref(csv_get(&p_stor)); @@ -254,7 +254,7 @@ bcode_ref any_value::force_code(state &cs) { break; } gen_state gs{state_p{cs}.ts()}; - gs.gen_main(get_string(cs)); + gs.gen_main(get_string(cs), source); auto bc = gs.steal_ref(); set_code(bc); return bc; diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 9e66f40..2d994ad 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -114,9 +114,7 @@ void exec_command( break; case '.': i = std::max(i + 1, numargs); - static_cast(id)->call( - ts, span_type{args, std::size_t(i)}, res - ); + id->call(ts, span_type{args, std::size_t(i)}, res); return; case '1': case '2': @@ -130,9 +128,7 @@ void exec_command( } } ++i; - static_cast(id)->call( - ts, span_type{args, std::size_t(i)}, res - ); + id->call(ts, span_type{args, std::size_t(i)}, res); res.force_plain(); } @@ -458,7 +454,7 @@ std::uint32_t *vm_exec( call_with_args(ts, [&]() { auto v = std::move(args.back()); args.pop_back(); - result = cs.call(v.get_code()); + result = v.get_code().call(cs); force_arg(cs, result, op & BC_INST_RET_MASK); }); continue; @@ -469,7 +465,7 @@ std::uint32_t *vm_exec( case BC_INST_DO | BC_RET_FLOAT: { auto v = std::move(args.back()); args.pop_back(); - result = cs.call(v.get_code()); + result = v.get_code().call(cs); force_arg(cs, result, op & BC_INST_RET_MASK); continue; } @@ -500,7 +496,7 @@ std::uint32_t *vm_exec( auto v = std::move(args.back()); args.pop_back(); if (v.get_type() == value_type::CODE) { - result = cs.call(v.get_code()); + result = v.get_code().call(cs); } else { result = std::move(v); } @@ -514,7 +510,7 @@ std::uint32_t *vm_exec( auto v = std::move(args.back()); args.pop_back(); if (v.get_type() == value_type::CODE) { - result = cs.call(v.get_code()); + result = v.get_code().call(cs); } else { result = std::move(v); } diff --git a/src/lib_base.cc b/src/lib_base.cc index 3ebf0c5..59ca7c7 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -20,10 +20,10 @@ static inline void do_loop( for (integer_type i = 0; i < n; ++i) { idv.set_integer(offset + i * step); st.set(idv); - if (cond && !cs.call(cond).get_bool()) { + if (cond && !cond.call(cs).get_bool()) { break; } - switch (cs.call_loop(body)) { + switch (body.call_loop(cs)) { case loop_state::BREAK: return; default: /* continue and normal */ @@ -46,7 +46,7 @@ static inline void do_loop_conc( idv.set_integer(offset + i * step); st.set(idv); any_value v{}; - switch (cs.call_loop(body, v)) { + switch (body.call_loop(cs, v)) { case loop_state::BREAK: goto end; case loop_state::CONTINUE: @@ -80,7 +80,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { any_value result{}, tback{}; bool rc = true; try { - result = cs.call(args[0].get_code()); + result = args[0].get_code().call(cs); } catch (error const &e) { result.set_string(e.what(), cs); if (e.get_stack().get()) { @@ -109,12 +109,12 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { new_cmd_quiet(gcs, "cond", "bb2...", [](auto &cs, auto args, auto &res) { for (size_t i = 0; i < args.size(); i += 2) { if ((i + 1) < args.size()) { - if (cs.call(args[i].get_code()).get_bool()) { - res = cs.call(args[i + 1].get_code()); + if (args[i].get_code().call(cs).get_bool()) { + res = args[i + 1].get_code().call(cs); break; } } else { - res = cs.call(args[i].get_code()); + res = args[i].get_code().call(cs); break; } } @@ -127,7 +127,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { (args[i].get_type() == value_type::NONE) || (args[i].get_integer() == val) ) { - res = cs.call(args[i + 1].get_code()); + res = args[i + 1].get_code().call(cs); return; } } @@ -140,7 +140,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { (args[i].get_type() == value_type::NONE) || (args[i].get_float() == val) ) { - res = cs.call(args[i + 1].get_code()); + res = args[i + 1].get_code().call(cs); return; } } @@ -153,7 +153,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { (args[i].get_type() == value_type::NONE) || (args[i].get_string(cs) == val) ) { - res = cs.call(args[i + 1].get_code()); + res = args[i + 1].get_code().call(cs); return; } } @@ -166,7 +166,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } if (args[1].get_bool()) { st.set(args[1]); - res = cs.call(args[2].get_code()); + res = args[2].get_code().call(cs); } }); @@ -233,8 +233,8 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { new_cmd_quiet(gcs, "while", "bb", [](auto &cs, auto args, auto &) { auto cond = args[0].get_code(); auto body = args[1].get_code(); - while (cs.call(cond).get_bool()) { - switch (cs.call_loop(body)) { + while (cond.call(cs).get_bool()) { + switch (body.call_loop(cs)) { case loop_state::BREAK: goto end; default: /* continue and normal */ @@ -325,7 +325,7 @@ end: throw error{cs, "cannot push an argument"}; } st.set(args[1]); - res = cs.call(args[2].get_code()); + res = args[2].get_code().call(cs); }); new_cmd_quiet(gcs, "resetvar", "s", [](auto &cs, auto args, auto &) { diff --git a/src/lib_list.cc b/src/lib_list.cc index e192567..cd433ab 100644 --- a/src/lib_list.cc +++ b/src/lib_list.cc @@ -87,7 +87,7 @@ static void loop_list_conc( r.push_back(' '); } any_value v{}; - switch (cs.call_loop(body, v)) { + switch (body.call_loop(cs, v)) { case loop_state::BREAK: goto end; case loop_state::CONTINUE: @@ -213,7 +213,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { ++n; idv.set_string(p.get_raw_item(), cs); st.set(std::move(idv)); - if (cs.call(body).get_bool()) { + if (body.call(cs).get_bool()) { res.set_integer(integer_type(n)); return; } @@ -230,7 +230,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { ++n; idv.set_string(p.get_raw_item(), cs); st.set(std::move(idv)); - if (cs.call(body).get_bool()) { + if (body.call(cs).get_bool()) { if (p.parse()) { res.set_string(p.get_item()); } @@ -294,7 +294,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) { idv.set_string(p.get_item()); st.set(std::move(idv)); - switch (cs.call_loop(body)) { + switch (body.call_loop(cs)) { case loop_state::BREAK: return; default: /* continue and normal */ @@ -318,7 +318,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { idv.set_string("", cs); } st2.set(std::move(idv)); - switch (cs.call_loop(body)) { + switch (body.call_loop(cs)) { case loop_state::BREAK: return; default: /* continue and normal */ @@ -349,7 +349,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { idv.set_string("", cs); } st3.set(std::move(idv)); - switch (cs.call_loop(body)) { + switch (body.call_loop(cs)) { case loop_state::BREAK: return; default: /* continue and normal */ @@ -387,7 +387,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) { idv.set_string(p.get_raw_item(), cs); st.set(std::move(idv)); - if (cs.call(body).get_bool()) { + if (body.call(cs).get_bool()) { if (r.size()) { r.push_back(' '); } @@ -405,7 +405,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) { idv.set_string(p.get_raw_item(), cs); st.set(std::move(idv)); - if (cs.call(body).get_bool()) { + if (body.call(cs).get_bool()) { r++; } } @@ -525,7 +525,7 @@ struct ListSortFun { xst.set(std::move(v)); v.set_string(yval.str, cs); yst.set(std::move(v)); - return cs.call(*body).get_bool(); + return body->call(cs).get_bool(); } }; diff --git a/tests/runner.cc b/tests/runner.cc index 4d71b75..b329592 100644 --- a/tests/runner.cc +++ b/tests/runner.cc @@ -38,7 +38,7 @@ static bool do_exec_file(cs::state &cs, char const *fname) { buf[len] = '\0'; - cs.call(std::string_view{buf.get(), std::size_t(len)}, fname); + cs.compile(std::string_view{buf.get(), std::size_t(len)}, fname).call(cs); return true; } @@ -62,7 +62,7 @@ int main(int argc, char **argv) { gcs.new_command("assert", "ss#", [](auto &s, auto args, auto &ret) { auto val = args[0]; val.force_code(s); - if (!s.call(val.get_code()).get_bool()) { + if (!val.get_code().call(s).get_bool()) { if (args[2].get_integer() > 1) { throw cs::error{ s, "assertion failed: [%s] (%s)", diff --git a/tools/repl.cc b/tools/repl.cc index 43c031f..260c6c3 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -214,7 +214,9 @@ static bool do_exec_file( buf[len] = '\0'; - ret = cs.call(std::string_view{buf.get(), std::size_t(len)}, fname); + ret = cs.compile( + std::string_view{buf.get(), std::size_t(len)}, fname + ).call(cs); return true; } @@ -228,7 +230,7 @@ static bool do_call(cs::state &cs, std::string_view line, bool file = false) { std::fprintf(stderr, "cannot read file: %s\n", line.data()); } } else { - ret = cs.call(line); + ret = cs.compile(line).call(cs); } } catch (cs::error const &e) { signal(SIGINT, SIG_DFL);