From a8cfa08bd8d7281e4450fccb4c218afd7cbbe80d Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Mon, 5 Apr 2021 04:40:52 +0200 Subject: [PATCH] split up cubescript.hh into individual files --- include/cubescript/cubescript.hh | 689 +--------------------- include/cubescript/cubescript/error.hh | 108 ++++ include/cubescript/cubescript/ident.hh | 132 +++++ include/cubescript/cubescript/platform.hh | 29 + include/cubescript/cubescript/state.hh | 156 +++++ include/cubescript/cubescript/util.hh | 174 ++++++ include/cubescript/cubescript/value.hh | 143 +++++ 7 files changed, 748 insertions(+), 683 deletions(-) create mode 100644 include/cubescript/cubescript/error.hh create mode 100644 include/cubescript/cubescript/ident.hh create mode 100644 include/cubescript/cubescript/platform.hh create mode 100644 include/cubescript/cubescript/state.hh create mode 100644 include/cubescript/cubescript/util.hh create mode 100644 include/cubescript/cubescript/value.hh diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index 4794469..dfabf53 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -1,691 +1,14 @@ #ifndef LIBCUBESCRIPT_CUBESCRIPT_HH #define LIBCUBESCRIPT_CUBESCRIPT_HH -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "cubescript_conf.hh" +#include "cubescript/platform.hh" #include "cubescript/callable.hh" - -#if defined(__CYGWIN__) || (defined(_WIN32) && !defined(_XBOX_VER)) -# ifdef LIBCUBESCRIPT_DLL -# ifdef LIBCUBESCRIPT_BUILD -# define LIBCUBESCRIPT_EXPORT __declspec(dllexport) -# else -# define LIBCUBESCRIPT_EXPORT __declspec(dllimport) -# endif -# else -# define LIBCUBESCRIPT_EXPORT -# endif -# define LIBCUBESCRIPT_LOCAL -#else -# if defined(__GNUC__) && (__GNUC__ >= 4) -# define LIBCUBESCRIPT_EXPORT __attribute__((visibility("default"))) -# define LIBCUBESCRIPT_LOCAL __attribute__((visibility("hidden"))) -# else -# define LIBCUBESCRIPT_EXPORT -# define LIBCUBESCRIPT_LOCAL -# endif -#endif - -namespace cubescript { - -struct internal_error: std::runtime_error { - using std::runtime_error::runtime_error; -}; - -using alloc_func = void *(*)(void *, void *, size_t, size_t); - -using hook_func = callable; -using command_func = callable< - void, struct state &, std::span, struct any_value & ->; - -struct internal_state; - -struct LIBCUBESCRIPT_EXPORT bcode_ref { - bcode_ref(): - p_code(nullptr) - {} - bcode_ref(struct bcode *v); - bcode_ref(bcode_ref const &v); - bcode_ref(bcode_ref &&v): - p_code(v.p_code) - { - v.p_code = nullptr; - } - - ~bcode_ref(); - - bcode_ref &operator=(bcode_ref const &v); - bcode_ref &operator=(bcode_ref &&v); - - bool empty() const; - - operator bool() const; - operator struct bcode *() const; - -private: - struct bcode *p_code; -}; - -struct LIBCUBESCRIPT_EXPORT string_ref { - friend struct any_value; - friend struct string_pool; - - string_ref() = delete; - string_ref(internal_state *cs, std::string_view str); - string_ref(state &cs, std::string_view str); - - string_ref(string_ref const &ref); - - ~string_ref(); - - string_ref &operator=(string_ref const &ref); - - operator std::string_view() const; - - std::size_t size() const { - return std::string_view{*this}.size(); - } - std::size_t length() const { - return std::string_view{*this}.length(); - } - - char const *data() const { - return std::string_view{*this}.data(); - } - - bool operator==(string_ref const &s) const; - -private: - /* for internal use only */ - string_ref(char const *p, internal_state *cs); - - internal_state *p_state; - char const *p_str; -}; - -enum class value_type { - NONE = 0, INT, FLOAT, STRING, CODE, IDENT -}; - -struct ident; - -struct LIBCUBESCRIPT_EXPORT any_value { - any_value() = delete; - ~any_value(); - - any_value(state &); - any_value(internal_state &); - - any_value(any_value const &); - any_value(any_value &&v); - - any_value &operator=(any_value const &); - any_value &operator=(any_value &&); - - value_type get_type() const; - - void set_int(integer_type val); - void set_float(float_type val); - void set_str(std::string_view val); - void set_str(string_ref const &val); - void set_none(); - void set_code(bcode_ref const &val); - void set_ident(ident *val); - - string_ref get_str() const; - integer_type get_int() const; - float_type get_float() const; - bcode_ref get_code() const; - ident *get_ident() const; - void get_val(any_value &r) const; - - bool get_bool() const; - - void force_none(); - float_type force_float(); - integer_type force_int(); - std::string_view force_str(); - bcode_ref force_code(state &cs); - ident *force_ident(state &cs); - -private: - template - struct stor_t { - internal_state *state; - T val; - }; - - internal_state *get_state() const { - return std::launder( - reinterpret_cast const *>(&p_stor) - )->state; - } - - std::aligned_union_t<1, - stor_t, - stor_t, - stor_t, - string_ref - > p_stor; - value_type p_type; -}; - -struct error; -struct codegen_state; - -enum class ident_type { - IVAR = 0, FVAR, SVAR, COMMAND, ALIAS, SPECIAL -}; - -struct global_var; -struct integer_var; -struct float_var; -struct string_var; -struct alias; -struct command; - -struct LIBCUBESCRIPT_EXPORT ident { - int get_raw_type() const; - ident_type get_type() const; - std::string_view get_name() const; - int get_index() const; - - bool is_alias() const; - alias *get_alias(); - alias const *get_alias() const; - - bool is_command() const; - command *get_command(); - command const *get_command() const; - - bool is_special() const; - - bool is_var() const; - global_var *get_var(); - global_var const *get_var() const; - - bool is_ivar() const; - integer_var *get_ivar(); - integer_var const *get_ivar() const; - - bool is_fvar() const; - float_var *get_fvar(); - float_var const *get_fvar() const; - - bool is_svar() const; - string_var *get_svar(); - string_var const *get_svar() const; - - bool is_overridden(state &cs) const; - bool is_persistent(state &cs) const; - -protected: - ident() = default; - - friend struct internal_state; - - struct ident_impl *p_impl{}; -}; - -enum class var_type { - DEFAULT = 0, - PERSISTENT, - OVERRIDABLE -}; - -struct LIBCUBESCRIPT_EXPORT global_var: ident { - bool is_read_only() const; - bool is_overridable() const; - - var_type get_variable_type() const; - - void save(state &cs); - -protected: - global_var() = default; -}; - -struct LIBCUBESCRIPT_EXPORT integer_var: global_var { - integer_type get_value() const; - void set_value( - state &cs, integer_type val, bool do_write = true, bool trigger = true - ); - void set_raw_value(integer_type val); - -protected: - integer_var() = default; -}; - -struct LIBCUBESCRIPT_EXPORT float_var: global_var { - float_type get_value() const; - void set_value( - state &cs, float_type val, bool do_write = true, bool trigger = true - ); - void set_raw_value(float_type val); - -protected: - float_var() = default; -}; - -struct LIBCUBESCRIPT_EXPORT string_var: global_var { - string_ref get_value() const; - void set_value( - state &cs, string_ref val, bool do_write = true, bool trigger = true - ); - void set_raw_value(string_ref val); - -protected: - string_var() = default; -}; - -struct LIBCUBESCRIPT_EXPORT alias: ident { - bool is_arg() const; - -protected: - alias() = default; -}; - -struct LIBCUBESCRIPT_EXPORT command: ident { - std::string_view get_args() const; - int get_num_args() const; - -protected: - command() = default; -}; - -enum { - LIB_MATH = 1 << 0, - LIB_STRING = 1 << 1, - LIB_LIST = 1 << 2, - LIB_ALL = 0b111 -}; - -enum class loop_state { - NORMAL = 0, BREAK, CONTINUE -}; - -struct LIBCUBESCRIPT_EXPORT state { - state(); - state(alloc_func func, void *data); - virtual ~state(); - - state(state const &) = delete; - state(state &&s) { - swap(s); - } - - state &operator=(state const &) = delete; - state &operator=(state &&s) { - swap(s); - s.destroy(); - return *this; - } - - void destroy(); - - void swap(state &s) { - std::swap(p_tstate, s.p_tstate); - } - - state new_thread(); - - template - hook_func set_call_hook(F &&f) { - return set_call_hook( - hook_func{std::forward(f), callable_alloc, this} - ); - } - hook_func const &get_call_hook() const; - hook_func &get_call_hook(); - - void init_libs(int libs = LIB_ALL); - - void clear_override(ident &id); - void clear_overrides(); - - integer_var *new_ivar( - std::string_view n, integer_type v, bool read_only = false, - var_type vtp = var_type::DEFAULT - ); - float_var *new_fvar( - std::string_view n, float_type v, bool read_only = false, - var_type vtp = var_type::DEFAULT - ); - string_var *new_svar( - std::string_view n, std::string_view v, bool read_only = false, - var_type vtp = var_type::DEFAULT - ); - ident *new_ident(std::string_view n); - - void reset_var(std::string_view name); - void touch_var(std::string_view name); - - template - command *new_command( - std::string_view name, std::string_view args, F &&f - ) { - return new_command( - name, args, - command_func{std::forward(f), callable_alloc, this} - ); - } - - ident *get_ident(std::string_view name); - alias *get_alias(std::string_view name); - bool have_ident(std::string_view name); - - std::span get_idents(); - std::span get_idents() const; - - void run(bcode_ref const &code, any_value &ret); - void run(std::string_view code, any_value &ret); - void run(std::string_view code, any_value &ret, std::string_view source); - void run(ident *id, std::span args, any_value &ret); - - any_value run(bcode_ref const &code); - any_value run(std::string_view code); - any_value run(std::string_view code, std::string_view source); - any_value run(ident *id, std::span args); - - loop_state run_loop(bcode_ref const &code, any_value &ret); - loop_state run_loop(bcode_ref const &code); - - bool get_override_mode() const; - bool set_override_mode(bool v); - - bool get_persist_mode() const; - bool set_persist_mode(bool v); - - std::size_t get_max_run_depth() const; - std::size_t set_max_run_depth(std::size_t v); - - void set_alias(std::string_view name, any_value v); - - std::optional get_alias_val(std::string_view name); - -private: - friend struct state_p; - - hook_func set_call_hook(hook_func func); - - command *new_command( - std::string_view name, std::string_view args, command_func func - ); - - static void *callable_alloc( - void *data, void *p, std::size_t os, std::size_t ns - ) { - return static_cast(data)->alloc(p, os, ns); - } - - LIBCUBESCRIPT_LOCAL state(internal_state *s); - - void *alloc(void *ptr, size_t olds, size_t news); - - struct thread_state *p_tstate = nullptr; -}; - -struct LIBCUBESCRIPT_EXPORT stack_state { - struct node { - node const *next; - ident const *id; - int index; - }; - - stack_state() = delete; - stack_state(state &cs, node *nd = nullptr, bool gap = false); - stack_state(stack_state const &) = delete; - stack_state(stack_state &&st); - ~stack_state(); - - stack_state &operator=(stack_state const &) = delete; - stack_state &operator=(stack_state &&); - - node const *get() const; - bool gap() const; - -private: - state &p_state; - node *p_node; - bool p_gap; -}; - -struct LIBCUBESCRIPT_EXPORT error { - friend struct state; - - error() = delete; - error(error const &) = delete; - error(error &&v): - p_errbeg{v.p_errbeg}, p_errend{v.p_errend}, - p_stack{std::move(v.p_stack)} - {} - - std::string_view what() const { - return std::string_view{p_errbeg, p_errend}; - } - - stack_state &get_stack() { - return p_stack; - } - - stack_state const &get_stack() const { - return p_stack; - } - - 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); - } - - template - 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 internal_error{"format error"}; - } 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: - stack_state save_stack(state &cs); - char *request_buf(state &cs, std::size_t bufs, char *&sp); - - char const *p_errbeg, *p_errend; - stack_state p_stack; -}; - -struct LIBCUBESCRIPT_EXPORT alias_local { - alias_local(state &cs, ident *a); - ~alias_local(); - - alias_local(alias_local const &) = delete; - alias_local(alias_local &&) = delete; - - alias_local &operator=(alias_local const &) = delete; - alias_local &operator=(alias_local &&v) = delete; - - alias *get_alias() noexcept { return p_alias; } - alias const *get_alias() const noexcept { return p_alias; } - - bool set(any_value val); - - explicit operator bool() const noexcept; - -private: - alias *p_alias; - void *p_sp; -}; - -struct LIBCUBESCRIPT_EXPORT list_parser { - list_parser(state &cs, std::string_view s = std::string_view{}): - p_state{&cs}, p_input_beg{s.data()}, p_input_end{s.data() + s.size()} - {} - - void set_input(std::string_view s) { - p_input_beg = s.data(); - p_input_end = s.data() + s.size(); - } - - std::string_view get_input() const { - return std::string_view{p_input_beg, p_input_end}; - } - - bool parse(); - std::size_t count(); - - string_ref get_item() const; - - std::string_view get_raw_item() const { - return std::string_view{p_ibeg, p_iend}; - } - std::string_view get_quoted_item() const { - return std::string_view{p_qbeg, p_qend}; - } - - void skip_until_item(); - -private: - state *p_state; - char const *p_input_beg, *p_input_end; - - char const *p_ibeg{}, *p_iend{}; - char const *p_qbeg{}, *p_qend{}; -}; - - -LIBCUBESCRIPT_EXPORT char const *parse_string( - state &cs, std::string_view str, size_t &nlines -); - -inline char const *parse_string( - state &cs, std::string_view str -) { - size_t nlines; - return parse_string(cs, str, nlines); -} - -LIBCUBESCRIPT_EXPORT char const *parse_word( - state &cs, std::string_view str -); - -LIBCUBESCRIPT_EXPORT string_ref concat_values( - state &cs, std::span vals, - std::string_view sep = std::string_view{} -); - -template -inline R escape_string(R writer, std::string_view str) { - *writer++ = '"'; - for (auto c: str) { - switch (c) { - case '\n': *writer++ = '^'; *writer++ = 'n'; break; - case '\t': *writer++ = '^'; *writer++ = 't'; break; - case '\f': *writer++ = '^'; *writer++ = 'f'; break; - case '"': *writer++ = '^'; *writer++ = '"'; break; - case '^': *writer++ = '^'; *writer++ = '^'; break; - default: *writer++ = c; break; - } - } - *writer++ = '"'; - return writer; -} - -template -inline R unescape_string(R writer, std::string_view str) { - for (auto it = str.begin(); it != str.end(); ++it) { - if (*it == '^') { - ++it; - if (it == str.end()) { - break; - } - switch (*it) { - case 'n': *writer++ = '\n'; break; - case 't': *writer++ = '\r'; break; - case 'f': *writer++ = '\f'; break; - case '"': *writer++ = '"'; break; - case '^': *writer++ = '^'; break; - default: *writer++ = *it; break; - } - } else if (*it == '\\') { - ++it; - if (it == str.end()) { - break; - } - char c = *it; - if ((c == '\r') || (c == '\n')) { - if ((c == '\r') && ((it + 1) != str.end())) { - if (it[1] == '\n') { - ++it; - } - } - continue; - } - *writer++ = '\\'; - } else { - *writer++ = *it; - } - } - return writer; -} - -template -inline R print_stack(R writer, stack_state const &st) { - char buf[32] = {0}; - auto nd = st.get(); - while (nd) { - auto name = nd->id->get_name(); - *writer++ = ' '; - *writer++ = ' '; - if ((nd->index == 1) && st.gap()) { - *writer++ = '.'; - *writer++ = '.'; - } - snprintf(buf, sizeof(buf), "%d", nd->index); - char const *p = buf; - std::copy(p, p + strlen(p), writer); - *writer++ = ')'; - std::copy(name.begin(), name.end(), writer); - nd = nd->next; - if (nd) { - *writer++ = '\n'; - } - } - return writer; -} - -} /* namespace cubescript */ +#include "cubescript/error.hh" +#include "cubescript/value.hh" +#include "cubescript/ident.hh" +#include "cubescript/state.hh" +#include "cubescript/util.hh" #endif /* LIBCUBESCRIPT_CUBESCRIPT_HH */ diff --git a/include/cubescript/cubescript/error.hh b/include/cubescript/cubescript/error.hh new file mode 100644 index 0000000..a234eb1 --- /dev/null +++ b/include/cubescript/cubescript/error.hh @@ -0,0 +1,108 @@ +#ifndef LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH +#define LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH + +#include +#include +#include +#include +#include + +namespace cubescript { + +struct state; + +struct internal_error: std::runtime_error { + using std::runtime_error::runtime_error; +}; + +struct LIBCUBESCRIPT_EXPORT stack_state { + struct node { + node const *next; + struct ident const *id; + int index; + }; + + stack_state() = delete; + stack_state(state &cs, node *nd = nullptr, bool gap = false); + stack_state(stack_state const &) = delete; + stack_state(stack_state &&st); + ~stack_state(); + + stack_state &operator=(stack_state const &) = delete; + stack_state &operator=(stack_state &&); + + node const *get() const; + bool gap() const; + +private: + state &p_state; + node *p_node; + bool p_gap; +}; + +struct LIBCUBESCRIPT_EXPORT error { + friend struct state; + + error() = delete; + error(error const &) = delete; + error(error &&v): + p_errbeg{v.p_errbeg}, p_errend{v.p_errend}, + p_stack{std::move(v.p_stack)} + {} + + std::string_view what() const { + return std::string_view{p_errbeg, p_errend}; + } + + stack_state &get_stack() { + return p_stack; + } + + stack_state const &get_stack() const { + return p_stack; + } + + 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); + } + + template + 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 internal_error{"format error"}; + } 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: + stack_state save_stack(state &cs); + char *request_buf(state &cs, std::size_t bufs, char *&sp); + + char const *p_errbeg, *p_errend; + stack_state p_stack; +}; + +} /* namespace cubescript */ + +#endif /* LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH */ diff --git a/include/cubescript/cubescript/ident.hh b/include/cubescript/cubescript/ident.hh new file mode 100644 index 0000000..7a28b8e --- /dev/null +++ b/include/cubescript/cubescript/ident.hh @@ -0,0 +1,132 @@ +#ifndef LIBCUBESCRIPT_CUBESCRIPT_IDENT_HH +#define LIBCUBESCRIPT_CUBESCRIPT_IDENT_HH + +#include + +#include "value.hh" + +namespace cubescript { + +enum class ident_type { + IVAR = 0, FVAR, SVAR, COMMAND, ALIAS, SPECIAL +}; + +struct global_var; +struct integer_var; +struct float_var; +struct string_var; +struct alias; +struct command; + +struct LIBCUBESCRIPT_EXPORT ident { + int get_raw_type() const; + ident_type get_type() const; + std::string_view get_name() const; + int get_index() const; + + bool is_alias() const; + alias *get_alias(); + alias const *get_alias() const; + + bool is_command() const; + command *get_command(); + command const *get_command() const; + + bool is_special() const; + + bool is_var() const; + global_var *get_var(); + global_var const *get_var() const; + + bool is_ivar() const; + integer_var *get_ivar(); + integer_var const *get_ivar() const; + + bool is_fvar() const; + float_var *get_fvar(); + float_var const *get_fvar() const; + + bool is_svar() const; + string_var *get_svar(); + string_var const *get_svar() const; + + bool is_overridden(state &cs) const; + bool is_persistent(state &cs) const; + +protected: + ident() = default; + + friend struct internal_state; + + struct ident_impl *p_impl{}; +}; + +enum class var_type { + DEFAULT = 0, + PERSISTENT, + OVERRIDABLE +}; + +struct LIBCUBESCRIPT_EXPORT global_var: ident { + bool is_read_only() const; + bool is_overridable() const; + + var_type get_variable_type() const; + + void save(state &cs); + +protected: + global_var() = default; +}; + +struct LIBCUBESCRIPT_EXPORT integer_var: global_var { + integer_type get_value() const; + void set_value( + state &cs, integer_type val, bool do_write = true, bool trigger = true + ); + void set_raw_value(integer_type val); + +protected: + integer_var() = default; +}; + +struct LIBCUBESCRIPT_EXPORT float_var: global_var { + float_type get_value() const; + void set_value( + state &cs, float_type val, bool do_write = true, bool trigger = true + ); + void set_raw_value(float_type val); + +protected: + float_var() = default; +}; + +struct LIBCUBESCRIPT_EXPORT string_var: global_var { + string_ref get_value() const; + void set_value( + state &cs, string_ref val, bool do_write = true, bool trigger = true + ); + void set_raw_value(string_ref val); + +protected: + string_var() = default; +}; + +struct LIBCUBESCRIPT_EXPORT alias: ident { + bool is_arg() const; + +protected: + alias() = default; +}; + +struct LIBCUBESCRIPT_EXPORT command: ident { + std::string_view get_args() const; + int get_num_args() const; + +protected: + command() = default; +}; + +} /* namespace cubescript */ + +#endif /* LIBCUBESCRIPT_CUBESCRIPT_IDENT_HH */ diff --git a/include/cubescript/cubescript/platform.hh b/include/cubescript/cubescript/platform.hh new file mode 100644 index 0000000..5429072 --- /dev/null +++ b/include/cubescript/cubescript/platform.hh @@ -0,0 +1,29 @@ +#ifndef LIBCUBESCRIPT_CUBESCRIPT_PLATFORM_HH +#define LIBCUBESCRIPT_CUBESCRIPT_PLATFORM_HH + +namespace cubescript { + +#if defined(__CYGWIN__) || (defined(_WIN32) && !defined(_XBOX_VER)) +# ifdef LIBCUBESCRIPT_DLL +# ifdef LIBCUBESCRIPT_BUILD +# define LIBCUBESCRIPT_EXPORT __declspec(dllexport) +# else +# define LIBCUBESCRIPT_EXPORT __declspec(dllimport) +# endif +# else +# define LIBCUBESCRIPT_EXPORT +# endif +# define LIBCUBESCRIPT_LOCAL +#else +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define LIBCUBESCRIPT_EXPORT __attribute__((visibility("default"))) +# define LIBCUBESCRIPT_LOCAL __attribute__((visibility("hidden"))) +# else +# define LIBCUBESCRIPT_EXPORT +# define LIBCUBESCRIPT_LOCAL +# endif +#endif + +} /* namespace cubescript */ + +#endif /* LIBCUBESCRIPT_CUBESCRIPT_PLATFORM_HH */ diff --git a/include/cubescript/cubescript/state.hh b/include/cubescript/cubescript/state.hh new file mode 100644 index 0000000..d5295c2 --- /dev/null +++ b/include/cubescript/cubescript/state.hh @@ -0,0 +1,156 @@ +#ifndef LIBCUBESCRIPT_CUBESCRIPT_STATE_HH +#define LIBCUBESCRIPT_CUBESCRIPT_STATE_HH + +#include +#include +#include +#include +#include + +#include "callable.hh" +#include "ident.hh" + +namespace cubescript { + +using alloc_func = void *(*)(void *, void *, size_t, size_t); + +using hook_func = callable; +using command_func = callable< + void, struct state &, std::span, struct any_value & +>; + +enum { + LIB_MATH = 1 << 0, + LIB_STRING = 1 << 1, + LIB_LIST = 1 << 2, + LIB_ALL = 0b111 +}; + +enum class loop_state { + NORMAL = 0, BREAK, CONTINUE +}; + +struct LIBCUBESCRIPT_EXPORT state { + state(); + state(alloc_func func, void *data); + virtual ~state(); + + state(state const &) = delete; + state(state &&s) { + swap(s); + } + + state &operator=(state const &) = delete; + state &operator=(state &&s) { + swap(s); + s.destroy(); + return *this; + } + + void destroy(); + + void swap(state &s) { + std::swap(p_tstate, s.p_tstate); + } + + state new_thread(); + + template + hook_func set_call_hook(F &&f) { + return set_call_hook( + hook_func{std::forward(f), callable_alloc, this} + ); + } + hook_func const &get_call_hook() const; + hook_func &get_call_hook(); + + void init_libs(int libs = LIB_ALL); + + void clear_override(ident &id); + void clear_overrides(); + + integer_var *new_ivar( + std::string_view n, integer_type v, bool read_only = false, + var_type vtp = var_type::DEFAULT + ); + float_var *new_fvar( + std::string_view n, float_type v, bool read_only = false, + var_type vtp = var_type::DEFAULT + ); + string_var *new_svar( + std::string_view n, std::string_view v, bool read_only = false, + var_type vtp = var_type::DEFAULT + ); + ident *new_ident(std::string_view n); + + void reset_var(std::string_view name); + void touch_var(std::string_view name); + + template + command *new_command( + std::string_view name, std::string_view args, F &&f + ) { + return new_command( + name, args, + command_func{std::forward(f), callable_alloc, this} + ); + } + + ident *get_ident(std::string_view name); + alias *get_alias(std::string_view name); + bool have_ident(std::string_view name); + + std::span get_idents(); + std::span get_idents() const; + + void run(bcode_ref const &code, any_value &ret); + void run(std::string_view code, any_value &ret); + void run(std::string_view code, any_value &ret, std::string_view source); + void run(ident *id, std::span args, any_value &ret); + + any_value run(bcode_ref const &code); + any_value run(std::string_view code); + any_value run(std::string_view code, std::string_view source); + any_value run(ident *id, std::span args); + + loop_state run_loop(bcode_ref const &code, any_value &ret); + loop_state run_loop(bcode_ref const &code); + + bool get_override_mode() const; + bool set_override_mode(bool v); + + bool get_persist_mode() const; + bool set_persist_mode(bool v); + + std::size_t get_max_run_depth() const; + std::size_t set_max_run_depth(std::size_t v); + + void set_alias(std::string_view name, any_value v); + + std::optional get_alias_val(std::string_view name); + +private: + friend struct state_p; + + hook_func set_call_hook(hook_func func); + + command *new_command( + std::string_view name, std::string_view args, command_func func + ); + + static void *callable_alloc( + void *data, void *p, std::size_t os, std::size_t ns + ) { + return static_cast(data)->alloc(p, os, ns); + } + + LIBCUBESCRIPT_LOCAL state(internal_state *s); + + void *alloc(void *ptr, size_t olds, size_t news); + + struct thread_state *p_tstate = nullptr; +}; + +} /* namespace cubescript */ + +#endif /* LIBCUBESCRIPT_CUBESCRIPT_STATE_HH */ diff --git a/include/cubescript/cubescript/util.hh b/include/cubescript/cubescript/util.hh new file mode 100644 index 0000000..def0e75 --- /dev/null +++ b/include/cubescript/cubescript/util.hh @@ -0,0 +1,174 @@ +#ifndef LIBCUBESCRIPT_CUBESCRIPT_UTIL_HH +#define LIBCUBESCRIPT_CUBESCRIPT_UTIL_HH + +#include +#include +#include +#include + +#include "ident.hh" + +namespace cubescript { + +struct LIBCUBESCRIPT_EXPORT alias_local { + alias_local(state &cs, ident *a); + ~alias_local(); + + alias_local(alias_local const &) = delete; + alias_local(alias_local &&) = delete; + + alias_local &operator=(alias_local const &) = delete; + alias_local &operator=(alias_local &&v) = delete; + + alias *get_alias() noexcept { return p_alias; } + alias const *get_alias() const noexcept { return p_alias; } + + bool set(any_value val); + + explicit operator bool() const noexcept; + +private: + alias *p_alias; + void *p_sp; +}; + +struct LIBCUBESCRIPT_EXPORT list_parser { + list_parser(state &cs, std::string_view s = std::string_view{}): + p_state{&cs}, p_input_beg{s.data()}, p_input_end{s.data() + s.size()} + {} + + void set_input(std::string_view s) { + p_input_beg = s.data(); + p_input_end = s.data() + s.size(); + } + + std::string_view get_input() const { + return std::string_view{p_input_beg, p_input_end}; + } + + bool parse(); + std::size_t count(); + + string_ref get_item() const; + + std::string_view get_raw_item() const { + return std::string_view{p_ibeg, p_iend}; + } + std::string_view get_quoted_item() const { + return std::string_view{p_qbeg, p_qend}; + } + + void skip_until_item(); + +private: + state *p_state; + char const *p_input_beg, *p_input_end; + + char const *p_ibeg{}, *p_iend{}; + char const *p_qbeg{}, *p_qend{}; +}; + + +LIBCUBESCRIPT_EXPORT char const *parse_string( + state &cs, std::string_view str, size_t &nlines +); + +inline char const *parse_string( + state &cs, std::string_view str +) { + size_t nlines; + return parse_string(cs, str, nlines); +} + +LIBCUBESCRIPT_EXPORT char const *parse_word( + state &cs, std::string_view str +); + +LIBCUBESCRIPT_EXPORT string_ref concat_values( + state &cs, std::span vals, + std::string_view sep = std::string_view{} +); + +template +inline R escape_string(R writer, std::string_view str) { + *writer++ = '"'; + for (auto c: str) { + switch (c) { + case '\n': *writer++ = '^'; *writer++ = 'n'; break; + case '\t': *writer++ = '^'; *writer++ = 't'; break; + case '\f': *writer++ = '^'; *writer++ = 'f'; break; + case '"': *writer++ = '^'; *writer++ = '"'; break; + case '^': *writer++ = '^'; *writer++ = '^'; break; + default: *writer++ = c; break; + } + } + *writer++ = '"'; + return writer; +} + +template +inline R unescape_string(R writer, std::string_view str) { + for (auto it = str.begin(); it != str.end(); ++it) { + if (*it == '^') { + ++it; + if (it == str.end()) { + break; + } + switch (*it) { + case 'n': *writer++ = '\n'; break; + case 't': *writer++ = '\r'; break; + case 'f': *writer++ = '\f'; break; + case '"': *writer++ = '"'; break; + case '^': *writer++ = '^'; break; + default: *writer++ = *it; break; + } + } else if (*it == '\\') { + ++it; + if (it == str.end()) { + break; + } + char c = *it; + if ((c == '\r') || (c == '\n')) { + if ((c == '\r') && ((it + 1) != str.end())) { + if (it[1] == '\n') { + ++it; + } + } + continue; + } + *writer++ = '\\'; + } else { + *writer++ = *it; + } + } + return writer; +} + +template +inline R print_stack(R writer, stack_state const &st) { + char buf[32] = {0}; + auto nd = st.get(); + while (nd) { + auto name = nd->id->get_name(); + *writer++ = ' '; + *writer++ = ' '; + if ((nd->index == 1) && st.gap()) { + *writer++ = '.'; + *writer++ = '.'; + } + snprintf(buf, sizeof(buf), "%d", nd->index); + char const *p = buf; + std::copy(p, p + strlen(p), writer); + *writer++ = ')'; + std::copy(name.begin(), name.end(), writer); + nd = nd->next; + if (nd) { + *writer++ = '\n'; + } + } + return writer; +} + +} /* namespace cubescript */ + +#endif /* LIBCUBESCRIPT_CUBESCRIPT_UTIL_HH */ diff --git a/include/cubescript/cubescript/value.hh b/include/cubescript/cubescript/value.hh new file mode 100644 index 0000000..3aed162 --- /dev/null +++ b/include/cubescript/cubescript/value.hh @@ -0,0 +1,143 @@ +#ifndef LIBCUBESCRIPT_CUBESCRIPT_VALUE_HH +#define LIBCUBESCRIPT_CUBESCRIPT_VALUE_HH + +#include +#include +#include + +namespace cubescript { + +struct internal_state; +struct ident; + +struct LIBCUBESCRIPT_EXPORT bcode_ref { + bcode_ref(): + p_code(nullptr) + {} + bcode_ref(struct bcode *v); + bcode_ref(bcode_ref const &v); + bcode_ref(bcode_ref &&v): + p_code(v.p_code) + { + v.p_code = nullptr; + } + + ~bcode_ref(); + + bcode_ref &operator=(bcode_ref const &v); + bcode_ref &operator=(bcode_ref &&v); + + bool empty() const; + + operator bool() const; + operator struct bcode *() const; + +private: + struct bcode *p_code; +}; + +struct LIBCUBESCRIPT_EXPORT string_ref { + friend struct any_value; + friend struct string_pool; + + string_ref() = delete; + string_ref(internal_state *cs, std::string_view str); + string_ref(state &cs, std::string_view str); + + string_ref(string_ref const &ref); + + ~string_ref(); + + string_ref &operator=(string_ref const &ref); + + operator std::string_view() const; + + std::size_t size() const { + return std::string_view{*this}.size(); + } + std::size_t length() const { + return std::string_view{*this}.length(); + } + + char const *data() const { + return std::string_view{*this}.data(); + } + + bool operator==(string_ref const &s) const; + +private: + /* for internal use only */ + string_ref(char const *p, internal_state *cs); + + internal_state *p_state; + char const *p_str; +}; + +enum class value_type { + NONE = 0, INT, FLOAT, STRING, CODE, IDENT +}; + +struct LIBCUBESCRIPT_EXPORT any_value { + any_value() = delete; + ~any_value(); + + any_value(state &); + any_value(internal_state &); + + any_value(any_value const &); + any_value(any_value &&v); + + any_value &operator=(any_value const &); + any_value &operator=(any_value &&); + + value_type get_type() const; + + void set_int(integer_type val); + void set_float(float_type val); + void set_str(std::string_view val); + void set_str(string_ref const &val); + void set_none(); + void set_code(bcode_ref const &val); + void set_ident(ident *val); + + string_ref get_str() const; + integer_type get_int() const; + float_type get_float() const; + bcode_ref get_code() const; + ident *get_ident() const; + void get_val(any_value &r) const; + + bool get_bool() const; + + void force_none(); + float_type force_float(); + integer_type force_int(); + std::string_view force_str(); + bcode_ref force_code(state &cs); + ident *force_ident(state &cs); + +private: + template + struct stor_t { + internal_state *state; + T val; + }; + + internal_state *get_state() const { + return std::launder( + reinterpret_cast const *>(&p_stor) + )->state; + } + + std::aligned_union_t<1, + stor_t, + stor_t, + stor_t, + string_ref + > p_stor; + value_type p_type; +}; + +} /* namespace cubescript */ + +#endif /* LIBCUBESCRIPT_CUBESCRIPT_VALUE_HH */