Parrotは、動的
プログラミング言語の実行に特化した、レジスタベースの仮想マシンです。
C言語で記述されており、型情報を扱う能力を持つことが、他の多くの仮想マシンとの大きな違いです。Parrotは、Parrot
アセンブリ言語(PASM)やParrot
中間言語(PIR)を、Parrotバイトコードに変換して実行します。
歴史
Parrotプロジェクトは、当初Rakuの実装を目的として開始されました。「Rakuを動作させるために開発中の
ソフトウェア」という位置づけが長く続きました。その名前の由来は、
エイプリルフールのジョーク「新しい言語Parrotが
Pythonと
Perlを統一する」という発表にあります。その後、
Perlと
Pythonのサポートも目標に加えられ、プロジェクト名として正式に採用されました。
Parrot仮想マシン上で動作するように、複数の
プログラミング言語がParrotとともに開発されています。
2009年3月17日には、バージョン1.0がリリースされ、
コードネームは"Haru Tatsu"と名付けられました。過去のリリース日はParrotのウェブサイトで確認できます。
対応言語
Parrot仮想マシンの主な目標は、様々なクライアント言語をホストし、それらの相互運用を可能にすることです。この目標を実現するためには、多くの課題をクリアする必要があります。
静的言語と動的言語
静的型付け言語と動的型付け言語の違いが、Parrot開発の大きな動機となっています。現在広く使われている
Java仮想マシン(JVM)や共通言語ランタイム(CLR)は静的型付け言語向けに開発されていますが、Parrotは動的型付け言語を対象としています。
さらに、JVMや
Perl 5の仮想マシンはスタックマシンですが、Parrotはレジスタを備えています。これにより、Parrotは実際の
ハードウェア設計に近くなり、既存のコンパイラ最適化技術をコード生成に活用することで、より高速な実行を実現できると考えられています。
関数型言語の概念
Parrotは、クロージャや継続など、関数型プログラミングの重要な概念をサポートしています。これらの機能は、例外処理やマルチスレッドと組み合わせると実現が難しくなりますが、Parrotが仮想マシンレベルでこれらの問題を解決することで、クライアント言語での実装の労力を大幅に軽減できます。
コンパイラツール
Parrotは、コンパイラ作成のための強力なツールセットを提供しています。再帰下降構文解析や演算子順位パーサーを表現できる
ハイブリッドのParser Grammar Engine(PGE)を搭載しており、これらを同じ文法内で自由に切り替えられます。
PGEは解析結果をTree Grammar Engine(TGE)に渡し、TGEは最適化や最終的なコード生成のために、PGEが作成した抽象構文木を変換します。
クライアント言語
Rakuのサブセットに加え、以下のような多数の言語がParrot
アセンブリ言語にコンパイルされる計画が立てられています。
APL,
BASIC, Befunge,
Brainfuck, Cola, Forth, Jako, LISP, m4, Miniperl, Parakeet, OpenComal, PHP, Plot, Pheme, Punie,
Python,
Ruby, Scheme, Span, Tcl (partcl), URM, YAL, Zork Z-codeなど。しかし、これらの言語実装の多くは、まだ不完全であったり、実験的であったり、開発が放棄されていたりします。
将来的な言語やプロジェクト
Rubyコミュニティでは、Parrotへの強い関心が寄せられています。
Pythonコミュニティは、すでにPsyco(
PythonからマシンコードへのJITコンパイラ)、Jython(
Pythonからバイトコードへのコンパイラ)、Iron
Python(.NETプラットフォームへのコンパイラ)、PyPy(高度な最適化や静的コード生成を目指すプロジェクト)が存在するため、今後の動向を見守る姿勢です。
Parrotの内部
バイトコード
Parrotのコードは、主に3つの形態で存在します。バイトコード(Parrot Bytecode, PBC)は、Parrotがネイティブに解釈する
機械語です。その他の2つは、
中間言語であり、IMCC(旧バージョン)またはPIRC(新バージョン)によってバイトコードにコンパイルされます。
アセンブリ言語(Parrot Assembly Language, PASM)は、バイトコードとほぼ1対1に対応する低レベル言語です。
Parrot中間表現(Parrot intermediate representation, PIR)は、PASMよりもやや高レベルの言語ですが、直接バイトコードにコンパイルできます。Parrot上で動作する言語処理系は、通常、PASMよりも扱いやすいPIRへのコンパイラを実装します。
PIRを使用することで、Parrotのルーチン間の呼び出し規約の違いを管理・吸収したり、より効率的な命令への変換(命令選択)や、変数のレジスタ割り当てやメモリ退避(レジスタスピル)などの最適化を個別に実装することなく、Parrot (IMCCやPIRC) に任せることができます。
ネイティブコードへの変換
Parrotは、独自のJITコンパイラを開発していましたが、
2009年のバージョン1.7.0で中止されました。将来的には、
LLVMやnanojitなどの既存のJITライブラリを利用して新しいコンパイラを用意する予定です。
PMC
Polymorphic Container(PMC、以前はParrot Magic Cookieの略とされていました)は、クライアント言語が扱う型を拡張するための仕組みです。
例
レジスタ
Parrotは、ほとんどの
ハードウェアCPUと同様にレジスタベースです。これは、多くの仮想マシンがスタックマシンであることとは対照的です。Parrotは4種類のレジスタを提供します。
I: ネイティブの整数型
N:
浮動小数点数
S: Unicodeをサポートする文字列レジスタ
P: Parrotのオブジェクト型であるPMC
Parrotは任意の数のレジスタを提供できます。レジスタの数はコンパイル時に
サブルーチンごとに決定されます。
数値演算
PASMコードの例:
pasm
set I1, 4
inc I1 # I1 は 5
add I1, 2 # I1 は 7
set N1, 42.0
dec N1 # N1 は 41.0
sub N1, 2.0 # N1 は 39.0
print I1
print ', '
print N1
print "
"
end
PIRコードの例:
pir
.sub 'main' :main
$I1 = 4
inc $I1 # $I1 は 5
$I1 += 2 # $I1 は 7
$N1 = 42.0
dec $N1 # $N1 は 41.0
$N1 -= 2.0 # $N1 は 39.0
print $I1
print ', '
print $N1
print "
"
.end
Parrotの文化
Parrotのキャッチフレーズは、「1つのバイトコードは全てを統べる」です。これは、J.R.R.トールキンの『
指輪物語』に登場する「一つの指輪」に刻まれた銘に由来します。
2005年後半まで、Dan SugalskiがParrotの設計者およびチーフアーキテクトでした。その後、長年の
Perl、
Linuxカーネル、
C++のハッカーであるチップ・ザルツェンベルクが
2006年半ばに開発リーダーを引き継ぎました。現在は、Punieのリード開発者であり、Parrotコンパイラツールのチーフアーキテクトでもあるアリソン・ランダルがチーフアーキテクトを務めています。
開発に関する議論は、主にIRCで行われており、通常はirc.perl.orgの#parrotチャンネルが使われます。また、#parrotsketchチャンネルでは、毎週Parrotと言語開発者のためのミーティングが開かれています。さらに、parrot.orgでホストされているparrot-dev
メーリングリストでも議論が行われています。
Parrotの設計に関する議論は、Parrotの
リポジトリ内のParrot設計文書(PDD)として公開されています。チーフアーキテクトや指名された設計者が、機能のアイデア、インターフェース、設計メモなどを記述しています。Parrotハッカーは、これらの文書を実用可能なテストに変換し、実際の機能として実装していきます。
Parrotの安定版は、毎月第3火曜日にリリースされます。リリース作業は、中心的な開発者が交代で担当し、同じ開発者が連続して担当しないように配慮されています。この慣習は、プロジェクトの進行速度と安定性の向上に貢献しています。
Parrotは自由
ソフトウェアプロジェクトであり、Artistic License Version 2.0の下で配布されています。
関連項目
共通言語ランタイム
Java仮想マシン
mod_parrot
外部リンク
Parrot homepage
*
Perl 6 and Parrot links