Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
|
816dbbbd03 | 4 months ago |
|
378d20e61d | 5 months ago |
|
63f5aea0e9 | 5 months ago |
|
b1e624f666 | 5 months ago |
|
93f78ddbb7 | 5 months ago |
|
8e32a84989 | 5 months ago |
|
097b7cd2d9 | 5 months ago |
|
74631fd500 | 5 months ago |
33 changed files with 1036 additions and 508 deletions
@ -0,0 +1,9 @@
|
||||
.idea/ |
||||
cmake-build-debug/ |
||||
*.make |
||||
*.cmake |
||||
CMakeFiles |
||||
*.cbp |
||||
Makefile |
||||
DartConfiguration.tcl |
||||
Testing |
@ -1,22 +1,35 @@
|
||||
cmake_minimum_required(VERSION 3.20) |
||||
set(CMAKE_CXX_STANDARD 20) |
||||
project(kst_disnomia) |
||||
project(kst_dsn) |
||||
|
||||
include(CTest) |
||||
|
||||
enable_testing() |
||||
|
||||
find_package(Lua 5.3 REQUIRED) |
||||
|
||||
add_library( |
||||
${PROJECT_NAME} |
||||
includes/kst/dsn/lua.hpp |
||||
includes/kst/disnomia.hpp |
||||
includes/kst/dsn/types.hpp |
||||
includes/kst/dsn/status.hpp |
||||
includes/kst/dsn/state.hpp |
||||
${PROJECT_NAME} INTERFACE |
||||
includes/kst/dsn/lib/lua.hpp |
||||
includes/kst/dsn/dsn.hpp |
||||
includes/kst/dsn/types/types.hpp |
||||
includes/kst/dsn/states/state.hpp |
||||
includes/kst/dsn/states/base.hpp |
||||
includes/kst/dsn/states/context.hpp |
||||
includes/kst/dsn/types/value.hpp |
||||
includes/kst/dsn/types/base_type.hpp |
||||
includes/kst/dsn/types/concepts/dsn.hpp |
||||
includes/kst/dsn/types/concepts/cpp.hpp |
||||
includes/kst/dsn/types/table.hpp |
||||
includes/kst/dsn/types/type_names.hpp |
||||
includes/kst/dsn/types/concepts/functions.hpp |
||||
includes/kst/dsn/types/function.hpp |
||||
) |
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) |
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC includes/) |
||||
target_include_directories(${PROJECT_NAME} INTERFACE includes/) |
||||
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE lua) |
||||
|
||||
target_link_libraries(${PROJECT_NAME} lua) |
||||
add_subdirectory(tests) |
@ -1,4 +0,0 @@
|
||||
#ifndef KST_DISNOMIA_HPP |
||||
#define KST_DISNOMIA_HPP |
||||
#include "dsn/state.hpp" |
||||
#endif //KST_DISNOMIA_HPP
|
@ -0,0 +1,2 @@
|
||||
#pragma once |
||||
#include <kst/dsn/states/state.hpp> |
@ -0,0 +1,2 @@
|
||||
#pragma once |
||||
#include <lua5.3/lua.hpp> |
@ -1,4 +0,0 @@
|
||||
#ifndef KST_DISNOMIA_LUA_HPP |
||||
#define KST_DISNOMIA_LUA_HPP |
||||
#include <lua5.3/lua.hpp> |
||||
#endif //KST_DISNOMIA_LUA_HPP
|
@ -1,126 +0,0 @@
|
||||
#ifndef KST_DISNOMIA_STATE_HPP |
||||
#define KST_DISNOMIA_STATE_HPP |
||||
|
||||
#include "kst/dsn/states/base.hpp" |
||||
#include "kst/dsn/states/context.hpp" |
||||
#include "kst/dsn/status.hpp" |
||||
|
||||
namespace kst::dsn { |
||||
class state : public states::base { |
||||
using DisnomiaFunction = void (*)(); |
||||
|
||||
using DisnomiaCtxFunction = void (*)(states::context&); |
||||
|
||||
template<types::any::Type...ATypes> |
||||
using DisnomiaAnyArgsFunction = void (*)(ATypes...); |
||||
|
||||
template<types::any::Type...ATypes> |
||||
using DisnomiaAnyCtxArgsFunction = void (*)(states::context&, ATypes...); |
||||
|
||||
public: |
||||
state() |
||||
:states::base(luaL_newstate()) { |
||||
luaL_openlibs(_state); |
||||
} |
||||
~state() { |
||||
lua_close(_state); |
||||
} |
||||
public: |
||||
auto load_file(char const* filename) { |
||||
auto status = luaL_loadfile(_state, filename); |
||||
if (status==LUA_OK) |
||||
return dsn::status::okay; |
||||
return dsn::status::error; |
||||
} |
||||
|
||||
auto run_file(char const* filename) { |
||||
auto status = luaL_dofile(_state, filename); |
||||
if (status==LUA_OK) |
||||
return dsn::status::okay; |
||||
return dsn::status::error; |
||||
} |
||||
|
||||
auto get_error() { |
||||
auto message = lua_tostring(_state, -1); |
||||
lua_pop(_state, 1); |
||||
return message; |
||||
} |
||||
|
||||
auto call() { |
||||
auto status = lua_pcall(_state, 0, LUA_MULTRET, 0); |
||||
if (status==LUA_OK) |
||||
return dsn::status::okay; |
||||
return dsn::status::error; |
||||
} |
||||
|
||||
auto register_function(const char* name, DisnomiaFunction function) { |
||||
lua_pushlightuserdata(_state, reinterpret_cast<void*>(function)); |
||||
lua_pushcclosure(_state, [](lua_State* s) -> int |
||||
{ |
||||
auto ctx = states::context(s, 0); |
||||
auto fn = ctx.get_closure<DisnomiaFunction>(); |
||||
fn(); |
||||
return 0; |
||||
}, 1); |
||||
lua_setglobal(_state, name); |
||||
} |
||||
|
||||
auto register_function(const char* name, DisnomiaCtxFunction function) { |
||||
lua_pushlightuserdata(_state, reinterpret_cast<void*>(function)); |
||||
lua_pushcclosure(_state, [](lua_State* s) -> int |
||||
{ |
||||
auto ctx = states::context(s, 0); |
||||
auto fn = ctx.get_closure<DisnomiaCtxFunction>(); |
||||
fn(ctx); |
||||
return ctx.get_return_argc(); |
||||
}, 1); |
||||
lua_setglobal(_state, name); |
||||
} |
||||
|
||||
template<types::any::Type...Args> |
||||
auto register_function(const char* name, DisnomiaAnyArgsFunction<Args...> function) { |
||||
lua_pushlightuserdata(_state, reinterpret_cast<void*>(function)); |
||||
lua_pushcclosure(_state, [](lua_State* s) -> int |
||||
{ |
||||
auto ctx = states::context(s, sizeof...(Args)); |
||||
if (auto error = ctx.validate_argc()) |
||||
{ |
||||
return error; |
||||
} |
||||
int argc = 0; |
||||
(ctx.validate_type<Args>(++argc), ...); |
||||
argc = sizeof...(Args); |
||||
auto fn = ctx.get_closure<DisnomiaAnyArgsFunction<Args...>>(); |
||||
fn(ctx.get_type<Args>(argc--)...); |
||||
return 0; |
||||
}, 1); |
||||
lua_setglobal(_state, name); |
||||
} |
||||
|
||||
template<types::any::Type...Args> |
||||
auto register_function(const char* name, DisnomiaAnyCtxArgsFunction<Args...> function) { |
||||
lua_pushlightuserdata(_state, reinterpret_cast<void*>(function)); |
||||
lua_pushcclosure(_state, [](lua_State* s) -> int |
||||
{ |
||||
auto ctx = states::context(s, sizeof...(Args)); |
||||
if (auto error = ctx.validate_argc()) |
||||
{ |
||||
return error; |
||||
} |
||||
int argc = 0; |
||||
(ctx.validate_type<Args>(++argc), ...); |
||||
argc = sizeof...(Args); |
||||
auto fn = ctx.get_closure<DisnomiaAnyCtxArgsFunction<Args...>>(); |
||||
fn(ctx, ctx.get_type<Args>(argc--)...); |
||||
if (auto error = ctx.get_error_c()) |
||||
{ |
||||
return error; |
||||
} |
||||
return ctx.get_return_argc(); |
||||
}, 1); |
||||
lua_setglobal(_state, name); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
#endif //KST_DISNOMIA_STATE_HPP
|
@ -0,0 +1,68 @@
|
||||
#ifndef KST_DISNOMIA_STATE_HPP |
||||
#define KST_DISNOMIA_STATE_HPP |
||||
|
||||
#include <string> |
||||
|
||||
#include <kst/dsn/states/base.hpp> |
||||
#include <kst/dsn/states/context.hpp> |
||||
#include <kst/dsn/types/value.hpp> |
||||
#include <stdexcept> |
||||
|
||||
namespace kst::dsn { |
||||
class state { |
||||
private: |
||||
states::base _state; |
||||
|
||||
public: |
||||
state() |
||||
:_state(luaL_newstate()) { |
||||
luaL_openlibs(_state); |
||||
} |
||||
public: |
||||
|
||||
auto get_top() { |
||||
return _state.get_top(); |
||||
} |
||||
|
||||
auto load_file(char const* filename) { |
||||
auto status = luaL_loadfile(_state, filename); |
||||
if (status!=LUA_OK) |
||||
throw std::runtime_error(_state.get_error()); |
||||
} |
||||
|
||||
auto run_file(char const* filename) { |
||||
auto status = luaL_dofile(_state, filename); |
||||
if (status!=LUA_OK) |
||||
throw std::runtime_error(_state.get_error()); |
||||
} |
||||
|
||||
auto eval(const std::string& script) { |
||||
if (luaL_dostring(_state, script.c_str())==LUA_OK) |
||||
return value(_state).get(-1); |
||||
throw std::runtime_error(_state.get_error()); |
||||
}; |
||||
|
||||
auto eval_file(const std::string& name) { |
||||
if (luaL_dofile(_state, name.c_str())==LUA_OK) |
||||
return value(_state).get(-1); |
||||
throw std::runtime_error(_state.get_error()); |
||||
}; |
||||
|
||||
auto call() { |
||||
auto status = lua_pcall(_state, 0, LUA_MULTRET, 0); |
||||
if (status!=LUA_OK) |
||||
throw std::runtime_error(_state.get_error()); |
||||
} |
||||
|
||||
auto operator[](variant_cpp id) { |
||||
_state.get_global(id); |
||||
value v(_state); |
||||
v._name = id; |
||||
v.get(-1); |
||||
lua_pop(_state,-1); |
||||
return v; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
#endif //KST_DISNOMIA_STATE_HPP
|
@ -1,11 +0,0 @@
|
||||
#ifndef KST_DISNOMIA_STATUS_HPP |
||||
#define KST_DISNOMIA_STATUS_HPP |
||||
|
||||
namespace kst::dsn { |
||||
enum class status { |
||||
okay, |
||||
error, |
||||
}; |
||||
} |
||||
|
||||
#endif //KST_DISNOMIA_STATUS_HPP
|
@ -1,150 +0,0 @@
|
||||
#ifndef KST_DISNOMIA_TYPES_HPP |
||||
#define KST_DISNOMIA_TYPES_HPP |
||||
#include <variant> |
||||
#include <string> |
||||
#include <concepts> |
||||
|
||||
namespace kst::dsn::types { |
||||
enum class type { |
||||
nil, |
||||
boolean, |
||||
number, |
||||
integer, |
||||
string, |
||||
function, |
||||
userdata, |
||||
thread, |
||||
table, |
||||
}; |
||||
|
||||
struct nil { |
||||
int value = 0; |
||||
static auto type() { |
||||
return types::type::nil; |
||||
} |
||||
}; |
||||
|
||||
struct boolean { |
||||
bool value; |
||||
explicit boolean(bool v) |
||||
:value(v) { } |
||||
static auto type() { |
||||
return types::type::boolean; |
||||
} |
||||
}; |
||||
|
||||
struct number { |
||||
double value; |
||||
explicit number(double v) |
||||
:value(v) { } |
||||
static auto type() { |
||||
return types::type::number; |
||||
} |
||||
}; |
||||
|
||||
struct integer { |
||||
int value; |
||||
explicit integer(int v) |
||||
:value(v) { } |
||||
static auto type() { |
||||
return types::type::integer; |
||||
} |
||||
}; |
||||
|
||||
struct string { |
||||
std::string value; |
||||
explicit string(const char* v) |
||||
:value(v) { } |
||||
static auto type() { |
||||
return types::type::string; |
||||
} |
||||
}; |
||||
|
||||
struct function { |
||||
static auto type() { |
||||
return types::type::function; |
||||
} |
||||
}; |
||||
|
||||
struct userdata { |
||||
static auto type() { |
||||
return types::type::userdata; |
||||
} |
||||
}; |
||||
|
||||
struct thread { |
||||
static auto type() { |
||||
return types::type::thread; |
||||
} |
||||
}; |
||||
|
||||
struct table { |
||||
int value; |
||||
explicit table(int value) |
||||
:value(value) { }; |
||||
static auto type() { |
||||
return types::type::table; |
||||
} |
||||
}; |
||||
|
||||
template<typename T> |
||||
concept String = std::is_same<T, string>::value; |
||||
|
||||
template<typename T> |
||||
concept Number = std::is_same<T, number>::value; |
||||
|
||||
template<typename T> |
||||
concept Integer = std::is_same<T, integer>::value; |
||||
|
||||
template<typename T> |
||||
concept Table = std::is_same<T, table>::value; |
||||
|
||||
template<typename T> |
||||
concept Boolean = std::is_same<T, boolean>::value; |
||||
|
||||
template<typename T> |
||||
concept Type = String<T> || Number<T> || Integer<T> || Boolean<T> || Table<T>; |
||||
|
||||
namespace cpp { |
||||
template<typename T> |
||||
concept String = std::is_same<T, std::string>::value; |
||||
|
||||
template<typename T> |
||||
concept Number = std::is_same<T, double>::value; |
||||
|
||||
template<typename T> |
||||
concept Integer = std::is_same<T, int>::value; |
||||
|
||||
template<typename T> |
||||
concept Boolean = std::is_same<T, bool>::value; |
||||
|
||||
template<typename T> |
||||
concept Type = cpp::String<T> || cpp::Number<T> || cpp::Integer<T> || cpp::Boolean<T>; |
||||
} |
||||
|
||||
namespace any { |
||||
template<typename T> |
||||
concept String = cpp::String<T> || String<T>; |
||||
|
||||
template<typename T> |
||||
concept Integer = cpp::Integer<T> || Integer<T>; |
||||
|
||||
template<typename T> |
||||
concept Number = cpp::Number<T> || Number<T>; |
||||
|
||||
template<typename T> |
||||
concept Boolean = cpp::Boolean<T> || Boolean<T>; |
||||
|
||||
template<typename T> |
||||
concept Type = cpp::Type<T> || Type<T>; |
||||
} |
||||
|
||||
template<Type T> |
||||
auto& operator<<(std::ostream& os, const T& t) { |
||||
os << t.value; |
||||
return os; |
||||
} |
||||
using value = std::variant<nil, boolean, number, integer, string, function, userdata, thread, table>; |
||||
} |
||||
|
||||
#endif //KST_DISNOMIA_TYPES_HPP
|
@ -0,0 +1,61 @@
|
||||
#pragma once |
||||
#include <string> |
||||
#include <map> |
||||
|
||||
#include <kst/dsn/lib/lua.hpp> |
||||
|
||||
namespace kst::dsn { |
||||
class value; |
||||
namespace types { |
||||
template<typename CppType, const std::string* TypeName, typename SelfType> |
||||
class base_type { |
||||
protected: |
||||
CppType _value; |
||||
public: |
||||
constexpr static const std::string* type_name = TypeName; |
||||
explicit base_type(CppType value) |
||||
: _value{ value } { } |
||||
|
||||
operator CppType() { |
||||
return _value; |
||||
} |
||||
|
||||
auto operator<=>(SelfType v) { |
||||
if constexpr(std::is_same_v<CppType, nullptr_t> || std::is_same_v<CppType, lua_CFunction>) |
||||
return std::partial_ordering::equivalent; |
||||
else if constexpr (std::is_same_v<std::map<value,value>,CppType>) |
||||
return std::partial_ordering::equivalent; |
||||
else |
||||
return _value<=>v._value; |
||||
} |
||||
|
||||
auto operator==(types::cpp::Any auto& v) { |
||||
if constexpr(std::is_convertible_v<typeof(v), CppType> && !std::is_null_pointer_v<typeof(v)> |
||||
&& !std::is_same_v<bool, CppType>) |
||||
return _value==v; |
||||
return false; |
||||
} |
||||
|
||||
auto operator==(const SelfType& v) { |
||||
return _value==v._value; |
||||
} |
||||
|
||||
auto operator==(const CppType& v) { |
||||
return _value==v; |
||||
} |
||||
|
||||
auto operator==(SelfType& v) { |
||||
return _value==v._value; |
||||
} |
||||
|
||||
auto operator==(CppType& v) { |
||||
return _value==v; |
||||
} |
||||
|
||||
friend std::ostream& operator<<(std::ostream& output, const SelfType& v) { |
||||
return output << v._value; |
||||
} |
||||
friend class dsn::value; |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
#pragma once |
||||
#include <concepts> |
||||
#include <string> |
||||
|
||||
namespace kst::dsn::types::cpp { |
||||
template<typename T> |
||||
concept String = std::is_same_v<T, std::string> || std::is_same_v<T, const char*>; |
||||
|
||||
template<typename T> |
||||
concept Number = std::floating_point<T>; |
||||
|
||||
template<typename T> |
||||
concept Integer = std::integral<T>; |
||||
|
||||
template<typename T> |
||||
concept Boolean = std::is_same_v<T, bool>; |
||||
|
||||
template<typename T> |
||||
concept Function = std::is_function_v<T>; |
||||
|
||||
template<typename T> |
||||
concept Null = std::is_void_v<T> || std::is_null_pointer_v<T>; |
||||
|
||||
template<typename T> |
||||
concept Any = cpp::String<T> || cpp::Number<T> || cpp::Integer<T> || cpp::Boolean<T> || cpp::Function<T> |
||||
|| cpp::Null<T>; |
||||
} |
@ -0,0 +1,61 @@
|
||||
#pragma once |
||||
#include <concepts> |
||||
#include <variant> |
||||
|
||||
#include <kst/dsn/types/concepts/cpp.hpp> |
||||
|
||||
namespace kst::dsn { |
||||
class string; |
||||
class number; |
||||
class integer; |
||||
class boolean; |
||||
class table; |
||||
class nil; |
||||
class function; |
||||
|
||||
using variant_t = std::variant<nil, boolean, number, integer, string, table, function>; |
||||
using variant_cpp = std::variant<bool, LUA_NUMBER, LUA_INTEGER, std::string>; |
||||
|
||||
namespace types { |
||||
template<typename T> |
||||
concept String = std::is_same<T, string>::value; |
||||
|
||||
template<typename T> |
||||
concept Number = std::is_same<T, number>::value; |
||||
|
||||
template<typename T> |
||||
concept Integer = std::is_same<T, integer>::value; |
||||
|
||||
template<typename T> |
||||
concept Boolean = std::is_same<T, boolean>::value; |
||||
|
||||
template<typename T> |
||||
concept Table = std::is_same<T, table>::value; |
||||
|
||||
template<typename T> |
||||
concept Null = std::is_same<T, nil>::value; |
||||
|
||||
template<typename T> |
||||
concept Function = std::is_same<T, function>::value; |
||||
|
||||
template<typename T> |
||||
concept Any = String<T> || Number<T> || Integer<T> || Boolean<T> || Table<T> || Null<T> || Function<T>; |
||||
|
||||
namespace all { |
||||
template<typename T> |
||||
concept String = cpp::String<T> || String<T>; |
||||
|
||||
template<typename T> |
||||
concept Integer = cpp::Integer<T> || Integer<T>; |
||||
|
||||
template<typename T> |
||||
concept Number = cpp::Number<T> || Number<T>; |
||||
|
||||
template<typename T> |
||||
concept Boolean = cpp::Boolean<T> || Boolean<T>; |
||||
|
||||
template<typename T> |
||||
concept Any = cpp::Any<T> || Any<T>; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
#pragma once |
||||
|
||||
#include <kst/dsn/types/concepts/dsn.hpp> |
||||
|
||||
namespace kst::dsn { |
||||
namespace states { |
||||
class context; |
||||
} |
||||
namespace types { |
||||
template<types::all::Any Ret, types::all::Any...ATypes> |
||||
using DisnomiaFunction = Ret (*)(ATypes...); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
#pragma once |
||||
#include <map> |
||||
|
||||
#include <kst/dsn/types/type_names.hpp> |
||||
#include <kst/dsn/types/base_type.hpp> |
||||
#include <kst/dsn/types/concepts/dsn.hpp> |
||||
#include <kst/dsn/lib/lua.hpp> |
||||
|
||||
namespace kst::dsn { |
||||
class value; |
||||
class function : public types::base_type<lua_CFunction, &type_names::function, function> { |
||||
int _closurec{}; |
||||
int _argc{}; |
||||
states::base _state; |
||||
std::string _name{}; |
||||
public: |
||||
function(states::base& state, lua_CFunction value) |
||||
:base_type(value),_state(state) { } |
||||
|
||||
function(states::base& state,lua_CFunction value, int n, int a) |
||||
:base_type(value), _closurec(n), _argc(a), _state(state) { } |
||||
|
||||
friend void states::base::push(function& t); |
||||
|
||||
template<types::all::Any...ATypes> |
||||
value operator()(ATypes...args); |
||||
}; |
||||
|
||||
void states::base::push(function& f) { |
||||
lua_pushcclosure(_state, f._value, f._closurec); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,31 @@
|
||||
#pragma once |
||||
#include <map> |
||||
#include <any> |
||||
|
||||
#include <kst/dsn/types/type_names.hpp> |
||||
#include <kst/dsn/types/base_type.hpp> |
||||
#include <kst/dsn/lib/lua.hpp> |
||||
#include <kst/dsn/states/base.hpp> |
||||
|
||||
namespace kst::dsn { |
||||
class value; |
||||
class table : public types::base_type<std::map<value, dsn::value>, &type_names::table, table> { |
||||
std::optional<variant_cpp> _id{}; |
||||
states::base _state; |
||||
public: |
||||
table(states::base& state,variant_cpp& id); |
||||
|
||||
dsn::value& operator[](variant_cpp & v); |
||||
|
||||
friend void states::base::push(table& t); |
||||
friend std::ostream& operator<<(std::ostream& output, table& v) { |
||||
return output << "dsn::table[" << &v << "]"; |
||||
} |
||||
friend class value; |
||||
}; |
||||
|
||||
void states::base::push(table& t) { |
||||
get_field(LUA_RIDX_GLOBALS,LUA_REGISTRYINDEX); |
||||
get_field(*t._id,-1); |
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
#pragma once |
||||
#include <string> |
||||
|
||||
namespace kst::dsn { |
||||
namespace type_names { |
||||
const std::string nil = "nil"; |
||||
const std::string boolean = "boolean"; |
||||
const std::string number = "number"; |
||||
const std::string integer = "integer"; |
||||
const std::string string = "string"; |
||||
const std::string function = "function"; |
||||
const std::string userdata = "userdata"; |
||||
const std::string thread = "thread"; |
||||
const std::string table = "table"; |
||||
}; |
||||
} |
@ -0,0 +1,39 @@
|
||||
#pragma once |
||||
#include <variant> |
||||
#include <string> |
||||
#include <functional> |
||||
|
||||
#include <kst/dsn/types/base_type.hpp> |
||||
#include <kst/dsn/types/type_names.hpp> |
||||
|
||||
namespace kst::dsn { |
||||
class nil : public types::base_type<nullptr_t, &type_names::nil, nil> { |
||||
public: |
||||
nil() |
||||
:base_type(nullptr) { } |
||||
}; |
||||
|
||||
class boolean : public types::base_type<bool, &type_names::boolean, boolean> { |
||||
public: |
||||
boolean(bool value) |
||||
:base_type(value) { } |
||||
}; |
||||
|
||||
class number : public types::base_type<LUA_NUMBER, &type_names::number, number> { |
||||
public: |
||||
number(double value) |
||||
:base_type(value) { } |
||||
}; |
||||
|
||||
class integer : public types::base_type<LUA_INTEGER, &type_names::integer, integer> { |
||||
public: |
||||
integer( LUA_INTEGER value) |
||||
:base_type(value) { } |
||||
}; |
||||
|
||||
class string : public types::base_type<std::string, &type_names::string, string> { |
||||
public: |
||||
string(const std::string& value) |
||||
:base_type(value) {} |
||||
}; |
||||
} |
@ -0,0 +1,324 @@
|
||||
#pragma once |
||||
|
||||
#include <variant> |
||||
#include <optional> |
||||
#include <iostream> |
||||
|
||||
#include <kst/dsn/types/concepts/functions.hpp> |
||||
#include <kst/dsn/types/types.hpp> |
||||
#include <kst/dsn/types/table.hpp> |
||||
#include <kst/dsn/types/function.hpp> |
||||
#include <kst/dsn/states/base.hpp> |
||||
|
||||
#include <memory> |
||||
|
||||
|
||||
namespace kst::dsn { |
||||
class value { |
||||
states::base _base{ nullptr }; |
||||
variant_t _variant{ dsn::nil() }; |
||||
std::optional<variant_cpp> _name; |
||||
std::optional<table> _parent; |
||||
public: |
||||
friend class table; |
||||
friend class state; |
||||
|
||||
value(const states::base& base, dsn::types::Any auto v) |
||||
:_base(base), _variant(v) { } |
||||
|
||||
explicit value(const states::base& base) |
||||
:_base(base), _variant(nil()) { } |
||||
|
||||
value(const value& v) = default; |
||||
|
||||
value() = default; |
||||
|
||||
value(lua_State* state, const std::string& name) |
||||
:_base(state), _variant(nil()), _name(name) { } |
||||
|
||||
template<types::Any T> |
||||
auto& operator=(T v) { |
||||
if (_name) |
||||
{ |
||||
bool set = false; |
||||
if constexpr(types::Table<T>){ |
||||
set = true; |
||||
_base.push(v); |
||||
} |
||||
else if constexpr(types::Function<T>) |
||||
{ |
||||
if (v._value!=nullptr) |
||||
{ |
||||
set = true; |
||||
_base.push(v); |
||||
} |
||||
} else { |
||||
set = true; |
||||
_base.push(v); |
||||
} |
||||
|
||||
if (_parent && set) |
||||
{ |
||||
_base.push(*_parent); |
||||
lua_rotate(_base, -2, 1); |
||||
_base.set_field(*_name, -2); |
||||
lua_pop(_base, 1); |
||||
} |
||||
else if(set){ |
||||
_base.set_global(*_name); |
||||
} |
||||
|
||||
} |
||||
|
||||
_variant = v; |
||||
return *this; |
||||
} |
||||
|
||||
auto& operator=(std::integral auto value) { |
||||
*this = integer(value); |
||||
return *this; |
||||
} |
||||
|
||||
auto& operator=(bool value) { |
||||
*this = boolean(value); |
||||
return *this; |
||||
} |
||||
|
||||
auto& operator=(const std::string& value) { |
||||
*this = string(value); |
||||
return *this; |
||||
} |
||||
|
||||
auto& operator=(const char* value) { |
||||
*this = string(value); |
||||
return *this; |
||||
} |
||||
|
||||
template<dsn::types::Any T> |
||||
operator T() { |
||||
try |
||||
{ |
||||
return std::get<T>(_variant); |
||||
} |
||||
catch (std::bad_variant_access& e) |
||||
{ |
||||
std::string type; |
||||
std::visit([&type](auto arg) |
||||
{ |
||||
type = *arg.type_name; |
||||
}, _variant); |
||||
throw std::runtime_error("Can't convert value of type <"+type+"> to <"+*T::type_name+">"); |
||||
} |
||||
} |
||||
|
||||
template<types::all::Any...ATypes> |
||||
auto operator()(ATypes... args) { |
||||
function* f = std::get_if<function>(&_variant); |
||||
if (auto& fn = *f; f) |
||||
{ |
||||
_base.get_global(*_name); |
||||
return fn(args...); |
||||
} |
||||
throw std::runtime_error("Cannot call non function value"); |
||||
} |
||||
|
||||
template<typename T, types::all::Any...Args> |
||||
auto& operator=(types::DisnomiaFunction<T, Args...> fn) { |
||||
lua_pushlightuserdata(_base, reinterpret_cast<void*>(fn)); |
||||
auto lua_function = [](lua_State* s) -> int |
||||
{ |
||||
auto ctx = states::context(s, sizeof...(Args)); |
||||
ctx.validate_argc(); |
||||
|
||||
int argc = 0; |
||||
(ctx.validate_type<Args>(++argc), ...); |
||||
auto fn = ctx.get_closure<types::DisnomiaFunction<T, Args...>>(); |
||||
if constexpr(std::is_void_v<T>) |
||||
{ |
||||
fn(ctx.get<Args>(argc--)...); |
||||
return 0; |
||||
} |
||||
else |
||||
{ |
||||
auto res = fn(ctx.get<Args>(argc--)...); |
||||
return ctx.return_arg(res); |
||||
} |
||||
}; |
||||
int argc; |
||||
if constexpr(std::is_void_v<T>) |
||||
argc = 0; |
||||
else if (types::all::Any<T>) |
||||
argc = 1; |
||||
*this = function(_base, lua_function, 1, argc); |
||||
return *this; |
||||
} |
||||
|
||||
template<std::integral T> |
||||
operator T() { |
||||
return std::get<integer>(_variant); |
||||
} |
||||
|
||||
auto& operator[](variant_cpp id) { |
||||
table* t = std::get_if<table>(&_variant); |
||||
if (auto& tb = *t; t) |
||||
{ |
||||
_base.push(tb); |
||||
std::visit([this](auto& arg) |
||||
{ |
||||
_base.push(arg); |
||||
}, id); |
||||
|
||||
return tb[id]; |
||||
} |
||||
throw std::runtime_error("Cannot index non table value"); |
||||
} |
||||
|
||||
bool operator==(auto v) { |
||||
bool res; |
||||
std::visit([&res, &v](auto arg) |
||||
{ |
||||
res = arg==v; |
||||
}, _variant); |
||||
return res; |
||||
} |
||||
|
||||
auto operator<=>(value v) { |
||||
auto res = std::partial_ordering::equivalent; |
||||
std::visit([&res, &v](auto arg) |
||||
{ |
||||
res = arg<=>v; |
||||