Browse Source

Initial commit

master
czar 6 months ago
commit
6fca434525
Signed by: czar
GPG Key ID: 2DBA9558E9277C37
  1. 22
      CMakeLists.txt
  2. 9
      COPYING
  3. 11
      README.org
  4. 4
      includes/kst/disnomia.hpp
  5. 4
      includes/kst/dsn/lua.hpp
  6. 126
      includes/kst/dsn/state.hpp
  7. 135
      includes/kst/dsn/states/base.hpp
  8. 118
      includes/kst/dsn/states/context.hpp
  9. 11
      includes/kst/dsn/status.hpp
  10. 150
      includes/kst/dsn/types.hpp

22
CMakeLists.txt

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.20)
set(CMAKE_CXX_STANDARD 20)
project(kst_disnomia)
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
includes/kst/dsn/states/base.hpp
includes/kst/dsn/states/context.hpp
)
set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(${PROJECT_NAME} PUBLIC includes/)
target_link_libraries(${PROJECT_NAME} lua)

9
COPYING

@ -0,0 +1,9 @@
Discordian Public License (DPL)
All Rights Reversed Ⓚ 3187 czar <czar@kalli.st>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

11
README.org

@ -0,0 +1,11 @@
#+title: DISNOMIA
#+author: [k-] czar
#+email: czar@kalli.st
#+options: toc:nil
C++ Lua wrapper.
* License
[[file:COPYING][Discordian Public License]]
All Rights Reversed Ⓚ

4
includes/kst/disnomia.hpp

@ -0,0 +1,4 @@
#ifndef KST_DISNOMIA_HPP
#define KST_DISNOMIA_HPP
#include "dsn/state.hpp"
#endif //KST_DISNOMIA_HPP

4
includes/kst/dsn/lua.hpp

@ -0,0 +1,4 @@
#ifndef KST_DISNOMIA_LUA_HPP
#define KST_DISNOMIA_LUA_HPP
#include <lua5.3/lua.hpp>
#endif //KST_DISNOMIA_LUA_HPP

126
includes/kst/dsn/state.hpp

@ -0,0 +1,126 @@
#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

135
includes/kst/dsn/states/base.hpp

@ -0,0 +1,135 @@
#ifndef KST_DISNOMIA_STATES_BASE_HPP
#define KST_DISNOMIA_STATES_BASE_HPP
#include "../lua.hpp"
#include "../types.hpp"
namespace kst::dsn::states {
class base {
protected:
lua_State* _state;
explicit base(lua_State* state)
:_state(state) { }
public:
void push(bool x) {
lua_pushboolean(_state, x);
}
void push(std::integral auto x) {
lua_pushinteger(_state, lua_Integer(x));
}
void push(std::floating_point auto x) {
lua_pushnumber(_state, lua_Number(x));
}
void push(char const* x) {
lua_pushstring(_state, x);
}
template<typename...Args>
void push_args(Args...args) {
(push(args), ...);
}
template<types::Type T>
auto get_field(types::table& t, const char* key) {
lua_getfield(_state, t.value, key);
auto field = get_type<T>(-1);
return field;
}
template<types::Type T>
auto get_value(types::table& t, const char* key) {
lua_getfield(_state, t.value, key);
auto value = get_value<T>(-1);
return value;
}
template<types::Type T>
auto get_field(int index, const char* key) {
lua_getfield(_state, index, key);
auto field = get_type<T>(-1);
return field;
}
types::value get_any(int index) {
switch (lua_type(_state, index))
{
case LUA_TSTRING:
return types::string(lua_tostring(_state, index));
case LUA_TNUMBER:
if (lua_isinteger(_state, index))
return types::integer(lua_tointeger(_state, index));
return types::number(lua_tonumber(_state, index));
case LUA_TBOOLEAN:
return types::boolean(lua_toboolean(_state, index));
case LUA_TTABLE:
return types::table(index);
default:
return types::nil();
}
}
template<types::Type T>
auto get_value(const types::value& v) {
return std::get<T>(v).value;
}
template<types::any::String T>
auto get_type(int index) {
return T(lua_tostring(_state, index));
}
template<types::any::Boolean T>
auto get_type(int index) {
return T(lua_toboolean(_state, index));
}
template<types::Table T>
auto get_type(int index) {
return T(lua_absindex(_state, index));
}
template<types::any::Number T>
auto get_type(int index) {
return T(lua_tonumber(_state, index));
}
template<types::any::Integer T>
auto get_type(int index) {
return T(lua_tointeger(_state, index));
}
template<types::cpp::Integer T>
auto get_value(int index) {
return T(lua_tointeger(_state, index));
}
template<types::cpp::Number T>
auto get_value(int index) {
return T(lua_tonumber(_state, index));
}
template<types::cpp::String T>
auto get_value(int index) {
return T(lua_tostring(_state, index));
}
template<types::cpp::Boolean T>
auto get_value(int index) {
return T(lua_toboolean(_state, index));
}
template<types::Type T>
auto get_value(int index) {
return get_type<T>(index).value;
}
template<types::Type T>
auto get_type(const types::value& v) {
return std::get<T>(v);
}
};
}
#endif //KST_DISNOMIA_STATES_BASE_HPP

118
includes/kst/dsn/states/context.hpp

@ -0,0 +1,118 @@
#ifndef KST_DISNOMIA_STATES_CONTEXT_HPP
#define KST_DISNOMIA_STATES_CONTEXT_HPP
#include "base.hpp"
namespace kst::dsn::states {
class context : public states::base { ;
int _argc;
int _return_argc = 0;
int _error_c = 0;
public:
explicit context(lua_State* state, int argc)
:base(state), _argc(argc) { }
template<typename T>
void return_arg(T arg) {
++_return_argc;
push(arg);
}
auto get_argc() {
return _argc;
}
auto validate_argc() {
if (_argc!=lua_gettop(_state))
return luaL_error(_state, "Disnomia: wrong number of arguments to function call: required %d", _argc);
}
template<typename T>
auto get_closure(int index = 1) {
return reinterpret_cast<T>(lua_touserdata(_state, lua_upvalueindex(index)));
}
template<typename...Args>
void return_args(Args...args) {
(return_arg(args), ...);
}
[[nodiscard]] auto get_return_argc() const {
return _return_argc;
};
template<types::any::String>
auto validate_type(int index) {
if (!lua_isstring(_state, index))
_error_c = luaL_error(_state, "Disnomia -> wrong type: expected string");
}
template<types::Table>
auto validate_type(int index) {
if (!lua_istable(_state, index))
_error_c = luaL_error(_state, "Disnomia -> wrong type: expected table");
}
template<types::any::Number>
auto validate_type(int index) {
if (!lua_isnumber(_state, index))
_error_c = luaL_error(_state, "Disnomia -> wrong type: expected number");
}
template<types::any::Integer>
auto validate_type(int index) {
if (!lua_isinteger(_state, index))
_error_c = luaL_error(_state, "Disnomia -> wrong type: expected integer");
}
template<types::any::Boolean>
auto validate_type(int index) {
if (!lua_isinteger(_state, index))
_error_c = luaL_error(_state, "Disnomia -> wrong type: expected boolean");
}
template<types::Type T>
auto validate(int index) {
validate_type<T>(index);
return _error_c;
}
template<types::Type T>
auto get_opt_field(types::table& t, const char* key) {
if (!validate<types::table>(t.value))
{
lua_getfield(_state, t.value, key);
if (!validate<T>(-1))
return std::make_optional(get_type<T>(-1));
}
};
template<types::Type T>
auto get_opt_type(int index) {
if (!validate<T>(index))
return std::make_optional(get_type<T>(index));
};
template<types::Type T>
auto get_opt_value(types::table& t, const char* key) {
if (!validate<types::table>(t.value))
{
lua_getfield(_state, t.value, key);
if (!validate<T>(-1))
return std::make_optional(get_value<T>(-1));
}
};
template<types::Type T>
auto get_opt_value(int index) {
if (!validate<T>(index))
return std::make_optional(get_value<T>(index));
};
[[nodiscard]] auto get_error_c() const {
return _error_c;
}
};
}
#endif //KST_DISNOMIA_STATES_CONTEXT_HPP

11
includes/kst/dsn/status.hpp

@ -0,0 +1,11 @@
#ifndef KST_DISNOMIA_STATUS_HPP
#define KST_DISNOMIA_STATUS_HPP
namespace kst::dsn {
enum class status {
okay,
error,
};
}
#endif //KST_DISNOMIA_STATUS_HPP

150
includes/kst/dsn/types.hpp

@ -0,0 +1,150 @@
#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
Loading…
Cancel
Save