php のソースコードを眺めていたときの雑多な流れ
前記事 「php 5.4 リポジトリに舞い戻ってきたクロージャの $this サポート - do_akiの徒然想記」 を書くきっかけとなった経緯とか、その周辺の調べたことを、備忘録的に書き記しておく。
乱文だし、尻切れトンボな感じだけど、せっかく調べたならオープンなところに置いといた方が良いかなと思って。
restore $this support for closures to its former glory
php のリポジトリを覗いていて、ふと目にとまった Revision.298187 *1
クロージャの中で $this を使えるようにする修正。
Author: stas Date: Mon Apr 19 19:45:03 2010 UTC (15 months, 1 week ago) Changed paths: 23 Log Message: restore $this support for closures to its former glory
このdiffの中で、従来の クロージャ生成文法 function(){} に加えて、 static function(){} という文法が加わっていた *2 ので、これは何だ? と思い調査してみることにした。
従来のクロージャ と static付きのクロージャ
二つの違いは、zend_do_begin_lambda_function_declaration の第4引数が 0 か 1 かというだけ。
zend_do_begin_lambda_function_declaration は、 Zend/zend_compile.c で定義され、やはり同コミットで変更が加えられていた。*3
違いは、 その第4引数 is_static が 真ならば CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC; をしていると言うことだけ。
CG は、 Zend/zend_globals_macros.h に定義された compiler_globals のメンバを取り出すためのマクロ。
active_op_array (struct _zend_op_array)が何なのかは厳密には分からないが、 おそらく現在読み込み中のスコープに属するオペコード群を格納しておく変数だと思う。
現在のスコープ = 現在の関数 ということだと思うので、 fn_flags は名前の通り関数自身の属性フラグということであり、どうやら、Zend/zend_compile.h に定義された ZEND_ACC_XXX が入るらしい。
つまり、 static function(){} は、 function(){} に static 属性をつけただけと言うことになる。
ところで、 php で static な function というのは、 クラス内メソッドでしか定義できない。
とすると、これが生きてくるのはクラス内で定義された クロージャだと想像できる。 (もともと $this を使えるようにするコミットに含まれているんだから当然だぁね)
そんなこんなで、色々調べてみたけど、結局 static なクロージャ の存在意義は$this の分のメモリを省略できるということくらいのよう。
https://wiki.php.net/rfc/closures の Interaction with OOP の最後の方にも書かれているし。
なんか、いろいろ調べたけど、分かったのがこんだけってのはちと悔しかったりする。