diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index 319eb9a..4794469 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -318,8 +318,6 @@ enum class loop_state { NORMAL = 0, BREAK, CONTINUE }; -struct thread_state; - struct LIBCUBESCRIPT_EXPORT state { state(); state(alloc_func func, void *data); @@ -419,15 +417,9 @@ struct LIBCUBESCRIPT_EXPORT state { std::optional get_alias_val(std::string_view name); - thread_state *thread_pointer() { - return p_tstate; - } - - thread_state const *thread_pointer() const { - return p_tstate; - } - private: + friend struct state_p; + hook_func set_call_hook(hook_func func); command *new_command( @@ -444,7 +436,7 @@ private: void *alloc(void *ptr, size_t olds, size_t news); - thread_state *p_tstate = nullptr; + struct thread_state *p_tstate = nullptr; }; struct LIBCUBESCRIPT_EXPORT stack_state { @@ -455,7 +447,7 @@ struct LIBCUBESCRIPT_EXPORT stack_state { }; stack_state() = delete; - stack_state(thread_state &ts, node *nd = nullptr, bool gap = false); + stack_state(state &cs, node *nd = nullptr, bool gap = false); stack_state(stack_state const &) = delete; stack_state(stack_state &&st); ~stack_state(); @@ -467,7 +459,7 @@ struct LIBCUBESCRIPT_EXPORT stack_state { bool gap() const; private: - thread_state &p_state; + state &p_state; node *p_node; bool p_gap; }; @@ -494,31 +486,26 @@ struct LIBCUBESCRIPT_EXPORT error { return p_stack; } - template - error(state &cs, std::string_view msg, A const &...args): - error{*cs.thread_pointer(), msg, args...} - {} - - error(thread_state &ts, std::string_view msg): - p_errbeg{}, p_errend{}, p_stack{ts} + error(state &cs, std::string_view msg): + p_errbeg{}, p_errend{}, p_stack{cs} { char *sp; - char *buf = request_buf(ts, msg.size(), sp); + char *buf = request_buf(cs, msg.size(), sp); std::memcpy(buf, msg.data(), msg.size()); buf[msg.size()] = '\0'; p_errbeg = sp; p_errend = buf + msg.size(); - p_stack = save_stack(ts); + p_stack = save_stack(cs); } template - error(thread_state &ts, std::string_view msg, A const &...args): - p_errbeg{}, p_errend{}, p_stack{ts} + error(state &cs, std::string_view msg, A const &...args): + p_errbeg{}, p_errend{}, p_stack{cs} { std::size_t sz = msg.size() + 64; char *buf, *sp; for (;;) { - buf = request_buf(ts, sz, sp); + buf = request_buf(cs, sz, sp); int written = std::snprintf(buf, sz, msg.data(), args...); if (written <= 0) { throw internal_error{"format error"}; @@ -529,12 +516,12 @@ struct LIBCUBESCRIPT_EXPORT error { } p_errbeg = sp; p_errend = buf + sz; - p_stack = save_stack(ts); + p_stack = save_stack(cs); } private: - stack_state save_stack(thread_state &ts); - char *request_buf(thread_state &ts, std::size_t bufs, char *&sp); + stack_state save_stack(state &cs); + char *request_buf(state &cs, std::size_t bufs, char *&sp); char const *p_errbeg, *p_errend; stack_state p_stack; diff --git a/src/cs_error.cc b/src/cs_error.cc index 05e2396..3149e3e 100644 --- a/src/cs_error.cc +++ b/src/cs_error.cc @@ -8,9 +8,9 @@ namespace cubescript { LIBCUBESCRIPT_EXPORT stack_state::stack_state( - thread_state &ts, node *nd, bool gap + state &cs, node *nd, bool gap ): - p_state{ts}, p_node{nd}, p_gap{gap} + p_state{cs}, p_node{nd}, p_gap{gap} {} LIBCUBESCRIPT_EXPORT stack_state::stack_state(stack_state &&st): @@ -25,7 +25,7 @@ LIBCUBESCRIPT_EXPORT stack_state::~stack_state() { for (node const *nd = p_node; nd; nd = nd->next) { ++len; } - p_state.istate->destroy_array(p_node, len); + state_p{p_state}.ts().istate->destroy_array(p_node, len); } LIBCUBESCRIPT_EXPORT stack_state &stack_state::operator=(stack_state &&st) { @@ -45,8 +45,9 @@ LIBCUBESCRIPT_EXPORT bool stack_state::gap() const { } LIBCUBESCRIPT_EXPORT char *error::request_buf( - thread_state &ts, std::size_t bufs, char *&sp + state &cs, std::size_t bufs, char *&sp ) { + auto &ts = state_p{cs}.ts(); charbuf &cb = ts.errbuf; codegen_state *gs = ts.cstate; cb.clear(); @@ -83,20 +84,21 @@ LIBCUBESCRIPT_EXPORT char *error::request_buf( return &cb[sz]; } -LIBCUBESCRIPT_EXPORT stack_state error::save_stack(thread_state &ts) { +LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) { + auto &ts = state_p{cs}.ts(); integer_var *dalias = ts.istate->ivar_dbgalias; auto dval = std::clamp( dalias->get_value(), integer_type(0), integer_type(1000) ); if (!dval) { - return stack_state{ts, nullptr, !!ts.callstack}; + return stack_state{cs, nullptr, !!ts.callstack}; } int total = 0, depth = 0; for (ident_link *l = ts.callstack; l; l = l->next) { total++; } if (!total) { - return stack_state{ts, nullptr, false}; + return stack_state{cs, nullptr, false}; } stack_state::node *st = ts.istate->create_array( std::min(total, dval) @@ -120,7 +122,7 @@ LIBCUBESCRIPT_EXPORT stack_state error::save_stack(thread_state &ts) { nd->next = nullptr; } } - return stack_state{ts, ret, total > dval}; + return stack_state{cs, ret, total > dval}; } } /* namespace cubescript */ diff --git a/src/cs_gen.cc b/src/cs_gen.cc index 3726a92..1ee9623 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -69,7 +69,7 @@ void codegen_state::skip_comments() { if (current() == '\\') { char c = current(1); if ((c != '\r') && (c != '\n')) { - throw error{ts, "invalid line break"}; + throw error{*ts.pstate, "invalid line break"}; } /* skip backslash */ next_char(); @@ -551,7 +551,7 @@ static void compileblockmain(codegen_state &gs, int wordtype) { for (int brak = 1; brak;) { switch (gs.skip_until("@\"/[]")) { case '\0': - throw error{gs.ts, "missing \"]\""}; + throw error{*gs.ts.pstate, "missing \"]\""}; return; case '\"': gs.get_str(); @@ -580,7 +580,7 @@ static void compileblockmain(codegen_state &gs, int wordtype) { if (brak > level) { continue; } else if (brak < level) { - throw error{gs.ts, "too many @s"}; + throw error{*gs.ts.pstate, "too many @s"}; return; } if (compileblockstr(gs, start, esc)) { @@ -1362,7 +1362,7 @@ endstatement: switch (gs.skip_until(")];/\n")) { case '\0': if (gs.current() != brak) { - throw error{gs.ts, "missing \"%c\"", char(brak)}; + throw error{*gs.ts.pstate, "missing \"%c\"", char(brak)}; return; } return; @@ -1372,7 +1372,7 @@ endstatement: gs.next_char(); return; } - throw error{gs.ts, "unexpected \"%c\"", gs.current()}; + throw error{*gs.ts.pstate, "unexpected \"%c\"", gs.current()}; return; case '/': gs.next_char(); diff --git a/src/cs_ident.cc b/src/cs_ident.cc index df36e55..bbc0e12 100644 --- a/src/cs_ident.cc +++ b/src/cs_ident.cc @@ -302,7 +302,7 @@ LIBCUBESCRIPT_EXPORT bool ident::is_overridden(state &cs) const { case ident_type::SVAR: return (p_impl->p_flags & IDENT_FLAG_OVERRIDDEN); case ident_type::ALIAS: - return (cs.thread_pointer()->get_astack( + return (state_p{cs}.ts().get_astack( static_cast(this) ).flags & IDENT_FLAG_OVERRIDDEN); default: @@ -318,7 +318,7 @@ LIBCUBESCRIPT_EXPORT bool ident::is_persistent(state &cs) const { case ident_type::SVAR: return (p_impl->p_flags & IDENT_FLAG_PERSIST); case ident_type::ALIAS: - return (cs.thread_pointer()->get_astack( + return (state_p{cs}.ts().get_astack( static_cast(this) ).flags & IDENT_FLAG_PERSIST); default: @@ -346,7 +346,7 @@ LIBCUBESCRIPT_EXPORT var_type global_var::get_variable_type() const { } LIBCUBESCRIPT_EXPORT void global_var::save(state &cs) { - auto &ts = *cs.thread_pointer(); + auto &ts = state_p{cs}.ts(); if ((ts.ident_flags & IDENT_FLAG_OVERRIDDEN) || is_overridable()) { if (p_impl->p_flags & IDENT_FLAG_PERSIST) { throw error{ @@ -380,7 +380,7 @@ LIBCUBESCRIPT_EXPORT void integer_var::set_value( save(cs); set_raw_value(val); if (trigger) { - var_changed(*cs.thread_pointer(), this); + var_changed(state_p{cs}.ts(), this); } } @@ -406,7 +406,7 @@ LIBCUBESCRIPT_EXPORT void float_var::set_value( save(cs); set_raw_value(val); if (trigger) { - var_changed(*cs.thread_pointer(), this); + var_changed(state_p{cs}.ts(), this); } } @@ -432,7 +432,7 @@ LIBCUBESCRIPT_EXPORT void string_var::set_value( save(cs); set_raw_value(std::move(val)); if (trigger) { - var_changed(*cs.thread_pointer(), this); + var_changed(state_p{cs}.ts(), this); } } @@ -459,7 +459,7 @@ LIBCUBESCRIPT_EXPORT alias_local::alias_local(state &cs, ident *a) { p_alias = nullptr; return; } - auto &ts = *cs.thread_pointer(); + auto &ts = state_p{cs}.ts(); p_alias = static_cast(a); auto &ast = ts.get_astack(p_alias); ast.push(ts.idstack.emplace_back(cs)); diff --git a/src/cs_state.cc b/src/cs_state.cc index 6ae2f0e..0b69cb9 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -180,7 +180,7 @@ state::state(alloc_func func, void *data) { static_cast(p)->p_type = ID_DO; p = new_command("doargs", "e", [](auto &cs, auto args, auto &res) { - call_with_args(*cs.thread_pointer(), [&cs, &res, &args]() { + call_with_args(*cs.p_tstate, [&cs, &res, &args]() { cs.run(args[0].get_code(), res); }); }); @@ -243,7 +243,7 @@ state::state(alloc_func func, void *data) { static_cast(p)->p_type = ID_LOCAL; p = new_command("break", "", [](auto &cs, auto, auto &) { - if (cs.thread_pointer()->loop_level) { + if (cs.p_tstate->loop_level) { throw break_exception{}; } else { throw error{cs, "no loop to break"}; @@ -252,7 +252,7 @@ state::state(alloc_func func, void *data) { static_cast(p)->p_type = ID_BREAK; p = new_command("continue", "", [](auto &cs, auto, auto &) { - if (cs.thread_pointer()->loop_level) { + if (cs.p_tstate->loop_level) { throw continue_exception{}; } else { throw error{cs, "no loop to continue"}; diff --git a/src/cs_state.hh b/src/cs_state.hh index 13195d1..07a44b9 100644 --- a/src/cs_state.hh +++ b/src/cs_state.hh @@ -103,6 +103,14 @@ struct internal_state { } }; +struct state_p { + state_p(state &cs): csp{&cs} {} + + thread_state &ts() { return *csp->p_tstate; } + + state *csp; +}; + template inline std_allocator::std_allocator(internal_state *s): istate{s} {} diff --git a/src/cs_std.cc b/src/cs_std.cc index 0428503..71a5663 100644 --- a/src/cs_std.cc +++ b/src/cs_std.cc @@ -4,7 +4,7 @@ namespace cubescript { -charbuf::charbuf(state &cs): charbuf{cs.thread_pointer()->istate} {} +charbuf::charbuf(state &cs): charbuf{state_p{cs}.ts().istate} {} charbuf::charbuf(thread_state &ts): charbuf{ts.istate} {} } /* namespace cubescript */ diff --git a/src/cs_strman.cc b/src/cs_strman.cc index d6c9c3a..2655844 100644 --- a/src/cs_strman.cc +++ b/src/cs_strman.cc @@ -121,7 +121,7 @@ LIBCUBESCRIPT_EXPORT string_ref::string_ref( } LIBCUBESCRIPT_EXPORT string_ref::string_ref(state &cs, std::string_view str): - p_state{cs.thread_pointer()->istate} + p_state{state_p{cs}.ts().istate} { p_str = p_state->strman->add(str); } diff --git a/src/cs_val.cc b/src/cs_val.cc index ab28ccd..077581d 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -84,7 +84,7 @@ static inline void csv_cleanup(value_type tv, T *stor) { } } -any_value::any_value(state &st): any_value(*st.thread_pointer()->istate) {} +any_value::any_value(state &st): any_value(*state_p{st}.ts().istate) {} any_value::any_value(internal_state &st): p_stor(), p_type(value_type::NONE) @@ -258,11 +258,11 @@ bcode_ref any_value::force_code(state &cs) { default: break; } - codegen_state gs{*cs.thread_pointer()}; + codegen_state gs{state_p{cs}.ts()}; gs.code.reserve(64); gs.gen_main(get_str()); gs.done(); - uint32_t *cbuf = bcode_alloc(cs.thread_pointer()->istate, gs.code.size()); + uint32_t *cbuf = bcode_alloc(state_p{cs}.ts().istate, gs.code.size()); std::memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(std::uint32_t)); auto *bc = reinterpret_cast(cbuf + 1); set_code(bc); @@ -276,7 +276,7 @@ ident *any_value::force_ident(state &cs) { default: break; } - auto *id = cs.thread_pointer()->istate->new_ident( + auto *id = state_p{cs}.ts().istate->new_ident( cs, get_str(), IDENT_FLAG_UNKNOWN ); set_ident(id); diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 4c4bbef..48f380e 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -281,7 +281,7 @@ bool exec_alias( run_depth_guard::run_depth_guard(thread_state &ts): tsp(&ts) { if (ts.max_run_depth && (ts.run_depth >= ts.max_run_depth)) { - throw error{ts, "exceeded recursion limit"}; + throw error{*ts.pstate, "exceeded recursion limit"}; } ++ts.run_depth; } diff --git a/src/lib_base.cc b/src/lib_base.cc index c26e3ef..74a0bd3 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -91,7 +91,7 @@ void init_lib_base(state &gcs) { rc = false; } ret.set_int(rc); - auto &ts = *cs.thread_pointer(); + auto &ts = state_p{cs}.ts(); ts.get_astack(cret).set_alias(cret, ts, result); ts.get_astack(css).set_alias(css, ts, tback); }); diff --git a/src/lib_list.cc b/src/lib_list.cc index b4f2d98..7e474cf 100644 --- a/src/lib_list.cc +++ b/src/lib_list.cc @@ -544,7 +544,7 @@ static void list_sort( return; } - valbuf items{cs.thread_pointer()->istate}; + valbuf items{state_p{cs}.ts().istate}; size_t total = 0; for (list_parser p{cs, list}; p.parse();) { diff --git a/src/lib_str.cc b/src/lib_str.cc index d325e69..8357606 100644 --- a/src/lib_str.cc +++ b/src/lib_str.cc @@ -60,7 +60,7 @@ void init_lib_string(state &cs) { cs.new_command("strlower", "s", [](auto &ccs, auto args, auto &res) { auto inps = std::string_view{args[0].get_str()}; - auto *ics = ccs.thread_pointer()->istate; + auto *ics = state_p{ccs}.ts().istate; auto *buf = ics->strman->alloc_buf(inps.size()); for (std::size_t i = 0; i < inps.size(); ++i) { buf[i] = char(tolower(inps[i])); @@ -70,7 +70,7 @@ void init_lib_string(state &cs) { cs.new_command("strupper", "s", [](auto &ccs, auto args, auto &res) { auto inps = std::string_view{args[0].get_str()}; - auto *ics = ccs.thread_pointer()->istate; + auto *ics = state_p{ccs}.ts().istate; auto *buf = ics->strman->alloc_buf(inps.size()); for (std::size_t i = 0; i < inps.size(); ++i) { buf[i] = char(toupper(inps[i]));