diff --git a/cs_val.cc b/cs_val.cc index 98b6c09d..b03389a2 100644 --- a/cs_val.cc +++ b/cs_val.cc @@ -4,13 +4,19 @@ namespace cscript { +template +inline T &csv_get(U &stor) { + /* ugly, but internal and unlikely to cause bugs */ + return const_cast(reinterpret_cast(stor)); +} + void CsValue::cleanup() { switch (get_type()) { case CsValueType::string: - delete[] p_s; + delete[] csv_get(p_stor); break; case CsValueType::code: { - ostd::Uint32 *bcode = reinterpret_cast(p_code); + ostd::Uint32 *bcode = csv_get(p_stor); if (bcode[-1] == CODE_START) { delete[] bcode; } @@ -27,12 +33,12 @@ CsValueType CsValue::get_type() const { void CsValue::set_int(CsInt val) { p_type = CsValueType::integer; - p_i = val; + csv_get(p_stor) = val; } void CsValue::set_float(CsFloat val) { p_type = CsValueType::number; - p_f = val; + csv_get(p_stor) = val; } void CsValue::set_str(CsString val) { @@ -50,35 +56,35 @@ void CsValue::set_str(CsString val) { void CsValue::set_null() { p_type = CsValueType::null; - p_code = nullptr; + csv_get(p_stor) = nullptr; } void CsValue::set_code(CsBytecode *val) { p_type = CsValueType::code; - p_code = val; + csv_get(p_stor) = val; } void CsValue::set_cstr(ostd::ConstCharRange val) { p_type = CsValueType::cstring; p_len = val.size(); - p_cstr = val.data(); + csv_get(p_stor) = val.data(); } void CsValue::set_mstr(ostd::CharRange val) { p_type = CsValueType::string; p_len = val.size(); - p_s = val.data(); + csv_get(p_stor) = val.data(); } void CsValue::set_ident(CsIdent *val) { p_type = CsValueType::ident; - p_id = val; + csv_get(p_stor) = val; } void CsValue::set_macro(ostd::ConstCharRange val) { p_type = CsValueType::macro; p_len = val.size(); - p_cstr = val.data(); + csv_get(p_stor) = val.data(); } void CsValue::set(CsValue &tv) { @@ -99,15 +105,17 @@ CsFloat CsValue::force_float() { CsFloat rf = 0.0f; switch (get_type()) { case CsValueType::integer: - rf = p_i; + rf = csv_get(p_stor); break; case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - rf = cs_parse_float(ostd::ConstCharRange(p_s, p_len)); + rf = cs_parse_float( + ostd::ConstCharRange(csv_get(p_stor), p_len) + ); break; case CsValueType::number: - return p_f; + return csv_get(p_stor); default: break; } @@ -120,15 +128,17 @@ CsInt CsValue::force_int() { CsInt ri = 0; switch (get_type()) { case CsValueType::number: - ri = p_f; + ri = csv_get(p_stor); break; case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - ri = cs_parse_int(ostd::ConstCharRange(p_s, p_len)); + ri = cs_parse_int( + ostd::ConstCharRange(csv_get(p_stor), p_len) + ); break; case CsValueType::integer: - return p_i; + return csv_get(p_stor); default: break; } @@ -141,35 +151,37 @@ ostd::ConstCharRange CsValue::force_str() { CsString rs; switch (get_type()) { case CsValueType::number: - rs = ostd::move(floatstr(p_f)); + rs = ostd::move(floatstr(csv_get(p_stor))); break; case CsValueType::integer: - rs = ostd::move(intstr(p_i)); + rs = ostd::move(intstr(csv_get(p_stor))); break; case CsValueType::macro: case CsValueType::cstring: - rs = ostd::ConstCharRange(p_s, p_len); + rs = ostd::ConstCharRange(csv_get(p_stor), p_len); break; case CsValueType::string: - return ostd::ConstCharRange(p_s, p_len); + return ostd::ConstCharRange(csv_get(p_stor), p_len); default: break; } cleanup(); set_str(ostd::move(rs)); - return ostd::ConstCharRange(p_s, p_len); + return ostd::ConstCharRange(csv_get(p_stor), p_len); } CsInt CsValue::get_int() const { switch (get_type()) { case CsValueType::number: - return CsInt(p_f); + return CsInt(csv_get(p_stor)); case CsValueType::integer: - return p_i; + return csv_get(p_stor); case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - return cs_parse_int(ostd::ConstCharRange(p_s, p_len)); + return cs_parse_int( + ostd::ConstCharRange(csv_get(p_stor), p_len) + ); default: break; } @@ -179,13 +191,15 @@ CsInt CsValue::get_int() const { CsFloat CsValue::get_float() const { switch (get_type()) { case CsValueType::number: - return p_f; + return csv_get(p_stor); case CsValueType::integer: - return CsFloat(p_i); + return CsFloat(csv_get(p_stor)); case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - return cs_parse_float(ostd::ConstCharRange(p_s, p_len)); + return cs_parse_float( + ostd::ConstCharRange(csv_get(p_stor), p_len) + ); default: break; } @@ -196,14 +210,14 @@ CsBytecode *CsValue::get_code() const { if (get_type() != CsValueType::code) { return nullptr; } - return p_code; + return csv_get(p_stor); } CsIdent *CsValue::get_ident() const { if (get_type() != CsValueType::ident) { return nullptr; } - return p_id; + return csv_get(p_stor); } CsString CsValue::get_str() const { @@ -211,11 +225,11 @@ CsString CsValue::get_str() const { case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - return ostd::ConstCharRange(p_s, p_len); + return ostd::ConstCharRange(csv_get(p_stor), p_len); case CsValueType::integer: - return intstr(p_i); + return intstr(csv_get(p_stor)); case CsValueType::number: - return floatstr(p_f); + return floatstr(csv_get(p_stor)); default: break; } @@ -227,7 +241,7 @@ ostd::ConstCharRange CsValue::get_strr() const { case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - return ostd::ConstCharRange(p_s, p_len); + return ostd::ConstCharRange(csv_get(p_stor), p_len); default: break; } @@ -239,13 +253,15 @@ void CsValue::get_val(CsValue &r) const { case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - r.set_str(ostd::ConstCharRange(p_s, p_len)); + r.set_str( + ostd::ConstCharRange(csv_get(p_stor), p_len) + ); break; case CsValueType::integer: - r.set_int(p_i); + r.set_int(csv_get(p_stor)); break; case CsValueType::number: - r.set_float(p_f); + r.set_float(csv_get(p_stor)); break; default: r.set_null(); @@ -266,7 +282,7 @@ bool CsValue::code_is_empty() const { if (get_type() != CsValueType::code) { return true; } - return cscript::cs_code_is_empty(p_code); + return cscript::cs_code_is_empty(csv_get(p_stor)); } static inline bool cs_get_bool(ostd::ConstCharRange s) { @@ -289,16 +305,42 @@ static inline bool cs_get_bool(ostd::ConstCharRange s) { bool CsValue::get_bool() const { switch (get_type()) { case CsValueType::number: - return p_f != 0; + return csv_get(p_stor) != 0; case CsValueType::integer: - return p_i != 0; + return csv_get(p_stor) != 0; case CsValueType::string: case CsValueType::macro: case CsValueType::cstring: - return cs_get_bool(ostd::ConstCharRange(p_s, p_len)); + return cs_get_bool( + ostd::ConstCharRange(csv_get(p_stor), p_len) + ); default: return false; } } +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; + } +} + } /* namespace cscript */ diff --git a/cs_vm.cc b/cs_vm.cc index 283052a5..0e70dc90 100644 --- a/cs_vm.cc +++ b/cs_vm.cc @@ -260,32 +260,13 @@ static ostd::Uint32 *skipcode( } } -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(p_s, p_len)); - break; - case CsValueType::code: { - ostd::Uint32 *bcode = reinterpret_cast(r.get_code()); - ostd::Uint32 *end = skipcode(bcode); - ostd::Uint32 *dst = new ostd::Uint32[end - bcode + 1]; - *dst++ = CODE_START; - memcpy(dst, bcode, (end - bcode) * sizeof(ostd::Uint32)); - r.set_code(reinterpret_cast(dst)); - break; - } - default: - r.set_null(); - break; - } +CsBytecode *cs_copy_code(CsBytecode *c) { + ostd::Uint32 *bcode = reinterpret_cast(c); + ostd::Uint32 *end = skipcode(bcode); + ostd::Uint32 *dst = new ostd::Uint32[end - bcode + 1]; + *dst++ = CODE_START; + memcpy(dst, bcode, (end - bcode) * sizeof(ostd::Uint32)); + return reinterpret_cast(dst); } static inline void callcommand( diff --git a/cs_vm.hh b/cs_vm.hh index 84d71b22..67267378 100644 --- a/cs_vm.hh +++ b/cs_vm.hh @@ -348,6 +348,8 @@ static void cs_do_args(CsState &cs, F body) { } } +CsBytecode *cs_copy_code(CsBytecode *c); + } /* namespace cscript */ #endif /* LIBCUBESCRIPT_CS_VM_HH */ diff --git a/cubescript.hh b/cubescript.hh index e9099d18..c658f386 100644 --- a/cubescript.hh +++ b/cubescript.hh @@ -100,14 +100,7 @@ struct OSTD_EXPORT CsValue { void copy_arg(CsValue &r) const; private: - union { - CsInt p_i; - CsFloat p_f; - CsBytecode *p_code; - CsIdent *p_id; - char *p_s; - char const *p_cstr; - }; + ostd::AlignedUnion<1, CsInt, CsFloat, void *> p_stor; ostd::Size p_len; CsValueType p_type; }; @@ -139,6 +132,9 @@ struct OSTD_EXPORT CsIdent { CsIdent(CsIdent const &) = delete; CsIdent(CsIdent &&) = delete; + /* trigger destructors for all inherited members properly */ + virtual ~CsIdent() {}; + CsIdent &operator=(CsIdent const &) = delete; CsIdent &operator=(CsIdent &&) = delete; diff --git a/tools/repl.cc b/tools/repl.cc index 41db9016..08148555 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -194,6 +194,7 @@ static void do_call(CsState &cs, ostd::ConstCharRange line) { if (ret.get_type() != CsValueType::null) { ostd::writeln(ret.get_str()); } + ret.cleanup(); } static void do_tty(CsState &cs) {