2016-08-14 18:35:38 +02:00
|
|
|
#ifndef LIBCUBESCRIPT_CUBESCRIPT_HH
|
|
|
|
#define LIBCUBESCRIPT_CUBESCRIPT_HH
|
2015-09-10 19:53:43 +02:00
|
|
|
|
2021-03-20 07:24:25 +01:00
|
|
|
#include <cstring>
|
2021-03-22 00:58:35 +01:00
|
|
|
#include <cstddef>
|
2017-04-23 15:34:45 +02:00
|
|
|
#include <vector>
|
2017-01-30 19:38:11 +01:00
|
|
|
#include <optional>
|
2017-02-08 01:07:35 +01:00
|
|
|
#include <functional>
|
2017-02-09 20:59:14 +01:00
|
|
|
#include <type_traits>
|
2021-03-20 06:18:31 +01:00
|
|
|
#include <algorithm>
|
2021-03-22 00:58:35 +01:00
|
|
|
#include <memory>
|
2017-02-16 20:51:03 +01:00
|
|
|
#include <utility>
|
2021-03-22 00:58:35 +01:00
|
|
|
#include <span>
|
2021-03-24 02:42:33 +01:00
|
|
|
#include <new>
|
2017-01-30 19:38:11 +01:00
|
|
|
|
2016-08-14 18:35:38 +02:00
|
|
|
#include "cubescript_conf.hh"
|
|
|
|
|
2021-03-20 07:24:25 +01:00
|
|
|
#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
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2021-03-23 23:32:25 +01:00
|
|
|
namespace cubescript {
|
2015-08-08 17:13:46 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
static_assert(std::is_integral_v<integer_type>, "integer_type must be integral");
|
|
|
|
static_assert(std::is_signed_v<integer_type>, "integer_type must be signed");
|
|
|
|
static_assert(std::is_floating_point_v<float_type>, "float_type must be floating point");
|
2016-11-12 19:15:28 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct internal_error: std::runtime_error {
|
2017-02-12 22:52:43 +01:00
|
|
|
using std::runtime_error::runtime_error;
|
|
|
|
};
|
|
|
|
|
2021-03-22 00:58:35 +01:00
|
|
|
template<typename R, typename ...A>
|
2021-03-23 23:29:32 +01:00
|
|
|
struct callable {
|
2021-03-22 00:58:35 +01:00
|
|
|
private:
|
|
|
|
struct base {
|
|
|
|
base(base const &);
|
|
|
|
base &operator=(base const &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
base() {}
|
|
|
|
virtual ~base() {}
|
|
|
|
virtual void move_to(base *) = 0;
|
|
|
|
virtual R operator()(A &&...args) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename F>
|
|
|
|
struct store: base {
|
|
|
|
explicit store(F &&f): p_stor{std::move(f)} {}
|
|
|
|
|
|
|
|
virtual void move_to(base *p) {
|
|
|
|
::new (p) store{std::move(p_stor)};
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual R operator()(A &&...args) {
|
2021-03-24 02:42:33 +01:00
|
|
|
return std::invoke(*std::launder(
|
|
|
|
reinterpret_cast<F *>(&p_stor)
|
|
|
|
), std::forward<A>(args)...);
|
2021-03-22 00:58:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
F p_stor;
|
|
|
|
};
|
|
|
|
|
|
|
|
using alloc_f = void *(*)(void *, void *, std::size_t, std::size_t);
|
|
|
|
|
|
|
|
struct f_alloc {
|
|
|
|
alloc_f af;
|
|
|
|
void *ud;
|
|
|
|
size_t asize;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::aligned_storage_t<sizeof(void *) * 4> p_stor;
|
|
|
|
base *p_func;
|
|
|
|
|
|
|
|
static inline base *as_base(void *p) {
|
|
|
|
return static_cast<base *>(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static inline bool f_not_null(T const &) { return true; }
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static inline bool f_not_null(T *p) { return !!p; }
|
|
|
|
|
|
|
|
template<typename CR, typename C>
|
|
|
|
static inline bool f_not_null(CR C::*p) { return !!p; }
|
|
|
|
|
|
|
|
template<typename T>
|
2021-03-23 23:29:32 +01:00
|
|
|
static inline bool f_not_null(callable<T> const &f) { return !!f; }
|
2021-03-22 00:58:35 +01:00
|
|
|
|
|
|
|
bool small_storage() {
|
|
|
|
return (static_cast<void *>(p_func) == &p_stor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cleanup() {
|
|
|
|
if (!p_func) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p_func->~base();
|
|
|
|
if (!small_storage()) {
|
2021-03-24 02:42:33 +01:00
|
|
|
auto &ad = *std::launder(reinterpret_cast<f_alloc *>(&p_stor));
|
2021-03-22 00:58:35 +01:00
|
|
|
ad.af(ad.ud, p_func, ad.asize, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2021-03-23 23:29:32 +01:00
|
|
|
callable() noexcept: p_func{nullptr} {}
|
|
|
|
callable(std::nullptr_t) noexcept: p_func{nullptr} {}
|
|
|
|
callable(std::nullptr_t, alloc_f, void *) noexcept: p_func{nullptr} {}
|
2021-03-22 00:58:35 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
callable(callable &&f) noexcept {
|
2021-03-22 00:58:35 +01:00
|
|
|
if (!f.p_func) {
|
|
|
|
p_func = nullptr;
|
|
|
|
} else if (f.small_storage()) {
|
|
|
|
p_func = as_base(&p_stor);
|
|
|
|
f.p_func->move_to(p_func);
|
|
|
|
} else {
|
|
|
|
p_func = f.p_func;
|
|
|
|
f.p_func = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
callable(F func, alloc_f af, void *ud) {
|
2021-03-22 00:58:35 +01:00
|
|
|
if (!f_not_null(func)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if constexpr (sizeof(store<F>) <= sizeof(p_stor)) {
|
|
|
|
auto *p = static_cast<void *>(&p_stor);
|
|
|
|
p_func = ::new (p) store<F>{std::move(func)};
|
|
|
|
} else {
|
2021-03-24 02:42:33 +01:00
|
|
|
auto &ad = *std::launder(reinterpret_cast<f_alloc *>(&p_stor));
|
2021-03-22 00:58:35 +01:00
|
|
|
ad.af = af;
|
|
|
|
ad.ud = ud;
|
|
|
|
ad.asize = sizeof(store<F>);
|
|
|
|
p_func = static_cast<store<F> *>(
|
|
|
|
af(ud, nullptr, 0, sizeof(store<F>))
|
|
|
|
);
|
|
|
|
try {
|
|
|
|
new (p_func) store<F>{std::move(func)};
|
|
|
|
} catch (...) {
|
|
|
|
af(ud, p_func, sizeof(store<F>), 0);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
callable &operator=(callable const &) = delete;
|
2021-03-22 00:58:35 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
callable &operator=(callable &&f) noexcept {
|
2021-03-22 00:58:35 +01:00
|
|
|
cleanup();
|
|
|
|
if (f.p_func == nullptr) {
|
|
|
|
p_func = nullptr;
|
|
|
|
} else if (f.small_storage()) {
|
|
|
|
p_func = as_base(&p_stor);
|
|
|
|
f.p_func->move_to(p_func);
|
|
|
|
} else {
|
|
|
|
p_func = f.p_func;
|
|
|
|
f.p_func = nullptr;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
callable &operator=(std::nullptr_t) noexcept {
|
2021-03-22 00:58:35 +01:00
|
|
|
cleanup();
|
|
|
|
p_func = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
callable &operator=(F &&func) {
|
|
|
|
callable{std::forward<F>(func)}.swap(*this);
|
2021-03-22 00:58:35 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
~callable() {
|
2021-03-22 00:58:35 +01:00
|
|
|
cleanup();
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void swap(callable &f) noexcept {
|
2021-03-22 00:58:35 +01:00
|
|
|
std::aligned_storage_t<sizeof(p_stor)> tmp_stor;
|
|
|
|
if (small_storage() && f.small_storage()) {
|
|
|
|
auto *t = as_base(&tmp_stor);
|
|
|
|
p_func->move_to(t);
|
|
|
|
p_func->~base();
|
|
|
|
p_func = nullptr;
|
|
|
|
f.p_func->move_to(as_base(&p_stor));
|
|
|
|
f.p_func->~base();
|
|
|
|
f.p_func = nullptr;
|
|
|
|
p_func = as_base(&p_stor);
|
|
|
|
t->move_to(as_base(&f.p_stor));
|
|
|
|
t->~base();
|
|
|
|
f.p_func = as_base(&f.p_stor);
|
|
|
|
} else if (small_storage()) {
|
|
|
|
/* copy allocator address/size */
|
|
|
|
memcpy(&tmp_stor, &f.p_stor, sizeof(tmp_stor));
|
|
|
|
p_func->move_to(as_base(&f.p_stor));
|
|
|
|
p_func->~base();
|
|
|
|
p_func = f.p_func;
|
|
|
|
f.p_func = as_base(&f.p_stor);
|
|
|
|
memcpy(&p_stor, &tmp_stor, sizeof(tmp_stor));
|
|
|
|
} else if (f.small_storage()) {
|
|
|
|
/* copy allocator address/size */
|
|
|
|
memcpy(&tmp_stor, &p_stor, sizeof(tmp_stor));
|
|
|
|
f.p_func->move_to(as_base(&p_stor));
|
|
|
|
f.p_func->~base();
|
|
|
|
f.p_func = p_func;
|
|
|
|
p_func = as_base(&p_stor);
|
|
|
|
memcpy(&f.p_stor, &tmp_stor, sizeof(tmp_stor));
|
|
|
|
} else {
|
|
|
|
/* copy allocator address/size */
|
|
|
|
memcpy(&tmp_stor, &p_stor, sizeof(tmp_stor));
|
|
|
|
memcpy(&p_stor, &f.p_stor, sizeof(tmp_stor));
|
|
|
|
memcpy(&f.p_stor, &tmp_stor, sizeof(tmp_stor));
|
|
|
|
std::swap(p_func, f.p_func);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit operator bool() const noexcept {
|
|
|
|
return !!p_func;
|
|
|
|
}
|
|
|
|
|
|
|
|
R operator()(A ...args) {
|
|
|
|
return (*p_func)(std::forward<A>(args)...);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
using alloc_func = void *(*)(void *, void *, size_t, size_t);
|
2021-03-22 00:58:35 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct state;
|
|
|
|
struct ident;
|
|
|
|
struct any_value;
|
|
|
|
struct global_var;
|
2021-03-22 00:58:35 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
using hook_func = callable<void, state &>;
|
|
|
|
using var_cb_func = callable<void, state &, ident &>;
|
|
|
|
using var_print_func = callable<void, state const &, global_var const &>;
|
|
|
|
using command_func = callable<
|
|
|
|
void, state &, std::span<any_value>, any_value &
|
2021-03-22 00:58:35 +01:00
|
|
|
>;
|
|
|
|
|
2015-08-05 23:58:45 +02:00
|
|
|
enum {
|
2021-03-23 23:29:32 +01:00
|
|
|
IDENT_FLAG_PERSIST = 1 << 0,
|
|
|
|
IDENT_FLAG_OVERRIDE = 1 << 1,
|
|
|
|
IDENT_FLAG_HEX = 1 << 2,
|
|
|
|
IDENT_FLAG_READONLY = 1 << 3,
|
|
|
|
IDENT_FLAG_OVERRIDDEN = 1 << 4,
|
|
|
|
IDENT_FLAG_UNKNOWN = 1 << 5,
|
|
|
|
IDENT_FLAG_ARG = 1 << 6
|
2015-08-05 23:58:45 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct bcode;
|
|
|
|
struct internal_state;
|
2021-03-24 20:33:20 +01:00
|
|
|
struct thread_state;
|
2021-03-23 23:29:32 +01:00
|
|
|
struct ident_impl;
|
2016-08-06 20:12:38 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT bcode_ref {
|
|
|
|
bcode_ref():
|
2016-08-07 22:39:27 +02:00
|
|
|
p_code(nullptr)
|
|
|
|
{}
|
2021-03-23 23:29:32 +01:00
|
|
|
bcode_ref(bcode *v);
|
|
|
|
bcode_ref(bcode_ref const &v);
|
|
|
|
bcode_ref(bcode_ref &&v):
|
2016-08-07 22:39:27 +02:00
|
|
|
p_code(v.p_code)
|
|
|
|
{
|
|
|
|
v.p_code = nullptr;
|
|
|
|
}
|
2015-12-20 00:28:12 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
~bcode_ref();
|
2015-12-24 15:57:19 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
bcode_ref &operator=(bcode_ref const &v);
|
|
|
|
bcode_ref &operator=(bcode_ref &&v);
|
2015-12-20 00:28:12 +01:00
|
|
|
|
|
|
|
operator bool() const { return p_code != nullptr; }
|
2021-03-23 23:29:32 +01:00
|
|
|
operator bcode *() const { return p_code; }
|
2015-12-20 00:28:12 +01:00
|
|
|
|
|
|
|
private:
|
2021-03-23 23:29:32 +01:00
|
|
|
bcode *p_code;
|
2015-12-20 00:28:12 +01:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
LIBCUBESCRIPT_EXPORT bool code_is_empty(bcode *code);
|
2016-08-06 18:33:01 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT string_ref {
|
|
|
|
friend struct any_value;
|
|
|
|
friend struct string_pool;
|
2021-03-16 00:44:25 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
string_ref() = delete;
|
|
|
|
string_ref(internal_state *cs, std::string_view str);
|
|
|
|
string_ref(state &cs, std::string_view str);
|
2021-03-16 00:44:25 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
string_ref(string_ref const &ref);
|
2021-03-16 00:44:25 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
~string_ref();
|
2021-03-16 00:44:25 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
string_ref &operator=(string_ref const &ref);
|
2021-03-16 00:44:25 +01:00
|
|
|
|
2021-03-20 02:26:37 +01:00
|
|
|
operator std::string_view() const;
|
2021-03-16 00:44:25 +01:00
|
|
|
|
2021-03-17 21:57:47 +01:00
|
|
|
std::size_t size() const {
|
2021-03-20 02:26:37 +01:00
|
|
|
return std::string_view{*this}.size();
|
2021-03-17 21:57:47 +01:00
|
|
|
}
|
|
|
|
std::size_t length() const {
|
2021-03-20 02:26:37 +01:00
|
|
|
return std::string_view{*this}.length();
|
2021-03-17 21:57:47 +01:00
|
|
|
}
|
|
|
|
|
2021-03-17 23:32:38 +01:00
|
|
|
char const *data() const {
|
2021-03-20 02:26:37 +01:00
|
|
|
return std::string_view{*this}.data();
|
2021-03-17 23:32:38 +01:00
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
bool operator==(string_ref const &s) const;
|
2021-03-17 21:46:37 +01:00
|
|
|
|
2021-03-16 00:44:25 +01:00
|
|
|
private:
|
|
|
|
/* for internal use only */
|
2021-03-23 23:29:32 +01:00
|
|
|
string_ref(char const *p, internal_state *cs);
|
2021-03-16 00:44:25 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
internal_state *p_state;
|
2021-03-17 01:26:16 +01:00
|
|
|
char const *p_str;
|
2021-03-16 00:44:25 +01:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
enum class value_type {
|
2021-03-18 20:55:14 +01:00
|
|
|
NONE = 0, INT, FLOAT, STRING, CODE, IDENT
|
2016-08-30 23:30:40 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT any_value {
|
|
|
|
any_value() = delete;
|
|
|
|
~any_value();
|
2016-09-06 22:23:03 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
any_value(state &);
|
|
|
|
any_value(internal_state &);
|
2021-03-17 01:26:16 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
any_value(any_value const &);
|
|
|
|
any_value(any_value &&v);
|
2016-09-06 22:23:03 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
any_value &operator=(any_value const &);
|
|
|
|
any_value &operator=(any_value &&);
|
2016-09-06 22:23:03 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
value_type get_type() const;
|
2016-08-25 22:24:23 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void set_int(integer_type val);
|
|
|
|
void set_float(float_type val);
|
2021-03-20 02:26:37 +01:00
|
|
|
void set_str(std::string_view val);
|
2021-03-23 23:29:32 +01:00
|
|
|
void set_str(string_ref const &val);
|
2021-03-18 20:55:14 +01:00
|
|
|
void set_none();
|
2021-03-23 23:29:32 +01:00
|
|
|
void set_code(bcode *val);
|
|
|
|
void set_ident(ident *val);
|
2016-08-25 22:24:23 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
string_ref get_str() const;
|
|
|
|
integer_type get_int() const;
|
|
|
|
float_type get_float() const;
|
|
|
|
bcode *get_code() const;
|
|
|
|
ident *get_ident() const;
|
|
|
|
void get_val(any_value &r) const;
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2016-08-02 02:21:36 +02:00
|
|
|
bool get_bool() const;
|
|
|
|
|
2021-03-18 20:55:14 +01:00
|
|
|
void force_none();
|
2021-03-23 23:29:32 +01:00
|
|
|
float_type force_float();
|
|
|
|
integer_type force_int();
|
2021-03-20 02:26:37 +01:00
|
|
|
std::string_view force_str();
|
2021-03-24 21:01:01 +01:00
|
|
|
bcode *force_code(state &cs);
|
|
|
|
ident *force_ident(state &cs);
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2016-08-06 18:33:01 +02:00
|
|
|
bool code_is_empty() const;
|
|
|
|
|
2015-08-13 22:48:03 +02:00
|
|
|
private:
|
2021-03-17 01:26:16 +01:00
|
|
|
template<typename T>
|
|
|
|
struct stor_t {
|
2021-03-23 23:29:32 +01:00
|
|
|
internal_state *state;
|
2021-03-17 01:26:16 +01:00
|
|
|
T val;
|
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
internal_state *get_state() const {
|
2021-03-24 02:42:33 +01:00
|
|
|
return std::launder(
|
|
|
|
reinterpret_cast<stor_t<void *> const *>(&p_stor)
|
|
|
|
)->state;
|
2021-03-17 01:26:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::aligned_union_t<1,
|
2021-03-23 23:29:32 +01:00
|
|
|
stor_t<integer_type>,
|
|
|
|
stor_t<float_type>,
|
2021-03-17 01:26:16 +01:00
|
|
|
stor_t<void *>,
|
2021-03-23 23:29:32 +01:00
|
|
|
string_ref
|
2021-03-17 01:26:16 +01:00
|
|
|
> p_stor;
|
2021-03-23 23:29:32 +01:00
|
|
|
value_type p_type;
|
2015-08-05 23:58:45 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct ident_stack {
|
|
|
|
any_value val_s;
|
|
|
|
ident_stack *next;
|
2021-03-17 01:26:16 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
ident_stack(state &cs): val_s{cs}, next{nullptr} {}
|
2015-08-05 23:58:45 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct error;
|
|
|
|
struct codegen_state;
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
enum class ident_type {
|
2021-03-18 20:55:14 +01:00
|
|
|
IVAR = 0, FVAR, SVAR, COMMAND, ALIAS, SPECIAL
|
2016-08-10 19:33:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct global_var;
|
|
|
|
struct integer_var;
|
|
|
|
struct float_var;
|
|
|
|
struct string_var;
|
|
|
|
struct alias;
|
|
|
|
struct command;
|
2016-08-18 00:54:57 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT ident {
|
2021-03-21 02:41:04 +01:00
|
|
|
int get_raw_type() const;
|
2021-03-23 23:29:32 +01:00
|
|
|
ident_type get_type() const;
|
2021-03-20 02:26:37 +01:00
|
|
|
std::string_view get_name() const;
|
2016-08-18 03:53:51 +02:00
|
|
|
int get_flags() const;
|
|
|
|
int get_index() const;
|
2016-08-10 19:33:43 +02:00
|
|
|
|
2016-08-18 00:54:57 +02:00
|
|
|
bool is_alias() const;
|
2021-03-23 23:29:32 +01:00
|
|
|
alias *get_alias();
|
|
|
|
alias const *get_alias() const;
|
2016-08-10 19:33:43 +02:00
|
|
|
|
2016-08-18 00:54:57 +02:00
|
|
|
bool is_command() const;
|
2021-03-23 23:29:32 +01:00
|
|
|
command *get_command();
|
|
|
|
command const *get_command() const;
|
2016-09-02 18:20:53 +02:00
|
|
|
|
2016-08-18 03:53:51 +02:00
|
|
|
bool is_special() const;
|
2016-08-10 19:33:43 +02:00
|
|
|
|
2016-08-18 00:54:57 +02:00
|
|
|
bool is_var() const;
|
2021-03-23 23:29:32 +01:00
|
|
|
global_var *get_var();
|
|
|
|
global_var const *get_var() const;
|
2016-08-10 19:33:43 +02:00
|
|
|
|
2016-08-18 00:54:57 +02:00
|
|
|
bool is_ivar() const;
|
2021-03-23 23:29:32 +01:00
|
|
|
integer_var *get_ivar();
|
|
|
|
integer_var const *get_ivar() const;
|
2016-08-10 19:33:43 +02:00
|
|
|
|
2016-08-18 00:54:57 +02:00
|
|
|
bool is_fvar() const;
|
2021-03-23 23:29:32 +01:00
|
|
|
float_var *get_fvar();
|
|
|
|
float_var const *get_fvar() const;
|
2016-08-10 19:33:43 +02:00
|
|
|
|
2016-08-18 00:54:57 +02:00
|
|
|
bool is_svar() const;
|
2021-03-23 23:29:32 +01:00
|
|
|
string_var *get_svar();
|
|
|
|
string_var const *get_svar() const;
|
2016-08-17 23:04:43 +02:00
|
|
|
|
|
|
|
protected:
|
2021-03-23 23:29:32 +01:00
|
|
|
ident() = default;
|
2016-08-18 03:53:51 +02:00
|
|
|
|
|
|
|
private:
|
2021-03-23 23:29:32 +01:00
|
|
|
friend struct state;
|
2021-03-21 02:41:04 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
ident_impl *p_impl{};
|
2016-08-17 23:04:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT global_var: ident {
|
2016-08-18 04:14:55 +02:00
|
|
|
protected:
|
2021-03-23 23:29:32 +01:00
|
|
|
global_var() = default;
|
2016-08-17 23:04:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT integer_var: global_var {
|
|
|
|
integer_type get_val_min() const;
|
|
|
|
integer_type get_val_max() const;
|
2016-08-18 04:14:55 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
integer_type get_value() const;
|
|
|
|
void set_value(integer_type val);
|
2016-08-18 00:36:37 +02:00
|
|
|
|
2021-03-21 02:41:04 +01:00
|
|
|
protected:
|
2021-03-23 23:29:32 +01:00
|
|
|
integer_var() = default;
|
2016-08-17 23:04:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT float_var: global_var {
|
|
|
|
float_type get_val_min() const;
|
|
|
|
float_type get_val_max() const;
|
2016-08-18 04:14:55 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
float_type get_value() const;
|
|
|
|
void set_value(float_type val);
|
2016-08-18 00:36:37 +02:00
|
|
|
|
2021-03-21 02:41:04 +01:00
|
|
|
protected:
|
2021-03-23 23:29:32 +01:00
|
|
|
float_var() = default;
|
2016-08-17 23:04:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT string_var: global_var {
|
|
|
|
string_ref get_value() const;
|
|
|
|
void set_value(string_ref val);
|
2016-08-18 00:36:37 +02:00
|
|
|
|
2021-03-21 02:41:04 +01:00
|
|
|
protected:
|
2021-03-23 23:29:32 +01:00
|
|
|
string_var() = default;
|
2016-08-17 23:04:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT alias: ident {
|
|
|
|
any_value get_value() const;
|
|
|
|
void get_cval(any_value &v) const;
|
2021-03-21 02:41:04 +01:00
|
|
|
|
|
|
|
protected:
|
2021-03-23 23:29:32 +01:00
|
|
|
alias() = default;
|
2016-08-17 23:04:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct command: ident {
|
2021-03-20 02:26:37 +01:00
|
|
|
std::string_view get_args() const;
|
2016-09-02 22:49:05 +02:00
|
|
|
int get_num_args() const;
|
2016-09-02 18:20:53 +02:00
|
|
|
|
2021-03-21 02:41:04 +01:00
|
|
|
protected:
|
2021-03-23 23:29:32 +01:00
|
|
|
command() = default;
|
2016-09-02 18:20:53 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct ident_link;
|
2015-08-06 22:43:36 +02:00
|
|
|
|
2016-08-18 20:47:29 +02:00
|
|
|
enum {
|
2021-03-23 23:29:32 +01:00
|
|
|
LIB_MATH = 1 << 0,
|
|
|
|
LIB_STRING = 1 << 1,
|
|
|
|
LIB_LIST = 1 << 2,
|
|
|
|
LIB_ALL = 0b111
|
2016-08-18 20:47:29 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
enum class loop_state {
|
2021-03-18 20:55:14 +01:00
|
|
|
NORMAL = 0, BREAK, CONTINUE
|
2016-09-14 23:24:13 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT state {
|
2015-08-05 23:58:45 +02:00
|
|
|
int identflags = 0;
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
state();
|
|
|
|
state(alloc_func func, void *data);
|
|
|
|
virtual ~state();
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
state(state const &) = delete;
|
|
|
|
state(state &&s) {
|
2018-04-26 19:23:11 +02:00
|
|
|
swap(s);
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
state &operator=(state const &) = delete;
|
|
|
|
state &operator=(state &&s) {
|
2018-04-26 19:23:11 +02:00
|
|
|
swap(s);
|
|
|
|
s.destroy();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void destroy();
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void swap(state &s) {
|
2021-03-24 20:33:20 +01:00
|
|
|
std::swap(p_tstate, s.p_tstate);
|
2018-04-26 19:23:11 +02:00
|
|
|
std::swap(identflags, s.identflags);
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
state new_thread();
|
2018-04-26 19:23:11 +02:00
|
|
|
|
2021-03-22 00:58:35 +01:00
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
hook_func set_call_hook(F &&f) {
|
2021-03-22 00:58:35 +01:00
|
|
|
return std::move(set_call_hook(
|
2021-03-23 23:29:32 +01:00
|
|
|
hook_func{std::forward<F>(f), callable_alloc, this}
|
2021-03-22 00:58:35 +01:00
|
|
|
));
|
|
|
|
}
|
2021-03-23 23:29:32 +01:00
|
|
|
hook_func const &get_call_hook() const;
|
|
|
|
hook_func &get_call_hook();
|
2016-09-05 21:34:48 +02:00
|
|
|
|
2021-03-22 00:58:35 +01:00
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
var_print_func set_var_printer(F &&f) {
|
2021-03-22 00:58:35 +01:00
|
|
|
return std::move(set_var_printer(
|
2021-03-23 23:29:32 +01:00
|
|
|
var_print_func{std::forward<F>(f), callable_alloc, this}
|
2021-03-22 00:58:35 +01:00
|
|
|
));
|
|
|
|
}
|
2021-03-23 23:29:32 +01:00
|
|
|
var_print_func const &get_var_printer() const;
|
2021-03-18 00:03:30 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void init_libs(int libs = LIB_ALL);
|
2016-09-13 23:46:51 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void clear_override(ident &id);
|
2015-08-05 23:58:45 +02:00
|
|
|
void clear_overrides();
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
ident *new_ident(std::string_view name, int flags = IDENT_FLAG_UNKNOWN);
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2021-03-22 00:58:35 +01:00
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
integer_var *new_ivar(
|
|
|
|
std::string_view name, integer_type m, integer_type x, integer_type v,
|
2021-03-22 00:58:35 +01:00
|
|
|
F &&f, int flags = 0
|
|
|
|
) {
|
|
|
|
return new_ivar(
|
|
|
|
name, m, x, v,
|
2021-03-23 23:29:32 +01:00
|
|
|
var_cb_func{std::forward<F>(f), callable_alloc, this}, flags
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
|
|
|
}
|
2021-03-23 23:29:32 +01:00
|
|
|
integer_var *new_ivar(
|
|
|
|
std::string_view name, integer_type m, integer_type x, integer_type v
|
|
|
|
) {
|
|
|
|
return new_ivar(name, m, x, v, var_cb_func{}, 0);
|
2021-03-22 00:58:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
float_var *new_fvar(
|
|
|
|
std::string_view name, float_type m, float_type x, float_type v,
|
2021-03-22 00:58:35 +01:00
|
|
|
F &&f, int flags = 0
|
|
|
|
) {
|
|
|
|
return new_fvar(
|
|
|
|
name, m, x, v,
|
2021-03-23 23:29:32 +01:00
|
|
|
var_cb_func{std::forward<F>(f), callable_alloc, this}, flags
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
|
|
|
}
|
2021-03-23 23:29:32 +01:00
|
|
|
float_var *new_fvar(
|
|
|
|
std::string_view name, float_type m, float_type x, float_type v
|
2021-03-22 00:58:35 +01:00
|
|
|
) {
|
2021-03-23 23:29:32 +01:00
|
|
|
return new_fvar(name, m, x, v, var_cb_func{}, 0);
|
2021-03-22 00:58:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
string_var *new_svar(
|
2021-03-22 00:58:35 +01:00
|
|
|
std::string_view name, std::string_view v, F &&f, int flags = 0
|
|
|
|
) {
|
|
|
|
return new_svar(
|
|
|
|
name, v,
|
2021-03-23 23:29:32 +01:00
|
|
|
var_cb_func{std::forward<F>(f), callable_alloc, this}, flags
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
|
|
|
}
|
2021-03-23 23:29:32 +01:00
|
|
|
string_var *new_svar(std::string_view name, std::string_view v) {
|
|
|
|
return new_svar(name, v, var_cb_func{}, 0);
|
2021-03-22 00:58:35 +01:00
|
|
|
}
|
2016-08-20 17:52:54 +02:00
|
|
|
|
2021-03-22 00:58:35 +01:00
|
|
|
template<typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
command *new_command(
|
2021-03-22 00:58:35 +01:00
|
|
|
std::string_view name, std::string_view args, F &&f
|
|
|
|
) {
|
|
|
|
return new_command(
|
|
|
|
name, args,
|
2021-03-23 23:29:32 +01:00
|
|
|
command_func{std::forward<F>(f), callable_alloc, this}
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
|
|
|
}
|
2016-09-02 19:03:01 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
ident *get_ident(std::string_view name);
|
|
|
|
alias *get_alias(std::string_view name);
|
2021-03-20 02:26:37 +01:00
|
|
|
bool have_ident(std::string_view name);
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
std::span<ident *> get_idents();
|
|
|
|
std::span<ident const *> get_idents() const;
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2021-03-20 02:26:37 +01:00
|
|
|
void reset_var(std::string_view name);
|
|
|
|
void touch_var(std::string_view name);
|
2015-08-05 23:58:45 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void run(bcode *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<any_value> args, any_value &ret);
|
2015-08-07 22:04:31 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
any_value run(bcode *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<any_value> args);
|
2016-08-18 20:34:24 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
loop_state run_loop(bcode *code, any_value &ret);
|
|
|
|
loop_state run_loop(bcode *code);
|
2016-09-14 23:24:13 +02:00
|
|
|
|
2021-03-24 20:33:20 +01:00
|
|
|
bool is_in_loop() const;
|
2016-09-14 23:24:13 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void set_alias(std::string_view name, any_value v);
|
2015-08-07 03:11:53 +02:00
|
|
|
|
2016-08-07 22:39:27 +02:00
|
|
|
void set_var_int(
|
2021-03-23 23:29:32 +01:00
|
|
|
std::string_view name, integer_type v,
|
2016-08-07 22:39:27 +02:00
|
|
|
bool dofunc = true, bool doclamp = true
|
|
|
|
);
|
|
|
|
void set_var_float(
|
2021-03-23 23:29:32 +01:00
|
|
|
std::string_view name, float_type v,
|
2016-08-07 22:39:27 +02:00
|
|
|
bool dofunc = true, bool doclamp = true
|
|
|
|
);
|
|
|
|
void set_var_str(
|
2021-03-20 02:26:37 +01:00
|
|
|
std::string_view name, std::string_view v, bool dofunc = true
|
2016-08-07 22:39:27 +02:00
|
|
|
);
|
2015-08-07 03:11:53 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void set_var_int_checked(integer_var *iv, integer_type v);
|
|
|
|
void set_var_int_checked(integer_var *iv, std::span<any_value> args);
|
|
|
|
void set_var_float_checked(float_var *fv, float_type v);
|
|
|
|
void set_var_str_checked(string_var *fv, std::string_view v);
|
2015-08-07 03:44:51 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
std::optional<integer_type> get_var_int(std::string_view name);
|
|
|
|
std::optional<float_type> get_var_float(std::string_view name);
|
|
|
|
std::optional<string_ref> get_var_str(std::string_view name);
|
2015-08-07 03:11:53 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
std::optional<integer_type> get_var_min_int(std::string_view name);
|
|
|
|
std::optional<integer_type> get_var_max_int(std::string_view name);
|
2015-08-07 03:11:53 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
std::optional<float_type> get_var_min_float(std::string_view name);
|
|
|
|
std::optional<float_type> get_var_max_float(std::string_view name);
|
2015-08-07 03:11:53 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
std::optional<string_ref> get_alias_val(std::string_view name);
|
2015-08-07 22:38:57 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
void print_var(global_var const &v) const;
|
2016-08-21 02:34:03 +02:00
|
|
|
|
2021-03-26 02:59:42 +01:00
|
|
|
thread_state *p_tstate = nullptr;
|
|
|
|
|
2016-08-21 02:34:03 +02:00
|
|
|
private:
|
2021-03-23 23:29:32 +01:00
|
|
|
hook_func set_call_hook(hook_func func);
|
|
|
|
var_print_func set_var_printer(var_print_func func);
|
2021-03-22 00:58:35 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
integer_var *new_ivar(
|
|
|
|
std::string_view n, integer_type m, integer_type x, integer_type v,
|
|
|
|
var_cb_func f, int flags
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
2021-03-23 23:29:32 +01:00
|
|
|
float_var *new_fvar(
|
|
|
|
std::string_view n, float_type m, float_type x, float_type v,
|
|
|
|
var_cb_func f, int flags
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
2021-03-23 23:29:32 +01:00
|
|
|
string_var *new_svar(
|
|
|
|
std::string_view n, std::string_view v, var_cb_func f, int flags
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
command *new_command(
|
|
|
|
std::string_view name, std::string_view args, command_func func
|
2021-03-22 00:58:35 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
static void *callable_alloc(
|
|
|
|
void *data, void *p, std::size_t os, std::size_t ns
|
|
|
|
) {
|
2021-03-23 23:29:32 +01:00
|
|
|
return static_cast<state *>(data)->alloc(p, os, ns);
|
2021-03-22 00:58:35 +01:00
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
LIBCUBESCRIPT_LOCAL state(internal_state *s);
|
2018-04-26 19:23:11 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
ident *add_ident(ident *id, ident_impl *impl);
|
2016-09-02 20:22:19 +02:00
|
|
|
|
2021-03-22 00:58:35 +01:00
|
|
|
void *alloc(void *ptr, size_t olds, size_t news);
|
2015-08-05 23:58:45 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct stack_state {
|
2021-03-26 02:59:42 +01:00
|
|
|
struct node {
|
|
|
|
node const *next;
|
|
|
|
ident const *id;
|
|
|
|
int index;
|
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
stack_state() = delete;
|
2021-03-26 02:59:42 +01:00
|
|
|
stack_state(thread_state &ts, node *nd = nullptr, bool gap = false);
|
2021-03-23 23:29:32 +01:00
|
|
|
stack_state(stack_state const &) = delete;
|
|
|
|
stack_state(stack_state &&st);
|
|
|
|
~stack_state();
|
2016-09-14 00:14:21 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
stack_state &operator=(stack_state const &) = delete;
|
|
|
|
stack_state &operator=(stack_state &&);
|
2016-09-14 00:14:21 +02:00
|
|
|
|
2021-03-26 02:59:42 +01:00
|
|
|
node const *get() const;
|
2016-09-14 00:14:21 +02:00
|
|
|
bool gap() const;
|
|
|
|
|
|
|
|
private:
|
2021-03-26 02:59:42 +01:00
|
|
|
thread_state &p_state;
|
|
|
|
node *p_node;
|
2016-09-14 00:14:21 +02:00
|
|
|
bool p_gap;
|
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT error {
|
|
|
|
friend struct state;
|
2016-09-14 00:14:21 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
error() = delete;
|
|
|
|
error(error const &) = delete;
|
|
|
|
error(error &&v):
|
2017-01-25 01:57:33 +01:00
|
|
|
p_errmsg(v.p_errmsg), p_stack(std::move(v.p_stack))
|
2016-09-14 00:14:21 +02:00
|
|
|
{}
|
|
|
|
|
2021-03-20 02:26:37 +01:00
|
|
|
std::string_view what() const {
|
2016-09-14 00:14:21 +02:00
|
|
|
return p_errmsg;
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
stack_state &get_stack() {
|
2016-09-14 00:14:21 +02:00
|
|
|
return p_stack;
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
stack_state const &get_stack() const {
|
2016-09-14 00:14:21 +02:00
|
|
|
return p_stack;
|
|
|
|
}
|
|
|
|
|
2021-03-26 02:59:42 +01:00
|
|
|
template<typename ...A>
|
|
|
|
error(state &cs, std::string_view msg, A const &...args):
|
|
|
|
error{*cs.p_tstate, msg, args...}
|
|
|
|
{}
|
|
|
|
|
|
|
|
error(thread_state &ts, std::string_view msg):
|
|
|
|
p_errmsg{}, p_stack{ts}
|
2016-09-14 00:14:21 +02:00
|
|
|
{
|
2021-03-20 21:06:26 +01:00
|
|
|
char *sp;
|
2021-03-26 02:59:42 +01:00
|
|
|
char *buf = request_buf(ts, msg.size(), sp);
|
2021-03-20 21:06:26 +01:00
|
|
|
std::memcpy(buf, msg.data(), msg.size());
|
|
|
|
buf[msg.size()] = '\0';
|
|
|
|
p_errmsg = std::string_view{sp, buf + msg.size()};
|
2021-03-26 02:59:42 +01:00
|
|
|
p_stack = save_stack(ts);
|
2016-09-14 00:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...A>
|
2021-03-26 02:59:42 +01:00
|
|
|
error(thread_state &ts, std::string_view msg, A const &...args):
|
|
|
|
p_errmsg{}, p_stack{ts}
|
2016-09-14 00:14:21 +02:00
|
|
|
{
|
2021-03-20 21:06:26 +01:00
|
|
|
std::size_t sz = msg.size() + 64;
|
|
|
|
char *buf, *sp;
|
|
|
|
for (;;) {
|
2021-03-26 02:59:42 +01:00
|
|
|
buf = request_buf(ts, sz, sp);
|
2021-03-20 21:06:26 +01:00
|
|
|
int written = std::snprintf(buf, sz, msg.data(), args...);
|
|
|
|
if (written <= 0) {
|
2021-03-23 23:29:32 +01:00
|
|
|
throw internal_error{"format error"};
|
2021-03-20 21:06:26 +01:00
|
|
|
} else if (std::size_t(written) <= sz) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sz = std::size_t(written);
|
2016-09-14 00:14:21 +02:00
|
|
|
}
|
2021-03-20 21:06:26 +01:00
|
|
|
p_errmsg = std::string_view{sp, buf + sz};
|
2021-03-26 02:59:42 +01:00
|
|
|
p_stack = save_stack(ts);
|
2016-09-14 00:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2021-03-26 02:59:42 +01:00
|
|
|
stack_state save_stack(thread_state &ts);
|
|
|
|
char *request_buf(thread_state &ts, std::size_t bufs, char *&sp);
|
2016-09-14 00:14:21 +02:00
|
|
|
|
2021-03-20 02:26:37 +01:00
|
|
|
std::string_view p_errmsg;
|
2021-03-23 23:29:32 +01:00
|
|
|
stack_state p_stack;
|
2016-09-14 00:14:21 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT stacked_value: any_value {
|
|
|
|
stacked_value(state &cs, ident *id = nullptr);
|
|
|
|
~stacked_value();
|
2015-08-13 20:48:58 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
stacked_value(stacked_value const &) = delete;
|
|
|
|
stacked_value(stacked_value &&) = delete;
|
2016-09-06 22:23:03 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
stacked_value &operator=(stacked_value const &) = delete;
|
|
|
|
stacked_value &operator=(stacked_value &&v) = delete;
|
2016-09-06 22:23:03 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
stacked_value &operator=(any_value const &v);
|
|
|
|
stacked_value &operator=(any_value &&v);
|
2016-09-06 22:23:03 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
bool set_alias(ident *id);
|
|
|
|
alias *get_alias() const;
|
2016-09-02 22:42:10 +02:00
|
|
|
bool has_alias() const;
|
2015-08-13 20:48:58 +02:00
|
|
|
|
2016-09-02 22:42:10 +02:00
|
|
|
bool push();
|
|
|
|
bool pop();
|
2015-08-14 00:18:48 +02:00
|
|
|
|
|
|
|
private:
|
2021-03-23 23:29:32 +01:00
|
|
|
alias *p_a;
|
|
|
|
ident_stack p_stack;
|
2015-08-14 00:18:48 +02:00
|
|
|
bool p_pushed;
|
2015-08-13 20:48:58 +02:00
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
struct LIBCUBESCRIPT_EXPORT list_parser {
|
|
|
|
list_parser(state &cs, std::string_view s = std::string_view{}):
|
2021-03-20 19:34:26 +01:00
|
|
|
p_state{&cs}, p_input_beg{s.data()}, p_input_end{s.data() + s.size()}
|
2021-03-20 02:26:37 +01:00
|
|
|
{}
|
2021-03-18 23:53:16 +01:00
|
|
|
|
2021-03-20 02:26:37 +01:00
|
|
|
void set_input(std::string_view s) {
|
2021-03-20 19:34:26 +01:00
|
|
|
p_input_beg = s.data();
|
|
|
|
p_input_end = s.data() + s.size();
|
2021-03-20 02:26:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string_view get_input() const {
|
2021-03-20 19:34:26 +01:00
|
|
|
return std::string_view{p_input_beg, p_input_end};
|
2021-03-20 02:26:37 +01:00
|
|
|
}
|
|
|
|
|
2021-03-20 19:34:26 +01:00
|
|
|
bool parse();
|
|
|
|
std::size_t count();
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
string_ref get_item() const;
|
2021-03-20 19:34:26 +01:00
|
|
|
|
|
|
|
std::string_view get_raw_item() const { return p_item; }
|
|
|
|
std::string_view get_quoted_item() const { return p_quoted_item; }
|
|
|
|
|
|
|
|
void skip_until_item();
|
2021-03-18 23:53:16 +01:00
|
|
|
|
2021-03-20 19:34:26 +01:00
|
|
|
private:
|
2021-03-23 23:29:32 +01:00
|
|
|
state *p_state;
|
2021-03-20 19:34:26 +01:00
|
|
|
char const *p_input_beg, *p_input_end;
|
|
|
|
|
|
|
|
std::string_view p_item{};
|
|
|
|
std::string_view p_quoted_item{};
|
|
|
|
};
|
2021-03-18 23:53:16 +01:00
|
|
|
|
2021-03-23 02:02:43 +01:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
LIBCUBESCRIPT_EXPORT char const *parse_string(
|
|
|
|
state &cs, std::string_view str, size_t &nlines
|
2021-03-23 02:02:43 +01:00
|
|
|
);
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
inline char const *parse_string(
|
|
|
|
state &cs, std::string_view str
|
2021-03-23 02:02:43 +01:00
|
|
|
) {
|
|
|
|
size_t nlines;
|
2021-03-23 23:29:32 +01:00
|
|
|
return parse_string(cs, str, nlines);
|
2021-03-23 02:02:43 +01:00
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
LIBCUBESCRIPT_EXPORT char const *parse_word(
|
|
|
|
state &cs, std::string_view str
|
2021-03-23 02:02:43 +01:00
|
|
|
);
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
LIBCUBESCRIPT_EXPORT string_ref concat_values(
|
|
|
|
state &cs, std::span<any_value> vals,
|
2021-03-20 05:41:25 +01:00
|
|
|
std::string_view sep = std::string_view{}
|
2021-03-19 00:30:54 +01:00
|
|
|
);
|
|
|
|
|
2021-03-23 02:02:43 +01:00
|
|
|
template<typename R>
|
2021-03-23 23:29:32 +01:00
|
|
|
inline R escape_string(R writer, std::string_view str) {
|
2021-03-23 02:02:43 +01:00
|
|
|
*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;
|
2015-08-08 17:06:18 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-23 02:02:43 +01:00
|
|
|
*writer++ = '"';
|
|
|
|
return writer;
|
|
|
|
}
|
2015-08-08 18:07:01 +02:00
|
|
|
|
2021-03-23 02:02:43 +01:00
|
|
|
template<typename R>
|
2021-03-23 23:29:32 +01:00
|
|
|
inline R unescape_string(R writer, std::string_view str) {
|
2021-03-23 02:02:43 +01:00
|
|
|
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;
|
2016-09-24 03:31:41 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-23 02:02:43 +01:00
|
|
|
continue;
|
2015-08-11 03:18:53 +02:00
|
|
|
}
|
2021-03-23 02:02:43 +01:00
|
|
|
*writer++ = '\\';
|
|
|
|
} else {
|
|
|
|
*writer++ = *it;
|
2015-08-11 03:18:53 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-23 02:02:43 +01:00
|
|
|
return writer;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R>
|
2021-03-23 23:29:32 +01:00
|
|
|
inline R print_stack(R writer, stack_state const &st) {
|
2021-03-23 02:02:43 +01:00
|
|
|
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';
|
2016-09-09 19:19:50 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-23 02:02:43 +01:00
|
|
|
return writer;
|
|
|
|
}
|
2015-08-08 17:13:46 +02:00
|
|
|
|
2021-03-23 23:32:25 +01:00
|
|
|
} /* namespace cubescript */
|
2015-09-10 19:53:43 +02:00
|
|
|
|
2016-08-14 18:35:38 +02:00
|
|
|
#endif /* LIBCUBESCRIPT_CUBESCRIPT_HH */
|