問題タブ [interpreter]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
4 に答える
1608 参照

compiler-construction - バイトコード解析命令と機械語の違いは?

「バイトコード プログラムは通常、一度に 1 つずつ命令を解析することによって実行されます。この種のバイトコード インタープリターは非常に移植性があります。動的トランスレーターまたは「ジャストインタイム」(JIT) コンパイラーと呼ばれる一部のシステムは、バイトコードを機械語に変換します。実行時に必要に応じて: これにより、仮想マシンは移植できなくなります。」

この段落に関する質問は次のとおりです。バイトコードが処理された後、解析された命令と機械語 (または機械コード) の違いは何ですか?

0 投票する
6 に答える
4466 参照

python - なぜPythonは解釈する前にソースをバイトコードにコンパイルするのですか?

なぜPythonは解釈する前にソースをバイトコードにコンパイルするのですか?

ソースから直接解釈してみませんか?

0 投票する
5 に答える
1498 参照

java - 抽象構文ツリーベースのインタープリターでクラスを表現する方法

関連する質問を読みましたが、質問に直接対処しているようには見えません。PHPスクリプトインタープリターの作成に取り組んでいます。クラス以外のすべてに対して適切なノードを生成する AST があります。クラスの処理は関数の処理とは少し異なるため、スタンドアロンのクラスや他のクラスを拡張するクラスを処理する方法を探しています。

ANTLR を見てきましたが、これは組み込みプラットフォーム用であるため、オーバーヘッドを許容できません。私が探しているのは、概念的に AST のクラスの背後にある理論であるため、インタープリターのエグゼキューター部分によって実行できます。この問題に対する特定の回答を含む適切なリンクは、間違いなく高く評価されます。

0 投票する
4 に答える
3422 参照

performance - VM 設計: オペコードを増やすか、オペコードを減らすか? 何が良いですか?

ショックを受けないでください。これは多くのテキストですが、詳細な情報を提供しないと、これが何であるかを実際に示すことはできません (そして、私の質問に実際には対応していない多くの回答が得られる可能性があります)。そして、これは間違いなく割り当てではありません(誰かが彼のコメントでばかげて主張したように)。

前提条件

この質問は、少なくともいくつかの前提条件が設定されていない限り、おそらくまったく答えられないため、前提条件は次のとおりです。

  • 仮想マシン コードは解釈されます。JIT コンパイラーが存在することは禁止されていませんが、設計はインタープリターをターゲットにする必要があります。
  • VM は、スタック ベースではなく、レジスタ ベースである必要があります。
  • 答えは、レジスタの固定セットがあることも、それらの数に制限がないことも想定していない可能性があります。

さらに、「より良い」のより良い定義が必要です。考慮しなければならないプロパティがいくつかあります。

  1. ディスク上の VM コードのストレージ領域。もちろん、ここですべての最適化を破棄してコードを圧縮することもできますが、これは (2) に悪影響を及ぼします。
  2. デコード速度。コードを直接実行できるものに変換するのに時間がかかりすぎる場合、コードを保存する最善の方法は役に立ちません。
  3. メモリ内のストレージ スペース。このコードは、さらにデコードするかどうかに関係なく、直接実行できる必要がありますが、さらにデコードが必要な場合、このエンコードは実行中および命令が実行されるたびに行われます (コードのロード時に 1 回だけ行われるデコードは項目 2 にカウントされます)。
  4. コードの実行速度 (一般的なインタープリター手法を考慮)。
  5. VM の複雑さと、そのためのインタープリターを作成するのがいかに難しいか。
  6. VM 自体が必要とするリソースの量。(VM が実行するコードのサイズが 2 KB で、瞬きするよりも速く実行される場合、それは適切な設計ではありませんが、これを行うには 150 MB が必要であり、その起動時間はコードの実行時間よりもはるかに長くなります。実行されます)

ここで、多かれ少なかれオペコードが実際に意味することの例を示します。操作ごとに 1 つのオペコードが必要なため、オペコードの数が実際に設定されているように見える場合があります。ただし、それほど簡単ではありません。

同じ操作に対する複数のオペコード

のような操作ができます。

R1 と R2 の値を加算し、結果を R3 に書き込みます。ここで、次の特殊なケースを検討してください。

これらは、多くのアプリケーションで見られる一般的な操作です。既存のオペコードでそれらを表現できます (最後のオペコードがレジスタではなく int 値を持っているために別のオペコードが必要な場合を除く)。ただし、これらに対して特別なオペコードを作成することもできます。

前と同じ。メリットはどこ?ADD2 は 3 つではなく 2 つの引数のみを必要とし、INC は 1 つしか必要としません。したがって、これはディスク上および/またはメモリ内でよりコンパクトにエンコードできます。いずれかの形式を別の形式に変換することも簡単であるため、デコード ステップでこれらのステートメントを表現するために両方の方法の間で変換できます。ただし、どちらの形式が実行速度にどの程度影響するかはわかりません。

2 つのオペコードを 1 つに結合する

ここで、ADD_RRR (レジスターの R) とデータをレジスターにロードするための LOAD があるとします。

これら 2 つのオペコードを使用して、コード全体で常にこのような構成を使用できます...または、それらを ADD_RMR (メモリの M) という名前の単一の新しいオペコードに結合できます。

データ型とオペコード

ネイティブ型として 16 ビット整数と 32 ビット整数があるとします。レジスタは 32 ビットなので、どちらのデータ型にも適合します。2 つのレジスタを追加すると、データ型をパラメーターにすることができます。

たとえば、符号付き整数と符号なし整数についても同じことが言えます。そうすれば、ADD は 1 バイトの短いオペコードになり、別のバイト (または単に 4 ビット) が VM にレジスタの解釈方法を伝えます (レジスタは 16 ビットまたは 32 ビットの値を保持しますか)。または、型エンコーディングを破棄して、代わりに 2 つのオペコードを使用できます。

どちらもまったく同じだと言う人もいるかもしれません.16ビットのオペコードとして最初の方法を解釈するだけでうまくいきます. はい、しかし非常にナイーブなインタープリターは、かなり異なって見えるかもしれません。たとえば、オペコードごとに 1 つの関数があり、switch ステートメントを使用してディスパッチする場合 (最適な方法ではなく、関数呼び出しのオーバーヘッド、switch ステートメントも最適ではないことはわかっています)、2 つのオペコードは次のようになります。

各機能は、特定の種類の追加を中心にしています。ただし、2番目のものは次のようになります。

サブスイッチをメイン スイッチに追加するか、サブ ディスパッチ テーブルをメイン ディスパッチ テーブルに追加します。もちろん、型が明示的であるかどうかに関係なく、インタープリターはどちらの方法でも実行できますが、オペコードの設計に応じて、どちらの方法も開発者にとってよりネイティブに感じられます。

メタ オペコード

より良い名前がないので、そのように呼びます。これらのオペコードは、それ自体ではまったく意味がなく、後続のオペコードの意味を変更するだけです。有名な WIDE 演算子のように:

たとえば、2 番目のケースでは、レジスタは 16 ビット (したがって、より多くのアドレスを指定できます) で、最初のケースでは 8 ビットしかありません。あるいは、そのようなメタ オペコードを持たず、ADD および ADD_WIDE オペコードを持つことはできません。WIDE のようなメタ オペコードは、SUB_WIDE、MUL_WIDE などを持つことを避けます。これは、他のすべての通常のオペコードに常に WIDE を付加できるためです (常に 1 つのオペコードのみ)。不利な点は、オペコードだけでは無意味になることです。それがメタ オペコードであったかどうか、その前にオペコードを常にチェックする必要があります。さらに、VM はスレッドごとに余分な状態を保存し (たとえば、現在ワイド モードであるかどうかに関係なく)、次の命令の後に状態を再度削除する必要があります。CPU にもそのようなオペコードがあります (x86 LOCK オペコードなど)。

適切なトレードオフを見つける方法???

もちろん、オペコードが多いほど、スイッチ/ディスパッチテーブルが大きくなり、これらのコードをディスクまたはメモリで表現するために必要なビットが多くなります (ただし、データが保存されていないディスクにより効率的に格納できる場合があります)。 VM で直接実行できる必要があります)。また、VM はより複雑になり、より多くのコード行が必要になります。一方で、オペコードがより強力になります。複雑な式であっても、すべての式が 1 つのオペコードになるポイントに近づいています。

小さなオペコードを選択すると、VM のコーディングが容易になり、非常にコンパクトなオペコードにつながると思います。一方、単純なタスクを実行するには非常に多くのオペコードが必要になる可能性があり、あまり使用されない式はすべて、オペコードを使用できないため、ある種の(ネイティブ)関数呼び出しになります。

私はインターネット上のあらゆる種類の VM について多くのことを読みましたが、どちらの方向にも適切で公正なトレードオフを実際に行っている情報源はありませんでした。VM の設計は CPU の設計に似ています。オペコードがほとんどなく高速な CPU もありますが、これらの多くも必要です。また、多くのオペコードを持つ CPU があり、非常に遅いものもありますが、同じコードを表現するために必要なオペコードははるかに少なくなります。「オペコードが多いほど良い」CPU が消費者市場を完全に獲得し、「オペコードが少ないほど良い」CPU は、サーバー市場またはスーパー コンピューター ビジネスの一部でのみ生き残ることができるようです。VMはどうですか?

0 投票する
2 に答える
1389 参照

python - Eclipse での Python インタープリターの問題

実行可能ファイルを選択して Eclipse で python のインタープリターを設定しようとすると、[OK] をクリックすると「エラーが発生しました」と表示されます。通訳者の名前は重要ですか?

0 投票する
1 に答える
914 参照

parsing - javacc parseException... 先読みの問題?

javacc で非常に単純な文法のパーサーを作成しています。まとまり始めていますが、現時点ではこのエラーに完全に行き詰まっています:

問題の入力行はz = y + z + 5

問題を引き起こしているのは、varDecl() から呼び出される式です。

式は次のようになります。

このエラーが発生する理由がわかりません。洞察をいただければ幸いです。

0 投票する
4 に答える
4903 参照

python - Lego Mindstorm 用の Ruby または Python インタープリターはありますか?

Python または Ruby でコーディングを開始したい。私はレゴ ミッドストームキットを所有しているので、それに対してプログラムを作成できればよいと考えました。Mindstorms ブリックの優れた翻訳者/通訳者はいますか?

0 投票する
2 に答える
653 参照

java - 何かを解釈し、生成されたバイトコードを Java で実行しますか?

JavaでREPLを使用しておもちゃのインタープリターを作成しています。AST を解釈して代わりに実行する代わりに、言語からバイトコードを生成して実行したいと思います。

私の Java は少し錆びているので、生成されたバイトコードを JVM でオンザフライで実行することは可能ですか?

0 投票する
5 に答える
1537 参照

compiler-construction - 「現実世界」のアプリケーションで ML を使用する

大学で ML を学ぶのがとても好きでした。関数型プログラミングは、特定のアルゴリズムを作成するための爽快でエレガントな方法であることがよくあります。F# について聞いたことがあり、少し遊んでみました。それでも、私は ML でいくつかの興味深い関数を作成しており、他のアプリケーションで使用できるライブラリとしてそれらを統合したいと考えています。

通常、関数を SMLnj インタープリターに貼り付けます。それらをコンパイルする方法はありますか?

0 投票する
3 に答える
443 参照

c++ - 改行の認識

ユーザーが「;」を入力すると出力を出力するかなり複雑な電卓があります。(そして入力を押します。) 私が今やろうとしているのは、ユーザーが入力を押したときに (セミコロンを使用せずに) 出力を印刷できるようにすることです。これを実装する方法を知る必要があります。

補足: 電卓はトークン化を使用してユーザー入力を読み取ります

これは電卓のソースの一部であり、変更が必要な唯一の部分です。これは、電卓の他のさまざまな関数が次のトークンを取得するために呼び出すときに呼び出される Token_stream のメンバー関数です。

これまでのところ、ユーザーが 5*5 を入力してスペースを押しても何も起こりません。ただし、スペースを押してからランダムな文字 (; だけでなく任意の文字) を入力してから Enter キーを押すと、答えが出力されます。この後、ユーザーは enter を使用して出力を生成できますが、スペースを押した後にユーザーが入力した余分なトークンが保存されるため、操作の順序がすべて厄介になります。

要するに、ユーザーが最初にスペースを押してから入力できるようにする方法を知る必要があります (または単に入力しますが、今のところはスペースを入力して入力します)。追加の文字なしで出力を生成します。

問題を解決するために、より多くのソースを表示したり、電卓自体に関する質問がある場合は、喜んで投稿します。

PS 元のプログラムは、私が C++ を学んでいる本からのものです。私はそれを変更して機能を追加する演習を行ってきました。