remove call() methods from state

master
Daniel Kolesa 2021-05-02 22:44:38 +02:00
parent 4dd1518f6c
commit 5b54c74f2a
16 changed files with 289 additions and 280 deletions

View File

@ -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<typename F>
@ -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<F *>(&p_stor)
reinterpret_cast<F const *>(&p_stor)
), std::forward<A>(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<A>(args)...);
}
};

View File

@ -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<any_value> 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<any_value> 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<any_value> 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<any_value> 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<any_value> 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<any_value> 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<any_value> args, state &cs);
protected:
command() = default;
};

View File

@ -71,16 +71,6 @@ using command_func = internal::callable<
void, state &, span_type<any_value>, 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<ident const *> 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<any_value> 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
*

View File

@ -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.
*

View File

@ -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 {

View File

@ -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<any_value> 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<any_value>, 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<any_value> args, state &cs
) {
return ident::call(args, cs);
}
LIBCUBESCRIPT_EXPORT integer_type integer_var::get_value() const {
return static_cast<ivar_impl const *>(this)->p_storage;
}
@ -308,6 +321,32 @@ LIBCUBESCRIPT_EXPORT void integer_var::set_raw_value(integer_type val) {
static_cast<ivar_impl *>(this)->p_storage = val;
}
inline any_value call_var(
ident &id, command *hid, span_type<any_value> &args, state &cs
) {
any_value ret{};
auto &ts = state_p{cs}.ts();
auto *cimp = static_cast<command_impl *>(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<any_value> 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<fvar_impl const *>(this)->p_storage;
}
@ -334,6 +373,12 @@ LIBCUBESCRIPT_EXPORT void float_var::set_raw_value(float_type val) {
static_cast<fvar_impl *>(this)->p_storage = val;
}
LIBCUBESCRIPT_EXPORT any_value float_var::call(
span_type<any_value> 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<svar_impl const *>(this)->p_storage;
}
@ -360,6 +405,12 @@ LIBCUBESCRIPT_EXPORT void string_var::set_raw_value(string_ref val) {
static_cast<svar_impl *>(this)->p_storage = val;
}
LIBCUBESCRIPT_EXPORT any_value string_var::call(
span_type<any_value> 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<alias_impl const *>(this)->p_flags & IDENT_FLAG_ARG);
}
LIBCUBESCRIPT_EXPORT any_value alias::call(
span_type<any_value> 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<command_impl const *>(this)->p_cargs;
}
@ -385,6 +449,31 @@ LIBCUBESCRIPT_EXPORT int command::get_num_args() const {
return static_cast<command_impl const *>(this)->p_numargs;
}
LIBCUBESCRIPT_EXPORT any_value command::call(
span_type<any_value> args, state &cs
) {
any_value ret{};
auto &cimpl = static_cast<command_impl &>(*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) {

View File

@ -44,7 +44,7 @@ struct alias_stack {
};
struct ident_link {
ident *id;
ident const *id;
ident_link *next;
std::bitset<MAX_ARGUMENTS> 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<any_value> args, any_value &ret);
void call(
thread_state &ts, span_type<any_value> 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} {}

View File

@ -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<command_impl *>(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<command_impl *>(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<command_impl *>(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<any_value>{&v, 1});
id->get().call(span_type<any_value>{&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<any_value> 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<command_impl &>(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<command_impl *>(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<command_impl *>(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<command_impl *>(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<alias &>(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 {

View File

@ -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<alias_impl *>(a)->p_initial;
it.first->second.flags = static_cast<alias_impl *>(a)->p_flags;
auto *imp = const_cast<alias_impl *>(
static_cast<alias_impl const *>(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<alias *>(a));
}
} /* namespace cubescript */

View File

@ -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 */

View File

@ -246,7 +246,7 @@ std::string_view any_value::force_string(state &cs) {
return str_managed_view(csv_get<char const *>(&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<bcode *>(&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;

View File

@ -114,9 +114,7 @@ void exec_command(
break;
case '.':
i = std::max(i + 1, numargs);
static_cast<command_impl *>(id)->call(
ts, span_type<any_value>{args, std::size_t(i)}, res
);
id->call(ts, span_type<any_value>{args, std::size_t(i)}, res);
return;
case '1':
case '2':
@ -130,9 +128,7 @@ void exec_command(
}
}
++i;
static_cast<command_impl *>(id)->call(
ts, span_type<any_value>{args, std::size_t(i)}, res
);
id->call(ts, span_type<any_value>{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);
}

View File

@ -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 &) {

View File

@ -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();
}
};

View File

@ -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)",

View File

@ -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);