remove separate stack_state
parent
fdcc8a09e9
commit
1739cbed6e
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue