源代码预处理

lua-users home
wiki

源代码预处理(或 Perl 中的 源代码过滤)是指在代码执行之前对源代码进行的一种转换。以下是一些背景信息:

源代码过滤可用于扩展语言的语法。在某些情况下,它也可以用于提高效率。

Lua 提供了 loadstring 函数(类似于其他动态语言中的 eval),可用于动态编译 Lua 代码。这使得 Lua 程序本身能够在某种程度上在进程内过滤自身或其他代码,而不是通过单独的预处理器(例如 C 预处理器)。

在下面的示例中,我们对执行向量乘法的典型方法与使用源代码过滤宏展开实现的方法进行了基准测试比较。这主要用于说明,并不一定推荐。

local lua = [[
  -- typical implementation (without filtering)
  local function cross_vector2(u, v, result)
    local u1, u2, u3 = u[1], u[2], u[3]
    local v1, v2, v3 = v[1], v[2], v[3]
    result[1], result[2], result[3] = u2*v3-u3*v2, u3*v1-u1*v3, u1*v2-u2*v1
    return result
  end

  -- test and benchmark
  local function benchmark(func)
    local t1 = os.clock()
    func()
    local t2 = os.clock()
    print("time:", t2-t1)
  end
  benchmark(function()
    local vector u = 1, 0, 0
    local vector v = 0, 1, 0
    for n = 1,5000000 do
      cross_vector(u,v,u)
      --print("DEBUG: u=" .. stringify_vector(u))
    end
  end)
  benchmark(function()
    local u = {1, 0, 0}
    local v = {0, 1, 0}
    for n = 1,5000000 do
      cross_vector2(u,v,u)
      -- print("DEBUG: u=" .. table.concat(u, ', '))
    end
  end)
]]

-- source filtering implementation
lua = string.gsub(lua, "local%s+vector%s+(%w+)%s*=%s*(%w+)%s*,%s*(%w+)%s*,%s*(%w+)", "local %1_1, %1_2, %1_3 = %2, %3, %4")
lua = string.gsub(lua, "cross_vector%s*%(%s*(%w+)%s*,%s*(%w+)%s*,%s*(%w+)%s*%)", "%3_1, %3_2, %3_3 = %1_2*%2_3-%1_3*%2_2, %1_3*%2_1-%1_1*%2_3, %1_1*%2_2-%1_2*%2_1")
lua = string.gsub(lua, "stringify_vector%((%w+)%)", "(%1_1 .. ',' .. %1_2 .. ',' .. %1_3)")

-- source filter
print("DEBUG[\n" .. lua .. "]")
assert(loadstring(lua))()

在一个系统上的结果

time: 0.937
time: 4.078

上述内容可以做得更健壮。特别是,应格外小心,以确保源代码过滤不会发生在不应该发生的地方。例如,在极少数情况下,您的程序可能包含

print("cross_vector(u,v,u) = ", cross_vector(u,v,u))

您可能不希望源代码过滤发生在字符串内部。要处理这个问题,您的源代码过滤器需要跳过字符串。这可能需要一个完整的 Lua 解析器(例如 [LuaParse]),或者您甚至可以使用一个部分词法分析器(例如 LuaBalanced)。幸运的是,与其他语言相比,Lua 相对容易解析。

如果您尝试同时使用两个独立的源代码过滤器,可能会出现交互问题。

源代码过滤与代码生成相关。例如,请参阅 LuaList:2006-09/msg00798.html 中的用法。

--DavidManura


另请参阅:LuaTokenParsing, SimpleLuaPreprocessor
RecentChanges · preferences
编辑 · 历史
最后编辑于 2008 年 12 月 18 日 下午 8:04 GMT (diff)