5.10.0
Other versions:
5.14.1
5.12.1
5.10.1

名前

perlcompile - Perlコンパイラ・トランスレータの解説

概説

Perlは常にコンパイラを持っています:ソースコードは内部コード(パースされたツリー)に変換され実行する前に最適化されます。バージョン5.005以来、Perlは最適化されたパースされたツリー(B)を調査できる能力があるモジュールとともに配布されいます。そして、このツールは様々な便利なユーティリティを記述するのに用いられています。モジュールを内包し、PerlからCのコードに変換されネイティブに実行可能なファイルにコンパイルされるのです。

Bモジュールはパースされた構文木にアクセスすることを可能にします、又、その他のモジュール("back ends")はその構文木を利用します。又、いくらか読みやすく出力します。その他の用途としてはサブルーチンの繋がりや変数がどこで使用されているかなどのクロスリファレンスを生成するのに用いられています。またコードのチェックにも用いられています。もう一つのバックエンドとしてコードを整頓し美しく読みやすいPerlソースとして再出力します。

なぜなら本来の目的がPerlプログラムと等価なC言語のコードを提供し、ネイティブで実行可能にすることにあるからです。Bモジュールは本来何もコンパイルはしないのですが、現在コンパイラとして知られています。このコンパイラは正確に言うとトランスレータやインスペクターに近いです。しかし、人々はPerlにインスペクタ・ツールではなくコンパイラーオプションを持ってほしいと思っています。あなたには何ができますか?

このドキュメントはPerlコンパイラについて解説しています。:Perlコンパイラを構成しているモジュール、バックエンドモジュールの使い方、そしてそこにどのような問題があるか、

構成

コンパイラのバックエンドはB::以下に入っています。、またフロントエンド(あなたや、コンパイラユーザーが使うであろう)はOモジュールです。

重要なバックエンドのリスト。それぞれの0(今後実装するためのアウトラインの段階)から10(完璧に仕事を完了したはずで、バグがあるとは考えられません)のステータスナンバーは作業進行度を表しています。

B::Lint

あなたのコードのに疑わしい部分があれば警告するバックエンドステータス: 6 (適切に動作しますが、限られたエリアしかチェックしません。).

B::Deparse

フォーマットが一貫しているか注意しながらのPerlソースの再構成を行うバックエンドステータス8:ほぼ正確に動作しますが、いくつかの不明瞭なものは失われるでしょう。

B::Xref

変数やサブルーチンの宣言のレポートステータス8:正しく働いているが、まだいくつかの根深いバグがあります。

バックエンドを使用する

これらの章はどのようにコンパイラのバックエンドを利用するかを解説します。これらのバックエンドは開発が盛んに行われています。そこで、まず初めに十分に検証されているバックエンドについて解説し、そのあと開発中のバックエンドについて解説したいと思います。

Oモジュールは-cフラグをPerlに渡すことで自動的に有効になります。このフラグを有効にするとPerlはコードを実行せずにコンパイルだけを行います。バックエンドの出力の解説:

  myperlprogram syntax OK

すべての出力に先立ってこのような表示がなされます。

クロスリファレンスのバックエンド

クロスリファレンスを作成するバックエンド(B::Xref)は変数の宣言やサブルーチンの使用法などの分析を行ったレポートを作成します。れいとして、pod2manプログラムのレポートを掲載します:

  Subroutine clear_noremap
    Package (lexical)
      $ready_to_print   i1069, 1079
    Package main
      $&                1086
      $.                1086
      $0                1086
      $1                1087
      $2                1085, 1085
      $3                1085, 1085
      $ARGV             1086
      %HTML_Escapes     1085, 1085

これはclear_noremapで用いられている変数を表示しています。$ready_to_printという変数はmy()(レキシカル)変数で、1069行目でmyで宣言されおり、1079行目で使用されております。メインパッケージの$&という変数は1086行目で使われております。変数の後に続く数値はこの様な意味を表しています。

行番号は以下のプレフィックスを伴って出力されます。

i

my()で宣言されたレキシカル変数

&

サブルーチンまたはメソッド呼び出し

s

サブルーチンの定義

r

フォーマットの定義

クロスリファレンスを作成するにあたり有用なオプションとしてレポートを複数のファイルに分割して保存するというものがあります。たとえばmyperlprogramのレポートとreportファイルに保存するには以下のようにします:

  $ perl -MO=Xref,-oreport myperlprogram

デコンパイルバックエンド

デパースバックエンドはあなたのPerlソースがPerlコンパイラにどのようにパースされたかを表示します. この出力は読みやすいように整形することができます。基本的な使用法は以下の通りです:

  $ perl -MO=Deparse myperlprogram

出力を見るとあなたはPerlがコードをどのように整形すべきか分かっていないことが分かるでしょう。あなたはコードのブロックごとに自分で改行することになるでしょうしかし、その作業は以下のワンライナーで可能です:

  $ perl -MO=Deparse -e '$op=shift||die "usage: $0
  code [...]";chomp(@ARGV=<>)unless@ARGV; for(@ARGV){$was=$_;eval$op;
  die$@ if$@; rename$was,$_ unless$was eq $_}'
  -e syntax OK
  $op = shift @ARGV || die("usage: $0 code [...]");
  chomp(@ARGV = <ARGV>) unless @ARGV;
  foreach $_ (@ARGV) {
      $was = $_;
      eval $op;
      die $@ if $@;
      rename $was, $_ unless $was eq $_;
  }

デコンパイラは生成するコードに対するオプションを持っています例えば、あなたはインデントとのサイズを4から2に変更できます:

  $ perl -MO=Deparse,-si2 myperlprogram

-pオプションは可能なところにはカッコを挿入します:

  $ perl -MO=Deparse -e 'print "Hello, world\n"'
  -e syntax OK
  print "Hello, world\n";
  $ perl -MO=Deparse,-p -e 'print "Hello, world\n"'
  -e syntax OK
  print("Hello, world\n");

その他のフォーマットオプションはB::Deparseを参照してください。

Lintバックエンド

Lintバックエンド(B::Lint)はプログラムを調査します他のプログラマの間違ったスタイルは他のプログラマの学習を促進します、よってどのような事について警告するかオプションで設定できます。

スタイルチェッカーをあなたのコードにたいして走らせるには以下のようにします:

  $ perl -MO=Lint myperlprogram

無効な構文や、定義されていないサブルーチンをチェックするには以下のようにします:

  $ perl -MO=Lint,-context,-undefined-subs myperlprogram

その他のオプションについてはB::Lintを参照してください。

コンパイラに関するモジュールのリスト

B

このモジュールはPerlプログラム内の機構を内省すること他できます。(Javaでは"reflective"といいます。)バックエンドモジュールはパースされた構文木にアクセスする機能を提供します。バックエンドモジュールのユーザーはBに関する経験は問われません。

O

このモジュールはコンパイラのバックエンドのフロントエンドモジュールです。通常では以下のように利用します:

  $ perl -MO=Deparse myperlprogram

use O'Deparse'があなたのプログラムに含まれているように表示します。

B::Concise

このモジュールは簡潔な(かつ完璧な)パース済みのPerl構文木を表示します。このモジュールの出力はB::TerseやB::Debugよりもカスタマイズ可能です。(またそれらをエミュレートすることも可能です。)このモジュールはバックエンドを書いている人や、Perlの内部構造を学びたい人に役立つでしょう。しかし、このモジュールは平均的なプログラマには役に立たないでしょう。

B::Debug

このモジュールはPerlパースツリーを詳細にSTDOUTに表示します。このモジュールはバックエンドを書いている人やPerlの内部構造を学びたい人には役立つでしょう。しかし、このモジュールは平均的なプログラマには役に立たないでしょう。

B::Deparse

このモジュールはPerlコードのコンパイル済みのパースされた構文木を提供します。このモジュールは他人の書いたコードをデバッグ・再構成しようとしている人に役立つでしょう。また自分のコードを綺麗に出力するのにも役立ちます。使用法の詳細は"The Decompiling Back End"を参照してください。

B::Lint

このモジュールはコンパイルされたあなたのソースコードを分析します。例えば、配列をscalar(@array)することなくスカラーとして扱おうとしているとき使用法の詳細は"The Lint Back End"を参照してください。

B::Showlex

このモジュールは関数内およびファイルないで使用されているmyで宣言された変数を表示します。myperlprogram内で定義されたmysub()サブルーチンないで使用されているmy()で宣言された変数を取得するには以下のようにします:

  $ perl -MO=Showlex,mysub myperlprogram

myperlprogram内で使用されているmy()で宣言された変数を取得するには以下のようにします:

  $ perl -MO=Showlex myperlprogram

[BROKEN]

B::Terse

このモジュールはパースされた構文木を出力しますが、B::Debugより得られる情報は少ないです。比較のための例としてprint "Hello, world."についてB::Debugは96行もの情報を出力しますが、B::Terseは6行しか出力しません。

このモジュールは自分のプログラムのバックエンドを書いている人及びPerlの内部について学ぼうとしている人に役立つでしょう。しかし、このモジュールは平均的なプログラマには役に立たないでしょう。

B::Xref

このモジュールは変数、サブルーチン、プログラム内で使用されたフォーマット、モジュールのロードそれぞれの場所についてレポートを出力します。使用法の詳細は"The Cross Referencing Back End"を参照してください。

既知の不具合

BEGIN{}ブロックはコードがコンパイルされる段階で実行されてしまいます。BEGIN{}内でのファイルを開閉、データベースの処理などの処理は通常どおりに動作しません。これにうまく対処するには、PerlのINIT{}ブロック構文を使います。この構文はあなたのコードがコンパイルされたあと、実行されるまえに処理されます。実行される順序:BEGIN{}ブロック、(コンパイラのバックエンドを用いて状態を保存できます)、INIT{}ブロック、コードの実行、END{}ブロック

著者

このドキュメントはNathan Torkingtonによって書かれ、現在は perl5-portersのメーリングリストperl5-porters@perl.orgによって保守されています。