diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index 3fd96f4..2c11a35 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -56,6 +56,7 @@ struct cs_bcode; struct cs_value; struct cs_state; struct cs_shared_state; +struct cs_ident_impl; struct LIBCUBESCRIPT_EXPORT cs_bcode_ref { cs_bcode_ref(): @@ -206,19 +207,7 @@ struct cs_alias; struct cs_command; struct LIBCUBESCRIPT_EXPORT cs_ident { - friend struct cs_state; - friend struct cs_shared_state; - - cs_ident() = delete; - cs_ident(cs_ident const &) = delete; - cs_ident(cs_ident &&) = delete; - - /* trigger destructors for all inherited members properly */ - virtual ~cs_ident() {}; - - cs_ident &operator=(cs_ident const &) = delete; - cs_ident &operator=(cs_ident &&) = delete; - + int get_raw_type() const; cs_ident_type get_type() const; std::string_view get_name() const; int get_flags() const; @@ -250,127 +239,64 @@ struct LIBCUBESCRIPT_EXPORT cs_ident { cs_svar *get_svar(); cs_svar const *get_svar() const; - int get_type_raw() const { - return p_type; - } - protected: - cs_ident(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; + cs_ident() = default; private: - int p_index = -1; + friend struct cs_state; + + cs_ident_impl *p_impl{}; }; struct LIBCUBESCRIPT_EXPORT cs_var: cs_ident { - friend struct cs_state; - friend struct cs_shared_state; - protected: - cs_var(cs_ident_type tp, cs_strref name, cs_var_cb func, int flags = 0); - -private: - cs_var_cb cb_var; - - void changed(cs_state &cs) { - if (cb_var) { - cb_var(cs, *this); - } - } + cs_var() = default; }; struct LIBCUBESCRIPT_EXPORT cs_ivar: cs_var { - friend struct cs_state; - friend struct cs_shared_state; - cs_int get_val_min() const; cs_int get_val_max() const; cs_int get_value() const; void set_value(cs_int val); -private: - cs_ivar( - 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; +protected: + cs_ivar() = default; }; struct LIBCUBESCRIPT_EXPORT cs_fvar: cs_var { - friend struct cs_state; - friend struct cs_shared_state; - cs_float get_val_min() const; cs_float get_val_max() const; cs_float get_value() const; void set_value(cs_float val); -private: - cs_fvar( - 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; +protected: + cs_fvar() = default; }; struct LIBCUBESCRIPT_EXPORT cs_svar: cs_var { - friend struct cs_state; - friend struct cs_shared_state; - cs_strref get_value() const; void set_value(cs_strref val); -private: - cs_svar(cs_strref n, cs_strref v, cs_strref ov, cs_var_cb f, int flags); - - cs_strref p_storage, p_overrideval; +protected: + cs_svar() = default; }; struct LIBCUBESCRIPT_EXPORT cs_alias: cs_ident { - friend struct cs_state; - friend struct cs_shared_state; - friend struct cs_alias_internal; - - cs_value get_value() const { - return p_val; - } - + cs_value get_value() const; void get_cval(cs_value &v) const; -private: - cs_alias(cs_state &cs, cs_strref n, cs_strref a, int flags); - cs_alias(cs_state &cs, cs_strref n, std::string_view a, int flags); - cs_alias(cs_state &cs, cs_strref n, cs_int a, int flags); - cs_alias(cs_state &cs, cs_strref n, cs_float a, int flags); - cs_alias(cs_state &cs, cs_strref n, int flags); - cs_alias(cs_state &cs, cs_strref n, cs_value v, int flags); - cs_bcode *p_acode; - cs_ident_stack *p_astack; - cs_value p_val; +protected: + cs_alias() = default; }; struct cs_command: cs_ident { - friend struct cs_state; - friend struct cs_shared_state; - friend struct cs_cmd_internal; - std::string_view get_args() const; int get_num_args() const; -private: - cs_command(cs_strref name, cs_strref args, int numargs, cs_command_cb func); - - cs_strref p_cargs; - cs_command_cb p_cb_cftv; - int p_numargs; +protected: + cs_command() = default; }; struct cs_ident_link; @@ -524,7 +450,7 @@ struct LIBCUBESCRIPT_EXPORT cs_state { private: LIBCUBESCRIPT_LOCAL cs_state(cs_shared_state *s); - cs_ident *add_ident(cs_ident *id); + cs_ident *add_ident(cs_ident *id, cs_ident_impl *impl); LIBCUBESCRIPT_LOCAL void *alloc(void *ptr, size_t olds, size_t news); diff --git a/src/cs_gen.cc b/src/cs_gen.cc index 8b0100c..3ec7ff0 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -323,7 +323,7 @@ lookupid: if (prevargs >= MaxResults) { gs.code.push_back(CS_CODE_ENTER); } - auto fmt = static_cast(id)->get_args(); + auto fmt = static_cast(id)->get_args(); for (char c: fmt) { switch (c) { case 'S': @@ -847,7 +847,7 @@ static bool compilearg( } static void compile_cmd( - cs_gen_state &gs, cs_command *id, bool &more, int rettype, int prevargs + cs_gen_state &gs, cs_command_impl *id, bool &more, int rettype, int prevargs ) { int comtype = CS_CODE_COM, numargs = 0, fakeargs = 0; bool rep = false; @@ -1159,8 +1159,8 @@ static void compile_and_or( } if (!more) { gs.code.push_back( - ((id->get_type_raw() == CsIdAnd) ? CS_CODE_TRUE : CS_CODE_FALSE) - | cs_ret_code(rettype) + ((id->get_raw_type() == CsIdAnd) + ? CS_CODE_TRUE : CS_CODE_FALSE) | cs_ret_code(rettype) ); } else { numargs++; @@ -1191,7 +1191,7 @@ static void compile_and_or( (numargs << 8) | (id->get_index() << 13) ); } else { - uint32_t op = (id->get_type_raw() == CsIdAnd) + uint32_t op = (id->get_raw_type() == CsIdAnd) ? (CS_CODE_JUMP_RESULT | CS_CODE_FLAG_FALSE) : (CS_CODE_JUMP_RESULT | CS_CODE_FLAG_TRUE); gs.code.push_back(op); @@ -1328,7 +1328,7 @@ noid: } gs.code.push_back(CS_CODE_RESULT); } else { - switch (id->get_type_raw()) { + switch (id->get_raw_type()) { case CsIdAlias: compile_alias( gs, static_cast(id), more, prevargs @@ -1336,7 +1336,7 @@ noid: break; case CsIdCommand: compile_cmd( - gs, static_cast(id), more, + gs, static_cast(id), more, rettype, prevargs ); break; diff --git a/src/cs_val.cc b/src/cs_val.cc index 9115af7..bd7b90a 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -417,7 +417,9 @@ bool cs_stacked_value::push() { if (!p_a) { return false; } - cs_alias_internal::push_arg(p_a, *this, p_stack); + cs_alias_internal::push_arg( + static_cast(p_a), *this, p_stack + ); p_pushed = true; return true; } @@ -426,7 +428,7 @@ bool cs_stacked_value::pop() { if (!p_pushed || !p_a) { return false; } - cs_alias_internal::pop_arg(p_a); + cs_alias_internal::pop_arg(static_cast(p_a)); p_pushed = false; return true; } diff --git a/src/cs_vm.cc b/src/cs_vm.cc index ff6a397..648113b 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -11,14 +11,14 @@ struct cs_cmd_internal { static void call( cs_state &cs, cs_command *c, std::span args, cs_value &ret ) { - c->p_cb_cftv(cs, args, ret); + static_cast(c)->p_cb_cftv(cs, args, ret); } static bool has_cb(cs_ident *id) { if (!id->is_command() && !id->is_special()) { return false; } - cs_command *cb = static_cast(id); + cs_command_impl *cb = static_cast(id); return !!cb->p_cb_cftv; } }; @@ -26,13 +26,13 @@ struct cs_cmd_internal { static inline void cs_push_alias(cs_state &cs, cs_ident *id, cs_ident_stack &st) { if (id->is_alias() && (id->get_index() >= MaxArguments)) { cs_value nv{cs}; - cs_alias_internal::push_arg(static_cast(id), nv, st); + cs_alias_internal::push_arg(static_cast(id), nv, st); } } static inline void cs_pop_alias(cs_ident *id) { if (id->is_alias() && (id->get_index() >= MaxArguments)) { - cs_alias_internal::pop_arg(static_cast(id)); + cs_alias_internal::pop_arg(static_cast(id)); } } @@ -310,8 +310,8 @@ cs_bcode *cs_copy_code(cs_bcode *c) { } static inline void callcommand( - cs_state &cs, cs_command *id, cs_value *args, cs_value &res, int numargs, - bool lookup = false + cs_state &cs, cs_command_impl *id, cs_value *args, cs_value &res, + int numargs, bool lookup = false ) { int i = -1, fakeargs = 0; bool rep = false; @@ -470,7 +470,7 @@ static inline void cs_call_alias( cs_valarray argstack{cs}; for(int i = 0; i < callargs; i++) { cs_alias_internal::push_arg( - static_cast(cs.p_state->identmap[i]), + static_cast(cs.p_state->identmap[i]), args[offset + i], argstack[i], false ); } @@ -483,7 +483,7 @@ static inline void cs_call_alias( }; cs.p_callstack = &aliaslink; uint32_t *codep = reinterpret_cast( - cs_alias_internal::compile_code(a, cs) + cs_alias_internal::compile_code(static_cast(a), cs) ); bcode_incr(codep); cs_do_and_cleanup([&]() { @@ -494,13 +494,13 @@ static inline void cs_call_alias( cs.identflags = oldflags; for (int i = 0; i < callargs; i++) { cs_alias_internal::pop_arg( - static_cast(cs.p_state->identmap[i]) + static_cast(cs.p_state->identmap[i]) ); } int argmask = aliaslink.usedargs & int(~0U << callargs); for (; argmask; ++callargs) { if (argmask & (1 << callargs)) { - cs_alias_internal::pop_arg(static_cast( + cs_alias_internal::pop_arg(static_cast( cs.p_state->identmap[callargs]) ); argmask &= ~(1 << callargs); @@ -570,7 +570,10 @@ static inline int cs_get_lookupu_type( case cs_ident_type::COMMAND: { arg.set_none(); cs_valarray buf{cs}; - callcommand(cs, static_cast(id), &buf[0], arg, 0, true); + callcommand( + cs, static_cast(id), + &buf[0], arg, 0, true + ); force_arg(arg, op & CS_CODE_RET_MASK); return -2; /* ignore */ } @@ -950,7 +953,8 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { if (!cs_is_arg_used(cs, a)) { cs_value nv{cs}; cs_alias_internal::push_arg( - a, nv, cs.p_callstack->argstack[a->get_index()], false + static_cast(a), nv, + cs.p_callstack->argstack[a->get_index()], false ); cs.p_callstack->usedargs |= 1 << a->get_index(); } @@ -966,7 +970,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { if ((id->get_index() < MaxArguments) && !cs_is_arg_used(cs, id)) { cs_value nv{cs}; cs_alias_internal::push_arg( - static_cast(id), nv, + static_cast(id), nv, cs.p_callstack->argstack[id->get_index()], false ); cs.p_callstack->usedargs |= 1 << id->get_index(); @@ -1308,7 +1312,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { case CS_CODE_COM | CS_RET_STRING: case CS_CODE_COM | CS_RET_FLOAT: case CS_CODE_COM | CS_RET_INT: { - cs_command *id = static_cast( + cs_command_impl *id = static_cast( cs.p_state->identmap[op >> 8] ); int offset = numargs - id->get_num_args(); @@ -1325,7 +1329,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { case CS_CODE_COM_V | CS_RET_STRING: case CS_CODE_COM_V | CS_RET_FLOAT: case CS_CODE_COM_V | CS_RET_INT: { - cs_command *id = static_cast( + cs_command_impl *id = static_cast( cs.p_state->identmap[op >> 13] ); std::size_t callargs = (op >> 8) & 0x1F, @@ -1342,7 +1346,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { case CS_CODE_COM_C | CS_RET_STRING: case CS_CODE_COM_C | CS_RET_FLOAT: case CS_CODE_COM_C | CS_RET_INT: { - cs_command *id = static_cast( + cs_command_impl *id = static_cast( cs.p_state->identmap[op >> 13] ); std::size_t callargs = (op >> 8) & 0x1F, @@ -1398,13 +1402,13 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { case CS_CODE_ALIAS: cs_alias_internal::set_alias( - static_cast(cs.p_state->identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), cs, args[--numargs] ); continue; case CS_CODE_ALIAS_ARG: cs_alias_internal::set_arg( - static_cast(cs.p_state->identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), cs, args[--numargs] ); continue; @@ -1481,7 +1485,7 @@ noid: ); } result.force_none(); - switch (id->get_type_raw()) { + switch (id->get_raw_type()) { default: if (!cs_cmd_internal::has_cb(id)) { numargs = offset - 1; @@ -1491,8 +1495,8 @@ noid: /* fallthrough */ case CsIdCommand: callcommand( - cs, static_cast(id), &args[offset], - result, callargs + cs, static_cast(id), + &args[offset], result, callargs ); force_arg(result, op & CS_CODE_RET_MASK); numargs = offset - 1; @@ -1618,18 +1622,18 @@ void cs_state::run(cs_ident *id, std::span args, cs_value &ret) { } /* fallthrough */ case cs_ident_type::COMMAND: - if (nargs < static_cast(id)->get_num_args()) { + if (nargs < static_cast(id)->get_num_args()) { cs_valarray buf{*this}; for (std::size_t i = 0; i < args.size(); ++i) { buf[i] = args[i]; } callcommand( - *this, static_cast(id), &buf[0], ret, + *this, static_cast(id), &buf[0], ret, nargs, false ); } else { callcommand( - *this, static_cast(id), &args[0], + *this, static_cast(id), &args[0], ret, nargs, false ); } diff --git a/src/cs_vm.hh b/src/cs_vm.hh index 8b966c7..b840945 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -25,6 +25,80 @@ enum { 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_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); + + 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); + + cs_strref p_cargs; + cs_command_cb p_cb_cftv; + int p_numargs; +}; + struct cs_ident_link { cs_ident *id; cs_ident_link *next; @@ -293,7 +367,7 @@ static inline bool cs_is_arg_used(cs_state &cs, cs_ident *id) { struct cs_alias_internal { static void push_arg( - cs_alias *a, cs_value &v, cs_ident_stack &st, bool um = true + cs_alias_impl *a, cs_value &v, cs_ident_stack &st, bool um = true ) { if (a->p_astack == &st) { /* prevent cycles and unnecessary code elsewhere */ @@ -311,7 +385,7 @@ struct cs_alias_internal { } } - static void pop_arg(cs_alias *a) { + static void pop_arg(cs_alias_impl *a) { if (!a->p_astack) { return; } @@ -321,7 +395,7 @@ struct cs_alias_internal { a->p_astack = st->next; } - static void undo_arg(cs_alias *a, cs_ident_stack &st) { + static void undo_arg(cs_alias_impl *a, cs_ident_stack &st) { cs_ident_stack *prev = a->p_astack; st.val_s = std::move(a->p_val); st.next = prev; @@ -330,7 +404,7 @@ struct cs_alias_internal { clean_code(a); } - static void redo_arg(cs_alias *a, cs_ident_stack &st) { + static void redo_arg(cs_alias_impl *a, cs_ident_stack &st) { cs_ident_stack *prev = st.next; prev->val_s = std::move(a->p_val); a->p_astack = prev; @@ -338,7 +412,7 @@ struct cs_alias_internal { clean_code(a); } - static void set_arg(cs_alias *a, cs_state &cs, cs_value &v) { + static void set_arg(cs_alias_impl *a, cs_state &cs, cs_value &v) { if (cs_is_arg_used(cs, a)) { a->p_val = std::move(v); clean_code(a); @@ -348,13 +422,13 @@ struct cs_alias_internal { } } - static void set_alias(cs_alias *a, cs_state &cs, cs_value &v) { + static void set_alias(cs_alias_impl *a, cs_state &cs, cs_value &v) { a->p_val = std::move(v); clean_code(a); a->p_flags = (a->p_flags & cs.identflags) | cs.identflags; } - static void clean_code(cs_alias *a) { + static void clean_code(cs_alias_impl *a) { uint32_t *bcode = reinterpret_cast(a->p_acode); if (bcode) { bcode_decr(bcode); @@ -362,7 +436,7 @@ struct cs_alias_internal { } } - static cs_bcode *compile_code(cs_alias *a, cs_state &cs) { + static cs_bcode *compile_code(cs_alias_impl *a, cs_state &cs) { if (!a->p_acode) { cs_gen_state gs(cs); gs.code.reserve(64); @@ -388,7 +462,7 @@ static void cs_do_args(cs_state &cs, F body) { for (int i = 0; argmask1; argmask1 >>= 1, ++i) { if (argmask1 & 1) { cs_alias_internal::undo_arg( - static_cast(cs.p_state->identmap[i]), argstack[i] + static_cast(cs.p_state->identmap[i]), argstack[i] ); } } @@ -408,7 +482,7 @@ static void cs_do_args(cs_state &cs, F body) { for (int i = 0; argmask2; argmask2 >>= 1, ++i) { if (argmask2 & 1) { cs_alias_internal::redo_arg( - static_cast(cs.p_state->identmap[i]), argstack[i] + static_cast(cs.p_state->identmap[i]), argstack[i] ); } } diff --git a/src/cubescript.cc b/src/cubescript.cc index b552327..15b8b2e 100644 --- a/src/cubescript.cc +++ b/src/cubescript.cc @@ -20,73 +20,73 @@ bool cs_check_num(std::string_view s) { } } -cs_ident::cs_ident(cs_ident_type tp, cs_strref nm, int fl): +cs_ident_impl::cs_ident_impl(cs_ident_type tp, cs_strref nm, int fl): p_name(nm), p_type(int(tp)), p_flags(fl) {} -cs_var::cs_var(cs_ident_type tp, cs_strref name, cs_var_cb f, int fl): - cs_ident(tp, name, fl), cb_var(std::move(f)) +cs_var_impl::cs_var_impl(cs_ident_type tp, cs_strref name, cs_var_cb f, int fl): + cs_ident_impl(tp, name, fl), cb_var(std::move(f)) {} -cs_ivar::cs_ivar( +cs_ivar_impl::cs_ivar_impl( cs_strref name, cs_int m, cs_int x, cs_int v, cs_var_cb f, int fl ): - cs_var(cs_ident_type::IVAR, name, std::move(f), fl | ((m > x) ? CS_IDF_READONLY : 0)), + cs_var_impl(cs_ident_type::IVAR, name, std::move(f), fl | ((m > x) ? CS_IDF_READONLY : 0)), p_storage(v), p_minval(m), p_maxval(x), p_overrideval(0) {} -cs_fvar::cs_fvar( +cs_fvar_impl::cs_fvar_impl( cs_strref name, cs_float m, cs_float x, cs_float v, cs_var_cb f, int fl ): - cs_var(cs_ident_type::FVAR, name, std::move(f), fl | ((m > x) ? CS_IDF_READONLY : 0)), + cs_var_impl(cs_ident_type::FVAR, name, std::move(f), fl | ((m > x) ? CS_IDF_READONLY : 0)), p_storage(v), p_minval(m), p_maxval(x), p_overrideval(0) {} -cs_svar::cs_svar(cs_strref name, cs_strref v, cs_strref ov, cs_var_cb f, int fl): - cs_var(cs_ident_type::SVAR, name, std::move(f), fl), +cs_svar_impl::cs_svar_impl(cs_strref name, cs_strref v, cs_strref ov, cs_var_cb f, int fl): + cs_var_impl(cs_ident_type::SVAR, name, std::move(f), fl), p_storage{v}, p_overrideval{ov} {} -cs_alias::cs_alias(cs_state &cs, cs_strref name, cs_strref a, int fl): - cs_ident(cs_ident_type::ALIAS, name, fl), +cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_strref a, int fl): + cs_ident_impl(cs_ident_type::ALIAS, name, fl), p_acode(nullptr), p_astack(nullptr), p_val{cs} { p_val.set_str(a); } -cs_alias::cs_alias(cs_state &cs, cs_strref name, std::string_view a, int fl): - cs_ident(cs_ident_type::ALIAS, name, fl), +cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, std::string_view a, int fl): + cs_ident_impl(cs_ident_type::ALIAS, name, fl), p_acode(nullptr), p_astack(nullptr), p_val{cs} { p_val.set_str(a); } -cs_alias::cs_alias(cs_state &cs, cs_strref name, cs_int a, int fl): - cs_ident(cs_ident_type::ALIAS, name, fl), +cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_int a, int fl): + cs_ident_impl(cs_ident_type::ALIAS, name, fl), p_acode(nullptr), p_astack(nullptr), p_val{cs} { p_val.set_int(a); } -cs_alias::cs_alias(cs_state &cs, cs_strref name, cs_float a, int fl): - cs_ident(cs_ident_type::ALIAS, name, fl), +cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_float a, int fl): + cs_ident_impl(cs_ident_type::ALIAS, name, fl), p_acode(nullptr), p_astack(nullptr), p_val{cs} { p_val.set_float(a); } -cs_alias::cs_alias(cs_state &cs, cs_strref name, int fl): - cs_ident(cs_ident_type::ALIAS, name, fl), +cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, int fl): + cs_ident_impl(cs_ident_type::ALIAS, name, fl), p_acode(nullptr), p_astack(nullptr), p_val{cs} { p_val.set_none(); } /* FIXME: use cs rather than val's cs */ -cs_alias::cs_alias(cs_state &, cs_strref name, cs_value v, int fl): - cs_ident(cs_ident_type::ALIAS, name, fl), +cs_alias_impl::cs_alias_impl(cs_state &, cs_strref name, cs_value v, int fl): + cs_ident_impl(cs_ident_type::ALIAS, name, fl), p_acode(nullptr), p_astack(nullptr), p_val(v) {} -cs_command::cs_command( +cs_command_impl::cs_command_impl( cs_strref name, cs_strref args, int nargs, cs_command_cb f ): - cs_ident(cs_ident_type::COMMAND, name, 0), + cs_ident_impl(cs_ident_type::COMMAND, name, 0), p_cargs(args), p_cb_cftv(std::move(f)), p_numargs(nargs) {} @@ -116,14 +116,14 @@ cs_command *cs_ident::get_command() { if (!is_command()) { return nullptr; } - return static_cast(this); + return static_cast(this); } cs_command const *cs_ident::get_command() const { if (!is_command()) { return nullptr; } - return static_cast(this); + return static_cast(this); } bool cs_ident::is_special() const { @@ -203,47 +203,65 @@ 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 p_minval; + return static_cast(this)->p_minval; } cs_int cs_ivar::get_val_max() const { - return p_maxval; + return static_cast(this)->p_maxval; } cs_int cs_ivar::get_value() const { - return p_storage; + return static_cast(this)->p_storage; } void cs_ivar::set_value(cs_int val) { - p_storage = val; + static_cast(this)->p_storage = val; } cs_float cs_fvar::get_val_min() const { - return p_minval; + return static_cast(this)->p_minval; } cs_float cs_fvar::get_val_max() const { - return p_maxval; + return static_cast(this)->p_maxval; } cs_float cs_fvar::get_value() const { - return p_storage; + return static_cast(this)->p_storage; } void cs_fvar::set_value(cs_float val) { - p_storage = val; + static_cast(this)->p_storage = val; } cs_strref cs_svar::get_value() const { - return p_storage; + return static_cast(this)->p_storage; } void cs_svar::set_value(cs_strref val) { - p_storage = val; + static_cast(this)->p_storage = val; } std::string_view cs_command::get_args() const { - return p_cargs; + return static_cast(this)->p_cargs; } int cs_command::get_num_args() const { - return p_numargs; + return static_cast(this)->p_numargs; } void cs_init_lib_base(cs_state &cs); @@ -261,6 +279,8 @@ cs_state::cs_state(): cs_state{cs_default_alloc, nullptr} {} cs_state::cs_state(cs_alloc_cb func, void *data): p_state(nullptr), p_callhook() { + cs_command *p; + if (!func) { func = cs_default_alloc; } @@ -295,29 +315,34 @@ cs_state::cs_state(cs_alloc_cb func, void *data): throw cs_internal_error{"invalid dbgalias index"}; } - new_command("do", "e", [](auto &cs, auto args, auto &res) { + p = new_command("do", "e", [](auto &cs, auto args, auto &res) { cs.run(args[0].get_code(), res); - })->p_type = CsIdDo; + }); + static_cast(p)->p_type = CsIdDo; - new_command("doargs", "e", [](auto &cs, auto args, auto &res) { + 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); }); - })->p_type = CsIdDoArgs; + }); + static_cast(p)->p_type = CsIdDoArgs; - new_command("if", "tee", [](auto &cs, auto args, auto &res) { + p = new_command("if", "tee", [](auto &cs, auto args, auto &res) { cs.run((args[0].get_bool() ? args[1] : args[2]).get_code(), res); - })->p_type = CsIdIf; + }); + static_cast(p)->p_type = CsIdIf; - new_command("result", "t", [](auto &, auto args, auto &res) { + p = new_command("result", "t", [](auto &, auto args, auto &res) { res = std::move(args[0]); - })->p_type = CsIdResult; + }); + static_cast(p)->p_type = CsIdResult; - new_command("!", "t", [](auto &, auto args, auto &res) { + p = new_command("!", "t", [](auto &, auto args, auto &res) { res.set_int(!args[0].get_bool()); - })->p_type = CsIdNot; + }); + static_cast(p)->p_type = CsIdNot; - new_command("&&", "E1V", [](auto &cs, auto args, auto &res) { + p = new_command("&&", "E1V", [](auto &cs, auto args, auto &res) { if (args.empty()) { res.set_int(1); } else { @@ -333,9 +358,10 @@ cs_state::cs_state(cs_alloc_cb func, void *data): } } } - })->p_type = CsIdAnd; + }); + static_cast(p)->p_type = CsIdAnd; - new_command("||", "E1V", [](auto &cs, auto args, auto &res) { + p = new_command("||", "E1V", [](auto &cs, auto args, auto &res) { if (args.empty()) { res.set_int(0); } else { @@ -351,25 +377,29 @@ cs_state::cs_state(cs_alloc_cb func, void *data): } } } - })->p_type = CsIdOr; + }); + static_cast(p)->p_type = CsIdOr; - new_command("local", "", nullptr)->p_type = CsIdLocal; + p = new_command("local", "", nullptr); + static_cast(p)->p_type = CsIdLocal; - new_command("break", "", [](auto &cs, auto, auto &) { + p = new_command("break", "", [](auto &cs, auto, auto &) { if (cs.is_in_loop()) { throw CsBreakException(); } else { throw cs_error(cs, "no loop to break"); } - })->p_type = CsIdBreak; + }); + static_cast(p)->p_type = CsIdBreak; - new_command("continue", "", [](auto &cs, auto, auto &) { + p = new_command("continue", "", [](auto &cs, auto, auto &) { if (cs.is_in_loop()) { throw CsContinueException(); } else { throw cs_error(cs, "no loop to continue"); } - })->p_type = CsIdContinue; + }); + static_cast(p)->p_type = CsIdContinue; cs_init_lib_base(*this); } @@ -387,7 +417,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::destroy() { cs_alias *a = i->get_alias(); if (a) { a->get_value().force_none(); - cs_alias_internal::clean_code(a); + cs_alias_internal::clean_code(static_cast(a)); } p_state->destroy(i); } @@ -438,25 +468,25 @@ LIBCUBESCRIPT_EXPORT void cs_state::clear_override(cs_ident &id) { } switch (id.get_type()) { case cs_ident_type::ALIAS: { - cs_alias &a = static_cast(id); + cs_alias_impl &a = static_cast(id); cs_alias_internal::clean_code(&a); a.get_value().set_str(""); break; } case cs_ident_type::IVAR: { - cs_ivar &iv = static_cast(id); + cs_ivar_impl &iv = static_cast(id); iv.set_value(iv.p_overrideval); iv.changed(*this); break; } case cs_ident_type::FVAR: { - cs_fvar &fv = static_cast(id); + cs_fvar_impl &fv = static_cast(id); fv.set_value(fv.p_overrideval); fv.changed(*this); break; } case cs_ident_type::SVAR: { - cs_svar &sv = static_cast(id); + cs_svar_impl &sv = static_cast(id); sv.set_value(sv.p_overrideval); sv.changed(*this); break; @@ -464,7 +494,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::clear_override(cs_ident &id) { default: break; } - id.p_flags &= ~CS_IDF_OVERRIDDEN; + id.p_impl->p_flags &= ~CS_IDF_OVERRIDDEN; } LIBCUBESCRIPT_EXPORT void cs_state::clear_overrides() { @@ -473,12 +503,15 @@ LIBCUBESCRIPT_EXPORT void cs_state::clear_overrides() { } } -LIBCUBESCRIPT_EXPORT cs_ident *cs_state::add_ident(cs_ident *id) { +LIBCUBESCRIPT_EXPORT cs_ident *cs_state::add_ident( + cs_ident *id, cs_ident_impl *impl +) { if (!id) { return nullptr; } + id->p_impl = impl; p_state->idents[id->get_name()] = id; - id->p_index = p_state->identmap.size(); + static_cast(impl)->p_index = p_state->identmap.size(); p_state->identmap.push_back(id); return p_state->identmap.back(); } @@ -491,9 +524,10 @@ LIBCUBESCRIPT_EXPORT cs_ident *cs_state::new_ident(std::string_view name, int fl *this, "number %s is not a valid identifier name", name.data() ); } - id = add_ident(p_state->create( + auto *inst = p_state->create( *this, cs_strref{*p_state, name}, flags - )); + ); + id = add_ident(inst, inst); } return id; } @@ -549,26 +583,32 @@ LIBCUBESCRIPT_EXPORT std::span cs_state::get_idents() const { LIBCUBESCRIPT_EXPORT cs_ivar *cs_state::new_ivar( std::string_view n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags ) { - return add_ident(p_state->create( + auto *iv = p_state->create( cs_strref{*p_state, n}, m, x, v, std::move(f), flags - ))->get_ivar(); + ); + add_ident(iv, iv); + return iv; } LIBCUBESCRIPT_EXPORT cs_fvar *cs_state::new_fvar( std::string_view n, cs_float m, cs_float x, cs_float v, cs_var_cb f, int flags ) { - return add_ident(p_state->create( + auto *fv = p_state->create( cs_strref{*p_state, n}, m, x, v, std::move(f), flags - ))->get_fvar(); + ); + add_ident(fv, fv); + return fv; } LIBCUBESCRIPT_EXPORT cs_svar *cs_state::new_svar( std::string_view n, std::string_view v, cs_var_cb f, int flags ) { - return add_ident(p_state->create( + auto *sv = p_state->create( cs_strref{*p_state, n}, cs_strref{*p_state, v}, cs_strref{*p_state, ""}, std::move(f), flags - ))->get_svar(); + ); + add_ident(sv, sv); + return sv; } LIBCUBESCRIPT_EXPORT void cs_state::reset_var(std::string_view name) { @@ -585,7 +625,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::reset_var(std::string_view name) { LIBCUBESCRIPT_EXPORT void cs_state::touch_var(std::string_view name) { cs_ident *id = get_ident(name); if (id && id->is_var()) { - static_cast(id)->changed(*this); + static_cast(id->p_impl)->changed(*this); } } @@ -594,7 +634,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_alias(std::string_view name, cs_value v) if (id) { switch (id->get_type()) { case cs_ident_type::ALIAS: { - cs_alias *a = static_cast(id); + cs_alias_impl *a = static_cast(id); if (a->get_index() < MaxArguments) { cs_alias_internal::set_arg(a, *this, v); } else { @@ -620,9 +660,10 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_alias(std::string_view name, cs_value v) } else if (cs_check_num(name)) { throw cs_error(*this, "cannot alias number %s", name.data()); } else { - add_ident(p_state->create( + auto *a = p_state->create( *this, cs_strref{*p_state, name}, std::move(v), identflags - )); + ); + add_ident(a, a); } } @@ -630,16 +671,21 @@ LIBCUBESCRIPT_EXPORT void cs_state::print_var(cs_var const &v) const { p_state->varprintf(*this, v); } +LIBCUBESCRIPT_EXPORT cs_value cs_alias::get_value() const { + return static_cast(this)->p_val; +} + void cs_alias::get_cval(cs_value &v) const { - switch (p_val.get_type()) { + auto *imp = static_cast(this); + switch (imp->p_val.get_type()) { case cs_value_type::STRING: - v = p_val; + v = imp->p_val; break; case cs_value_type::INT: - v.set_int(p_val.get_int()); + v.set_int(imp->p_val.get_int()); break; case cs_value_type::FLOAT: - v.set_float(p_val.get_float()); + v.set_float(imp->p_val.get_float()); break; default: v.set_none(); @@ -647,23 +693,27 @@ void cs_alias::get_cval(cs_value &v) const { } } +int cs_ident::get_raw_type() const { + return p_impl->p_type; +} + cs_ident_type cs_ident::get_type() const { - if (p_type > CsIdAlias) { + if (p_impl->p_type > CsIdAlias) { return cs_ident_type::SPECIAL; } - return cs_ident_type(p_type); + return cs_ident_type(p_impl->p_type); } std::string_view cs_ident::get_name() const { - return p_name; + return p_impl->p_name; } int cs_ident::get_flags() const { - return p_flags; + return p_impl->p_flags; } int cs_ident::get_index() const { - return p_index; + return p_impl->p_index; } template @@ -693,7 +743,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_int( if (!id || id->is_ivar()) { return; } - cs_ivar *iv = static_cast(id); + cs_ivar_impl *iv = static_cast(id); cs_override_var( *this, iv, iv->p_flags, [&iv]() { iv->p_overrideval = iv->get_value(); } @@ -715,7 +765,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_float( if (!id || id->is_fvar()) { return; } - cs_fvar *fv = static_cast(id); + cs_fvar_impl *fv = static_cast(id); cs_override_var( *this, fv, fv->p_flags, [&fv]() { fv->p_overrideval = fv->get_value(); } @@ -737,7 +787,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_str( if (!id || id->is_svar()) { return; } - cs_svar *sv = static_cast(id); + cs_svar_impl *sv = static_cast(id); cs_override_var( *this, sv, sv->p_flags, [&sv]() { sv->p_overrideval = sv->get_value(); } @@ -850,15 +900,16 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_int_checked(cs_ivar *iv, cs_int v) { *this, "variable '%s' is read only", iv->get_name().data() ); } + cs_ivar_impl *ivp = static_cast(iv); cs_override_var( - *this, iv, iv->p_flags, - [&iv]() { iv->p_overrideval = iv->get_value(); } + *this, iv, ivp->p_flags, + [&ivp]() { ivp->p_overrideval = ivp->p_storage; } ); if ((v < iv->get_val_min()) || (v > iv->get_val_max())) { v = cs_clamp_var(*this, iv, v); } iv->set_value(v); - iv->changed(*this); + ivp->changed(*this); } LIBCUBESCRIPT_EXPORT void cs_state::set_var_int_checked( @@ -898,15 +949,16 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_float_checked(cs_fvar *fv, cs_float *this, "variable '%s' is read only", fv->get_name().data() ); } + cs_fvar_impl *fvp = static_cast(fv); cs_override_var( - *this, fv, fv->p_flags, - [&fv]() { fv->p_overrideval = fv->get_value(); } + *this, fv, fvp->p_flags, + [&fvp]() { fvp->p_overrideval = fvp->p_storage; } ); if ((v < fv->get_val_min()) || (v > fv->get_val_max())) { v = cs_clamp_fvar(*this, fv, v); } fv->set_value(v); - fv->changed(*this); + fvp->changed(*this); } LIBCUBESCRIPT_EXPORT void cs_state::set_var_str_checked( @@ -917,12 +969,13 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_str_checked( *this, "variable '%s' is read only", sv->get_name().data() ); } + cs_svar_impl *svp = static_cast(sv); cs_override_var( - *this, sv, sv->p_flags, - [&sv]() { sv->p_overrideval = sv->get_value(); } + *this, sv, svp->p_flags, + [&svp]() { svp->p_overrideval = svp->p_storage; } ); sv->set_value(cs_strref{*p_state, v}); - sv->changed(*this); + svp->changed(*this); } LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command( @@ -974,10 +1027,12 @@ LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command( return nullptr; } } - return static_cast(add_ident(p_state->create( + auto *cmd = p_state->create( cs_strref{*p_state, name}, cs_strref{*p_state, args}, nargs, - std::move(func)) - )); + std::move(func) + ); + add_ident(cmd, cmd); + return cmd; } static inline void cs_do_loop( @@ -1061,8 +1116,12 @@ void cs_init_lib_base(cs_state &gcs) { rc = false; } ret.set_int(rc); - cs_alias_internal::set_alias(cret, cs, result); - cs_alias_internal::set_alias(css, cs, tback); + cs_alias_internal::set_alias( + static_cast(cret), cs, result + ); + cs_alias_internal::set_alias( + static_cast(css), cs, tback + ); }); gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) {