Lua 编译器在 Lua 中 |
|
lua -e 'io.write(string.dump(assert(loadfile())))' <sample.lua >sample.out
Lua 5.1 发行版中也包含了此功能的基本版本(test/luac.lua)。
如果您想模拟 luac
在给定多个输入文件时的行为
-- https://lua-users.lua.ac.cn/wiki/LuaCompilerInLua -- compile the input file(s) local chunk = {} for _, file in ipairs(arg) do chunk[#chunk + 1] = assert(loadfile(file)) end if #chunk == 1 then chunk = chunk[1] else -- combine multiple input files into a single chunk for i, func in ipairs(chunk) do chunk[i] = ("%sloadstring%q(...);"):format( i==#chunk and "return " or " ", string.dump(func)) end chunk = assert(loadstring(table.concat(chunk))) end local out = assert(io.open("luac.lua.out", "wb")) out:write(string.dump(chunk)) out:close()
以下是一个更完整的版本,它试图尽可能地模拟 luac(luac.c)的行为
-- luac.lua - partial reimplementation of luac in Lua. -- https://lua-users.lua.ac.cn/wiki/LuaCompilerInLua -- David Manura et al. -- Licensed under the same terms as Lua (MIT license). local outfile = 'luac.out' -- Parse options. local chunks = {} local allowoptions = true local iserror = false local parseonly = false while arg[1] do if allowoptions and arg[1] == '-' then chunks[#chunks + 1] = arg[1] allowoptions = false elseif allowoptions and arg[1] == '-l' then io.stderr:write('-l option not implemented\n') iserror = true elseif allowoptions and arg[1] == '-o' then outfile = assert(arg[2], '-o needs argument') table.remove(arg, 1) elseif allowoptions and arg[1] == '-p' then parseonly = true elseif allowoptions and arg[1] == '-s' then io.stderr:write("-s option ignored\n") elseif allowoptions and arg[1] == '-v' then io.stdout:write(_VERSION .. " Copyright (C) 1994-2008 Lua.org, PUC-Rio\n") elseif allowoptions and arg[1] == '--' then allowoptions = false elseif allowoptions and arg[1]:sub(1,1) == '-' then io.stderr:write("luac: unrecognized option '" .. arg[1] .. "'\n") iserror = true break else chunks[#chunks + 1] = arg[1] end table.remove(arg, 1) end if #chunks == 0 then io.stderr:write("luac: no input files given\n") iserror = true end if iserror then io.stdout:write[[ usage: luac [options] [filenames]. Available options are: - process stdin -l list -o name output to file 'name' (default is "luac.out") -p parse only -s strip debug information -v show version information -- stop handling options ]] os.exit(1) end -- Load/compile chunks. for i,filename in ipairs(chunks) do chunks[i] = assert(loadfile(filename ~= '-' and filename or nil)) end if parseonly then os.exit(0) end -- Combine chunks. if #chunks == 1 then chunks = chunks[1] else -- Note: the reliance on loadstring is possibly not ideal, -- though likely unavoidable. local ts = { "local loadstring=loadstring;" } for i,f in ipairs(chunks) do ts[i] = ("loadstring%q(...);"):format(string.dump(f)) end --possible extension: ts[#ts] = 'return ' .. ts[#ts] chunks = assert(loadstring(table.concat(ts))) end -- Output. local out = outfile == '-' and io.stdout or assert(io.open(outfile, "wb")) out:write(string.dump(chunks)) if out ~= io.stdout then out:close() end
注意:列表 (-l) 可以通过 lbci [1] 实现。请参阅 lbci 发行版中的 print.lua。
Strip 可以用 Lua 实现 (LuaList:2008-02/msg01158.html),并且 LuaJit 在 string.dump 中添加了此选项 [2]。