Move public headers to a separate directory, make a library
This commit is contained in:
parent
7252a6e1ec
commit
0f0d149ad2
15 changed files with 22 additions and 11 deletions
|
@ -1,5 +1,5 @@
|
|||
#include "wren/vm_fun.hpp"
|
||||
#include "wren/def_configuration.hpp"
|
||||
#include "wrenpp/vm_fun.hpp"
|
||||
#include "wrenpp/def_configuration.hpp"
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "configuration.hpp"
|
||||
#include "wrenpp/configuration.hpp"
|
||||
#include <wren.hpp>
|
||||
|
||||
namespace wren {
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace wren {
|
||||
class Configuration {
|
||||
public:
|
||||
Configuration();
|
||||
~Configuration() noexcept = default;
|
||||
|
||||
std::size_t initial_heap_size() const { return m_initial_heap_size; }
|
||||
void set_initial_heap_size(std::size_t v) { m_initial_heap_size = v; }
|
||||
|
||||
std::size_t min_heap_size() const { return m_min_heap_size; }
|
||||
void set_min_heap_size(std::size_t v) { m_min_heap_size = v; }
|
||||
|
||||
std::size_t heap_growth_percent() const { return m_heap_growth_percent; }
|
||||
void set_heap_growth_percent(std::size_t v) { m_heap_growth_percent = v; }
|
||||
|
||||
private:
|
||||
std::size_t m_initial_heap_size;
|
||||
std::size_t m_min_heap_size;
|
||||
std::size_t m_heap_growth_percent;
|
||||
};
|
||||
} //namespace wren
|
|
@ -1,4 +1,4 @@
|
|||
#include "def_configuration.hpp"
|
||||
#include "wrenpp/def_configuration.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace wren {
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "configuration.hpp"
|
||||
#include "error_type.hpp"
|
||||
|
||||
namespace wren {
|
||||
class VM;
|
||||
|
||||
typedef void(*foreign_method_t)(VM*);
|
||||
|
||||
class DefConfiguration : public Configuration {
|
||||
public:
|
||||
static void write_fn (VM*, const char* text);
|
||||
static void error_fn (VM*, ErrorType, const char* module, int line, const char* msg);
|
||||
foreign_method_t foreign_method_fn (VM* vm, const char* module, const char* class_name, bool is_static, const char* signature);
|
||||
};
|
||||
} //namespace wren
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace wren {
|
||||
enum class ErrorType {
|
||||
// A syntax or resolution error detected at compile time.
|
||||
Compile,
|
||||
|
||||
// The error message for a runtime error.
|
||||
Runtime,
|
||||
|
||||
// One entry of a runtime error's stack trace.
|
||||
StackTrace
|
||||
};
|
||||
} //namespace wren
|
|
@ -1,5 +1,5 @@
|
|||
#include "handle.hpp"
|
||||
#include "vm.hpp"
|
||||
#include "wrenpp/handle.hpp"
|
||||
#include "wrenpp/vm.hpp"
|
||||
#include <cassert>
|
||||
|
||||
namespace wren {
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct WrenHandle WrenHandle;
|
||||
|
||||
namespace wren {
|
||||
class VM;
|
||||
|
||||
class Handle {
|
||||
public:
|
||||
Handle() noexcept;
|
||||
Handle (const Handle&) = delete;
|
||||
Handle (Handle&& other) noexcept;
|
||||
Handle (VM* vm, WrenHandle* handle) noexcept :
|
||||
m_handle(handle),
|
||||
m_vm(vm)
|
||||
{
|
||||
}
|
||||
|
||||
Handle& operator= (const Handle&) = delete;
|
||||
Handle& operator= (Handle&& other) noexcept;
|
||||
|
||||
~Handle() noexcept;
|
||||
void release() noexcept;
|
||||
|
||||
operator WrenHandle*() const { return m_handle; }
|
||||
operator bool() const { return nullptr != m_handle; }
|
||||
|
||||
private:
|
||||
WrenHandle* m_handle;
|
||||
VM* m_vm;
|
||||
};
|
||||
|
||||
inline Handle::Handle() noexcept :
|
||||
m_handle(nullptr),
|
||||
m_vm(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
inline Handle::Handle (Handle&& other) noexcept :
|
||||
m_handle(other.m_handle),
|
||||
m_vm(other.m_vm)
|
||||
{
|
||||
other.m_handle = nullptr;
|
||||
other.m_vm = nullptr;
|
||||
}
|
||||
|
||||
inline Handle& Handle::operator= (Handle&& other) noexcept {
|
||||
{
|
||||
auto tmp = other.m_handle;
|
||||
other.m_handle = m_handle;
|
||||
m_handle = tmp;
|
||||
}
|
||||
{
|
||||
auto tmp = other.m_vm;
|
||||
other.m_vm = m_vm;
|
||||
m_vm = tmp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
} //namespace wren
|
|
@ -1,53 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
//see https://stackoverflow.com/a/10707822
|
||||
#define define_method_info(method_name, pretty_name, ret_type, ...) \
|
||||
class method_ ## pretty_name { \
|
||||
typedef std::integral_constant<int, 0> no_method_t; \
|
||||
typedef std::integral_constant<int, 1> has_method_t; \
|
||||
typedef std::integral_constant<int, 2> has_static_method_t; \
|
||||
template<typename A, typename... Args> \
|
||||
static has_method_t test(ret_type (A::*)(Args...)) { \
|
||||
return {}; \
|
||||
} \
|
||||
template <typename A, typename... Args> \
|
||||
static has_static_method_t test(ret_type (*)(Args...)) { \
|
||||
return {}; \
|
||||
} \
|
||||
template <typename A, typename... Args> \
|
||||
static auto test(decltype(std::declval<A>().method_name(std::declval<Args>()...))*,void *) { \
|
||||
typedef decltype(test<A, Args...>(&A::method_name)) return_type; \
|
||||
return return_type{}; \
|
||||
} \
|
||||
template<typename A, typename... Args> \
|
||||
static no_method_t test(...) { \
|
||||
return {}; \
|
||||
} \
|
||||
public: \
|
||||
template< typename T> \
|
||||
class exists { \
|
||||
typedef decltype(test<T, __VA_ARGS__>(0,0)) found_t; \
|
||||
public: \
|
||||
static const constexpr bool value = (found_t::value != no_method_t::value); \
|
||||
}; \
|
||||
template <typename T> \
|
||||
class is_static { \
|
||||
typedef decltype(test<T, __VA_ARGS__>(0,0)) found_t; \
|
||||
public: \
|
||||
static const constexpr bool value = (found_t::value == has_static_method_t::value); \
|
||||
}; \
|
||||
template <typename T> struct static_ptr { \
|
||||
typedef ret_type (*type)(__VA_ARGS__); \
|
||||
}; \
|
||||
template <typename T> struct nonstatic_ptr { \
|
||||
typedef ret_type (T::*type)(__VA_ARGS__); \
|
||||
}; \
|
||||
template <typename T> struct ptr { \
|
||||
typedef typename std::conditional<is_static<T>::value, typename static_ptr<T>::type, typename std::conditional<exists<T>::value, typename nonstatic_ptr<T>::type, void>::type>::type type; \
|
||||
}; \
|
||||
}
|
||||
|
||||
namespace wren {
|
||||
} //namespace wren
|
|
@ -1,135 +0,0 @@
|
|||
/* Copyright 2016-2018 Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* "duckhandy" is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id170B0E6C34D14EBA9B92A35977BDBFB3
|
||||
#define id170B0E6C34D14EBA9B92A35977BDBFB3
|
||||
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace dhandy {
|
||||
namespace bt {
|
||||
template <std::size_t S, typename Ch=char>
|
||||
class string;
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
std::basic_ostream<Ch>& operator<< ( std::basic_ostream<Ch>& parStream, const string<S, Ch>& parString );
|
||||
|
||||
namespace implem {
|
||||
template <std::size_t S, typename Ch> constexpr bool eq (const string<S, Ch>& l, const string<S, Ch>& r);
|
||||
} //namespace implem
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
class string {
|
||||
friend std::ostream& operator<< <>( std::ostream& parStream, const string<S>& parString );
|
||||
friend constexpr bool implem::eq<S, Ch> (const string<S, Ch>&, const string<S, Ch>&);
|
||||
public:
|
||||
using value_type = Ch;
|
||||
constexpr string ( const value_type* parString );
|
||||
|
||||
constexpr std::size_t size ( void ) const { return S - 1; }
|
||||
template <std::size_t S2>
|
||||
constexpr string<S + S2 - 1, Ch> operator+ ( const string<S2, Ch>& parOther ) const;
|
||||
constexpr value_type operator[] ( std::size_t parIndex ) const;
|
||||
constexpr bool operator== (const string<S, Ch>& other) const;
|
||||
template <std::size_t Start, std::size_t Len=S-1> constexpr auto substr() const;
|
||||
template <std::size_t S2> constexpr bool operator== (const string<S2, Ch>&) const { return false; }
|
||||
|
||||
template <typename... Args>
|
||||
constexpr string ( Args... );
|
||||
|
||||
constexpr const value_type (&data_arr() const)[S] { return m_data; }
|
||||
constexpr const value_type* data() const { return m_data; }
|
||||
|
||||
private:
|
||||
template <std::size_t... I>
|
||||
constexpr string ( std::index_sequence<I...>, const value_type* parString );
|
||||
|
||||
const value_type m_data[S];
|
||||
};
|
||||
|
||||
namespace implem {
|
||||
template <std::size_t S, std::size_t S2, std::size_t... I>
|
||||
constexpr string<S + S2 - 1> concat ( std::index_sequence<I...>, const string<S>& parLeft, const string<S2>& parRight ) {
|
||||
return string<S + S2 - 1>(
|
||||
(I < S - 1 ? parLeft[I] : (I < S + S2 - 2 ? parRight[I - (S - 1)] : '\0'))...
|
||||
);
|
||||
}
|
||||
|
||||
template <> constexpr inline bool eq (const string<1>& l, const string<1>& r) { return l[0] == r[0]; }
|
||||
template <std::size_t S, typename Ch>
|
||||
constexpr inline bool eq (const string<S, Ch>& l, const string<S, Ch>& r) { return l[0] == r[0] and eq(string<S-1>(l.m_data+1), string<S-1>(r.m_data+1)); }
|
||||
} //namespace implem
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
template <std::size_t... I>
|
||||
constexpr string<S, Ch>::string (std::index_sequence<I...>, const value_type* parString) :
|
||||
m_data{parString[I]...}
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
inline constexpr string<S, Ch>::string (const value_type* parString) :
|
||||
string(std::make_index_sequence<S>(), parString)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
template <typename... Args>
|
||||
inline constexpr string<S, Ch>::string (Args... parArgs) :
|
||||
m_data{parArgs...}
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
template <std::size_t S2>
|
||||
constexpr inline string<S + S2 - 1, Ch> string<S, Ch>::operator+ (const string<S2, Ch>& parOther) const {
|
||||
return implem::concat(std::make_index_sequence<S + S2 - 1>(), string<S>(m_data), parOther);
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
inline std::ostream& operator<< (std::ostream& parStream, const string<S, Ch>& parString) {
|
||||
parStream << parString.m_data;
|
||||
return parStream;
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
constexpr auto string<S, Ch>::operator[] (std::size_t parIndex) const -> value_type {
|
||||
return (parIndex < S ? m_data[parIndex] : throw std::out_of_range(""));
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
constexpr string<S, Ch> make_string (const Ch (&parData)[S]) {
|
||||
return string<S>(parData);
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
constexpr bool string<S, Ch>::operator== (const string<S, Ch>& other) const {
|
||||
return implem::eq(*this, other);
|
||||
}
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
template <std::size_t Start, std::size_t Len>
|
||||
constexpr auto string<S, Ch>::substr() const {
|
||||
return string<std::min(S - 1 - std::min(Start, S - 1), Len) + 1, Ch>(m_data + std::min(Start, S - 1)) + make_string("");
|
||||
}
|
||||
} //namespace bt
|
||||
} //namespace dhandy
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#include "vm.hpp"
|
||||
#include "configuration.hpp"
|
||||
#include "wrenpp/vm.hpp"
|
||||
#include "wrenpp/configuration.hpp"
|
||||
#include "dynafunc_maker.hpp"
|
||||
#include <wren.hpp>
|
||||
#include <cassert>
|
||||
|
|
157
src/wren/vm.hpp
157
src/wren/vm.hpp
|
@ -1,157 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "has_method.hpp"
|
||||
#include "error_type.hpp"
|
||||
#include "handle.hpp"
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#if __cpp_concepts >= 201907
|
||||
# include <concepts>
|
||||
#endif
|
||||
|
||||
namespace wren {
|
||||
class Configuration;
|
||||
class VM;
|
||||
class DynafuncMaker;
|
||||
|
||||
typedef void(*foreign_method_t)(VM*);
|
||||
typedef void(*finalizer_t)(void*);
|
||||
|
||||
struct foreign_class_t {
|
||||
foreign_method_t allocate;
|
||||
finalizer_t finalize;
|
||||
};
|
||||
|
||||
enum class SlotType {
|
||||
Bool, Num, Foreign, List, Null, String, Unknown
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
struct Callbacks {
|
||||
void (*write_fn)(Configuration&, VM*, const char*) {nullptr};
|
||||
void (*error_fn)(Configuration&, VM*, ErrorType, const char*, int, const char*) {nullptr};
|
||||
void* (*reallocate_fn)(void*, std::size_t) {nullptr};
|
||||
const char* (*resolve_module_fn)(Configuration&, VM*, const char*, const char*) {nullptr};
|
||||
char* (*load_module_fn)(Configuration&, VM*, const char*) {nullptr};
|
||||
foreign_method_t (*foreign_method_fn)(Configuration&, VM*, const char*, const char*, bool, const char*);
|
||||
foreign_class_t (*foreign_class_fn)(Configuration&, VM*, const char*, const char*);
|
||||
|
||||
Configuration* config_obj {nullptr};
|
||||
VM* owner {nullptr};
|
||||
DynafuncMaker* dynafunc {nullptr};
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
class VM {
|
||||
public:
|
||||
template <typename T>
|
||||
VM (T* conf);
|
||||
VM (const VM&) = delete;
|
||||
VM (VM&& other) = default;
|
||||
~VM() noexcept;
|
||||
|
||||
void interpret (const char* module_name, const char* script);
|
||||
void call (const Handle& method);
|
||||
void release_handle (Handle& handle) noexcept;
|
||||
void ensure_slots(int num_slots);
|
||||
int slot_count();
|
||||
void variable(const char* module, const char* name, int slot);
|
||||
void set_slot_handle(const Handle& handle, int slot);
|
||||
SlotType slot_type(int slot_num);
|
||||
Handle slot_handle(int slot_num);
|
||||
Handle make_call_handle(const char* signature);
|
||||
|
||||
//slot setters
|
||||
void set_slot_string (int slot_num, const char* value);
|
||||
void set_slot_double (int slot_num, double value);
|
||||
void set_slot_bool (int slot_num, bool value);
|
||||
void set_slot_null (int slot_num);
|
||||
void set_slot_bytes (int slot_num, const char* bytes, std::size_t length);
|
||||
void* set_slot_new_foreign (int slot_num, int class_slot, std::size_t size);
|
||||
|
||||
//slot getters
|
||||
const char* slot_string (int slot_num);
|
||||
double slot_double (int slot_num);
|
||||
bool slot_bool (int slot_num);
|
||||
std::pair<const char*, int> slot_bytes (int slot_num);
|
||||
void* slot_foreign (int slot_num);
|
||||
|
||||
private:
|
||||
struct LocalData;
|
||||
|
||||
VM (Configuration* conf, const detail::Callbacks&);
|
||||
DynafuncMaker* dynafunc_maker();
|
||||
|
||||
template <typename T>
|
||||
detail::Callbacks to_callbacks (T& conf);
|
||||
|
||||
std::unique_ptr<LocalData> m_local;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
define_method_info(write_fn, write, void, VM*, const char*);
|
||||
define_method_info(error_fn, error, void, VM*, ErrorType, const char*, int, const char*);
|
||||
define_method_info(reallocate_fn, reallocate, void*, void*, std::size_t);
|
||||
define_method_info(resolve_module_fn, resolve_module, const char*, const char*, const char*);
|
||||
define_method_info(load_module_fn, load_module, char*, VM*, const char*);
|
||||
define_method_info(foreign_method_fn, foreign_method, foreign_method_t, VM*, const char*, const char*, bool, const char*);
|
||||
define_method_info(foreign_class_fn, foreign_class, foreign_class_t, VM*, const char*, const char*);
|
||||
|
||||
template <typename T, typename F> struct AnyFunctionWrap;
|
||||
template <typename T, typename R, typename... Args>
|
||||
struct AnyFunctionWrap<T, R(T::*)(Args...)> {
|
||||
template <R(T::*M)(Args...)>
|
||||
inline static R call(Configuration& obj, Args... args) {
|
||||
return (reinterpret_cast<T&>(obj).*M)(args...);
|
||||
}
|
||||
};
|
||||
template <typename T, typename R, typename... Args>
|
||||
struct AnyFunctionWrap<T, R(*)(Args...)> {
|
||||
template <R(*M)(Args...)>
|
||||
inline static R call(Configuration&, Args... args) {
|
||||
return (*M)(args...);
|
||||
}
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
template <typename T>
|
||||
inline detail::Callbacks VM::to_callbacks (T& conf) {
|
||||
using detail::method_reallocate;
|
||||
|
||||
detail::Callbacks ret;
|
||||
ret.config_obj = &conf;
|
||||
ret.owner = this;
|
||||
ret.dynafunc = nullptr;
|
||||
|
||||
if constexpr (detail::method_write::exists<T>::value)
|
||||
ret.write_fn = &detail::AnyFunctionWrap<T, decltype(&T::write_fn)>::template call<&T::write_fn>;
|
||||
|
||||
if constexpr (detail::method_error::exists<T>::value)
|
||||
ret.error_fn = &detail::AnyFunctionWrap<T, decltype(&T::error_fn)>::template call<&T::error_fn>;
|
||||
|
||||
if constexpr (method_reallocate::exists<T>::value and method_reallocate::is_static<T>::value)
|
||||
ret.reallocate_fn = &T::reallocate_fn;
|
||||
static_assert(not method_reallocate::exists<T>::value or method_reallocate::is_static<T>::value, "Realloc function must be a static function");
|
||||
|
||||
if constexpr (detail::method_resolve_module::exists<T>::value)
|
||||
ret.resolve_module_fn = &detail::AnyFunctionWrap<T, decltype(&T::resolve_module_fn)>::template call<&T::resolve_module_fn>;
|
||||
|
||||
if constexpr (detail::method_load_module::exists<T>::value)
|
||||
ret.load_module_fn = &detail::AnyFunctionWrap<T, decltype(&T::load_module_fn)>::template call<&T::load_module_fn>;
|
||||
|
||||
if constexpr (detail::method_foreign_method::exists<T>::value)
|
||||
ret.foreign_method_fn = &detail::AnyFunctionWrap<T, decltype(&T::foreign_method_fn)>::template call<&T::foreign_method_fn>;
|
||||
|
||||
if constexpr (detail::method_foreign_class::exists<T>::value)
|
||||
ret.foreign_class_fn = &detail::AnyFunctionWrap<T, decltype(&T::foreign_class_fn)>::template call<&T::foreign_class_fn>;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline VM::VM (T* conf) :
|
||||
VM(static_cast<Configuration*>(conf), to_callbacks(*conf))
|
||||
{
|
||||
}
|
||||
} //namespace wren
|
|
@ -1,4 +1,4 @@
|
|||
#include "vm_fun.hpp"
|
||||
#include "wrenpp/vm_fun.hpp"
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "vm.hpp"
|
||||
#include "string_bt.hpp"
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
namespace wren {
|
||||
typedef std::tuple<const char*, const char*> ModuleAndName;
|
||||
|
||||
namespace detail {
|
||||
#if __cpp_concepts >= 201907
|
||||
template <typename T>
|
||||
concept ConstCharTuple = requires {
|
||||
std::same_as<std::remove_cv_t<T>, Handle> or
|
||||
std::same_as<std::remove_cv_t<T>, ModuleAndName>;
|
||||
};
|
||||
#endif
|
||||
} //namespace detail
|
||||
|
||||
#if __cpp_concepts >= 201907
|
||||
template <typename... Outs, detail::ConstCharTuple... Params>
|
||||
#else
|
||||
template <typename... Outs, typename... Params>
|
||||
#endif
|
||||
std::tuple<Outs...> variables(VM& vm, Params&&... modules_names);
|
||||
|
||||
template <typename R, typename... Args>
|
||||
R call (VM& vm, const Handle& object, const Handle& method, const Args&... args);
|
||||
|
||||
template <typename R, typename... Args>
|
||||
R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args);
|
||||
|
||||
template <typename R, std::size_t N, typename... Args>
|
||||
R call (VM& vm, const ModuleAndName& object, const char (&method)[N], const Args&... args);
|
||||
|
||||
void interpret (VM& vm, const std::string& module_name, const std::string& script);
|
||||
void set (VM& vm, int slot_num, const char* value);
|
||||
void set (VM& vm, int slot_num, double value);
|
||||
void set (VM& vm, int slot_num, bool value);
|
||||
void set (VM& vm, int slot_num, std::nullptr_t);
|
||||
void set (VM& vm, int slot_num, const char* bytes, std::size_t length);
|
||||
void set (VM& vm, int slot_num, const std::string& value);
|
||||
void set (VM& vm, int slot_num, std::string_view value);
|
||||
void set (VM& vm, int slot_num, const std::vector<char>& value);
|
||||
void set (VM& vm, int slot_num, const char* beg, const char* end);
|
||||
void set (VM& vm, int slot_num, int value);
|
||||
std::string_view slot_string_view (VM& vm, int slot_num);
|
||||
template <typename T> T get (VM& vm, int slot_num);
|
||||
void variable(VM& vm, const ModuleAndName& mod_and_name, int slot);
|
||||
void variable(VM& vm, const Handle& handle, int slot);
|
||||
|
||||
namespace detail {
|
||||
#if __cpp_concepts >= 201907
|
||||
template <typename... Outs, int... Indices, ConstCharTuple... Params>
|
||||
#else
|
||||
template <typename... Outs, int... Indices, typename... Params>
|
||||
#endif
|
||||
inline std::tuple<Outs...> variables_impl (
|
||||
VM& vm,
|
||||
std::integer_sequence<int, Indices...>,
|
||||
Params&&... modules_names
|
||||
) {
|
||||
if constexpr (sizeof...(Outs) == 0) {
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
static_assert(sizeof...(Params) == sizeof...(Outs), "Expected a module/name pair per requested output");
|
||||
static_assert(sizeof...(Outs) == sizeof...(Indices), "Mismatching index count");
|
||||
|
||||
vm.ensure_slots(sizeof...(Params));
|
||||
(variable(vm, modules_names, Indices), ...);
|
||||
return std::tuple<Outs...>(get<Outs>(vm, Indices)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void set_single_for_call (VM& vm, int slot, const T& value) {
|
||||
set(vm, slot, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void set_single_for_call (VM& vm, int slot_num, const Handle& handle) {
|
||||
vm.set_slot_handle(handle, slot_num);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void set_single_for_call (VM& vm, int slot_num, const ModuleAndName& name) {
|
||||
variable(vm, name, slot_num);
|
||||
}
|
||||
|
||||
template <typename... Args, int... Indices>
|
||||
inline void set_for_call (std::integer_sequence<int, Indices...>, VM& vm, const Args&... args) {
|
||||
vm.ensure_slots(sizeof...(Args));
|
||||
(set_single_for_call(vm, Indices + 1, args), ...);
|
||||
}
|
||||
} //namespace detail
|
||||
|
||||
#if __cpp_concepts >= 201907
|
||||
template <typename... Outs, detail::ConstCharTuple... Params>
|
||||
#else
|
||||
template <typename... Outs, typename... Params>
|
||||
#endif
|
||||
inline std::tuple<Outs...> variables(VM& vm, Params&&... modules_names) {
|
||||
return detail::variables_impl<Outs...>(vm, std::make_integer_sequence<int, sizeof...(Outs)>(), std::forward<Params>(modules_names)...);
|
||||
}
|
||||
|
||||
inline void interpret (VM& vm, const std::string& module_name, const std::string& script) {
|
||||
return vm.interpret(module_name.c_str(), script.c_str());
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const char* value) {
|
||||
vm.set_slot_string(slot_num, value);
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, double value) {
|
||||
vm.set_slot_double(slot_num, value);
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, bool value) {
|
||||
vm.set_slot_bool(slot_num, value);
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, std::nullptr_t) {
|
||||
vm.set_slot_null(slot_num);
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const char* bytes, std::size_t length) {
|
||||
vm.set_slot_bytes(slot_num, bytes, length);
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const std::string& value) {
|
||||
vm.set_slot_string(slot_num, value.c_str());
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, std::string_view value) {
|
||||
vm.set_slot_bytes(slot_num, value.data(), value.size());
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const std::vector<char>& value) {
|
||||
vm.set_slot_bytes(slot_num, value.data(), value.size());
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, int value) {
|
||||
vm.set_slot_double(slot_num, static_cast<double>(value));
|
||||
}
|
||||
|
||||
template <typename R, typename... Args>
|
||||
inline R call (VM& vm, const Handle& object, const Handle& method, const Args&... args) {
|
||||
detail::set_for_call<Args...>(std::make_integer_sequence<int, sizeof...(Args)>(), vm, args...);
|
||||
vm.call(method);
|
||||
if constexpr (not std::is_same<void, R>::value) {
|
||||
return get<R>(vm, 0);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename R, typename... Args>
|
||||
inline R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args) {
|
||||
vm.ensure_slots(sizeof...(args) + 1);
|
||||
variable(vm, object, 0);
|
||||
Handle obj_handle = vm.slot_handle(0);
|
||||
return call<R, Args...>(vm, obj_handle, method, args...);
|
||||
}
|
||||
|
||||
template <typename R, std::size_t N, typename... Args>
|
||||
inline R call (VM& vm, const ModuleAndName& object, const char (&method)[N], const Args&... args) {
|
||||
const constexpr char dummy_name_buff[N] = {0};
|
||||
const constexpr auto params = dhandy::bt::string<N, char>(dummy_name_buff) +
|
||||
dhandy::bt::make_string("(") +
|
||||
((static_cast<void>(args), dhandy::bt::make_string(",_")) + ...).template substr<1>() +
|
||||
dhandy::bt::make_string(")");
|
||||
;
|
||||
char cat_buff[params.size() + 1];
|
||||
std::copy(method, method + N - 1, cat_buff);
|
||||
std::copy(params.data() + N - 1, params.data() + params.size() + 1, cat_buff + N - 1);
|
||||
return call<R, Args...>(vm, object, vm.make_call_handle(cat_buff), args...);
|
||||
}
|
||||
} //namespace wren
|
Loading…
Add table
Add a link
Reference in a new issue