lean
import SFLean4.PLF.Maps
import SFLean4.LF.Imp
import SFLean4.LF.IndProp
import SFLean4.PLF.Smallstep
namespace PLF.PE
open Maps
open Imp
open IndProp
open Smallstep《软件基础》(Software Foundations) 卷二:程序语言基础 (PLF)
偏求值与程序特化 (PE: Partial Evaluation)
在前面的章节中,我们学习了常量折叠(Constant Folding),它能对显式常量进行化简(例如将 Y := 3 + 1 简化为 Y := 4)。 但常量折叠无法沿着数据流传播已知的常量信息。例如对于序列:
X := 3; Y := X + 1常规常量折叠并不能直接将其化简为:
X := 3; Y := 4因为在处理到 Y 的赋值时,系统已经遗忘了 X 在此处的静态已知值 3。
偏求值(Partial Evaluation,亦称在线特化 / Program Specialization) 正是这一思想的推广: 当一个程序的部分输入在编译期已知(称为静态数据 (Static Data)),而其余输入未知(称为动态数据 (Dynamic Data))时, 偏求值器在已知数据上“预先执行”程序,展开循环、消除已知分支,从而生成一个更精简、更高效的剩余程序 (Residual Program)。
1. 推广常量折叠:部分状态 (Partial States)
lean
/-- 部分状态:以具象列表 `List (String × Nat)` 记录当前已确定取值的变量及其静态数值 -/
abbrev pe_state := List (String × Nat)
/-- 在部分状态中查找变量的值 -/
def pe_lookup (pe_st : pe_state) (V : String) : Option Nat :=
match pe_st with
| [] => none
| (V', n') :: rest =>
if V == V' then some n'
else pe_lookup rest V
/-- 空部分状态:表示对所有变量的值一无所知 -/
def empty_pe_state : pe_state := []
/-- 列表成员谓词 -/
def In {A : Type} (a : A) : List A → Prop
| [] => False
| b :: m => b = a ∨ In a m
/-- 若在部分状态中查找到某变量,则该变量必然存在于状态列表的键域中 -/
theorem pe_domain : ∀ (pe_st : pe_state) (V : String) (n : Nat),
pe_lookup pe_st V = some n →
In V (pe_st.map Prod.fst) := by
intro pe_st V n h
induction pe_st with
| nil => contradiction
| cons p rest ih =>
obtain ⟨V', n'⟩ := p
dsimp [pe_lookup] at h
split at h
· rename_i heq
have heq' : V = V' := of_decide_eq_true heq
subst heq'
left
rfl
· right
exact ih h
/-- 检验元素是否属于列表的布尔谓词 -/
def inb {A : Type} (eqb : A → A → Bool) (a : A) (l : List A) : Bool :=
match l with
| [] => false
| a' :: l' => eqb a a' || inb eqb a l'
/-- `inb` 与命题列表成员 `In` 的布尔反射定理 -/
theorem inbP : ∀ (A : Type) (eqb : A → A → Bool),
(∀ a1 a2, reflect (a1 = a2) (eqb a1 a2)) →
∀ a l, reflect (In a l) (inb eqb a l) := by
sorry2. 算术表达式的偏求值 (Arithmetic Expressions)
lean
/-- 算术表达式的偏求值函数:结合部分状态折叠已知变量与常量 -/
def pe_aexp (pe_st : pe_state) (a : aexp) : aexp :=
match a with
| aexp.ANum n => aexp.ANum n
| aexp.AId i =>
match pe_lookup pe_st i with
| some n => aexp.ANum n
| none => aexp.AId i
| aexp.APlus a1 a2 =>
match pe_aexp pe_st a1, pe_aexp pe_st a2 with
| aexp.ANum n1, aexp.ANum n2 => aexp.ANum (n1 + n2)
| a1', a2' => aexp.APlus a1' a2'
| aexp.AMinus a1 a2 =>
match pe_aexp pe_st a1, pe_aexp pe_st a2 with
| aexp.ANum n1, aexp.ANum n2 => aexp.ANum (n1 - n2)
| a1', a2' => aexp.AMinus a1' a2'
| aexp.AMult a1 a2 =>
match pe_aexp pe_st a1, pe_aexp pe_st a2 with
| aexp.ANum n1, aexp.ANum n2 => aexp.ANum (n1 * n2)
| a1', a2' => aexp.AMult a1' a2'
theorem test_pe_aexp1 :
pe_aexp ([(X, 3)] : pe_state) (aexp.APlus (aexp.APlus X 1) Y) = aexp.APlus 4 Y := by
rfl
theorem text_pe_aexp2 :
pe_aexp ([(Y, 3)] : pe_state) (aexp.APlus (aexp.APlus X 1) Y) = aexp.APlus (aexp.APlus X 1) 3 := by
rfl
/-- 具体状态与部分状态的一致性:部分状态中记录的变量值必须与全状态完全吻合 -/
def pe_consistent (st : state) (pe_st : pe_state) : Prop :=
∀ V n, some n = pe_lookup pe_st V → st V = n
/-- 弱正确性:一致状态下求值结果不变 -/
theorem pe_aexp_correct_weak : ∀ st pe_st, pe_consistent st pe_st →
∀ a, aeval st a = aeval st (pe_aexp pe_st a) := by
sorry
/-- 将部分状态中的已知赋值叠加覆盖到全域状态上 -/
def pe_update (st : state) (pe_st : pe_state) : state :=
match pe_st with
| [] => st
| (V, n) :: pe_st' => (V !-> n; pe_update st pe_st')
theorem test_pe_update :
pe_update (Y !-> 1) ([(X, 3), (Z, 2)] : pe_state) = (X !-> 3; Z !-> 2; Y !-> 1) := by
rfl
/-- 字符串不相等时布尔判等为假 -/
theorem false_eqb_string : ∀ x y : String, x ≠ y → (x == y) = false := by
intro x y h
simp [h]
/-- `pe_update` 的查找语义正确性 -/
theorem pe_update_correct : ∀ st pe_st V0,
pe_update st pe_st V0 =
match pe_lookup pe_st V0 with
| some n => n
| none => st V0 := by
sorry
/-- 覆盖更新后的状态必然与该部分状态一致 -/
theorem pe_update_consistent : ∀ st pe_st,
pe_consistent (pe_update st pe_st) pe_st := by
sorry
/-- 若原状态已经一致,则叠加覆盖不会产生变化 -/
theorem pe_consistent_update : ∀ st pe_st,
pe_consistent st pe_st → ∀ V, st V = pe_update st pe_st V := by
sorry
/-- 算术表达式偏求值的强正确性定理 -/
theorem pe_aexp_correct : ∀ (pe_st : pe_state) (a : aexp) (st : state),
aeval (pe_update st pe_st) a = aeval st (pe_aexp pe_st a) := by
sorry3. 布尔表达式的偏求值 (Boolean Expressions)
lean
/-- 布尔表达式的偏求值函数 -/
def pe_bexp (pe_st : pe_state) (b : bexp) : bexp :=
match b with
| bexp.BTrue => bexp.BTrue
| bexp.BFalse => bexp.BFalse
| bexp.BEq a1 a2 =>
match pe_aexp pe_st a1, pe_aexp pe_st a2 with
| aexp.ANum n1, aexp.ANum n2 => if n1 == n2 then bexp.BTrue else bexp.BFalse
| a1', a2' => bexp.BEq a1' a2'
| bexp.BNeq a1 a2 =>
match pe_aexp pe_st a1, pe_aexp pe_st a2 with
| aexp.ANum n1, aexp.ANum n2 => if !(n1 == n2) then bexp.BTrue else bexp.BFalse
| a1', a2' => bexp.BNeq a1' a2'
| bexp.BLe a1 a2 =>
match pe_aexp pe_st a1, pe_aexp pe_st a2 with
| aexp.ANum n1, aexp.ANum n2 => if n1 <= n2 then bexp.BTrue else bexp.BFalse
| a1', a2' => bexp.BLe a1' a2'
| bexp.BGt a1 a2 =>
match pe_aexp pe_st a1, pe_aexp pe_st a2 with
| aexp.ANum n1, aexp.ANum n2 => if n1 <= n2 then bexp.BFalse else bexp.BTrue
| a1', a2' => bexp.BGt a1' a2'
| bexp.BNot b1 =>
match pe_bexp pe_st b1 with
| bexp.BTrue => bexp.BFalse
| bexp.BFalse => bexp.BTrue
| b1' => bexp.BNot b1'
| bexp.BAnd b1 b2 =>
match pe_bexp pe_st b1, pe_bexp pe_st b2 with
| bexp.BTrue, bexp.BTrue => bexp.BTrue
| bexp.BTrue, bexp.BFalse => bexp.BFalse
| bexp.BFalse, bexp.BTrue => bexp.BFalse
| bexp.BFalse, bexp.BFalse => bexp.BFalse
| b1', b2' => bexp.BAnd b1' b2'
theorem test_pe_bexp1 :
pe_bexp ([(X, 3)] : pe_state) (bexp.BNot (bexp.BLe X 3)) = bexp.BFalse := by
rfl
theorem test_pe_bexp2 : ∀ b : bexp,
b = bexp.BNot (bexp.BLe X (aexp.APlus X 1)) →
pe_bexp [] b = b := by
intro b hb
subst hb
rfl
/-- 布尔表达式偏求值的正确性定理 -/
theorem pe_bexp_correct : ∀ (pe_st : pe_state) (b : bexp) (st : state),
beval (pe_update st pe_st) b = beval st (pe_bexp pe_st b) := by
sorry4. 无循环命令的偏求值 (Commands Without Loops)
lean
/-- 从部分状态中移除指定变量(使其重新变为动态未知) -/
def pe_remove (pe_st : pe_state) (V : String) : pe_state :=
match pe_st with
| [] => []
| (V', n') :: rest =>
if V == V' then pe_remove rest V
else (V', n') :: pe_remove rest V
theorem pe_remove_correct : ∀ pe_st V V0,
pe_lookup (pe_remove pe_st V) V0 = if V == V0 then none else pe_lookup pe_st V0 := by
sorry
/-- 向部分状态添加或更新一个静态常量赋值 -/
def pe_add (pe_st : pe_state) (V : String) (n : Nat) : pe_state :=
(V, n) :: pe_remove pe_st V
theorem pe_add_correct : ∀ pe_st V n V0,
pe_lookup (pe_add pe_st V n) V0 = if V == V0 then some n else pe_lookup pe_st V0 := by
sorry
theorem pe_update_update_remove : ∀ st pe_st V n,
(V !-> n; pe_update st pe_st) = pe_update (V !-> n; st) (pe_remove pe_st V) := by
sorry
theorem pe_update_update_add : ∀ st pe_st V n,
(V !-> n; pe_update st pe_st) = pe_update st (pe_add pe_st V n) := by
sorry
/-- 检验两个部分状态在某变量处是否存在分歧 -/
def pe_disagree_at (pe_st1 pe_st2 : pe_state) (V : String) : Bool :=
match pe_lookup pe_st1 V, pe_lookup pe_st2 V with
| some x, some y => !(x == y)
| none, none => false
| _, _ => true
theorem pe_disagree_domain : ∀ (pe_st1 pe_st2 : pe_state) (V : String),
true = pe_disagree_at pe_st1 pe_st2 V →
In V (pe_st1.map Prod.fst ++ pe_st2.map Prod.fst) := by
sorry
/-- 列表元素去重辅助函数 -/
def pe_unique (l : List String) : List String :=
match l with
| [] => []
| x :: rest =>
x :: (pe_unique rest).filter (fun y => !(x == y))
theorem pe_unique_correct : ∀ l x,
In x l ↔ In x (pe_unique l) := by
sorry
/-- 计算两个部分状态产生分歧的所有变量列表 -/
def pe_compare (pe_st1 pe_st2 : pe_state) : List String :=
pe_unique ((pe_st1.map Prod.fst ++ pe_st2.map Prod.fst).filter (pe_disagree_at pe_st1 pe_st2))
theorem pe_compare_correct : ∀ pe_st1 pe_st2 V,
pe_lookup pe_st1 V = pe_lookup pe_st2 V ↔
¬ In V (pe_compare pe_st1 pe_st2) := by
sorry
/-- 批量从部分状态中移除一组变量 -/
def pe_removes (pe_st : pe_state) (ids : List String) : pe_state :=
match ids with
| [] => pe_st
| V :: rest => pe_remove (pe_removes pe_st rest) V
theorem pe_removes_correct : ∀ pe_st ids V,
pe_lookup (pe_removes pe_st ids) V =
if inb (· == ·) V ids then none else pe_lookup pe_st V := by
sorry
theorem pe_compare_removes : ∀ pe_st1 pe_st2 V,
pe_lookup (pe_removes pe_st1 (pe_compare pe_st1 pe_st2)) V =
pe_lookup (pe_removes pe_st2 (pe_compare pe_st1 pe_st2)) V := by
sorry
theorem pe_compare_update : ∀ pe_st1 pe_st2 st,
pe_update st (pe_removes pe_st1 (pe_compare pe_st1 pe_st2)) =
pe_update st (pe_removes pe_st2 (pe_compare pe_st1 pe_st2)) := by
sorry
/-- 将分歧变量列表转化为相应的静态赋值命令序列,用于动态分支合并补偿 -/
def assign (pe_st : pe_state) (ids : List String) : com :=
match ids with
| [] => SKIP
| V :: rest =>
match pe_lookup pe_st V with
| some n => (assign pe_st rest ;; (V ::= aexp.ANum n))
| none => assign pe_st rest
/-- 静态赋值补偿命令序列对全域状态的作用效果 -/
def assigned (pe_st : pe_state) (ids : List String) (st : state) : state :=
fun V =>
if inb (· == ·) V ids then
match pe_lookup pe_st V with
| some n => n
| none => st V
else st V
theorem assign_removes : ∀ pe_st ids st,
pe_update st pe_st =
pe_update (assigned pe_st ids st) (pe_removes pe_st ids) := by
sorry
theorem ceval_extensionality : ∀ c st st1 st2,
(st =[ c ]=> st1) → (∀ V, st1 V = st2 V) → (st =[ c ]=> st2) := by
sorry
theorem eval_assign : ∀ pe_st ids st,
st =[ assign pe_st ids ]=> assigned pe_st ids st := by
sorry
/-- 命令偏求值关系:`c / pe_st ==> c' / pe_st'` -/
inductive pe_com : com → pe_state → com → pe_state → Prop where
| PE_Skip : ∀ pe_st,
pe_com SKIP pe_st SKIP pe_st
| PE_AsgnStatic : ∀ pe_st a1 (n1 : Nat) l,
pe_aexp pe_st a1 = aexp.ANum n1 →
pe_com (l ::= a1) pe_st SKIP (pe_add pe_st l n1)
| PE_AsgnDynamic : ∀ pe_st a1 a1' l,
pe_aexp pe_st a1 = a1' →
(∀ n : Nat, a1' ≠ aexp.ANum n) →
pe_com (l ::= a1) pe_st (l ::= a1') (pe_remove pe_st l)
| PE_Seq : ∀ pe_st pe_st' pe_st'' c1 c2 c1' c2',
pe_com c1 pe_st c1' pe_st' →
pe_com c2 pe_st' c2' pe_st'' →
pe_com (c1 ;; c2) pe_st (c1' ;; c2') pe_st''
| PE_IfTrue : ∀ pe_st pe_st' b1 c1 c2 c1',
pe_bexp pe_st b1 = bexp.BTrue →
pe_com c1 pe_st c1' pe_st' →
pe_com (TEST b1 THEN c1 ELSE c2 FI) pe_st c1' pe_st'
| PE_IfFalse : ∀ pe_st pe_st' b1 c1 c2 c2',
pe_bexp pe_st b1 = bexp.BFalse →
pe_com c2 pe_st c2' pe_st' →
pe_com (TEST b1 THEN c1 ELSE c2 FI) pe_st c2' pe_st'
| PE_If : ∀ pe_st pe_st1 pe_st2 b1 c1 c2 c1' c2',
pe_bexp pe_st b1 ≠ bexp.BTrue →
pe_bexp pe_st b1 ≠ bexp.BFalse →
pe_com c1 pe_st c1' pe_st1 →
pe_com c2 pe_st c2' pe_st2 →
pe_com (TEST b1 THEN c1 ELSE c2 FI) pe_st
(TEST pe_bexp pe_st b1
THEN (c1' ;; assign pe_st1 (pe_compare pe_st1 pe_st2))
ELSE (c2' ;; assign pe_st2 (pe_compare pe_st1 pe_st2)) FI)
(pe_removes pe_st1 (pe_compare pe_st1 pe_st2))
theorem pe_example1 :
pe_com (X ::= 3 ;; Y ::= Z * (X + X)) []
(SKIP ;; (Y ::= Z * 6)) ([(X, 3)] : pe_state) := by
sorry
theorem pe_example2 :
pe_com (X ::= 3 ;; TEST (bexp.BLe X 4) THEN X ::= 4 ELSE SKIP FI) []
(SKIP ;; SKIP) ([(X, 4)] : pe_state) := by
sorry
theorem pe_example3 :
pe_com (X ::= 3 ;;
TEST (bexp.BLe Y 4)
THEN (Y ::= 4 ;; TEST (bexp.BEq X Y) THEN Y ::= 999 ELSE SKIP FI)
ELSE SKIP FI) []
(SKIP ;;
TEST (bexp.BLe Y 4)
THEN ((SKIP ;; SKIP) ;; (SKIP ;; (Y ::= 4)))
ELSE (SKIP ;; SKIP) FI)
([(X, 3)] : pe_state) := by
sorry
/-- 偏求值剩余程序的联合大步执行关系 -/
inductive pe_ceval (c' : com) (pe_st' : pe_state) (st : state) (st'' : state) : Prop where
| pe_ceval_intro : ∀ st',
(st =[ c' ]=> st') →
pe_update st' pe_st' = st'' →
pe_ceval c' pe_st' st st''
/-- 完备性定理:原程序在覆盖状态上的执行均可在剩余程序中重现 -/
theorem pe_com_complete :
∀ c pe_st pe_st' c', pe_com c pe_st c' pe_st' →
∀ st st'',
(pe_update st pe_st =[ c ]=> st'') →
pe_ceval c' pe_st' st st'' := by
sorry
/-- 可靠性定理:剩余程序的执行完全忠实于原程序语义 -/
theorem pe_com_sound :
∀ c pe_st pe_st' c', pe_com c pe_st c' pe_st' →
∀ st st'',
pe_ceval c' pe_st' st st'' →
(pe_update st pe_st =[ c ]=> st'') := by
sorry
/-- 主定理:命令偏求值的双向语义保持定理 -/
theorem pe_com_correct :
∀ c pe_st pe_st' c', pe_com c pe_st c' pe_st' →
∀ st st'',
(pe_update st pe_st =[ c ]=> st'') ↔
pe_ceval c' pe_st' st st'' := by
sorry5. 循环语句的偏求值 (Partial Evaluation of Loops)
lean
namespace Loop
/-- 支持循环展开与在线卷起的偏求值关系 -/
inductive pe_com : com → pe_state → com → pe_state → com → Prop where
| PE_Skip : ∀ pe_st,
pe_com SKIP pe_st SKIP pe_st SKIP
| PE_AsgnStatic : ∀ pe_st a1 (n1 : Nat) l,
pe_aexp pe_st a1 = aexp.ANum n1 →
pe_com (l ::= a1) pe_st SKIP (pe_add pe_st l n1) SKIP
| PE_AsgnDynamic : ∀ pe_st a1 a1' l,
pe_aexp pe_st a1 = a1' →
(∀ n : Nat, a1' ≠ aexp.ANum n) →
pe_com (l ::= a1) pe_st (l ::= a1') (pe_remove pe_st l) SKIP
| PE_Seq : ∀ pe_st pe_st' pe_st'' c1 c2 c1' c2' c'',
pe_com c1 pe_st c1' pe_st' SKIP →
pe_com c2 pe_st' c2' pe_st'' c'' →
pe_com (c1 ;; c2) pe_st (c1' ;; c2') pe_st'' c''
| PE_IfTrue : ∀ pe_st pe_st' b1 c1 c2 c1' c'',
pe_bexp pe_st b1 = bexp.BTrue →
pe_com c1 pe_st c1' pe_st' c'' →
pe_com (TEST b1 THEN c1 ELSE c2 FI) pe_st c1' pe_st' c''
| PE_IfFalse : ∀ pe_st pe_st' b1 c1 c2 c2' c'',
pe_bexp pe_st b1 = bexp.BFalse →
pe_com c2 pe_st c2' pe_st' c'' →
pe_com (TEST b1 THEN c1 ELSE c2 FI) pe_st c2' pe_st' c''
| PE_If : ∀ pe_st pe_st1 pe_st2 b1 c1 c2 c1' c2' c'',
pe_bexp pe_st b1 ≠ bexp.BTrue →
pe_bexp pe_st b1 ≠ bexp.BFalse →
pe_com c1 pe_st c1' pe_st1 c'' →
pe_com c2 pe_st c2' pe_st2 c'' →
pe_com (TEST b1 THEN c1 ELSE c2 FI) pe_st
(TEST pe_bexp pe_st b1
THEN (c1' ;; assign pe_st1 (pe_compare pe_st1 pe_st2))
ELSE (c2' ;; assign pe_st2 (pe_compare pe_st1 pe_st2)) FI)
(pe_removes pe_st1 (pe_compare pe_st1 pe_st2))
c''
| PE_WhileFalse : ∀ pe_st b1 c1,
pe_bexp pe_st b1 = bexp.BFalse →
pe_com (WHILE b1 DO c1 END) pe_st SKIP pe_st SKIP
| PE_WhileTrue : ∀ pe_st pe_st' pe_st'' b1 c1 c1' c2' c2'',
pe_bexp pe_st b1 = bexp.BTrue →
pe_com c1 pe_st c1' pe_st' SKIP →
pe_com (WHILE b1 DO c1 END) pe_st' c2' pe_st'' c2'' →
pe_compare pe_st pe_st'' ≠ ([] : List String) →
pe_com (WHILE b1 DO c1 END) pe_st (c1' ;; c2') pe_st'' c2''
| PE_While : ∀ pe_st pe_st' pe_st'' b1 c1 c1' c2' c2'',
pe_bexp pe_st b1 ≠ bexp.BFalse →
pe_bexp pe_st b1 ≠ bexp.BTrue →
pe_com c1 pe_st c1' pe_st' SKIP →
pe_com (WHILE b1 DO c1 END) pe_st' c2' pe_st'' c2'' →
pe_compare pe_st pe_st'' ≠ ([] : List String) →
(c2'' = SKIP ∨ c2'' = (WHILE b1 DO c1 END)) →
pe_com (WHILE b1 DO c1 END) pe_st
(TEST pe_bexp pe_st b1
THEN (c1' ;; c2' ;; assign pe_st'' (pe_compare pe_st pe_st''))
ELSE assign pe_st (pe_compare pe_st pe_st'') FI)
(pe_removes pe_st (pe_compare pe_st pe_st''))
c2''
| PE_WhileFixedEnd : ∀ pe_st b1 c1,
pe_bexp pe_st b1 ≠ bexp.BFalse →
pe_com (WHILE b1 DO c1 END) pe_st SKIP pe_st (WHILE b1 DO c1 END)
| PE_WhileFixedLoop : ∀ pe_st pe_st' pe_st'' b1 c1 c1' c2',
pe_bexp pe_st b1 = bexp.BTrue →
pe_com c1 pe_st c1' pe_st' SKIP →
pe_com (WHILE b1 DO c1 END) pe_st' c2' pe_st'' (WHILE b1 DO c1 END) →
pe_compare pe_st pe_st'' = ([] : List String) →
pe_com (WHILE b1 DO c1 END) pe_st (WHILE bexp.BTrue DO SKIP END) pe_st SKIP
| PE_WhileFixed : ∀ pe_st pe_st' pe_st'' b1 c1 c1' c2',
pe_bexp pe_st b1 ≠ bexp.BFalse →
pe_bexp pe_st b1 ≠ bexp.BTrue →
pe_com c1 pe_st c1' pe_st' SKIP →
pe_com (WHILE b1 DO c1 END) pe_st' c2' pe_st'' (WHILE b1 DO c1 END) →
pe_compare pe_st pe_st'' = ([] : List String) →
pe_com (WHILE b1 DO c1 END) pe_st (WHILE pe_bexp pe_st b1 DO c1' ;; c2' END) pe_st SKIP
/-- 重复平方循环示例程序 -/
def square_loop : com :=
WHILE (bexp.BLe 1 X) DO
(Y ::= Y * Y ;;
X ::= X - 1)
END
theorem pe_loop_example1 :
pe_com square_loop []
(WHILE (bexp.BLe 1 X) DO
((Y ::= Y * Y ;; X ::= X - 1) ;; SKIP)
END) [] SKIP := by
sorry
theorem pe_loop_example2 :
pe_com (X ::= 3 ;; square_loop) []
(SKIP ;;
((Y ::= Y * Y ;; SKIP) ;;
((Y ::= Y * Y ;; SKIP) ;;
((Y ::= Y * Y ;; SKIP) ;; SKIP)))) ([(X, 0)] : pe_state) SKIP := by
sorry
theorem pe_loop_example3 :
pe_com (Z ::= 3 ;; subtract_slowly) []
(SKIP ;;
TEST (bexp.BNeq X 0)
THEN ((SKIP ;; X ::= X - 1) ;;
TEST (bexp.BNeq X 0)
THEN ((SKIP ;; X ::= X - 1) ;;
TEST (bexp.BNeq X 0)
THEN ((SKIP ;; X ::= X - 1) ;;
WHILE (bexp.BNeq X 0) DO (SKIP ;; X ::= X - 1) ;; SKIP END ;;
(SKIP ;; Z ::= 0))
ELSE (SKIP ;; Z ::= 1) FI ;;
SKIP)
ELSE (SKIP ;; Z ::= 2) FI ;;
SKIP)
ELSE (SKIP ;; Z ::= 3) FI) [] SKIP := by
sorry
theorem pe_loop_example4 :
pe_com (X ::= 0 ;;
WHILE (bexp.BLe X 2) DO
X ::= 1 - X
END) []
(SKIP ;; WHILE bexp.BTrue DO SKIP END) ([(X, 0)] : pe_state) SKIP := by
sorry
/-- 带有循环步数计数的求值关系,用于为循环展开归纳提供良基度量 -/
inductive ceval_count : com → state → state → Nat → Prop where
| E'Skip : ∀ st,
ceval_count SKIP st st 0
| E'Asgn : ∀ st a1 n l,
aeval st a1 = n →
ceval_count (l ::= a1) st (l !-> n; st) 0
| E'Seq : ∀ c1 c2 st st' st'' n1 n2,
ceval_count c1 st st' n1 →
ceval_count c2 st' st'' n2 →
ceval_count (c1 ;; c2) st st'' (n1 + n2)
| E'IfTrue : ∀ st st' b1 c1 c2 n,
beval st b1 = true →
ceval_count c1 st st' n →
ceval_count (TEST b1 THEN c1 ELSE c2 FI) st st' n
| E'IfFalse : ∀ st st' b1 c1 c2 n,
beval st b1 = false →
ceval_count c2 st st' n →
ceval_count (TEST b1 THEN c1 ELSE c2 FI) st st' n
| E'WhileFalse : ∀ b1 st c1,
beval st b1 = false →
ceval_count (WHILE b1 DO c1 END) st st 0
| E'WhileTrue : ∀ st st' st'' b1 c1 n1 n2,
beval st b1 = true →
ceval_count c1 st st' n1 →
ceval_count (WHILE b1 DO c1 END) st' st'' n2 →
ceval_count (WHILE b1 DO c1 END) st st'' (Nat.succ (n1 + n2))
theorem ceval_count_complete : ∀ c st st',
(st =[ c ]=> st') → ∃ n, ceval_count c st st' n := by
sorry
theorem ceval_count_sound : ∀ c st st' n,
ceval_count c st st' n → (st =[ c ]=> st') := by
sorry
theorem pe_compare_nil_lookup : ∀ pe_st1 pe_st2,
pe_compare pe_st1 pe_st2 = ([] : List String) →
∀ V, pe_lookup pe_st1 V = pe_lookup pe_st2 V := by
sorry
theorem pe_compare_nil_update : ∀ pe_st1 pe_st2,
pe_compare pe_st1 pe_st2 = ([] : List String) →
∀ st, pe_update st pe_st1 = pe_update st pe_st2 := by
sorry
/-- 带有步数计数的循环偏求值语义关系 -/
inductive pe_ceval_count (c' : com) (pe_st' : pe_state) (c'' : com)
(st : state) (st'' : state) (n : Nat) : Prop where
| pe_ceval_count_intro : ∀ st' n',
(st =[ c' ]=> st') →
ceval_count c'' (pe_update st' pe_st') st'' n' →
n' ≤ n →
pe_ceval_count c' pe_st' c'' st st'' n
theorem pe_ceval_count_le : ∀ c' pe_st' c'' st st'' n n',
n' ≤ n →
pe_ceval_count c' pe_st' c'' st st'' n' →
pe_ceval_count c' pe_st' c'' st st'' n := by
sorry
theorem pe_com_complete :
∀ c pe_st pe_st' c' c'', pe_com c pe_st c' pe_st' c'' →
∀ st st'' n,
ceval_count c (pe_update st pe_st) st'' n →
pe_ceval_count c' pe_st' c'' st st'' n := by
sorry
theorem pe_com_sound :
∀ c pe_st pe_st' c' c'', pe_com c pe_st c' pe_st' c'' →
∀ st st'' n,
pe_ceval_count c' pe_st' c'' st st'' n →
(pe_update st pe_st =[ c ]=> st'') := by
sorry
theorem pe_com_correct :
∀ c pe_st pe_st' c', pe_com c pe_st c' pe_st' SKIP →
∀ st st'',
(pe_update st pe_st =[ c ]=> st'') ↔
(∃ st', (st =[ c' ]=> st') ∧ pe_update st' pe_st' = st'') := by
sorry
end Loop6. 流程图程序的偏求值 (Flowchart Programs)
lean
/-- 基本块 (Basic Block):以连续赋值开始,以条件跳转或无条件跳转结束 -/
inductive block (Label : Type) : Type where
| Goto : Label → block Label
| If : bexp → Label → Label → block Label
| Assign : String → aexp → block Label → block Label
/-- 奇偶检验程序的四状态标签 -/
inductive parity_label : Type where
| entry : parity_label
| loop : parity_label
| body : parity_label
| done : parity_label
deriving Repr, DecidableEq
/-- 循环体基本块 -/
def parity_body : block parity_label :=
block.Assign Y (aexp.AMinus Y 1)
(block.Assign X (aexp.AMinus 1 X)
(block.Goto parity_label.loop))
/-- 基本块求值函数 -/
def keval {L : Type} (st : state) (k : block L) : state × L :=
match k with
| block.Goto l => (st, l)
| block.If b l1 l2 => (st, if beval st b then l1 else l2)
| block.Assign i a k' => keval (i !-> aeval st a; st) k'
theorem keval_example :
keval empty_st parity_body = ((X !-> 1; Y !-> 0; empty_st), parity_label.loop) := by
rfl
/-- 流程图程序:从标签到基本块的映射表 -/
def program (L : Type) : Type := L → Option (block L)
/-- 奇偶检验流程图程序 -/
def parity : program parity_label := fun l =>
match l with
| parity_label.entry => some (block.Assign X 0 (block.Goto parity_label.loop))
| parity_label.loop => some (block.If (bexp.BLe 1 Y) parity_label.body parity_label.done)
| parity_label.body => some parity_body
| parity_label.done => none
/-- 流程图程序的求值归纳关系 -/
inductive peval {L : Type} (p : program L) : state → L → state → L → Prop where
| E_None : ∀ st l,
p l = none →
peval p st l st l
| E_Some : ∀ st l k st' l' st'' l'',
p l = some k →
keval st k = (st', l') →
peval p st' l' st'' l'' →
peval p st l st'' l''
theorem parity_eval : peval parity empty_st parity_label.entry empty_st parity_label.done := by
sorry
/-- 基本块的偏求值转换:将标签提升为 `(pe_state × L)` 组合标签 -/
def pe_block {L : Type} (pe_st : pe_state) (k : block L) : block (pe_state × L) :=
match k with
| block.Goto l => block.Goto (pe_st, l)
| block.If b l1 l2 =>
match pe_bexp pe_st b with
| bexp.BTrue => block.Goto (pe_st, l1)
| bexp.BFalse => block.Goto (pe_st, l2)
| b' => block.If b' (pe_st, l1) (pe_st, l2)
| block.Assign i a k' =>
match pe_aexp pe_st a with
| aexp.ANum n => pe_block (pe_add pe_st i n) k'
| a' => block.Assign i a' (pe_block (pe_remove pe_st i) k')
theorem pe_block_example :
pe_block ([(X, 0)] : pe_state) parity_body =
block.Assign Y (aexp.AMinus Y 1) (block.Goto (([(X, 1)] : pe_state), parity_label.loop)) := by
rfl
/-- 基本块偏求值的正确性定理 -/
theorem pe_block_correct : ∀ (L : Type) st pe_st k st' pe_st' (l' : L),
keval st (pe_block pe_st k) = (st', (pe_st', l')) →
keval (pe_update st pe_st) k = (pe_update st' pe_st', l') := by
sorry
/-- 流程图程序的偏求值特化:全程序标签展开 -/
def pe_program {L : Type} (p : program L) : program (pe_state × L) :=
fun ⟨pe_st, l⟩ => (p l).map (pe_block pe_st)
/-- 偏求值特化后程序的联合求值关系 -/
inductive pe_peval {L : Type} (p : program L)
(st : state) (pe_st : pe_state) (l : L) (st'o : state) (l' : L) : Prop where
| pe_peval_intro : ∀ st' pe_st',
peval (pe_program p) st (pe_st, l) st' (pe_st', l') →
pe_update st' pe_st' = st'o →
pe_peval p st pe_st l st'o l'
/-- 流程图程序偏求值的端到端正确性主定理 -/
theorem pe_program_correct :
∀ (L : Type) (p : program L) st pe_st l st'o l',
peval p (pe_update st pe_st) l st'o l' ↔
pe_peval p st pe_st l st'o l' := by
sorry
end PLF.PE