Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • a1ae43fa74eee51a21abcdbb9d052cc1d7abbf59
  • master par défaut protégée
  • tichadou2015-master-patch-52256
3 résultats

manger.py

Blame
  • CRTPLuaScriptObject.hh 6,48 Kio
    #pragma once
    
    #include "LuaContext.hh"
    
    #include "lua.hpp"
    #include <vector>
    #include <cstdio>
    
    namespace Vivy::Script
    {
    // clang-format off
    #define LUA_DECL_METHOD(class, name) luaL_Reg{ #name, class ::name   }
    #define LUA_DECL_CREATE(class)       luaL_Reg{ "new", class ::CREATE }
    
    #define script_class(theClassName) \
        class theClassName final : public CRTPLuaScriptObject<theClassName>
    
    #define method_list static constexpr inline auto
    
    #define LUA_SCRIPTABLE_CLASS(theClassName)                      \
        VIVY_UNMOVABLE_OBJECT(theClassName)                         \
        static constexpr char className[] = #theClassName;          \
        friend CRTPLuaScriptObject<theClassName>;                   \
        theClassName(lua_State *) noexcept;                         \
        ~theClassName() noexcept;
    // clang-format on
    
    // CRTP to expose objects to Lua
    template <class Object> class CRTPLuaScriptObject {
    protected:
        static int GC(lua_State *L) noexcept
        {
            const Object *obj = reinterpret_cast<const Object *>(lua_topointer(L, 1));
            auto *context     = LuaContext::getContext(L);
            err(context) << "Call destructor for " << Object::className << "\n";
            obj->~Object();
            return 0;
        }
    
        static int CREATE(lua_State *L) noexcept
        {
            Object *obj = reinterpret_cast<Object *>(lua_newuserdata(L, sizeof(Object)));
            new (obj) Object(L);
            luaL_getmetatable(L, Object::className);
            lua_setmetatable(L, -2);
            return 1;
        }
    
        static Object *CHECK(lua_State *L, int index) noexcept
        {
            luaL_checktype(L, index, LUA_TUSERDATA);
            auto *context = LuaContext::getContext(L);
            Object *obj   = reinterpret_cast<Object *>(luaL_checkudata(L, index, Object::className));
            if (obj == nullptr) {
                err(context) << "Type error, userdata is not of class " << Object::className << "\n";
                luaL_typeerror(L, index, Object::className);
            }
            return obj;
        }
    
        static inline constexpr luaL_Reg luaRegDefaultGC = { "__gc", GC };
    
    public:
        static void Register(lua_State *L) noexcept
        {
            auto *context = LuaContext::getContext(L);
    
            // Fill the method table, newclass = {}
            lua_newtable(L);
            const int methodtable = lua_gettop(L);
    
            // Fill the meta-table, metatable = {}
            {
                luaL_newmetatable(L, Object::className);
                const int metatable = lua_gettop(L);
    
                lua_pushliteral(L, "__metatable");
                lua_pushvalue(L, methodtable);
                lua_settable(L, metatable);
    
                lua_pushliteral(L, "__index");
                lua_pushvalue(L, methodtable);
                lua_settable(L, metatable);
    
                for (const luaL_Reg &meta : Object::metaMethods) {
                    err(context) << "Register " << Object::className << "::" << meta.name << "\n";
                    lua_pushstring(L, meta.name);
                    lua_pushcfunction(L, meta.func);
                    lua_settable(L, metatable);
                }
    
                lua_pop(L, 1);
            }
    
            // Fill the method table with specified methods
            for (const luaL_Reg &method : Object::methods) {
                err(context) << "Register " << Object::className << "::" << method.name << "\n";
                lua_pushstring(L, method.name);
                lua_pushcfunction(L, method.func);
                lua_settable(L, methodtable);
            }
    
            // Last thing to do it seems...
            lua_pop(L, 1);                              // drop method-table
            lua_register(L, Object::className, CREATE); // Register the create method
            err(context) << "Register constructor " << Object::className << "()\n";
        }
    };
    
    // Option declaration
    script_class (OptionDeclaration) {
        LUA_SCRIPTABLE_CLASS(OptionDeclaration)
    
        static int addOptionContent(lua_State *) noexcept;
    
        method_list metaMethods = { luaRegDefaultGC, LUA_DECL_CREATE(OptionDeclaration) };
        method_list methods     = { LUA_DECL_METHOD(OptionDeclaration, addOptionContent) };
    };
    
    // Job declaration
    script_class (JobDeclaration) {
        LUA_SCRIPTABLE_CLASS(JobDeclaration)
    
        static int setName(lua_State *) noexcept;
        static int setOptions(lua_State *) noexcept;
        static int setImportFromScript(lua_State *) noexcept;
    
        method_list metaMethods = { luaRegDefaultGC, LUA_DECL_CREATE(JobDeclaration) };
        method_list methods     = { LUA_DECL_METHOD(JobDeclaration, setName),
                                LUA_DECL_METHOD(JobDeclaration, setOptions),
                                LUA_DECL_METHOD(JobDeclaration, setImportFromScript) };
    };
    
    // Function declaration
    script_class (FunctionDeclaration) {
        LUA_SCRIPTABLE_CLASS(FunctionDeclaration)
    
        static int setName(lua_State *) noexcept;
        static int setImportFromScript(lua_State *) noexcept;
    
        method_list metaMethods = { luaRegDefaultGC, LUA_DECL_CREATE(FunctionDeclaration) };
        method_list methods     = { LUA_DECL_METHOD(FunctionDeclaration, setName),
                                LUA_DECL_METHOD(FunctionDeclaration, setImportFromScript) };
    };
    
    // Module declaration
    script_class (ModuleDeclaration) {
        LUA_SCRIPTABLE_CLASS(ModuleDeclaration)
    
        static int setName(lua_State *) noexcept;
        static int setAuthorName(lua_State *) noexcept;
        static int setRevision(lua_State *) noexcept;
        static int setDescription(lua_State *) noexcept;
        static int setImplementationFile(lua_State *) noexcept;
        static int setImports(lua_State *) noexcept;
        static int setOptions(lua_State *) noexcept;
        static int setFunctions(lua_State *) noexcept;
        static int setJobs(lua_State *) noexcept;
    
        method_list metaMethods = { luaRegDefaultGC, LUA_DECL_CREATE(ModuleDeclaration) };
        method_list methods     = {
            LUA_DECL_METHOD(ModuleDeclaration, setName),
            LUA_DECL_METHOD(ModuleDeclaration, setDescription),
            LUA_DECL_METHOD(ModuleDeclaration, setRevision),
            LUA_DECL_METHOD(ModuleDeclaration, setAuthorName),
            LUA_DECL_METHOD(ModuleDeclaration, setImplementationFile),
            LUA_DECL_METHOD(ModuleDeclaration, setImports),
            LUA_DECL_METHOD(ModuleDeclaration, setOptions),
            LUA_DECL_METHOD(ModuleDeclaration, setFunctions),
            LUA_DECL_METHOD(ModuleDeclaration, setJobs),
        };
    };
    
    // Holds all the free functions (well, not really free functions here...)
    script_class (FreeFunctions) {
        LUA_SCRIPTABLE_CLASS(FreeFunctions)
    
        static int print(lua_State *) noexcept;
    
        method_list metaMethods = { luaRegDefaultGC, LUA_DECL_CREATE(FreeFunctions) };
        method_list methods     = { LUA_DECL_METHOD(FreeFunctions, print) };
    };
    }