view paper/chapter3.tex @ 78:a456a90f9f35

add perl6 sample code
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Mon, 18 Feb 2019 20:29:10 +0900
parents 49e6b3116f12
children 0d4418a76093
line wrap: on
line source

\chapter{Perl6}
\section{Perl6の概要}
Perl6は2002年にLarryWallが、 Perl5を置き換える言語として設計を開始したプログラミング言語である。
Perl5の言語的な問題点である、 オブジェクト指向機能の強力なサポートや、 正規表現の表現力の拡大などを取り入れた言語として設計された。
Perl5は設計と実装が同一であり、 Unixベースの環境で主に利用されている perl はLarryらによって開発されているC言語による実装のみである。
Perl6は仕様と実装が分離されており、 現在はテストスイートであるRoastが仕様となっている。

実装は歴史的に様々なものが開発されており、 Haskellで実装されたPugs、 Pythonとの共同実行環境を目指したParrotなどが存在する。
PugsやParrotは現在は歴史的な実装となっており、 開発は行われていない。
現在の主要な実装であるRakudoは、 Parrotと入れ替わる形で実装が進んでいる。

Perl6そのものはスクリプト言語として実装されている。
また、 Perl5の様に型が無い様にも振る舞えるが、 TypeScriptの様に型がある様にも振る舞う事が出来る。
この型システムの特徴を、漸進的型付けと呼び、 Perl6は漸進的型付け言語である。
言語的な特徴としては、 独自にPerl6の文法を拡張可能なGrammer、 Perl5と比較してオブジェクト指向言語としての機能の強化などが見られる。
Perl6の実際のサンプルコードをソースコード\ref{perl6_grammer}とソースコード\ref{p6_fizzbuzz}に示す。

\lstinputlisting[frame=lrbt, label=perl6_grammer, caption=Perl6のGrammerを利用したサンプルコード]{./codes/grammer.p6}
\lstinputlisting[frame=lrbt, label=p6_fizzbuzz, caption=Perl6の型システムを利用したfizzbuzz]{./codes/fizzbuzz.p6}


Perl6は言語的な仕様や、 実装がPerl5と大幅に異なっており、 言語的な互換性が存在しない。
その為、 現在ではPerl5とPerl6は別言語として開発されており、 Perl6は主要な処理系であるRakudoから名前を取り、 Rakuという別名がついている。

\section{Rakudo}

RakudoとはNQPによって記述され、 MoarVM、 JVM上で動作するPerl6の実装である。
NQPとはNotQuitPerlの略であり、 Perl6のサブセットである。

RakudoがPerl6のコンパイラかつインタプリタとして機能する。
Rakudoの構成を図\ref{fig:perl6nqp}に示す。

\begin{figure}[ht]
\caption{Rakudoの構成図}
 \begin{center}
  \includegraphics[width=50mm]{./fig/prosym/perl6nqp.pdf}
 \end{center}
 \label{fig:perl6nqp}
\end{figure}

Perl6そのものはNQPで大本が記述されており、 その上にPerl6自身で記述された箇所が存在する。
図\ref{fig:perl6nqp}に示すとおり、 MoarVMが解釈するのはNQPが発行したMoarVMバイトコードである。
Perl6のプログラムはPerl6及びNQPコンパイラによってMoarVMバイトコードに変換され、 MoarVMが評価する。
現在はMoarVMの他にJVMも動作環境として選択可能であるが、 JVM側にはMoarVMと比較して実装された機能が少ないなどの特徴がある。

MoarMVそのものはPerl6やNQPプログラムを直接は評価する事が出来ない。
従って、 NQP及びPerl6で書かれているRakudoをソースコードからビルドする際は、 予めNQPインタプリタであるnqpをビルドする必要が存在する。
Rakudoのビルド時にはこのnqpと、 nqpが動作するVMを設定として与える必要がある。
この両者を指定しない場合、 ビルド時に動的にNQP、 MoarVMをソースコードをダウンロードし、 ビルドを行う。
実際にNQPで記述されたRakudoの実装の一部をソースコード\ref{nqp_on_rakud}に示す。
\lstinputlisting[frame=lrbt, label=nqp_on_rakud, caption=Rakudoの実装の一部]{./codes/src_main.nqp}

\section{MoarVM}
MoarVMとはRakudo実装で主に使われる仮想機械である。
RakudoではPerl6とNQPを実行する際に仮想機械上で実行する。
この仮想機械はOSレベルの仮想化に使用するVirtualBoxやqemuと異なり、プロセスレベルの仮想機械である。
Rakudoではこの仮想機械にMoarVM、 Javaの仮想機械であるJVM(JavaVirtualMachine)が選択可能である。
MoarVMはこの中でRakudo独自に作成されたプロセス仮想機械であり、 現在のRakudoプロジェクトの主流な実装となっている。

MoarVMはC言語で実装されており、 レジスタマシンである。
MoarVMはNQPやPerl6から与えられたMoarVMバイトコードを評価する。

MoarVM自体の改良は現在も行われているが、 開発者の多くは新機能の実装などを中心に行っている。
速度上昇を目指したプロジェクトも存在はするが、 介入する余地があると考えられる。
また、 内部ではLuaJitというJITコンパイル用のライブラリを利用しているが、 JITに対して開発者チームの力が注がれていない。
その為、 本研究ではJITや速度上昇を最終的な目標として考え、 速度上昇までに必要なモジュール化などの実装を行う。

\section{NQP}
NQPとはRakudoにおけるPerl6の実装に利用されているプログラミング言語である。
NQP自体は、 Perl6のサブセットとして開発されている。
歴史的にはPerl6の主力実装がParrotであった際に開発され、 現在のRakudoに引き継がれている。
RakudoにおけるNQPは、 Parrot依存であった実装が取り払われている。

基本文法などはPerl6に準拠しているが、 変数を束縛で宣言する。インクリメント演算子が一部利用できない。
Perl6に存在する関数などが一部利用できないなどの制約が存在する。

NQPのコード例をソースコード\ref{fib_nqp}に示す。
\lstinputlisting[frame=lrbt, label=fib_nqp, caption=フィボナッチ数列を求めるNQPのソースコード]{./codes/fib.nqp}


Perl6はNQPで実装されている為、 Perl6におけるVMはNQPの実行を目標として開発されている。

NQP自体もNQPで実装されており、 NQPのビルドには予め用意されたMoarVMなどのVMバイトコードによるNQPインタプリタが必要となる。
実際にNQP内部で入力として与えられたNQPから加算命令を生成する部分をソースコード\ref{nqp_code_add_ops}に示す。

\lstinputlisting[frame=lrbt, label=nqp_code_add_ops, caption=NQPが加算命令を生成する箇所]{./codes/nqp_ops.nqp}


MoarVMを利用する場合、 MoarVMの実行バイナリであるmoarに対して、 ライブラリパスなどを予め用意したNQPインタプリタのバイトコードに設定する。
moarの起動時の設定は、 コマンドライン引数のオプションで与える事が可能である。
その為、 既に存在しているMoarVMバイトコードで記述されたNQPのインプリタファイルを、 適切にオプションで指定し、moarを実行することでNQPのインタプリタが起動する。


NQPのビルドフローの一部を図\ref{fig:nqp_stage0_to_1}に示す。

NQPのビルドには、 このNQPインタプリタをまず利用し、 NQP自体のソースコードを入力して与え、 ターゲットとなるVMのバイトコードを生成する。
既に用意されている、 ターゲットのVMのバイトコード化しているNQPインタプリタの状態を Stage0 と呼ぶ。
Stage0を利用し、NQPソースコードからビルドしたNQPインタプリタであるバイトコードを、 Stage1と呼ぶ。

\begin{figure}[ht]
\caption{NQP Stage1のビルドフロー}
 \begin{center}
  \includegraphics[width=120mm]{./fig/nqp_stage0_to_1.pdf}
 \end{center}
 \label{fig:nqp_stage0_to_1}
\end{figure}

Stage1をmoarの起動時オプションにライブラリとして設定し、 起動したNQPインタプリタで再度ビルドしたNQPインタプリタを、 Stage2と呼ぶ。
この2度目のビルドで、ソースコードからビルドされたVMバイトコードでNQP自身をビルドした事になる。
処理系自身をその処理系でビルドする事をセルフビルドと呼び、 NQPはセルフビルドしたStage2のバイトコードを利用する。
2度目のビルドの際に生成されたStage2を利用して、 moarを起動するスクリプトの事を小文字のnqpと呼び、これがNQPのインタプリタのコマンドとなる。

nqpは使用しているVMのバイトコードを生成する機能があり、 Rakudoのビルド時にはこの機能を利用してバイトコードを生成する。




%Data Gear はデータの単位であり、int や文字列などの Primitive Type を持っている。

%Code Gear は 任意の数の Input Data Gear を参照して処理を行い、Output Data Gear を出力し処理を終える。
%また、接続された Data Gear 以外には参照を行わない。

%処理やデータの構造が Code Gear、Data Gear に閉じているため、これにより実行時間、メモリ使用量などを予測可能なものにすることが可能になる。