原始碼前處理 |
|
原始碼過濾可用於延伸語言的語法。在某些情況下,它還可用於提升效率。
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))()
一個系統上的結果
以上內容可以設計得更健全。特別是,應該更加小心,以確保原始碼過濾出現在非預期的位置。例如,在程式包含在遠端情況下
print("cross_vector(u,v,u) = ", cross_vector(u,v,u))
您可能不希望在字串內執行原始碼過濾。要處理這一點,您的原始碼過濾器必須略過字串。這可能需要一個完整的 Lua 分析器(例如 [LuaParse]),或者您甚至可以用一個部分詞法分析器(例如 LuaBalanced)來處理。幸運的是,與其他語言相比,Lua 相對容易進行分析。
如果您嘗試同時使用兩個獨立的原始碼過濾器,可能會發生互動問題。
原始碼過濾與程式碼產生有關。例如,請參閱 LuaList:2006-09/msg00798.html 中的用法。