PHPの関数は使用前に定義しなくても呼び出せるという記事を書いてる途中にふとなぜそのような仕様になるのか疑問に思い,調べてみました.
注意:この記事は筆者が途中で力尽きたため,しっかりした根拠のある結論が出ていません.ご了承の上お読みください
調べた過程やリンク先について共有します,こちらについては役に立てるかと思います.
疑問
PHPはインタプリタ言語のはずなのに,定義前の関数を呼び出しても正常に呼び出せるのはなぜ?
調べてわかったこと
Zend OpCodesっていうのに一回コンパイルされるらしい
「how it works」をつけて調べてみました.以下の説明が非常にわかりやすかったです.
あくまで推測ですが,この「Zend OpCodes」という中間バイナリコードの生成時に,関数は事前に読み込まれ定義されているように見えます.
もしかしたら,定義行のアドレスはここですよって参照が貼られているだけかもしれませんが.
関数は中間コード前処理の際になんかされるらしい
Q&Aサイトの記述ですが,それっぽい記載はありました.
The PHP compiler's job is to parse your PHP code and convert it into a form suitable for the runtime engine. Here are some of its functions:https://www.quora.com/How-is-PHP-interpreted/answer/Ian-Atkin?ch=2&srid=uBQqa0
...(中略)...
- Removes comments
- Resolves variables, functions/methods and inserts relevant data into a symbol table
- Constructs an abstract syntax tree of your program
- Writes out the bytecode
The symbol table is used to store the values of variables and provide the bytecode addresses for functions and methods. Otherwise, functions would have to be defined before use, which is clearly not the case.
この説明によると,
- シンボルテーブルに関数のバイトコードのアドレスが格納される
- そのため,定義前に関数を呼び出そうとしても問題はない
と理解できました.
まだこの情報が間違っている可能性がアリアリ1なのですが,ちょっとこの辺りで終わろうと思います.
以下の情報が更に詳しそうですが,もはや理解できませんでしたw
https://blog.krakjoe.ninja/2016/03/hacking-php-7.html
参考資料他
Zend Engineについての説明:https://phpbuilder.com/php-and-zend-engine-internals/
ZendAPIについてのマニュアル説明(古い) - https://www.php.net/manual/en/internals2.ze1.zendapi.php
PHP組み込み関数の登録方法 - http://www.phpinternalsbook.com/php7/extensions_design/php_functions.html
OPCODES「DECLARE_FUNCTION」:https://www.php.net/manual/en/internals2.opcodes.declare-function.php#internals2.opcodes.declare-function
Sebastian Bergmann 氏の資料:https://www.scribd.com/document/18171982/PHP-Compiler-Internals
-
古い資料とかも参照したので,5系と7系で挙動が違ったりもしそうです ↩