Source Optimizer |
|
内联是部分求值的一种形式[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 和带有 debug 库的堆栈级别的函数可能无法正确内联。这可能发生在访问任何全局变量时。
local function f() local _ = x end f()
理论上,我们不应该内联上述函数,因为访问全局变量 x "可能"会触发全局环境的元表,进而可能改变 f 的环境,因此内联 f 会改变 f 调用者的环境。(在LuaFiveTwo中,环境将不再是问题,但某些 debug 函数仍然会使用堆栈级别。)理想情况下,翻译器应该扩展以支持 Lua 注释中的 pragma,这些 pragma 定义了我们希望内联的激进程度。
--!inline local function f() local _ = x end f()
这可以按函数进行,也可以是文件中的更全局的默认设置。(请参阅 LuaFish 中的 luaanalyze,以获取建议的语法设计。)
更多详情请参阅 sourceoptimizer.mlua 的源代码。
警告:对于某些不常见的情况,例如内联函数使用 setfenv 或利用堆栈级别的 debug 函数(见上文),可能无法正常工作。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"。