-- given a global_db, makes an accessor that fetches named -- tables from that global_db. function make_global_accessor(db) return function(name) local global = rawget(db, name) if type(global) ~= "table" then global = {} rawset(db, name, global) end return global end end -- The sandbox list - a list of the builtin functions that gets imported -- into world models. This is a very weak form of sandboxing, a world -- model can still easily use functions that are not on this list. If you -- want stronger sandboxing, you need to not link in certain builtins at all. -- -- Omitted from this list: "debug", "dofile", "getfenv", "io", "jit", -- "load", "loadfile", "loadstring", "module", "newproxy", "os", "package", -- "pcall", "require", "xpcall" -- local sandbox_list = { "assert", "bit", "error", "getmetatable", "inspect", "ipairs", "math", "next", "pairs", "print", "rawequal", "rawget", "rawset", "select", "setmetatable", "tonumber", "tostring", "type", "unpack" } -- Make a world model. -- function make_world_model() genv = {} genv._G = genv meta = {} meta.class_db = {} meta.global_db = {} meta.source_db = {} meta.tangible_db = {} meta.__newindex = function() error("Global environment is read-only") end -- meta.__metatable = false genv.class = classdb.accessor(meta.class_db) genv.global = make_global_accessor(meta.global_db) for i,name in ipairs(sandbox_list) do genv[name] = _G[name] end setmetatable(genv, meta) return genv end