//////////////////////////////////////////////////////////// // // SOURCE // // This module manages the loading of lua source files into the Lua environment. // Since the source files can be reloaded over and over, this module doesn't // just load the source files. Instead, it does "source rebuilds" in which it // purges everything from the global environment, then it reinstalls everything // that should be there. That way, if you delete something from a lua source // file, it gets removed from the lua global environment. // // // THE MAKECLASS OPERATOR // // This module provides a new lua 'builtin' operator: "makeclass". This creates // a table and stores it in the global environment. The new table is meant to be // used as a class. Three fields are initially created: // // __class --> the name of the class as a string // // __index --> points back to the class. Makes it convenient to use the // class as a metatable. // // action --> a subtable of additional methods. // // If you invoke 'makeclass' on a class that already exists, the existing table // is "repaired" - the __class and __index fields are restored and the action // subtable, if not present, is recreated. If there are already functions or // constants inside the class, they are not affected. // // // THE LUA SOURCE DATABASE // // The function 'source_update' loads the lua source code from disk, and stores // it in the "source database." The source database is a table inside the lua // registry. // // The source database is a lua table where the keys are filenames, and the // values are information about that file: // // "foo.lua" : { // "name": "foo.lua", // "fingerprint": "12893129385854", // "code": "function xyz ...", // "loadresult": , // "sequence": 13 // } // // Let's break that down a little. The "name" field is just the filename. The // "fingerprint" is an encoding of the file modification date and the file // length, it is used to detect whether the file has been altered on disk // without having to reread the file. The "code" is the entire content of the // source file. The "loadresult" is the closure that results from calling the // lua 'load' function on the code. If load fails, then the "loadresult" is an // error message. Finally, "sequence" indicates the order in which the source // files are meant to be loaded. // // The operation "source_update" refreshes the source database from disk. It // doesn't reread files whose fingerprints have not changed. In a synchronous // model, we don't call source_update - instead, we update the source database // by difference transmission. // // Note that updating the source database has *no effect* on the lua global // variables (or lua function definitions). The source_update operation calls // lua's "load" on the code, but all that does is return a loaded closure. // Nothing happens to the lua invironment until you *invoke* the loaded closure. // That doesn't happen until you do a source_rebuild operation, described below. // // // SOURCE REBUILDS, IN DEPTH // // The function source_rebuild clears and then rebuilds the entire contents of // the global environment. The reason to clear the environment is that if we // didn't clear it, then removing a function from the lua source would not // remove it from the lua environment. Rebuilding the lua environment is a // multi-step process: // // * Delete everything from the global environment except class tables. // // - Class tables are kept, but the contents are cleared. // - If a class has an "actions" subtable, that is kept and cleared. // - Anything else is deleted. // // * Lua Builtin functions are reinstalled in the global environment. // // - To make this possible, a snapshot of these builtins is kept. // // * C++ functions registered with "LuaDefine" are reinstalled. // // - LuaDefine creates a registry, that registry is iterated over. // // * Lua code is reinstalled by running the closures in the source DB. // // - Simply call the "loadresult" closure to reinstall functions into the // global environment. // // Note that if you've stored any global data in the lua environment, it's gone. // So therefore, we have to provide a separate "safe" space for global data // structures. That is provided elsewhere, in the module "globaldb". // //////////////////////////////////////////////////////////// #ifndef SOURCE_HPP #define SOURCE_HPP #include "luastack.hpp" // The Lua 'makeclass' operator. // // Creates a table in the global environment with the specified name. // Adds a __class field and an __index field, and an action subtable. // If there's already a table with this name in the global environment, // leaves it there, and repairs the __class and __index fields. // int source_makeclass(lua_State *L); // source_install_and_snapshot_builtins. // // Install the lua builtins into a brand new lua state, and then create the // snapshot of the builtins (in the registry). This uses lua_openlibs, which // only works if the lua environment is brand new. Do not try to use // source_snapshot_builtins unless the lua environment has just been created // using lua_newstate! // int source_install_and_snapshot_builtins(lua_State *L); // source_update // // Read all the lua source files from disk and store them in the // source database. Also compiles these files using lua's "load" // function. Efficient: if a source file is already in the database // and hasn't been modified, it is not reloaded. // int source_update(lua_State *L); // source_rebuild // // Rebuild the lua environment: clear it out, then reinstall all the // functions that should be there. See above for more information. // int source_rebuild(lua_State *L); #endif // SOURCE_HPP