diff --git a/lundi.hpp b/lundi.hpp index f7ac23d..4ae5989 100644 --- a/lundi.hpp +++ b/lundi.hpp @@ -41,19 +41,60 @@ class function_wrapper { virtual ~function_wrapper() {}; }; +std::string get_type_name(int lua_type_name) { + switch (lua_type_name) { + case LUA_TNUMBER: return "number"; + case LUA_TBOOLEAN: return "bool"; + case LUA_TSTRING: return "string"; + case LUA_TNIL: return "nil"; + case LUA_TUSERDATA: return "userdata"; + case LUA_TTHREAD: return "thread"; + case LUA_TLIGHTUSERDATA: return "lightuserdata"; + case LUA_TTABLE: return "table"; + case LUA_TFUNCTION: return "function"; + default: return "unknown-type"; + } +} + struct fetch_parameter { lua_State *state; fetch_parameter(lua_State *s) : state(s) {} + // that function is complementary to peek + // the main difference is that it knows what to expect + + // the template version is more flexible, but produces no error message + /*template + void operator()(T&) const { + static_assert(false, "This type can't be used in function signature."); + }*/ + + // TODO : add error reporting to that + // it has to utilize userdata stored in state somehow + void operator()(std::string& t) const { t = lua_tostring(state, -1); lua_pop(state, 1); } void operator()(int& t) const { + t = lua_tointeger(state, -1); + lua_pop(state, 1); + } + + void operator()(double& t) const { t = lua_tonumber(state, -1); lua_pop(state, 1); } + + void operator()(bool& t) const { + t = static_cast(lua_toboolean(state, -1)); + lua_pop(state, 1); + } + + void operator()(lua::nil_type&) const { + lua_pop(state, 1); + } }; template @@ -131,6 +172,10 @@ char const *stream_name(StreamT &stream) { class state { lua_State *state_; std::function error_func_; + void report_error(std::string const& error_message) { + if (error_func_) + error_func_(error_message); + } variant peek(int index) { switch(lua_type(state_, index)) { @@ -165,8 +210,7 @@ class state { error_msg = std::string(lua_tostring(state_, -1)); lua_pop(state_, -1); // remove error message } - if (error_func_) - error_func_(error_msg); + report_error(error_msg); } } diff --git a/test.cpp b/test.cpp index a4ad3e7..235a4d4 100644 --- a/test.cpp +++ b/test.cpp @@ -3,33 +3,116 @@ #include #include +#include +#include + #include "lundi.hpp" #define CATCH_CONFIG_MAIN #include namespace { + namespace c_funs { + + // left for historical purposes + int plop_xyz(int x, int y, std::string z) { + std::cout << x << " " << y << " " << z << std::endl; + return 11; + } + + // the naming pattern goes: + // {return_type}_{number_of_args} + + // basic empty functions + namespace basic { + template + void void_unary(A a) { } + template + void void_binary_first(A a, int) { } + template + void void_binary_second(int, B b) { } + + // function without parameters + template + Ret nonparam() { return Ret{}; } + + // functions returning nonparameter + template + A same_unary(A a) { return a; } + template + A first_binary_first(A a, int) { return a; } + template + B second_binary_second(int, B b) { return b; } + } + + // functions with aggregates + /*namespace aggregate{ + template + void void_unary(Aggr a) { } + // TODO add more + }*/ + } + + // equivalent of Boost.Variant operator== + template + inline bool equals(V const& variant, T const& value){ + return boost::get(variant) && boost::get(variant) == value; + } + + //[](std::string const& s) { std::cerr << "Lua ERROR : " << s << std::endl; } + void defaultErrorReporter(std::string const& s) { + std::cerr << "Lua ERROR : " << s << std::endl; + } + + void exceptionErrorReporter(std::string const& s) { + throw lua::exception(s); + } + +} + +#define BASIC_TYPES (int)(double)(bool)(std::string)(lua::nil_type) + +TEST_CASE( "coverage/register_void_return", "Check if basic calls in form of void(T) compile." ) { + lua::state lua (&exceptionErrorReporter); + + #define MACRO(r, data, Elem) \ + REQUIRE_NOTHROW(lua.register_function("foo", c_funs::basic::void_unary)); \ + REQUIRE_NOTHROW(lua.register_function("foo", c_funs::basic::void_binary_first)); \ + REQUIRE_NOTHROW(lua.register_function("foo", c_funs::basic::void_binary_second)); + BOOST_PP_SEQ_FOR_EACH(MACRO, _, BASIC_TYPES) + #undef MACRO +} + +TEST_CASE(" coverage/register_nonvoid_return", "Check if basic calls in form of void(T) compile.") { + lua::state lua(&exceptionErrorReporter); -int plop_xyz(int x, int y, std::string z) { - std::cout << x << " " << y << " " << z << std::endl; - return 11; + #define MACRO(r, data, Elem) \ + REQUIRE_NOTHROW(lua.register_function("foo", c_funs::basic::same_unary)); \ + REQUIRE_NOTHROW(lua.register_function("foo", c_funs::basic::first_binary_first)); \ + REQUIRE_NOTHROW(lua.register_function("foo", c_funs::basic::second_binary_second)); + + BOOST_PP_SEQ_FOR_EACH(MACRO, _, BASIC_TYPES) + #undef MACRO } -// equivalent of Boost.Variant operator== -template -inline bool equals(V const& variant, T const& value){ - return boost::get(variant) && boost::get(variant) == value; -} +TEST_CASE( "coverage/void_lambda_call", "Check if basic calls in form of void (T) compile." ) { + lua::state lua(&exceptionErrorReporter); -//[](std::string const& s) { std::cerr << "Lua ERROR : " << s << std::endl; } -void defaultErrorReporter(std::string const& s) { - std::cerr << "Lua ERROR : " << s << std::endl; + #define MACRO(r, data, Elem) \ + REQUIRE_NOTHROW(lua.register_function("foo", [](Elem){})); \ + REQUIRE_NOTHROW(lua.register_function("foo", [](Elem, Elem){})); + BOOST_PP_SEQ_FOR_EACH(MACRO, _, BASIC_TYPES) + #undef MACRO } -void exceptionErrorReporter(std::string const& s) { - throw lua::exception(s); -} +TEST_CASE("coverage/type_lambda_call", "Check if basic calls in form of T (T) compile.") { + lua::state lua(&exceptionErrorReporter); + #define MACRO(r, data, Elem) \ + REQUIRE_NOTHROW(lua.register_function("foo", [](Elem){ return Elem {}; })); \ + REQUIRE_NOTHROW(lua.register_function("foo", [](Elem, Elem){ return Elem {}; })); + BOOST_PP_SEQ_FOR_EACH(MACRO, _, BASIC_TYPES) + #undef MACRO } TEST_CASE( "simple/set_global", "Check if the set_global works properly." ) { @@ -118,7 +201,7 @@ TEST_CASE( "simple/callWithParameters", "Lua function is called with a few param TEST_CASE( "simple/callCppFunction", "Desc" ) { lua::state lua(&exceptionErrorReporter); - lua.register_function("plop_xyz", plop_xyz); + lua.register_function("plop_xyz", c_funs::plop_xyz); lua.eval("x = plop_xyz(2, 6, 'hello')"); std::cout << lua.get_global("x") << std::endl; @@ -148,7 +231,7 @@ TEST_CASE( "advanced/callLambdaReturns", "Checks for lambdas returning values") lua.register_function("f", []{ return true; }); lua.register_function("g", []{ return std::string("str"); }); lua.register_function("h", []{}); - lua.register_function("i", []{ return lua::nil(); }); + lua.register_function("i", []{ return lua::nil; }); } TEST_CASE( "advanced/callLambda2", "A C++ lambda is exposed to lua and called") {