SlideShare a Scribd company logo
php7’s
ast 2015/11/22
第六回闇PHP勉強会
do_aki
@do_aki
@do_aki
http://do-aki.net/
php7's ast
コンパイルプロセス(教科書的)
字句
解析
構文
解析
最適化
コード
生成
字句解析
• ソースコードをトークンに分解
• トークン := 意味を持つ最小単位
<?php
function hello ( ) {
echo ‘HELLO WORLD’ ;
}
字句解析
• ソースコードをトークンに分解
• トークン := 意味を持つ最小単位
<?php
function hello ( ) {
echo ‘HELLO WORLD’ ;
}
T_OPEN_TAG
T_FUNCTION T_STRING ( ) {
}
T_ECHO
T_CONSTANT
_ENCAPSED_STRING
;
構文解析
• トークン列から規則(文法)を導く
function hello ( ) {
echo ‘HELLO WORLD’ ;
}
T_FUNCTION T_STRING ( ) {
}
T_ECHO
T_CONSTANT
_ENCAPSED_STRING
;inner_statement_list
関数定義
php5 の コンパイルプロセス
字句解析 構文解析+コード生成
php7 の コンパイルプロセス
字句解析 構文解析 コード生成
zendlex -> TOKEN zendparse -> OPCODE
zendlex -> TOKEN zendparse -> AST zend_compile_stmt -> OPCODE
php5 の コンパイルプロセス
字句解析 構文解析+コード生成
php7 の コンパイルプロセス
字句解析 構文解析 コード生成
zendlex -> TOKEN zendparse -> OPCODE
zendlex -> TOKEN zendparse -> AST zend_compile_stmt -> OPCODE
構文解析で AST を構築し、
AST から OPCODE を生成
導入理由
コンパイラおよびパーサのメンテナンス
性向上 (技巧的なコードの排除)
技術的な問題により、導入が困難であっ
た文法を扱えるようになる
PHP の AST
zend_ast (基本形)
• Zend/zend_ast.h / Zend/zend_ast.c
typedef uint16_t zend_ast_kind;
typedef uint16_t zend_ast_attr;
struct _zend_ast {
zend_ast_kind kind;
/* Type of the node (ZEND_AST_* enum constant) */
zend_ast_attr attr;
/* Additional attribute, use depending on node type */
uint32_t lineno;
/* Line number */
zend_ast *child[1];
/* Array of children (using struct hack) */
};
typedef struct _zend_ast zend_ast; // <- Zend/zend_types.h
Zend/zend_ast.h より 一部見やすさのために改変
zend_ast_kind
• ZEND_AST_*
• 全98種 (php7.0.0 RC7 時点)
• 大まかに分類して4系統
– 特殊ノード ZEND_AST_ZVAL / ZEND_AST_ZNODE
– 定義ノード ZEND_AST_CLASS など
– リストノード ZEND_AST_STMT_LIST など
– 通常ノード ZEND_AST_VAR, ZEND_AST_FOREACH など
特殊ノード (special nodes)
• ZEND_AST_ZVAL
– zval を包含するノード
– リテラル や 変数名、呼び出し関数名等
– 常にリーフ
• ZEND_AST_ZNODE
– 構文解析の過程では一切利用されない
– コンパイル時に一時的に使われる
– あまり詳しく追ってない
定義ノード (declaration nodes)
• doc_comment を保持
• 常に4つの子ノードを確保 (NULL の場合もある)
• ZEND_AST_FUNC_DECL 関数定義
• ZEND_AST_CLOSURE 無名関数定義
• ZEND_AST_METHOD メソッド定義
• ZEND_AST_CLASS クラス、無名クラス、
インタフェース、トレイト定義
リストノード (list nodes)
• 配下に複数のノードを格納するノード
• ZEND_AST_STMT ステートメントを格納(ASTのROOT)
• ZEND_AST_IF if文の各条件とブロックを格納
• ZEND_AST_ARRAY 配列
• その他、 ZEND_AST_ARG_LIST 等 “,” を
使って列挙するところは大体ここに分類
通常ノード(standard nodes)
• 0 child nodes
– ZEND_AST_MAGIC_CONST / ZEND_AST_TYPE
– __LINE__ とか / callable とか
• 1 child nodes
– 変数、定数、キャスト、単項演算子 等
• 2 child nodes
– 配列の要素参照、関数呼び出し、代入、2項演算子、new など
• 3 child nodes
– メソッド呼び出し、プロパティ定義、3項演算子 など
• 4 child nodes
– ZEND_AST_FOR / ZEND_AST_FOREACH
– for (1, 2, 3) { 4 } / foreach (1 as 2 => 3) {4}
専用のメモリ領域
• CG(ast_arena)
• 初期サイズは32MB
• 構文解析前に確保
(zend_arena_create)
• OPCODE生成後に破棄
(zend_arena_destroy)
zend_ast_create_*
zend_ast_alloc(size)
zend_arena_alloc(
&CG(ast_arena), size)
AST Hook Function
• AST構築直後 (OPCODE 生成前)に呼ばれる
• AST そのものが渡される -> 改変可能
• 将来的には、このフックポイントを利用した、最
適化やフィルタを行う拡張が生まれるのでは
• https://wiki.php.net/rfc/parser-
extension-api
typedef void (*zend_ast_process_t)(zend_ast *ast);
extern ZEND_API zend_ast_process_t zend_ast_process;
nikic/php-ast
https://github.com/nikic/php-ast
do-aki/phpast
https://github.com/do-aki/phpast
DEMO
Hello world
function hello() {
echo 'hello wporld';
}
FizzBuzz
for ($i = 1; $i <= 100; $i++) {
if ($i % 3 == 0 && $i % 5 == 0) {
echo 'FizzBuzz';
} elseif ($i % 5 == 0) {
echo 'Buzz';
} elseif ($i % 3 == 0) {
echo 'Fizz';
} else {
echo $i;
}
echo PHP_EOL;
}
any question?
(blank)
字句解析器の状態 (全10状態)
• 初期状態 (INITIAL)
• PHP Script (ST_IN_SCRIPTING)
• 文字列解析のための状態
– ST_DOUBLE_QUOTES
– ST_BACKQUOTE
– ST_HEREDOC
– ST_END_HEREDOC
– ST_NOWDOC
– ST_LOOKING_FOR_VARNAME (${)
• プロパティ参照解析のための状態
– ST_LOOKING_FOR_PROPERTY ($xxx->)
• 配列要素参照解析のための状態
– ST_VAR_OFFSET

More Related Content

PPTX
PHP AST 徹底解説(補遺)
PPTX
PHP AST 徹底解説
PPTX
php-src の歩き方
PPTX
PHP と SAPI と ZendEngine3 と
PPTX
Php in ruby
PDF
OPcache の最適化器の今
PPT
CPANの依存モジュールをもう少し正しく検出したい
PPTX
php and sapi and zendengine2 and...
PHP AST 徹底解説(補遺)
PHP AST 徹底解説
php-src の歩き方
PHP と SAPI と ZendEngine3 と
Php in ruby
OPcache の最適化器の今
CPANの依存モジュールをもう少し正しく検出したい
php and sapi and zendengine2 and...

What's hot (20)

PDF
最近の PHP の話
PPT
2017年夏のPerl
PPT
How to debug a perl script using gdb
PPTX
PHPとシグナル、その裏側
PPTX
CMSとPerlで遊ぼう
PDF
OSS開発勉強会-10
PDF
PHPの今とこれから2014
PDF
Good Parts of PHP and the UNIX Philosophy
PDF
ELFの動的リンク
PDF
PECL を数えてみた
PPT
2017年春のPerl
KEY
モダンmod_perl入門 #yapcasia
PDF
Local php-100828 2
PDF
実"戦"CakePHP Plugin
PDF
PHPの今とこれから 2013
PDF
WebAPIではじめるphp入門
PDF
PPTX
はりぼて OS で ELF なアプリを起動してみた
PDF
Hack/HHVM 入門
PPTX
詳説ぺちぺち
最近の PHP の話
2017年夏のPerl
How to debug a perl script using gdb
PHPとシグナル、その裏側
CMSとPerlで遊ぼう
OSS開発勉強会-10
PHPの今とこれから2014
Good Parts of PHP and the UNIX Philosophy
ELFの動的リンク
PECL を数えてみた
2017年春のPerl
モダンmod_perl入門 #yapcasia
Local php-100828 2
実"戦"CakePHP Plugin
PHPの今とこれから 2013
WebAPIではじめるphp入門
はりぼて OS で ELF なアプリを起動してみた
Hack/HHVM 入門
詳説ぺちぺち
Ad

Viewers also liked (20)

PPTX
Writing php extensions in golang
PPTX
N対1 レプリケーション + Optimizer Hint
PPTX
SQLite2と3のエスケープ関数の違いとその対策
PPTX
signal の話 或いは Zend Signals とは何か
PDF
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
PDF
php-buildがいかに便利かを力説する
PDF
PHPNGの動向
PDF
PHP7の拡張モジュール事情
PDF
Laungage Update PHP編
PDF
PHP7の内部実装から学ぶ性能改善テクニック
PDF
realpathキャッシュと OPcacheの面倒すぎる関係
PDF
PHPの拡張モジュールをGoで作る
PDF
PHP7はなぜ速いのか
PDF
偶然にも500万個のSSH公開鍵を手に入れた俺たちは
PDF
PHP7で変わること ——言語仕様とエンジンの改善ポイント
PPTX
20141011 mastering mysqlnd
PDF
Sinatra風マイクロフレームワークで始めるPython
PPTX
マスタN対スレーブ1レプリケーションの作り方 ~あれから~
PDF
Testing PHP extension on Travis CI
PPTX
Excel is image viewer
Writing php extensions in golang
N対1 レプリケーション + Optimizer Hint
SQLite2と3のエスケープ関数の違いとその対策
signal の話 或いは Zend Signals とは何か
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
php-buildがいかに便利かを力説する
PHPNGの動向
PHP7の拡張モジュール事情
Laungage Update PHP編
PHP7の内部実装から学ぶ性能改善テクニック
realpathキャッシュと OPcacheの面倒すぎる関係
PHPの拡張モジュールをGoで作る
PHP7はなぜ速いのか
偶然にも500万個のSSH公開鍵を手に入れた俺たちは
PHP7で変わること ——言語仕様とエンジンの改善ポイント
20141011 mastering mysqlnd
Sinatra風マイクロフレームワークで始めるPython
マスタN対スレーブ1レプリケーションの作り方 ~あれから~
Testing PHP extension on Travis CI
Excel is image viewer
Ad

Similar to php7's ast (20)

PDF
PPTX
C# 7.2 with .NET Core 2.1
PDF
Java8から17へ
PDF
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
PDF
asm.js x emscripten: The foundation of the next level Web games
ODP
Racc でおてがる構文解析
PDF
Lisp batton - Common LISP
PDF
シェル芸初心者によるシェル芸入門 (修正版)
PDF
中3女子が狂える本当に気持ちのいい constexpr
PDF
「Html sql」で図書館hpにアクセスしてみよう
PDF
Elasticsearch入門 pyfes 201207
PDF
What is Metasepi?
PDF
Perl io layer
PDF
Lisp Tutorial for Pythonista : Day 3
PDF
最新PHP事情 (2000年7月22日,PHPカンファレンス)
PDF
Write good parser in perl
PDF
Cookpad Summer Intern 2015 - Programming Paradigm
ODP
Buffer overflow
PDF
Dalvikバイトコードリファレンスの読み方 改訂版
PDF
Boost Fusion Library
C# 7.2 with .NET Core 2.1
Java8から17へ
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
asm.js x emscripten: The foundation of the next level Web games
Racc でおてがる構文解析
Lisp batton - Common LISP
シェル芸初心者によるシェル芸入門 (修正版)
中3女子が狂える本当に気持ちのいい constexpr
「Html sql」で図書館hpにアクセスしてみよう
Elasticsearch入門 pyfes 201207
What is Metasepi?
Perl io layer
Lisp Tutorial for Pythonista : Day 3
最新PHP事情 (2000年7月22日,PHPカンファレンス)
Write good parser in perl
Cookpad Summer Intern 2015 - Programming Paradigm
Buffer overflow
Dalvikバイトコードリファレンスの読み方 改訂版
Boost Fusion Library

More from do_aki (17)

PPTX
Tritonn から Elasticsearch への移行話
PPTX
再考:列挙型
PPTX
20150212 プレゼンテーションzen
PPTX
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」
PPTX
20141017 introduce razor
PPTX
php in ruby
PPTX
PHP から Groonga を使うにはこんなコードになるよ!
PPTX
N:1 Replication meets MHA
PDF
Php radomize
PPTX
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editor
PPTX
Immortal
PDF
A bridge between php and ruby
PDF
Ruby and comparison_and...php
PPTX
Sore php
PPTX
Ruby enumerable source code reading
PPTX
続マスタN対スレーブ1レプリケーションの作り方
PPTX
Mod lua
Tritonn から Elasticsearch への移行話
再考:列挙型
20150212 プレゼンテーションzen
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」
20141017 introduce razor
php in ruby
PHP から Groonga を使うにはこんなコードになるよ!
N:1 Replication meets MHA
Php radomize
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editor
Immortal
A bridge between php and ruby
Ruby and comparison_and...php
Sore php
Ruby enumerable source code reading
続マスタN対スレーブ1レプリケーションの作り方
Mod lua

php7's ast

Editor's Notes

  • #13: ほかにも zval, list, decl といった構造体もあるが、 kind, attr を持ち、lineno を包含し、 0以上の子ノードを持つ というのは同じ