[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: package system modification (module loaders)
- From: Mike Pall <mikelu-0501@...>
- Date: Wed, 12 Jan 2005 02:18:56 +0100
Hi,
Tiago Dionizio wrote:
> Looking at the new package system for Lua 5.1 (work 4) i was thinking
> about a simple feature that could be added to the core system.
>
> The ability to register module loaders, enabling a user to load lua
> scripts from specific locations or even compressed files (along with
> many other uses).
Well, the
setmetatable(package.preload, { __index = your_loader })
trick from Diego sure is nice.
But you made me think about a different idea: require() uses hardcoded
control flow to go through package.loaded, package.preload, package.cpath
and package.path. Why not use a single 'path table' that holds closures for
individual loaders (bound to individual path elements):
package.path = {
loader_table(package.preload), -- could do without a closure here
loader_c "./?.so",
loader_c "/usr/local/lib/lua/5.1/?.so",
loader_lua "./?.lua",
loader_lua "/usr/local/share/lua/5.1/?.lua",
loader_lua "/usr/local/share/lua/5.1/?/init.lua",
}
Sample implementation (untested):
function package.loader_table(t)
return function(name) return t[name] end
end
local function exists(path, name)
local file = string.gsub(path, "%?", name)
local f = io.open(file)
return f and f:close() and file
end
function package.loader_c(path)
return function(name)
local file = exists(path, name)
local init = "luaopen_" .. string.gsub(name, "%.", "_")
return file and assert(loadlib(file, init))
end
end
function package.loader_lua(path)
return function(name)
local file = exists(path, name)
return file and assert(loadfile(file))
end
end
function require(name)
local res = package.loaded[name]
if res then return res end
for _,loader in ipairs(package.path) do
local f = loader(name)
if f then
package.loaded[name] = true
res = f(name)
package.loaded[name] = res
return res
end
end
error("cannot find "..name.." in package path", 2)
end
Adding a zip loader, a DLL-path-relative-to-EXE loader and so on is very
simple (for anyone who wants it -- not part of the core). Manipulation of
the path and the loader priorities can be done with standard Lua functions
(table.insert, table.remove) and does not require string processing and/or
patching the core.
IMHO this is much cleaner and simpler than the current hardcoded approach.
It may even use less code than the current approach if properly coded in C
(because we can get rid of path splitting and other cruft).
Opinions?
Bye,
Mike