Parrot-quick-guide

提供:Dev Guides
移動先:案内検索

オウム-概要

プログラムを従来のPerlにフィードすると、最初に内部表現またはバイトコードにコンパイルされます。このバイトコードは、Perl内のほぼ独立したサブシステムに送られて解釈されます。 したがって、Perlの操作には2つの異なるフェーズがあります。

  • バイトコードへのコンパイルと
  • バイトコードの解釈。

これはPerlに固有のものではありません。 この設計に従う他の言語には、Python、Ruby、Tcl、さらにはJavaが含まれます。

また、Javaバイトコードをマシン言語に変換して実行する、プラットフォームに依存しない実行環境であるJava仮想マシン(JVM)があることもわかっています。 この概念を理解すれば、Parrotを理解できます。

*Parrot* は、インタープリター言語のバイトコードを効率的にコンパイルおよび実行するように設計された仮想マシンです。 Parrotは、最終的なPerl 6コンパイラのターゲットであり、Pugsのバックエンドとしてだけでなく、Tcl、Ruby、Pythonなどのさまざまな言語として使用されます。

Parrotは、最も一般的な言語「C」を使用して記述されています。

オウム-インストール

始める前に、Parrotの最新のコピーを1つダウンロードして、マシンにインストールしましょう。

Parrotダウンロードリンクは、http://www.parrot.org/sourcel [Parrot CVS Snapshot]にあります。 Parrotの最新バージョンをダウンロードしてインストールするには、次の手順を実行します。

  • ダウンロードしたファイルを解凍して解凍します。
  • マシンにPerl 5がすでにインストールされていることを確認してください。
  • 次の手順を実行してください。
% cd parrot
% perl Configure.pl
Parrot Configure
Copyright (C) 2001 Yet Another Society
Since you're running this script, you obviously have
Perl 5 -- I'll be pulling some defaults from its configuration.
...
  • その後、ローカル設定に関する一連の質問が表示されます。ほとんどの場合、それぞれにReturn/Enterキーを押すことができます。
  • 最後に、入力するように指示されます-make _test_prog、_とParrotはテストインタープリターを正常にビルドします。
  • ここで、いくつかのテストを実行する必要があります。 「テストを行う」と入力すると、次のような表示が表示されます。
perl t/harness
t/op/basic.....ok,1/2 skipped:label constants unimplemented in
assembler
t/op/string....ok, 1/4 skipped:  I'm unable to write it!
All tests successful, 2 subtests skipped.
Files=2, Tests=6,......

これを読むまでに、さらにテストが行​​われる可能性があり、スキップしたもののいくつかはスキップしないかもしれませんが、それらのいずれも失敗してはいけないことを確認してください!

オウム実行可能ファイルをインストールしたら、link:/parrot/parrot_examples [Parrot 'Examples']セクションにあるさまざまなタイプの例を確認できます。 また、parrotリポジトリのexamplesディレクトリをチェックアウトできます。

オウム-命令形式

Parrotは現在、4つの形式で実行する命令を受け入れることができます。 PIR(Parrot Intermediate Representation)は、人々によって記述され、コンパイラーによって生成されるように設計されています。 パラメータが関数に渡される方法など、いくつかの低レベルの詳細を隠します。

PASM(Parrot Assembly)はPIRよりも下のレベルです-まだ人間が読み取り/書き込み可能であり、コンパイラによって生成できますが、作成者は呼び出し規約やレジスタ割り当てなどの詳細に注意する必要があります。 PAST(Parrot Abstract Syntax Tree)を使用すると、Parrotは抽象構文ツリースタイルの入力を受け入れることができます。これは、コンパイラを作成する人に役立ちます。

上記のすべての入力形式は、Parrot内でPBC(Parrotバイトコード)に自動的に変換されます。 これはマシンコードによく似ていますが、Parrotインタープリターによって理解されます。

人間が読み取り可能または人間が書き込み可能にすることは意図されていませんが、他のフォームとは異なり、アセンブリ段階を必要とせずにすぐに実行を開始できます。 Parrotバイトコードはプラットフォームに依存しません。

指図書

Parrot命令セットには、算術演算子と論理演算子、比較と分岐/ジャンプ(ループの実装、if …​ thenコンストラクトなど)、グローバル変数とレキシカル変数の検索と保存、クラスとオブジェクトの操作、サブルーチンとメソッドの呼び出しが含まれますパラメータ、I/O、スレッドなどが含まれます。

オウム-ガベージコレクション

Java Virtual Machineと同様に、Parrotはメモリの割り当て解除について心配する必要もありません。

  • Parrotはガベージコレクションを提供します。
  • Parrotプログラムでは、メモリを明示的に解放する必要はありません。
  • 割り当てられたメモリは、使用されなくなると解放されます。 参照されなくなりました。
  • Parrot Garbage Collectorは、不要なメモリを処理するために定期的に実行されます。

オウム-データ型

Parrot CPUには4つの基本的なデータ型があります。

  • IV +整数型。ポインタを保持するのに十分な幅があることが保証されています。
  • NV +アーキテクチャに依存しない浮動小数点型。
  • STRING +抽象化された、エンコードに依存しない文字列型。
  • PMC +スカラー。

最初の3つのタイプはほとんど自明です。最後のタイプ-Parrot Magic Cookiesは、理解するのが少し難しいです。

PMCとは何ですか?

PMCはParrot Magic Cookieの略です。 PMCは、集約データタイプ(配列、ハッシュテーブルなど)を含む、複雑なデータ構造またはタイプを表します。 PMCは、算術演算、論理演算、および文字列演算に対して独自の動作を実装でき、言語固有の動作を導入できます。 PMCは、Parrot実行可能ファイルに組み込むか、必要なときに動的にロードできます。

オウム-登録

現在のPerl 5仮想マシンはスタックマシンです。 スタックに値を保持することにより、操作間で値を通信します。 オペレーションは値をスタックにロードし、必要なことは何でも行い、結果をスタックに戻します。 これは簡単に使用できますが、時間がかかります。

2つの数値を加算するには、3つのスタックプッシュと2つのスタックポップを実行する必要があります。 さらに悪いことに、スタックは実行時に拡大する必要があります。つまり、割り当てたくないときにメモリを割り当てる必要があります。

そのため、Parrotは仮想マシンの確立された伝統を破り、実際のハードウェアCPUのアーキテクチャにより近いレジスタアーキテクチャを使用します。 これには別の利点があります。 ソフトウェアCPU用のレジスタベースCPU用のコンパイラーとオプティマイザーの作成方法に関する既存の文献をすべて使用できます!

Parrotには、32のIVレジスタ、32のNVレジスタ、32の文字列レジスタ、32のPMCレジスタの各タイプの専門レジスタがあります。 Parrotアセンブラでは、これらはそれぞれI1 …​ I32、N1 …​ N32、S1 …​ S32、P1 …​ P32という名前です。

次に、いくつかのアセンブラを見てみましょう。 これらのレジスタは、set演算子で設定できます。

   set I1, 10
   set N1, 3.1415
   set S1, "Hello, Parrot"

すべてのParrot opの形式は同じです。演算子の名前、デスティネーションレジスタ、そしてオペランドです。

オウム-操作

実行できるさまざまな操作があります。 たとえば、レジ​​スタまたは定数の内容を出力できます。

set I1, 10
print "The contents of register I1 is: "
print I1
print "\n"

上記の命令により、レジスタI1の内容は次のようになります:10

レジスタに対して数学演算を実行できます。

# Add the contents of I2 to the contents of I1
add I1, I1, I2

# Multiply I2 by I4 and store in I3
mul I3, I2, I4

# Increment I1 by one
inc I1

# Decrement N3 by 1.5
dec N3, 1.5

いくつかの単純な文字列操作も実行できます。

set S1, "fish"
set S2, "bone"
concat S1, S2       # S1 is now "fishbone"

set S3, "w"
substr S4, S1, 1, 7

concat S3, S4       # S3 is now "wishbone"
length I1, S3       # I1 is now 8

オウム-枝

コードはフロー制御なしでは少し退屈です。まず、Parrotは分岐とラベルについて知っています。 ブランチopはPerlのgotoと同等です:

         branch TERRY
JOHN:    print "fjords\n"
         branch END
MICHAEL: print " pining"
         branch GRAHAM
TERRY:   print "It's"
         branch MICHAEL
GRAHAM:  print " for the "
         branch JOHN
END:     end

また、レジスタにtrue値が含まれているかどうかを確認する簡単なテストを実行できます。

         set I1, 12
         set I2, 5
         mod I3, I2, I2
         if I3, REMAIND, DIVISOR

REMAIND: print "5 divides 12 with remainder "
         print I3
         branch DONE

DIVISOR: print "5 is an integer divisor of 12"

DONE:    print "\n"
         end

比較のために、Perlでは次のようになります。

$i1 = 12;
$i2 = 5;
$i3 = $i1 % $i2;

if ($i3) {
   print "5 divides 12 with remainder ";
   print $i3;
} else {
   print "5 is an integer divisor of 12";
}

print "\n";
exit;

オウムオペレーター

eq、ne、lt、gt、le、geのすべての数値コンパレータがあります。 これらの演算子は、異なる型の引数には使用できないことに注意してください。使用している引数のタイプを伝えるために、接尾辞_iまたは_nをopに追加する必要があるかもしれませんが、アセンブラはこれを読むまでにこれを理解する必要があります。

Parrot-プログラミングの例

Parrotプログラミングはアセンブリ言語プログラミングに似ており、低レベルで作業する機会が得られます。 Parrotプログラミングのさまざまな側面を理解するためのプログラミング例のリストを以下に示します。

  • リンク:/parrot/parrot_examples#parrot_hello_world [クラシックハローワールド!]
  • リンク:/parrot/parrot_examples#parrot_registers [レジスターの使用]
  • リンク:/parrot/parrot_examples#parrot_squares [平方和]
  • リンク:/parrot/parrot_examples#parrot_fibonacci [フィボナッチ数]
  • リンク:/parrot/parrot_examples#parrot_factorial [階乗の計算]
  • リンク:/parrot/parrot_examples#parrot_pbc [PBCへのコンパイル] *リンク:/parrot/parrot_examples#parrot_pir [PIR vs. PASM]

[#parrot_hello_world]#クラシックHello world!#

次のコードを含むhello.pirというファイルを作成します。

.sub _main
   print "Hello world!\n"
   end
.end

次に、次のように入力して実行します。

parrot hello.pir

予想どおり、これにより「Hello world!」というテキストが表示されます。コンソールで、新しい行が続きます(\ nのため)。

上記の例では、「。sub _main」は、「。end」が検出されるまで、後続の命令が「_main」という名前のサブルーチンを構成することを示しています。 2行目には、印刷指示が含まれています。 この場合、定数文字列を受け入れる命令のバリアントを呼び出しています。 アセンブラーは、使用する命令のバリアントを決定します。 3行目には、インタープリターを終了させる「終了」命令が含まれています。

[#parrot_registers]#レジスタの使用#

hello.pirを変更して、最初に文字列Hello world!\ nをレジスターに格納してから、そのレジスターを印刷命令で使用できます。

.sub _main
   set S1, "Hello world!\n"
   print S1
   end
.end

ここで、使用するレジスタを正確に述べました。 ただし、S1を$ S1に置き換えることにより、使用するレジスタの選択をParrotに委任できます。 set命令を記述する代わりに=表記を使用することもできます。

.sub _main
   $S0 = "Hello world!\n"
   print $S0
   end
.end

PIRをさらに読みやすくするために、名前付きレジスタを使用できます。 これらは後に実数のレジスタにマッピングされます。

.sub _main
   .local string hello
   hello = "Hello world!\n"
   print hello
   end
.end

'.local’ディレクティブは、指定されたレジスターが現在のコンパイル単位内(つまり、.subと.endの間)でのみ必要であることを示します。 「.local」に続くのがタイプです。 これは、int(Iレジスタの場合)、float(Nレジスタの場合)、string(Sレジスタの場合)、pmc(Pレジスタの場合)、またはPMCタイプの名前です。

[#parrot_squares] #Summing squares#

この例では、さらにいくつかの命令とPIR構文を紹介します。 #で始まる行はコメントです。

.sub _main
   # State the number of squares to sum.
   .local int maxnum
   maxnum = 10

   # Some named registers we'll use.
   # Note how we can declare many
   # registers of the same type on one line.
   .local int i, total, temp
   total = 0

   # Loop to do the sum.
   i = 1

loop:
   temp = i* i
   total += temp
   inc i
   if i <= maxnum goto loop

   # Output result.
   print "The sum of the first "
   print maxnum
   print " squares is "
   print total
   print ".\n"
   end
.end

PIRは、アセンブリよりも高レベルに見える構文糖を少し提供します。 例えば:

temp = i * i

より多くのアセンブリのように書くための単なる別の方法です:

mul temp, i, i

And:

if i <= maxnum goto loop

と同じです:

le i, maxnum, loop

And:

total += temp

と同じです:

add total, temp

原則として、Parrot命令がレジスターの内容を変更するときは常に、アセンブリー形式で命令を書き込むときの最初のレジスターになります。

アセンブリ言語で通常行われているように、ループと選択は、上記のように条件分岐ステートメントとラベルの観点から実装されます。 アセンブリプログラミングは、gotoの使用が悪い形ではない1つの場所です!

[#parrot_fibonacci]#フィボナッチ数#

フィボナッチ数列は次のように定義されます:1と1の2つの数値を取ります。 次に、シリーズの最後の2つの数字を繰り返し加算して、次の数字を作成します:1、1、2、3、5、8、13など。 フィボナッチ数fib(n)は、シリーズのn番目の数です。 以下は、最初の20個のフィボナッチ数を見つける簡単なParrotアセンブラプログラムです。

# Some simple code to print some Fibonacci numbers

        print   "The first 20 fibonacci numbers are:\n"
        set     I1, 0
        set     I2, 20
        set     I3, 1
        set     I4, 1

REDO:   eq      I1, I2, DONE, NEXT

NEXT:   set     I5, I4
        add     I4, I3, I4
        set     I3, I5
        print   I3
        print   "\n"
        inc     I1
        branch  REDO
DONE:   end

これはPerlの同等のコードです:

print "The first 20 fibonacci numbers are:\n";

my $i = 0;
my $target = 20;
my $a = 1;
my $b = 1;

until ($i == $target) {
   my $num = $b;
   $b += $a;
   $a = $num;
   print $a,"\n";
   $i++;
}
  • 注:*興味深い点として、Perlでフィボナッチ数列を印刷する最も短く確実な最も美しい方法の1つはperl -le '$ b = 1;です。 $ b + = $ a 'を印刷しながら$ a + = $ bを印刷します。

[#parrot_factorial]#再帰的階乗計算#

この例では、階乗関数を定義し、再帰的に呼び出して階乗を計算します。

.sub _fact
   # Get input parameter.
   .param int n

   # return (n > 1 ? n *_fact(n - 1) : 1)
   .local int result

   if n > 1 goto recurse
   result = 1
   goto return

recurse:
   $I0 = n - 1
   result = _fact($I0)
   result* = n

return:
   .return (result)
.end


.sub _main :main
   .local int f, i

   # We'll do factorial 0 to 10.
   i = 0

loop:
   f = _fact(i)

   print "Factorial of "
   print i
   print " is "
   print f
   print ".\n"

   inc i
   if i <= 10 goto loop

   # That's it.
   end
.end

最初に_factサブを見てみましょう。 先ほど説明したポイントは、サブルーチンの名前がす​​べてアンダースコアで始まる理由です! これは、ラベルが特定のサブルーチンにスコープされているのではなく、グローバルであることを示す方法としてのみ行われます。 これは、ラベルが他のサブルーチンから見えるようになるため重要です。

最初の行の.param int nは、このサブルーチンが1つの整数パラメーターを取り、残りのサブに対してnという名前で渡されたレジスターを参照することを指定します。

以下の内容の多くは、行の読み取りを除き、以前の例で見られました。

result = _fact($I0)

このPIRの単一行は、実際にはPASMのかなりの数の行を表しています。 最初に、レジスタ$ I0の値が適切なレジスタに移動され、_fact関数によって整数パラメータとして受信されます。 次に、他の呼び出し関連レジスタがセットアップされ、続いて_factが呼び出されます。 次に、_factが返されると、_factによって返された値が、名前の結果を指定してレジスタに配置されます。

_factサブの.endの直前に、.returnディレクティブを使用して、レジスタに保持されている値を確認します。名前付き結果は、subを呼び出すコードによって戻り値として表示されるように、正しいレジスタに配置されます。

mainでの_factの呼び出しは、sub _fact自体内での_factの再帰呼び出しと同じように機能します。 新しい構文の唯一の残りのビットは、.sub _mainの後に記述された:mainです。 デフォルトでは、PIRは実行がファイルの最初のサブルーチンから始まると想定します。 この動作は、:mainで始まるサブをマークすることで変更できます。

[#parrot_pbc] #PBCへのコンパイル#

PIRをバイトコードにコンパイルするには、-oフラグを使用して、拡張子が.pbcの出力ファイルを指定します。

parrot -o factorial.pbc factorial.pir

[#parrot_pir] #PIR対 PASM#

PIRは、次を実行することでPASMに変換できます。

parrot -o hello.pasm hello.pir

最後の例のPASMは次のようになります。

_main:
   set S30, "Hello world!\n"
   print S30
end

PASMは、レジスターの割り当てを処理せず、名前付きレジスターのサポートも提供しません。 また、.subディレクティブと.endディレクティブはありません。代わりに、命令の開始時にそれらをラベルに置き換えます。

オウム-便利なリソース

次のリソースには、Parrotに関する追加情報が含まれています。 このトピックに関する詳細な知識を得るためにそれらを使用してください。

オウムの便利なリンク

Glossary

重要なオウム用語の用語集

Patch&Bug Report Submission Information

パッチの提出に関する簡単な説明

オウムの役に立つ本

このページにサイトを登録するには、 contact @ finddevguides.com にメールを送信してください。