diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index b1a95a5b..aa80f015 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -190,6 +190,9 @@ private: int p_index = -1; }; +using CsIdentRange = ostd::PointerRange; +using CsConstIdentRange = ostd::PointerRange; + using CsVarCb = ostd::Function; struct OSTD_EXPORT CsVar: CsIdent { @@ -369,10 +372,10 @@ private: CsState &p_state; }; -struct OSTD_EXPORT CsState { - CsMap idents; - CsVector identmap; +struct CsSharedState; +struct OSTD_EXPORT CsState { + CsSharedState *p_state; CsIdentLink *p_callstack = nullptr; int identflags = 0; @@ -381,6 +384,10 @@ struct OSTD_EXPORT CsState { CsState(); virtual ~CsState(); + bool is_alive() const { + return bool(p_state); + } + CsStream const &get_out() const; CsStream &get_out(); void set_out(CsStream &s); @@ -492,25 +499,12 @@ struct OSTD_EXPORT CsState { )); } - CsIdent *get_ident(ostd::ConstCharRange name) { - CsIdent **id = idents.at(name); - if (!id) { - return nullptr; - } - return *id; - } + CsIdent *get_ident(ostd::ConstCharRange name); + CsAlias *get_alias(ostd::ConstCharRange name); + bool have_ident(ostd::ConstCharRange name); - CsAlias *get_alias(ostd::ConstCharRange name) { - CsIdent *id = get_ident(name); - if (!id->is_alias()) { - return nullptr; - } - return static_cast(id); - } - - bool have_ident(ostd::ConstCharRange name) { - return idents.at(name) != nullptr; - } + CsIdentRange get_idents(); + CsConstIdentRange get_idents() const; bool reset_var(ostd::ConstCharRange name); void touch_var(ostd::ConstCharRange name); diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 74f457db..652688fe 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -66,7 +66,7 @@ bool CsStackState::gap() const { } CsStackState cs_save_stack(CsState &cs) { - CsIvar *dalias = static_cast(cs.identmap[DbgaliasIdx]); + CsIvar *dalias = static_cast(cs.p_state->identmap[DbgaliasIdx]); if (!dalias->get_value()) { return CsStackState(nullptr, !!cs.p_callstack); } @@ -384,7 +384,7 @@ static inline void callcommand( if (rep) { break; } - args[i].set_ident(cs.identmap[DummyIdx]); + args[i].set_ident(cs.p_state->identmap[DummyIdx]); fakeargs++; } else { cs.force_ident(args[i]); @@ -432,11 +432,11 @@ static inline void cs_call_alias( CsState &cs, CsAlias *a, CsValue *args, CsValue &result, int callargs, int &nargs, int offset, int skip, ostd::Uint32 op ) { - CsIvar *anargs = static_cast(cs.identmap[NumargsIdx]); + CsIvar *anargs = static_cast(cs.p_state->identmap[NumargsIdx]); CsIdentStack argstack[MaxArguments]; for(int i = 0; i < callargs; i++) { CsAliasInternal::push_arg( - static_cast(cs.identmap[i]), + static_cast(cs.p_state->identmap[i]), args[offset + i], argstack[i], false ); } @@ -459,13 +459,15 @@ static inline void cs_call_alias( cs.p_callstack = aliaslink.next; cs.identflags = oldflags; for (int i = 0; i < callargs; i++) { - CsAliasInternal::pop_arg(static_cast(cs.identmap[i])); + CsAliasInternal::pop_arg( + static_cast(cs.p_state->identmap[i]) + ); } int argmask = aliaslink.usedargs & (~0 << callargs); for (; argmask; ++callargs) { if (argmask & (1 << callargs)) { CsAliasInternal::pop_arg(static_cast( - cs.identmap[callargs]) + cs.p_state->identmap[callargs]) ); argmask &= ~(1 << callargs); } @@ -480,7 +482,7 @@ static constexpr int MaxRunDepth = 255; static thread_local int rundepth = 0; static inline CsAlias *cs_get_lookup_id(CsState &cs, ostd::Uint32 op) { - CsIdent *id = cs.identmap[op >> 8]; + CsIdent *id = cs.p_state->identmap[op >> 8]; if (id->get_flags() & CsIdfUnknown) { cs_debug_code(cs, "unknown alias lookup: %s", id->get_name()); } @@ -488,7 +490,7 @@ static inline CsAlias *cs_get_lookup_id(CsState &cs, ostd::Uint32 op) { } static inline CsAlias *cs_get_lookuparg_id(CsState &cs, ostd::Uint32 op) { - CsIdent *id = cs.identmap[op >> 8]; + CsIdent *id = cs.p_state->identmap[op >> 8]; if (!cs_is_arg_used(cs, id)) { return nullptr; } @@ -631,7 +633,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { args[numargs++] = ostd::move(result); continue; case CsCodePrint: - cs.print_var(static_cast(cs.identmap[op >> 8])); + cs.print_var(static_cast(cs.p_state->identmap[op >> 8])); continue; case CsCodeLocal: { @@ -892,10 +894,12 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { } case CsCodeIdent: - args[numargs++].set_ident(cs.identmap[op >> 8]); + args[numargs++].set_ident(cs.p_state->identmap[op >> 8]); continue; case CsCodeIdentArg: { - CsAlias *a = static_cast(cs.identmap[op >> 8]); + CsAlias *a = static_cast( + cs.p_state->identmap[op >> 8] + ); if (!cs_is_arg_used(cs, a)) { CsValue nv; CsAliasInternal::push_arg( @@ -908,7 +912,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { } case CsCodeIdentU: { CsValue &arg = args[numargs - 1]; - CsIdent *id = cs.identmap[DummyIdx]; + CsIdent *id = cs.p_state->identmap[DummyIdx]; if ( arg.get_type() == CsValueType::String || arg.get_type() == CsValueType::Macro || @@ -1176,58 +1180,58 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeSvar | CsRetString: case CsCodeSvar | CsRetNull: - args[numargs++].set_str( - static_cast(cs.identmap[op >> 8])->get_value() - ); + args[numargs++].set_str(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value()); continue; case CsCodeSvar | CsRetInt: - args[numargs++].set_int(cs_parse_int( - static_cast(cs.identmap[op >> 8])->get_value() - )); + args[numargs++].set_int(cs_parse_int(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value())); continue; case CsCodeSvar | CsRetFloat: - args[numargs++].set_float(cs_parse_float( - static_cast(cs.identmap[op >> 8])->get_value() - )); + args[numargs++].set_float(cs_parse_float(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value())); continue; case CsCodeSvarM: - args[numargs++].set_cstr( - static_cast(cs.identmap[op >> 8])->get_value() - ); + args[numargs++].set_cstr(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value()); continue; case CsCodeSvar1: cs.set_var_str_checked( - static_cast(cs.identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), args[--numargs].get_strr() ); continue; case CsCodeIvar | CsRetInt: case CsCodeIvar | CsRetNull: - args[numargs++].set_int( - static_cast(cs.identmap[op >> 8])->get_value() - ); + args[numargs++].set_int(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value()); continue; case CsCodeIvar | CsRetString: - args[numargs++].set_str(ostd::move(intstr( - static_cast(cs.identmap[op >> 8])->get_value() - ))); + args[numargs++].set_str(ostd::move(intstr(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value()))); continue; case CsCodeIvar | CsRetFloat: - args[numargs++].set_float(CsFloat( - static_cast(cs.identmap[op >> 8])->get_value() - )); + args[numargs++].set_float(CsFloat(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value())); continue; case CsCodeIvar1: cs.set_var_int_checked( - static_cast(cs.identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), args[--numargs].get_int() ); continue; case CsCodeIvar2: numargs -= 2; cs.set_var_int_checked( - static_cast(cs.identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), (args[numargs].get_int() << 16) | (args[numargs + 1].get_int() << 8) ); @@ -1235,7 +1239,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeIvar3: numargs -= 3; cs.set_var_int_checked( - static_cast(cs.identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), (args[numargs].get_int() << 16) | (args[numargs + 1].get_int() << 8) | (args[numargs + 2].get_int())); @@ -1243,23 +1247,25 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeFvar | CsRetFloat: case CsCodeFvar | CsRetNull: - args[numargs++].set_float( - static_cast(cs.identmap[op >> 8])->get_value() - ); + args[numargs++].set_float(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value()); continue; case CsCodeFvar | CsRetString: args[numargs++].set_str(ostd::move(floatstr( - static_cast(cs.identmap[op >> 8])->get_value() + static_cast( + cs.p_state->identmap[op >> 8] + )->get_value() ))); continue; case CsCodeFvar | CsRetInt: - args[numargs++].set_int(int( - static_cast(cs.identmap[op >> 8])->get_value() - )); + args[numargs++].set_int(int(static_cast( + cs.p_state->identmap[op >> 8] + )->get_value())); continue; case CsCodeFvar1: cs.set_var_float_checked( - static_cast(cs.identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), args[--numargs].get_float() ); continue; @@ -1268,7 +1274,9 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeCom | CsRetString: case CsCodeCom | CsRetFloat: case CsCodeCom | CsRetInt: { - CsCommand *id = static_cast(cs.identmap[op >> 8]); + CsCommand *id = static_cast( + cs.p_state->identmap[op >> 8] + ); int offset = numargs - id->get_num_args(); result.force_null(); CsCommandInternal::call( @@ -1284,7 +1292,9 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeComV | CsRetString: case CsCodeComV | CsRetFloat: case CsCodeComV | CsRetInt: { - CsCommand *id = static_cast(cs.identmap[op >> 13]); + CsCommand *id = static_cast( + cs.p_state->identmap[op >> 13] + ); int callargs = (op >> 8) & 0x1F, offset = numargs - callargs; result.force_null(); CsCommandInternal::call( @@ -1298,7 +1308,9 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeComC | CsRetString: case CsCodeComC | CsRetFloat: case CsCodeComC | CsRetInt: { - CsCommand *id = static_cast(cs.identmap[op >> 13]); + CsCommand *id = static_cast( + cs.p_state->identmap[op >> 13] + ); int callargs = (op >> 8) & 0x1F, offset = numargs - callargs; result.force_null(); { @@ -1353,13 +1365,13 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeAlias: CsAliasInternal::set_alias( - static_cast(cs.identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), cs, args[--numargs] ); continue; case CsCodeAliasArg: CsAliasInternal::set_arg( - static_cast(cs.identmap[op >> 8]), + static_cast(cs.p_state->identmap[op >> 8]), cs, args[--numargs] ); continue; @@ -1375,7 +1387,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeCall | CsRetFloat: case CsCodeCall | CsRetInt: { result.force_null(); - CsIdent *id = cs.identmap[op >> 13]; + CsIdent *id = cs.p_state->identmap[op >> 13]; int callargs = (op >> 8) & 0x1F, offset = numargs - callargs; if (id->get_flags() & CsIdfUnknown) { cs_debug_code(cs, "unknown command: %s", id->get_name()); @@ -1394,7 +1406,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CsCodeCallArg | CsRetFloat: case CsCodeCallArg | CsRetInt: { result.force_null(); - CsIdent *id = cs.identmap[op >> 13]; + CsIdent *id = cs.p_state->identmap[op >> 13]; int callargs = (op >> 8) & 0x1F, offset = numargs - callargs; if (!cs_is_arg_used(cs, id)) { numargs = offset; diff --git a/src/cs_vm.hh b/src/cs_vm.hh index 5d008f88..80bd9c33 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -89,6 +89,11 @@ enum { CsRetFloat = CsValFloat << CsCodeRet, }; +struct CsSharedState { + CsMap idents; + CsVector identmap; +}; + template constexpr ostd::Size CsTypeStorageSize = (sizeof(T) - 1) / sizeof(ostd::Uint32) + 1; @@ -202,7 +207,7 @@ struct GenState { } void gen_ident() { - gen_ident(cs.identmap[DummyIdx]); + gen_ident(cs.p_state->identmap[DummyIdx]); } void gen_ident(ostd::ConstCharRange word) { @@ -343,7 +348,7 @@ static void cs_do_args(CsState &cs, F body) { for (int i = 0; argmask1; argmask1 >>= 1, ++i) { if (argmask1 & 1) { CsAliasInternal::undo_arg( - static_cast(cs.identmap[i]), argstack[i] + static_cast(cs.p_state->identmap[i]), argstack[i] ); } } @@ -359,7 +364,7 @@ static void cs_do_args(CsState &cs, F body) { for (int i = 0; argmask2; argmask2 >>= 1, ++i) { if (argmask2 & 1) { CsAliasInternal::redo_arg( - static_cast(cs.identmap[i]), argstack[i] + static_cast(cs.p_state->identmap[i]), argstack[i] ); } } diff --git a/src/cubescript.cc b/src/cubescript.cc index ae6fb7bf..78fc522d 100644 --- a/src/cubescript.cc +++ b/src/cubescript.cc @@ -253,8 +253,19 @@ int CsCommand::get_num_args() const { void cs_init_lib_base(CsState &cs); CsState::CsState(): - p_callhook(), p_panicfunc(), p_out(&ostd::out), p_err(&ostd::err) + p_state(nullptr), p_callhook(), p_panicfunc(), + p_out(&ostd::out), p_err(&ostd::err) { + CsSharedState *ps = static_cast( + alloc(nullptr, 0, sizeof(CsSharedState)) + ); + if (!ps) { + return; + } + /* TODO: protect with a Box */ + new (ps) CsSharedState(); + p_state = ps; + /* default panic func */ p_panicfunc = [](CsState &cs, ostd::ConstCharRange v, CsStackState) { cs.get_err().writefln( @@ -342,7 +353,10 @@ CsState::CsState(): } CsState::~CsState() { - for (auto &p: idents.iter()) { + if (!p_state) { + return; + } + for (auto &p: p_state->idents.iter()) { CsIdent *i = p.second; CsAlias *a = i->get_alias(); if (a) { @@ -351,6 +365,8 @@ CsState::~CsState() { } delete i; } + p_state->~CsSharedState(); + alloc(p_state, sizeof(CsSharedState), 0); } CsStream const &CsState::get_out() const { @@ -484,7 +500,7 @@ void CsState::clear_override(CsIdent &id) { } void CsState::clear_overrides() { - for (auto &p: idents.iter()) { + for (auto &p: p_state->idents.iter()) { clear_override(*(p.second)); } } @@ -493,9 +509,9 @@ CsIdent *CsState::add_ident(CsIdent *id) { if (!id) { return nullptr; } - idents[id->get_name()] = id; - id->p_index = identmap.size(); - return identmap.push(id); + p_state->idents[id->get_name()] = id; + id->p_index = p_state->identmap.size(); + return p_state->identmap.push(id); } CsIdent *CsState::new_ident(ostd::ConstCharRange name, int flags) { @@ -505,7 +521,7 @@ CsIdent *CsState::new_ident(ostd::ConstCharRange name, int flags) { cs_debug_code( *this, "number %s is not a valid identifier name", name ); - return identmap[DummyIdx]; + return p_state->identmap[DummyIdx]; } id = add_ident(new CsAlias(name, flags)); } @@ -526,8 +542,39 @@ CsIdent *CsState::force_ident(CsValue &v) { default: break; } - v.set_ident(identmap[DummyIdx]); - return identmap[DummyIdx]; + v.set_ident(p_state->identmap[DummyIdx]); + return p_state->identmap[DummyIdx]; +} + +CsIdent *CsState::get_ident(ostd::ConstCharRange name) { + CsIdent **id = p_state->idents.at(name); + if (!id) { + return nullptr; + } + return *id; +} + +CsAlias *CsState::get_alias(ostd::ConstCharRange name) { + CsIdent **id = p_state->idents.at(name); + if (!id || !(*id)->is_alias()) { + return nullptr; + } + return static_cast(*id); +} + +bool CsState::have_ident(ostd::ConstCharRange name) { + return p_state->idents.at(name) != nullptr; +} + +CsIdentRange CsState::get_idents() { + return CsIdentRange(p_state->identmap.data(), p_state->identmap.size()); +} + +CsConstIdentRange CsState::get_idents() const { + return CsConstIdentRange( + const_cast(p_state->identmap.data()), + p_state->identmap.size() + ); } CsIvar *CsState::new_ivar( diff --git a/tools/edit_linenoise.hh b/tools/edit_linenoise.hh index 80d820af..5bc89639 100644 --- a/tools/edit_linenoise.hh +++ b/tools/edit_linenoise.hh @@ -18,7 +18,7 @@ static CsState *ln_cs = nullptr; #ifdef CS_REPL_HAS_COMPLETE static void ln_complete(char const *buf, linenoiseCompletions *lc) { ostd::ConstCharRange cmd = get_complete_cmd(buf); - for (auto id: ln_cs->identmap.iter()) { + for (auto id: ln_cs->get_idents()) { if (!id->is_command()) { continue; } diff --git a/tools/edit_readline.hh b/tools/edit_readline.hh index 6fad1aef..1873350b 100644 --- a/tools/edit_readline.hh +++ b/tools/edit_readline.hh @@ -20,7 +20,7 @@ static char *ln_complete_list(char const *buf, int state) { if (!state) { cmd = get_complete_cmd(buf); - itr = rd_cs->identmap.iter(); + itr = rd_cs->get_idents(); } for (; !itr.empty(); itr.pop_front()) { diff --git a/tools/repl.cc b/tools/repl.cc index a69378b0..0887d864 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -273,6 +273,9 @@ static void do_tty(CsState &cs) { int main(int argc, char **argv) { CsState gcs; + if (!gcs.is_alive()) { + return 1; + } gcs.init_libs(); gcs.new_command("exec", "sb", [](CsState &cs, auto args, auto &res) {