Upload
aislin
View
74
Download
0
Embed Size (px)
DESCRIPTION
CPS 変換における 型保存の証明に関する研究. 渡邊裕貴 コンピュータ科学専攻 米澤研究室. コンパイラの検証. ソースの 意味論. ソース コード. 意味論が 一致することを 証明. 構文の変換. アセンブリの 意味論. アセンブリ コード. 依存型の型保存コンパイル. プログラムを依存型で型付け 依存型でプログラムの意味論を記述 コンパイル後も型付けが成り立つことを 保証 意味論の一致 Cf. CompCert [Leroy 2006, etc.] 型を保存しない Chlipala 2007 型を意味論の記述に使用しない. - PowerPoint PPT Presentation
Citation preview
CPS 変換における型保存の証明に関する研究渡邊裕貴コンピュータ科学専攻 米澤研究室
コンパイラの検証
構文の変換ソース コード
アセンブリ コード
2
ソースの意味論
アセンブリの意味論
意味論が一致することを証明
依存型の型保存コンパイル1. プログラムを依存型で型付け– 依存型でプログラムの意味論を記述2. コンパイル後も型付けが成り立つことを保証– 意味論の一致
• Cf.– CompCert [Leroy 2006, etc.]
• 型を保存しない– Chlipala 2007
• 型を意味論の記述に使用しない3
本研究では CPS 変換を扱うCPS 変換
クロージャ変換
Hoisting
レジスタ割り当て4
典型的なラムダ計算のコンパイルの流れ
CPS 変換• ラムダ式を CPS に変換する
G.D. Plotkin. “Call-by-name, call-by-value and the lambda-calculus.” 1975
[[x]] = λk. k x[[λx. t]]= λk. k (λx. [[t]])[[t1 t2]] = λk. [[t1]] (λv1. [[t2]] (λv2. v1 v2 k))
5
(Continuation Passing Style)
Plotkin による call-by-value な CPS 変換の定義
CPS 変換における型保存• CPS 変換前の項が型付けされているなら変換後の項も必ず型付けされること
IfΓ ⊢ t : T
thenΓ [[′ ⊢ t]] : T′
for some Γ and′ T′
6
7
依存型の型保存を証明するための課題• 証明の中で項の等価性を示す必要がある– 通常の依存型の定義では条件が不十分
… ⊢ v1 v2 k : ⊥… ⊢ v1 v2 : (T[x ↦ v2] → ⊥) → ⊥… ⊢ k : T[x ↦ t2] → ⊥
⋮
v2 = t2 が必要
Call-by-name な CPS 変換ではこのような問題はない [Barthe et al. 1999]
本研究の貢献• CPS 変換の型保存の証明法の研究– 依存型 → 依存型 + シングルトン型
• シングルトン型を使うことで証明に必要な等価性を導くやり方を示した– 単純型 → 単純型 + シングルトン型
• 型保存を Coq でほぼ証明した– 単純型 → 単純型
• 型保存を Coq で証明した– Two-sorted locally nameless な定式化を初めて使った– 定式化による証明の違いを比較した
8
CPS 変換での型保存単純型 → 単純型9
単純型• 単純型付きラムダ計算の型– 関数• X → Y
– プリミティブ型• Nat, Int, Unit, , …⊥
10
ラムダ計算の定式化• 色々なやり方がある– Named ( 普通の書き方 )
• λx. λy. x z y– De Bruijn index• λ. λ. 1 2 0
– Locally nameless• λ. λ. 1 z 0
11
N.G. de Bruijn. “Lambda calculus notation with nameless dummies, a tool for automatic formula manipulation, with application to the Church-Rosser theorem.” 1972.B. Aydemir, et al. “Engineering formal metatheory.” 2008.
Named + de Bruijn index
変数を名前で区別
変数を番号で区別
置換を扱いやすい
CPS 変換の定式化• ナイーブな定式化では証明が面倒– 変数名の制約を明示的に扱わないといけない
12
[[x]] = λk. k x (k ≠ x)[[λx. t]] = λk. k (λx. [[t]]) (k FV(λ∉ x. t))[[t1 t2]] = λk. [[t1]] (λv1. [[t2]] (λv2. v1 v2 k)) (k FV(∉ t1 t2))
(v1 ≠ k, v1 FV(∉ t2))(v2 ≠ k, v2 ≠ v1)
新しく導入される変数名の重複を避ける制約
Two-Sorted Representation
• 変数名の制約がなくなり証明が楽– 名前だけでなく「′」の有無でも変数を区別
13
[[x]] = λk . ′ k ′ x[[λx. t]]= λk . ′ k (λ′ x. [[t]])[[t1 t2]] = λk . [[′ t1]] (λv1 . [[′ t2]] (λv2 . ′ v1 ′ v2 ′ k))
新しく導入される変数には「′」を付ける
Z. Dargaye and X. Leroy. “Mechanized verification of CPS transformations.” 2007.
CPS 変換の型保存を Coq で証明した( 単純型 → 単純型 )
• Two-sorted & locally nameless な定式化– Two-sorted が型保存の証明に使えることを実証
14
IfΓ ⊢ t : T
then[[Γ]]; Γ [[′ ⊢ t]] : ([[T]] → ) → ⊥ ⊥証明は Γ ⊢ t : T の導出に対する帰納法による
各定式化での証明の比較ラムダ計算の定式化 CPS 変換の定式化 Coq コード行数Named Naïve 505
Named Two-Sorted 382
De Bruijn Index Two-Sorted 235
Locally Nameless Two-Sorted 538
15
Locally nameless では行数が増えているが……• Opening という操作に関する補題が要る• 単純型では項の置換が不要• 置換はシングルトン型や依存型で必要• 置換があると named や de Bruijn は不利
CPS 変換での型保存単純型 → 単純型 + シングルトン型16
シングルトン型• 項の値を直接表す型
17
⊢ (1 + 2) : {3 : Nat}
シングルトン型
D. Aspinall. “Subtyping with singleton types.” 1995.
CPS 変換後の項をシングルトン型で型付けする• 例 : 変数の CPS 変換の型保存
18
( 変換前 ) 3 : Nat⊢
( 変換後 ) λ⊢ k. k 3 : ({3 : Nat} → ) → ⊥ ⊥継続が変数 x を受け取ることをシングルトン型で保証
型保存を Coq でほぼ証明した( 単純型 → 単純型 + シングルトン型 )
• Two-sorted & locally nameless な定式化– 項の置換を扱うので locally nameless が有利
19
IfΓ ⊢ t : T
thenΓ [[′ ⊢ t]] : ({t : [[′ T]]} → ) → ⊥ ⊥
for properly defined Γ and ′ t′
CPS 変換での型保存依存型 → 依存型 + シングルトン型20
依存型• 型の中に項がある
21
⊢ nil : List 0 ⊢ cons : Πn:Nat. String → List n → List (n+1) ⊢ cons 0 “foo” nil : List 1
リストの型 List n はリストの長さを表す項 n を含んでいる
R. Harper, et al. “A framework for defining logics.” 1993.
依存型の型付け規則• 関数適用で、型に含まれる項が置換される
22
⊢ t1 : Πx:T1. T2
⊢ t2 : T1
⊢ t1 t2 : T2[x ↦ t2]
置換を扱うので locally nameless が有利
23
依存型の型保存を証明するための課題• 証明の中で項の等価性を示す必要がある– 通常の依存型の定義では条件が不十分
… ⊢ v1 v2 k : ⊥… ⊢ v1 v2 : (T[x ↦ v2] → ⊥) → ⊥… ⊢ k : T[x ↦ t2] → ⊥
⋮
v2 = t2 が必要
シングルトン型で証明に必要な等価性を導いた⊢ [[t2]] : ({t2 : Nat} → ⊥) → ⊥
⊢ v2 : {t2 : Nat}
v2 = t2
24
継続が受け取る値をシングルトン型で表す
まとめ• コンパイラの正しさの検証の一環として
CPS 変換の型保存の証明法を研究した– 依存型 → 依存型 + シングルトン型
• シングルトン型を使って証明に必要な等価性を導くやり方を示した– 単純型 → 単純型 + シングルトン型
• 型保存を Coq でほぼ証明した– 単純型 → 単純型
• 型保存を Coq で証明した– Two-sorted locally nameless な定式化を初めて使った
25
26
ラムダ計算の定式化• Higher-order abstract syntax (HOAS)– 定式化する言語の変数で定式化される言語の変数を表す
– F. Pfenning and C. Elliot. “Higher-order abstract syntax.” 1988.
• Nominal logic– Alpha-equivalent な項を構文的に等しいとして公理化する
– Andrew M. Pitts. “Nominal logic, a first order theory of names and binding.” 2003.
27
CPS 変換の検証• CPS 変換の依存型の型保存の証明– Call-by-name な CPS 変換
– Gilles Barthe et al. “CPS transformations and applications: The cube and beyond.” 1999.
– 型の中の項を型に変換– Zhong Shao et al. “A type system for certified binaries.” 2005.
28
Certified Compiler
• CompCert– C のサブセットから PowerPC アセンブリへ– http://compcert.inria.fr/
• Chlipala’s compiler– 単純型付きラムダ計算から抽象アセンブリへ
– Adam Chlipala. “A certified type-preserving compiler from lambda calculus to assembly language.” 2007.
29
Coq
• 定理証明支援系– 人間が証明を書くのを対話的フロントエンドで補助する– 証明が正しいかどうかチェックする– http://coq.inria.fr/
30
厳密な証明を書く必要がある
Theorem cps_term_preserves_typing : forall (Cs : sctxt) (T : stype) (t : sterm), sterm_typing Cs t T -> forall Cc : cctxt, cterm_typing (cps_ctxt Cs) Cc (cps_term t) (! ! cps_type T).Proof. induction 1 as [ Cs x T H1 H2 | Cs | Cs l TA TR t H1 IH1 | Cs TA TR tf ta H1 IH1 H2 IH2 ]; intro Cc; simpl.
(* case stt_fvar *) apply ctt_cabs with (l := domain_of_cctxt Cc). intros x1 H3. unfold open_cterm_c; simpl open_cterm_c_n. apply ctt_app with (TA := cps_type T). apply ctt_cfvar; auto_in constructor.
apply ctt_sfvar. apply cps_ctxt_preserves_in, H1.
31
証明の行数Unsorted
namedTwo-sorted
namedTwo-sorted
de Bruijn indexTwo-sorted
loc. namelessDefinition 194 230 160 251
Name lemmas 57 57 0 12
List manipulation
134 12 18 151
Proof of type preservation
120 83 57 124
Total 505 382 235 538
32
証明の行数単純型→単純型 単純型→シングルトン
型( 暫定 )
定義 251 570
変数名に関する補題 12 64
リストに関する補題 151 86
型保存の証明 124 1155
合計 538 1875
33
Continuation Passing Style (CPS)
• 関数は継続を受け取り、継続に結果を渡す• 例 : 整数のインクリメント
λn. λk. k (n + 1)– 整数 n と継続 k を受け取り、 k に n + 1 を渡す– Cf.: λn. n + 1
34
依存型の型保存を証明するための課題• 関数適用の型付けで置換される項が一致しない
35
⊢ λk. [[cons]] (λv1. [[3]] (λv2. v1 v2 k)) : ([[String → List 3 → List (3+1)]] → ⊥) → ⊥
… ⊢ v1 v2 k : ⊥k:[[String → List 3 → List (3+1)]] → ⊥ ⊢ [[cons]] (λv1. [[3]] (λv2. v1 v2 k)) : ⊥⋮
… ⊢ v1 v2 : ([[String → List v2 → List (v2+1)]] → ⊥) → ⊥… ⊢ k : [[String → List 3 → List (3+1)]] → ⊥
v2 = 3 ?
依存型の型付け規則• 関数適用で、型に含まれる項が置換される
36
⊢ cons : Πn:Nat. String → List n → List (n+1) ⊢ 3 : Nat
⊢ cons 3 : String → List 3 → List (3+1)
置換を扱うので locally nameless が有利