remove separate stack_state

master
Daniel Kolesa 2021-05-09 20:21:35 +02:00
parent fdcc8a09e9
commit 1739cbed6e
5 changed files with 42 additions and 102 deletions

View File

@ -18,61 +18,6 @@ namespace cubescript {
struct state;
/** @brief Represents the simplified call stack at a point in time.
*
* This is a simplified call stack; it is generally carried by errors
* and can be utilized to print out a stack trace.
*
* The actual stack is represented as a linked list of nodes. There can
* be a gap in the list, if the user has limited the maximum debug depth
* with the `dbgalias` cubescript variable; the bottommost node will always
* represent the bottom of the stack, while the nodes above it will be the
* rest of the stack or a part of the stack starting from the top.
*/
struct LIBCUBESCRIPT_EXPORT stack_state {
/** @brief A node in the call stack.
*
* The nodes are indexed. The bottommost node has index 1, the topmost
* node has index N (where N is the number of levels the call stack has).
*/
struct node {
node const *next; /**< @brief Next level. */
struct ident const *id; /**< @brief The ident of this level. */
std::size_t index; /**< @brief The level index. */
};
stack_state() = delete;
/** @brief Construct the stack state. */
stack_state(state &cs, node *nd = nullptr);
stack_state(stack_state const &) = delete;
/** @brief Move the stack state somewhere else.
*
* Stack states are movable, but not copyable.
*/
stack_state(stack_state &&st);
/** @brief Destroy the stack state. */
~stack_state();
stack_state &operator=(stack_state const &) = delete;
/** @brief Move-assign the stack state somewhere else.
*
* Stack states are move assignable, but not copy assignable.
*/
stack_state &operator=(stack_state &&);
/** @brief Get the pointer to the topmost (current) level. */
node const *get() const;
private:
state &p_state;
node *p_node;
};
/** @brief Represents a Cubescript error.
*
* This is a standard error that can be thrown by either the Cubescript APIs
@ -86,7 +31,21 @@ private:
* which is reused for each error raised from that thread.
*/
struct LIBCUBESCRIPT_EXPORT error {
friend struct state;
/** @brief A node in the call stack.
*
* The nodes are indexed. The bottommost node has index 1, the topmost
* node has index N (where N is the number of levels the call stack has).
*
* There can be a gap in the stack (i.e. the bottommost node will have
* index 1 and the one above it greater than 2). The gap is controlled
* by the value of the `dbgalias` cubescript variable at the time of
* creation of the error (the stack list will contain at most N nodes).
*/
struct stack_node {
stack_node const *next; /**< @brief Next level. */
struct ident const *id; /**< @brief The ident of this level. */
std::size_t index; /**< @brief The level index. */
};
error() = delete;
error(error const &) = delete;
@ -94,24 +53,27 @@ struct LIBCUBESCRIPT_EXPORT error {
/** @brief Errors are move constructible. */
error(error &&v):
p_errbeg{v.p_errbeg}, p_errend{v.p_errend},
p_stack{std::move(v.p_stack)}
p_stack{std::move(v.p_stack)}, p_state{v.p_state}
{}
/** @brief Construct an error using a string. */
error(state &cs, std::string_view msg);
/** @brief Destroy the error. */
~error();
/** @brief Get a view of the error message. */
std::string_view what() const {
return std::string_view{p_errbeg, std::size_t(p_errend - p_errbeg)};
}
/** @brief Get a reference to the call stack state. */
stack_state &stack() {
stack_node *stack() {
return p_stack;
}
/** @brief Get a reference to the call stack state. */
stack_state const &stack() const {
stack_node const *stack() const {
return p_stack;
}
private:
@ -120,7 +82,8 @@ private:
error(state &cs, char const *errbeg, char const *errend);
char const *p_errbeg, *p_errend;
stack_state p_stack;
stack_node *p_stack;
state *p_state;
};
} /* namespace cubescript */

View File

@ -293,9 +293,8 @@ inline R unescape_string(R writer, std::string_view str) {
* @return `writer` after writing into it
*/
template<typename R>
inline R print_stack(R writer, stack_state const &st) {
inline R print_stack(R writer, typename error::stack_node const *nd) {
char buf[32] = {0};
auto nd = st.get();
std::size_t pindex = 1;
while (nd) {
auto name = nd->id->name();

View File

@ -8,56 +8,26 @@
namespace cubescript {
LIBCUBESCRIPT_EXPORT stack_state::stack_state(
state &cs, node *nd
):
p_state{cs}, p_node{nd}
{}
LIBCUBESCRIPT_EXPORT stack_state::stack_state(stack_state &&st):
p_state{st.p_state}, p_node{st.p_node}
{
st.p_node = nullptr;
}
LIBCUBESCRIPT_EXPORT stack_state::~stack_state() {
size_t len = 0;
for (node const *nd = p_node; nd; nd = nd->next) {
++len;
}
state_p{p_state}.ts().istate->destroy_array(p_node, len);
}
LIBCUBESCRIPT_EXPORT stack_state &stack_state::operator=(stack_state &&st) {
p_node = st.p_node;
st.p_node = nullptr;
return *this;
}
LIBCUBESCRIPT_EXPORT stack_state::node const *stack_state::get() const {
return p_node;
}
static stack_state save_stack(state &cs) {
static typename error::stack_node *save_stack(state &cs) {
auto &ts = state_p{cs}.ts();
builtin_var *dalias = ts.istate->ivar_dbgalias;
auto dval = std::clamp(
dalias->value().get_integer(), integer_type(0), integer_type(1000)
);
if (!dval) {
return stack_state{cs, nullptr};
return nullptr;
}
int total = 0, depth = 0;
for (ident_link *l = ts.callstack; l; l = l->next) {
total++;
}
if (!total) {
return stack_state{cs, nullptr};
return nullptr;
}
stack_state::node *st = ts.istate->create_array<stack_state::node>(
auto *st = ts.istate->create_array<typename error::stack_node>(
std::min(total, dval)
);
stack_state::node *ret = st, *nd = st;
typename error::stack_node *ret = st, *nd = st;
++st;
for (ident_link *l = ts.callstack; l; l = l->next) {
++depth;
@ -76,11 +46,19 @@ static stack_state save_stack(state &cs) {
nd->next = nullptr;
}
}
return stack_state{cs, ret};
return ret;
}
LIBCUBESCRIPT_EXPORT error::~error() {
std::size_t slen = 0;
for (stack_node const *nd = p_stack; nd; nd = nd->next) {
++slen;
}
state_p{*p_state}.ts().istate->destroy_array(p_stack, slen);
}
LIBCUBESCRIPT_EXPORT error::error(state &cs, std::string_view msg):
p_errbeg{}, p_errend{}, p_stack{cs}
p_errbeg{}, p_errend{}, p_state{&cs}
{
char *sp;
char *buf = state_p{cs}.ts().request_errbuf(msg.size(), sp);
@ -93,7 +71,7 @@ LIBCUBESCRIPT_EXPORT error::error(state &cs, std::string_view msg):
LIBCUBESCRIPT_EXPORT error::error(
state &cs, char const *errbeg, char const *errend
): p_errbeg{errbeg}, p_errend{errend}, p_stack{cs} {
): p_errbeg{errbeg}, p_errend{errend}, p_state{&cs} {
p_stack = save_stack(cs);
}

View File

@ -84,7 +84,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) {
result = args[0].get_code().call(cs);
} catch (error const &e) {
result.set_string(e.what(), cs);
if (e.stack().get()) {
if (e.stack()) {
charbuf buf{cs};
print_stack(std::back_inserter(buf), e.stack());
tback.set_string(buf.str(), cs);

View File

@ -253,7 +253,7 @@ static bool do_call(cs::state &cs, std::string_view line, bool file = false) {
std::printf(
"%s%s\n", !is_lnum ? "stdin: " : "stdin:", e.what().data()
);
if (e.stack().get()) {
if (e.stack()) {
std::string str;
cs::print_stack(std::back_inserter(str), e.stack());
std::printf("%s\n", str.data());