From 01c464c6194f25a6e3d4c91f6e5a9c8c05cd2886 Mon Sep 17 00:00:00 2001 From: q66 Date: Tue, 6 Sep 2016 22:23:03 +0200 Subject: [PATCH] start re-doing the CsValue interface to support copy/move semantics --- cs_val.cc | 129 +++++++++++++++++++++++++++++++++++++++----------- cs_vm.cc | 12 ++--- cs_vm.hh | 20 ++++---- cubescript.cc | 74 ++++++----------------------- cubescript.hh | 26 ++++++++-- 5 files changed, 154 insertions(+), 107 deletions(-) diff --git a/cs_val.cc b/cs_val.cc index 6f463998..ecf2b05e 100644 --- a/cs_val.cc +++ b/cs_val.cc @@ -10,6 +10,54 @@ inline T &csv_get(U &stor) { return const_cast(reinterpret_cast(stor)); } +CsValue::CsValue(): + p_stor(), p_len(0), p_type(CsValueType::null) +{} + +CsValue::CsValue(CsValue const &v): CsValue() { + *this = v; +} + +CsValue::CsValue(CsValue &&v): CsValue() { + *this = ostd::move(v); +} + +CsValue &CsValue::operator=(CsValue const &v) { + cleanup(); + switch (v.get_type()) { + case CsValueType::integer: + case CsValueType::number: + case CsValueType::ident: + p_len = v.p_len; + p_type = v.p_type; + memcpy(&p_stor, &v.p_stor, sizeof(p_stor)); + break; + case CsValueType::string: + case CsValueType::cstring: + case CsValueType::macro: + set_str( + ostd::ConstCharRange(csv_get(v.p_stor), v.p_len) + ); + break; + case CsValueType::code: + set_code(cs_copy_code(v.get_code())); + break; + default: + set_null(); + break; + } + return *this; +} + +CsValue &CsValue::operator=(CsValue &&v) { + cleanup(); + p_len = v.p_len; + p_type = v.p_type; + memcpy(&p_stor, &v.p_stor, sizeof(p_stor)); + v.set_null(); + return *this; +} + void CsValue::cleanup() { switch (get_type()) { case CsValueType::string: @@ -95,13 +143,6 @@ void CsValue::set_macro(ostd::ConstCharRange val) { csv_get(p_stor) = val.data(); } -void CsValue::set(CsValue &tv) { - cleanup(); - *this = tv; - tv.set_null(); -} - - void CsValue::force_null() { if (get_type() == CsValueType::null) { return; @@ -328,28 +369,60 @@ bool CsValue::get_bool() const { } } -void CsValue::copy_arg(CsValue &r) const { - r.cleanup(); - switch (get_type()) { - case CsValueType::integer: - case CsValueType::number: - case CsValueType::ident: - r = *this; - break; - case CsValueType::string: - case CsValueType::cstring: - case CsValueType::macro: - r.set_str( - ostd::ConstCharRange(csv_get(p_stor), p_len) - ); - break; - case CsValueType::code: - r.set_code(cs_copy_code(get_code())); - break; - default: - r.set_null(); - break; +/* stacked value for easy stack management */ + +CsStackedValue::CsStackedValue(CsIdent *id): + CsValue(), p_a(nullptr), p_stack(), p_pushed(false) +{ + set_alias(id); +} + +CsStackedValue::~CsStackedValue() { + pop(); +} + +CsStackedValue &CsStackedValue::operator=(CsValue const &v) { + *static_cast(this) = v; + return *this; +} + +CsStackedValue &CsStackedValue::operator=(CsValue &&v) { + *static_cast(this) = ostd::move(v); + return *this; +} + +bool CsStackedValue::set_alias(CsIdent *id) { + if (!id || !id->is_alias()) { + return false; } + p_a = static_cast(id); + return true; +} + +CsAlias *CsStackedValue::get_alias() const { + return p_a; +} + +bool CsStackedValue::has_alias() const { + return p_a != nullptr; +} + +bool CsStackedValue::push() { + if (!p_a) { + return false; + } + CsAliasInternal::push_arg(p_a, *this, p_stack); + p_pushed = true; + return true; +} + +bool CsStackedValue::pop() { + if (!p_pushed || !p_a) { + return false; + } + CsAliasInternal::pop_arg(p_a); + p_pushed = false; + return true; } } /* namespace cscript */ diff --git a/cs_vm.cc b/cs_vm.cc index bcdef9bd..46b7b981 100644 --- a/cs_vm.cc +++ b/cs_vm.cc @@ -642,7 +642,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { force_arg(result, op & CODE_RET_MASK); /* fallthrough */ case CODE_RESULT_ARG | RET_NULL: - args[numargs++] = result; + args[numargs++].v_copy_no_alloc(result); result.set_null(); continue; case CODE_PRINT: @@ -713,7 +713,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { cs.run_ret(args[numargs].get_code(), result); args[numargs].cleanup(); } else { - result = args[numargs]; + result.v_copy_no_alloc(args[numargs]); } if (result.get_bool()) { code += len; @@ -728,7 +728,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { cs.run_ret(args[numargs].get_code(), result); args[numargs].cleanup(); } else { - result = args[numargs]; + result.v_copy_no_alloc(args[numargs]); } if (!result.get_bool()) { code += len; @@ -810,13 +810,13 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { case CODE_RESULT | RET_NULL: result.cleanup(); - result = args[--numargs]; + result.v_copy_no_alloc(args[--numargs]); continue; case CODE_RESULT | RET_STR: case CODE_RESULT | RET_INT: case CODE_RESULT | RET_FLOAT: result.cleanup(); - result = args[--numargs]; + result.v_copy_no_alloc(args[--numargs]); force_arg(result, op & CODE_RET_MASK); continue; @@ -1443,7 +1443,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { ) { litval: result.cleanup(); - result = idarg; + result.v_copy_no_alloc(idarg); force_arg(result, op & CODE_RET_MASK); while (--numargs >= offset) { args[numargs].cleanup(); diff --git a/cs_vm.hh b/cs_vm.hh index 67267378..09815743 100644 --- a/cs_vm.hh +++ b/cs_vm.hh @@ -237,14 +237,14 @@ struct CsAliasInternal { if (a->p_astack == &st) { /* prevent cycles and unnecessary code elsewhere */ a->p_val.cleanup(); - a->p_val = v; + a->p_val.v_copy_no_alloc(v); clean_code(a); return; } - st.val_s = a->p_val; + st.val_s.v_copy_no_alloc(a->p_val); st.next = a->p_astack; a->p_astack = &st; - a->p_val = v; + a->p_val.v_copy_no_alloc(v); clean_code(a); if (um) { a->p_flags &= ~IDF_UNKNOWN; @@ -257,32 +257,32 @@ struct CsAliasInternal { } CsIdentStack *st = a->p_astack; a->p_val.cleanup(); - a->p_val = a->p_astack->val_s; + a->p_val.v_copy_no_alloc(a->p_astack->val_s); clean_code(a); a->p_astack = st->next; } static void undo_arg(CsAlias *a, CsIdentStack &st) { CsIdentStack *prev = a->p_astack; - st.val_s = a->p_val; + st.val_s.v_copy_no_alloc(a->p_val); st.next = prev; a->p_astack = prev->next; - a->p_val = prev->val_s; + a->p_val.v_copy_no_alloc(prev->val_s); clean_code(a); } static void redo_arg(CsAlias *a, CsIdentStack const &st) { CsIdentStack *prev = st.next; - prev->val_s = a->p_val; + prev->val_s.v_copy_no_alloc(a->p_val); a->p_astack = prev; - a->p_val = st.val_s; + a->p_val.v_copy_no_alloc(st.val_s); clean_code(a); } static void set_arg(CsAlias *a, CsState &cs, CsValue &v) { if (cs.p_stack->usedargs & (1 << a->get_index())) { a->p_val.cleanup(); - a->p_val = v; + a->p_val.v_copy_no_alloc(v); clean_code(a); } else { push_arg(a, v, cs.p_stack->argstack[a->get_index()], false); @@ -292,7 +292,7 @@ struct CsAliasInternal { static void set_alias(CsAlias *a, CsState &cs, CsValue &v) { a->p_val.cleanup(); - a->p_val = v; + a->p_val.v_copy_no_alloc(v); clean_code(a); a->p_flags = (a->p_flags & cs.identflags) | cs.identflags; } diff --git a/cubescript.cc b/cubescript.cc index c66c73c4..56dbc246 100644 --- a/cubescript.cc +++ b/cubescript.cc @@ -83,8 +83,10 @@ CsAlias::CsAlias(ostd::ConstCharRange name, int fl): } CsAlias::CsAlias(ostd::ConstCharRange name, CsValue const &v, int fl): CsIdent(CsIdentType::alias, name, fl), - p_acode(nullptr), p_astack(nullptr), p_val(v) -{} + p_acode(nullptr), p_astack(nullptr), p_val() +{ + p_val.v_copy_no_alloc(v); +} CsCommand::CsCommand( ostd::ConstCharRange name, ostd::ConstCharRange args, @@ -288,9 +290,7 @@ CsState::CsState(): p_out(&ostd::out), p_err(&ostd::err) { })->p_type = ID_IF; new_command("result", "T", [](CsValueRange args, CsValue &res) { - CsValue &v = args[0]; - res = v; - v.set_null(); + res = ostd::move(args[0]); })->p_type = ID_RESULT; new_command("!", "t", [](CsValueRange args, CsValue &res) { @@ -302,14 +302,11 @@ CsState::CsState(): p_out(&ostd::out), p_err(&ostd::err) { res.set_int(1); } else { for (ostd::Size i = 0; i < args.size(); ++i) { - if (i) { - res.cleanup(); - } CsBytecode *code = args[i].get_code(); if (code) { run_ret(code, res); } else { - res = args[i]; + res = ostd::move(args[i]); } if (!res.get_bool()) { break; @@ -323,14 +320,11 @@ CsState::CsState(): p_out(&ostd::out), p_err(&ostd::err) { res.set_int(0); } else { for (ostd::Size i = 0; i < args.size(); ++i) { - if (i) { - res.cleanup(); - } CsBytecode *code = args[i].get_code(); if (code) { run_ret(code, res); } else { - res = args[i]; + res = ostd::move(args[i]); } if (res.get_bool()) { break; @@ -670,50 +664,6 @@ int CsIdent::get_index() const { return p_index; } -CsStackedValue::CsStackedValue(CsIdent *id): - CsValue(), p_a(nullptr), p_stack(), p_pushed(false) -{ - set_alias(id); -} - -CsStackedValue::~CsStackedValue() { - pop(); -} - -bool CsStackedValue::set_alias(CsIdent *id) { - if (!id || !id->is_alias()) { - return false; - } - p_a = static_cast(id); - return true; -} - -CsAlias *CsStackedValue::get_alias() const { - return p_a; -} - -bool CsStackedValue::has_alias() const { - return p_a != nullptr; -} - -bool CsStackedValue::push() { - if (!p_a) { - return false; - } - CsAliasInternal::push_arg(p_a, *this, p_stack); - p_pushed = true; - return true; -} - -bool CsStackedValue::pop() { - if (!p_pushed || !p_a) { - return false; - } - CsAliasInternal::pop_arg(p_a); - p_pushed = false; - return true; -} - template static inline bool cs_override_var(CsState &cs, CsVar *v, int &vflags, SF sf) { if ((cs.identflags & IDF_OVERRIDDEN) || (vflags & IDF_OVERRIDE)) { @@ -1077,7 +1027,11 @@ static inline void cs_loop_conc( void cs_init_lib_base(CsState &cs) { cs.new_command("?", "tTT", [](CsValueRange args, CsValue &res) { - res.set(args[0].get_bool() ? args[1] : args[2]); + if (args[0].get_bool()) { + res = ostd::move(args[1]); + } else { + res = ostd::move(args[2]); + } }); cs.new_command("cond", "ee2V", [&cs](CsValueRange args, CsValue &res) { @@ -1139,7 +1093,7 @@ void cs_init_lib_base(CsState &cs) { return; } if (args[1].get_bool()) { - idv.set(args[1]); + idv = ostd::move(args[1]); idv.push(); cs.run_ret(args[2].get_code(), res); } @@ -1275,7 +1229,7 @@ void cs_init_lib_base(CsState &cs) { if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) { return; } - idv.set(args[1]); + idv = ostd::move(args[1]); idv.push(); cs.run_ret(args[2].get_code(), res); }); diff --git a/cubescript.hh b/cubescript.hh index c658f386..b7ea6596 100644 --- a/cubescript.hh +++ b/cubescript.hh @@ -65,6 +65,20 @@ enum class CsValueType { }; struct OSTD_EXPORT CsValue { + CsValue(); + + CsValue(CsValue const &); + CsValue(CsValue &&); + + CsValue &operator=(CsValue const &v); + CsValue &operator=(CsValue &&v); + + void v_copy_no_alloc(CsValue const &v) { + memcpy(&p_stor, &v.p_stor, sizeof(p_stor)); + p_len = v.p_len; + p_type = v.p_type; + } + CsValueType get_type() const; void set_int(CsInt val); @@ -77,8 +91,6 @@ struct OSTD_EXPORT CsValue { void set_ident(CsIdent *val); void set_macro(ostd::ConstCharRange val); - void set(CsValue &tv); - CsString get_str() const; ostd::ConstCharRange get_strr() const; CsInt get_int() const; @@ -97,7 +109,6 @@ struct OSTD_EXPORT CsValue { bool code_is_empty() const; void cleanup(); - void copy_arg(CsValue &r) const; private: ostd::AlignedUnion<1, CsInt, CsFloat, void *> p_stor; @@ -464,6 +475,15 @@ struct OSTD_EXPORT CsStackedValue: CsValue { CsStackedValue(CsIdent *id = nullptr); ~CsStackedValue(); + CsStackedValue(CsStackedValue const &) = delete; + CsStackedValue(CsStackedValue &&) = delete; + + CsStackedValue &operator=(CsStackedValue const &) = delete; + CsStackedValue &operator=(CsStackedValue &&v) = delete; + + CsStackedValue &operator=(CsValue const &v); + CsStackedValue &operator=(CsValue &&v); + bool set_alias(CsIdent *id); CsAlias *get_alias() const; bool has_alias() const;