separate cs_state, cs_std

master
Daniel Kolesa 2021-03-23 01:11:21 +01:00
parent 702dca0809
commit 4588ae2373
12 changed files with 303 additions and 241 deletions

31
src/cs_state.cc 100644
View File

@ -0,0 +1,31 @@
#include <memory>
#include "cs_util.hh"
#include "cs_bcode.hh"
#include "cs_state.hh"
namespace cscript {
cs_shared_state::cs_shared_state(cs_alloc_cb af, void *data):
allocf{af}, aptr{data},
idents{allocator_type{this}},
identmap{allocator_type{this}},
varprintf{},
strman{create<cs_strman>(this)},
empty{bcode_init_empty(this)}
{}
cs_shared_state::~cs_shared_state() {
bcode_free_empty(this, empty);
destroy(strman);
}
void *cs_shared_state::alloc(void *ptr, size_t os, size_t ns) {
void *p = allocf(aptr, ptr, os, ns);
if (!p && ns) {
throw std::bad_alloc{};
}
return p;
}
} /* namespace cscript */

116
src/cs_state.hh 100644
View File

@ -0,0 +1,116 @@
#ifndef LIBCUBESCRIPT_STATE_HH
#define LIBCUBESCRIPT_STATE_HH
#include <cubescript/cubescript.hh>
#include <unordered_map>
#include <string>
#include "cs_bcode.hh"
namespace cscript {
struct cs_state;
struct cs_shared_state;
struct cs_strman;
template<typename T>
struct cs_allocator {
using value_type = T;
inline cs_allocator(cs_shared_state *s);
inline cs_allocator(cs_state &cs);
template<typename U>
cs_allocator(cs_allocator<U> const &a): state{a.state} {};
inline T *allocate(std::size_t n);
inline void deallocate(T *p, std::size_t n);
template<typename U>
bool operator==(cs_allocator<U> const &a) {
return state == a.state;
}
cs_shared_state *state;
};
struct cs_shared_state {
using allocator_type = cs_allocator<
std::pair<std::string_view const, cs_ident *>
>;
cs_alloc_cb allocf;
void *aptr;
std::unordered_map<
std::string_view, cs_ident *,
std::hash<std::string_view>,
std::equal_to<std::string_view>,
allocator_type
> idents;
std::vector<cs_ident *, cs_allocator<cs_ident *>> identmap;
cs_vprint_cb varprintf;
cs_strman *strman;
empty_block *empty;
cs_shared_state() = delete;
cs_shared_state(cs_alloc_cb af, void *data);
~cs_shared_state();
void *alloc(void *ptr, size_t os, size_t ns);
template<typename T, typename ...A>
T *create(A &&...args) {
T *ret = static_cast<T *>(alloc(nullptr, 0, sizeof(T)));
new (ret) T(std::forward<A>(args)...);
return ret;
}
template<typename T>
T *create_array(size_t len) {
T *ret = static_cast<T *>(alloc(nullptr, 0, len * sizeof(T)));
for (size_t i = 0; i < len; ++i) {
new (&ret[i]) T();
}
return ret;
}
template<typename T>
void destroy(T *v) noexcept {
v->~T();
alloc(v, sizeof(T), 0);
}
template<typename T>
void destroy_array(T *v, size_t len) noexcept {
v->~T();
alloc(v, len * sizeof(T), 0);
}
};
inline cs_shared_state *cs_get_sstate(cs_state &cs) {
return cs.p_state;
}
template<typename T>
inline cs_allocator<T>::cs_allocator(cs_shared_state *s): state{s} {}
template<typename T>
inline cs_allocator<T>::cs_allocator(cs_state &s): state{cs_get_sstate(s)} {}
template<typename T>
inline T *cs_allocator<T>::allocate(std::size_t n) {
return static_cast<T *>(state->alloc(nullptr, 0, n * sizeof(T)));
}
template<typename T>
inline void cs_allocator<T>::deallocate(T *p, std::size_t n) {
state->alloc(p, n, 0);
}
} /* namespace cscript */
#endif

122
src/cs_std.hh 100644
View File

@ -0,0 +1,122 @@
#ifndef LIBCUBESCRIPT_STD_HH
#define LIBCUBESCRIPT_STD_HH
#include <cstddef>
#include <utility>
#include <type_traits>
#include "cs_state.hh"
namespace cscript {
/* run func, call the second one after finishing */
template<typename F>
struct CsScopeExit {
template<typename FF>
CsScopeExit(FF &&f): func(std::forward<FF>(f)) {}
~CsScopeExit() {
func();
}
std::decay_t<F> func;
};
template<typename F1, typename F2>
inline void call_with_cleanup(F1 &&dof, F2 &&clf) {
CsScopeExit<F2> cleanup(std::forward<F2>(clf));
dof();
}
/* a simple static array with elements constructed using ctor args */
template<typename T, std::size_t N>
struct cs_valarray {
template<typename ...A>
cs_valarray(A &&...args) {
for (std::size_t i = 0; i < N; ++i) {
new (&stor[i]) T{std::forward<A>(args)...};
}
}
~cs_valarray() {
for (std::size_t i = 0; i < N; ++i) {
reinterpret_cast<T *>(&stor[i])->~T();
}
}
T &operator[](std::size_t i) {
return *reinterpret_cast<T *>(&stor[i]);
}
std::aligned_storage_t<sizeof(T), alignof(T)> stor[N];
};
/* a value buffer */
template<typename T>
struct cs_valbuf {
cs_valbuf() = delete;
cs_valbuf(cs_shared_state *cs): buf{cs_allocator<T>{cs}} {}
cs_valbuf(cs_state &cs): buf{cs_allocator<T>{cs}} {}
using size_type = std::size_t;
using value_type = T;
using reference = T &;
using const_reference = T const &;
void reserve(std::size_t s) { buf.reserve(s); }
void resize(std::size_t s) { buf.resize(s); }
void append(T const *beg, T const *end) {
buf.insert(buf.end(), beg, end);
}
void push_back(T const &v) { buf.push_back(v); }
void pop_back() { buf.pop_back(); }
T &back() { return buf.back(); }
T const &back() const { return buf.back(); }
std::size_t size() const { return buf.size(); }
std::size_t capacity() const { return buf.capacity(); }
bool empty() const { return buf.empty(); }
void clear() { buf.clear(); }
T &operator[](std::size_t i) { return buf[i]; }
T const &operator[](std::size_t i) const { return buf[i]; }
T *data() { return &buf[0]; }
T const *data() const { return &buf[0]; }
std::vector<T, cs_allocator<T>> buf;
};
/* specialization of value buffer for bytes */
struct cs_charbuf: cs_valbuf<char> {
cs_charbuf(cs_shared_state *cs): cs_valbuf<char>{cs} {}
cs_charbuf(cs_state &cs): cs_valbuf<char>{cs} {}
void append(char const *beg, char const *end) {
cs_valbuf<char>::append(beg, end);
}
void append(std::string_view v) {
append(&v[0], &v[v.size()]);
}
std::string_view str() {
return std::string_view{buf.data(), buf.size()};
}
std::string_view str_term() {
return std::string_view{buf.data(), buf.size() - 1};
}
};
} /* namespace cscript */
#endif

View File

@ -286,10 +286,10 @@ char *cs_strman::alloc_buf(std::size_t len) const {
/* strref */
cs_strref::cs_strref(cs_shared_state &cs, std::string_view str):
p_state{&cs}
cs_strref::cs_strref(cs_shared_state *cs, std::string_view str):
p_state{cs}
{
p_str = cs.strman->add(str);
p_str = cs->strman->add(str);
}
cs_strref::cs_strref(cs_state &cs, std::string_view str):
@ -304,8 +304,8 @@ cs_strref::cs_strref(cs_strref const &ref): p_state{ref.p_state}, p_str{ref.p_st
}
/* this can be used by friends to do quick cs_strref creation */
cs_strref::cs_strref(char const *p, cs_shared_state &cs):
p_state{&cs}
cs_strref::cs_strref(char const *p, cs_shared_state *cs):
p_state{cs}
{
p_str = p_state->strman->ref(p);
}

View File

@ -6,6 +6,7 @@
#include <vector>
#include "cs_bcode.hh"
#include "cs_state.hh"
namespace cscript {
@ -17,201 +18,10 @@ cs_float cs_parse_float(
std::string_view input, std::string_view *end = nullptr
);
template<typename F>
struct CsScopeExit {
template<typename FF>
CsScopeExit(FF &&f): func(std::forward<FF>(f)) {}
~CsScopeExit() {
func();
}
std::decay_t<F> func;
};
template<typename F1, typename F2>
inline void cs_do_and_cleanup(F1 &&dof, F2 &&clf) {
CsScopeExit<F2> cleanup(std::forward<F2>(clf));
dof();
}
struct cs_strman;
struct cs_shared_state;
template<typename T>
struct cs_allocator {
using value_type = T;
cs_allocator(cs_shared_state *s): state{s} {}
cs_allocator(cs_state &cs): state{cs_get_sstate(cs)} {}
template<typename U>
cs_allocator(cs_allocator<U> const &a): state{a.state} {};
inline T *allocate(std::size_t n);
inline void deallocate(T *p, std::size_t n);
template<typename U>
bool operator==(cs_allocator<U> const &a) {
return state == a.state;
}
cs_shared_state *state;
};
template<typename T>
struct cs_valbuf {
cs_valbuf() = delete;
cs_valbuf(cs_shared_state &cs):
buf{cs_allocator<T>{&cs}}
{}
cs_valbuf(cs_state &cs):
buf{cs_allocator<T>{cs_get_sstate(cs)}}
{}
using size_type = std::size_t;
using value_type = T;
using reference = T &;
using const_reference = T const &;
void reserve(std::size_t s) { buf.reserve(s); }
void resize(std::size_t s) { buf.resize(s); }
void append(T const *beg, T const *end) {
buf.insert(buf.end(), beg, end);
}
void push_back(T const &v) { buf.push_back(v); }
void pop_back() { buf.pop_back(); }
T &back() { return buf.back(); }
T const &back() const { return buf.back(); }
std::size_t size() const { return buf.size(); }
std::size_t capacity() const { return buf.capacity(); }
bool empty() const { return buf.empty(); }
void clear() { buf.clear(); }
T &operator[](std::size_t i) { return buf[i]; }
T const &operator[](std::size_t i) const { return buf[i]; }
T *data() { return &buf[0]; }
T const *data() const { return &buf[0]; }
std::vector<T, cs_allocator<T>> buf;
};
struct cs_charbuf: cs_valbuf<char> {
cs_charbuf(cs_shared_state &cs): cs_valbuf<char>(cs) {}
cs_charbuf(cs_state &cs): cs_valbuf<char>(cs) {}
void append(char const *beg, char const *end) {
cs_valbuf<char>::append(beg, end);
}
void append(std::string_view v) {
append(&v[0], &v[v.size()]);
}
std::string_view str() {
return std::string_view{buf.data(), buf.size()};
}
std::string_view str_term() {
return std::string_view{buf.data(), buf.size() - 1};
}
};
struct cs_shared_state {
using allocator_type = cs_allocator<
std::pair<std::string_view const, cs_ident *>
>;
cs_alloc_cb allocf;
void *aptr;
std::unordered_map<
std::string_view, cs_ident *,
std::hash<std::string_view>,
std::equal_to<std::string_view>,
allocator_type
> idents;
std::vector<cs_ident *, cs_allocator<cs_ident *>> identmap;
cs_vprint_cb varprintf;
cs_strman *strman;
empty_block *empty;
cs_shared_state() = delete;
cs_shared_state(cs_alloc_cb af, void *data):
allocf{af}, aptr{data},
idents{allocator_type{this}},
identmap{allocator_type{this}},
varprintf{},
strman{create<cs_strman>(this)},
empty{bcode_init_empty(this)}
{}
~cs_shared_state() {
bcode_free_empty(this, empty);
destroy(strman);
}
void *alloc(void *ptr, size_t os, size_t ns) {
void *p = allocf(aptr, ptr, os, ns);
if (!p && ns) {
throw std::bad_alloc{};
}
return p;
}
template<typename T, typename ...A>
T *create(A &&...args) {
T *ret = static_cast<T *>(alloc(nullptr, 0, sizeof(T)));
new (ret) T(std::forward<A>(args)...);
return ret;
}
template<typename T>
T *create_array(size_t len) {
T *ret = static_cast<T *>(alloc(nullptr, 0, len * sizeof(T)));
for (size_t i = 0; i < len; ++i) {
new (&ret[i]) T();
}
return ret;
}
template<typename T>
void destroy(T *v) noexcept {
v->~T();
alloc(v, sizeof(T), 0);
}
template<typename T>
void destroy_array(T *v, size_t len) noexcept {
v->~T();
alloc(v, len * sizeof(T), 0);
}
};
template<typename T>
inline T *cs_allocator<T>::allocate(std::size_t n) {
return static_cast<T *>(state->alloc(nullptr, 0, n * sizeof(T)));
}
template<typename T>
inline void cs_allocator<T>::deallocate(T *p, std::size_t n) {
state->alloc(p, n, 0);
}
inline cs_shared_state *cs_get_sstate(cs_state &cs) {
return cs.p_state;
}
inline cs_strref cs_make_strref(char const *p, cs_shared_state &cs) {
inline cs_strref cs_make_strref(char const *p, cs_shared_state *cs) {
return cs_strref{p, cs};
}

View File

@ -148,7 +148,7 @@ void cs_value::set_float(cs_float val) {
void cs_value::set_str(std::string_view val) {
csv_cleanup(p_type, p_stor);
new (&p_stor) cs_strref{*state(), val};
new (&p_stor) cs_strref{state(), val};
p_type = cs_value_type::STRING;
}
@ -224,7 +224,7 @@ cs_int cs_value::force_int() {
}
std::string_view cs_value::force_str() {
cs_charbuf rs{*state()};
cs_charbuf rs{state()};
std::string_view str;
switch (get_type()) {
case cs_value_type::FLOAT:
@ -294,17 +294,17 @@ cs_strref cs_value::get_str() const {
case cs_value_type::STRING:
return *reinterpret_cast<cs_strref const *>(&p_stor);
case cs_value_type::INT: {
cs_charbuf rs{*state()};
return cs_strref{*state(), intstr(csv_get<cs_int>(p_stor), rs)};
cs_charbuf rs{state()};
return cs_strref{state(), intstr(csv_get<cs_int>(p_stor), rs)};
}
case cs_value_type::FLOAT: {
cs_charbuf rs{*state()};
return cs_strref{*state(), floatstr(csv_get<cs_float>(p_stor), rs)};
cs_charbuf rs{state()};
return cs_strref{state(), floatstr(csv_get<cs_float>(p_stor), rs)};
}
default:
break;
}
return cs_strref{*state(), ""};
return cs_strref{state(), ""};
}
void cs_value::get_val(cs_value &r) const {

View File

@ -284,7 +284,7 @@ static inline void cs_call_alias(
cs.p_callstack = &aliaslink;
uint32_t *codep = static_cast<cs_alias_impl *>(a)->compile_code(cs)->get_raw();
bcode_incr(codep);
cs_do_and_cleanup([&]() {
call_with_cleanup([&]() {
runcode(cs, codep+1, result);
}, [&]() {
bcode_decr(codep);
@ -479,7 +479,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) {
for (int i = 0; i < numlocals; ++i) {
cs_push_alias(cs, args[offset + i].get_ident(), locals[i]);
}
cs_do_and_cleanup([&]() {
call_with_cleanup([&]() {
code = runcode(cs, code, result);
}, [&]() {
for (int i = offset; i < numargs; i++) {
@ -1296,7 +1296,7 @@ noid:
args[offset + j]
), locals[j]);
}
cs_do_and_cleanup([&]() {
call_with_cleanup([&]() {
code = runcode(cs, code, result);
}, [&]() {
for (size_t j = 0; j < size_t(callargs); ++j) {

View File

@ -8,6 +8,7 @@
#include <vector>
#include <type_traits>
#include "cs_std.hh"
#include "cs_util.hh"
#include "cs_bcode.hh"
#include "cs_ident.hh"
@ -21,27 +22,6 @@ static constexpr int DummyIdx = MaxArguments;
static constexpr int NumargsIdx = MaxArguments + 1;
static constexpr int DbgaliasIdx = MaxArguments + 2;
template<typename T, std::size_t N>
struct cs_valarray {
cs_valarray(cs_state &cs) {
for (std::size_t i = 0; i < N; ++i) {
new (&stor[i]) T{cs};
}
}
~cs_valarray() {
for (std::size_t i = 0; i < N; ++i) {
reinterpret_cast<T *>(&stor[i])->~T();
}
}
T &operator[](std::size_t i) {
return *reinterpret_cast<T *>(&stor[i]);
}
std::aligned_storage_t<sizeof(T), alignof(T)> stor[N];
};
static const int cs_valtypet[] = {
CS_VAL_NULL, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
CS_VAL_CODE, CS_VAL_IDENT
@ -235,7 +215,7 @@ static void cs_do_args(cs_state &cs, F body) {
prevstack ? prevstack->argstack : nullptr
};
cs.p_callstack = &aliaslink;
cs_do_and_cleanup(std::move(body), [&]() {
call_with_cleanup(std::move(body), [&]() {
if (prevstack) {
prevstack->usedargs = aliaslink.usedargs;
}

View File

@ -506,7 +506,7 @@ LIBCUBESCRIPT_EXPORT cs_ident *cs_state::new_ident(std::string_view name, int fl
);
}
auto *inst = p_state->create<cs_alias_impl>(
*this, cs_strref{*p_state, name}, flags
*this, cs_strref{p_state, name}, flags
);
id = add_ident(inst, inst);
}
@ -565,7 +565,7 @@ LIBCUBESCRIPT_EXPORT cs_ivar *cs_state::new_ivar(
std::string_view n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags
) {
auto *iv = p_state->create<cs_ivar_impl>(
cs_strref{*p_state, n}, m, x, v, std::move(f), flags
cs_strref{p_state, n}, m, x, v, std::move(f), flags
);
add_ident(iv, iv);
return iv;
@ -575,7 +575,7 @@ LIBCUBESCRIPT_EXPORT cs_fvar *cs_state::new_fvar(
std::string_view n, cs_float m, cs_float x, cs_float v, cs_var_cb f, int flags
) {
auto *fv = p_state->create<cs_fvar_impl>(
cs_strref{*p_state, n}, m, x, v, std::move(f), flags
cs_strref{p_state, n}, m, x, v, std::move(f), flags
);
add_ident(fv, fv);
return fv;
@ -585,8 +585,8 @@ LIBCUBESCRIPT_EXPORT cs_svar *cs_state::new_svar(
std::string_view n, std::string_view v, cs_var_cb f, int flags
) {
auto *sv = p_state->create<cs_svar_impl>(
cs_strref{*p_state, n}, cs_strref{*p_state, v},
cs_strref{*p_state, ""}, std::move(f), flags
cs_strref{p_state, n}, cs_strref{p_state, v},
cs_strref{p_state, ""}, std::move(f), flags
);
add_ident(sv, sv);
return sv;
@ -642,7 +642,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_alias(std::string_view name, cs_value v)
throw cs_error(*this, "cannot alias number %s", name.data());
} else {
auto *a = p_state->create<cs_alias_impl>(
*this, cs_strref{*p_state, name}, std::move(v), identflags
*this, cs_strref{p_state, name}, std::move(v), identflags
);
add_ident(a, a);
}
@ -775,7 +775,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_str(
*this, sv, sv->p_flags,
[&sv]() { sv->p_overrideval = sv->get_value(); }
);
sv->set_value(cs_strref{*p_state, v});
sv->set_value(cs_strref{p_state, v});
if (dofunc) {
sv->changed(*this);
}
@ -805,7 +805,7 @@ cs_state::get_var_str(std::string_view name) {
if (!id || id->is_svar()) {
return std::nullopt;
}
return cs_strref{*p_state, static_cast<cs_svar *>(id)->get_value()};
return cs_strref{p_state, static_cast<cs_svar *>(id)->get_value()};
}
LIBCUBESCRIPT_EXPORT std::optional<cs_int>
@ -957,7 +957,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_str_checked(
*this, sv, svp->p_flags,
[&svp]() { svp->p_overrideval = svp->p_storage; }
);
sv->set_value(cs_strref{*p_state, v});
sv->set_value(cs_strref{p_state, v});
svp->changed(*this);
}
@ -1011,7 +1011,7 @@ LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command(
}
}
auto *cmd = p_state->create<cs_command_impl>(
cs_strref{*p_state, name}, cs_strref{*p_state, args}, nargs,
cs_strref{p_state, name}, cs_strref{p_state, args}, nargs,
std::move(func)
);
add_ident(cmd, cmd);

View File

@ -3,6 +3,7 @@
#include <cubescript/cubescript.hh>
#include "cs_util.hh"
#include "cs_std.hh"
namespace cscript {

View File

@ -4,6 +4,7 @@
#include <cubescript/cubescript.hh>
#include "cs_util.hh"
#include "cs_std.hh"
namespace cscript {
@ -64,7 +65,7 @@ void cs_init_lib_string(cs_state &cs) {
buf[i] = tolower(inps[i]);
}
auto const *cbuf = ics->strman->steal(buf);
auto sr = cs_make_strref(cbuf, *ics);
auto sr = cs_make_strref(cbuf, ics);
ics->strman->unref(cbuf);
res.set_str(sr);
});
@ -77,7 +78,7 @@ void cs_init_lib_string(cs_state &cs) {
buf[i] = toupper(inps[i]);
}
auto const *cbuf = ics->strman->steal(buf);
auto sr = cs_make_strref(cbuf, *ics);
auto sr = cs_make_strref(cbuf, ics);
ics->strman->unref(cbuf);
res.set_str(sr);
});

View File

@ -8,6 +8,7 @@ libcubescript_src = [
'cs_error.cc',
'cs_gen.cc',
'cs_ident.cc',
'cs_state.cc',
'cs_util.cc',
'cs_val.cc',
'cs_vm.cc',