php7's ast

27
php7’s ast 2015/11/22 第第第第 PHP 第第第 do_aki

Upload: doaki

Post on 07-Jan-2017

6.136 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: php7's ast

php7’s ast

2015/11/22 第六回闇 PHP勉強会do_aki

Page 2: php7's ast

@do_aki

@do_aki

http://do-aki.net/

Page 3: php7's ast

agenda

1.PHP コンパイラの概要

2.PHP AST の概要

3.PHP AST の視覚化 (DEMO)

Page 4: php7's ast

コンパイルプロセス(教科書的 )

字句解析

構文解析 最適化 コード

生成

Page 5: php7's ast

字句解析

• ソースコードをトークンに分解• トークン := 意味を持つ最小単位

<?php

function hello ( ) {

echo ‘HELLO WORLD’ ;

}

Page 6: php7's ast

字句解析

• ソースコードをトークンに分解• トークン := 意味を持つ最小単位

<?php

function hello ( ) {

echo ‘HELLO WORLD’ ;

}

T_OPEN_TAG

T_FUNCTION T_STRING ( ) {

}

T_ECHO T_CONSTANT_ENCAPSED_STRING ;

Page 7: php7's ast

構文解析

• トークン列から規則(文法)を導く

function hello ( ) {

echo ‘HELLO WORLD’ ;

}

T_FUNCTION T_STRING ( ) {

}

T_ECHO T_CONSTANT_ENCAPSED_STRING ;inner_statement_list

関数定義

Page 8: php7's ast

php5 の コンパイルプロセス

字句解析 構文解析 + コード生成

php7 の コンパイルプロセス

字句解析 構文解析 コード生成

zendlex -> TOKEN zendparse -> OPCODE

zendlex -> TOKEN zendparse -> AST zend_compile_stmt -> OPCODE

Page 9: php7's ast

php5 の コンパイルプロセス

字句解析 構文解析 + コード生成

php7 の コンパイルプロセス

字句解析 構文解析 コード生成

zendlex -> TOKEN zendparse -> OPCODE

zendlex -> TOKEN zendparse -> AST zend_compile_stmt -> OPCODE

構文解析で AST を構築し、AST から OPCODE を生成

Page 10: php7's ast

導入理由

コンパイラおよびパーサのメンテナンス性向上 (技巧的なコードの排除)

技術的な問題により、導入が困難であった文法を扱えるようになる

Page 11: php7's ast

PHP の AST

Page 12: php7's 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 より 一部見やすさのために改変

Page 13: php7's ast

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 な

Page 14: php7's ast

特殊ノード (special nodes)

• ZEND_AST_ZVAL– zval を包含するノード–リテラル や 変数名、呼び出し関数名等–常にリーフ

• ZEND_AST_ZNODE–構文解析の過程では一切利用されない–コンパイル時に一時的に使われる–あまり詳しく追ってない

Page 15: php7's ast

定義ノード (declaration nodes)

• doc_comment を保持

• 常に4つの子ノードを確保 (NULL の場合もある)

• ZEND_AST_FUNC_DECL 関数定義

• ZEND_AST_CLOSURE  無名関数定義

• ZEND_AST_METHOD   メソッド定義

• ZEND_AST_CLASS   クラス、無名クラス、 インタ

フェース、トレイト定義

Page 16: php7's ast

リストノード (list nodes)• 配下に複数のノードを格納するノード

• ZEND_AST_STMT ステートメントを格納 (ASTの ROOT)

• ZEND_AST_IF if文の各条件とブロックを格納

• ZEND_AST_ARRAY 配列

• その他、 ZEND_AST_ARG_LIST 等 “ ,” を使って列挙するところは大体ここに分類

Page 17: php7's ast

通常ノード (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}

Page 18: php7's ast

専用のメモリ領域

• 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)

Page 19: php7's ast

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;

Page 20: php7's ast

nikic/php-asthttps://github.com/nikic/php-ast

Page 21: php7's ast

do-aki/phpasthttps://github.com/do-aki/phpast

Page 22: php7's ast

DEMO

Page 23: php7's ast

Hello world

function hello() { echo 'hello wporld';}

Page 24: php7's ast

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;}

Page 25: php7's ast

any question?

Page 26: php7's ast

(blank)

Page 27: php7's ast

字句解析器の状態 (全 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