web-dev-qa-db-ja.com

JVMプログラミング言語を作成する

ループ、関数内の関数宣言、再帰呼び出しなどをサポートする動的型付きプログラミング言語用に、Cでコンパイラを作成しました(Lex&bisonを使用)。また、コンパイラによって作成された中間コードを実行する仮想マシンを作成しました。

私は自分の中間コードにコンパイルする代わりに、Javaバイトコードにコンパイルすることを考えていました。

JVM言語の作成に関する質問はすでに 質問 であることがわかりましたが、その答えはあまり有益ではありません。

だからここに私の質問があります:

  1. JVMの言語を作成するためには、 JVM仕様 本を読む必要がありますが、他の本(もちろんDragon Bookを除く)を提案できますか?私は主に、一般的なコンパイラーではなく、JVM言語の作成方法に関する本やチュートリアルを心配しています。
  2. jclasslibbcelgnuバイトコード のような.classファイルの読み取り、書き込み、変更を行うライブラリは多数ありますJava =などどちらを提案しますか?また、同じ仕事をするCライブラリを知っていますか?
  3. Clojure、Jython、JRubyなど、JVMをターゲットとする別の言語を検討することを考えていました。しかし、これらの言語はすべて非常に高レベルで複雑です(コンパイラーを作成するため)。私は、JVMをターゲットとするシンプルな(未知または未使用のどちらでも構いません)プログラミング言語を探していました。コンパイラはオープンソースです。何か案は?
87
functional

ASMもお勧めしますが、 Jasmin を見て、大学プロジェクトに使用しました(または使用する必要がありました)、それは非常にうまく機能し、lexer/parse /を作成しましたJavaとjasminを使用したJVM言語の生成を使用するプログラミング言語用のアナライザー/オプティマイザー/ジェネレーターの組み合わせ。コードをアップロードしました。 here 、興味深い部分は- source-code自体 。フォルダ「bytecode/InsanelyFastByteCodeCreator.Java」には、AST Treeをjasminアセンブラの入力フォーマットに変換するコードの断片があります。とても簡単です。

ソース言語(Lexer + Parser + AnalyzerによってASTに変換された)は、MiniJavaと呼ばれるJavaのサブセットです。継承、コンストラクタ、静的メソッド、プライベートフィールド/メソッドなどの機能。これらの機能はどれも実装するのは難しくありませんが、X86バックエンドを記述する別のタスクがあり(マシンアセンブラを生成するため)、これらの機能はいくつかのことを処理するJVMがありません。

奇妙なクラス名について疑問に思う場合:大学プロジェクトのタスクは、ASTをaa [〜#〜]に変換することでしたssa [〜#〜] グラフ(入力コードを表すグラフ)、グラフを最適化してから、グラフをJavaバイトコードに変換します。プロジェクトとInsanlyFastByteCodeCreatorの作業は、すべてをテストするためのショートカットにすぎませんでした。

Jon Meyer and Troy Downingの「Java Virtual Machine」本をご覧ください。この本はJasmin-Assemblerに重点を置いており、JVM内部を理解するのに非常に役立ちます。

58
theomega

前学期、私は「コンパイラー構築」コースに参加しました。私たちのプロジェクトはまさにあなたがやりたいことでした。

私の言語を書くのに使った言語は Scala でした。 JVM上で動作しますが、Javaではできない多くの高度な機能をサポートしています(純粋なJava JVM)と完全に互換性があります)。

出力するには、Javaバイトコードを使用しました Scala CAFEBABEライブラリー 。十分に文書化されているので、奥深くに行く必要はありませんJava =何をすべきかを理解するためのクラス。

本のほかに、コースで行った labs をたどることで、多くの情報を見つけることができると思います。

11
Kami

[〜#〜] asm [〜#〜] は、バイトコードを生成するための解決策になります。開始するには、 手動 から要素を生成するトピックを確認してください。

4
h3xStream

Clojure、Jython、JRubyなど、JVMをターゲットとする別の言語を見てみたいと思っていました。しかし、これらの言語はすべて非常に高レベルで複雑です(コンパイラーを作成するため)。

提案:Luaプログラミング言語 を見ることができます。 LuaJ

軽量、高速、Java中心のLuaJ2MEおよびJ2SE用に作成されたインタープリター 、基本、文字列、テーブル、パッケージ、数学、io、os、デバッグおよびコルーチンパッケージのライブラリ、compiler、luajavaバインディング、およびJSR- 233個のプラグ可能なスクリプトエンジンバインディング。

(JNIアプローチでネイティブライブラリを使用するLuaJavaと混同しないでください。)

3
bakkal

先週末、自分のおもちゃの言語をJVMに移植するのと同じ質問をしていました。

情報を検索するのに数時間しか費やさないので、この参照を一粒ずつ取ります。

  • 言語実装パターン。私はantlrが嫌いですが、この本はとても良さそうです。どちらもantlrが気に入らない場合は、「Parsing Techniques。A Practical Guide」を解析することについて非常に良い点があります。

    構成ファイルリーダー、データリーダー、モデル駆動型コードジェネレーター、ソースからソースへのトランスレーター、ソースアナライザー、およびインタープリターの構築方法を学びます。コンピュータサイエンスの背景は必要ありません。ANTLRの作成者であるTerence Parrは、言語実装を最も一般的なデザインパターンに分解することで、言語実装を分かりやすく説明しています。パターンごとに、独自のコンピューター言語を実装するために必要な主要なスキルを学びます。

    第10章では、このトピックについて30ページ(IMOの高速化)で説明しています。しかし、おそらくあなたが興味を持つ他の章があります。

    • 10バイトコードインタープリターの構築
      • 10.1バイトコードインタープリターのプログラミング。 。
      • 10.2アセンブリ言語構文の定義
      • 10.3バイトコードマシンアーキテクチャ。 。 。 。 。
      • 10.4ここから先へ。 。 。 。 。 。 。 。 。 。
      • P.26。バイトコードアセンブラー。 。 。 。 。 。 。 。 。 。 。
      • P.27。スタックベースのバイトコードインタープリター。 。 。
      • P.28。レジスタベースのバイトコードインタープリター
      http://pragprog.com/titles/tpdsl/language-implementation-patterns
    • Lua 5.0の実装これは、レジスタベースのバイトコードマシンに関する素晴らしい論文です。それのためにも読んでください。

    • LISP in Small Pieces。この本は、Cにコンパイルする2つのschmeコンパイラの書き方を教えます。この本から多くの教訓を学ぶことができます。私はこの本のコピーを所有しており、LISPが面白い人にとっては本当に良いのですが、あなたのお茶ではないかもしれません。

      これは、LISP言語、つまりLISP、Scheme、および関連する方言の全体のセマンティクスと実装の包括的な説明です。 11のインタープリターと2つのコンパイラーについて説明しています...

    http://www.Amazon.com/LISP-Small-Pieces-Christian-Queinnec/dp/052156247

レジスタベースのVMであるDalvik7 VMを確認します。 DVMは、JavaコンパイラーによってコンパイルされたJavaクラスファイルから変換されたバイトコードで動作します。

トピックに関するメーリングリストjvm-languagesがあります。

どこにでもコードをアップロードする予定ですか?見てみたい。

2
Pedro

最初に最適なリソースは Ola Biniのプレゼンテーション です。同様にスライドをつかみます。

1
lisak

まだ知らない場合は、最初にJVMアセンブリの仕組みを学ぶことをお勧めします。

多くの命令の形式は?nameです。ここで、?は、命令が整数型で機能する場合はi、参照型で機能する場合はaです。

基本的に、JVMはレジスタのないスタックマシンであるため、すべての命令はスタック上のデータを直接処理します。 ?push/?popを使用してデータをプッシュ/ポップし、?store/?loadを使用して、ローカル変数(オフセットによって参照されるスタック位置)とスタックの最上部の間でデータを移動できます。その他の重要な指示には、invoke???およびif_???があります。

私の大学のコンパイラコース では、プログラムをアセンブルするために Jasmin を使用しました。これが最善の方法であるかどうかはわかりませんが、少なくとも簡単に始めることができます。

これは命令リファレンスです 古いバージョンのJVMの場合、新しいバージョンよりも少ない命令が含まれる場合があります。

1
Jørgen Fogh

もちろん、かつてJavaを使用して新しい言語を記述できます。Java reflection-APIを使用すると、大量のデータを取得できます。 、Javaを優先します。プログラミングはJava(IMHO )。RPN言語 7th を見てください。これは完全にJavaで書かれています。

0
Kaplan

最初に戻って、コンパイラを変更して、Javaバイトコード(コンパイラよりも多くのトランスレータを作成することを意味します)ではなく、実際のJava Java出力を何でもJava環境で便利にコンパイルします(おそらく、自分のコンパイラよりも優れたオブジェクトコードを生成します)).

同じ手法(たとえば、C#にコンパイル)を使用してCLIバイトコードを生成したり、PascalにコンパイルしてPコードなどを生成したりできます。

独自のVMを使用する代わりにJavaコードを検討している理由は明らかではありませんが、パフォーマンスのためであれば、もちろん実際のマシンコードへのコンパイルも検討する必要があります。

0
joe snyder