SlideShare a Scribd company logo
1 of 24
言語処理系入門
第6回:制御構造,例外,継続
2009 年 12 月 4 日(金)
服部 健太
これまでの評価器の構造
 例:
| PrimAppExpr(op,es) ->
let vs = List.map (eval_expr env) es in
PrimOp.apply op vs
 eval_expr が次にどの部分式を評価するかは,構文木の構造によって暗黙的
に決まっていた.
 eval_expr env [[a + (f 5)]] の実行後,次に評価器が何をするのかは文脈に依
存
PrimAppExpr
+ AppExprVarExpr
a VarExpr
f
ValExpr
5
a + (f 5)
2009/12/4 2言語処理系入門 6
命令型言語に特有の制御文
 return, break, continue など
 例:関数の本体中に以下の部分式があるとする
 fn x a -> … a / (if x == 0 then return 0 else x) …
 式の構造を飛び越えて計算を行うには,工夫が必要!
PrimAppExpr
/ IfExprVarExpr
a PrimAppExpr
==
RetnExpr VarExpr
xVarExpr ValExpr ValExpr
この部分式
を評価した
後,どうす
る?
2009/12/4 3言語処理系入門 6
継続( continuation )とは
 残りの計算を表す概念
 プログラムの実行のある時点から最終的な答えを
得るまでの計算
 例:
let x = 2 in
let y = 3 + x * (f x) in
y * y;
 部分式 (f x) に注目したとき,このときの継続
let y = 3 + x * [<(f x) の値 >] in y * y
2009/12/4 4言語処理系入門 6
継続渡しスタイル( CPS )
 継続を明示的に渡す関数のスタイル
 ダイレクトスタイル(通常の形式)
let rec fact n =
if n == 0 then 1
else n * (fact (n – 1));
 継続渡しスタイル
let rec fact n k =
if n == 0 then k 1
else fact (n-1) (fn v -> k (v * n));
fact(n-1) を計算し
た後にする計算
(継続)
2009/12/4 5言語処理系入門 6
末尾呼び出し( tail call )
 処理の最後にくるような関数呼び出し
 関数呼び出しから戻ってきた後は,単に return するこ
とだけ
 例: iter は末尾呼び出しになっている
let rec iter x =
if x == 0 then
    ()
else
    begin print x; iter (x – 1)   end;
 CPS では,関数呼び出しは常に tail call となる
 tail call は goto に変換できる(スタックを消費しない
)
2009/12/4 6言語処理系入門 6
継続渡し評価器
 次に何をするのか ( 継続 ) を評価器の引数として明
示的に与える
 継続渡しスタイルの eval_expr
(*
  * Env.t -> Cont.t -> Syntax.expr -> Value.t
*)
let rec eval_expr env cont e =
match e with …
 継続 cont は,部分式 e を評価した結果を受け取り,最終的
な答えを得るまでの残りの計算.
 トップレベルから eval_expr を呼び出すときには, (もう
何もすることが無いことを意味する)空の継続を渡してや
る
部分式 e を評価し終
えた後に,やるべき
計算
2009/12/4 7言語処理系入門 6
継続の表現
 継続の表現( cont.ml )
 Value.t を受け取って Value.t を返す Ocaml の関数として表
現
type t = Value.t -> Value.t
 実際には’ a   -> ’  b の多相型関数として定義
 空の継続
 もらった値をそのまま返す
let init v -> v
 はじめの一歩 (main.ml)
Syntax.Expr e ->
print_result
(Eval.eval_expr env Cont.init e)
2009/12/4 8言語処理系入門 6
評価器( eval.ml )の抜粋
 値式の場合:
| ValExpr v -> cont (eval_value env v)
 If 式の場合
| IfExpr(e1,e2,e3) ->
eval_expr env (fun v ->
if Value.get_bool v
then eval_expr env cont e2
else eval_expr env cont e3
) e1
 関数適用の場合
| AppExpr(e1,e2) ->
eval_expr env (fun v1 ->
eval_expr env (fun v2 ->
clos_apply cont v1 v2) e2) e1
2009/12/4 9言語処理系入門 6
評価器の処理の流れ
 ρ = {a -> 5;f->Cls(x,{},[[x+x]]}, k = Id とする
E[[a + (f (f 3))]] ρ k
=> E[[a]] ρ (fn v -> E[[(f (f 3))]] ρ (fn v’->k(v+v’)))
=> (fn v -> E[[(f (f 3))]] ρ (fn v’->k(v+v’))) ρ(a)
=> E[[f (f 3)]] ρ (fn v’->k(5+v’)))
=> E[[f]] ρ (fn c->E[[f 3]]ρ(fn v->AppCls(c,v,(fn v’->k(5+v’)))))
=>(fn c->E[[f 3]]ρ(fn v->AppCls(c,v,(fn v’->k(5+v’))))) Cls(x,{},[[x+x]])
=> E[[f 3]]ρ(fn v->AppCls(Cls(x,{},[[x+x]]),v,(fn v’->k(5+v’))))
k‘ = (fn v->AppCls(Cls(x,{},[[x+x]]),v,(fn v’->k(5+v’))))
=> E[[f]]ρ(fn c->E[[3]]ρ (fn v->AppCls(c,v, k’)))
=> … => E[[3]]ρ (fn v->AppCls(Cls(x,{},x+x),v,k’))
=> … => AppCls(Cls(x,{},x+x),3,k’)
=> E[[x+x]]{x->3}k’
ρ‘={x->3}
=> E[[x]]ρ’(fn v->E[[x]]ρ’(fn v’->k’(v+v’)))
=> E[[x]]ρ’(fn v’->k’(3+v’))
=> … =>(fn v->AppCls(Cls(x,{},[[x+x]]),v,(fn v’->k(5+v’)))) (3+3)
=> AppCls(Cls(x,{},[[x+x]]),6,(fn v’->k(5+v’)))
=> E[[x+x]]{x->6} (fn v’->k(5+v’))
=> …=>k(5+12)=>Id17=>17
2009/12/4 10言語処理系入門 6
表示意味論
)))((]][[.(]][[]][[
)}{]][[.(]][[
)}{]][[.(]][[
]][[
)]][[|]][[.(]][[
]][[
))((]][[
)(]][[
.{},
2121
21
21
321
321
initinit
κρλρκρ
ρλκκρ
κρλρ
κρ
κρκρλρ
κρ
ρκκρ
κκρ
λκρ
fEfEEE
kvxEkvEx
vxEvE
EEx
EEbbE
EEE
xx
cc
vv
ΕΕΕ
ΕΕ
ΕΕ
Ε
ΕΕΕ
Ε
Ε
Ε
=
=>−
=
=
→=
=
=
==


fn
inlet
elsethenif
      
      
eval_expr を数学的に
表記したようなもの
2009/12/4 11言語処理系入門 6
例外処理
 例外の捕捉
 E ::= try E1 handle x in E2
 例外発生
 E ::= raise E1
 プログラム例:
let f x y =
if y == 0 then   raise @Divided_zero
  else x / y
in
try f 10 0 handle x in
  case x of @Divided_zero -> 0
           | * -> raise x
2009/12/4 12言語処理系入門 6
例外ハンドラの管理
 例外ハンドラ管理モジュール( exn.ml )
 例外ハンドラは,単なる継続として表現
type t = (Value.t, Value.t) Cont.t
 デフォルトのハンドラ定義
 Ocaml の例外を投げてトップレベルに戻る
let handler:t ref =
ref (fun v ->
raise (Unhandled_exception_error v))
 ハンドラの設定
let set_handler h = handler := h
 ハンドラの取得
let get_handler() = !handler
2009/12/4 13言語処理系入門 6
例外処理の実装
let rec eval_expr env cont e = match e with
…
| TryExpr(e1,s,e2) ->
let old_h = Exn.get_handler() in
let new_h exn_v =
Exn.set_handler old_h;
eval_expr
(Env.extend env [s,Value.DirectObj exn_v])
cont e2
in
Exn.set_handler new_h;
eval_expr env
(fun v -> Exn.set_handler old_h; cont v) e1
| RaiseExpr e1 ->
    eval_expr env (fun v -> (Exn.get_handler()) v)
e1
元のハンドラ
をセットし直
す
新しいハンド
ラをセットす
る
新しい
ハンドラ
定義
2009/12/4 14言語処理系入門 6
一級継続( first class
continuation )
 プログラマに,継続を直接操作する手段を提供する
 letcc 構文
 E ::= letcc k in E1| throw E1 with E2
 現在の継続( letcc を取り囲んでいる文脈)を k に束縛し
, E1 を実行する
 例:
# 3 + (letcc k in 2 + (throw k with 5) * 1);
==> 8
 変数 k には fn x->3+x という継続を表す関数が束縛され
る
 継続に値を渡すと(現在の継続を捨てて)その継続を実行
する
 呼び出し元には戻らない
ジャンプする
2009/12/4 15言語処理系入門 6
一級継続の応用
 深い関数呼び出しからの脱出
let prod ls =
letcc k in
let rec iter result ls_ =
case ls_ of
@Nil -> result
| @Cons x ->
if x.car == 0 then throw k with 0
else iter (result * x.car) x.cdr
in iter 1 ls
2009/12/4 16言語処理系入門 6
letcc による break, continue の実現
 Syntax Sugar として実装できる
 while 式
[[while E1 do E2]]⇒
  letcc break in
   let rec loop x =
      if x then begin
     letcc continue in [[E2]]; loop [[E1]]
    end
    in loop [[E1]]
 break/continue
[[break]] ⇒ throw break with ()
[[continue]] ⇒ throw continue with ()
2009/12/4 17言語処理系入門 6
letcc の実装
 表示意味論
 素朴な letcc の実装
| LetccExpr(x,e1) -> eval_expr (
Env.extend env
[x,Value.DirectObj(Value.Cont cont)]
) cont e1
| ThrowExpr(e1,e2) -> eval_expr env (
fun k -> eval_expr env
(fun v -> (Value.get_cont k) v) e2
) e1
))(.]][[.(]][[]][[
}{]][[]][[
2121 vkvEkEEE
xEEx
λρλρκρ
κκρκρ
ΕΕΕ
ΕΕ
=
=
 
 
withthrow
inletcc 
2009/12/4 18言語処理系入門 6
例外を考慮に入れた letcc の実装
 try ブロック中で継続により脱出した場合,例外ハンドラが残ってしま
う
# letcc k in try k 0 handle c in c;
==> 0
# raise 10;
==> 10???
 逆に,継続によって try ブロック内に突入した場合,例外ハンドラがセット
されない
 正しい実装
| LetccExpr(x,e1) ->
     let h = Exn.get_handler() in
  eval_expr (
Env.extend env
[s,Value.DirectObj(Value.Cont
              (fun v -> Exn.set_handler h;
cont v))]
) cont e1
継続が呼ばれたら
,元のハンドラを
セットし直す
2009/12/4 19言語処理系入門 6
限定継続( delimited
continuation )
 継続に区切りを付け,複数の継続を関数のよ
うに合成できるようにしたもの.
 shift k in E
 現在の継続を捕捉して E を評価.その後,現在
の継続を捨てて , 一番最近の reset まで戻る
 reset E
 継続の仕切り直し
init))}((.{]][[]][[ κκλρκρ vkkvxEEx ΕΕ = inshift
)]][[(]][[ initκρκκρ EE ΕΕ = reset
2009/12/4 20言語処理系入門 6
shift/reset の実行例
# 1 + (reset 3);
==> 4
# 1 + (reset (2 * (shift k in 4)));
==> 5
# 1 + (reset (2 * (shift k in k 4)));
==> 9
# 1 + (reset (2 * (shift k in k (k 4))));
==> 17
2009/12/4 21言語処理系入門 6
shift/reset による並行プロセスの実装
let ready_queue = Queue.new();
let rec dispatch _ =
if !ready_queue.is_empty() then ready_queue.get() ()
and yield _ =
shift k in begin
ready_queue.put
(fn -> begin k (); dispatch() end);
dispatch()
end
and spawn ?proc = begin
ready_queue.put
(fn -> begin reset proc; dispatch() end);
yield ()
end;
2009/12/4 22言語処理系入門 6
演習問題
 今週のサンプルプログラムを動かしてみよ
 foreach/yield を追加してみよ.
 try/handle/raise を一級継続を用いて syntax
sugar として実現できるか?
2009/12/4 言語処理系入門 6 23
次回予定
 日時:
 2009 年 12 月 11 日(金) 10 : 30 - 12 : 00
 場所:
 LB2 3F/C1
 内容:
 型検査,型推論,多相型
2009/12/4 24言語処理系入門 6

More Related Content

What's hot

JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
F#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングF#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングsatoshimurakumo
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミングOuka Yuka
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたってTsuyoshi Matsudate
 
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けープログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けーTanUkkii
 
Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説JPCERT Coordination Center
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
私を SKI に連れてって
私を SKI に連れてって私を SKI に連れてって
私を SKI に連れてってSusisu
 
Python勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージPython勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージ理 小林
 
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPAkira Takahashi
 
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpSwift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpTomohiro Kumagai
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたってTsuyoshi Matsudate
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Ransui Iso
 

What's hot (20)

C言語講習会3
C言語講習会3C言語講習会3
C言語講習会3
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
F#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングF#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミング
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けープログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
 
Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
ALPSチュートリアル(6) Matplotlib入門
ALPSチュートリアル(6) Matplotlib入門ALPSチュートリアル(6) Matplotlib入門
ALPSチュートリアル(6) Matplotlib入門
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
私を SKI に連れてって
私を SKI に連れてって私を SKI に連れてって
私を SKI に連れてって
 
C言語講習会4
C言語講習会4C言語講習会4
C言語講習会4
 
Python勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージPython勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージ
 
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JP
 
Haskell超入門 Part.1
Haskell超入門 Part.1Haskell超入門 Part.1
Haskell超入門 Part.1
 
Sml#探検隊
Sml#探検隊Sml#探検隊
Sml#探検隊
 
Lisp study
Lisp studyLisp study
Lisp study
 
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpSwift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
 

Viewers also liked

Bemutatkozás jó
Bemutatkozás jóBemutatkozás jó
Bemutatkozás jóBia3
 
言語処理系入門€9
言語処理系入門€9言語処理系入門€9
言語処理系入門€9Kenta Hattori
 
Ppt kaakko135° kauppatie 4.4.2012
Ppt kaakko135° kauppatie 4.4.2012Ppt kaakko135° kauppatie 4.4.2012
Ppt kaakko135° kauppatie 4.4.2012hyvantuulenrannikko
 
корпоративная политика зарождение
корпоративная политика   зарождениекорпоративная политика   зарождение
корпоративная политика зарождениеVasy Ivanov
 
言語処理系入門€7
言語処理系入門€7言語処理系入門€7
言語処理系入門€7Kenta Hattori
 
Ce platforma de blog să alegi?
Ce platforma de blog să alegi?Ce platforma de blog să alegi?
Ce platforma de blog să alegi?Didi Kasa
 
取り残されたIt未開の地
取り残されたIt未開の地取り残されたIt未開の地
取り残されたIt未開の地Kenta Hattori
 
Latihan geografi tingkatan 1
Latihan geografi tingkatan 1Latihan geografi tingkatan 1
Latihan geografi tingkatan 1Zubaidah Halim
 
Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...
Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...
Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...Didi Kasa
 

Viewers also liked (10)

Bemutatkozás jó
Bemutatkozás jóBemutatkozás jó
Bemutatkozás jó
 
言語処理系入門€9
言語処理系入門€9言語処理系入門€9
言語処理系入門€9
 
Ppt kaakko135° kauppatie 4.4.2012
Ppt kaakko135° kauppatie 4.4.2012Ppt kaakko135° kauppatie 4.4.2012
Ppt kaakko135° kauppatie 4.4.2012
 
корпоративная политика зарождение
корпоративная политика   зарождениекорпоративная политика   зарождение
корпоративная политика зарождение
 
言語処理系入門€7
言語処理系入門€7言語処理系入門€7
言語処理系入門€7
 
Ce platforma de blog să alegi?
Ce platforma de blog să alegi?Ce platforma de blog să alegi?
Ce platforma de blog să alegi?
 
取り残されたIt未開の地
取り残されたIt未開の地取り残されたIt未開の地
取り残されたIt未開の地
 
Latihan geografi tingkatan 1
Latihan geografi tingkatan 1Latihan geografi tingkatan 1
Latihan geografi tingkatan 1
 
Cubism
CubismCubism
Cubism
 
Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...
Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...
Leslie Cabarga -- Logo, Font & Lettering Bible: A Comprehensive Guide to the ...
 

Similar to 言語処理系入門€6

言語処理系入門3
言語処理系入門3言語処理系入門3
言語処理系入門3Kenta Hattori
 
言語処理系入門€8
言語処理系入門€8言語処理系入門€8
言語処理系入門€8Kenta Hattori
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話bleis tift
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Ransui Iso
 
「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04Minoru Chikamune
 
モナドをつくろう
モナドをつくろうモナドをつくろう
モナドをつくろうdico_leque
 
Excel vba
Excel vbaExcel vba
Excel vbakeki3
 
初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)Masahiro Hayashi
 
言語処理系入門€10
言語処理系入門€10言語処理系入門€10
言語処理系入門€10Kenta Hattori
 
初めてのHaskell (表)
初めてのHaskell (表)初めてのHaskell (表)
初めてのHaskell (表)karky7
 
プログラミング言語Scala
プログラミング言語Scalaプログラミング言語Scala
プログラミング言語ScalaTanUkkii
 
2013computer s1
2013computer s12013computer s1
2013computer s1munich1502
 
Swift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftSwift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftTomohiro Kumagai
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2Masao Kato
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座bleis tift
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPIDaisuke Igarashi
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)Masahiro Hayashi
 

Similar to 言語処理系入門€6 (20)

言語処理系入門3
言語処理系入門3言語処理系入門3
言語処理系入門3
 
言語処理系入門€8
言語処理系入門€8言語処理系入門€8
言語処理系入門€8
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
 
pecl-AOPの紹介
pecl-AOPの紹介pecl-AOPの紹介
pecl-AOPの紹介
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
 
「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04
 
モナドをつくろう
モナドをつくろうモナドをつくろう
モナドをつくろう
 
講座C入門
講座C入門講座C入門
講座C入門
 
Excel vba
Excel vbaExcel vba
Excel vba
 
初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)
 
言語処理系入門€10
言語処理系入門€10言語処理系入門€10
言語処理系入門€10
 
初めてのHaskell (表)
初めてのHaskell (表)初めてのHaskell (表)
初めてのHaskell (表)
 
Introduction Xtend
Introduction XtendIntroduction Xtend
Introduction Xtend
 
プログラミング言語Scala
プログラミング言語Scalaプログラミング言語Scala
プログラミング言語Scala
 
2013computer s1
2013computer s12013computer s1
2013computer s1
 
Swift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftSwift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswift
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPI
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)
 

More from Kenta Hattori

オブジェクト指向入門2
オブジェクト指向入門2オブジェクト指向入門2
オブジェクト指向入門2Kenta Hattori
 
オブジェクト指向入門1
オブジェクト指向入門1オブジェクト指向入門1
オブジェクト指向入門1Kenta Hattori
 
オブジェクト指向入門10
オブジェクト指向入門10オブジェクト指向入門10
オブジェクト指向入門10Kenta Hattori
 
オブジェクト指向入門9
オブジェクト指向入門9オブジェクト指向入門9
オブジェクト指向入門9Kenta Hattori
 
オブジェクト指向入門8
オブジェクト指向入門8オブジェクト指向入門8
オブジェクト指向入門8Kenta Hattori
 
オブジェクト指向入門7
オブジェクト指向入門7オブジェクト指向入門7
オブジェクト指向入門7Kenta Hattori
 
オブジェクト指向入門6
オブジェクト指向入門6オブジェクト指向入門6
オブジェクト指向入門6Kenta Hattori
 
オブジェクト指向入門5
オブジェクト指向入門5オブジェクト指向入門5
オブジェクト指向入門5Kenta Hattori
 
オブジェクト指向入門4
オブジェクト指向入門4オブジェクト指向入門4
オブジェクト指向入門4Kenta Hattori
 
オブジェクト指向入門3
オブジェクト指向入門3オブジェクト指向入門3
オブジェクト指向入門3Kenta Hattori
 
ソフトウェア・テスト入門2
ソフトウェア・テスト入門2ソフトウェア・テスト入門2
ソフトウェア・テスト入門2Kenta Hattori
 
ソフトウェア・テスト入門1
ソフトウェア・テスト入門1ソフトウェア・テスト入門1
ソフトウェア・テスト入門1Kenta Hattori
 
ソフトウェア・テスト入門8
ソフトウェア・テスト入門8ソフトウェア・テスト入門8
ソフトウェア・テスト入門8Kenta Hattori
 
ソフトウェア・テスト入門7
ソフトウェア・テスト入門7ソフトウェア・テスト入門7
ソフトウェア・テスト入門7Kenta Hattori
 
ソフトウェア・テスト入門6
ソフトウェア・テスト入門6ソフトウェア・テスト入門6
ソフトウェア・テスト入門6Kenta Hattori
 
ソフトウェア・テスト入門5
ソフトウェア・テスト入門5ソフトウェア・テスト入門5
ソフトウェア・テスト入門5Kenta Hattori
 
ソフトウェア・テスト入門4
ソフトウェア・テスト入門4ソフトウェア・テスト入門4
ソフトウェア・テスト入門4Kenta Hattori
 
ソフトウェア・テスト入門3
ソフトウェア・テスト入門3ソフトウェア・テスト入門3
ソフトウェア・テスト入門3Kenta Hattori
 
アルゴリズムとデータ構造15
アルゴリズムとデータ構造15アルゴリズムとデータ構造15
アルゴリズムとデータ構造15Kenta Hattori
 
アルゴリズムとデータ構造14
アルゴリズムとデータ構造14アルゴリズムとデータ構造14
アルゴリズムとデータ構造14Kenta Hattori
 

More from Kenta Hattori (20)

オブジェクト指向入門2
オブジェクト指向入門2オブジェクト指向入門2
オブジェクト指向入門2
 
オブジェクト指向入門1
オブジェクト指向入門1オブジェクト指向入門1
オブジェクト指向入門1
 
オブジェクト指向入門10
オブジェクト指向入門10オブジェクト指向入門10
オブジェクト指向入門10
 
オブジェクト指向入門9
オブジェクト指向入門9オブジェクト指向入門9
オブジェクト指向入門9
 
オブジェクト指向入門8
オブジェクト指向入門8オブジェクト指向入門8
オブジェクト指向入門8
 
オブジェクト指向入門7
オブジェクト指向入門7オブジェクト指向入門7
オブジェクト指向入門7
 
オブジェクト指向入門6
オブジェクト指向入門6オブジェクト指向入門6
オブジェクト指向入門6
 
オブジェクト指向入門5
オブジェクト指向入門5オブジェクト指向入門5
オブジェクト指向入門5
 
オブジェクト指向入門4
オブジェクト指向入門4オブジェクト指向入門4
オブジェクト指向入門4
 
オブジェクト指向入門3
オブジェクト指向入門3オブジェクト指向入門3
オブジェクト指向入門3
 
ソフトウェア・テスト入門2
ソフトウェア・テスト入門2ソフトウェア・テスト入門2
ソフトウェア・テスト入門2
 
ソフトウェア・テスト入門1
ソフトウェア・テスト入門1ソフトウェア・テスト入門1
ソフトウェア・テスト入門1
 
ソフトウェア・テスト入門8
ソフトウェア・テスト入門8ソフトウェア・テスト入門8
ソフトウェア・テスト入門8
 
ソフトウェア・テスト入門7
ソフトウェア・テスト入門7ソフトウェア・テスト入門7
ソフトウェア・テスト入門7
 
ソフトウェア・テスト入門6
ソフトウェア・テスト入門6ソフトウェア・テスト入門6
ソフトウェア・テスト入門6
 
ソフトウェア・テスト入門5
ソフトウェア・テスト入門5ソフトウェア・テスト入門5
ソフトウェア・テスト入門5
 
ソフトウェア・テスト入門4
ソフトウェア・テスト入門4ソフトウェア・テスト入門4
ソフトウェア・テスト入門4
 
ソフトウェア・テスト入門3
ソフトウェア・テスト入門3ソフトウェア・テスト入門3
ソフトウェア・テスト入門3
 
アルゴリズムとデータ構造15
アルゴリズムとデータ構造15アルゴリズムとデータ構造15
アルゴリズムとデータ構造15
 
アルゴリズムとデータ構造14
アルゴリズムとデータ構造14アルゴリズムとデータ構造14
アルゴリズムとデータ構造14
 

言語処理系入門€6

  • 2. これまでの評価器の構造  例: | PrimAppExpr(op,es) -> let vs = List.map (eval_expr env) es in PrimOp.apply op vs  eval_expr が次にどの部分式を評価するかは,構文木の構造によって暗黙的 に決まっていた.  eval_expr env [[a + (f 5)]] の実行後,次に評価器が何をするのかは文脈に依 存 PrimAppExpr + AppExprVarExpr a VarExpr f ValExpr 5 a + (f 5) 2009/12/4 2言語処理系入門 6
  • 3. 命令型言語に特有の制御文  return, break, continue など  例:関数の本体中に以下の部分式があるとする  fn x a -> … a / (if x == 0 then return 0 else x) …  式の構造を飛び越えて計算を行うには,工夫が必要! PrimAppExpr / IfExprVarExpr a PrimAppExpr == RetnExpr VarExpr xVarExpr ValExpr ValExpr この部分式 を評価した 後,どうす る? 2009/12/4 3言語処理系入門 6
  • 4. 継続( continuation )とは  残りの計算を表す概念  プログラムの実行のある時点から最終的な答えを 得るまでの計算  例: let x = 2 in let y = 3 + x * (f x) in y * y;  部分式 (f x) に注目したとき,このときの継続 let y = 3 + x * [<(f x) の値 >] in y * y 2009/12/4 4言語処理系入門 6
  • 5. 継続渡しスタイル( CPS )  継続を明示的に渡す関数のスタイル  ダイレクトスタイル(通常の形式) let rec fact n = if n == 0 then 1 else n * (fact (n – 1));  継続渡しスタイル let rec fact n k = if n == 0 then k 1 else fact (n-1) (fn v -> k (v * n)); fact(n-1) を計算し た後にする計算 (継続) 2009/12/4 5言語処理系入門 6
  • 6. 末尾呼び出し( tail call )  処理の最後にくるような関数呼び出し  関数呼び出しから戻ってきた後は,単に return するこ とだけ  例: iter は末尾呼び出しになっている let rec iter x = if x == 0 then     () else     begin print x; iter (x – 1)   end;  CPS では,関数呼び出しは常に tail call となる  tail call は goto に変換できる(スタックを消費しない ) 2009/12/4 6言語処理系入門 6
  • 7. 継続渡し評価器  次に何をするのか ( 継続 ) を評価器の引数として明 示的に与える  継続渡しスタイルの eval_expr (*   * Env.t -> Cont.t -> Syntax.expr -> Value.t *) let rec eval_expr env cont e = match e with …  継続 cont は,部分式 e を評価した結果を受け取り,最終的 な答えを得るまでの残りの計算.  トップレベルから eval_expr を呼び出すときには, (もう 何もすることが無いことを意味する)空の継続を渡してや る 部分式 e を評価し終 えた後に,やるべき 計算 2009/12/4 7言語処理系入門 6
  • 8. 継続の表現  継続の表現( cont.ml )  Value.t を受け取って Value.t を返す Ocaml の関数として表 現 type t = Value.t -> Value.t  実際には’ a   -> ’  b の多相型関数として定義  空の継続  もらった値をそのまま返す let init v -> v  はじめの一歩 (main.ml) Syntax.Expr e -> print_result (Eval.eval_expr env Cont.init e) 2009/12/4 8言語処理系入門 6
  • 9. 評価器( eval.ml )の抜粋  値式の場合: | ValExpr v -> cont (eval_value env v)  If 式の場合 | IfExpr(e1,e2,e3) -> eval_expr env (fun v -> if Value.get_bool v then eval_expr env cont e2 else eval_expr env cont e3 ) e1  関数適用の場合 | AppExpr(e1,e2) -> eval_expr env (fun v1 -> eval_expr env (fun v2 -> clos_apply cont v1 v2) e2) e1 2009/12/4 9言語処理系入門 6
  • 10. 評価器の処理の流れ  ρ = {a -> 5;f->Cls(x,{},[[x+x]]}, k = Id とする E[[a + (f (f 3))]] ρ k => E[[a]] ρ (fn v -> E[[(f (f 3))]] ρ (fn v’->k(v+v’))) => (fn v -> E[[(f (f 3))]] ρ (fn v’->k(v+v’))) ρ(a) => E[[f (f 3)]] ρ (fn v’->k(5+v’))) => E[[f]] ρ (fn c->E[[f 3]]ρ(fn v->AppCls(c,v,(fn v’->k(5+v’))))) =>(fn c->E[[f 3]]ρ(fn v->AppCls(c,v,(fn v’->k(5+v’))))) Cls(x,{},[[x+x]]) => E[[f 3]]ρ(fn v->AppCls(Cls(x,{},[[x+x]]),v,(fn v’->k(5+v’)))) k‘ = (fn v->AppCls(Cls(x,{},[[x+x]]),v,(fn v’->k(5+v’)))) => E[[f]]ρ(fn c->E[[3]]ρ (fn v->AppCls(c,v, k’))) => … => E[[3]]ρ (fn v->AppCls(Cls(x,{},x+x),v,k’)) => … => AppCls(Cls(x,{},x+x),3,k’) => E[[x+x]]{x->3}k’ ρ‘={x->3} => E[[x]]ρ’(fn v->E[[x]]ρ’(fn v’->k’(v+v’))) => E[[x]]ρ’(fn v’->k’(3+v’)) => … =>(fn v->AppCls(Cls(x,{},[[x+x]]),v,(fn v’->k(5+v’)))) (3+3) => AppCls(Cls(x,{},[[x+x]]),6,(fn v’->k(5+v’))) => E[[x+x]]{x->6} (fn v’->k(5+v’)) => …=>k(5+12)=>Id17=>17 2009/12/4 10言語処理系入門 6
  • 12. 例外処理  例外の捕捉  E ::= try E1 handle x in E2  例外発生  E ::= raise E1  プログラム例: let f x y = if y == 0 then   raise @Divided_zero   else x / y in try f 10 0 handle x in   case x of @Divided_zero -> 0            | * -> raise x 2009/12/4 12言語処理系入門 6
  • 13. 例外ハンドラの管理  例外ハンドラ管理モジュール( exn.ml )  例外ハンドラは,単なる継続として表現 type t = (Value.t, Value.t) Cont.t  デフォルトのハンドラ定義  Ocaml の例外を投げてトップレベルに戻る let handler:t ref = ref (fun v -> raise (Unhandled_exception_error v))  ハンドラの設定 let set_handler h = handler := h  ハンドラの取得 let get_handler() = !handler 2009/12/4 13言語処理系入門 6
  • 14. 例外処理の実装 let rec eval_expr env cont e = match e with … | TryExpr(e1,s,e2) -> let old_h = Exn.get_handler() in let new_h exn_v = Exn.set_handler old_h; eval_expr (Env.extend env [s,Value.DirectObj exn_v]) cont e2 in Exn.set_handler new_h; eval_expr env (fun v -> Exn.set_handler old_h; cont v) e1 | RaiseExpr e1 ->     eval_expr env (fun v -> (Exn.get_handler()) v) e1 元のハンドラ をセットし直 す 新しいハンド ラをセットす る 新しい ハンドラ 定義 2009/12/4 14言語処理系入門 6
  • 15. 一級継続( first class continuation )  プログラマに,継続を直接操作する手段を提供する  letcc 構文  E ::= letcc k in E1| throw E1 with E2  現在の継続( letcc を取り囲んでいる文脈)を k に束縛し , E1 を実行する  例: # 3 + (letcc k in 2 + (throw k with 5) * 1); ==> 8  変数 k には fn x->3+x という継続を表す関数が束縛され る  継続に値を渡すと(現在の継続を捨てて)その継続を実行 する  呼び出し元には戻らない ジャンプする 2009/12/4 15言語処理系入門 6
  • 16. 一級継続の応用  深い関数呼び出しからの脱出 let prod ls = letcc k in let rec iter result ls_ = case ls_ of @Nil -> result | @Cons x -> if x.car == 0 then throw k with 0 else iter (result * x.car) x.cdr in iter 1 ls 2009/12/4 16言語処理系入門 6
  • 17. letcc による break, continue の実現  Syntax Sugar として実装できる  while 式 [[while E1 do E2]]⇒   letcc break in    let rec loop x =       if x then begin      letcc continue in [[E2]]; loop [[E1]]     end     in loop [[E1]]  break/continue [[break]] ⇒ throw break with () [[continue]] ⇒ throw continue with () 2009/12/4 17言語処理系入門 6
  • 18. letcc の実装  表示意味論  素朴な letcc の実装 | LetccExpr(x,e1) -> eval_expr ( Env.extend env [x,Value.DirectObj(Value.Cont cont)] ) cont e1 | ThrowExpr(e1,e2) -> eval_expr env ( fun k -> eval_expr env (fun v -> (Value.get_cont k) v) e2 ) e1 ))(.]][[.(]][[]][[ }{]][[]][[ 2121 vkvEkEEE xEEx λρλρκρ κκρκρ ΕΕΕ ΕΕ = =     withthrow inletcc  2009/12/4 18言語処理系入門 6
  • 19. 例外を考慮に入れた letcc の実装  try ブロック中で継続により脱出した場合,例外ハンドラが残ってしま う # letcc k in try k 0 handle c in c; ==> 0 # raise 10; ==> 10???  逆に,継続によって try ブロック内に突入した場合,例外ハンドラがセット されない  正しい実装 | LetccExpr(x,e1) ->      let h = Exn.get_handler() in   eval_expr ( Env.extend env [s,Value.DirectObj(Value.Cont               (fun v -> Exn.set_handler h; cont v))] ) cont e1 継続が呼ばれたら ,元のハンドラを セットし直す 2009/12/4 19言語処理系入門 6
  • 20. 限定継続( delimited continuation )  継続に区切りを付け,複数の継続を関数のよ うに合成できるようにしたもの.  shift k in E  現在の継続を捕捉して E を評価.その後,現在 の継続を捨てて , 一番最近の reset まで戻る  reset E  継続の仕切り直し init))}((.{]][[]][[ κκλρκρ vkkvxEEx ΕΕ = inshift )]][[(]][[ initκρκκρ EE ΕΕ = reset 2009/12/4 20言語処理系入門 6
  • 21. shift/reset の実行例 # 1 + (reset 3); ==> 4 # 1 + (reset (2 * (shift k in 4))); ==> 5 # 1 + (reset (2 * (shift k in k 4))); ==> 9 # 1 + (reset (2 * (shift k in k (k 4)))); ==> 17 2009/12/4 21言語処理系入門 6
  • 22. shift/reset による並行プロセスの実装 let ready_queue = Queue.new(); let rec dispatch _ = if !ready_queue.is_empty() then ready_queue.get() () and yield _ = shift k in begin ready_queue.put (fn -> begin k (); dispatch() end); dispatch() end and spawn ?proc = begin ready_queue.put (fn -> begin reset proc; dispatch() end); yield () end; 2009/12/4 22言語処理系入門 6
  • 23. 演習問題  今週のサンプルプログラムを動かしてみよ  foreach/yield を追加してみよ.  try/handle/raise を一級継続を用いて syntax sugar として実現できるか? 2009/12/4 言語処理系入門 6 23
  • 24. 次回予定  日時:  2009 年 12 月 11 日(金) 10 : 30 - 12 : 00  場所:  LB2 3F/C1  内容:  型検査,型推論,多相型 2009/12/4 24言語処理系入門 6