1 local package = package
5 package.metalua_extension_prefix = 'metalua.extension.'
7 package.mpath = os.getenv 'LUA_MPATH' or
8 './?.mlua;/usr/local/share/lua/5.1/?.mlua;'..
9 '/usr/local/share/lua/5.1/?/init.mlua;'..
10 '/usr/local/lib/lua/5.1/?.mlua;'..
11 '/usr/local/lib/lua/5.1/?/init.mlua'
14 ----------------------------------------------------------------------
15 -- resc(k) returns "%"..k if it's a special regular expression char,
16 -- or just k if it's normal.
17 ----------------------------------------------------------------------
18 local regexp_magic = table.transpose{
19 "^", "$", "(", ")", "%", ".", "[", "]", "*", "+", "-", "?" }
20 local function resc(k)
21 return regexp_magic[k] and '%'..k or k
24 ----------------------------------------------------------------------
25 -- Take a Lua module name, return the open file and its name,
26 -- or <false> and an error message.
27 ----------------------------------------------------------------------
28 function package.findfile(name, path_string)
29 local config_regexp = ("([^\n])\n"):rep(5):sub(1, -2)
30 local dir_sep, path_sep, path_mark, execdir, igmark =
31 package.config:strmatch (config_regexp)
32 name = name:gsub ('%.', dir_sep)
34 local path_pattern = string.format('[^%s]+', resc(path_sep))
35 for path in path_string:gmatch (path_pattern) do
36 --printf('path = %s, rpath_mark=%s, name=%s', path, resc(path_mark), name)
37 local filename = path:gsub (resc (path_mark), name)
38 --printf('filename = %s', filename)
39 local file = io.open (filename, 'r')
40 if file then return file, filename end
41 table.insert(errors, string.format("\tno lua file %q", filename))
43 return false, table.concat(errors, "\n")..'\n'
47 ----------------------------------------------------------------------
48 -- Execute a metalua module sources compilation in a separate process
49 ----------------------------------------------------------------------
50 local function spring_load(filename)
52 [[lua -l metalua.mlc -l -e "print(mlc.luacstring_of_luafile('%s', '%s'))"]]
53 local cmd = string.format (pattern, f, filename, filename)
54 print ("running command: ``" .. cmd .. "''")
55 local fd = io.popen (cmd)
56 local bytecode = fd:read '*a'
58 return string.undump (bytecode)
61 ----------------------------------------------------------------------
62 -- Load a metalua source file.
63 ----------------------------------------------------------------------
64 function package.metalua_loader (name)
65 local file, filename_or_msg = package.findfile (name, package.mpath)
66 if not file then return filename_or_msg end
68 return spring_load(filename_or_msg)
71 ----------------------------------------------------------------------
72 -- Placed after lua/luac loader, so precompiled files have
74 ----------------------------------------------------------------------
75 table.insert(package.loaders, package.metalua_loader)
77 ----------------------------------------------------------------------
79 ----------------------------------------------------------------------
80 function extension (name, noruntime)
81 local complete_name = package.metalua_extension_prefix..name
82 local x = require (complete_name)
83 if x==true then return
84 elseif type(x) ~= 'table' then
85 error ("extension returned %s instead of an AST", type(x))