Lua Compiler In Lua

lua-users home
wiki

The standard Lua compiler [luac.c] is a C program included with the Lua distribution.

Lua compiler in Lua

A Lua compiler that compiles Lua sourcecode to Lua bytecode could be used to bootstrap and run Lua in different environments. You only need a Lua VM that executed Lua bytecode and the Lua compiler in Lua to run any Lua program in the new environment.

Use the Lua interpreter as compiler

It is possible to compile a Lua script using only the standard interpreter:


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

A basic version of this is also included in the Lua 5.1 distribution (test/luac.lua).

If you want to emulate the behavior of luac when given multiple input files:

-- http://lua-users.org/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()

Here's a more complete version that seeks to emulate the behavior of luac (luac.c) as much as reasonably possible:

-- luac.lua - partial reimplementation of luac in Lua.

-- http://lua-users.org/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

Note: The listing (-l) can be implemented via lbci [1]. See print.lua in the lbci distribution.

Strip can be implemented in Lua (LuaList:2008-02/msg01158.html), and LuaJit has such an option added to string.dump [2].

See Also


RecentChanges · preferences
edit · history
Last edited July 4, 2011 7:20 pm GMT (diff)