Parrot-examples
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というファイルを作成します。
次に、次のように入力して実行します。
予想どおり、これにより「Hello world!」というテキストが表示されます。コンソールで、新しい行が続きます(\ nのため)。
上記の例では、「。sub _main」は、「。end」が検出されるまで、後続の命令が「_main」という名前のサブルーチンを構成することを示しています。 2行目には、印刷指示が含まれています。 この場合、定数文字列を受け入れる命令のバリアントを呼び出しています。 アセンブラーは、使用する命令のバリアントを決定します。 3行目には、インタープリターを終了させる「終了」命令が含まれています。
[#parrot_registers]#レジスタの使用#
hello.pirを変更して、最初に文字列Hello world!\ nをレジスターに格納してから、そのレジスターを印刷命令で使用できます。
ここで、使用するレジスタを正確に述べました。 ただし、S1を$ S1に置き換えることにより、使用するレジスタの選択をParrotに委任できます。 set命令を記述する代わりに=表記を使用することもできます。
PIRをさらに読みやすくするために、名前付きレジスタを使用できます。 これらは後に実数のレジスタにマッピングされます。
'.local’ディレクティブは、指定されたレジスターが現在のコンパイル単位内(つまり、.subと.endの間)でのみ必要であることを示します。 「.local」に続くのがタイプです。 これは、int(Iレジスタの場合)、float(Nレジスタの場合)、string(Sレジスタの場合)、pmc(Pレジスタの場合)、またはPMCタイプの名前です。
[#parrot_squares] #Summing squares#
この例では、さらにいくつかの命令とPIR構文を紹介します。 #で始まる行はコメントです。
PIRは、アセンブリよりも高レベルに見える構文糖を少し提供します。 例えば:
より多くのアセンブリのように書くための単なる別の方法です:
And:
と同じです:
And:
と同じです:
原則として、Parrot命令がレジスターの内容を変更するときは常に、アセンブリー形式で命令を書き込むときの最初のレジスターになります。
アセンブリ言語で通常行われているように、ループと選択は、上記のように条件分岐ステートメントとラベルの観点から実装されます。 アセンブリプログラミングは、gotoの使用が悪い形ではない1つの場所です!
[#parrot_fibonacci]#フィボナッチ数#
フィボナッチ数列は次のように定義されます:1と1の2つの数値を取ります。 次に、シリーズの最後の2つの数字を繰り返し加算して、次の数字を作成します:1、1、2、3、5、8、13など。 フィボナッチ数fib(n)は、シリーズのn番目の数です。 以下は、最初の20個のフィボナッチ数を見つける簡単なParrotアセンブラプログラムです。
これはPerlの同等のコードです:
- 注:*興味深い点として、Perlでフィボナッチ数列を印刷する最も短く確実な最も美しい方法の1つはperl -le '$ b = 1;です。 $ b + = $ a 'を印刷しながら$ a + = $ bを印刷します。
[#parrot_factorial]#再帰的階乗計算#
この例では、階乗関数を定義し、再帰的に呼び出して階乗を計算します。
最初に_factサブを見てみましょう。 先ほど説明したポイントは、サブルーチンの名前がすべてアンダースコアで始まる理由です! これは、ラベルが特定のサブルーチンにスコープされているのではなく、グローバルであることを示す方法としてのみ行われます。 これは、ラベルが他のサブルーチンから見えるようになるため重要です。
最初の行の.param int nは、このサブルーチンが1つの整数パラメーターを取り、残りのサブに対してnという名前で渡されたレジスターを参照することを指定します。
以下の内容の多くは、行の読み取りを除き、以前の例で見られました。
この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_pir] #PIR対 PASM#
PIRは、次を実行することでPASMに変換できます。
最後の例のPASMは次のようになります。
PASMは、レジスターの割り当てを処理せず、名前付きレジスターのサポートも提供しません。 また、.subディレクティブと.endディレクティブはありません。代わりに、命令の開始時にそれらをラベルに置き換えます。