From 350f430d7428db8a8c9869fd8a0c02b231ce7924 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Wed, 11 Dec 2013 11:18:13 -0500 Subject: [PATCH] Improved tests, added a build.ninja for TeamCity, and fixed formatting again to work with Rapptz's style. --- .gitignore | 3 +- build.ninja | 27 ++++++ sol.scratch.cpp | 213 ++++++++++++++++++++++++++++++------------- sol/function.hpp | 16 ++-- sol/lua_function.hpp | 72 +++++++-------- sol/stack.hpp | 28 +++--- sol/state.hpp | 12 ++- sol/table.hpp | 4 +- 8 files changed, 250 insertions(+), 125 deletions(-) create mode 100644 build.ninja diff --git a/.gitignore b/.gitignore index 7355685a..bfbe70a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ obj/* bin/* -*.ninja* demacro.txt Shinobi2 dev.* @@ -16,3 +15,5 @@ x64/ *.sln *.gitattributes liblua.a +sol/include/ +.ninja* diff --git a/build.ninja b/build.ninja new file mode 100644 index 00000000..c6a0c4a9 --- /dev/null +++ b/build.ninja @@ -0,0 +1,27 @@ +# This file has been generated by shinobi version 0.9.5 + +ninja_required_version = 1.3 +builddir = bin +objdir = obj +cxx = g++ +cxxflags = -std=c++11 -pedantic -pedantic-errors -Wextra -Wall -O2 -DNDEBUG +incflags = -I"." -I"./include" -I"." -I"./lua-5.2.2/src/" -I"./Catch/include/" +linkflags = -static liblua.a -L"./lib" + +rule compile + command = $cxx -MMD -MF $out.d $cxxflags -c $in -o $out $incflags + deps = gcc + depfile = $out.d + description = Compiling $in + +rule link + command = $cxx $in -o $out $linkflags + description = Creating $out + +build $objdir/sol.scratch.o: compile sol.scratch.cpp + +build $builddir/sol.scratch: link $objdir/sol.scratch.o + +build install: phony $builddir/sol.scratch + +default install diff --git a/sol.scratch.cpp b/sol.scratch.cpp index c5affbdc..fb968850 100644 --- a/sol.scratch.cpp +++ b/sol.scratch.cpp @@ -16,95 +16,184 @@ struct object { }; +int plop_xyz(int x, int y, std::string z) { + std::cout << x << " " << y << " " << z << std::endl; + return 11; +} + void run_script(sol::state& lua) { lua.script("assert(os.fun() == \"test\")\n" "assert(os.name == \"windows\")"); } -TEST_CASE( "simple/set_global", "Check if the set_global works properly." ) { - sol::state lua; +TEST_CASE("simple/set_global", "Check if the set_global works properly.") { + sol::state lua; - lua.set( "a", 9 ); - REQUIRE_NOTHROW( lua.script( "if a ~= 9 then error('wrong value') end" ) ); + lua.set("a", 9); + REQUIRE_NOTHROW(lua.script("if a ~= 9 then error('wrong value') end")); - lua.set( "d", "hello" ); - REQUIRE_NOTHROW( lua.script( "if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end" ) ); + lua.set("d", "hello"); + REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); - lua.set( "e", std::string( "hello" ) ); - REQUIRE_NOTHROW( lua.script( "if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end" ) ); + lua.set("e", std::string("hello")); + REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); - lua.set( "f", true ); - REQUIRE_NOTHROW( lua.script( "if f ~= true then error('wrong value') end" ) ); + lua.set("f", true); + REQUIRE_NOTHROW(lua.script("if f ~= true then error('wrong value') end")); } -TEST_CASE( "simple/get", "Tests if the get function works properly." ) { - sol::state lua; +TEST_CASE("simple/get", "Tests if the get function works properly.") { + sol::state lua; - lua.script( "a = 9" ); - auto a = lua.get( "a" ); - REQUIRE( a == 9.0 ); + lua.script("a = 9"); + auto a = lua.get("a"); + REQUIRE(a == 9.0); - lua.script( "b = nil" ); - REQUIRE_NOTHROW( auto b = lua.get( "b" ) ); - - lua.script( "d = 'hello'" ); - auto d = lua.get( "d" ); - REQUIRE( d == "hello" ); + lua.script("b = nil"); + REQUIRE_NOTHROW(auto b = lua.get("b")); + + lua.script("d = 'hello'"); + auto d = lua.get("d"); + REQUIRE(d == "hello"); - lua.script( "e = true" ); - auto e = lua.get( "e" ); - REQUIRE( e == true ); + lua.script("e = true"); + auto e = lua.get("e"); + REQUIRE(e == true); } -TEST_CASE( "simple/addition", "" ) { - sol::state lua; +TEST_CASE("simple/addition", "") { + sol::state lua; - lua.set( "b", 0.2 ); - lua.script( "c = 9 + b" ); - auto c = lua.get( "c" ); + lua.set("b", 0.2); + lua.script("c = 9 + b"); + auto c = lua.get("c"); - REQUIRE( c == 9.2 ); + REQUIRE(c == 9.2); +} + +TEST_CASE("simple/if", "") { + sol::state lua; + + std::string program = "if true then f = 0.1 else f = 'test' end"; + lua.script(program); + auto f = lua.get("f"); + + REQUIRE(f == 0.1); +} + +TEST_CASE("simple/evalStream", "The VM evaluates a stream's contents using a reader") { + sol::state lua; + + std::stringstream sscript; + int g = 9; + sscript << "g = " << g << ";"; + + REQUIRE_NOTHROW(lua.script(sscript.str())); + REQUIRE(lua.get("g") == 9.0); +} + +TEST_CASE("simple/callWithParameters", "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")); + auto f = lua.get("my_add"); + REQUIRE_NOTHROW(f.call(1, 2, 3)); + REQUIRE_THROWS(f.call(1, 2, "arf")); +} + +TEST_CASE("simple/callCppFunction", "C++ function is called from lua") { + sol::state lua; + + lua.set_function("plop_xyz", plop_xyz); + lua.script("x = plop_xyz(2, 6, 'hello')"); + + REQUIRE(lua.get("x") == 11); +} + +TEST_CASE("simple/callLambda", "A C++ lambda is exposed to lua and called") { + sol::state lua; + + int x = 0; + + lua.set_function("foo", [ &x ] { x = 1; }); + + lua.script("foo()"); + + REQUIRE(x == 1); +} + +TEST_CASE("advanced/callLambdaReturns", "Checks for lambdas returning values") { + sol::state lua; + + lua.set_function("a", [ ] { return 42; }); + lua.set_function("b", [ ] { return 42u; }); + lua.set_function("c", [ ] { return 3.14; }); + lua.set_function("d", [ ] { return 6.28f; }); + lua.set_function("e", [ ] { return "lol"; }); + lua.set_function("f", [ ] { return true; }); + lua.set_function("g", [ ] { return std::string("str"); }); + lua.set_function("h", [ ] { }); + lua.set_function("i", [ ] { return sol::nil; }); +} + +TEST_CASE("advanced/callLambda2", "A C++ lambda is exposed to lua and called") { + sol::state lua; + + int x = 0; + lua.set_function("set_x", [ &] (int new_x) { + x = new_x; + return 0; + }); + + lua.script("set_x(9)"); + REQUIRE(x == 9); +} + +TEST_CASE("negative/basicError", "Check if error handling works correctly") { + sol::state lua; + + REQUIRE_THROWS(lua.script("nil[5]")); } /* - lua.get( "os" ).set( "name", "windows" ); + lua.get("os").set("name", "windows"); - SECTION( "" ) - lua.get( "os" ).set_function( "fun", - [ ] ( ) { - std::cout << "stateless lambda()" << std::endl; - return "test"; - } - ); - run_script( lua ); + SECTION("") + lua.get("os").set_function("fun", + [ ] () { + std::cout << "stateless lambda()" << std::endl; + return "test"; + } + ); + run_script(lua); - lua.get( "os" ).set_function( "fun", &free_function ); - run_script( lua ); + lua.get("os").set_function("fun", &free_function); + run_script(lua); - // l-value, can optomize - auto lval = object( ); - lua.get( "os" ).set_function( "fun", &object::operator(), lval ); - run_script( lua ); + // l-value, can optomize + auto lval = object(); + lua.get("os").set_function("fun", &object::operator(), lval); + run_script(lua); - // Tests will begin failing here - // stateful lambda: non-convertible, unoptomizable - int breakit = 50; - lua.get( "os" ).set_function( "fun", - [ &breakit ] ( ) { - std::cout << "stateless lambda()" << std::endl; - return "test"; - } - ); - run_script( lua ); + // Tests will begin failing here + // stateful lambda: non-convertible, unoptomizable + int breakit = 50; + lua.get("os").set_function("fun", + [ &breakit ] () { + std::cout << "stateless lambda()" << std::endl; + return "test"; + } + ); + run_script(lua); - // r-value, cannot optomize - lua.get( "os" ).set_function( "fun", &object::operator(), object( ) ); - run_script( lua ); + // r-value, cannot optomize + lua.get("os").set_function("fun", &object::operator(), object()); + run_script(lua); - // r-value, cannot optomize - auto rval = object( ); - lua.get( "os" ).set_function( "fun", &object::operator(), std::move( rval ) ); - run_script( lua ); + // r-value, cannot optomize + auto rval = object(); + lua.get("os").set_function("fun", &object::operator(), std::move(rval)); + run_script(lua); } */ diff --git a/sol/function.hpp b/sol/function.hpp index ebb730f9..edf44337 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -30,22 +30,22 @@ namespace sol { class function : virtual public reference { private: template - std::tuple call(types, std::size_t n) { - lua_pcall(state(), n, sizeof...(Ret), 0); + std::tuple invoke(types, std::size_t n) { + lua_pcall(state(), static_cast(n), sizeof...(Ret), 0); return stack::pop_call(state(), std::make_tuple, types()); } template - Ret call(types, std::size_t n) { - lua_pcall(state(), n, 1, 0); + Ret invoke(types, std::size_t n) { + lua_pcall(state(), static_cast(n), 1, 0); return stack::pop(state()); } - void call(types, std::size_t n) { + void invoke(types, std::size_t n) { lua_pcall(state(), static_cast(n), 0, 0); } - void call(types<>, std::size_t n) { + void invoke(types<>, std::size_t n) { lua_pcall(state(), static_cast(n), 0, 0); } @@ -56,10 +56,10 @@ public: } template - auto invoke(Args&&... args) -> decltype(call(types(), sizeof...(Args))) { + auto call(Args&&... args) -> decltype(invoke(types(), sizeof...(Args))) { push(); stack::push_args(state(), std::forward(args)...); - return call(types(), sizeof...(Args)); + return invoke(types(), sizeof...(Args)); } }; } // sol diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index 61a5249d..e73f818e 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -29,32 +29,32 @@ namespace sol { namespace detail { template -void get_upvalue_ptr( lua_State* L, T*& data, std::size_t datasize, std::array voiddata, int& upvalue ) { - for ( std::size_t i = 0, d = 0; d < datasize; ++i, d += sizeof( void* ) ) { - voiddata[ i ] = lua_touserdata( L, lua_upvalueindex( upvalue++ ) ); - } - data = reinterpret_cast( static_cast( voiddata.data( ) ) ); +void get_upvalue_ptr(lua_State* L, T*& data, std::size_t datasize, std::array voiddata, int& upvalue) { + for (std::size_t i = 0, d = 0; d < datasize; ++i, d += sizeof(void*)) { + voiddata[ i ] = lua_touserdata(L, lua_upvalueindex(upvalue++)); + } + data = reinterpret_cast(static_cast(voiddata.data())); } template -void get_upvalue_ptr( lua_State* L, T*& data, std::array voiddata, int& upvalue ) { - get_upvalue_ptr( L, data, sizeof( T ), voiddata, upvalue ); +void get_upvalue_ptr(lua_State* L, T*& data, std::array voiddata, int& upvalue) { + get_upvalue_ptr(L, data, sizeof(T), voiddata, upvalue); } template -void get_upvalue_ptr( lua_State* L, T*& data, int& upvalue ) { - const static std::size_t data_t_count = ( sizeof(T)+( sizeof(void*)-1 ) ) / sizeof( void* ); - typedef std::array data_t; - data_t voiddata{{}}; - return get_upvalue_ptr(L, data, voiddata, upvalue); +void get_upvalue_ptr(lua_State* L, T*& data, int& upvalue) { + const static std::size_t data_t_count = (sizeof(T)+(sizeof(void*)-1)) / sizeof(void*); + typedef std::array data_t; + data_t voiddata{{}}; + return get_upvalue_ptr(L, data, voiddata, upvalue); } template -void get_upvalue( lua_State* L, T& data, int& upvalue ) { - const static std::size_t data_t_count = ( sizeof(T)+( sizeof(void*)-1 ) ) / sizeof( void* ); - typedef std::array data_t; - data_t voiddata{ { } }; - for ( std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof( void* ) ) { - voiddata[ i ] = lua_touserdata( L, lua_upvalueindex( upvalue++ ) ); - } - data = *reinterpret_cast( static_cast( voiddata.data( ) ) ); +void get_upvalue(lua_State* L, T& data, int& upvalue) { + const static std::size_t data_t_count = (sizeof(T)+(sizeof(void*)-1)) / sizeof(void*); + typedef std::array data_t; + data_t voiddata{ { } }; + for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { + voiddata[ i ] = lua_touserdata(L, lua_upvalueindex(upvalue++)); + } + data = *reinterpret_cast(static_cast(voiddata.data())); } } // detail @@ -80,7 +80,7 @@ struct static_lua_func { static int call(lua_State* L) { int upvalue = 1; fx_t* fx; - detail::get_upvalue( L, fx, upvalue ); + detail::get_upvalue(L, fx, upvalue); int r = typed_call(tuple_types(), typename fx_traits::args_type(), fx, L); return r; } @@ -105,8 +105,8 @@ struct static_object_lua_func { template static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { auto fx = [ &item, &ifx ] (Args&&... args) -> TR { - return (item.*ifx)(std::forward(args)...); - }; + return (item.*ifx)(std::forward(args)...); + }; auto r = stack::pop_call(L, fx, types()); stack::push(L, std::move(r)); return 1; @@ -121,19 +121,19 @@ struct static_object_lua_func { } static int call(lua_State* L) { - const static std::size_t data_t_count = ( sizeof(fx_t)+( sizeof(void*)-1 ) ) / sizeof( void* ); - typedef std::array data_t; - int upvalue = 1; - data_t data = { { } }; - fx_t* fxptr; - for ( std::size_t i = 0, d = 0; d < sizeof(fx_t*); ++i, d += sizeof( void* ) ) { - data[ i ] = lua_touserdata( L, lua_upvalueindex( upvalue++ ) ); - } - fxptr = reinterpret_cast( static_cast( data.data( ) ) ); - fx_t& mem_ptr = *fxptr; - void* objectdata = lua_touserdata( L, lua_upvalueindex( upvalue++ ) ); - T& obj = *static_cast( objectdata ); - int r = typed_call( tuple_types( ), typename fx_traits::args_type( ), obj, mem_ptr, L ); + const static std::size_t data_t_count = (sizeof(fx_t)+(sizeof(void*)-1)) / sizeof(void*); + typedef std::array data_t; + int upvalue = 1; + data_t data = { { } }; + fx_t* fxptr; + for (std::size_t i = 0, d = 0; d < sizeof(fx_t*); ++i, d += sizeof(void*)) { + data[ i ] = lua_touserdata(L, lua_upvalueindex(upvalue++)); + } + fxptr = reinterpret_cast(static_cast(data.data())); + fx_t& mem_ptr = *fxptr; + void* objectdata = lua_touserdata(L, lua_upvalueindex(upvalue++)); + T& obj = *static_cast(objectdata); + int r = typed_call(tuple_types(), typename fx_traits::args_type(), obj, mem_ptr, L); return r; } diff --git a/sol/stack.hpp b/sol/stack.hpp index dc8cd811..bda81815 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -45,7 +45,7 @@ inline T get_unsigned(lua_State* L, std::true_type, int index = -1) { template inline T get_unsigned(lua_State* L, std::false_type, int index = -1) { - return static_cast( lua_tointeger(L, index) ); + return static_cast(lua_tointeger(L, index)); } template @@ -68,7 +68,7 @@ inline T get_helper(lua_State* L, std::true_type, int index = -1) { template inline T get_nil(lua_State* L, std::true_type, int index = -1) { if (lua_isnil(L, index) == 0) - throw sol::sol_error("not nil"); + throw sol::sol_error("not nil"); return nil_t{}; } @@ -196,19 +196,19 @@ inline void push(lua_State* L, const std::array& data) { } } -template -inline int push_user( lua_State* L, T& item ) { - typedef typename std::decay::type TValue; - const static std::size_t itemsize = sizeof( TValue ); - const static std::size_t voidsize = sizeof( void* ); - const static std::size_t voidsizem1 = voidsize - 1; - const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; - typedef std::array data_t; +template +inline int push_user(lua_State* L, T& item) { + typedef typename std::decay::type TValue; + const static std::size_t itemsize = sizeof(TValue); + const static std::size_t voidsize = sizeof(void*); + const static std::size_t voidsizem1 = voidsize - 1; + const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; + typedef std::array data_t; - data_t data{{}}; - std::memcpy( std::addressof( data[ 0 ] ), std::addressof( item ), itemsize ); - push( L, data ); - return data_t_count; + data_t data{{}}; + std::memcpy(std::addressof(data[ 0 ]), std::addressof(item), itemsize); + push(L, data); + return data_t_count; } namespace detail { diff --git a/sol/state.hpp b/sol/state.hpp index ebd4ced7..4f2f34ea 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -115,14 +115,22 @@ public: } } + void eval(const std::string& code) { + script(code); + } + void script(const std::string& code) { if(luaL_dostring(L.get(), code.c_str())) { lua_error(L.get()); } } - void open_file(const std::string& filename) { - if(luaL_dofile(L.get(), filename.c_str())) { + void eval_file(const std::string& filename) { + script_file(filename); + } + + void script_file(const std::string& filename) { + if (luaL_dofile(L.get(), filename.c_str())) { lua_error(L.get()); } } diff --git a/sol/table.hpp b/sol/table.hpp index bcf635bb..14120adc 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -170,7 +170,7 @@ private: push(); - int upvalues = stack::push_user( state( ), target ); + int upvalues = stack::push_user(state(), target); luaL_setfuncs(state(), funcreg, upvalues); lua_pop(state(), 1); @@ -199,7 +199,7 @@ private: lua_settable(state(), -3); } - push(); + push(); stack::push_user(state(), userdata, metatablename); luaL_setfuncs(state(), funcreg, 1);