From 1739cbed6e218fbff9764cb7f1fab5be4d77b654 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Sun, 9 May 2021 20:21:35 +0200 Subject: [PATCH] remove separate stack_state --- include/cubescript/cubescript/error.hh | 83 +++++++------------------- include/cubescript/cubescript/util.hh | 3 +- src/cs_error.cc | 54 +++++------------ src/lib_base.cc | 2 +- tools/repl.cc | 2 +- 5 files changed, 42 insertions(+), 102 deletions(-) diff --git a/include/cubescript/cubescript/error.hh b/include/cubescript/cubescript/error.hh index 6a4b905..30fc1ef 100644 --- a/include/cubescript/cubescript/error.hh +++ b/include/cubescript/cubescript/error.hh @@ -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 */ diff --git a/include/cubescript/cubescript/util.hh b/include/cubescript/cubescript/util.hh index b4c8944..d835315 100644 --- a/include/cubescript/cubescript/util.hh +++ b/include/cubescript/cubescript/util.hh @@ -293,9 +293,8 @@ inline R unescape_string(R writer, std::string_view str) { * @return `writer` after writing into it */ template -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(); diff --git a/src/cs_error.cc b/src/cs_error.cc index 4a70057..2e01ef3 100644 --- a/src/cs_error.cc +++ b/src/cs_error.cc @@ -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( + auto *st = ts.istate->create_array( 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); } diff --git a/src/lib_base.cc b/src/lib_base.cc index 4d3545c..4dfeada 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -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); diff --git a/tools/repl.cc b/tools/repl.cc index 3331bfb..21327b9 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -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());