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));
}
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() {
switch (get_type()) {
case CsValueType::string:
@ -95,13 +143,6 @@ void CsValue::set_macro(ostd::ConstCharRange val) {
csv_get<char const *>(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<char const *>(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<CsValue *>(this) = v;
return *this;
}
CsStackedValue &CsStackedValue::operator=(CsValue &&v) {
*static_cast<CsValue *>(this) = ostd::move(v);
return *this;
}
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 */

View File

@ -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();

View File

@ -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;
}

View File

@ -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<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>
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);
});

View File

@ -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;