2012-02-03 66 views
4

我正在給Lua翻譯器寫一個LSL,並且在執行遞增和遞減操作符時遇到各種麻煩。 LSL具有使用通常的C語法(x ++,x--,++ x,--x)的這種東西,但Lua不會。爲了避免大量的打字,我將這些操作符稱爲「拼接」。在下面的代碼中,我將使用「...」來表示表達式的其他部分。當翻譯成Lua時實現post/pre increment/decrement

... x += 1 ... 

不會工作,因爲Lua只有簡單的任務。

... x = x + 1 ... 

不會工作因爲這是一個聲明,並且Lua不能在表達式中使用語句。 LSL可以在表達式中使用crements。

function preIncrement(x) x = x + 1; return x; end 
... preIncrement(x) ... 

雖然它提供在表達正確的值,Lua是通過對數字值傳遞,所以原來的變量不被改變。如果我能得到這個實際改變的變量,那麼一切都很好。混淆環境可能不是一個好主意,不知道範圍x是什麼。我想我會在下面進行調查。翻譯者可以輸出範圍細節。

假設上述功能的存在 -

... x = preIncrement(x) ... 

對於慣於工作「這是一個聲明」的原因。

其他解決方案開始變得非常混亂。

x = preIncrement(x) 
... x ... 

工作正常,但在原來的LSL代碼是這樣的 -

while (doOneThing(x++)) 
{ 
    doOtherThing(x); 
} 

,這已經成爲蠕蟲病毒的一個整體可以。在功能中使用表格 -

function preIncrement(x) x[1] = x[1] + 1; return x[1]; end 
temp = {x} 
... preincrement(temp) ... 
x = temp[1] 

更加混亂,並且具有相同的問題。

開始看起來像我可能不得不實際分析周圍的代碼,而不是做簡單的翻譯來理清實現任何給定的內容的正確方法。任何人有任何簡單的想法?

回答

0

經過一番研究和思考後,我想出了一個可能有效的想法。

對於全局 -

function preIncrement(x) 
    _G[x] = _G[x] + 1 
    return _G[x] 
end 
... preIncrement("x") ... 

當地人和功能參數(這是當地人),我知道我在解析crement,這是本地的時間,我可以存儲四個標誌告訴我哪的四個創建中正在使用變量AST結構。然後,當談到時間輸出變量的定義,我可以輸出像這樣 -

local x; 
function preIncrement_x() x = x + 1; return x; end 
function postDecrement_x() local y = x; x = x - 1; return y; end 
... preIncrement_x() ... 
0

Lua被設計成對這類事情的實現幾乎不受影響。這可能是由於編譯器/解釋器的問題,因爲解釋器可以知道變量只有在執行語句時纔會改變。

在Lua中沒有辦法實現這種事情。不在一般情況下。您可以通過將字符串傳遞給增量函數來爲全局變量執行此操作。但顯然它不適用於本地人,或者對於本身是全局的表中的變量。

Lua不希望你這樣做;最好找到一種在限制範圍內工作的方式。這意味着代碼分析。

+0

_G [「variable」]應該適用於全局變量。表格內的變量不是問題,LSL沒有這樣的事情。這仍然留給當地人。函數內部定義的函數可以訪問上層的本地人,這樣可以使事情變得更容易。 – 2012-02-03 07:44:45

0

只有當你的Lua變量都是全局變量時,你提出的解決方案才能工作。除非LSL也這樣做,否則在使用變量的LSL程序翻譯時會遇到麻煩,這些變量在不同的地方被稱爲相同的方式。

Lua只能修改每個語句的一個左值 - 傳遞給函數的表是這個規則的唯一例外。你可以使用本地表來存儲所有的本地人,這可以幫助你解決前期的問題。他們可以在它們被包含在表達式中被評估之前被評估。但後期......必須在後期進行評估,這在lua中是不可能的 - 至少在沒有涉及匿名函數的醜陋代碼的情況下是不可能的。

所以你有一個選擇:你必須接受一些LSL語句將被翻譯成幾個Lua語句。

說你有增量LSL聲明是這樣的:

f(integer x) { 
    integer y = x + x++; 
    return (y + ++y) 
} 

您可以翻譯這Lua的聲明是這樣的:

function f(x) { 
    local post_incremented_x = x + 1 -- extra statement 1 for post increment 
    local y = x + post_incremented_x 
    x = post_incremented_x -- extra statement 2 for post increment 

    local pre_incremented_y = y + 1 
    return y + pre_incremented_y 
    y = pre_incremented_y -- this line will never be executed 
} 

所以你基本上會以每年新增兩條語句..- crement在你的陳述中使用。對於複雜的結構,這將意味着計算表達式的評估順序。

對於什麼是值得的,我喜歡在語言中發佈遞減和作爲單個語句的預定義。但是,我認爲它也可以用作表達方式,這是語言的一個缺陷。句法糖迅速變成語義糖尿病。

+1

恩,你是指我用_G提出的解決方案嗎?這只是解決方案的一半,用於全局。您在本地人問題結束時是否看到我提出的解決方案? – 2012-02-03 09:21:20

+0

哦,我沒有看到它。它比我的乾淨。道歉。不理我。 – kikito 2012-02-03 09:26:12

1

我認爲要真正做到這一點,您將不得不做一些更詳細的分析,並將一些表達式拆分爲多個語句,儘管許多語句可能會非常直接地進行翻譯。請注意,至少在C中,您可以將後增量/減量延遲到下一個「序列點」,並將之前的增量/減量延遲到前一個序列點之前;序列點僅位於在幾個地方:語句之間,在「短路運營商」(&&||)等(more info here)

所以它的精細與{ x = *y + z * f(); y = y + 1; } —用戶更換x = *y++ + z * f();不允許假設y將在語句中的任何其他內容之前遞增,只有在*y中使用的值將在y之前遞增。同樣,x = *--y + z * f();可以替換爲{ y = y - 1; x = *y + z * f(); }

0

在大部分的可配置性評估的代碼。您試圖將數據類型從一個傳遞到另一個。並稱之爲'翻譯'。在這一切中,你都會錯過正則表達式和其他模式匹配能力。 LUA比LSL更多。並且由於LSL代碼正在傳遞給LUA。嘗試使用它們以及其他功能。這可以將工作更多地定義爲翻譯,而不是硬通。

是的,我知道這是前一陣子問過的。雖然,這個話題的其他觀衆。永遠不要忘記你正在工作的環境。永遠。使用他們給你的最好的能力。