document error, ident
parent
a1b5575a9a
commit
e7578f7e17
|
@ -20,27 +20,71 @@ namespace cubescript {
|
||||||
|
|
||||||
struct state;
|
struct state;
|
||||||
|
|
||||||
|
/** @brief An internal Cubescript error.
|
||||||
|
*
|
||||||
|
* This is an error that is never expected; it is thrown
|
||||||
|
* when some API call fails due to most likely a bug.
|
||||||
|
*/
|
||||||
struct internal_error: std::runtime_error {
|
struct internal_error: std::runtime_error {
|
||||||
using std::runtime_error::runtime_error;
|
using std::runtime_error::runtime_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @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 {
|
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 {
|
struct node {
|
||||||
node const *next;
|
node const *next; /**< @brief Next level. */
|
||||||
struct ident const *id;
|
struct ident const *id; /**< @brief The ident of this level. */
|
||||||
int index;
|
int index; /**< @brief The level index. */
|
||||||
};
|
};
|
||||||
|
|
||||||
stack_state() = delete;
|
stack_state() = delete;
|
||||||
|
|
||||||
|
/** @brief Construct the stack state. */
|
||||||
stack_state(state &cs, node *nd = nullptr, bool gap = false);
|
stack_state(state &cs, node *nd = nullptr, bool gap = false);
|
||||||
|
|
||||||
stack_state(stack_state const &) = delete;
|
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);
|
stack_state(stack_state &&st);
|
||||||
|
|
||||||
|
/** @brief Destroy the stack state. */
|
||||||
~stack_state();
|
~stack_state();
|
||||||
|
|
||||||
stack_state &operator=(stack_state const &) = delete;
|
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 &&);
|
stack_state &operator=(stack_state &&);
|
||||||
|
|
||||||
|
/** @brief Get the pointer to the topmost (current) level. */
|
||||||
node const *get() const;
|
node const *get() const;
|
||||||
|
|
||||||
|
/** @brief Get whether the stack is incomplete.
|
||||||
|
*
|
||||||
|
* A value of `true` means the call stack has a gap in it, i.e. the
|
||||||
|
* bottommost node has index 1 while the node just above it has index
|
||||||
|
* greater than 2.
|
||||||
|
*/
|
||||||
bool gap() const;
|
bool gap() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -49,28 +93,46 @@ private:
|
||||||
bool p_gap;
|
bool p_gap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief Represents a Cubescript error.
|
||||||
|
*
|
||||||
|
* This is a standard error that can be thrown by either the Cubescript APIs
|
||||||
|
* or from the language itself (either by the user, or by incorrect use of
|
||||||
|
* the API).
|
||||||
|
*
|
||||||
|
* It has a message attached, as well as the current state of the call stack,
|
||||||
|
* represented as cubescript::stack_state.
|
||||||
|
*
|
||||||
|
* Each Cubescript thread internally stores a buffer for the error message,
|
||||||
|
* which is reused for each error raised from that thread.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT error {
|
struct LIBCUBESCRIPT_EXPORT error {
|
||||||
friend struct state;
|
friend struct state;
|
||||||
|
|
||||||
error() = delete;
|
error() = delete;
|
||||||
error(error const &) = delete;
|
error(error const &) = delete;
|
||||||
|
|
||||||
|
/** @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)}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/** @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. */
|
||||||
stack_state &get_stack() {
|
stack_state &get_stack() {
|
||||||
return p_stack;
|
return p_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Get a reference to the call stack state. */
|
||||||
stack_state const &get_stack() const {
|
stack_state const &get_stack() const {
|
||||||
return p_stack;
|
return p_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Construct an error using an unformatted string. */
|
||||||
error(state &cs, std::string_view msg):
|
error(state &cs, std::string_view msg):
|
||||||
p_errbeg{}, p_errend{}, p_stack{cs}
|
p_errbeg{}, p_errend{}, p_stack{cs}
|
||||||
{
|
{
|
||||||
|
@ -83,6 +145,7 @@ struct LIBCUBESCRIPT_EXPORT error {
|
||||||
p_stack = save_stack(cs);
|
p_stack = save_stack(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Construct an error using a `printf`-style format string. */
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
error(state &cs, std::string_view msg, A const &...args):
|
error(state &cs, std::string_view msg, A const &...args):
|
||||||
p_errbeg{}, p_errend{}, p_stack{cs}
|
p_errbeg{}, p_errend{}, p_stack{cs}
|
||||||
|
|
|
@ -18,8 +18,17 @@
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
/** @brief The type of the ident.
|
||||||
|
*
|
||||||
|
* Cubescript has a selection of idents. This represents the type of each.
|
||||||
|
*/
|
||||||
enum class ident_type {
|
enum class ident_type {
|
||||||
IVAR = 0, FVAR, SVAR, COMMAND, ALIAS, SPECIAL
|
IVAR = 0, /**< @brief Integer builtin variable. */
|
||||||
|
FVAR, /**< @brief Float builtin variable. */
|
||||||
|
SVAR, /**< @brief String builtin variable. */
|
||||||
|
COMMAND, /**< @brief Builtin command. */
|
||||||
|
ALIAS, /**< @brief User assigned variable. */
|
||||||
|
SPECIAL /**< @brief Other (internal unexposed type). */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct global_var;
|
struct global_var;
|
||||||
|
@ -29,38 +38,156 @@ struct string_var;
|
||||||
struct alias;
|
struct alias;
|
||||||
struct command;
|
struct command;
|
||||||
|
|
||||||
|
/** @brief The ident structure.
|
||||||
|
*
|
||||||
|
* Every object within the Cubescript language is represented with an ident.
|
||||||
|
* This is the generic base interface. There are some operations that are
|
||||||
|
* available on any ident.
|
||||||
|
*
|
||||||
|
* You can also check the actual type with it (cubescript::ident_type) and
|
||||||
|
* decide to cast it to its appropriate specific type, or use the helpers.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT ident {
|
struct LIBCUBESCRIPT_EXPORT ident {
|
||||||
|
/** @brief Get the cubescript::ident_type of this ident. */
|
||||||
ident_type get_type() const;
|
ident_type get_type() const;
|
||||||
|
|
||||||
|
/** @brief Get a view to the name of the ident. */
|
||||||
std::string_view get_name() const;
|
std::string_view get_name() const;
|
||||||
|
|
||||||
|
/** @brief Get the index of the ident.
|
||||||
|
*
|
||||||
|
* Idents are internally indexed. There is no guarantee of what index
|
||||||
|
* the ident will have, but you can still use it to identify the object
|
||||||
|
* with an integer (it is guaranteed that once created, it will stay the
|
||||||
|
* same for the whole lifetime of the main thread).
|
||||||
|
*/
|
||||||
int get_index() const;
|
int get_index() const;
|
||||||
|
|
||||||
|
/** @brief Check if the ident is a cubescript::alias.
|
||||||
|
*
|
||||||
|
* Effectively like `get_type() == ident_type::ALIAS`.
|
||||||
|
*/
|
||||||
bool is_alias() const;
|
bool is_alias() const;
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::alias.
|
||||||
|
*
|
||||||
|
* @return A pointer to the alias if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
alias *get_alias();
|
alias *get_alias();
|
||||||
alias const *get_alias() const;
|
alias const *get_alias() const;
|
||||||
|
|
||||||
|
/** @brief Check if the ident is a cubescript::command.
|
||||||
|
*
|
||||||
|
* Effectively like `get_type() == ident_type::COMMAND`.
|
||||||
|
*/
|
||||||
bool is_command() const;
|
bool is_command() const;
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::command.
|
||||||
|
*
|
||||||
|
* @return A pointer to the command if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
command *get_command();
|
command *get_command();
|
||||||
command const *get_command() const;
|
command const *get_command() const;
|
||||||
|
|
||||||
|
/** @brief Check if the ident is a special ident.
|
||||||
|
*
|
||||||
|
* Effectively like `get_type() == ident_type::SPECIAL`.
|
||||||
|
*/
|
||||||
bool is_special() const;
|
bool is_special() const;
|
||||||
|
|
||||||
|
/** @brief Check if the ident is a cubescript::global_var.
|
||||||
|
*
|
||||||
|
* This will return `true` if ident::get_type() returns either
|
||||||
|
* ident_type::IVAR, ident_type::FVAR or ident_type::SVAR.
|
||||||
|
*/
|
||||||
bool is_var() const;
|
bool is_var() const;
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::global_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
global_var *get_var();
|
global_var *get_var();
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::global_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
global_var const *get_var() const;
|
global_var const *get_var() const;
|
||||||
|
|
||||||
|
/** @brief Check if the ident is a cubescript::integer_var.
|
||||||
|
*
|
||||||
|
* Effectively like `get_type() == ident_type::IVAR`.
|
||||||
|
*/
|
||||||
bool is_ivar() const;
|
bool is_ivar() const;
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::integer_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
integer_var *get_ivar();
|
integer_var *get_ivar();
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::integer_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
integer_var const *get_ivar() const;
|
integer_var const *get_ivar() const;
|
||||||
|
|
||||||
|
/** @brief Check if the ident is a cubescript::float_var.
|
||||||
|
*
|
||||||
|
* Effectively like `get_type() == ident_type::FVAR`.
|
||||||
|
*/
|
||||||
bool is_fvar() const;
|
bool is_fvar() const;
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::float_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
float_var *get_fvar();
|
float_var *get_fvar();
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::float_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
float_var const *get_fvar() const;
|
float_var const *get_fvar() const;
|
||||||
|
|
||||||
|
/** @brief Check if the ident is a cubescript::string_var.
|
||||||
|
*
|
||||||
|
* Effectively like `get_type() == ident_type::SVAR`.
|
||||||
|
*/
|
||||||
bool is_svar() const;
|
bool is_svar() const;
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::string_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
string_var *get_svar();
|
string_var *get_svar();
|
||||||
|
|
||||||
|
/** @brief Try to convert this to cubescript::string_var.
|
||||||
|
*
|
||||||
|
* @return A pointer to the var if it is one, or `nullptr`.
|
||||||
|
*/
|
||||||
string_var const *get_svar() const;
|
string_var const *get_svar() const;
|
||||||
|
|
||||||
|
/** @brief Get if the ident is overridden.
|
||||||
|
*
|
||||||
|
* This can be true for aliases or builtins. When an alias or a builtin
|
||||||
|
* is assigned to and the VM is in override mode or the builtin is
|
||||||
|
* var_type::OVERRIDABLE, they are marked as overridden (and builtins
|
||||||
|
* have their value saved beforehand).
|
||||||
|
*
|
||||||
|
* This can be cleared later, which will erase the value (for aliases)
|
||||||
|
* or restore the saved one (for builtins). For aliases, this can be
|
||||||
|
* specific to the Cubescript thread.
|
||||||
|
*/
|
||||||
bool is_overridden(state &cs) const;
|
bool is_overridden(state &cs) const;
|
||||||
|
|
||||||
|
/** @brief Get if the ident is persistent.
|
||||||
|
*
|
||||||
|
* This can be true in two cases. Either it's a builtin and it has the
|
||||||
|
* var_type::PERSISTENT flag, or it's an alias that is assigned to while
|
||||||
|
* the VM is in persist mode. The latter can be thread specific (when the
|
||||||
|
* alias is currently pushed).
|
||||||
|
*/
|
||||||
bool is_persistent(state &cs) const;
|
bool is_persistent(state &cs) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -71,69 +198,209 @@ protected:
|
||||||
struct ident_impl *p_impl{};
|
struct ident_impl *p_impl{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief An additional cubescript::global_var type.
|
||||||
|
*
|
||||||
|
* Global vars can have no additional type, or they can be persistent, or
|
||||||
|
* they can be overridable. Persistent variables are meant to be saved and
|
||||||
|
* loaded later (the actual logic is up to the user of the library).
|
||||||
|
*
|
||||||
|
* Overridable variables are overridden when assigned to (this can also
|
||||||
|
* happen to normal variables when the VM is in override mode), which saves
|
||||||
|
* their old value (which can be restored later when un-overridden). This
|
||||||
|
* is mutually exclusive; overridable variables cannot be persistent, and
|
||||||
|
* attempting to assign to a persistent variable while the VM is in override
|
||||||
|
* mode will raise an error.
|
||||||
|
*/
|
||||||
enum class var_type {
|
enum class var_type {
|
||||||
DEFAULT = 0,
|
DEFAULT = 0, /**< @brief The default type. */
|
||||||
PERSISTENT,
|
PERSISTENT, /**< @brief Persistent variable. */
|
||||||
OVERRIDABLE
|
OVERRIDABLE /**< @brief Overridable variable. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief A global variable.
|
||||||
|
*
|
||||||
|
* This represents one of cubescript::integer_var, cubescript::float_var or
|
||||||
|
* cubescript::string_var as a single interface, with shared operations.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT global_var: ident {
|
struct LIBCUBESCRIPT_EXPORT global_var: ident {
|
||||||
|
/** @brief Get whether the variable is read only.
|
||||||
|
*
|
||||||
|
* Variables can be set as read only during their creation (but not
|
||||||
|
* later). This will prevent assignments to them from within the language
|
||||||
|
* or using checked APIs, but it is still possible to assign to them
|
||||||
|
* using raw APIs. The raw APIs will not invoke value triggers, however.
|
||||||
|
*/
|
||||||
bool is_read_only() const;
|
bool is_read_only() const;
|
||||||
|
|
||||||
|
/** @brief Get whether the variable is overridable.
|
||||||
|
*
|
||||||
|
* Equivalent to `get_variable_type() == var_type::OVERRIDABLE`.
|
||||||
|
*/
|
||||||
bool is_overridable() const;
|
bool is_overridable() const;
|
||||||
|
|
||||||
|
/** @brief Get the cubescript::var_type of the variable. */
|
||||||
var_type get_variable_type() const;
|
var_type get_variable_type() const;
|
||||||
|
|
||||||
|
/** @brief Save the variable.
|
||||||
|
*
|
||||||
|
* This is mainly intended for variable assignment triggers. If the
|
||||||
|
* variable is overridable or the given thread is in override mode,
|
||||||
|
* this will save the current value of the variable (if not already
|
||||||
|
* overridden). Otherwise, it will clear any existing overridden flag.
|
||||||
|
*
|
||||||
|
* @throw cubescript::error if the thread is in override mode and the
|
||||||
|
* variable is persistent.
|
||||||
|
*/
|
||||||
void save(state &cs);
|
void save(state &cs);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
global_var() = default;
|
global_var() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief An integer variable.
|
||||||
|
*
|
||||||
|
* A specialization of cubescript::global_var for integer values.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT integer_var: global_var {
|
struct LIBCUBESCRIPT_EXPORT integer_var: global_var {
|
||||||
|
/** @brief Get the value of the variable. */
|
||||||
integer_type get_value() const;
|
integer_type get_value() const;
|
||||||
|
|
||||||
|
/** @brief Set the value of the variable.
|
||||||
|
*
|
||||||
|
* If read only, an error is raised. If `do_write` is `false`, nothing
|
||||||
|
* will be performed other than the read-only checking. If `trigger` is
|
||||||
|
* `false`, a potential variable change trigger command will not be
|
||||||
|
* invoked. The value is saved with global_var::save(), assuming
|
||||||
|
* `do_write` is `true`. After that, integer_var::set_raw_value()
|
||||||
|
* is invoked, and then the trigger.
|
||||||
|
*
|
||||||
|
* @throw cubescript::error if read only or if the changed trigger throws.
|
||||||
|
*/
|
||||||
void set_value(
|
void set_value(
|
||||||
state &cs, integer_type val, bool do_write = true, bool trigger = true
|
state &cs, integer_type val, bool do_write = true, bool trigger = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** @brief Set the value of the variable in a raw manner.
|
||||||
|
*
|
||||||
|
* This will always set the value and ignore any kinds of checks. It will
|
||||||
|
* not invoke any triggers either, nor it will save the the value.
|
||||||
|
*/
|
||||||
void set_raw_value(integer_type val);
|
void set_raw_value(integer_type val);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
integer_var() = default;
|
integer_var() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief A float variable.
|
||||||
|
*
|
||||||
|
* A specialization of cubescript::global_var for float values.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT float_var: global_var {
|
struct LIBCUBESCRIPT_EXPORT float_var: global_var {
|
||||||
|
/** @brief Get the value of the variable. */
|
||||||
float_type get_value() const;
|
float_type get_value() const;
|
||||||
|
|
||||||
|
/** @brief Set the value of the variable.
|
||||||
|
*
|
||||||
|
* If read only, an error is raised. If `do_write` is `false`, nothing
|
||||||
|
* will be performed other than the read-only checking. If `trigger` is
|
||||||
|
* `false`, a potential variable change trigger command will not be
|
||||||
|
* invoked. The value is saved with global_var::save(), assuming
|
||||||
|
* `do_write` is `true`. After that, integer_var::set_raw_value()
|
||||||
|
* is invoked, and then the trigger.
|
||||||
|
*
|
||||||
|
* @throw cubescript::error if read only or if the changed trigger throws.
|
||||||
|
*/
|
||||||
void set_value(
|
void set_value(
|
||||||
state &cs, float_type val, bool do_write = true, bool trigger = true
|
state &cs, float_type val, bool do_write = true, bool trigger = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** @brief Set the value of the variable in a raw manner.
|
||||||
|
*
|
||||||
|
* This will always set the value and ignore any kinds of checks. It will
|
||||||
|
* not invoke any triggers either, nor it will save the the value.
|
||||||
|
*/
|
||||||
void set_raw_value(float_type val);
|
void set_raw_value(float_type val);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float_var() = default;
|
float_var() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief A string variable.
|
||||||
|
*
|
||||||
|
* A specialization of cubescript::global_var for string values.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT string_var: global_var {
|
struct LIBCUBESCRIPT_EXPORT string_var: global_var {
|
||||||
|
/** @brief Get the value of the variable. */
|
||||||
string_ref get_value() const;
|
string_ref get_value() const;
|
||||||
|
|
||||||
|
/** @brief Set the value of the variable.
|
||||||
|
*
|
||||||
|
* If read only, an error is raised. If `do_write` is `false`, nothing
|
||||||
|
* will be performed other than the read-only checking. If `trigger` is
|
||||||
|
* `false`, a potential variable change trigger command will not be
|
||||||
|
* invoked. The value is saved with global_var::save(), assuming
|
||||||
|
* `do_write` is `true`. After that, integer_var::set_raw_value()
|
||||||
|
* is invoked, and then the trigger.
|
||||||
|
*
|
||||||
|
* @throw cubescript::error if read only or if the changed trigger throws.
|
||||||
|
*/
|
||||||
void set_value(
|
void set_value(
|
||||||
state &cs, string_ref val, bool do_write = true, bool trigger = true
|
state &cs, string_ref val, bool do_write = true, bool trigger = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** @brief Set the value of the variable in a raw manner.
|
||||||
|
*
|
||||||
|
* This will always set the value and ignore any kinds of checks. It will
|
||||||
|
* not invoke any triggers either, nor it will save the the value.
|
||||||
|
*/
|
||||||
void set_raw_value(string_ref val);
|
void set_raw_value(string_ref val);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
string_var() = default;
|
string_var() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief An alias.
|
||||||
|
*
|
||||||
|
* An alias is an ident that is created inside the language, for example
|
||||||
|
* by assignment. Any variable that you can assign to or look up and is not
|
||||||
|
* a builtin is an alias. Aliases don't have special assignment syntax nor
|
||||||
|
* they have changed triggers nor value saving. They technically always
|
||||||
|
* represent a string within the language, though on C++ side they can
|
||||||
|
* have float or integer values too.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT alias: ident {
|
struct LIBCUBESCRIPT_EXPORT alias: ident {
|
||||||
|
/** @brief Get if this alias represents a function argument.
|
||||||
|
*
|
||||||
|
* This is true for `argN` aliases representing the arguments passed to
|
||||||
|
* the current function.
|
||||||
|
*/
|
||||||
bool is_arg() const;
|
bool is_arg() const;
|
||||||
|
|
||||||
|
/** @brief Get the value of the alias for the given thread. */
|
||||||
any_value get_value(state &cs) const;
|
any_value get_value(state &cs) const;
|
||||||
|
|
||||||
|
/** @brief Set the value of the alias for the given thread. */
|
||||||
void set_value(state &cs, any_value v);
|
void set_value(state &cs, any_value v);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
alias() = default;
|
alias() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief A command.
|
||||||
|
*
|
||||||
|
* Commands are builtins that can be invoked from the language and have a
|
||||||
|
* native implementation registered from C++. Once registered, a command
|
||||||
|
* cannot be unregistered or otherwise changed.
|
||||||
|
*/
|
||||||
struct LIBCUBESCRIPT_EXPORT command: ident {
|
struct LIBCUBESCRIPT_EXPORT command: ident {
|
||||||
|
/** @brief Get the argument list. */
|
||||||
std::string_view get_args() const;
|
std::string_view get_args() const;
|
||||||
|
|
||||||
|
/** @brief Get the number of arguments the command expects.
|
||||||
|
*
|
||||||
|
* Only non-variadic arguments count here (i.e. no repeated arguments,
|
||||||
|
* no `C`, no `V`; everything else counts as one argument).
|
||||||
|
*/
|
||||||
int get_num_args() const;
|
int get_num_args() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -19,10 +19,8 @@
|
||||||
# include "cubescript_conf_user.hh"
|
# include "cubescript_conf_user.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __has_include(<span>)
|
#if !defined(LIBCUBESCRIPT_CONF_USER_SPAN)
|
||||||
# include <span>
|
# include <span>
|
||||||
#elif !defined(LIBCUBESCRIPT_CONF_USER_SPAN)
|
|
||||||
# error "This implementation does not provide an std::span<T>."
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
|
@ -351,6 +351,7 @@ LIBCUBESCRIPT_EXPORT void global_var::save(state &cs) {
|
||||||
}
|
}
|
||||||
if (!(p_impl->p_flags & IDENT_FLAG_OVERRIDDEN)) {
|
if (!(p_impl->p_flags & IDENT_FLAG_OVERRIDDEN)) {
|
||||||
static_cast<var_impl *>(p_impl)->save_val();
|
static_cast<var_impl *>(p_impl)->save_val();
|
||||||
|
p_impl->p_flags |= IDENT_FLAG_OVERRIDDEN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p_impl->p_flags &= IDENT_FLAG_OVERRIDDEN;
|
p_impl->p_flags &= IDENT_FLAG_OVERRIDDEN;
|
||||||
|
|
Loading…
Reference in New Issue