coroutines \o/

This commit is contained in:
ThePhD 2016-02-27 02:43:53 -05:00
parent 8dddc4ecf2
commit 251e350539
40 changed files with 391 additions and 103 deletions

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -25,5 +25,6 @@
#include "sol/state.hpp"
#include "sol/object.hpp"
#include "sol/function.hpp"
#include "sol/coroutine.hpp"
#endif // SOL_HPP

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

115
sol/coroutine.hpp Normal file
View File

@ -0,0 +1,115 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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.
#ifndef SOL_COROUTINE_HPP
#define SOL_COROUTINE_HPP
#include "reference.hpp"
#include "stack.hpp"
#include "function_result.hpp"
#include "thread.hpp"
namespace sol {
class coroutine : public reference {
private:
call_status stats = call_status::yielded;
void luacall( std::ptrdiff_t argcount, std::ptrdiff_t ) {
#if SOL_LUA_VERSION < 503
stats = static_cast<call_status>(lua_resume(lua_state(), static_cast<int>(argcount)));
#else
stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount)));
#endif // Lua 5.3
}
template<std::size_t... I, typename... Ret>
auto invoke( types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n ) {
luacall(n, sizeof...(Ret));
int stacksize = lua_gettop(lua_state());
int firstreturn = std::max(1, stacksize - static_cast<int>(sizeof...(Ret)) + 1);
auto r = stack::get<std::tuple<Ret...>>(lua_state(), firstreturn);
lua_pop(lua_state(), static_cast<int>(sizeof...(Ret)));
return r;
}
template<std::size_t I, typename Ret>
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) {
luacall(n, 1);
return stack::pop<Ret>(lua_state());
}
template <std::size_t I>
void invoke(lua_State* Lthread, types<void>, std::index_sequence<I>, std::ptrdiff_t n) {
luacall(n, 0);
}
protected_function_result invoke(lua_State* Lthread, types<>, std::index_sequence<>, std::ptrdiff_t n) {
int stacksize = lua_gettop( Lthread );
int firstreturn = std::max( 1, stacksize - static_cast<int>( n ) );
luacall(n, LUA_MULTRET);
int poststacksize = lua_gettop( Lthread );
int returncount = poststacksize - (firstreturn - 1);
return protected_function_result( lua_state( ), firstreturn, returncount, returncount, status() );
}
public:
coroutine(lua_State* L, int index = -1) : reference(L, index) {}
coroutine() = default;
coroutine(const coroutine&) = default;
coroutine& operator=(const coroutine&) = default;
call_status status() const {
return stats;
}
bool error() const {
call_status cs = status();
return cs != call_status::ok && cs != call_status::yielded;
}
bool runnable () const {
return valid()
&& (status() == call_status::yielded);
}
explicit operator bool() const {
return runnable();
}
template<typename... Args>
protected_function_result operator()( Args&&... args ) {
return call<>( std::forward<Args>( args )... );
}
template<typename... Ret, typename... Args>
decltype(auto) operator()( types<Ret...>, Args&&... args ) {
return call<Ret...>( std::forward<Args>( args )... );
}
template<typename... Ret, typename... Args>
decltype(auto) call( Args&&... args ) {
push();
int pushcount = stack::push_args( lua_state(), std::forward<Args>( args )... );
return invoke( lua_state(), types<Ret...>( ), std::index_sequence_for<Ret...>(), pushcount );
}
};
}
#endif // SOL_COUROUTINE_HPP

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -79,15 +79,8 @@ private:
}
public:
function( ) = default;
function( lua_State* L, int index = -1 ) : reference( L, index ) {
type_assert( L, index, type::function );
}
function( const function& ) = default;
function& operator=( const function& ) = default;
function( function&& ) = default;
function& operator=( function&& ) = default;
using reference::reference;
template<typename... Args>
function_result operator()( Args&&... args ) const {
return call<>( std::forward<Args>( args )... );
@ -169,10 +162,10 @@ private:
int stacksize = lua_gettop(lua_state());
int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
int returncount = 0;
call_error code = call_error::ok;
call_status code = call_status::ok;
try {
code = static_cast<call_error>(luacall(n, LUA_MULTRET, h));
code = static_cast<call_status>(luacall(n, LUA_MULTRET, h));
int poststacksize = lua_gettop(lua_state());
returncount = poststacksize - firstreturn;
}
@ -181,7 +174,7 @@ private:
h.stackindex = 0;
stack::push(lua_state(), error.what());
firstreturn = lua_gettop(lua_state());
return protected_function_result(lua_state(), firstreturn, 0, 1, call_error::runtime);
return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
}
catch (...) {
throw;

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -72,17 +72,17 @@ public:
}
};
struct protected_function_result : public proxy_base<function_result> {
struct protected_function_result : public proxy_base<protected_function_result> {
private:
lua_State* L;
int index;
int returncount;
int popcount;
call_error error;
call_status error;
public:
protected_function_result() = default;
protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_error error = call_error::ok): L(L), index(index), returncount(returncount), popcount(popcount), error(error) {
protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_status error = call_status::ok): L(L), index(index), returncount(returncount), popcount(popcount), error(error) {
}
protected_function_result(const protected_function_result&) = default;
@ -95,7 +95,7 @@ public:
o.index = 0;
o.returncount = 0;
o.popcount = 0;
o.error = call_error::runtime;
o.error = call_status::runtime;
}
protected_function_result& operator=(protected_function_result&& o) {
L = o.L;
@ -110,12 +110,12 @@ public:
o.index = 0;
o.returncount = 0;
o.popcount = 0;
o.error = call_error::runtime;
o.error = call_status::runtime;
return *this;
}
bool valid() const {
return error == call_error::ok;
return error == call_status::ok;
}
template<typename T>

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -64,10 +64,11 @@ protected:
lua_pushglobaltable(L);
ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
public:
reference() noexcept = default;
reference(lua_State* L, int index): L(L) {
reference(lua_State* L, int index = -1): L(L) {
lua_pushvalue(L, index);
ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
@ -122,6 +123,10 @@ public:
return !(ref == LUA_NOREF);
}
explicit operator bool () const {
return valid();
}
type get_type() const {
push();
int result = lua_type(L, -1);

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -796,6 +796,22 @@ inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai,
check_arguments<checkargs>{}.check(ta, tai, L, start);
fx(std::forward<FxArgs>(args)..., stack::get<Args>(L, start + I)...);
}
inline int luajit_exception_jump (lua_State* L, lua_CFunction func) {
try {
return func(L);
}
catch (const char *s) { // Catch and convert exceptions.
lua_pushstring(L, s);
}
catch (const std::exception& e) {
lua_pushstring(L, e.what());
}
catch (...) {
lua_pushstring(L, "caught (...)");
}
return lua_error(L); // Rethrow as a Lua error.
}
} // stack_detail
inline void remove( lua_State* L, int index, int count ) {
@ -878,6 +894,20 @@ inline call_syntax get_call_syntax(lua_State* L, const std::string& meta) {
lua_pop(L, 1);
return call_syntax::dot;
}
inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = stack_detail::luajit_exception_jump) {
#ifdef SOL_LUAJIT
lua_pushlightuserdata(L, (void*)handler);
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
lua_pop(L, 1);
#endif
}
inline void luajit_exception_off(lua_State* L) {
#ifdef SOL_LUAJIT
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
#endif
}
} // stack
} // sol

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -29,12 +29,13 @@ class state : private std::unique_ptr<lua_State, void(*)(lua_State*)>, public st
private:
typedef std::unique_ptr<lua_State, void(*)(lua_State*)> unique_base;
public:
using state_view::get;
state(lua_CFunction panic = detail::atpanic):
unique_base(luaL_newstate(), lua_close),
state(lua_CFunction panic = detail::atpanic) : unique_base(luaL_newstate(), lua_close),
state_view(unique_base::get()) {
set_panic(panic);
sol::stack::luajit_exception_handler(unique_base::get());
}
using state_view::get;
};
} // sol

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -210,24 +210,24 @@ private:
void set_resolved_function( Key&& key, Args&&... args ) {
set(std::forward<Key>(key), function_pack<function_sig<Sig...>>(std::forward<Args>(args)...));
}
};
namespace stack {
inline table create_table(lua_State* L, int narr = 0, int nrec = 0) {
lua_createtable(L, narr, nrec);
table result(L);
lua_pop(L, 1);
return result;
}
template <typename Key, typename Value, typename... Args>
inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
lua_createtable(L, narr, nrec);
table result(L);
result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
lua_pop(L, 1);
return result;
}
} // stack
public:
static inline table create(lua_State* L, int narr = 0, int nrec = 0) {
lua_createtable(L, narr, nrec);
table result(L);
lua_pop(L, 1);
return result;
}
template <typename Key, typename Value, typename... Args>
static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
lua_createtable(L, narr, nrec);
table result(L);
result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
lua_pop(L, 1);
return result;
}
};
} // sol
#endif // SOL_TABLE_CORE_HPP

62
sol/thread.hpp Normal file
View File

@ -0,0 +1,62 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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.
#ifndef SOL_THREAD_HPP
#define SOL_THREAD_HPP
#include "reference.hpp"
#include "stack.hpp"
namespace sol {
class thread : public reference {
public:
using reference::reference;
state_view state() const {
return state_view(this->thread_state());
}
lua_State* thread_state () const {
auto pp = stack::push_pop(*this);
lua_State* lthread = lua_tothread(lua_state(), -1);
return lthread;
}
thread_status status () const {
lua_State* lthread = thread_state();
thread_status lstat = static_cast<thread_status>(lua_status(lthread));
if (lstat != thread_status::normal && lua_gettop(lthread) == 0) {
// No thing on the thread's stack means its dead
return thread_status::dead;
}
return lstat;
}
static thread create (lua_State* L) {
lua_newthread(L);
thread result(L);
lua_pop(L, 1);
return result;
}
};
} // sol
#endif // SOL_THREAD_HPP

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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
@ -67,12 +67,23 @@ enum class call_syntax {
colon = 1
};
enum class call_error : int {
ok = LUA_OK,
enum class call_status : int {
ok = LUA_OK,
yielded = LUA_YIELD,
runtime = LUA_ERRRUN,
memory = LUA_ERRMEM,
memory = LUA_ERRMEM,
handler = LUA_ERRERR,
gc = LUA_ERRGCMM
gc = LUA_ERRGCMM
};
enum class thread_status : int {
normal = LUA_OK,
yielded = LUA_YIELD,
error_runtime = LUA_ERRRUN,
error_memory = LUA_ERRMEM,
error_gc = LUA_ERRGCMM,
error_handler = LUA_ERRERR,
dead,
};
enum class type : int {
@ -124,6 +135,7 @@ inline std::string type_name(lua_State*L, type t) {
return lua_typename(L, static_cast<int>(t));
}
class reference;
template<typename T>
class usertype;
template <bool>
@ -132,6 +144,8 @@ typedef table_core<false> table;
typedef table_core<true> global_table;
class function;
class protected_function;
class coroutine;
class thread;
class object;
template <typename T, typename = void>
@ -170,6 +184,12 @@ struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function>
template <>
struct lua_type_of<function> : std::integral_constant<type, type::function> {};
template <>
struct lua_type_of<coroutine> : std::integral_constant<type, type::function> {};
template <>
struct lua_type_of<thread> : std::integral_constant<type, type::thread> {};
template <>
struct lua_type_of<protected_function> : std::integral_constant<type, type::function> {};
@ -186,7 +206,7 @@ template <typename T>
struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {};
template <typename T>
struct is_lua_primitive : std::integral_constant<bool, type::userdata != lua_type_of<meta::Unqualified<T>>::value> { };
struct is_lua_primitive : std::integral_constant<bool, type::userdata != lua_type_of<meta::Unqualified<T>>::value || std::is_base_of<reference, meta::Unqualified<T>>::value> { };
template <typename T>
struct is_proxy_primitive : is_lua_primitive<T> { };

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

View File

@ -1,6 +1,6 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// 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

105
tests.cpp
View File

@ -387,7 +387,7 @@ TEST_CASE("simple/if", "check if if statements work through lua") {
REQUIRE((f == lua["f"]));
}
TEST_CASE("simple/call_with_parameters", "Lua function is called with a few parameters from C++") {
TEST_CASE("simple/call-with-parameters", "Lua function is called with a few parameters from C++") {
sol::state lua;
REQUIRE_NOTHROW(lua.script("function my_add(i, j, k) return i + j + k end"));
@ -401,7 +401,7 @@ TEST_CASE("simple/call_with_parameters", "Lua function is called with a few para
REQUIRE_THROWS(a = f(1, 2, "arf"));
}
TEST_CASE("simple/call_c++_function", "C++ function is called from lua") {
TEST_CASE("simple/call-c++-function", "C++ function is called from lua") {
sol::state lua;
lua.set_function("plop_xyz", plop_xyz);
@ -410,7 +410,7 @@ TEST_CASE("simple/call_c++_function", "C++ function is called from lua") {
REQUIRE(lua.get<int>("x") == 11);
}
TEST_CASE("simple/call_lambda", "A C++ lambda is exposed to lua and called") {
TEST_CASE("simple/call-lambda", "A C++ lambda is exposed to lua and called") {
sol::state lua;
int x = 0;
@ -422,7 +422,7 @@ TEST_CASE("simple/call_lambda", "A C++ lambda is exposed to lua and called") {
REQUIRE(x == 1);
}
TEST_CASE("advanced/get_and_call", "Checks for lambdas returning values after a get operation") {
TEST_CASE("advanced/get-and-call", "Checks for lambdas returning values after a get operation") {
const static std::string lol = "lol", str = "str";
const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh"));
sol::state lua;
@ -457,7 +457,7 @@ TEST_CASE("advanced/get_and_call", "Checks for lambdas returning values after a
REQUIRE((lua.get<sol::function>("j").call<int, float, double, std::string>() == heh_tuple));
}
TEST_CASE("advanced/operator[]_calls", "Checks for lambdas returning values using operator[]") {
TEST_CASE("advanced/operator[]-call", "Checks for lambdas returning values using operator[]") {
const static std::string lol = "lol", str = "str";
const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh"));
sol::state lua;
@ -492,7 +492,7 @@ TEST_CASE("advanced/operator[]_calls", "Checks for lambdas returning values usin
REQUIRE((lua["j"].call<int, float, double, std::string>() == heh_tuple));
}
TEST_CASE("advanced/call_lambdas", "A C++ lambda is exposed to lua and called") {
TEST_CASE("advanced/call-lambdas", "A C++ lambda is exposed to lua and called") {
sol::state lua;
int x = 0;
@ -505,7 +505,7 @@ TEST_CASE("advanced/call_lambdas", "A C++ lambda is exposed to lua and called")
REQUIRE(x == 9);
}
TEST_CASE("advanced/call_referenced_obj", "A C++ object is passed by pointer/reference_wrapper to lua and invoked") {
TEST_CASE("advanced/call-referenced_obj", "A C++ object is passed by pointer/reference_wrapper to lua and invoked") {
sol::state lua;
int x = 0;
@ -546,7 +546,7 @@ TEST_CASE("tables/variables", "Check if tables and variables work as intended")
REQUIRE_NOTHROW(lua.script("assert(os.name == \"windows\")"));
}
TEST_CASE("tables/functions_variables", "Check if tables and function calls work as intended") {
TEST_CASE("tables/functions-variables", "Check if tables and function calls work as intended") {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::os);
auto run_script = [] (sol::state& lua) -> void {
@ -626,7 +626,7 @@ TEST_CASE("functions/overload-resolution", "Check if overloaded function resolut
REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))"));
}
TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in the same reading order specified in Lua") {
TEST_CASE("functions/return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua") {
const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12);
const static std::tuple<int, float> paired = std::make_tuple(10, 10.f);
sol::state lua;
@ -648,7 +648,7 @@ TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in t
REQUIRE(tcpp2 == paired);
}
TEST_CASE("functions/deducing_return_order_and_multi_get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") {
TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") {
const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12);
sol::state lua;
lua.set_function( "f_string", []() { return "this is a string!"; } );
@ -675,7 +675,7 @@ TEST_CASE("functions/deducing_return_order_and_multi_get", "Check if return orde
REQUIRE(tluaget == triple);
}
TEST_CASE("functions/sol::function to std::function", "check if conversion to std::function works properly and calls with correct arguments") {
TEST_CASE("functions/sol::function-to-std::function", "check if conversion to std::function works properly and calls with correct arguments") {
sol::state lua;
lua.open_libraries(sol::lib::base);
@ -694,7 +694,7 @@ TEST_CASE("functions/sol::function to std::function", "check if conversion to st
);
}
TEST_CASE("functions/returning functions from C++ and getting in lua", "check to see if returning a functor and getting a functor from lua is possible") {
TEST_CASE("functions/returning-functions-from-C++-and-gettin-in-lua", "check to see if returning a functor and getting a functor from lua is possible") {
sol::state lua;
lua.open_libraries(sol::lib::base);
@ -784,7 +784,7 @@ TEST_CASE("tables/usertype", "Show that we can create classes from usertype and
REQUIRE(cresult == 3);
}
TEST_CASE("tables/usertype constructors", "Show that we can create classes from usertype and use them with multiple constructors") {
TEST_CASE("tables/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") {
sol::state lua;
@ -827,7 +827,7 @@ TEST_CASE("tables/usertype constructors", "Show that we can create classes from
REQUIRE((z.as<int>() == 9));
}
TEST_CASE("tables/usertype utility", "Show internal management of classes registered through new_usertype") {
TEST_CASE("tables/usertype-utility", "Show internal management of classes registered through new_usertype") {
sol::state lua;
lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
@ -852,7 +852,7 @@ TEST_CASE("tables/usertype utility", "Show internal management of classes regist
REQUIRE(cresult == 3);
}
TEST_CASE("tables/usertype utility derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") {
TEST_CASE("tables/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") {
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<int>> basector;
@ -925,7 +925,7 @@ TEST_CASE("tables/arbitrary-creation", "tables should be created from standard c
REQUIRE(c.get<std::string>("project") == "sol");
}
TEST_CASE("tables/for_each", "Testing the use of for_each to get values from a lua table") {
TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a lua table") {
sol::state lua;
lua.open_libraries(sol::lib::base);
@ -1085,7 +1085,7 @@ TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as
));
}
TEST_CASE("usertype/nonmember functions implement functionality", "let users set non-member functions that take unqualified T as first parameter to usertype") {
TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
sol::state lua;
lua.open_libraries( sol::lib::base );
@ -1162,11 +1162,9 @@ TEST_CASE("interop/null-to-nil-and-back", "nil should be the given type when a p
"assert(x == nil)"));
}
#ifndef SOL_LUAJIT // LuaJIT does not have error message handling support for lua_pcall, and thus this test will always fail
TEST_CASE( "functions/function_result-protected_function", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers" ) {
TEST_CASE( "functions/function_result-protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers" ) {
sol::state lua;
lua.open_libraries( sol::lib::base, sol::lib::debug );
static const char errormessage1[] = "true error message";
static const char errormessage2[] = "doodle";
@ -1210,7 +1208,6 @@ TEST_CASE( "functions/function_result-protected_function", "Function result shou
errorstring = result2;
REQUIRE(errorstring == errormessage2);
}
#endif // LuaJIT Issues
TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") {
static int created = 0;
@ -1344,7 +1341,7 @@ TEST_CASE("functions/overloading", "Check if overloading works properly for regu
REQUIRE_THROWS(lua.script("func(1,2,'meow')"));
}
TEST_CASE("usertype/private constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") {
TEST_CASE("usertype/private-constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") {
int numsaved = factory_test::num_saved;
int numkilled = factory_test::num_killed;
{
@ -1410,6 +1407,70 @@ TEST_CASE("usertype/overloading", "Check if overloading works properly for usert
REQUIRE_THROWS(lua.script("r:func(1,2,'meow')"));
}
TEST_CASE("threading/coroutines", "ensure calling a coroutine works") {
const auto& script = R"(counter = 20
function loop()
while counter ~= 30
do
print("Sending " .. counter);
coroutine.yield(counter);
counter = counter + 1;
end
print("Sending " .. counter);
return counter
end
)";
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
lua.script(script);
sol::coroutine cr = lua["loop"];
int counter;
for (counter = 20; counter < 31 && cr; ++counter) {
int x = cr();
if (counter != x) {
throw std::logic_error("fuck");
}
}
counter -= 1;
REQUIRE(counter == 30);
}
TEST_CASE("threading/new-thread-coroutines", "ensure calling a coroutine works") {
const auto& script = R"(counter = 20
function loop()
while counter ~= 30
do
print("Sending " .. counter);
coroutine.yield(counter);
counter = counter + 1;
end
print("Sending " .. counter);
return counter
end
)";
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
lua.script(script);
sol::thread runner = sol::thread::create(lua.lua_state());
sol::state_view runnerstate = runner.state();
sol::coroutine cr = lua["loop"];
int counter;
for (counter = 20; counter < 31 && cr; ++counter) {
int x = cr();
if (counter != x) {
throw std::logic_error("fuck");
}
}
counter -= 1;
REQUIRE(counter == 30);
}
TEST_CASE("issues/stack-overflow", "make sure various operations repeated don't trigger stack overflow") {
sol::state lua;
lua.script("t = {};t[0]=20");