start re-doing the CsValue interface to support copy/move semantics

master
Daniel Kolesa 2016-09-06 22:23:03 +02:00
parent 16c99e1f9e
commit 01c464c619
5 changed files with 154 additions and 107 deletions

129
cs_val.cc
View File

@ -10,6 +10,54 @@ inline T &csv_get(U &stor) {
return const_cast<T &>(reinterpret_cast<T const &>(stor)); return const_cast<T &>(reinterpret_cast<T const &>(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<char const *>(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() { void CsValue::cleanup() {
switch (get_type()) { switch (get_type()) {
case CsValueType::string: case CsValueType::string:
@ -95,13 +143,6 @@ void CsValue::set_macro(ostd::ConstCharRange val) {
csv_get<char const *>(p_stor) = val.data(); csv_get<char const *>(p_stor) = val.data();
} }
void CsValue::set(CsValue &tv) {
cleanup();
*this = tv;
tv.set_null();
}
void CsValue::force_null() { void CsValue::force_null() {
if (get_type() == CsValueType::null) { if (get_type() == CsValueType::null) {
return; return;
@ -328,28 +369,60 @@ bool CsValue::get_bool() const {
} }
} }
void CsValue::copy_arg(CsValue &r) const { /* stacked value for easy stack management */
r.cleanup();
switch (get_type()) { CsStackedValue::CsStackedValue(CsIdent *id):
case CsValueType::integer: CsValue(), p_a(nullptr), p_stack(), p_pushed(false)
case CsValueType::number: {
case CsValueType::ident: set_alias(id);
r = *this; }
break;
case CsValueType::string: CsStackedValue::~CsStackedValue() {
case CsValueType::cstring: pop();
case CsValueType::macro: }
r.set_str(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len) CsStackedValue &CsStackedValue::operator=(CsValue const &v) {
); *static_cast<CsValue *>(this) = v;
break; return *this;
case CsValueType::code: }
r.set_code(cs_copy_code(get_code()));
break; CsStackedValue &CsStackedValue::operator=(CsValue &&v) {
default: *static_cast<CsValue *>(this) = ostd::move(v);
r.set_null(); return *this;
break; }
bool CsStackedValue::set_alias(CsIdent *id) {
if (!id || !id->is_alias()) {
return false;
} }
p_a = static_cast<CsAlias *>(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 */ } /* namespace cscript */

View File

@ -642,7 +642,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
force_arg(result, op & CODE_RET_MASK); force_arg(result, op & CODE_RET_MASK);
/* fallthrough */ /* fallthrough */
case CODE_RESULT_ARG | RET_NULL: case CODE_RESULT_ARG | RET_NULL:
args[numargs++] = result; args[numargs++].v_copy_no_alloc(result);
result.set_null(); result.set_null();
continue; continue;
case CODE_PRINT: 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); cs.run_ret(args[numargs].get_code(), result);
args[numargs].cleanup(); args[numargs].cleanup();
} else { } else {
result = args[numargs]; result.v_copy_no_alloc(args[numargs]);
} }
if (result.get_bool()) { if (result.get_bool()) {
code += len; 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); cs.run_ret(args[numargs].get_code(), result);
args[numargs].cleanup(); args[numargs].cleanup();
} else { } else {
result = args[numargs]; result.v_copy_no_alloc(args[numargs]);
} }
if (!result.get_bool()) { if (!result.get_bool()) {
code += len; code += len;
@ -810,13 +810,13 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
case CODE_RESULT | RET_NULL: case CODE_RESULT | RET_NULL:
result.cleanup(); result.cleanup();
result = args[--numargs]; result.v_copy_no_alloc(args[--numargs]);
continue; continue;
case CODE_RESULT | RET_STR: case CODE_RESULT | RET_STR:
case CODE_RESULT | RET_INT: case CODE_RESULT | RET_INT:
case CODE_RESULT | RET_FLOAT: case CODE_RESULT | RET_FLOAT:
result.cleanup(); result.cleanup();
result = args[--numargs]; result.v_copy_no_alloc(args[--numargs]);
force_arg(result, op & CODE_RET_MASK); force_arg(result, op & CODE_RET_MASK);
continue; continue;
@ -1443,7 +1443,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
) { ) {
litval: litval:
result.cleanup(); result.cleanup();
result = idarg; result.v_copy_no_alloc(idarg);
force_arg(result, op & CODE_RET_MASK); force_arg(result, op & CODE_RET_MASK);
while (--numargs >= offset) { while (--numargs >= offset) {
args[numargs].cleanup(); args[numargs].cleanup();

View File

@ -237,14 +237,14 @@ struct CsAliasInternal {
if (a->p_astack == &st) { if (a->p_astack == &st) {
/* prevent cycles and unnecessary code elsewhere */ /* prevent cycles and unnecessary code elsewhere */
a->p_val.cleanup(); a->p_val.cleanup();
a->p_val = v; a->p_val.v_copy_no_alloc(v);
clean_code(a); clean_code(a);
return; return;
} }
st.val_s = a->p_val; st.val_s.v_copy_no_alloc(a->p_val);
st.next = a->p_astack; st.next = a->p_astack;
a->p_astack = &st; a->p_astack = &st;
a->p_val = v; a->p_val.v_copy_no_alloc(v);
clean_code(a); clean_code(a);
if (um) { if (um) {
a->p_flags &= ~IDF_UNKNOWN; a->p_flags &= ~IDF_UNKNOWN;
@ -257,32 +257,32 @@ struct CsAliasInternal {
} }
CsIdentStack *st = a->p_astack; CsIdentStack *st = a->p_astack;
a->p_val.cleanup(); 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); clean_code(a);
a->p_astack = st->next; a->p_astack = st->next;
} }
static void undo_arg(CsAlias *a, CsIdentStack &st) { static void undo_arg(CsAlias *a, CsIdentStack &st) {
CsIdentStack *prev = a->p_astack; CsIdentStack *prev = a->p_astack;
st.val_s = a->p_val; st.val_s.v_copy_no_alloc(a->p_val);
st.next = prev; st.next = prev;
a->p_astack = prev->next; a->p_astack = prev->next;
a->p_val = prev->val_s; a->p_val.v_copy_no_alloc(prev->val_s);
clean_code(a); clean_code(a);
} }
static void redo_arg(CsAlias *a, CsIdentStack const &st) { static void redo_arg(CsAlias *a, CsIdentStack const &st) {
CsIdentStack *prev = st.next; 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_astack = prev;
a->p_val = st.val_s; a->p_val.v_copy_no_alloc(st.val_s);
clean_code(a); clean_code(a);
} }
static void set_arg(CsAlias *a, CsState &cs, CsValue &v) { static void set_arg(CsAlias *a, CsState &cs, CsValue &v) {
if (cs.p_stack->usedargs & (1 << a->get_index())) { if (cs.p_stack->usedargs & (1 << a->get_index())) {
a->p_val.cleanup(); a->p_val.cleanup();
a->p_val = v; a->p_val.v_copy_no_alloc(v);
clean_code(a); clean_code(a);
} else { } else {
push_arg(a, v, cs.p_stack->argstack[a->get_index()], false); 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) { static void set_alias(CsAlias *a, CsState &cs, CsValue &v) {
a->p_val.cleanup(); a->p_val.cleanup();
a->p_val = v; a->p_val.v_copy_no_alloc(v);
clean_code(a); clean_code(a);
a->p_flags = (a->p_flags & cs.identflags) | cs.identflags; a->p_flags = (a->p_flags & cs.identflags) | cs.identflags;
} }

View File

@ -83,8 +83,10 @@ CsAlias::CsAlias(ostd::ConstCharRange name, int fl):
} }
CsAlias::CsAlias(ostd::ConstCharRange name, CsValue const &v, int fl): CsAlias::CsAlias(ostd::ConstCharRange name, CsValue const &v, int fl):
CsIdent(CsIdentType::alias, name, 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( CsCommand::CsCommand(
ostd::ConstCharRange name, ostd::ConstCharRange args, ostd::ConstCharRange name, ostd::ConstCharRange args,
@ -288,9 +290,7 @@ CsState::CsState(): p_out(&ostd::out), p_err(&ostd::err) {
})->p_type = ID_IF; })->p_type = ID_IF;
new_command("result", "T", [](CsValueRange args, CsValue &res) { new_command("result", "T", [](CsValueRange args, CsValue &res) {
CsValue &v = args[0]; res = ostd::move(args[0]);
res = v;
v.set_null();
})->p_type = ID_RESULT; })->p_type = ID_RESULT;
new_command("!", "t", [](CsValueRange args, CsValue &res) { 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); res.set_int(1);
} else { } else {
for (ostd::Size i = 0; i < args.size(); ++i) { for (ostd::Size i = 0; i < args.size(); ++i) {
if (i) {
res.cleanup();
}
CsBytecode *code = args[i].get_code(); CsBytecode *code = args[i].get_code();
if (code) { if (code) {
run_ret(code, res); run_ret(code, res);
} else { } else {
res = args[i]; res = ostd::move(args[i]);
} }
if (!res.get_bool()) { if (!res.get_bool()) {
break; break;
@ -323,14 +320,11 @@ CsState::CsState(): p_out(&ostd::out), p_err(&ostd::err) {
res.set_int(0); res.set_int(0);
} else { } else {
for (ostd::Size i = 0; i < args.size(); ++i) { for (ostd::Size i = 0; i < args.size(); ++i) {
if (i) {
res.cleanup();
}
CsBytecode *code = args[i].get_code(); CsBytecode *code = args[i].get_code();
if (code) { if (code) {
run_ret(code, res); run_ret(code, res);
} else { } else {
res = args[i]; res = ostd::move(args[i]);
} }
if (res.get_bool()) { if (res.get_bool()) {
break; break;
@ -670,50 +664,6 @@ int CsIdent::get_index() const {
return p_index; 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<CsAlias *>(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<typename SF> template<typename SF>
static inline bool cs_override_var(CsState &cs, CsVar *v, int &vflags, SF sf) { static inline bool cs_override_var(CsState &cs, CsVar *v, int &vflags, SF sf) {
if ((cs.identflags & IDF_OVERRIDDEN) || (vflags & IDF_OVERRIDE)) { 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) { void cs_init_lib_base(CsState &cs) {
cs.new_command("?", "tTT", [](CsValueRange args, CsValue &res) { 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) { cs.new_command("cond", "ee2V", [&cs](CsValueRange args, CsValue &res) {
@ -1139,7 +1093,7 @@ void cs_init_lib_base(CsState &cs) {
return; return;
} }
if (args[1].get_bool()) { if (args[1].get_bool()) {
idv.set(args[1]); idv = ostd::move(args[1]);
idv.push(); idv.push();
cs.run_ret(args[2].get_code(), res); 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)) { if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) {
return; return;
} }
idv.set(args[1]); idv = ostd::move(args[1]);
idv.push(); idv.push();
cs.run_ret(args[2].get_code(), res); cs.run_ret(args[2].get_code(), res);
}); });

View File

@ -65,6 +65,20 @@ enum class CsValueType {
}; };
struct OSTD_EXPORT CsValue { 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; CsValueType get_type() const;
void set_int(CsInt val); void set_int(CsInt val);
@ -77,8 +91,6 @@ struct OSTD_EXPORT CsValue {
void set_ident(CsIdent *val); void set_ident(CsIdent *val);
void set_macro(ostd::ConstCharRange val); void set_macro(ostd::ConstCharRange val);
void set(CsValue &tv);
CsString get_str() const; CsString get_str() const;
ostd::ConstCharRange get_strr() const; ostd::ConstCharRange get_strr() const;
CsInt get_int() const; CsInt get_int() const;
@ -97,7 +109,6 @@ struct OSTD_EXPORT CsValue {
bool code_is_empty() const; bool code_is_empty() const;
void cleanup(); void cleanup();
void copy_arg(CsValue &r) const;
private: private:
ostd::AlignedUnion<1, CsInt, CsFloat, void *> p_stor; ostd::AlignedUnion<1, CsInt, CsFloat, void *> p_stor;
@ -464,6 +475,15 @@ struct OSTD_EXPORT CsStackedValue: CsValue {
CsStackedValue(CsIdent *id = nullptr); CsStackedValue(CsIdent *id = nullptr);
~CsStackedValue(); ~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); bool set_alias(CsIdent *id);
CsAlias *get_alias() const; CsAlias *get_alias() const;
bool has_alias() const; bool has_alias() const;