mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
initial __type implementation, need to bikeshed over what goes in it and how to query information (sol::lib::extensions
time?)
fixed `sol::string_view` not pushing a string based on return type
This commit is contained in:
parent
a11e127d4d
commit
761641202f
|
@ -19,8 +19,10 @@ The examples folder also has a number of really great examples for you to see. T
|
|||
- If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object
|
||||
- ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``)
|
||||
- You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details
|
||||
* (Advanced) You can override the iteration function for Lua 5.2 and above (LuaJIT does not have the capability) `as shown in the pairs example`_
|
||||
* You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
|
||||
* You can work with special wrapper types such as ``std::unique_ptr<T>``, ``std::shared_ptr<T>``, and others by default
|
||||
- Extend them using the :doc:`sol::unique_usertype\<T\> traits<api/unique_usertype_traits>`
|
||||
* (Advanced) You can override the iteration function for Lua 5.2 and above (LuaJIT does not have the capability) `as shown in the pairs example`_
|
||||
* Please note that the colon is necessary to "automatically" pass the ``this``/``self`` argument to Lua methods
|
||||
- ``obj:method_name()`` is how you call "member" methods in Lua
|
||||
- It is purely syntactic sugar that passes the object name as the first argument to the ``method_name`` function
|
||||
|
@ -32,13 +34,13 @@ The examples folder also has a number of really great examples for you to see. T
|
|||
- You can retrieve a usertype from the Lua runtime at any time
|
||||
- Methods and properties will be added to the type only after you register the usertype with the Lua runtime
|
||||
- All methods and properties will appear on all userdata, even if that object was pushed before the usertype (all userdata will be updated)
|
||||
* Types either copy once or move once into the memory location, if it is a value type. If it is a pointer, we store only the reference.
|
||||
- This means retrieval of class types (not primitive types like strings or integers) by ``T&`` or ``T*`` allow you to modify the data in Lua directly.
|
||||
* Types either copy once or move once into the memory location, if it is a value type. If it is a pointer, we store only the reference
|
||||
- This means retrieval of class types (not primitive types like strings or integers) by ``T&`` or ``T*`` allow you to modify the data in Lua directly
|
||||
- Retrieve a plain ``T`` to get a copy
|
||||
- Return types and passing arguments to ``sol::function``-types use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`.
|
||||
* You can set ``index`` and ``new_index`` freely on any usertype you like to override the default "if a key is missing, find it / set it here" functionality of a specific object of a usertype.
|
||||
- ``new_index`` and ``index`` will not be called if you try to manipulate the named usertype table directly. sol2's will be called to add that function to the usertype's function/variable lookup table.
|
||||
- ``new_index`` and ``index`` will be called if you attempt to call a key that does not exist on an actual userdata object (the C++ object) itself.
|
||||
- Return types and passing arguments to ``sol::function``-types use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`
|
||||
* You can set ``index`` and ``new_index`` freely on any usertype you like to override the default "if a key is missing, find it / set it here" functionality of a specific object of a usertype
|
||||
- ``new_index`` and ``index`` will not be called if you try to manipulate the named usertype table directly. sol2's will be called to add that function to the usertype's function/variable lookup table
|
||||
- ``new_index`` and ``index`` will be called if you attempt to call a key that does not exist on an actual userdata object (the C++ object) itself
|
||||
- If you made a usertype named ``test``, this means ``t = test()``, with ``t.hi = 54`` will call your function, but ``test.hi = function () print ("hi"); end`` will instead set the key ``hi`` to to lookup that function for all ``test`` types
|
||||
* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems other than just sol2, making it easy to interop with select other Lua systems.
|
||||
* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly
|
||||
|
|
|
@ -302,8 +302,8 @@ namespace sol {
|
|||
};
|
||||
|
||||
template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
||||
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, clean_stack, C> {
|
||||
static int call(lua_State* L, lua_r_CFunction f) {
|
||||
struct agnostic_lua_call_wrapper<lua_CFunction_ref, is_index, is_variable, checked, boost, clean_stack, C> {
|
||||
static int call(lua_State* L, lua_CFunction_ref f) {
|
||||
return f(L);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -64,12 +64,33 @@ namespace sol {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename F = void>
|
||||
struct argument_handler {
|
||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
||||
return type_panic_string(L, index, expected, actual, message + " (bad argument to variable or function call)");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct argument_handler<types<R, Args...>> {
|
||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
||||
std::string addendum = " (bad argument to type expecting '";
|
||||
addendum += detail::demangle<R>();
|
||||
addendum += "(";
|
||||
int marker = 0;
|
||||
auto action = [&addendum, &marker](const std::string& n) {
|
||||
if (marker > 0) {
|
||||
addendum += ", ";
|
||||
}
|
||||
addendum += n;
|
||||
++marker;
|
||||
}
|
||||
(void)detail::swallow{ int(), (action(detail::demangle<Args>()), int())... };
|
||||
addendum += ")')";
|
||||
return type_panic_string(L, index, expected, actual, message + addendum);
|
||||
}
|
||||
};
|
||||
|
||||
// Specify this function as the handler for lua::check if you know there's nothing wrong
|
||||
inline int no_panic(lua_State*, int, type, type, const char* = nullptr) noexcept {
|
||||
return 0;
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace sol {
|
|||
void* baseclasscast;
|
||||
bool mustindex;
|
||||
bool secondarymeta;
|
||||
std::array<bool, 29> properties;
|
||||
std::array<bool, 30> properties;
|
||||
|
||||
template <typename N>
|
||||
void insert(N&& n, object&& o) {
|
||||
|
@ -415,6 +415,13 @@ namespace sol {
|
|||
auto& properties = umx.properties;
|
||||
auto sic = hasindex ? &usertype_detail::simple_index_call<T, true> : &usertype_detail::simple_index_call<T, false>;
|
||||
auto snic = hasnewindex ? &usertype_detail::simple_new_index_call<T, true> : &usertype_detail::simple_new_index_call<T, false>;
|
||||
|
||||
lua_createtable(L, 0, 2);
|
||||
stack_reference type_table(L, -1);
|
||||
|
||||
stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index());
|
||||
stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index());
|
||||
|
||||
auto register_kvp = [&](std::size_t meta_index, stack_reference& t, const std::string& first, object& second) {
|
||||
meta_function mf = meta_function::construct;
|
||||
for (std::size_t j = 1; j < properties.size(); ++j) {
|
||||
|
@ -469,6 +476,8 @@ namespace sol {
|
|||
}
|
||||
luaL_newmetatable(L, metakey);
|
||||
stack_reference t(L, -1);
|
||||
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||
|
||||
for (auto& kvp : varmap.functions) {
|
||||
auto& first = std::get<0>(kvp);
|
||||
auto& second = std::get<1>(kvp);
|
||||
|
@ -514,6 +523,7 @@ namespace sol {
|
|||
// for call constructor purposes and such
|
||||
lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid()));
|
||||
stack_reference metabehind(L, -1);
|
||||
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||
if (umx.callconstructfunc.valid()) {
|
||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||
}
|
||||
|
@ -538,6 +548,7 @@ namespace sol {
|
|||
// Now for the shim-table that actually gets pushed
|
||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
|
||||
stack_reference t(L, -1);
|
||||
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||
for (auto& kvp : varmap.functions) {
|
||||
auto& first = std::get<0>(kvp);
|
||||
auto& second = std::get<1>(kvp);
|
||||
|
@ -546,6 +557,7 @@ namespace sol {
|
|||
{
|
||||
lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid()));
|
||||
stack_reference metabehind(L, -1);
|
||||
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||
if (umx.callconstructfunc.valid()) {
|
||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||
}
|
||||
|
@ -570,6 +582,8 @@ namespace sol {
|
|||
metabehind.pop();
|
||||
}
|
||||
|
||||
lua_remove(L, type_table.stack_index());
|
||||
|
||||
// Don't pop the table when we're done;
|
||||
// return it
|
||||
return 1;
|
||||
|
|
|
@ -112,8 +112,8 @@ namespace sol {
|
|||
inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
#ifndef _MSC_VER
|
||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||
#endif // This compiler make me so fucking sad
|
||||
argument_handler handler{};
|
||||
#endif // This compiler make me so sad
|
||||
argument_handler<types<R, Args...>> handler{};
|
||||
multi_check<checkargs, Args...>(L, start, handler);
|
||||
record tracking{};
|
||||
return evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
|
@ -124,7 +124,7 @@ namespace sol {
|
|||
#ifndef _MSC_VER
|
||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||
#endif // This compiler make me so fucking sad
|
||||
argument_handler handler{};
|
||||
argument_handler<types<void, Args...>> handler{};
|
||||
multi_check<checkargs, Args...>(L, start, handler);
|
||||
record tracking{};
|
||||
evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
|
|
|
@ -880,7 +880,18 @@ namespace sol {
|
|||
return std::visit(stack_detail::push_function(L), std::move(v));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
template <>
|
||||
struct pusher<string_view> {
|
||||
static int push(lua_State* L, const std::string_view& sv) {
|
||||
return stack::push(L, sv.data(), sv.length());
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const std::string_view& sv, std::size_t len) {
|
||||
return stack::push(L, sv.data(), len);
|
||||
}
|
||||
};
|
||||
#endif // C++17 Support
|
||||
} // stack
|
||||
} // sol
|
||||
|
||||
|
|
|
@ -30,19 +30,33 @@
|
|||
|
||||
namespace sol {
|
||||
enum class lib : char {
|
||||
// print, assert, and other base functions
|
||||
base,
|
||||
// require and other package functions
|
||||
package,
|
||||
// coroutine functions and utilities
|
||||
coroutine,
|
||||
// string library
|
||||
string,
|
||||
// functionality from the OS
|
||||
os,
|
||||
// all things math
|
||||
math,
|
||||
// the table manipulator and observer functions
|
||||
table,
|
||||
// the debug library
|
||||
debug,
|
||||
// the bit library: different based on which you're using
|
||||
bit32,
|
||||
// input/output library
|
||||
io,
|
||||
// LuaJIT only
|
||||
ffi,
|
||||
// LuaJIT only
|
||||
jit,
|
||||
// library for handling utf8: new to Lua
|
||||
utf8,
|
||||
// do not use
|
||||
count
|
||||
};
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ namespace sol {
|
|||
struct no_metatable_t {};
|
||||
const no_metatable_t no_metatable = {};
|
||||
|
||||
typedef std::remove_pointer_t<lua_CFunction> lua_r_CFunction;
|
||||
typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
|
||||
|
||||
template <typename T>
|
||||
struct unique_usertype_traits {
|
||||
|
@ -617,13 +617,15 @@ namespace sol {
|
|||
bitwise_or,
|
||||
bitwise_xor,
|
||||
pairs,
|
||||
next
|
||||
next,
|
||||
type,
|
||||
type_info,
|
||||
};
|
||||
|
||||
typedef meta_function meta_method;
|
||||
|
||||
inline const std::array<std::string, 29>& meta_function_names() {
|
||||
static const std::array<std::string, 29> names = { {
|
||||
inline const std::array<std::string, 31>& meta_function_names() {
|
||||
static const std::array<std::string, 31> names = { {
|
||||
"new",
|
||||
"__index",
|
||||
"__newindex",
|
||||
|
@ -654,7 +656,9 @@ namespace sol {
|
|||
"__bxor",
|
||||
|
||||
"__pairs",
|
||||
"__next"
|
||||
"__next",
|
||||
"__type",
|
||||
"__typeinfo"
|
||||
} };
|
||||
return names;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,11 @@ namespace sol {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
int is_check(lua_State* L) {
|
||||
return stack::push(L, stack::check<T>(L, 1, &no_panic));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int member_default_to_string(std::true_type, lua_State* L) {
|
||||
decltype(auto) ts = stack::get<T>(L, 1).to_string();
|
||||
|
|
|
@ -379,7 +379,7 @@ namespace sol {
|
|||
struct usertype_metatable<T, std::index_sequence<I...>, Tn...> : usertype_metatable_core, usertype_detail::registrar {
|
||||
typedef std::make_index_sequence<sizeof...(I) * 2> indices;
|
||||
typedef std::index_sequence<I...> half_indices;
|
||||
typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 29> regs_t;
|
||||
typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 31> regs_t;
|
||||
typedef std::tuple<Tn...> RawTuple;
|
||||
typedef std::tuple<clean_type_t<Tn> ...> Tuple;
|
||||
template <std::size_t Idx>
|
||||
|
@ -394,7 +394,7 @@ namespace sol {
|
|||
void* baseclasscheck;
|
||||
void* baseclasscast;
|
||||
bool secondarymeta;
|
||||
std::array<bool, 29> properties;
|
||||
std::array<bool, 30> properties;
|
||||
|
||||
template <std::size_t Idx, meta::enable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler>
|
||||
lua_CFunction make_func() const {
|
||||
|
@ -676,6 +676,12 @@ namespace sol {
|
|||
}
|
||||
unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> };
|
||||
|
||||
lua_createtable(L, 0, 2);
|
||||
stack_reference type_table(L, -1);
|
||||
|
||||
stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index());
|
||||
stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index());
|
||||
|
||||
// Now use um
|
||||
const bool& mustindex = umc.mustindex;
|
||||
for (std::size_t i = 0; i < 3; ++i) {
|
||||
|
@ -699,6 +705,7 @@ namespace sol {
|
|||
}
|
||||
luaL_newmetatable(L, metakey);
|
||||
stack_reference t(L, -1);
|
||||
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, make_light(um));
|
||||
|
@ -735,6 +742,9 @@ namespace sol {
|
|||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
}
|
||||
// type information needs to be present on the behind-tables too
|
||||
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
// We want to just leave the table
|
||||
|
@ -745,6 +755,7 @@ namespace sol {
|
|||
// Now for the shim-table that actually gets assigned to the name
|
||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
|
||||
stack_reference t(L, -1);
|
||||
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, make_light(um));
|
||||
|
@ -758,11 +769,14 @@ namespace sol {
|
|||
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
// type information needs to be present on the behind-tables too
|
||||
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||
metabehind.pop();
|
||||
}
|
||||
|
||||
lua_remove(L, type_table.stack_index());
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -888,3 +888,35 @@ TEST_CASE("simple_usertype/indexing", "make sure simple usertypes can be indexed
|
|||
REQUIRE(val == 50);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("simple_usertype/basic type information", "check that we can query some basic type information") {
|
||||
struct my_thing {};
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<my_thing>("my_thing");
|
||||
|
||||
lua.safe_script("obj = my_thing.new()");
|
||||
|
||||
lua.safe_script("assert(my_thing.__type.is(obj))");
|
||||
lua.safe_script("assert(not my_thing.__type.is(1))");
|
||||
lua.safe_script("assert(not my_thing.__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(my_thing.__type.name)");
|
||||
|
||||
lua.safe_script("assert(obj.__type.is(obj))");
|
||||
lua.safe_script("assert(not obj.__type.is(1))");
|
||||
lua.safe_script("assert(not obj.__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(obj.__type.name)");
|
||||
|
||||
lua.safe_script("assert(getmetatable(my_thing).__type.is(obj))");
|
||||
lua.safe_script("assert(not getmetatable(my_thing).__type.is(1))");
|
||||
lua.safe_script("assert(not getmetatable(my_thing).__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(getmetatable(my_thing).__type.name)");
|
||||
|
||||
lua.safe_script("assert(getmetatable(obj).__type.is(obj))");
|
||||
lua.safe_script("assert(not getmetatable(obj).__type.is(1))");
|
||||
lua.safe_script("assert(not getmetatable(obj).__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(getmetatable(obj).__type.name)");
|
||||
}
|
||||
|
||||
|
|
|
@ -115,8 +115,23 @@ TEST_CASE("object/string-pushers", "test some basic string pushers with in_place
|
|||
|
||||
sol::object ocs(lua, sol::in_place, "bark\0bark", 9);
|
||||
sol::object os(lua, sol::in_place_type<std::string>, std::string("bark\0bark", 9), 8);
|
||||
bool test1 = os.as<std::string>() == std::string("bark\0bar", 8);
|
||||
bool test2 = ocs.as<std::string>() == std::string("bark\0bark", 9);
|
||||
sol::object osv(lua, sol::in_place_type<sol::string_view>, std::string_view("woofwoof", 8), 8);
|
||||
bool test1 = ocs.as<std::string>() == std::string("bark\0bark", 9);
|
||||
bool test2 = os.as<std::string>() == std::string("bark\0bar", 8);
|
||||
bool test3 = osv.as<std::string>() == std::string("woofwoof", 8);
|
||||
REQUIRE(ocs.get_type() == sol::type::string);
|
||||
REQUIRE(ocs.is<std::string>());
|
||||
REQUIRE(ocs.is<sol::string_view>());
|
||||
|
||||
REQUIRE(os.get_type() == sol::type::string);
|
||||
REQUIRE(os.is<std::string>());
|
||||
REQUIRE(os.is<sol::string_view>());
|
||||
|
||||
REQUIRE(osv.get_type() == sol::type::string);
|
||||
REQUIRE(osv.is<std::string>());
|
||||
REQUIRE(osv.is<sol::string_view>());
|
||||
|
||||
REQUIRE(test1);
|
||||
REQUIRE(test2);
|
||||
REQUIRE(test3);
|
||||
}
|
||||
|
|
|
@ -1764,3 +1764,34 @@ TEST_CASE("usertype/noexcept-methods", "make sure noexcept functinos and methods
|
|||
REQUIRE(v1 == 0x61);
|
||||
REQUIRE(v2 == 0x62);
|
||||
}
|
||||
|
||||
TEST_CASE("usertype/basic type information", "check that we can query some basic type information") {
|
||||
struct my_thing {};
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_simple_usertype<my_thing>("my_thing");
|
||||
|
||||
lua.safe_script("obj = my_thing.new()");
|
||||
|
||||
lua.safe_script("assert(my_thing.__type.is(obj))");
|
||||
lua.safe_script("assert(not my_thing.__type.is(1))");
|
||||
lua.safe_script("assert(not my_thing.__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(my_thing.__type.name)");
|
||||
|
||||
lua.safe_script("assert(obj.__type.is(obj))");
|
||||
lua.safe_script("assert(not obj.__type.is(1))");
|
||||
lua.safe_script("assert(not obj.__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(obj.__type.name)");
|
||||
|
||||
lua.safe_script("assert(getmetatable(my_thing).__type.is(obj))");
|
||||
lua.safe_script("assert(not getmetatable(my_thing).__type.is(1))");
|
||||
lua.safe_script("assert(not getmetatable(my_thing).__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(getmetatable(my_thing).__type.name)");
|
||||
|
||||
lua.safe_script("assert(getmetatable(obj).__type.is(obj))");
|
||||
lua.safe_script("assert(not getmetatable(obj).__type.is(1))");
|
||||
lua.safe_script("assert(not getmetatable(obj).__type.is(\"not a thing\"))");
|
||||
lua.safe_script("print(getmetatable(obj).__type.name)");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user