B 演習 ( 言語処理系演習 ) 第 8 回 評価器

35
B 演演 ( 演演演演演演演 ) 演 8 演 演演演 演演

description

B 演習 ( 言語処理系演習 ) 第 8 回 評価器. 田浦. すでにそろっている材料. すでにそろっている材料 構文木 ( 実行すべきプログラムの文面を表したデータ構造 ) Python 値の表現や構築方法 mk_py_int(5), mk_py_float(3.3), … 最終ステージ : 評価器 プログラムを実行  言われた Python 値を作ったり,表示したり, etc. 概要. 環境の概念 式を評価する 演算子,組み込み関数の実装法 文を評価する 実行時エラーの表示. 最終課題について. いずれも規定課題の 正しい実行 + 性能測定 - PowerPoint PPT Presentation

Transcript of B 演習 ( 言語処理系演習 ) 第 8 回 評価器

Page 1: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

B 演習 ( 言語処理系演習 ) 第 8 回評価器

田浦

Page 2: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

すでにそろっている材料 すでにそろっている材料

• 構文木 ( 実行すべきプログラムの文面を表したデータ構造 )

• Python 値の表現や構築方法• mk_py_int(5), mk_py_float(3.3), …

最終ステージ : 評価器• プログラムを実行 言われた Python 値を

作ったり,表示したり, etc.

Page 3: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

概要 環境の概念 式を評価する

• 演算子,組み込み関数の実装法 文を評価する 実行時エラーの表示

Page 4: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

最終課題について いずれも規定課題の正しい実行 + 性能測定 選択肢

• ○ mini-Python• △ sub-Python =

mini-Python – 辞書,リスト,タプル,文字列• ◎ mini-Python + α

• α の例• 性能向上• オリジナルな mini-Python プログラム ( 大きめ )• GC

Page 5: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

sub-Python

サポートするデータ型が• 整数,浮動小数点数, None, 関数 (Python,

native) だけ• おまけとして for 文もなくなる ( 文字列,タ

プル,リストのどれかがないと実行できないため )

• これでも評価器の大部分を作ることにはなるが,組み込み関数・演算子の数が激減し,各々の演算子の動作も単純になる

Page 6: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

式を評価する py_val_t eval_expr(expr_t e, …)

構文木評価値のデータ表現

構文木評価値のデータ表現

Page 7: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

全体像 py_val_t eval_expr(expr_t e, …) {

switch (e->kind) { case expr_kind_var: … case expr_kind_literal_int: … case expr_kind_literal_float: … … }}

Page 8: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

最も簡単な場合の例 (int リテラル )

case expr_kind_literal_int: return mk_py_int(e->u.lit_i);

構文木中にある整数

mini-Python のデータ表現への変換 (pyvalues.c)

Page 9: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

簡単にいかない例 : 変数 case expr_kind_var:

… e->u.var … ?? 構文木を見ただけではその変数の値は分

からない 「変数名 値に関する情報」が必要

環境

Page 10: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

環境 変数名とその値の対応を保持しているもの ある式の評価値はそれだけでは定まらず,環境

があってはじめて値が決まる• 式を「環境の下」で評価する• 同じ変数名でも関数が違えば異なる値を保持してい

る• それらは「環境が違う」

• eval_expr は「環境」を引数として受け取る 変数のスコープ規則 ( 局所変数,大域変数 ) な

どを正確に述べる上でも役に立つ概念

Page 11: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

Python の変数,スコープ規則 局所変数と大域変数 z = 10def f(): y = 20def g(): z = 30def h(): global z z = 40

大域変数 z への代入

局所変数 y への代入

局所変数 z への代入

大域変数 z への代入

Page 12: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

変数参照 まず局所変数を,なければ大域変数を参

照する z = 10def f(): z = 5 return zdef g(): return z

局所変数 z を参照

大域変数 z を参照

Page 13: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

環境による説明 プログラム全体で唯一,大域環境が作ら

れる 毎関数呼び出し時に,その呼び出し用の

「局所環境」が作られる あらゆる式・文は,局所環境,大域環境

の下で評価される ( 便宜上,トップレベルは局所環境 = 大域環境と考える )

Page 14: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

eval_expr のインタフェース py_val_t eval_expr(expr_t e,

env_t lenv, env_t genv,              stack_trace_t bt)

局所環境 大域環境

スタックトレース ( 関数呼び出し履歴 )エラーメッセージの表示用 ( 後述 )

Page 15: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

変数への代入 , global

global x• 局所環境で「 x は大域変数である」とマーク

x = v• 局所環境の x を v にセット• ただし, x が大域変数であるとマークされて

いれば大域環境の x を v にセット

Page 16: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

変数の参照 局所環境を探索 見つからなければ,またはその変数が大

域変数であるとマークされていれば大域環境を探索

見つかればそれが評価値 見つからなければ実行時エラー

Page 17: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

環境のインタフェース env_t mk_env() env_set(env_t env, char* key, py_val_t val) py_val_t env_lookup(env_t env, char * key) void env_set_global(env_t env, char * key) int env_is_global(env_t env, char * key)

Page 18: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

変数参照の評価 ( まとめ ) py_val_t env_lookup_var( env_t lenv, env_t genv, char * key, …) { py_val_t v = env_lookup(lenv, key); if (v != py_val_not_found && v != py_val_global) return v; v = env_lookup(genv, key); if (v != py_val_not_found) return v; else エラー ; }

Page 19: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

その他のケース expr_kind_display_tuple:   /* [ a, b, c,...] */ expr_kind_display_list:   /* [ a, b, c,...] */ expr_kind_display_dict:   /* { a : x, b : y }

*/ expr_kind_paren:   /* ( e ) */ expr_kind_operator:     /* e + e, etc. */ expr_kind_subscript: /* e[e] */ expr_kind_attref: /* e.f */ case expr_kind_call: /* e(e:e,..) */

要素部を評価してデータを作る関数を呼ぶ(mk_py_tuple, etc.)

sub-Python では不要

カッコ内の式を評価する

ほとんどの場合関数呼び出しの一種とみなせる ( 後述 )

単独で現れたらエラー ( 後述 )

Page 20: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

関数呼び出し式の評価

E0 (E1, …, En) の評価 ( 後でひとつだけ例外説明 )• E0 を評価   py_val_t : f

• E1, …, En を評価   py_val_vec_t : A

• 場合 1: f が native 関数の場合対応する C 関数を呼び出す

• 場合 2: f が Python 関数の場合後述• 場合 3: どちらでもない場合エラー

Page 21: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

Python 関数の呼び出し 新しい環境を作る (e’ = mk_env()) その環境に「パラメータ名 : 渡された引

数」を登録する (env_set(e’, …)) その新しい局所環境の下で関数の本体

( 文の列 ) を評価する (eval_stmt_vec(…, e’, …)

Page 22: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

E0 が attref 式の場合の例外

例 : L.append(x) mini-Python 固有の約束 :

• L.append(x) = append(L, x)• L.append は構文としては, expr_kind_attref と

いう種類の式として構文解析されるが,関数呼び出しの関数の位置以外に現れることを許さない

• 関数呼び出しを評価する際にこの場合を特別扱いする ( レジュメ 4.6節 )

Page 23: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

演算子,添え字式,などを関数呼び出しとみなす

例 : E0 + E1

• 実際評価の方法は似ている• E0 を評価   v0

• E1 を評価   v1

• v0 + v1 を計算する ( それほど簡単ではない ) そこでこれを add(E0 , E1) という関数呼び

出しだとみなして評価する add はどこかに (native 関数, Python 関数

として ) 定義する

Page 24: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

文の評価 py_val_t eval_stmt(stmt_t s,

env_t lenv, env_t genv, stack_trace_t bt)

返り値の意味• py_val_continue continue で実行が終了した• py_val_break break で実行が終了した• Python データの表現   return で実行が終了し

た• py_val_next それ以外で (普通に ) 実行が終了した

Page 25: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

文の種類 stmt_kind_expression stmt_kind_assignment stmt_kind_pass stmt_kind_return stmt_kind_break: stmt_kind_continue: stmt_kind_del: stmt_kind_print: stmt_kind_global: stmt_kind_if: stmt_kind_while: stmt_kind_for: stmt_kind_fundef:

Page 26: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

自明な 3 つ pass, break, continue

• py_val_next, py_val_break, py_val_continue を返すだけ

Page 27: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

次に簡単な 2 つ expression

• 式を eval_expr を用いて評価する• py_val_next を返す

return E• E を eval_expr を用いて評価する• それを返す

Page 28: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

「関数呼び出しとみなせる」文たち

print E del E0[E1] E0[E1] = E

Page 29: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

環境を書き換える文 (1)

global x• 局所環境で x が大域変数であるとマーク

(env_set_global) x = E

• E を評価   v• 局所環境で x を v にセット• ただし,局所環境で x が大域変数であると

マークされていれば (env_is_global) 大域環境で x を v にセット

Page 30: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

環境を書き換える文 (2)

def f(x, y, …): S

Python 関数 (mk_py_ifun) を作って,環境に登録• 変数 f への代入と同じ効果

Page 31: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

制御構造 if, while, for

Page 32: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

エラーメッセージの表示 エラー発生ソース位置 簡単なエラーメッセージ スタックトレース

Page 33: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

スタックトレースのインタフェース

stack_trace_t mk_stack_trace() void stack_trace_push(stack_trace_t

bt, char* name, src_pos_t call_site)• bt に,「 name とい関数がソース位置 call_site で呼ばれた」と記録 (push)

void stack_trace_pop(stack_trace_t bt, char* name, src_pos_t call_site)

• bt から頂上のエントリをひとつ除去 (pop) する.それは,「 name とい関数がソース位置 call_site で呼ばれた」というエントリでなくてはならない

void print_stack_trace(stack_trace_t bt)

Page 34: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

まとめ : 作る部品の全体像

eval_expr

eval_stmt

環境 (env_t)

スタックトレース実行時エラー表示

native 関数群

Python で書かれた組み込み関数,演算子,添え字式, del, print に対応した関数群

関数呼び出し

式文 , return 文

各種演算子,組み込み関数

del, print, E[E] = E

Page 35: B 演習 ( 言語処理系演習 ) 第 8 回 評価器

まとめ : 概念として重要だったもの

環境• これがないと変数を含む式・文は評価できない

Python 関数呼び出しの評価方法• 新しい局所環境が作られる• 引数のあたいが局所環境に登録されて渡される

様々な種類の式・文が「関数呼び出しの一種」とみなせる ( 要領よく実装 )• 演算子,添え字,添え字に代入, del, print

文を評価した結果の返り値• py_val_continue, break, next