2021-01-02 13:31:18 -05:00
|
|
|
////////////////////////////////////////////////////////////
|
2020-11-27 13:21:07 -05:00
|
|
|
//
|
2021-01-12 14:14:38 -05:00
|
|
|
// SOURCE
|
2020-11-27 13:21:07 -05:00
|
|
|
//
|
2021-01-12 14:14:38 -05:00
|
|
|
// 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.
|
2021-01-02 13:31:18 -05:00
|
|
|
//
|
|
|
|
|
//
|
2021-01-12 14:14:38 -05:00
|
|
|
// THE MAKECLASS OPERATOR
|
2021-01-02 13:31:18 -05:00
|
|
|
//
|
2021-01-12 14:14:38 -05:00
|
|
|
// 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": <function-23>,
|
|
|
|
|
// "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".
|
2021-01-02 13:31:18 -05:00
|
|
|
//
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
2020-11-27 13:21:07 -05:00
|
|
|
|
|
|
|
|
#ifndef SOURCE_HPP
|
|
|
|
|
#define SOURCE_HPP
|
|
|
|
|
|
|
|
|
|
#include "luastack.hpp"
|
|
|
|
|
|
2021-01-12 14:14:38 -05:00
|
|
|
// 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);
|
2020-12-05 18:57:53 -05:00
|
|
|
|
2021-01-12 14:14:38 -05:00
|
|
|
// 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);
|
2021-01-02 13:31:18 -05:00
|
|
|
|
2021-01-12 14:14:38 -05:00
|
|
|
// 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);
|
2021-01-02 13:31:18 -05:00
|
|
|
|
2021-01-12 14:14:38 -05:00
|
|
|
// source_rebuild
|
|
|
|
|
//
|
|
|
|
|
// Rebuild the lua environment: clear it out, then reinstall all the
|
|
|
|
|
// functions that should be there. See above for more information.
|
|
|
|
|
//
|
2020-12-05 18:57:53 -05:00
|
|
|
int source_rebuild(lua_State *L);
|
2020-11-27 13:21:07 -05:00
|
|
|
|
|
|
|
|
#endif // SOURCE_HPP
|
|
|
|
|
|
|
|
|
|
|