remove separate stack_state
parent
fdcc8a09e9
commit
1739cbed6e
|
@ -18,61 +18,6 @@ namespace cubescript {
|
||||||
|
|
||||||
struct state;
|
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.
|
/** @brief Represents a Cubescript error.
|
||||||
*
|
*
|
||||||
* This is a standard error that can be thrown by either the Cubescript APIs
|
* 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.
|
* which is reused for each error raised from that thread.
|
||||||
*/
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT error {
|
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() = delete;
|
||||||
error(error const &) = delete;
|
error(error const &) = delete;
|
||||||
|
@ -94,24 +53,27 @@ struct LIBCUBESCRIPT_EXPORT error {
|
||||||
/** @brief Errors are move constructible. */
|
/** @brief Errors are move constructible. */
|
||||||
error(error &&v):
|
error(error &&v):
|
||||||
p_errbeg{v.p_errbeg}, p_errend{v.p_errend},
|
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. */
|
/** @brief Construct an error using a string. */
|
||||||
error(state &cs, std::string_view msg);
|
error(state &cs, std::string_view msg);
|
||||||
|
|
||||||
|
/** @brief Destroy the error. */
|
||||||
|
~error();
|
||||||
|
|
||||||
/** @brief Get a view of the error message. */
|
/** @brief Get a view of the error message. */
|
||||||
std::string_view what() const {
|
std::string_view what() const {
|
||||||
return std::string_view{p_errbeg, std::size_t(p_errend - p_errbeg)};
|
return std::string_view{p_errbeg, std::size_t(p_errend - p_errbeg)};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Get a reference to the call stack state. */
|
/** @brief Get a reference to the call stack state. */
|
||||||
stack_state &stack() {
|
stack_node *stack() {
|
||||||
return p_stack;
|
return p_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Get a reference to the call stack state. */
|
/** @brief Get a reference to the call stack state. */
|
||||||
stack_state const &stack() const {
|
stack_node const *stack() const {
|
||||||
return p_stack;
|
return p_stack;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
@ -120,7 +82,8 @@ private:
|
||||||
error(state &cs, char const *errbeg, char const *errend);
|
error(state &cs, char const *errbeg, char const *errend);
|
||||||
|
|
||||||
char const *p_errbeg, *p_errend;
|
char const *p_errbeg, *p_errend;
|
||||||
stack_state p_stack;
|
stack_node *p_stack;
|
||||||
|
state *p_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace cubescript */
|
} /* namespace cubescript */
|
||||||
|
|
|
@ -293,9 +293,8 @@ inline R unescape_string(R writer, std::string_view str) {
|
||||||
* @return `writer` after writing into it
|
* @return `writer` after writing into it
|
||||||
*/
|
*/
|
||||||
template<typename R>
|
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};
|
char buf[32] = {0};
|
||||||
auto nd = st.get();
|
|
||||||
std::size_t pindex = 1;
|
std::size_t pindex = 1;
|
||||||
while (nd) {
|
while (nd) {
|
||||||
auto name = nd->id->name();
|
auto name = nd->id->name();
|
||||||
|
|
|
@ -8,56 +8,26 @@
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT stack_state::stack_state(
|
static typename error::stack_node *save_stack(state &cs) {
|
||||||
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) {
|
|
||||||
auto &ts = state_p{cs}.ts();
|
auto &ts = state_p{cs}.ts();
|
||||||
builtin_var *dalias = ts.istate->ivar_dbgalias;
|
builtin_var *dalias = ts.istate->ivar_dbgalias;
|
||||||
auto dval = std::clamp(
|
auto dval = std::clamp(
|
||||||
dalias->value().get_integer(), integer_type(0), integer_type(1000)
|
dalias->value().get_integer(), integer_type(0), integer_type(1000)
|
||||||
);
|
);
|
||||||
if (!dval) {
|
if (!dval) {
|
||||||
return stack_state{cs, nullptr};
|
return nullptr;
|
||||||
}
|
}
|
||||||
int total = 0, depth = 0;
|
int total = 0, depth = 0;
|
||||||
for (ident_link *l = ts.callstack; l; l = l->next) {
|
for (ident_link *l = ts.callstack; l; l = l->next) {
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
if (!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)
|
std::min(total, dval)
|
||||||
);
|
);
|
||||||
stack_state::node *ret = st, *nd = st;
|
typename error::stack_node *ret = st, *nd = st;
|
||||||
++st;
|
++st;
|
||||||
for (ident_link *l = ts.callstack; l; l = l->next) {
|
for (ident_link *l = ts.callstack; l; l = l->next) {
|
||||||
++depth;
|
++depth;
|
||||||
|
@ -76,11 +46,19 @@ static stack_state save_stack(state &cs) {
|
||||||
nd->next = nullptr;
|
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):
|
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 *sp;
|
||||||
char *buf = state_p{cs}.ts().request_errbuf(msg.size(), 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(
|
LIBCUBESCRIPT_EXPORT error::error(
|
||||||
state &cs, char const *errbeg, char const *errend
|
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);
|
p_stack = save_stack(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) {
|
||||||
result = args[0].get_code().call(cs);
|
result = args[0].get_code().call(cs);
|
||||||
} catch (error const &e) {
|
} catch (error const &e) {
|
||||||
result.set_string(e.what(), cs);
|
result.set_string(e.what(), cs);
|
||||||
if (e.stack().get()) {
|
if (e.stack()) {
|
||||||
charbuf buf{cs};
|
charbuf buf{cs};
|
||||||
print_stack(std::back_inserter(buf), e.stack());
|
print_stack(std::back_inserter(buf), e.stack());
|
||||||
tback.set_string(buf.str(), cs);
|
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(
|
std::printf(
|
||||||
"%s%s\n", !is_lnum ? "stdin: " : "stdin:", e.what().data()
|
"%s%s\n", !is_lnum ? "stdin: " : "stdin:", e.what().data()
|
||||||
);
|
);
|
||||||
if (e.stack().get()) {
|
if (e.stack()) {
|
||||||
std::string str;
|
std::string str;
|
||||||
cs::print_stack(std::back_inserter(str), e.stack());
|
cs::print_stack(std::back_inserter(str), e.stack());
|
||||||
std::printf("%s\n", str.data());
|
std::printf("%s\n", str.data());
|
||||||
|
|
Loading…
Reference in New Issue