4

私はLSLをLuaトランスレータに書き込んでいますが、インクリメント演算子とデクリメント演算子の実装にさまざまな問題があります。LSLには、構文(x ++、x-、++ x、-x)のような通常のCを使用するようなものがありますが、Luaにはありません。大量の入力を避けるために、私はこれらの種類の演算子を「クリーメント」と呼びます。以下のコードでは、式の他の部分を表すために「...」を使用します。

... x += 1 ...

動作しません。cozLuaには単純な割り当てしかありません。

... x = x + 1 ...

ステートメントであるcozは機能しません。また、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]

さらに厄介で、同じ問題があります。

単純な翻訳を行うのではなく、実際に周囲のコードを分析して、特定の要素を実装する正しい方法を整理する必要があるように見え始めました。誰か簡単なアイデアがありますか?

4

5 に答える 5

1

これを実際に適切に行うには、より詳細な分析を行い、いくつかの式を複数のステートメントに分割する必要がありますが、多くはおそらく非常に簡単に翻訳できます。

少なくともCでは、ポストインクリメント/デクリメントを次の「シーケンスポイント」まで遅らせ、プレインクリメント/デクリメントを前のシーケンスポイントの前に置くことができることに注意してください。シーケンスポイントは、ステートメント間、「短絡演算子」(&&および||)などのいくつかの場所にのみ配置されます(詳細はこちら)

x = *y++ + z * f ();したがって、次のように置き換えることは問題ありません。ユーザーは、ステートメント内で他の何よりも先にインクリメントされる{ x = *y + z * f(); y = y + 1; }と想定することはできません。で使用される値は、インクリメントされる前になります。同様に、で置き換えることができますy*yyx = *--y + z * f();{ y = y - 1; x = *y + z * f (); }

于 2012-02-03T13:53:09.950 に答える
0

Luaは、この種のものの実装に対してほとんど不浸透性になるように設計されています。インタプリタは、ステートメントが実行されたときにのみ変数が変更されることを知ることができるため、一種のコンパイラ/インタプリタの問題として実行される可能性があります。

Luaでこの種のものを実装する方法はありません。一般的なケースではありません。文字列をincrement関数に渡すことで、グローバル変数に対してこれを行うことができます。ただし、ローカルの場合や、それ自体がグローバルなテーブルにある変数の場合は、明らかに機能しません。

Luaはあなたにそれをしてほしくない。制限内で作業する方法を見つけるのが最善です。そしてそれはコード分析を意味します。

于 2012-02-03T06:53:20.003 に答える
0

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

Luaは、ステートメントごとに1つの左辺値しか変更できません。関数に渡されるテーブルは、このルールの唯一の例外です。ローカルテーブルを使用してすべてのローカルを保存することができます。これは、事前作成に役立ちます。それらが含まれている式が評価される前に、それらを評価することができます。しかし、post ....-crementsは後で評価する必要があります。これは、luaでは単純に不可能です。少なくとも匿名関数を含む醜いコードがなければ不可能です。

したがって、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
}

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

価値があるのは、言語の個別のステートメントとしてポストデクリメントとプレデクリメントを使用するのが好きです。でも、表現としても使えるのは言語の欠点だと思います。糖衣構文はすぐに意味糖尿病になります。

于 2012-02-03T09:05:08.487 に答える
0

いくつかの調査と考えの結果、私はうまくいくかもしれないアイデアを思いつきました。

グローバルの場合-

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

ローカルおよび関数パラメーター(ローカル)の場合、クレメントを解析しているときにローカルであることを知っているので、4つのフラグを格納して、4つのクレメントのどれが変数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() ...
于 2012-02-03T23:23:36.113 に答える
0

コードに対する構成可能性の評価のほとんどで。データ型を別のデータ型にハードパスしようとしています。そしてそれを「翻訳者」と呼んでください。そして、これらすべてにおいて、正規表現やその他のパタ​​ーンマッチの容量を見逃しています。LSLよりもLUAにはるかに多く存在します。そして、LSLコードがLUAに渡されているので。他の機能と一緒に使ってみてください。これは、ハードパスではなく、翻訳者としての作業を定義します。

はい、私はこれが少し前に尋ねられたことを知っています。ただし、このトピックの他の視聴者にとっては。作業している環境を決して忘れないでください。彼らがあなたに与えるものをあなたができる最高の能力に使ってください。

于 2013-08-11T17:04:33.433 に答える