forked from OctaForge/libcubescript
start re-doing the CsValue interface to support copy/move semantics
parent
16c99e1f9e
commit
01c464c619
129
cs_val.cc
129
cs_val.cc
|
@ -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 */
|
||||
|
|
12
cs_vm.cc
12
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();
|
||||
|
|
20
cs_vm.hh
20
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue