add assert in lib_base, remove formatting public error api
parent
dec7e844e7
commit
54a7b4b7f1
|
@ -10,6 +10,7 @@
|
||||||
#ifndef LIBCUBESCRIPT_CUBESCRIPT_CALLABLE_HH
|
#ifndef LIBCUBESCRIPT_CUBESCRIPT_CALLABLE_HH
|
||||||
#define LIBCUBESCRIPT_CUBESCRIPT_CALLABLE_HH
|
#define LIBCUBESCRIPT_CUBESCRIPT_CALLABLE_HH
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -108,6 +106,9 @@ struct LIBCUBESCRIPT_EXPORT error {
|
||||||
p_stack{std::move(v.p_stack)}
|
p_stack{std::move(v.p_stack)}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/** @brief Construct an error using a string. */
|
||||||
|
error(state &cs, std::string_view msg);
|
||||||
|
|
||||||
/** @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)};
|
||||||
|
@ -122,45 +123,10 @@ struct LIBCUBESCRIPT_EXPORT error {
|
||||||
stack_state const &stack() const {
|
stack_state const &stack() const {
|
||||||
return p_stack;
|
return p_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Construct an error using an unformatted string. */
|
|
||||||
error(state &cs, std::string_view msg):
|
|
||||||
p_errbeg{}, p_errend{}, p_stack{cs}
|
|
||||||
{
|
|
||||||
char *sp;
|
|
||||||
char *buf = request_buf(cs, msg.size(), sp);
|
|
||||||
std::memcpy(buf, msg.data(), msg.size());
|
|
||||||
buf[msg.size()] = '\0';
|
|
||||||
p_errbeg = sp;
|
|
||||||
p_errend = buf + msg.size();
|
|
||||||
p_stack = save_stack(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Construct an error using a `printf`-style format string. */
|
|
||||||
template<typename ...A>
|
|
||||||
error(state &cs, std::string_view msg, A const &...args):
|
|
||||||
p_errbeg{}, p_errend{}, p_stack{cs}
|
|
||||||
{
|
|
||||||
std::size_t sz = msg.size() + 64;
|
|
||||||
char *buf, *sp;
|
|
||||||
for (;;) {
|
|
||||||
buf = request_buf(cs, sz, sp);
|
|
||||||
int written = std::snprintf(buf, sz, msg.data(), args...);
|
|
||||||
if (written <= 0) {
|
|
||||||
throw error{cs, "malformed format string"};
|
|
||||||
} else if (std::size_t(written) <= sz) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sz = std::size_t(written);
|
|
||||||
}
|
|
||||||
p_errbeg = sp;
|
|
||||||
p_errend = buf + sz;
|
|
||||||
p_stack = save_stack(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
stack_state save_stack(state &cs);
|
friend struct error_p;
|
||||||
char *request_buf(state &cs, std::size_t bufs, char *&sp);
|
|
||||||
|
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_state p_stack;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "cs_thread.hh"
|
#include "cs_thread.hh"
|
||||||
|
#include "cs_error.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -44,46 +45,7 @@ LIBCUBESCRIPT_EXPORT bool stack_state::gap() const {
|
||||||
return p_gap;
|
return p_gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT char *error::request_buf(
|
static stack_state save_stack(state &cs) {
|
||||||
state &cs, std::size_t bufs, char *&sp
|
|
||||||
) {
|
|
||||||
auto &ts = state_p{cs}.ts();
|
|
||||||
charbuf &cb = ts.errbuf;
|
|
||||||
cb.clear();
|
|
||||||
std::size_t sz = 0;
|
|
||||||
if (ts.current_line) {
|
|
||||||
/* we can attach line number */
|
|
||||||
sz = ts.source.size() + 32;
|
|
||||||
for (;;) {
|
|
||||||
/* we are using so the buffer tracks the elements and therefore
|
|
||||||
* does not wipe them when we attempt to reserve more capacity
|
|
||||||
*/
|
|
||||||
cb.resize(sz);
|
|
||||||
int nsz;
|
|
||||||
if (!ts.source.empty()) {
|
|
||||||
nsz = std::snprintf(
|
|
||||||
cb.data(), sz, "%.*s:%zu: ",
|
|
||||||
int(ts.source.size()), ts.source.data(),
|
|
||||||
*ts.current_line
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
nsz = std::snprintf(cb.data(), sz, "%zu: ", *ts.current_line);
|
|
||||||
}
|
|
||||||
if (nsz <= 0) {
|
|
||||||
abort(); /* should be unreachable */
|
|
||||||
} else if (std::size_t(nsz) < sz) {
|
|
||||||
sz = std::size_t(nsz);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sz = std::size_t(nsz + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cb.resize(sz + bufs + 1);
|
|
||||||
sp = cb.data();
|
|
||||||
return &cb[sz];
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT stack_state error::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(
|
||||||
|
@ -124,4 +86,22 @@ LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) {
|
||||||
return stack_state{cs, ret, total > dval};
|
return stack_state{cs, ret, total > dval};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBCUBESCRIPT_EXPORT error::error(state &cs, std::string_view msg):
|
||||||
|
p_errbeg{}, p_errend{}, p_stack{cs}
|
||||||
|
{
|
||||||
|
char *sp;
|
||||||
|
char *buf = state_p{cs}.ts().request_errbuf(msg.size(), sp);
|
||||||
|
std::memcpy(buf, msg.data(), msg.size());
|
||||||
|
buf[msg.size()] = '\0';
|
||||||
|
p_errbeg = sp;
|
||||||
|
p_errend = buf + msg.size();
|
||||||
|
p_stack = save_stack(cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBCUBESCRIPT_EXPORT error::error(
|
||||||
|
state &cs, char const *errbeg, char const *errend
|
||||||
|
): p_errbeg{errbeg}, p_errend{errend}, p_stack{cs} {
|
||||||
|
p_stack = save_stack(cs);
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace cubescript */
|
} /* namespace cubescript */
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cs_bcode.hh"
|
#include "cs_bcode.hh"
|
||||||
#include "cs_thread.hh"
|
#include "cs_thread.hh"
|
||||||
#include "cs_vm.hh"
|
#include "cs_vm.hh"
|
||||||
|
#include "cs_error.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -229,10 +230,10 @@ LIBCUBESCRIPT_EXPORT void builtin_var::save(state &cs) {
|
||||||
auto &ts = state_p{cs}.ts();
|
auto &ts = state_p{cs}.ts();
|
||||||
if ((ts.ident_flags & IDENT_FLAG_OVERRIDDEN) || is_overridable()) {
|
if ((ts.ident_flags & IDENT_FLAG_OVERRIDDEN) || is_overridable()) {
|
||||||
if (p_impl->p_flags & IDENT_FLAG_PERSIST) {
|
if (p_impl->p_flags & IDENT_FLAG_PERSIST) {
|
||||||
throw error{
|
throw error_p::make(
|
||||||
cs, "cannot override persistent variable '%s'",
|
cs, "cannot override persistent variable '%s'",
|
||||||
name().data()
|
name().data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
if (!(p_impl->p_flags & IDENT_FLAG_OVERRIDDEN)) {
|
if (!(p_impl->p_flags & IDENT_FLAG_OVERRIDDEN)) {
|
||||||
auto *imp = static_cast<var_impl *>(p_impl);
|
auto *imp = static_cast<var_impl *>(p_impl);
|
||||||
|
@ -293,9 +294,9 @@ LIBCUBESCRIPT_EXPORT void builtin_var::set_value(
|
||||||
state &cs, any_value val, bool do_write, bool trigger
|
state &cs, any_value val, bool do_write, bool trigger
|
||||||
) {
|
) {
|
||||||
if (is_read_only()) {
|
if (is_read_only()) {
|
||||||
throw error{
|
throw error_p::make(
|
||||||
cs, "variable '%s' is read only", name().data()
|
cs, "variable '%s' is read only", name().data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
if (!do_write) {
|
if (!do_write) {
|
||||||
return;
|
return;
|
||||||
|
@ -375,7 +376,7 @@ LIBCUBESCRIPT_EXPORT any_value command::call(
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT alias_local::alias_local(state &cs, ident &a) {
|
LIBCUBESCRIPT_EXPORT alias_local::alias_local(state &cs, ident &a) {
|
||||||
if (a.type() != ident_type::ALIAS) {
|
if (a.type() != ident_type::ALIAS) {
|
||||||
throw error{cs, "ident '%s' is not an alias", a.name().data()};
|
throw error_p::make(cs, "ident '%s' is not an alias", a.name().data());
|
||||||
}
|
}
|
||||||
auto &ts = state_p{cs}.ts();
|
auto &ts = state_p{cs}.ts();
|
||||||
p_alias = static_cast<alias *>(&a);
|
p_alias = static_cast<alias *>(&a);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
#include "cs_parser.hh"
|
#include "cs_parser.hh"
|
||||||
|
#include "cs_error.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -56,9 +57,9 @@ LIBCUBESCRIPT_EXPORT char const *parse_string(
|
||||||
end:
|
end:
|
||||||
nlines = nl;
|
nlines = nl;
|
||||||
if ((beg == end) || (*beg != '\"')) {
|
if ((beg == end) || (*beg != '\"')) {
|
||||||
throw error{
|
throw error_p::make(
|
||||||
cs, "unfinished string '%.*s'", int(beg - orig), orig
|
cs, "unfinished string '%.*s'", int(beg - orig), orig
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
return ++beg;
|
return ++beg;
|
||||||
}
|
}
|
||||||
|
@ -1116,7 +1117,9 @@ static bool finish_statement(parser_state &ps, bool more, int term) {
|
||||||
/* EOS */
|
/* EOS */
|
||||||
case '\0':
|
case '\0':
|
||||||
if (ps.current() != term) {
|
if (ps.current() != term) {
|
||||||
throw error{*ps.ts.pstate, "missing \"%c\"", char(term)};
|
throw error_p::make(
|
||||||
|
*ps.ts.pstate, "missing \"%c\"", char(term)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
/* terminating parens/brackets */
|
/* terminating parens/brackets */
|
||||||
|
@ -1127,7 +1130,9 @@ static bool finish_statement(parser_state &ps, bool more, int term) {
|
||||||
ps.next_char();
|
ps.next_char();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
throw error{*ps.ts.pstate, "unexpected \"%c\"", ps.current()};
|
throw error_p::make(
|
||||||
|
*ps.ts.pstate, "unexpected \"%c\"", ps.current()
|
||||||
|
);
|
||||||
/* potential comment */
|
/* potential comment */
|
||||||
case '/':
|
case '/':
|
||||||
ps.next_char();
|
ps.next_char();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "cs_strman.hh"
|
#include "cs_strman.hh"
|
||||||
#include "cs_vm.hh" // break/continue, call_with_args
|
#include "cs_vm.hh" // break/continue, call_with_args
|
||||||
#include "cs_parser.hh"
|
#include "cs_parser.hh"
|
||||||
|
#include "cs_error.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -58,9 +59,9 @@ ident &internal_state::new_ident(state &cs, std::string_view name, int flags) {
|
||||||
ident *id = get_ident(name);
|
ident *id = get_ident(name);
|
||||||
if (!id) {
|
if (!id) {
|
||||||
if (!is_valid_name(name)) {
|
if (!is_valid_name(name)) {
|
||||||
throw error{
|
throw error_p::make(
|
||||||
cs, "'%s' is not a valid identifier name", name.data()
|
cs, "'%s' is not a valid identifier name", name.data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
auto *inst = create<alias_impl>(
|
auto *inst = create<alias_impl>(
|
||||||
cs, string_ref{cs, name}, flags
|
cs, string_ref{cs, name}, flags
|
||||||
|
@ -392,14 +393,14 @@ static void var_name_check(
|
||||||
state &cs, ident *id, std::string_view n
|
state &cs, ident *id, std::string_view n
|
||||||
) {
|
) {
|
||||||
if (id) {
|
if (id) {
|
||||||
throw error{
|
throw error_p::make(
|
||||||
cs, "redefinition of ident '%.*s'", int(n.size()), n.data()
|
cs, "redefinition of ident '%.*s'", int(n.size()), n.data()
|
||||||
};
|
);
|
||||||
} else if (!is_valid_name(n)) {
|
} else if (!is_valid_name(n)) {
|
||||||
throw error{
|
throw error_p::make(
|
||||||
cs, "'%.*s' is not a valid variable name",
|
cs, "'%.*s' is not a valid variable name",
|
||||||
int(n.size()), n.data()
|
int(n.size()), n.data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,13 +473,15 @@ LIBCUBESCRIPT_EXPORT void state::assign_value(
|
||||||
id->get().call(span_type<any_value>{&v, 1}, *this);
|
id->get().call(span_type<any_value>{&v, 1}, *this);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw error{
|
throw error_p::make(
|
||||||
*this, "cannot redefine builtin %s with an alias",
|
*this, "cannot redefine builtin %s with an alias",
|
||||||
id->get().name().data()
|
id->get().name().data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
} else if (!is_valid_name(name)) {
|
} else if (!is_valid_name(name)) {
|
||||||
throw error{*this, "cannot alias invalid name '%s'", name.data()};
|
throw error_p::make(
|
||||||
|
*this, "cannot alias invalid name '%s'", name.data()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
auto *a = p_tstate->istate->create<alias_impl>(
|
auto *a = p_tstate->istate->create<alias_impl>(
|
||||||
*this, string_ref{*this, name}, std::move(v),
|
*this, string_ref{*this, name}, std::move(v),
|
||||||
|
@ -531,17 +534,21 @@ LIBCUBESCRIPT_EXPORT any_value state::lookup_value(std::string_view name) {
|
||||||
return any_value{};
|
return any_value{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw error{*this, "unknown alias lookup: %s", name.data()};
|
throw error_p::make(*this, "unknown alias lookup: %s", name.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT void state::reset_value(std::string_view name) {
|
LIBCUBESCRIPT_EXPORT void state::reset_value(std::string_view name) {
|
||||||
auto id = get_ident(name);
|
auto id = get_ident(name);
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw error{*this, "variable '%s' does not exist", name.data()};
|
throw error_p::make(
|
||||||
|
*this, "variable '%s' does not exist", name.data()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (id->get().type() == ident_type::VAR) {
|
if (id->get().type() == ident_type::VAR) {
|
||||||
if (static_cast<builtin_var &>(id->get()).is_read_only()) {
|
if (static_cast<builtin_var &>(id->get()).is_read_only()) {
|
||||||
throw error{*this, "variable '%s' is read only", name.data()};
|
throw error_p::make(
|
||||||
|
*this, "variable '%s' is read only", name.data()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clear_override(id->get());
|
clear_override(id->get());
|
||||||
|
@ -619,9 +626,9 @@ LIBCUBESCRIPT_EXPORT command &state::new_command(
|
||||||
fmt += 2;
|
fmt += 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw error{
|
throw error_p::make(
|
||||||
*this, "invalid argument type: %c", *fmt
|
*this, "invalid argument type: %c", *fmt
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto &is = *p_tstate->istate;
|
auto &is = *p_tstate->istate;
|
||||||
|
@ -653,18 +660,18 @@ LIBCUBESCRIPT_EXPORT command &state::new_command(
|
||||||
}
|
}
|
||||||
/* we haven't found one matching the list, so error */
|
/* we haven't found one matching the list, so error */
|
||||||
is.destroy(cmd);
|
is.destroy(cmd);
|
||||||
throw error{
|
throw error_p::make(
|
||||||
*this, "forbidden builtin command: %.*s",
|
*this, "forbidden builtin command: %.*s",
|
||||||
int(name.size()), name.data()
|
int(name.size()), name.data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
valid:
|
valid:
|
||||||
if (is.get_ident(name)) {
|
if (is.get_ident(name)) {
|
||||||
is.destroy(cmd);
|
is.destroy(cmd);
|
||||||
throw error{
|
throw error_p::make(
|
||||||
*this, "redefinition of ident '%.*s'",
|
*this, "redefinition of ident '%.*s'",
|
||||||
int(name.size()), name.data()
|
int(name.size()), name.data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
do_add:
|
do_add:
|
||||||
is.add_ident(cmd, cmd);
|
is.add_ident(cmd, cmd);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "cs_thread.hh"
|
#include "cs_thread.hh"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
thread_state::thread_state(internal_state *cs):
|
thread_state::thread_state(internal_state *cs):
|
||||||
|
@ -27,4 +29,41 @@ alias_stack &thread_state::get_astack(alias const *a) {
|
||||||
return it.first->second;
|
return it.first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *thread_state::request_errbuf(std::size_t bufs, char *&sp) {
|
||||||
|
errbuf.clear();
|
||||||
|
std::size_t sz = 0;
|
||||||
|
if (current_line) {
|
||||||
|
/* we can attach line number */
|
||||||
|
sz = source.size() + 32;
|
||||||
|
for (;;) {
|
||||||
|
/* we are using so the buffer tracks the elements and therefore
|
||||||
|
* does not wipe them when we attempt to reserve more capacity
|
||||||
|
*/
|
||||||
|
errbuf.resize(sz);
|
||||||
|
int nsz;
|
||||||
|
if (!source.empty()) {
|
||||||
|
nsz = std::snprintf(
|
||||||
|
errbuf.data(), sz, "%.*s:%zu: ",
|
||||||
|
int(source.size()), source.data(),
|
||||||
|
*current_line
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
nsz = std::snprintf(
|
||||||
|
errbuf.data(), sz, "%zu: ", *current_line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (nsz <= 0) {
|
||||||
|
abort(); /* should be unreachable */
|
||||||
|
} else if (std::size_t(nsz) < sz) {
|
||||||
|
sz = std::size_t(nsz);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sz = std::size_t(nsz + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errbuf.resize(sz + bufs + 1);
|
||||||
|
sp = errbuf.data();
|
||||||
|
return &errbuf[sz];
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace cubescript */
|
} /* namespace cubescript */
|
||||||
|
|
|
@ -53,6 +53,8 @@ struct thread_state {
|
||||||
hook_func const &get_hook() const { return call_hook; }
|
hook_func const &get_hook() const { return call_hook; }
|
||||||
|
|
||||||
alias_stack &get_astack(alias const *a);
|
alias_stack &get_astack(alias const *a);
|
||||||
|
|
||||||
|
char *request_errbuf(std::size_t bufs, char *&sp);
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace cubescript */
|
} /* namespace cubescript */
|
||||||
|
|
13
src/cs_vm.cc
13
src/cs_vm.cc
|
@ -2,6 +2,7 @@
|
||||||
#include "cs_vm.hh"
|
#include "cs_vm.hh"
|
||||||
#include "cs_std.hh"
|
#include "cs_std.hh"
|
||||||
#include "cs_parser.hh"
|
#include "cs_parser.hh"
|
||||||
|
#include "cs_error.hh"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -149,9 +150,9 @@ bool exec_alias(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (aast.flags & IDENT_FLAG_UNKNOWN) {
|
} else if (aast.flags & IDENT_FLAG_UNKNOWN) {
|
||||||
throw error {
|
throw error_p::make(
|
||||||
*ts.pstate, "unknown command: %s", a->name().data()
|
*ts.pstate, "unknown command: %s", a->name().data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
/* excess arguments get ignored (make error maybe?) */
|
/* excess arguments get ignored (make error maybe?) */
|
||||||
callargs = std::min(callargs, MAX_ARGUMENTS);
|
callargs = std::min(callargs, MAX_ARGUMENTS);
|
||||||
|
@ -237,9 +238,9 @@ static inline alias *get_lookup_id(
|
||||||
} else {
|
} else {
|
||||||
ast = &ts.get_astack(static_cast<alias *>(id));
|
ast = &ts.get_astack(static_cast<alias *>(id));
|
||||||
if (ast->flags & IDENT_FLAG_UNKNOWN) {
|
if (ast->flags & IDENT_FLAG_UNKNOWN) {
|
||||||
throw error{
|
throw error_p::make(
|
||||||
*ts.pstate, "unknown alias lookup: %s", id->name().data()
|
*ts.pstate, "unknown alias lookup: %s", id->name().data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return static_cast<alias *>(id);
|
return static_cast<alias *>(id);
|
||||||
|
@ -799,9 +800,9 @@ noid:
|
||||||
result.force_none();
|
result.force_none();
|
||||||
force_arg(cs, result, op & BC_INST_RET_MASK);
|
force_arg(cs, result, op & BC_INST_RET_MASK);
|
||||||
std::string_view ids{idn};
|
std::string_view ids{idn};
|
||||||
throw error{
|
throw error_p::make(
|
||||||
cs, "unknown command: %s", ids.data()
|
cs, "unknown command: %s", ids.data()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
result.force_none();
|
result.force_none();
|
||||||
switch (ident_p{id->get()}.impl().p_type) {
|
switch (ident_p{id->get()}.impl().p_type) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "cs_std.hh"
|
#include "cs_std.hh"
|
||||||
#include "cs_ident.hh"
|
#include "cs_ident.hh"
|
||||||
#include "cs_thread.hh"
|
#include "cs_thread.hh"
|
||||||
|
#include "cs_error.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -72,10 +73,10 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) {
|
||||||
auto &cret = args[1].get_ident(cs);
|
auto &cret = args[1].get_ident(cs);
|
||||||
auto &css = args[2].get_ident(cs);
|
auto &css = args[2].get_ident(cs);
|
||||||
if (cret.type() != ident_type::ALIAS) {
|
if (cret.type() != ident_type::ALIAS) {
|
||||||
throw error{cs, "'%s' is not an alias", cret.name().data()};
|
throw error_p::make(cs, "'%s' is not an alias", cret.name().data());
|
||||||
}
|
}
|
||||||
if (css.type() != ident_type::ALIAS) {
|
if (css.type() != ident_type::ALIAS) {
|
||||||
throw error{cs, "'%s' is not an alias", css.name().data()};
|
throw error_p::make(cs, "'%s' is not an alias", css.name().data());
|
||||||
}
|
}
|
||||||
any_value result{}, tback{};
|
any_value result{}, tback{};
|
||||||
bool rc = true;
|
bool rc = true;
|
||||||
|
@ -98,6 +99,25 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) {
|
||||||
ts.get_astack(ssa).set_alias(ssa, ts, tback);
|
ts.get_astack(ssa).set_alias(ssa, ts, tback);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
new_cmd_quiet(gcs, "assert", "ss#", [](auto &s, auto args, auto &ret) {
|
||||||
|
auto val = args[0];
|
||||||
|
val.force_code(s);
|
||||||
|
if (!val.get_code().call(s).get_bool()) {
|
||||||
|
if (args[2].get_integer() > 1) {
|
||||||
|
throw error_p::make(
|
||||||
|
s, "assertion failed: [%s] (%s)",
|
||||||
|
args[0].get_string(s).data(), args[1].get_string(s).data()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw error_p::make(
|
||||||
|
s, "assertion failed: [%s]",
|
||||||
|
args[0].get_string(s).data()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = std::move(args[0]);
|
||||||
|
});
|
||||||
|
|
||||||
new_cmd_quiet(gcs, "?", "aaa", [](auto &, auto args, auto &res) {
|
new_cmd_quiet(gcs, "?", "aaa", [](auto &, auto args, auto &res) {
|
||||||
if (args[0].get_bool()) {
|
if (args[0].get_bool()) {
|
||||||
res = std::move(args[1]);
|
res = std::move(args[1]);
|
||||||
|
@ -343,7 +363,7 @@ end:
|
||||||
new_cmd_quiet(gcs, "getalias", "s", [](auto &cs, auto args, auto &res) {
|
new_cmd_quiet(gcs, "getalias", "s", [](auto &cs, auto args, auto &res) {
|
||||||
auto &id = cs.new_ident(args[0].get_string(cs));
|
auto &id = cs.new_ident(args[0].get_string(cs));
|
||||||
if (id.type() != ident_type::ALIAS) {
|
if (id.type() != ident_type::ALIAS) {
|
||||||
throw error{cs, "'%s' is not an alias", id.name().data()};
|
throw error_p::make(cs, "'%s' is not an alias", id.name().data());
|
||||||
}
|
}
|
||||||
if (ident_p{id}.impl().p_flags & IDENT_FLAG_UNKNOWN) {
|
if (ident_p{id}.impl().p_flags & IDENT_FLAG_UNKNOWN) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -58,26 +58,6 @@ int main(int argc, char **argv) {
|
||||||
throw skip_test{};
|
throw skip_test{};
|
||||||
});
|
});
|
||||||
|
|
||||||
/* takes a string so we can print it */
|
|
||||||
gcs.new_command("assert", "ss#", [](auto &s, auto args, auto &ret) {
|
|
||||||
auto val = args[0];
|
|
||||||
val.force_code(s);
|
|
||||||
if (!val.get_code().call(s).get_bool()) {
|
|
||||||
if (args[2].get_integer() > 1) {
|
|
||||||
throw cs::error{
|
|
||||||
s, "assertion failed: [%s] (%s)",
|
|
||||||
args[0].get_string(s).data(), args[1].get_string(s).data()
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
throw cs::error{
|
|
||||||
s, "assertion failed: [%s]",
|
|
||||||
args[0].get_string(s).data()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = std::move(args[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
do_exec_file(gcs, argv[1]);
|
do_exec_file(gcs, argv[1]);
|
||||||
} catch (skip_test) {
|
} catch (skip_test) {
|
||||||
|
|
|
@ -360,9 +360,11 @@ int main(int argc, char **argv) {
|
||||||
cs::any_value val{};
|
cs::any_value val{};
|
||||||
bool ret = do_exec_file(css, file, val);
|
bool ret = do_exec_file(css, file, val);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
throw cs::error(
|
char buf[4096];
|
||||||
css, "could not execute file \"%s\"", file.data()
|
std::snprintf(
|
||||||
|
buf, sizeof(buf), "could not execute file \"%s\"", file.data()
|
||||||
);
|
);
|
||||||
|
throw cs::error(css, buf);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue