diff --git a/src/cs_val.cc b/src/cs_val.cc index bd7b90a..81b17ab 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -417,9 +417,7 @@ bool cs_stacked_value::push() { if (!p_a) { return false; } - cs_alias_internal::push_arg( - static_cast(p_a), *this, p_stack - ); + static_cast(p_a)->push_arg(*this, p_stack); p_pushed = true; return true; } @@ -428,7 +426,7 @@ bool cs_stacked_value::pop() { if (!p_pushed || !p_a) { return false; } - cs_alias_internal::pop_arg(static_cast(p_a)); + static_cast(p_a)->pop_arg(); p_pushed = false; return true; } diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 648113b..ab2075d 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -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); + static_cast(id)->push_arg(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)); + static_cast(id)->pop_arg(); } } @@ -469,8 +469,7 @@ static inline void cs_call_alias( cs_ivar *anargs = static_cast(cs.p_state->identmap[NumargsIdx]); 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])->push_arg( args[offset + i], argstack[i], false ); } @@ -483,7 +482,7 @@ static inline void cs_call_alias( }; cs.p_callstack = &aliaslink; uint32_t *codep = reinterpret_cast( - cs_alias_internal::compile_code(static_cast(a), cs) + static_cast(a)->compile_code(cs) ); bcode_incr(codep); cs_do_and_cleanup([&]() { @@ -493,16 +492,14 @@ static inline void cs_call_alias( cs.p_callstack = aliaslink.next; 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])->pop_arg(); } int argmask = aliaslink.usedargs & int(~0U << callargs); for (; argmask; ++callargs) { if (argmask & (1 << callargs)) { - cs_alias_internal::pop_arg(static_cast( - cs.p_state->identmap[callargs]) - ); + static_cast( + cs.p_state->identmap[callargs] + )->pop_arg(); argmask &= ~(1 << callargs); } } @@ -952,9 +949,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( - static_cast(a), nv, - cs.p_callstack->argstack[a->get_index()], false + static_cast(a)->push_arg( + nv, cs.p_callstack->argstack[a->get_index()], false ); cs.p_callstack->usedargs |= 1 << a->get_index(); } @@ -969,9 +965,8 @@ 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, - cs.p_callstack->argstack[id->get_index()], false + static_cast(id)->push_arg( + nv, cs.p_callstack->argstack[id->get_index()], false ); cs.p_callstack->usedargs |= 1 << id->get_index(); } @@ -1401,16 +1396,14 @@ 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]), - cs, args[--numargs] - ); + static_cast( + cs.p_state->identmap[op >> 8] + )->set_alias(cs, args[--numargs]); continue; case CS_CODE_ALIAS_ARG: - cs_alias_internal::set_arg( - static_cast(cs.p_state->identmap[op >> 8]), - cs, args[--numargs] - ); + static_cast( + cs.p_state->identmap[op >> 8] + )->set_arg(cs, args[--numargs]); continue; case CS_CODE_ALIAS_U: numargs -= 2; diff --git a/src/cs_vm.hh b/src/cs_vm.hh index b840945..8fe976a 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -78,6 +78,20 @@ struct cs_svar_impl: cs_var_impl, cs_svar { 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); @@ -86,6 +100,69 @@ struct cs_alias_impl: cs_ident_impl, cs_alias { 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; @@ -99,13 +176,6 @@ struct cs_command_impl: cs_ident_impl, cs_command { int p_numargs; }; -struct cs_ident_link { - cs_ident *id; - cs_ident_link *next; - int usedargs; - cs_ident_stack *argstack; -}; - template struct cs_valarray { cs_valarray(cs_state &cs) { @@ -358,98 +428,27 @@ static inline void bcode_decr(uint32_t *bc) { } } -static inline bool cs_is_arg_used(cs_state &cs, cs_ident *id) { - if (!cs.p_callstack) { - return true; +inline void cs_alias_impl::clean_code() { + uint32_t *bcode = reinterpret_cast(p_acode); + if (bcode) { + bcode_decr(bcode); + p_acode = nullptr; } - return cs.p_callstack->usedargs & (1 << id->get_index()); } -struct cs_alias_internal { - static void push_arg( - 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 */ - a->p_val = std::move(v); - clean_code(a); - return; - } - st.val_s = std::move(a->p_val); - st.next = a->p_astack; - a->p_astack = &st; - a->p_val = std::move(v); - clean_code(a); - if (um) { - a->p_flags &= ~CS_IDF_UNKNOWN; - } +inline 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 = new uint32_t[gs.code.size()]; + memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t)); + bcode_incr(code); + p_acode = reinterpret_cast(code); } - - static void pop_arg(cs_alias_impl *a) { - if (!a->p_astack) { - return; - } - cs_ident_stack *st = a->p_astack; - a->p_val = std::move(a->p_astack->val_s); - clean_code(a); - a->p_astack = st->next; - } - - 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; - a->p_astack = prev->next; - a->p_val = std::move(prev->val_s); - clean_code(a); - } - - 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; - a->p_val = std::move(st.val_s); - clean_code(a); - } - - 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); - } else { - push_arg(a, v, cs.p_callstack->argstack[a->get_index()], false); - cs.p_callstack->usedargs |= 1 << a->get_index(); - } - } - - 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_impl *a) { - uint32_t *bcode = reinterpret_cast(a->p_acode); - if (bcode) { - bcode_decr(bcode); - a->p_acode = nullptr; - } - } - - 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); - gs.gen_main(a->get_value().get_str()); - /* i wish i could steal the memory somehow */ - uint32_t *code = new uint32_t[gs.code.size()]; - memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t)); - bcode_incr(code); - a->p_acode = reinterpret_cast(code); - } - return a->p_acode; - } -}; + return p_acode; +} template static void cs_do_args(cs_state &cs, F body) { @@ -461,8 +460,8 @@ static void cs_do_args(cs_state &cs, F body) { int argmask1 = cs.p_callstack->usedargs; 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])->undo_arg( + argstack[i] ); } } @@ -481,8 +480,8 @@ static void cs_do_args(cs_state &cs, F body) { int argmask2 = cs.p_callstack->usedargs; 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])->redo_arg( + argstack[i] ); } } diff --git a/src/cubescript.cc b/src/cubescript.cc index 15b8b2e..656d564 100644 --- a/src/cubescript.cc +++ b/src/cubescript.cc @@ -417,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(static_cast(a)); + static_cast(a)->clean_code(); } p_state->destroy(i); } @@ -469,7 +469,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::clear_override(cs_ident &id) { switch (id.get_type()) { case cs_ident_type::ALIAS: { cs_alias_impl &a = static_cast(id); - cs_alias_internal::clean_code(&a); + a.clean_code(); a.get_value().set_str(""); break; } @@ -636,9 +636,9 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_alias(std::string_view name, cs_value v) case cs_ident_type::ALIAS: { cs_alias_impl *a = static_cast(id); if (a->get_index() < MaxArguments) { - cs_alias_internal::set_arg(a, *this, v); + a->set_arg(*this, v); } else { - cs_alias_internal::set_alias(a, *this, v); + a->set_alias(*this, v); } return; } @@ -1116,12 +1116,8 @@ void cs_init_lib_base(cs_state &gcs) { rc = false; } ret.set_int(rc); - cs_alias_internal::set_alias( - static_cast(cret), cs, result - ); - cs_alias_internal::set_alias( - static_cast(css), cs, tback - ); + static_cast(cret)->set_alias(cs, result); + static_cast(css)->set_alias(cs, tback); }); gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) {