5

「foo」という名前の別のプログラミング言語を実装するためにpythonを使用しています。foo のコードはすべて python に変換され、同じ python インタープリターで実行されるため、python に JIT 変換されます。

以下は foo のコードの一部です。

function bar(arg1, arg2) {
    while (arg1 > arg2) {
        arg2 += 5;
    }
    return arg2 - arg1;
}

これは次のように変換されます:

def _bar(arg1, arg2):
    while arg1 > arg2:
        arg2 += 5
        watchdog.switch()
    watchdog.switch()
    return arg2 - arg1

「ウォッチドッグ」は、言語が信頼できないコードを実行するため、リソースの使用を監視/制限する greenlet (生成されたコードも greenlet コンテキストで実行されます) です。

例でわかるように、python コードが生成される前に、ウォッチドッグ スイッチを追加し、関数識別子に小さな変更を加えるために、解析ツリーに小さな変更が加えられます。

すべての要件を満たすには、言語にトレースバック/デバッグ機能も追加する必要があります。これにより、python ランタイムが例外をスローしたときに、ユーザーが表示するのは foo のコード トレースバック (生成された python コード トレースバックを表示するのではなく) になります。

ユーザーが次の内容で「program.foo」という名前のファイルを作成するとします。

1  function bar() {
2      throw Exception('Some exception message');
3  }
4
5  function foo() {
6      output('invoking function bar');
7      bar();
8  }
9
10 foo();

これは次のように変換されます:

def _bar():
    watchdog.switch()
    raise Exception('Some exception message')

def _foo():
    print 'invoking function bar'
    watchdog.switch()
    _bar()

watchdog.switch()
_foo()

次に、「program.foo」の出力は次のようになります。

invoking function bar
Traceback (most recent call last):
  File "program.foo", line 10
    foo();
  File "program.foo", line 7, inside function 'foo'
    bar();
  File "program.foo", line 2, inside function 'bar'
    throw Exception('Some exception message');
Exception: Some exception message

それを行う簡単な方法はありますか?Pythonバイトコードはインタープリター実装の内部にあるため、インストルメント化を伴わないソリューションを好みますが、他に何もない場合は、バイトコードをインストルメント化することもできます。

4

1 に答える 1

2

コンテキスト (ファイル名、関数、行番号など) をグローバル スタックに記録するデコレータを使用して、生成された各 Python 関数を装飾できます。次に、独自の Exception クラスを派生させ、インタープリターのトップレベルでキャッチできます。最後に、グローバル デバッグ スタックからの情報を使用して、好きなものを出力します。

于 2012-03-09T13:34:54.753 に答える