#include "threading.h" #include "shared-table.h" #include "garbage-collector.h" #include "channel.h" #include using namespace effil; namespace { sol::object createTable(sol::this_state lua, const sol::optional& tbl) { if (tbl) { REQUIRE(tbl->get_type() == sol::type::table) << "Unexpected type for effil.table, table expected got: " << lua_typename(lua, (int)tbl->get_type()); return createStoredObject(*tbl)->unpack(lua); } return sol::make_object(lua, GC::instance().create()); } sol::object createChannel(const sol::stack_object& capacity, sol::this_state lua) { return sol::make_object(lua, GC::instance().create(capacity)); } SharedTable globalTable = GC::instance().create(); std::string getLuaTypename(const sol::stack_object& obj) { return luaTypename<>(obj); } size_t luaSize(const sol::stack_object& obj) { if (obj.is()) return SharedTable::luaSize(obj); else if (obj.is()) return obj.as().size(); throw effil::Exception() << "Unsupported type " << luaTypename(obj) << " for effil.size()"; } sol::object luaDump(sol::this_state lua, const sol::stack_object& obj) { if (obj.is()) { BaseHolder::DumpCache cache; return obj.as().luaDump(lua, cache); } else if (obj.get_type() == sol::type::table) { return obj; } throw effil::Exception() << "bad argument #1 to 'effil.dump' (table expected, got " << luaTypename(obj) << ")"; } sol::table luaThreadConfig(sol::this_state state, const sol::stack_object& obj) { REQUIRE(obj.valid() && obj.get_type() == sol::type::function) << "bad argument #1 to 'effil.thread' (function expected, got " << luaTypename(obj) << ")"; auto lua = sol::state_view(state); const sol::function func = obj.as(); auto config = lua.create_table_with( "path", lua["package"]["path"], "cpath", lua["package"]["cpath"], "step", 200 ); auto meta = lua.create_table_with(); meta[sol::meta_function::call] = [func](sol::this_state lua, const sol::stack_table& self, const sol::variadic_args& args) { return sol::make_object(lua, GC::instance().create( self["path"], self["cpath"], self["step"], func, args)); }; config[sol::metatable_key] = meta; return config; } } // namespace extern "C" #ifdef _WIN32 __declspec(dllexport) #endif int luaopen_effil(lua_State* L) { sol::state_view lua(L); Thread::exportAPI(lua); SharedTable::exportAPI(lua); Channel::exportAPI(lua); const sol::table gcApi = GC::exportAPI(lua); const sol::object gLuaTable = sol::make_object(lua, globalTable); const auto luaIndex = [gcApi, gLuaTable]( const sol::stack_object& obj, const std::string& key) -> sol::object { if (key == "G") return gLuaTable; else if (key == "gc") return gcApi; else if (key == "version") return sol::make_object(obj.lua_state(), "0.1.0"); return sol::nil; }; sol::usertype type("new", sol::no_constructor, "thread", luaThreadConfig, "thread_id", threadId, "sleep", sleep, "yield", yield, "table", createTable, "rawset", SharedTable::luaRawSet, "rawget", SharedTable::luaRawGet, "setmetatable", SharedTable::luaSetMetatable, "getmetatable", SharedTable::luaGetMetatable, "channel", createChannel, "type", getLuaTypename, "pairs", SharedTable::globalLuaPairs, "ipairs", SharedTable::globalLuaIPairs, "next", SharedTable::globalLuaNext, "size", luaSize, "dump", luaDump, "hardware_threads", std::thread::hardware_concurrency, sol::meta_function::index, luaIndex ); sol::stack::push(lua, type); sol::stack::pop(lua); sol::stack::push(lua, EffilApiMarker()); return 1; }