2012-02-03 14 views
4

LSLをLuaトランスレータに書いていますが、増分と減分の演算子を実装するのにさまざまな問題があります。 LSLは普通のCのような構文(x ++、x--、++ x、 - x)を使っていますが、Luaはそうではありません。大量の入力を避けるために、私はこれらの種類の演算子を「クリエイティブ」と呼びます。以下のコードでは、式の他の部分を表すために "..."を使用します。Luaへの翻訳時にポスト/プリインクリメント/デクリメントを実装する

... x += 1 ... 

coz Luaは簡単な割り当てしかありません。

... x = x + 1 ... 

これは文であり、式では文を使用できません。 LSLは表現のクリエーションを使用できます。

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

それは式の正しい値を提供しているが、Luaは番号の値渡しなので、元の変数が変更されません。変数を実際に変更することができれば、すべてが有効です。環境に迷惑をかけるようなことはあまり良いことではないかもしれません。私は次にそれを調べると思います。翻訳者は範囲の詳細を出力できます。

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

文句を言わない仕事を「それは文の」理由 - 上記の関数が存在すると仮定すると、

他の解決策は本当に乱雑になり始めます。ワームの全体の缶になっ

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

-

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

は、元LSLコードはこのようなものである場合を除いて、正常に動作します。関数内のテーブルを使用する -

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を解析してる時に、私は、私に教えて4つのフラグを格納することができます4つのクリエーションのうちの1つが変数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

ルアは、この種の実装にはほとんど影響を受けないように設計されています。インタプリタは、文が実行されたときにのみ変数が変化することを知ることができるため、コンパイラ/インタプリタの問題の一種として実行される可能性があります。

ルアにはこの種のものを実装する方法はありません。一般的なケースではありません。インクリメント関数に文字列を渡すことによって、グローバル変数に対して行うことができます。しかし明らかに、それは地元の人々にとって、あるいはそれ自体がグローバルなテーブルにある変数に対しては機能しません。

ルアはあなたにそれをしたくありません。制限内で作業する方法を見つけることが最善です。それはコード分析を意味します。

+0

_G ["variable"]はグローバルに有効です。テーブル内の変数は問題ではなく、LSLにはそのようなことはありません。それはまだ地元の人を去らせる。関数内で定義された関数は、上位レベルのローカルにアクセスできるため、作業が楽になる可能性があります。 –

0

あなたの提案されたソリューションは、Lua変数がすべてグローバルである場合にのみ機能します。 LSLもそうでない限り、異なる場所で同じ方法で呼ばれる変数を使用するLSLプログラムの翻訳には問題があります。

ルアは文ごとに1つの左辺値しか変更できません。関数に渡されるテーブルはこのルールの唯一の例外です。あなたはローカルのテーブルを使ってすべての地元の人々を保存することができます。それは、あなたの前身を助けるでしょう。彼らは彼らが含まれている表現が喚起される前に評価することができます。しかし、post -...-クリエーションは、後で評価する必要があります。これは、少なくとも匿名関数を含む醜いコードがなくても、単に可能ではありません。

あなたは1つの選択肢があります:いくつかの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 
} 

ですから、基本的にごとに2つのステートメントを追加する必要がありますあなたの声明で使用された創造複雑な構造の場合、式が評価される順序を計算することを意味します。

何が価値あるのか、私は言語の個々のステートメントとしてのポストデクリメントとプリデクリメントが好きです。しかし、私はそれを表現として使うことができるときには、それを言語の欠陥とみなします。統語砂糖はすぐに意味論的な糖尿病になります。

+1

ええと、あなたは私の提案した解決策に、_Gを使っていますか?これは、グローバルのために使用されるソリューションの半分にすぎません。地元民の質問の終わりに私の提案された解決策を見ましたか? –

+0

ああ、私はそれを見ませんでした。それは私のものよりもきれいです。謝罪。私を無視。 – kikito

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

コードの構成可能性の評価のほとんどは、あなたは、あるタイプから別のタイプへデータタイプを厳密に渡そうとしています。それを「翻訳者」と呼んでください。そして、このすべてにおいて、正規表現と他のパターンマッチ能力が欠けています。 LSLよりもはるかにLUAに存在します。 LSLコードはLUAに渡されているためです。他の機能と一緒に使用してみてください。これはハードパスよりも翻訳者としての仕事をより明確にします。

はいこれはしばらく前に尋ねられました。しかし、このトピックの他の視聴者のために。あなたが働いている環境を決して忘れないでください。彼らがあなたにできることをあなたができる最高の能力に与える。

関連する問題