源代码预处理

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))()

在一个系统上的结果

时间: 0.937
时间: 4.078

以上可以做得更健壮。特别是,应该格外小心以确保源代码过滤不会发生在不希望的地方。例如,在极端情况下,如果你的程序有

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

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

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

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

--DavidManura


另请参阅: LuaTokenParsingSimpleLuaPreprocessor
最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2008 年 12 月 19 日凌晨 2:04 GMT (差异)