From 702dca08096a83e2bb7b60f539f64696fe801cc3 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Mon, 22 Mar 2021 22:33:01 +0100 Subject: [PATCH] separate ident and error impls into their own files --- src/cs_error.cc | 84 ++++++++++++++++++++ src/cs_gen.cc | 34 ++++---- src/cs_ident.cc | 114 +++++++++++++++++++++++++++ src/cs_ident.hh | 121 +++++++++++++++++++++++++++++ src/cs_vm.cc | 193 ++++++++++++---------------------------------- src/cs_vm.hh | 162 +------------------------------------- src/cubescript.cc | 42 +++------- src/meson.build | 2 + 8 files changed, 400 insertions(+), 352 deletions(-) create mode 100644 src/cs_error.cc create mode 100644 src/cs_ident.cc create mode 100644 src/cs_ident.hh diff --git a/src/cs_error.cc b/src/cs_error.cc new file mode 100644 index 0000000..71788de --- /dev/null +++ b/src/cs_error.cc @@ -0,0 +1,84 @@ +#include + +#include "cs_util.hh" +#include "cs_vm.hh" + +namespace cscript { + +LIBCUBESCRIPT_EXPORT char *cs_error::request_buf( + cs_state &cs, std::size_t bufs, char *&sp +) { + cs_charbuf &cb = *static_cast(cs.p_errbuf); + cs_gen_state *gs = cs.p_pstate; + cb.clear(); + std::size_t sz = 0; + if (gs) { + /* we can attach line number */ + sz = gs->src_name.size() + 32; + for (;;) { + /* we are using so the buffer tracks the elements and therefore + * does not wipe them when we attempt to reserve more capacity + */ + cb.resize(sz); + int nsz; + if (!gs->src_name.empty()) { + nsz = std::snprintf( + cb.data(), sz, "%.*s:%zu: ", + int(gs->src_name.size()), gs->src_name.data(), + gs->current_line + ); + } else { + nsz = std::snprintf(cb.data(), sz, "%zu: ", gs->current_line); + } + if (nsz <= 0) { + throw cs_internal_error{"format error"}; + } else if (std::size_t(nsz) < sz) { + sz = std::size_t(nsz); + break; + } + sz = std::size_t(nsz + 1); + } + } + cb.resize(sz + bufs + 1); + sp = cb.data(); + return &cb[sz]; +} + +LIBCUBESCRIPT_EXPORT cs_stack_state cs_error::save_stack(cs_state &cs) { + cs_ivar *dalias = static_cast(cs.p_state->identmap[DbgaliasIdx]); + if (!dalias->get_value()) { + return cs_stack_state(cs, nullptr, !!cs.p_callstack); + } + int total = 0, depth = 0; + for (cs_ident_link *l = cs.p_callstack; l; l = l->next) { + total++; + } + if (!total) { + return cs_stack_state(cs, nullptr, false); + } + cs_stack_state_node *st = cs.p_state->create_array( + std::min(total, dalias->get_value()) + ); + cs_stack_state_node *ret = st, *nd = st; + ++st; + for (cs_ident_link *l = cs.p_callstack; l; l = l->next) { + ++depth; + if (depth < dalias->get_value()) { + nd->id = l->id; + nd->index = total - depth + 1; + if (!l->next) { + nd->next = nullptr; + } else { + nd->next = st; + } + nd = st++; + } else if (!l->next) { + nd->id = l->id; + nd->index = 1; + nd->next = nullptr; + } + } + return cs_stack_state(cs, ret, total > dalias->get_value()); +} + +} /* namespace cscript */ diff --git a/src/cs_gen.cc b/src/cs_gen.cc index 60f4af7..4ac0e04 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -1162,7 +1162,7 @@ static void compile_and_or( } if (!more) { gs.code.push_back( - ((id->get_raw_type() == CsIdAnd) + ((id->get_raw_type() == ID_AND) ? CS_CODE_TRUE : CS_CODE_FALSE) | cs_ret_code(rettype) ); } else { @@ -1194,7 +1194,7 @@ static void compile_and_or( (numargs << 8) | (id->get_index() << 13) ); } else { - uint32_t op = (id->get_raw_type() == CsIdAnd) + uint32_t op = (id->get_raw_type() == ID_AND) ? (CS_CODE_JUMP_RESULT | CS_CODE_FLAG_FALSE) : (CS_CODE_JUMP_RESULT | CS_CODE_FLAG_TRUE); gs.code.push_back(op); @@ -1332,36 +1332,36 @@ noid: gs.code.push_back(CS_CODE_RESULT); } else { switch (id->get_raw_type()) { - case CsIdAlias: + case ID_ALIAS: compile_alias( gs, static_cast(id), more, prevargs ); break; - case CsIdCommand: + case ID_COMMAND: compile_cmd( gs, static_cast(id), more, rettype, prevargs ); break; - case CsIdLocal: + case ID_LOCAL: compile_local(gs, more, prevargs); break; - case CsIdDo: + case ID_DO: compile_do(gs, more, prevargs, rettype, CS_CODE_DO); break; - case CsIdDoArgs: + case ID_DOARGS: compile_do(gs, more, prevargs, rettype, CS_CODE_DO_ARGS); break; - case CsIdIf: + case ID_IF: compile_if(gs, id, more, prevargs, rettype); break; - case CsIdBreak: + case ID_BREAK: gs.code.push_back(CS_CODE_BREAK | CS_CODE_FLAG_FALSE); break; - case CsIdContinue: + case ID_CONTINUE: gs.code.push_back(CS_CODE_BREAK | CS_CODE_FLAG_TRUE); break; - case CsIdResult: + case ID_RESULT: if (more) { more = compilearg(gs, CS_VAL_ANY, prevargs); } @@ -1370,7 +1370,7 @@ noid: cs_ret_code(rettype) ); break; - case CsIdNot: + case ID_NOT: if (more) { more = compilearg(gs, CS_VAL_ANY, prevargs); } @@ -1378,11 +1378,11 @@ noid: (more ? CS_CODE_NOT : CS_CODE_TRUE) | cs_ret_code(rettype) ); break; - case CsIdAnd: - case CsIdOr: + case ID_AND: + case ID_OR: compile_and_or(gs, id, more, prevargs, rettype); break; - case CsIdIvar: + case ID_IVAR: if (!(more = compilearg(gs, CS_VAL_INT, prevargs))) { gs.code.push_back(CS_CODE_PRINT | (id->get_index() << 8)); } else if (!(id->get_flags() & CS_IDF_HEX) || !( @@ -1397,14 +1397,14 @@ noid: gs.code.push_back(CS_CODE_IVAR3 | (id->get_index() << 8)); } break; - case CsIdFvar: + case ID_FVAR: if (!(more = compilearg(gs, CS_VAL_FLOAT, prevargs))) { gs.code.push_back(CS_CODE_PRINT | (id->get_index() << 8)); } else { gs.code.push_back(CS_CODE_FVAR1 | (id->get_index() << 8)); } break; - case CsIdSvar: + case ID_SVAR: if (!(more = compilearg(gs, CS_VAL_STRING, prevargs))) { gs.code.push_back(CS_CODE_PRINT | (id->get_index() << 8)); } else { diff --git a/src/cs_ident.cc b/src/cs_ident.cc new file mode 100644 index 0000000..0b3dcd8 --- /dev/null +++ b/src/cs_ident.cc @@ -0,0 +1,114 @@ +#include "cs_ident.hh" + +#include "cs_bcode.hh" +#include "cs_vm.hh" + +namespace cscript { + +void cs_var_impl::changed(cs_state &cs) { + if (cb_var) { + switch (p_type) { + case ID_IVAR: + cb_var(cs, *static_cast(this)); + break; + case ID_FVAR: + cb_var(cs, *static_cast(this)); + break; + case ID_SVAR: + cb_var(cs, *static_cast(this)); + break; + default: + break; + } + } +} + +void cs_alias_impl::push_arg(cs_value &v, cs_ident_stack &st, bool um) { + if (p_astack == &st) { + /* prevent cycles and unnecessary code elsewhere */ + p_val = std::move(v); + clean_code(); + return; + } + st.val_s = std::move(p_val); + st.next = p_astack; + p_astack = &st; + p_val = std::move(v); + clean_code(); + if (um) { + p_flags &= ~CS_IDF_UNKNOWN; + } +} + +void cs_alias_impl::pop_arg() { + if (!p_astack) { + return; + } + cs_ident_stack *st = p_astack; + p_val = std::move(p_astack->val_s); + clean_code(); + p_astack = st->next; +} + +void cs_alias_impl::undo_arg(cs_ident_stack &st) { + cs_ident_stack *prev = p_astack; + st.val_s = std::move(p_val); + st.next = prev; + p_astack = prev->next; + p_val = std::move(prev->val_s); + clean_code(); +} + +void cs_alias_impl::redo_arg(cs_ident_stack &st) { + cs_ident_stack *prev = st.next; + prev->val_s = std::move(p_val); + p_astack = prev; + p_val = std::move(st.val_s); + clean_code(); +} + +void cs_alias_impl::set_arg(cs_state &cs, cs_value &v) { + if (ident_is_used_arg(this, cs)) { + p_val = std::move(v); + clean_code(); + } else { + push_arg(v, cs.p_callstack->argstack[get_index()], false); + cs.p_callstack->usedargs |= 1 << get_index(); + } +} + +void cs_alias_impl::set_alias(cs_state &cs, cs_value &v) { + p_val = std::move(v); + clean_code(); + p_flags = (p_flags & cs.identflags) | cs.identflags; +} + +void cs_alias_impl::clean_code() { + if (p_acode) { + bcode_decr(p_acode->get_raw()); + p_acode = nullptr; + } +} + +cs_bcode *cs_alias_impl::compile_code(cs_state &cs) { + if (!p_acode) { + cs_gen_state gs(cs); + gs.code.reserve(64); + gs.gen_main(get_value().get_str()); + /* i wish i could steal the memory somehow */ + uint32_t *code = bcode_alloc(cs, gs.code.size()); + memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t)); + bcode_incr(code); + p_acode = reinterpret_cast(code); + } + return p_acode; +} + +bool ident_is_used_arg(cs_ident *id, cs_state &cs) { + if (!cs.p_callstack) { + return true; + } + return cs.p_callstack->usedargs & (1 << id->get_index()); +} + +} /* namespace cscript */ diff --git a/src/cs_ident.hh b/src/cs_ident.hh new file mode 100644 index 0000000..ad20db4 --- /dev/null +++ b/src/cs_ident.hh @@ -0,0 +1,121 @@ +#ifndef LIBCUBESCRIPT_ALIAS_HH +#define LIBCUBESCRIPT_ALIAS_HH + +#include + +#include "cs_util.hh" + +namespace cscript { + +enum { + ID_UNKNOWN = -1, ID_IVAR, ID_FVAR, ID_SVAR, ID_COMMAND, ID_ALIAS, + ID_LOCAL, ID_DO, ID_DOARGS, ID_IF, ID_BREAK, ID_CONTINUE, ID_RESULT, + ID_NOT, ID_AND, ID_OR +}; + +struct cs_ident_link { + cs_ident *id; + cs_ident_link *next; + int usedargs; + cs_ident_stack *argstack; +}; + +struct cs_ident_impl { + cs_ident_impl() = delete; + cs_ident_impl(cs_ident_impl const &) = delete; + cs_ident_impl(cs_ident_impl &&) = delete; + + /* trigger destructors for all inherited members properly */ + virtual ~cs_ident_impl() {}; + + cs_ident_impl &operator=(cs_ident_impl const &) = delete; + cs_ident_impl &operator=(cs_ident_impl &&) = delete; + + cs_ident_impl(cs_ident_type tp, cs_strref name, int flags = 0); + + cs_strref p_name; + /* represents the cs_ident_type above, but internally it has a wider + * variety of values, so it's an int here (maps to an internal enum) + */ + int p_type, p_flags; + + int p_index = -1; +}; + +struct cs_var_impl: cs_ident_impl { + cs_var_impl( + cs_ident_type tp, cs_strref name, cs_var_cb func, int flags = 0 + ); + + cs_var_cb cb_var; + + void changed(cs_state &cs); +}; + +struct cs_ivar_impl: cs_var_impl, cs_ivar { + cs_ivar_impl( + cs_strref n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags + ); + + cs_int p_storage, p_minval, p_maxval, p_overrideval; +}; + +struct cs_fvar_impl: cs_var_impl, cs_fvar { + cs_fvar_impl( + cs_strref n, cs_float m, cs_float x, cs_float v, + cs_var_cb f, int flags + ); + + cs_float p_storage, p_minval, p_maxval, p_overrideval; +}; + +struct cs_svar_impl: cs_var_impl, cs_svar { + cs_svar_impl( + cs_strref n, cs_strref v, cs_strref ov, cs_var_cb f, int flags + ); + + cs_strref p_storage, p_overrideval; +}; + +struct cs_alias_impl: cs_ident_impl, cs_alias { + cs_alias_impl(cs_state &cs, cs_strref n, cs_strref a, int flags); + cs_alias_impl(cs_state &cs, cs_strref n, std::string_view a, int flags); + cs_alias_impl(cs_state &cs, cs_strref n, cs_int a, int flags); + cs_alias_impl(cs_state &cs, cs_strref n, cs_float a, int flags); + cs_alias_impl(cs_state &cs, cs_strref n, int flags); + cs_alias_impl(cs_state &cs, cs_strref n, cs_value v, int flags); + + void push_arg(cs_value &v, cs_ident_stack &st, bool um = true); + void pop_arg(); + void undo_arg(cs_ident_stack &st); + void redo_arg(cs_ident_stack &st); + void set_arg(cs_state &cs, cs_value &v); + void set_alias(cs_state &cs, cs_value &v); + + void clean_code(); + cs_bcode *compile_code(cs_state &cs); + + cs_bcode *p_acode; + cs_ident_stack *p_astack; + cs_value p_val; +}; + +struct cs_command_impl: cs_ident_impl, cs_command { + cs_command_impl( + cs_strref name, cs_strref args, int numargs, cs_command_cb func + ); + + void call(cs_state &cs, std::span args, cs_value &ret) { + p_cb_cftv(cs, args, ret); + } + + cs_strref p_cargs; + cs_command_cb p_cb_cftv; + int p_numargs; +}; + +bool ident_is_used_arg(cs_ident *id, cs_state &cs); + +} /* namespace cscript */ + +#endif diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 9288890..7b4a864 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -61,101 +61,6 @@ bool cs_stack_state::gap() const { return p_gap; } -char *cs_error::request_buf(cs_state &cs, std::size_t bufs, char *&sp) { - cs_charbuf &cb = *static_cast(cs.p_errbuf); - cs_gen_state *gs = cs.p_pstate; - cb.clear(); - std::size_t sz = 0; - if (gs) { - /* we can attach line number */ - sz = gs->src_name.size() + 32; - for (;;) { - /* we are using so the buffer tracks the elements and therefore - * does not wipe them when we attempt to reserve more capacity - */ - cb.resize(sz); - int nsz; - if (!gs->src_name.empty()) { - nsz = std::snprintf( - cb.data(), sz, "%.*s:%zu: ", - int(gs->src_name.size()), gs->src_name.data(), - gs->current_line - ); - } else { - nsz = std::snprintf(cb.data(), sz, "%zu: ", gs->current_line); - } - if (nsz <= 0) { - throw cs_internal_error{"format error"}; - } else if (std::size_t(nsz) < sz) { - sz = std::size_t(nsz); - break; - } - sz = std::size_t(nsz + 1); - } - } - cb.resize(sz + bufs + 1); - sp = cb.data(); - return &cb[sz]; -} - -cs_stack_state cs_error::save_stack(cs_state &cs) { - cs_ivar *dalias = static_cast(cs.p_state->identmap[DbgaliasIdx]); - if (!dalias->get_value()) { - return cs_stack_state(cs, nullptr, !!cs.p_callstack); - } - int total = 0, depth = 0; - for (cs_ident_link *l = cs.p_callstack; l; l = l->next) { - total++; - } - if (!total) { - return cs_stack_state(cs, nullptr, false); - } - cs_stack_state_node *st = cs.p_state->create_array( - std::min(total, dalias->get_value()) - ); - cs_stack_state_node *ret = st, *nd = st; - ++st; - for (cs_ident_link *l = cs.p_callstack; l; l = l->next) { - ++depth; - if (depth < dalias->get_value()) { - nd->id = l->id; - nd->index = total - depth + 1; - if (!l->next) { - nd->next = nullptr; - } else { - nd->next = st; - } - nd = st++; - } else if (!l->next) { - nd->id = l->id; - nd->index = 1; - nd->next = nullptr; - } - } - return cs_stack_state(cs, ret, total > dalias->get_value()); -} - -void cs_alias_impl::clean_code() { - if (p_acode) { - bcode_decr(p_acode->get_raw()); - p_acode = nullptr; - } -} - -cs_bcode *cs_alias_impl::compile_code(cs_state &cs) { - if (!p_acode) { - cs_gen_state gs(cs); - gs.code.reserve(64); - gs.gen_main(get_value().get_str()); - /* i wish i could steal the memory somehow */ - uint32_t *code = bcode_alloc(cs, gs.code.size()); - memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t)); - bcode_incr(code); - p_acode = reinterpret_cast(code); - } - return p_acode; -} - static inline uint32_t *forcecode(cs_state &cs, cs_value &v) { auto *code = v.get_code(); if (!code) { @@ -429,7 +334,7 @@ static inline cs_alias *cs_get_lookup_id(cs_state &cs, uint32_t op) { static inline cs_alias *cs_get_lookuparg_id(cs_state &cs, uint32_t op) { cs_ident *id = cs.p_state->identmap[op >> 8]; - if (!cs_is_arg_used(cs, id)) { + if (!ident_is_used_arg(id, cs)) { return nullptr; } return static_cast(id); @@ -448,16 +353,16 @@ static inline int cs_get_lookupu_type( if (id->get_flags() & CS_IDF_UNKNOWN) { break; } - if ((id->get_index() < MaxArguments) && !cs_is_arg_used(cs, id)) { - return CsIdUnknown; + if ((id->get_index() < MaxArguments) && !ident_is_used_arg(id, cs)) { + return ID_UNKNOWN; } - return CsIdAlias; + return ID_ALIAS; case cs_ident_type::SVAR: - return CsIdSvar; + return ID_SVAR; case cs_ident_type::IVAR: - return CsIdIvar; + return ID_IVAR; case cs_ident_type::FVAR: - return CsIdFvar; + return ID_FVAR; case cs_ident_type::COMMAND: { arg.set_none(); cs_valarray buf{cs}; @@ -469,7 +374,7 @@ static inline int cs_get_lookupu_type( return -2; /* ignore */ } default: - return CsIdUnknown; + return ID_UNKNOWN; } } throw cs_error(cs, "unknown alias lookup: %s", arg.get_str().data()); @@ -841,7 +746,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { cs_alias *a = static_cast( cs.p_state->identmap[op >> 8] ); - if (!cs_is_arg_used(cs, a)) { + if (!ident_is_used_arg(a, cs)) { cs_value nv{cs}; static_cast(a)->push_arg( nv, cs.p_callstack->argstack[a->get_index()], false @@ -857,7 +762,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { if (arg.get_type() == cs_value_type::STRING) { id = cs.new_ident(arg.get_str()); } - if ((id->get_index() < MaxArguments) && !cs_is_arg_used(cs, id)) { + if ((id->get_index() < MaxArguments) && !ident_is_used_arg(id, cs)) { cs_value nv{cs}; static_cast(id)->push_arg( nv, cs.p_callstack->argstack[id->get_index()], false @@ -872,22 +777,22 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { cs_ident *id = nullptr; cs_value &arg = args[numargs - 1]; switch (cs_get_lookupu_type(cs, arg, id, op)) { - case CsIdAlias: + case ID_ALIAS: arg = static_cast(id)->get_value(); arg.force_str(); continue; - case CsIdSvar: + case ID_SVAR: arg.set_str(static_cast(id)->get_value()); continue; - case CsIdIvar: + case ID_IVAR: arg.set_int(static_cast(id)->get_value()); arg.force_str(); continue; - case CsIdFvar: + case ID_FVAR: arg.set_float(static_cast(id)->get_value()); arg.force_str(); continue; - case CsIdUnknown: + case ID_UNKNOWN: arg.set_str(""); continue; default: @@ -912,25 +817,25 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { cs_ident *id = nullptr; cs_value &arg = args[numargs - 1]; switch (cs_get_lookupu_type(cs, arg, id, op)) { - case CsIdAlias: + case ID_ALIAS: arg.set_int( static_cast(id)->get_value().get_int() ); continue; - case CsIdSvar: + case ID_SVAR: arg.set_int(cs_parse_int( static_cast(id)->get_value() )); continue; - case CsIdIvar: + case ID_IVAR: arg.set_int(static_cast(id)->get_value()); continue; - case CsIdFvar: + case ID_FVAR: arg.set_int( cs_int(static_cast(id)->get_value()) ); continue; - case CsIdUnknown: + case ID_UNKNOWN: arg.set_int(0); continue; default: @@ -955,27 +860,27 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { cs_ident *id = nullptr; cs_value &arg = args[numargs - 1]; switch (cs_get_lookupu_type(cs, arg, id, op)) { - case CsIdAlias: + case ID_ALIAS: arg.set_float( static_cast(id)->get_value().get_float() ); continue; - case CsIdSvar: + case ID_SVAR: arg.set_float(cs_parse_float( static_cast(id)->get_value() )); continue; - case CsIdIvar: + case ID_IVAR: arg.set_float(cs_float( static_cast(id)->get_value() )); continue; - case CsIdFvar: + case ID_FVAR: arg.set_float( static_cast(id)->get_value() ); continue; - case CsIdUnknown: + case ID_UNKNOWN: arg.set_float(cs_float(0)); continue; default: @@ -1000,21 +905,21 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { cs_ident *id = nullptr; cs_value &arg = args[numargs - 1]; switch (cs_get_lookupu_type(cs, arg, id, op)) { - case CsIdAlias: + case ID_ALIAS: static_cast(id)->get_value().get_val(arg); continue; - case CsIdSvar: + case ID_SVAR: arg.set_str(static_cast(id)->get_value()); continue; - case CsIdIvar: + case ID_IVAR: arg.set_int(static_cast(id)->get_value()); continue; - case CsIdFvar: + case ID_FVAR: arg.set_float( static_cast(id)->get_value() ); continue; - case CsIdUnknown: + case ID_UNKNOWN: arg.set_none(); continue; default: @@ -1038,22 +943,22 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { cs_ident *id = nullptr; cs_value &arg = args[numargs - 1]; switch (cs_get_lookupu_type(cs, arg, id, op)) { - case CsIdAlias: + case ID_ALIAS: arg = static_cast(id)->get_value(); arg.force_str(); continue; - case CsIdSvar: + case ID_SVAR: arg.set_str(static_cast(id)->get_value()); continue; - case CsIdIvar: + case ID_IVAR: arg.set_int(static_cast(id)->get_value()); arg.force_str(); continue; - case CsIdFvar: + case ID_FVAR: arg.set_float(static_cast(id)->get_value()); arg.force_str(); continue; - case CsIdUnknown: + case ID_UNKNOWN: arg.set_str(""); continue; default: @@ -1078,19 +983,19 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { cs_ident *id = nullptr; cs_value &arg = args[numargs - 1]; switch (cs_get_lookupu_type(cs, arg, id, op)) { - case CsIdAlias: + case ID_ALIAS: static_cast(id)->get_cval(arg); continue; - case CsIdSvar: + case ID_SVAR: arg.set_str(static_cast(id)->get_value()); continue; - case CsIdIvar: + case ID_IVAR: arg.set_int(static_cast(id)->get_value()); continue; - case CsIdFvar: + case ID_FVAR: arg.set_float(static_cast(id)->get_value()); continue; - case CsIdUnknown: + case ID_UNKNOWN: arg.set_none(); continue; default: @@ -1328,7 +1233,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { result.force_none(); cs_ident *id = cs.p_state->identmap[op >> 13]; int callargs = (op >> 8) & 0x1F, offset = numargs - callargs; - if (!cs_is_arg_used(cs, id)) { + if (!ident_is_used_arg(id, cs)) { numargs = offset; force_arg(result, op & CS_CODE_RET_MASK); continue; @@ -1376,7 +1281,7 @@ noid: continue; } /* fallthrough */ - case CsIdCommand: + case ID_COMMAND: callcommand( cs, static_cast(id), &args[offset], result, callargs @@ -1384,7 +1289,7 @@ noid: force_arg(result, op & CS_CODE_RET_MASK); numargs = offset - 1; continue; - case CsIdLocal: { + case ID_LOCAL: { cs_valarray locals{cs}; for (size_t j = 0; j < size_t(callargs); ++j) { cs_push_alias(cs, cs.force_ident( @@ -1400,7 +1305,7 @@ noid: }); return code; } - case CsIdIvar: + case ID_IVAR: if (callargs <= 0) { cs.print_var(*static_cast(id)); } else { @@ -1412,7 +1317,7 @@ noid: numargs = offset - 1; force_arg(result, op & CS_CODE_RET_MASK); continue; - case CsIdFvar: + case ID_FVAR: if (callargs <= 0) { cs.print_var(*static_cast(id)); } else { @@ -1424,7 +1329,7 @@ noid: numargs = offset - 1; force_arg(result, op & CS_CODE_RET_MASK); continue; - case CsIdSvar: + case ID_SVAR: if (callargs <= 0) { cs.print_var(*static_cast(id)); } else { @@ -1436,11 +1341,11 @@ noid: numargs = offset - 1; force_arg(result, op & CS_CODE_RET_MASK); continue; - case CsIdAlias: { + case ID_ALIAS: { cs_alias *a = static_cast(id); if ( (a->get_index() < MaxArguments) && - !cs_is_arg_used(cs, a) + !ident_is_used_arg(a, cs) ) { numargs = offset - 1; force_arg(result, op & CS_CODE_RET_MASK); @@ -1549,7 +1454,7 @@ void cs_state::run(cs_ident *id, std::span args, cs_value &ret) { case cs_ident_type::ALIAS: { cs_alias *a = static_cast(id); if ( - (a->get_index() < MaxArguments) && !cs_is_arg_used(*this, a) + (a->get_index() < MaxArguments) && !ident_is_used_arg(a, *this) ) { break; } diff --git a/src/cs_vm.hh b/src/cs_vm.hh index 05fec23..e81a11e 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -10,6 +10,7 @@ #include "cs_util.hh" #include "cs_bcode.hh" +#include "cs_ident.hh" namespace cscript { @@ -20,167 +21,6 @@ static constexpr int DummyIdx = MaxArguments; static constexpr int NumargsIdx = MaxArguments + 1; static constexpr int DbgaliasIdx = MaxArguments + 2; -enum { - CsIdUnknown = -1, CsIdIvar, CsIdFvar, CsIdSvar, CsIdCommand, CsIdAlias, - CsIdLocal, CsIdDo, CsIdDoArgs, CsIdIf, CsIdBreak, CsIdContinue, CsIdResult, - CsIdNot, CsIdAnd, CsIdOr -}; - -struct cs_ident_impl { - cs_ident_impl() = delete; - cs_ident_impl(cs_ident_impl const &) = delete; - cs_ident_impl(cs_ident_impl &&) = delete; - - /* trigger destructors for all inherited members properly */ - virtual ~cs_ident_impl() {}; - - cs_ident_impl &operator=(cs_ident_impl const &) = delete; - cs_ident_impl &operator=(cs_ident_impl &&) = delete; - - cs_ident_impl(cs_ident_type tp, cs_strref name, int flags = 0); - - cs_strref p_name; - /* represents the cs_ident_type above, but internally it has a wider variety - * of values, so it's an int here (maps to an internal enum) - */ - int p_type, p_flags; - - int p_index = -1; -}; - -struct cs_var_impl: cs_ident_impl { - cs_var_impl(cs_ident_type tp, cs_strref name, cs_var_cb func, int flags = 0); - - cs_var_cb cb_var; - - void changed(cs_state &cs); -}; - -struct cs_ivar_impl: cs_var_impl, cs_ivar { - cs_ivar_impl( - cs_strref n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags - ); - - cs_int p_storage, p_minval, p_maxval, p_overrideval; -}; - -struct cs_fvar_impl: cs_var_impl, cs_fvar { - cs_fvar_impl( - cs_strref n, cs_float m, cs_float x, cs_float v, - cs_var_cb f, int flags - ); - - cs_float p_storage, p_minval, p_maxval, p_overrideval; -}; - -struct cs_svar_impl: cs_var_impl, cs_svar { - cs_svar_impl(cs_strref n, cs_strref v, cs_strref ov, cs_var_cb f, int flags); - - cs_strref p_storage, p_overrideval; -}; - -struct cs_ident_link { - cs_ident *id; - cs_ident_link *next; - int usedargs; - cs_ident_stack *argstack; -}; - -static inline bool cs_is_arg_used(cs_state &cs, cs_ident *id) { - if (!cs.p_callstack) { - return true; - } - return cs.p_callstack->usedargs & (1 << id->get_index()); -} - -struct cs_alias_impl: cs_ident_impl, cs_alias { - cs_alias_impl(cs_state &cs, cs_strref n, cs_strref a, int flags); - cs_alias_impl(cs_state &cs, cs_strref n, std::string_view a, int flags); - cs_alias_impl(cs_state &cs, cs_strref n, cs_int a, int flags); - cs_alias_impl(cs_state &cs, cs_strref n, cs_float a, int flags); - cs_alias_impl(cs_state &cs, cs_strref n, int flags); - cs_alias_impl(cs_state &cs, cs_strref n, cs_value v, int flags); - - void push_arg(cs_value &v, cs_ident_stack &st, bool um = true) { - if (p_astack == &st) { - /* prevent cycles and unnecessary code elsewhere */ - p_val = std::move(v); - clean_code(); - return; - } - st.val_s = std::move(p_val); - st.next = p_astack; - p_astack = &st; - p_val = std::move(v); - clean_code(); - if (um) { - p_flags &= ~CS_IDF_UNKNOWN; - } - } - - void pop_arg() { - if (!p_astack) { - return; - } - cs_ident_stack *st = p_astack; - p_val = std::move(p_astack->val_s); - clean_code(); - p_astack = st->next; - } - - void undo_arg(cs_ident_stack &st) { - cs_ident_stack *prev = p_astack; - st.val_s = std::move(p_val); - st.next = prev; - p_astack = prev->next; - p_val = std::move(prev->val_s); - clean_code(); - } - - void redo_arg(cs_ident_stack &st) { - cs_ident_stack *prev = st.next; - prev->val_s = std::move(p_val); - p_astack = prev; - p_val = std::move(st.val_s); - clean_code(); - } - - void set_arg(cs_state &cs, cs_value &v) { - if (cs_is_arg_used(cs, this)) { - p_val = std::move(v); - clean_code(); - } else { - push_arg(v, cs.p_callstack->argstack[get_index()], false); - cs.p_callstack->usedargs |= 1 << get_index(); - } - } - - void set_alias(cs_state &cs, cs_value &v) { - p_val = std::move(v); - clean_code(); - p_flags = (p_flags & cs.identflags) | cs.identflags; - } - - void clean_code(); - cs_bcode *compile_code(cs_state &cs); - - cs_bcode *p_acode; - cs_ident_stack *p_astack; - cs_value p_val; -}; - -struct cs_command_impl: cs_ident_impl, cs_command { - cs_command_impl(cs_strref name, cs_strref args, int numargs, cs_command_cb func); - - void call(cs_state &cs, std::span args, cs_value &ret) { - p_cb_cftv(cs, args, ret); - } - - cs_strref p_cargs; - cs_command_cb p_cb_cftv; - int p_numargs; -}; - template struct cs_valarray { cs_valarray(cs_state &cs) { diff --git a/src/cubescript.cc b/src/cubescript.cc index bdc1319..814c8e5 100644 --- a/src/cubescript.cc +++ b/src/cubescript.cc @@ -203,24 +203,6 @@ cs_svar const *cs_ident::get_svar() const { return static_cast(this); } -void cs_var_impl::changed(cs_state &cs) { - if (cb_var) { - switch (p_type) { - case CsIdIvar: - cb_var(cs, *static_cast(this)); - break; - case CsIdFvar: - cb_var(cs, *static_cast(this)); - break; - case CsIdSvar: - cb_var(cs, *static_cast(this)); - break; - default: - break; - } - } -} - cs_int cs_ivar::get_val_min() const { return static_cast(this)->p_minval; } @@ -318,29 +300,29 @@ cs_state::cs_state(cs_alloc_cb func, void *data): p = new_command("do", "e", [](auto &cs, auto args, auto &res) { cs.run(args[0].get_code(), res); }); - static_cast(p)->p_type = CsIdDo; + 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 = CsIdDoArgs; + 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 = CsIdIf; + 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 = CsIdResult; + 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 = CsIdNot; + static_cast(p)->p_type = ID_NOT; p = new_command("&&", "E1V", [](auto &cs, auto args, auto &res) { if (args.empty()) { @@ -359,7 +341,7 @@ cs_state::cs_state(cs_alloc_cb func, void *data): } } }); - static_cast(p)->p_type = CsIdAnd; + static_cast(p)->p_type = ID_AND; p = new_command("||", "E1V", [](auto &cs, auto args, auto &res) { if (args.empty()) { @@ -378,10 +360,10 @@ cs_state::cs_state(cs_alloc_cb func, void *data): } } }); - static_cast(p)->p_type = CsIdOr; + static_cast(p)->p_type = ID_OR; p = new_command("local", "", nullptr); - static_cast(p)->p_type = CsIdLocal; + static_cast(p)->p_type = ID_LOCAL; p = new_command("break", "", [](auto &cs, auto, auto &) { if (cs.is_in_loop()) { @@ -390,7 +372,7 @@ cs_state::cs_state(cs_alloc_cb func, void *data): throw cs_error(cs, "no loop to break"); } }); - static_cast(p)->p_type = CsIdBreak; + static_cast(p)->p_type = ID_BREAK; p = new_command("continue", "", [](auto &cs, auto, auto &) { if (cs.is_in_loop()) { @@ -399,7 +381,7 @@ cs_state::cs_state(cs_alloc_cb func, void *data): throw cs_error(cs, "no loop to continue"); } }); - static_cast(p)->p_type = CsIdContinue; + static_cast(p)->p_type = ID_CONTINUE; cs_init_lib_base(*this); } @@ -699,7 +681,7 @@ int cs_ident::get_raw_type() const { } cs_ident_type cs_ident::get_type() const { - if (p_impl->p_type > CsIdAlias) { + if (p_impl->p_type > ID_ALIAS) { return cs_ident_type::SPECIAL; } return cs_ident_type(p_impl->p_type); @@ -868,7 +850,7 @@ cs_state::get_alias_val(std::string_view name) { if (!a) { return std::nullopt; } - if ((a->get_index() < MaxArguments) && !cs_is_arg_used(*this, a)) { + if ((a->get_index() < MaxArguments) && !ident_is_used_arg(a, *this)) { return std::nullopt; } return a->get_value().get_str(); diff --git a/src/meson.build b/src/meson.build index 8dbde8a..5862927 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,7 +5,9 @@ libcubescript_header_src = [ libcubescript_src = [ 'cs_bcode.cc', + 'cs_error.cc', 'cs_gen.cc', + 'cs_ident.cc', 'cs_util.cc', 'cs_val.cc', 'cs_vm.cc',