# Theory Optimizer

```section "Correctness of an optimizer"

theory Optimizer
imports Lambda DenotEqualitiesFSet
begin

fun is_value :: "exp ⇒ bool" where
"is_value (ENat n) = True" |
"is_value (ELam x e) = (FV e = {})" |
"is_value _ = False"

lemma is_value_is_val[simp]: "is_value e ⟹ isval e ∧ FV e = {}"
by (case_tac e) auto

fun opt :: "exp ⇒ nat ⇒ exp" where
"opt (EVar x) k = EVar x" |
"opt (ENat n) k = ENat n" |
"opt (ELam x e) k = ELam x (opt e k)" |
"opt (EApp e1 e2) 0 = EApp (opt e1 0) (opt e2 0)" |
"opt (EApp e1 e2) (Suc k) =
(let e1' = opt e1 (Suc k) in let e2' = opt e2 (Suc k) in
(case e1' of
ELam x e ⇒ if is_value e2' then opt (subst x e2' e) k
else EApp e1' e2'
| _ ⇒ EApp e1' e2'))" |
"opt (EPrim f e1 e2) k =
(let e1' = opt e1 k in let e2' = opt e2 k in
(case (e1', e2') of
(ENat n1, ENat n2) ⇒ ENat (f n1 n2)
| _ ⇒ EPrim f e1' e2'))" |
"opt (EIf e1 e2 e3) k =
(let e1' = opt e1 k in let e2' = opt e2 k in let e3' = opt e3 k in
(case e1' of
ENat n ⇒ if n = 0 then e3' else e2'
| _ ⇒ EIf e1' e2' e3'))"

lemma opt_correct_aux: "E e = E (opt e k)"
proof (induction e k rule: opt.induct)
case (5 e1 e2 k)
then show ?case
apply (cases "opt e1 (Suc k)")
apply force
apply force
prefer 2 apply force
prefer 2 apply force
prefer 2 apply force
apply (rename_tac x e)
apply (cases "is_value (opt e2 (Suc k))")
apply (subgoal_tac "E (EApp (ELam x e) (opt e2 (Suc k)))
= E (subst x (opt e2 (Suc k)) e)")
prefer 2 apply (rule eval_app_lam)
apply (simp del: E.simps)
apply (subgoal_tac "E(EApp e1 e2) = E(EApp (ELam x e) (opt e2 (Suc k)))")
prefer 2
apply (rule e_app_cong)
apply force+ done
next
case (6 f e1 e2 k)
then show ?case apply auto apply (cases "opt e1 k") apply auto
apply (cases "opt e2 k") apply auto done
next
case (7 e1 e2 e3 k)
then show ?case by (cases "opt e1 k") auto
qed auto

theorem opt_correct: "e ≃ opt e k"
using opt_correct_aux denot_sound_wrt_ctx_equiv by blast

end
```