Upload
tsunenori-oohara
View
583
Download
0
Embed Size (px)
Citation preview
EExTemplate Engine for Elixir
Embedded Elixir2016/09/22 tokyo.ex #6 おーはら
Agenda
自己紹介|> 趣旨|> TemplateEngine とは|> EEx とは|> EEx の構成|> eval_(string|file)|> function_from_(string|file)|> compile_(string|file)
|> 仕組み|> AST とは|> compile|> Tokenizer|> Engine|> まとめ
自己紹介• おーはら @ohrdev– 基盤技術部 @ ドリコム
• 仕事 / 技術スタック– 広告サービスのお世話– 全社基盤システムのお世話– Elixir/Erlang/Ruby/LFE/Lisp/etc…
• コミュニティ– ElixirMeetUp 、 tokyo.ex 、 VR.tokyo– tokyo.erl (予定、 10 月前半頃に告知します)
趣旨• ターゲット– EEx is 何 ? な方
• ゴール– EEx の使い方がわかる– EEx の仕組みがわかる
TemplateEngine とは• テンプレート ( 雛形 ) と入力データを合成してドキュメント ( 文字列 ) を出力するソフトウェア– ex) jinja2, jade, erb, haml, slim,
etc• ウェブページ ( マークアップ ) を出力するエンジンを特に、ウェブテンプレートエンジンと言う– WAF にバンドルされてる事が多い (Rails の erb など )
EEx とは• Embedded Elixir (EEx)• 文字列、テンプレートに Elixir のコードを評価して埋め込む処理を提供するモジュール• Elixir にデフォルトでバンドル– https://github.com/elixir-lang/elixir/tree/master/li
b/eex
EEx の構成• 主要 API– eval_string, eval_file• 入力データと文字列 / ファイルを直接評価して文字列を出力、実行毎に compile/eval するので遅い
– function_from_string, function_from_file• 文字列 / ファイルから、入力データを引数にして文字列を出力する関数を定義するマクロ
– compile_string, compile_file• 上 2 つの API の内部で使用される、文字列 / ファイルを Elixir の AST にコンパイルする
eval_stringEEx.eval_string <source>, <binding>, <option>
eval_fileEEx.eval_file <file>, <binding>, <option>
function_from_(string|file)EEx.function_from_string <type>, <name>, <source>, <args>, <option>EEx.function_from_file <type>, <name>, <file>, <args>, <option>
function_from_string(public)
function_from_string(private)
function_from_file
仕組み :eval_(string|file)<source> <file>
EEx.compile_stringEEx.compile_file
EEx.eval_string <source>, <binding>
EEx.eval_file <file>, <binding>
EEx.do_eval
Result Document
<binding>Elixir の AST
Code.eval_quoted
実行毎に、 compile, evalされる
遅い !
<file> が更新されても、即反映される
仕組み :function_from_(string|file)
<source> <file>
EEx.function_from_stringEEx.function_from_file
EEx.function_from_string <type>, <name>, <source>, <args>
EEx.function_from_file <type>, <name>, <file>, <args>
Result Document
BEAM
macro
def(p) name(args) do <source> or <file>end
compile
expand
VMname(a1, a2 …)
load
compile してから実行
phoenix_live_reloader等でリロード
<file> が更新されると、再 compile が必要
AST とは• Abstract Syntax Tree• Elixir の式の内部表現、以下のタプルで表す– { : 関数名 , メタデータ , 引数 }– ex) 1 + 1 #=> {:+, [metadatas], [1, 1]}
• quote で AST を確認できる
AST とは• Code.eval_quoted で AST を評価できる– eval_quoted <ast>, <binding>
• 詳しくは、 Metaprogramming Elixir を参照– https://www.amazon.co.jp/dp/B00U1VU2GA
compile
• compile_string, compile_file の実体は、 EEx.Compiler.compile <source>, <option>
• EEx.Engine|EEx.SmartEngine を使って、出力文字列の AST を返却する
compile
compile の流れEEx.Tokenizer.tokenize
<source>
<tokens>
EEx.Engine.init EEx.Engine.handle_body
buffer
<AST>
EEx.Engine.handle_text EEx.Engine.handle_expr
入力文字列をトークンのリストに変換
Tokenizer
• Elixir コード ( ロジックやバインディング )を含む文字列を Token のリストに変換する
compile の流れEEx.Tokenizer.tokenize
<source>
<tokens>
EEx.Engine.init EEx.Engine.handle_body
buffer
<AST>
EEx.Engine.handle_text EEx.Engine.handle_expr
Engine
初期 Buffer 後処理
Buffer と Token からquote された式を返却
Engine
• Token をバッファを使って、 quote された式 (AST) に変換する• 4 つのコールバックを実装する必要がある
( ビヘイビア )– init/1, handle_text/2, handle_expr/3,
handle_body/1• デフォルトは EEx.SmartEngine• compile 時の :engine オプションで使用する Engine を指定
カスタム Engine
• カスタムエンジンの使い方– init, handle_test, handle_expr, handle_body の
callback を実装したエンジンモジュールを作成– コンパイル時の :engine オプションで指定
まとめ• Elixir のテンプレートエンジンの EEx を紹介しました• テンプレートとデータからドキュメント
( 文字列 ) を出力する流れを説明しました• コンパイル時のトークナイザー、エンジンの処理を説明しました• カスタムエンジンの作り方を説明しました