源代码优化器 |
|
内联是部分求值的一种形式 [1]。
代码需要 [Metalua 0.5](开发分支)。
它包含以下文件
Download tar file from http://github.com/fab13n/metalua/tree/0.5-branch . tar xzvf fab13n-metalua-28e8e1037ab33d96c123667f4c3fc94b5aca83bc.tar.gz mv fab13n-metalua-28e8e1037ab33d96c123667f4c3fc94b5aca83bc metalua cd metalua && make Download sourceoptimizer.mlua and place in metalua/build/lib/dmlib . Download sourceoptimize.lua and place in metalua/ . Download fib.lua example and place in metalua/ . ./build/bin/metalua sourceoptimize.lua fib.lua # or ./build/bin/metalua sourceoptimize.lua fib.lua | lua -
这是一个基本示例
-- input: local y=-1 local function square(x) return x*x end local function g(x) return x >= 0 and square(square(x))+1 or 1 end while (function() y = g(y)^(1/4) return y < 2 end)() do print(y) end -- output: local y = - 1 while 1 do local __v13x = y local __v10 = 0 <= __v13x if __v10 then local __v12x = __v13x local __v14x = __v12x * __v12x __v10 = __v14x * __v14x + 1 end local __v11 = __v10 if not __v11 then __v11 = 1 end y = __v11 ^ (1 / 4) if not (y < 2) then break end print (y) end
下面是一些 Lua 示例的内联示例(在函数名前添加“local”,这是内联所必需的)
代码将内联立即求值的匿名函数
x=(function(x) return x*x end)(y()) --> local __v1x=y() x=__v1x*__v1x
以及“常量”的局部函数(函数变量从不修改)
local function square(x) return x*x end; x=square(y()) --> local __v1x=y() x=__v1x*__v1x
它消除了无用函数,例如完全内联的函数(如上所述)。它正确地执行转换以将表达式转换为语句
x = y or (function(x)z=1 return x*x end)(w) --> local __v2=y if not __v2 then local __v1x=w z=1 __v2=__v1x*__v1x end x=__v2
if (function()x=x+1 return x end)() then f() elseif (function()y=y+1 return y end)() then g() else h() end --> x=x+1 if x then f()else y=y+1 if y then g()else h()end end
使用setfenv
和调试库的堆栈级别的函数可能无法正确内联。这可能发生在访问任何全局变量时
local function f() local _ = x end f()
理论上我们不应该内联上面的函数,因为访问全局变量x
“可能”会触发全局环境上的元表,进而可能改变f
的环境,因此内联f
会改变f
调用者的环境。(在 LuaFiveTwo 中,环境将不再是一个问题,但一些调试函数仍然使用堆栈级别。)理想情况下,翻译器应该扩展以支持 Lua 注释中的pragma,这些pragma 定义了我们希望内联的程度
--!inline local function f() local _ = x end f()
这可以在每个函数的基础上进行,也可以是文件中更全局的默认设置。(有关建议的语法设计,请参阅 LuaFish 中的 luaanalyze。)
有关更多详细信息,请参阅 sourceoptimizer.mlua 的源代码。
警告:对于内联函数使用 setfenv 或利用堆栈级别的调试函数的奇特情况,可能无法正常工作(见上文)。getfenv/setfenv 问题在 LuaFiveTwo 中将不那么重要。
for i,v in ipairs(t) do
" 替换为 "local __t=t; for i=1,#__t do local v=__t[i]
"(通常更有效)。仅当文件中未重新定义 ipairs
时才执行此操作。但允许 "local ipairs = ipairs
"。
if false then ... end
"