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行目の把握にかなり時間食った気がする。