Lua 編譯器以 Lua 編寫

lua-users home
wiki

Lua 標準編譯器 [luac.c] 是 Lua 程式所包含的 C 程式。

Lua 編譯器以 Lua 編寫

Lua 編譯器將 Lua 原始碼編譯成 Lua 位元組碼,可作為在不同環境中啟動和執行 Lua 的依據。你只需要一個執行 Lua 位元組碼的 Lua VM 和 Lua 編譯器以 Lua 在新環境中執行任何 Lua 程式。

將 Lua 編譯器用作編譯器

僅使用標準編譯器就能編譯 Lua 腳本。

lua -e 'io.write(string.dump(assert(loadfile())))' <sample.lua >sample.out

Lua 5.1 程式中亦包含這項基本版本的程式(test/luac.lua)。

如果你想在提供多個輸入檔案時複製 luac 的行為

-- https://lua-users.dev.org.tw/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.dev.org.tw/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。

在 Lua 中可以實作一項功能用來清除 LuaList:2008-02/msg01158.html),而 LuaJit 也將此選項新增至 string.dump [2] 中。

另請參閱


最近更新 · 喜好設定
編輯 · 歷史記錄
最後編輯時間 2023 年 8 月 14 日 晚上 11:18 GMT (diff)