あたらしものずきっ!

試してみたものとか、遊んでみたものを色々記してみます。

Yacafiの動作を読み解く 2

Yacafiの動作を読みとく より引き続く。

79 〜 95行目

_pack

 79     my $yacafi = _read_file( $INC{'Yacafi.pm'} );

_read_fileについては、143〜147に実装が書かれてる。

143 sub _read_file {
144     my $file = shift;
145     open my $fh, '<', $file or die $file . ': ' . $!;
146     do { local $/; <$fh> };
147 }

%INCには、読み込まれたファイル名とフルパスがkeyとvalueの組み合わせでつっこまれてる。Yacafi.pmのファイルパスを持ってきて、Yacafi.pmの中身を丸ごと取得する。$/はslurping(丸呑み)なモードのこと。79行目の$yacafiには、Yacafi.pm内のソースコードが丸々収まっていることになる。

次に、Yacafiソースコードから EXTEND 〜 EXTEND .. END の部分を対象にして正規表現のmatchを行う。

 81     # extends
 82     $yacafi =~ s!### EXTEND (\w+)\n(.+?)### EXTEND \1 END\n!
 83         $args{extends}->{$1} ? $2 : ''
 84     !esg;

実態は、

$yacafi =~ s!!!esg;

84行目のesgは、

  • e:式の右側の評価を行なう
  • s:ワイルドカードのドット( . )が改行にもマッチするようにする
  • g:繰り返し置換

特にYacafi.pmを弄っていない場合、importで呼び出された時に渡されるハッシュのextendsがtemplateをkeyの一つとして保有していれば、2番目にマッチした値が 382 〜 607行目の ###EXTEND 〜 ### EXTEND template END と置き換わる。

一見して分かりにくいこと間違いないけれど、

$yacafi =~ /### EXTEND (\w+)\n(.+?)### EXTEND \1 END\n/;
$yacafi = $args{extends}->{$1} ? $2 : '';

と同義。

とりあえずここまで。82〜84行目の把握にかなり時間食った気がする。