theory NBE imports Main begin
ML"Syntax.ambiguity_level := 1000000"
declare Let_def[simp]
section "Terms"
types vname = nat
ml_vname = nat
types cname=int
text{* ML terms: *}
datatype ml =
-- "ML"
C_ML cname ("CML")
| V_ML ml_vname ("VML")
| A_ML ml "(ml list)" ("AML")
| Lam_ML ml ("LamML")
-- "the universal datatype"
| CU cname "(ml list)"
| VU vname "(ml list)"
| Clo ml "(ml list)" nat
--{*ML function \emph{apply}*}
| "apply" ml ml
text{* Lambda-terms: *}
datatype tm = C cname | V vname | Λ tm | At tm tm (infix "•" 100)
| "term" ml -- {*ML function \texttt{term}*}
text {* The following locale captures type conventions for variables.
It is not actually used, merely a formal comment. *}
locale Vars =
fixes r s t:: tm
and rs ss ts :: "tm list"
and u v w :: ml
and us vs ws :: "ml list"
and nm :: cname
and x :: vname
and X :: ml_vname
text{* The subset of pure terms: *}
inductive pure :: "tm => bool" where
"pure(C nm)" |
"pure(V x)" |
Lam: "pure t ==> pure(Λ t)" |
"pure s ==> pure t ==> pure(s•t)"
declare pure.intros[simp]
declare Lam[simp del]
lemma pure_Lam[simp]: "pure(Λ t) = pure t"
proof
assume "pure(Λ t)" thus "pure t"
proof cases qed auto
next
assume "pure t" thus "pure(Λ t)" by(rule Lam)
qed
text{* Closed terms w.r.t.\ ML variables:*}
fun closed_ML :: "nat => ml => bool" ("closedML") where
"closedML i (CML nm) = True" |
"closedML i (VML X) = (X<i)" |
"closedML i (AML v vs) = (closedML i v ∧ (∀v ∈ set vs. closedML i v))" |
"closedML i (LamML v) = closedML (i+1) v" |
"closedML i (CU nm vs) = (∀v ∈ set vs. closedML i v)" |
"closedML i (VU nm vs) = (∀v ∈ set vs. closedML i v)" |
"closedML i (Clo f vs n) = (closedML i f ∧ (∀v ∈ set vs. closedML i v))" |
"closedML i (apply v w) = (closedML i v ∧ closedML i w)"
fun closed_tm_ML :: "nat => tm => bool" ("closedML") where
"closed_tm_ML i (r•s) = (closed_tm_ML i r ∧ closed_tm_ML i s)" |
"closed_tm_ML i (Λ t) = (closed_tm_ML i t)" |
"closed_tm_ML i (term v) = closed_ML i v" |
"closed_tm_ML i v = True"
text{* Free variables: *}
fun fv_ML :: "ml => ml_vname set" ("fvML") where
"fvML (CML nm) = {}" |
"fvML (VML X) = {X}" |
"fvML (AML v vs) = fvML v ∪ (\<Union>v ∈ set vs. fvML v)" |
"fvML (LamML v) = {X. Suc X : fvML v}" |
"fvML (CU nm vs) = (\<Union>v ∈ set vs. fvML v)" |
"fvML (VU nm vs) = (\<Union>v ∈ set vs. fvML v)" |
"fvML (Clo f vs n) = fvML f ∪ (\<Union>v ∈ set vs. fvML v)" |
"fvML (apply v w) = fvML v ∪ fvML w"
primrec fv :: "tm => vname set" where
"fv (C nm) = {}" |
"fv (V X) = {X}" |
"fv (s • t) = fv s ∪ fv t" |
"fv (Λ t) = {X. Suc X : fv t}"
subsection "Iterated Term Application"
abbreviation foldl_At (infix "••" 90) where
"t •• ts ≡ foldl (op •) t ts"
text{*Auxiliary measure function:*}
primrec depth_At :: "tm => nat"
where
"depth_At(C nm) = 0"
| "depth_At(V x) = 0"
| "depth_At(s • t) = depth_At s + 1"
| "depth_At(Λ t) = 0"
| "depth_At(term v) = 0"
lemma depth_At_foldl:
"depth_At(s •• ts) = depth_At s + size ts"
by (induct ts arbitrary: s) simp_all
lemma foldl_At_eq_lemma: "size ts = size ts' ==>
s •• ts = s' •• ts' <-> s = s' ∧ ts = ts'"
by (induct arbitrary: s s' rule:list_induct2) simp_all
lemma foldl_At_eq_length:
"s •• ts = s •• ts' ==> length ts = length ts'"
apply(subgoal_tac "depth_At(s •• ts) = depth_At(s •• ts')")
apply(erule thin_rl)
apply (simp add:depth_At_foldl)
apply simp
done
lemma foldl_At_eq[simp]: "s •• ts = s •• ts' <-> ts = ts'"
apply(rule)
prefer 2 apply simp
apply(blast dest:foldl_At_eq_lemma foldl_At_eq_length)
done
lemma term_eq_foldl_At[simp]:
"term v = t •• ts <-> t = term v ∧ ts = []"
by (induct ts arbitrary:t) auto
lemma At_eq_foldl_At[simp]:
"r • s = t •• ts <->
(if ts=[] then t = r • s else s = last ts ∧ r = t •• butlast ts)"
apply (induct ts arbitrary:t)
apply fastsimp
apply rule
apply clarsimp
apply rule
apply clarsimp
apply clarsimp
apply(subgoal_tac "∃ts' t'. ts = ts' @ [t']")
apply clarsimp
defer
apply (clarsimp split:list.split)
apply (metis append_butlast_last_id)
done
lemma foldl_At_eq_At[simp]:
"t •• ts = r • s <->
(if ts=[] then t = r • s else s = last ts ∧ r = t •• butlast ts)"
by(metis At_eq_foldl_At)
lemma Lam_eq_foldl_At[simp]:
"Λ s = t •• ts <-> t = Λ s ∧ ts = []"
by (induct ts arbitrary:t) auto
lemma foldl_At_eq_Lam[simp]:
"t •• ts = Λ s <-> t = Λ s ∧ ts = []"
by (induct ts arbitrary:t) auto
lemma [simp]: "s • t ≠ s"
apply(subgoal_tac "size(s • t) ≠ size s")
apply metis
apply simp
done
fun atomic_tm :: "tm => bool" where
"atomic_tm(s • t) = False" |
"atomic_tm(_) = True"
fun head_tm where
"head_tm(s • t) = head_tm s" |
"head_tm(s) = s"
fun args_tm where
"args_tm(s • t) = args_tm s @ [t]" |
"args_tm(_) = []"
lemma head_tm_foldl_At[simp]: "head_tm(s •• ts) = head_tm s"
by(induct ts arbitrary: s) auto
lemma args_tm_foldl_At[simp]: "args_tm(s •• ts) = args_tm s @ ts"
by(induct ts arbitrary: s) auto
lemma tm_eq_iff:
"atomic_tm(head_tm s) ==> atomic_tm(head_tm t)
==> s = t <-> head_tm s = head_tm t ∧ args_tm s = args_tm t"
apply(induct s arbitrary: t)
apply(case_tac t, simp+)+
done
declare
tm_eq_iff[of "h •• ts", standard, simp]
tm_eq_iff[of _ "h •• ts", standard, simp]
lemma atomic_tm_head_tm: "atomic_tm(head_tm t)"
by(induct t) auto
lemma head_tm_idem: "head_tm(head_tm t) = head_tm t"
by(induct t) auto
lemma args_tm_head_tm: "args_tm(head_tm t) = []"
by(induct t) auto
lemma eta_head_args: "t = head_tm t •• args_tm t"
by (subst tm_eq_iff) (auto simp: atomic_tm_head_tm head_tm_idem args_tm_head_tm)
lemma tm_vector_cases:
"(∃n ts. t = V n •• ts) ∨
(∃nm ts. t = C nm •• ts) ∨
(∃t' ts. t = Λ t' •• ts) ∨
(∃v ts. t = term v •• ts)"
apply(induct t)
apply simp_all
apply (metis append_is_Nil_conv args_tm.simps(2) args_tm.simps(5) args_tm_foldl_At butlast.simps(2) butlast_append butlast_snoc eta_head_args head_tm.simps(2) head_tm.simps(4) head_tm.simps(5) head_tm_foldl_At last_snoc list.simps(2) not_Cons_self rotate1_is_Nil_conv rotate_simps self_append_conv self_append_conv2 tm.simps(12) tm.simps(22))
done
lemma fv_head_C[simp]: "fv (t •• ts) = fv t ∪ (\<Union>t∈set ts. fv t)"
by(induct ts arbitrary:t) auto
subsection "Lifting and Substitution"
fun lift_ml :: "nat => ml => ml" ("lift") where
"lift i (CML nm) = CML nm" |
"lift i (VML X) = VML X" |
"lift i (AML v vs) = AML (lift i v) (map (lift i) vs)" |
"lift i (LamML v) = LamML (lift i v)" |
"lift i (CU nm vs) = CU nm (map (lift i) vs)" |
"lift i (VU x vs) = VU (if x < i then x else x+1) (map (lift i) vs)" |
"lift i (Clo v vs n) = Clo (lift i v) (map (lift i) vs) n" |
"lift i (apply u v) = apply (lift i u) (lift i v)"
lemmas ml_induct = lift_ml.induct[of "λi v. P v", standard]
fun lift_tm :: "nat => tm => tm" ("lift") where
"lift i (C nm) = C nm" |
"lift i (V x) = V(if x < i then x else x+1)" |
"lift i (s•t) = (lift i s)•(lift i t)" |
"lift i (Λ t) = Λ(lift (i+1) t)" |
"lift i (term v) = term (lift i v)"
fun lift_ML :: "nat => ml => ml" ("liftML") where
"liftML i (CML nm) = CML nm" |
"liftML i (VML X) = VML (if X < i then X else X+1)" |
"liftML i (AML v vs) = AML (liftML i v) (map (liftML i) vs)" |
"liftML i (LamML v) = LamML (liftML (i+1) v)" |
"liftML i (CU nm vs) = CU nm (map (liftML i) vs)" |
"liftML i (VU x vs) = VU x (map (liftML i) vs)" |
"liftML i (Clo v vs n) = Clo (liftML i v) (map (liftML i) vs) n" |
"liftML i (apply u v) = apply (liftML i u) (liftML i v)"
definition
cons :: "tm => (nat => tm) => (nat => tm)" (infix "##" 65) where
"t##σ ≡ λi. case i of 0 => t | Suc j => lift 0 (σ j)"
definition
cons_ML :: "ml => (nat => ml) => (nat => ml)" (infix "##" 65) where
"v##σ ≡ λi. case i of 0 => v::ml | Suc j => liftML 0 (σ j)"
text{* Only for pure terms! *}
primrec subst :: "(nat => tm) => tm => tm"
where
"subst σ (C nm) = C nm"
| "subst σ (V x) = σ x"
| "subst σ (Λ t) = Λ(subst (V 0 ## σ) t)"
| "subst σ (s•t) = (subst σ s) • (subst σ t)"
fun subst_ML :: "(nat => ml) => ml => ml" ("substML") where
"substML σ (CML nm) = CML nm" |
"substML σ (VML X) = σ X" |
"substML σ (AML v vs) = AML (substML σ v) (map (substML σ) vs)" |
"substML σ (LamML v) = LamML (substML (VML 0 ## σ) v)" |
"substML σ (CU nm vs) = CU nm (map (substML σ) vs)" |
"substML σ (VU x vs) = VU x (map (substML σ) vs)" |
"substML σ (Clo v vs n) = Clo (substML σ v) (map (substML σ) vs) n" |
"substML σ (apply u v) = apply (substML σ u) (substML σ v)"
abbreviation
subst_decr :: "nat => tm => nat => tm" where
"subst_decr k t ≡ λn. if n<k then V n else if n=k then t else V(n - 1)"
abbreviation
subst_decr_ML :: "nat => ml => nat => ml" where
"subst_decr_ML k v ≡ λn. if n<k then VML n else if n=k then v else VML(n - 1)"
abbreviation
subst1 :: "tm => tm => nat => tm" ("(_/[_'/_])" [300, 0, 0] 300) where
"s[t/k] ≡ subst (subst_decr k t) s"
abbreviation
subst1_ML :: "ml => ml => nat => ml" ("(_/[_'/_])" [300, 0, 0] 300) where
"u[v/k] ≡ substML (subst_decr_ML k v) u"
lemma apply_cons[simp]:
"(t##σ) i = (if i=0 then t::tm else lift 0 (σ(i - 1)))"
by(simp add: cons_def split:nat.split)
lemma apply_cons_ML[simp]:
"(v##σ) i = (if i=0 then v::ml else liftML 0 (σ(i - 1)))"
by(simp add: cons_ML_def split:nat.split)
lemma lift_foldl_At[simp]:
"lift k (s •• ts) = (lift k s) •• (map (lift k) ts)"
by(induct ts arbitrary:s) simp_all
lemma lift_lift_ml: fixes v :: ml shows
"i < k+1 ==> lift (Suc k) (lift i v) = lift i (lift k v)"
by(induct i v rule:lift_ml.induct)
simp_all
lemma lift_lift_tm: fixes t :: tm shows
"i < k+1 ==> lift (Suc k) (lift i t) = lift i (lift k t)"
by(induct t arbitrary: i rule:lift_tm.induct)(simp_all add:lift_lift_ml)
lemma lift_lift_ML:
"i < k+1 ==> liftML (Suc k) (liftML i v) = liftML i (liftML k v)"
by(induct v arbitrary: i rule:lift_ML.induct)
simp_all
lemma lift_lift_ML_comm:
"lift j (liftML i v) = liftML i (lift j v)"
by(induct v arbitrary: i j rule:lift_ML.induct)
simp_all
lemma V_ML_cons_ML_subst_decr[simp]:
"VML 0 ## subst_decr_ML k v = subst_decr_ML (Suc k) (liftML 0 v)"
by(rule ext)(simp add:cons_ML_def split:nat.split)
lemma shift_subst_decr[simp]:
"V 0 ## subst_decr k t = subst_decr (Suc k) (lift 0 t)"
by(rule ext)(simp add:cons_def split:nat.split)
lemma lift_comp_subst_decr[simp]:
"lift 0 o subst_decr_ML k v = subst_decr_ML k (lift 0 v)"
by(rule ext) simp
lemma subst_ML_ext: "∀i. σ i = σ' i ==> substML σ v = substML σ' v"
by(metis ext)
lemma subst_ext: "∀i. σ i = σ' i ==> subst σ v = subst σ' v"
by(metis ext)
lemma lift_Pure_tms[simp]: "pure t ==> pure(lift k t)"
by(induct arbitrary:k pred:pure) simp_all
lemma cons_ML_V_ML[simp]: "(VML 0 ## VML) = VML"
by(rule ext) simp
lemma cons_V[simp]: "(V 0 ## V) = V"
by(rule ext) simp
lemma lift_o_shift: "lift k o (VML 0 ## σ) = (VML 0 ## (lift k o σ))"
by(rule ext)(simp add: lift_lift_ML_comm)
lemma lift_subst_ML:
"lift k (substML σ v) = substML (lift k o σ) (lift k v)"
apply(induct σ v rule:subst_ML.induct)
apply(simp_all add: o_assoc lift_o_shift del:apply_cons_ML)
apply(simp add:o_def)
done
corollary lift_subst_ML1:
"∀v k. lift_ml 0 (u[v/k]) = (lift_ml 0 u)[lift 0 v/k]"
apply(induct u rule:ml_induct)
apply(simp_all add:lift_lift_ml lift_subst_ML)
apply(subst lift_lift_ML_comm)apply simp
done
lemma lift_ML_subst_ML:
"liftML k (substML σ v) =
substML (λi. if i<k then liftML k (σ i) else if i=k then VML k else liftML k (σ(i - 1))) (liftML k v)"
(is "_ = substML (?insrt k σ) (liftML k v)")
apply (induct k v arbitrary: σ k rule: lift_ML.induct)
apply (simp_all add: o_assoc lift_o_shift)
apply(subgoal_tac "VML 0 ## ?insrt k σ = ?insrt (Suc k) (VML 0 ## σ)")
apply simp
apply (simp add:expand_fun_eq lift_lift_ML cons_ML_def split:nat.split)
done
corollary subst_cons_lift:
"substML (VML 0 ## σ) o (liftML 0) = liftML 0 o (substML σ)"
apply(rule ext)
apply(simp add: lift_ML_subst_ML)
apply(subgoal_tac "(VML 0 ## σ) = (λi. if i = 0 then VML 0 else liftML 0 (σ (i - 1)))")
apply simp
apply(rule ext, simp)
done
lemma lift_ML_id[simp]: "closedML k v ==> liftML k v = v"
by(induct k v rule: lift_ML.induct)(simp_all add:list_eq_iff_nth_eq)
lemma subst_ML_id:
"closedML k v ==> ∀i<k. σ i = VML i ==> substML σ v = v"
apply (induct σ v arbitrary: k rule: subst_ML.induct)
apply (auto simp add: list_eq_iff_nth_eq)
apply(simp add:Ball_def)
apply(erule_tac x="vs!i" in meta_allE)
apply(erule_tac x="k" in meta_allE)
apply(erule_tac x="k" in meta_allE)
apply simp
apply(erule_tac x="vs!i" in meta_allE)
apply(erule_tac x="k" in meta_allE)
apply simp
apply(erule_tac x="vs!i" in meta_allE)
apply(erule_tac x="k" in meta_allE)
apply simp
apply(erule_tac x="vs!i" in meta_allE)
apply(erule_tac x="k" in meta_allE)
apply(erule_tac x="k" in meta_allE)
apply simp
done
corollary subst_ML_id2[simp]: "closedML 0 v ==> substML σ v = v"
using subst_ML_id[where k=0] by simp
lemma subst_ML_coincidence:
"closedML k v ==> ∀i<k. σ i = σ' i ==> substML σ v = substML σ' v"
by (induct σ v arbitrary: k σ' rule: subst_ML.induct) auto
lemma subst_ML_comp:
"substML σ (substML σ' v) = substML (substML σ o σ') v"
apply (induct σ' v arbitrary: σ rule: subst_ML.induct)
apply (simp_all add: list_eq_iff_nth_eq)
apply(rule subst_ML_ext)
apply simp
apply (metis o_apply subst_cons_lift)
done
lemma subst_ML_comp2:
"∀i. σ'' i = substML σ (σ' i) ==> substML σ (substML σ' v) = substML σ'' v"
by(simp add:subst_ML_comp subst_ML_ext)
lemma closed_tm_ML_foldl_At:
"closedML k (t •• ts) <-> closedML k t ∧ (∀t ∈ set ts. closedML k t)"
by(induct ts arbitrary: t) simp_all
lemma closed_ML_lift[simp]:
fixes v :: ml shows "closedML k v ==> closedML k (lift m v)"
by(induct k v arbitrary: m rule: lift_ML.induct)
(simp_all add:list_eq_iff_nth_eq)
lemma closed_ML_Suc: "closedML n v ==> closedML (Suc n) (liftML k v)"
by (induct k v arbitrary: n rule: lift_ML.induct) simp_all
lemma closed_ML_subst_ML:
"∀i. closedML k (σ i) ==> closedML k (substML σ v)"
by(induct σ v arbitrary: k rule: subst_ML.induct) (auto simp: closed_ML_Suc)
lemma closed_ML_subst_ML2:
"closedML k v ==> ∀i<k. closedML l (σ i) ==> closedML l (substML σ v)"
by(induct σ v arbitrary: k l rule: subst_ML.induct)(auto simp: closed_ML_Suc)
lemma subst_foldl[simp]:
"subst σ (s •• ts) = (subst σ s) •• (map (subst σ) ts)"
by (induct ts arbitrary: s) auto
lemma subst_V: "pure t ==> subst V t = t"
by(induct pred:pure) simp_all
lemma lift_subst_aux:
"pure t ==> ∀i<k. σ' i = lift k (σ i) ==>
∀i≥k. σ'(Suc i) = lift k (σ i) ==>
σ' k = V k ==> lift k (subst σ t) = subst σ' (lift k t)"
apply(induct arbitrary:σ σ' k pred:pure)
apply (simp_all add: split:nat.split)
apply(erule meta_allE)+
apply(erule meta_impE)
defer
apply(erule meta_impE)
defer
apply(erule meta_mp)
apply (simp_all add: cons_def lift_lift_ml lift_lift_tm split:nat.split)
done
corollary lift_subst:
"pure t ==> lift 0 (subst σ t) = subst (V 0 ## σ) (lift 0 t)"
by (simp add: lift_subst_aux lift_lift_ml)
lemma subst_comp:
"pure t ==> ∀i. pure(σ' i) ==>
σ'' = (λi. subst σ (σ' i)) ==> subst σ (subst σ' t) = subst σ'' t"
apply(induct arbitrary:σ σ' σ'' pred:pure)
apply simp
apply simp
defer
apply simp
apply (simp (no_asm))
apply(erule meta_allE)+
apply(erule meta_impE)
defer
apply(erule meta_mp)
prefer 2 apply simp
apply(rule ext)
apply(simp add:lift_subst)
done
section "Reduction"
subsection "Patterns"
inductive pattern :: "tm => bool"
and patterns :: "tm list => bool" where
"patterns ts ≡ ∀t∈set ts. pattern t" |
pat_V: "pattern(V X)" |
pat_C: "patterns ts ==> pattern(C nm •• ts)"
lemma pattern_Lam[simp]: "¬ pattern(Λ t)"
by(auto elim!: pattern.cases)
lemma pattern_At'D12: "pattern r ==> r = (s • t) ==> pattern s ∧ pattern t"
proof(induct arbitrary: s t pred:pattern)
case pat_V thus ?case by simp
next
case pat_C thus ?case
by (simp add: atomic_tm_head_tm split:split_if_asm)
(metis eta_head_args in_set_butlastD pattern.pat_C)
qed
lemma pattern_AtD12: "pattern(s • t) ==> pattern s ∧ pattern t"
by(metis pattern_At'D12)
lemma pattern_At_vecD: "pattern(s •• ts) ==> patterns ts"
apply(induct ts rule:rev_induct)
apply simp
apply (fastsimp dest!:pattern_AtD12)
done
lemma pattern_At_decomp: "pattern(s • t) ==> ∃nm ss. s = C nm •• ss"
proof(induct s arbitrary: t)
case (At s1 s2) show ?case
using pattern_AtD12[OF At.prems] At(1)[of s2]
by clarsimp (metis append_is_Nil_conv butlast_snoc last_snoc not_Cons_self)
qed (auto elim!: pattern.cases split:split_if_asm)
subsection "Reduction of @{text λ}-terms"
text{* The source program: *}
axiomatization R :: "(cname * tm list * tm)set" where
pure_R: "(nm,ts,t) : R ==> (∀t ∈ set ts. pure t) ∧ pure t" and
fv_R: "(nm,ts,t) : R ==> X : fv t ==> ∃t' ∈ set ts. X : fv t'" and
pattern_R: "(nm,ts,t') : R ==> patterns ts"
inductive_set
Red_tm :: "(tm * tm)set"
and red_tm :: "[tm, tm] => bool" (infixl "->" 50)
where
"s -> t ≡ (s, t) ∈ Red_tm"
-- {*$\beta$-reduction*}
| "(Λ t) • s -> t[s/0]"
-- {*$\eta$-expansion*}
| "t -> Λ ((lift 0 t) • (V 0))"
-- "Rewriting"
| "(nm,ts,t) : R ==> (C nm) •• (map (subst σ) ts) -> subst σ t"
| "t -> t' ==> Λ t -> Λ t'"
| "s -> s' ==> s • t -> s' • t"
| "t -> t' ==> s • t -> s • t'"
abbreviation
reds_tm :: "[tm, tm] => bool" (infixl "->*" 50) where
"s ->* t ≡ (s, t) ∈ Red_tm^*"
inductive_set
Reds_tm_list :: "(tm list * tm list) set"
and reds_tm_list :: "[tm list, tm list] => bool" (infixl "->*" 50)
where
"ss ->* ts ≡ (ss, ts) ∈ Reds_tm_list"
| "[] ->* []"
| "ts ->* ts' ==> t ->* t' ==> t#ts ->* t'#ts'"
declare Reds_tm_list.intros[simp]
lemma Reds_tm_list_refl[simp]: fixes ts :: "tm list" shows "ts ->* ts"
by(induct ts) auto
lemma Red_tm_append: "rs ->* rs' ==> ts ->* ts' ==> rs @ ts ->* rs' @ ts'"
by(induct set: Reds_tm_list) auto
lemma Red_tm_rev: "ts ->* ts' ==> rev ts ->* rev ts'"
by(induct set: Reds_tm_list) (auto simp:Red_tm_append)
lemma red_Lam[simp]: "t ->* t' ==> Λ t ->* Λ t'"
apply(induct rule:rtrancl_induct)
apply(simp_all)
apply(blast intro: rtrancl_into_rtrancl Red_tm.intros)
done
lemma red_At1[simp]: "t ->* t' ==> t • s ->* t' • s"
apply(induct rule:rtrancl_induct)
apply(simp_all)
apply(blast intro: rtrancl_into_rtrancl Red_tm.intros)
done
lemma red_At2[simp]: "t ->* t' ==> s • t ->* s • t'"
apply(induct rule:rtrancl_induct)
apply(simp_all)
apply(blast intro:rtrancl_into_rtrancl Red_tm.intros)
done
lemma Reds_tm_list_foldl_At:
"ts ->* ts' ==> s ->* s' ==> s •• ts ->* s' •• ts'"
apply(induct arbitrary:s s' rule:Reds_tm_list.induct)
apply simp
apply simp
apply(blast dest: red_At1 red_At2 intro:rtrancl_trans)
done
subsection "Reduction of ML-terms"
text{* The compiled rule set: *}
consts compR :: "(cname * ml list * ml)set"
text{* \noindent
The actual definition is given in \S\ref{sec:Compiler} below. *}
text{* Now we characterize ML values that cannot possibly be rewritten by a
rule in @{const compR}. *}
lemma termination_no_match_ML:
"i < length ps ==> rev ps ! i = CU nm vs
==> listsum (map size vs) < listsum (map size ps)"
apply(subgoal_tac "CU nm vs : set ps")
apply(drule listsum_map_remove1[of _ _ size])
apply (simp add:list_size_conv_listsum)
apply (metis in_set_conv_nth length_rev set_rev)
done
declare conj_cong[fundef_cong]
function no_match_ML ("no'_matchML") where
"no_matchML ps os =
(∃i < min (size os) (size ps).
∃nm nm' vs vs'. (rev ps)!i = CU nm vs ∧ (rev os)!i = CU nm' vs' ∧
(nm=nm' --> no_matchML vs vs'))"
by pat_completeness auto
termination
apply(relation "measure(%(vs::ml list,_). ∑v\<leftarrow>vs. size v)")
apply (auto simp:termination_no_match_ML)
done
abbreviation
"no_match_compR nm os ≡
∀(nm',ps,v)∈ compR. nm=nm' --> no_matchML ps os"
declare no_match_ML.simps[simp del]
inductive_set
Red_ml :: "(ml * ml)set"
and Red_ml_list :: "(ml list * ml list)set"
and red_ml :: "[ml, ml] => bool" (infixl "=>" 50)
and red_ml_list :: "[ml list, ml list] => bool" (infixl "=>" 50)
and reds_ml :: "[ml, ml] => bool" (infixl "=>*" 50)
where
"s => t ≡ (s, t) ∈ Red_ml"
| "ss => ts ≡ (ss, ts) ∈ Red_ml_list"
| "s =>* t ≡ (s, t) ∈ Red_ml^*"
-- {* ML $\beta$-reduction *}
| "AML (LamML u) [v] => u[v/0]"
-- "Execution of a compiled rewrite rule"
| "(nm,vs,v) : compR ==> ∀ i. closedML 0 (σ i) ==>
AML (CML nm) (map (substML σ) vs) => substML σ v"
-- {* default rule: *}
| "∀i. closedML 0 (σ i)
==> vs = map VML [0..<arity nm] ==> vs' = map (substML σ) vs
==> no_match_compR nm vs'
==> AML (CML nm) vs' => substML σ (CU nm vs)"
-- {* Equations for function \texttt{apply}*}
| apply_Clo1: "apply (Clo f vs (Suc 0)) v => AML f (v # vs)"
| apply_Clo2: "n > 0 ==>
apply (Clo f vs (Suc n)) v => Clo f (v # vs) n"
| apply_C: "apply (CU nm vs) v => CU nm (v # vs)"
| apply_V: "apply (VU x vs) v => VU x (v # vs)"
-- "Context rules"
| ctxt_C: "vs => vs' ==> CU nm vs => CU nm vs'"
| ctxt_V: "vs => vs' ==> VU x vs => VU x vs'"
| ctxt_Clo1: "f => f' ==> Clo f vs n => Clo f' vs n"
| ctxt_Clo3: "vs => vs' ==> Clo f vs n => Clo f vs' n"
| ctxt_apply1: "s => s' ==> apply s t => apply s' t"
| ctxt_apply2: "t => t' ==> apply s t => apply s t'"
| ctxt_A_ML1: "f => f' ==> AML f vs => AML f' vs"
| ctxt_A_ML2: "vs => vs' ==> AML f vs => AML f vs'"
| ctxt_list1: "v => v' ==> v#vs => v'#vs"
| ctxt_list2: "vs => vs' ==> v#vs => v#vs'"
inductive_set
Red_term :: "(tm * tm)set"
and red_term :: "[tm, tm] => bool" (infixl "=>" 50)
and reds_term :: "[tm, tm] => bool" (infixl "=>*" 50)
where
"s => t ≡ (s, t) ∈ Red_term"
| "s =>* t ≡ (s, t) ∈ Red_term^*"
--{* function \texttt{term} *}
| term_C: "term (CU nm vs) => (C nm) •• (map term (rev vs))"
| term_V: "term (VU x vs) => (V x) •• (map term (rev vs))"
| term_Clo: "term(Clo vf vs n) => Λ (term (apply (lift 0 (Clo vf vs n)) (VU 0 [])))"
-- "context rules"
| ctxt_Lam: "t => t' ==> Λ t => Λ t'"
| ctxt_At1: "s => s' ==> s • t => s' • t"
| ctxt_At2: "t => t' ==> s • t => s • t'"
| ctxt_term: "v => v' ==> term v => term v'"
section "Kernel"
text{* First a special size function and some lemmas for the
termination proof of the kernel function. *}
fun size' :: "ml => nat" where
"size' (CML nm) = 1" |
"size' (VML X) = 1" |
"size' (AML v vs) = (size' v + (∑v\<leftarrow>vs. size' v))+1" |
"size' (LamML v) = size' v + 1" |
"size' (CU nm vs) = (∑v\<leftarrow>vs. size' v)+1" |
"size' (VU nm vs) = (∑v\<leftarrow>vs. size' v)+1" |
"size' (Clo f vs n) = (size' f + (∑v\<leftarrow>vs. size' v))+1" |
"size' (apply v w) = (size' v + size' w)+1"
lemma listsum_size'[simp]:
"v ∈ set vs ==> size' v < Suc(listsum (map size' vs))"
by(induct vs)(auto)
corollary cor_listsum_size'[simp]:
"v ∈ set vs ==> size' v < Suc(m + listsum (map size' vs))"
using listsum_size'[of v vs] by arith
lemma size'_lift_ML: "size' (liftML k v) = size' v"
apply(induct v arbitrary:k rule:size'.induct)
apply simp_all
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
done
lemma size'_subst_ML[simp]:
"∀i j. size'(σ i) = 1 ==> size' (substML σ v) = size' v"
apply(induct v arbitrary:σ rule:size'.induct)
apply simp_all
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(erule meta_allE)
apply(erule meta_mp)
apply(simp add: size'_lift_ML split:nat.split)
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
done
lemma size'_lift[simp]: "size' (lift i v) = size' v"
apply(induct v arbitrary:i rule:size'.induct)
apply simp_all
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
apply(rule arg_cong[where f = listsum])
apply(rule map_ext)
apply simp
done
function kernel :: "ml => tm" ("_!" 300) where
"(CML nm)! = C nm" |
"(AML v vs)! = v! •• (map kernel (rev vs))" |
"(LamML v)! = Λ (((lift 0 v)[VU 0 []/0])!)" |
"(CU nm vs)! = (C nm) •• (map kernel (rev vs))" |
"(VU x vs)! = (V x) •• (map kernel (rev vs))" |
"(Clo f vs n)! = f! •• (map kernel (rev vs))" |
"(apply v w)! = v! • (w!)" |
"(VML X)! = undefined"
by pat_completeness auto
termination by(relation "measure size'") auto
primrec kernelt :: "tm => tm" ("_!" 300)
where
"(C nm)! = C nm"
| "(V x)! = V x"
| "(s • t)! = (s!) • (t!)"
| "(Λ t)! = Λ(t!)"
| "(term v)! = v!"
abbreviation
kernels :: "ml list => tm list" ("_!" 300) where
"vs! ≡ map kernel vs"
lemma kernel_pure: assumes "pure t" shows "t! = t"
using assms by (induct) simp_all
lemma kernel_foldl_At[simp]: "(s •• ts)! = (s!) •• (map kernelt ts)"
by (induct ts arbitrary: s) simp_all
lemma kernelt_o_term[simp]: "(kernelt o term) = kernel"
by(rule ext) simp
lemma pure_foldl:
"pure t ==> ∀t∈set ts. pure t ==>
(!!s t. pure s ==> pure t ==> pure(f s t)) ==>
pure(foldl f t ts)"
by(induct ts arbitrary: t) simp_all
lemma pure_kernel: fixes v :: ml shows "closedML 0 v ==> pure(v!)"
proof(induct v rule:kernel.induct)
case (3 v)
hence "closedML (Suc 0) (lift 0 v)" by simp
then have "substML (λn. VU 0 []) (lift 0 v) = lift 0 v[VU 0 []/0]"
by(rule subst_ML_coincidence) simp
moreover have "closedML 0 (substML (λn. VU 0 []) (lift 0 v))"
by(simp add: closed_ML_subst_ML)
ultimately have "closedML 0 (lift 0 v[VU 0 []/0])" by simp
thus ?case using 3(1) by (simp add:pure_foldl)
qed (simp_all add:pure_foldl)
corollary subst_V_kernel: fixes v :: ml shows
"closedML 0 v ==> subst V (v!) = v!"
by (metis pure_kernel subst_V)
lemma kernel_lift_tm: fixes v :: ml shows
"closedML 0 v ==> (lift i v)! = lift i (v!)"
apply(induct v arbitrary: i rule: kernel.induct)
apply (simp_all add:list_eq_iff_nth_eq)
apply(simp add: rev_nth)
defer
apply(simp add: rev_nth)
apply(simp add: rev_nth)
apply(simp add: rev_nth)
apply(erule_tac x="Suc i" in meta_allE)
apply(erule meta_impE)
defer
apply (simp add:lift_subst_ML)
apply(subgoal_tac "lift (Suc i) o (λn. if n = 0 then VU 0 [] else VML (n - 1)) = (λn. if n = 0 then VU 0 [] else VML (n - 1))")
apply (simp add:lift_lift_ml)
apply(rule ext)
apply(simp)
apply(subst closed_ML_subst_ML2[of "1"])
apply(simp)
apply(simp)
apply(simp)
done
subsection "An auxiliary substitution"
text{* This function is only introduced to prove the involved susbtitution
lemma @{text kernel_subst1} below. *}
fun subst_ml :: "(nat => nat) => ml => ml" where
"subst_ml σ (CML nm) = CML nm" |
"subst_ml σ (VML X) = VML X" |
"subst_ml σ (AML v vs) = AML (subst_ml σ v) (map (subst_ml σ) vs)" |
"subst_ml σ (LamML v) = LamML (subst_ml σ v)" |
"subst_ml σ (CU nm vs) = CU nm (map (subst_ml σ) vs)" |
"subst_ml σ (VU x vs) = VU (σ x) (map (subst_ml σ) vs)" |
"subst_ml σ (Clo v vs n) = Clo (subst_ml σ v) (map (subst_ml σ) vs) n" |
"subst_ml σ (apply u v) = apply (subst_ml σ u) (subst_ml σ v)"
lemma lift_ML_subst_ml:
"liftML k (subst_ml σ v) = subst_ml σ (liftML k v)"
apply (induct σ v arbitrary: k rule:subst_ml.induct)
apply (simp_all add:list_eq_iff_nth_eq)
done
lemma subst_ml_subst_ML:
"subst_ml σ (substML σ' v) = substML (subst_ml σ o σ') (subst_ml σ v)"
apply (induct σ' v arbitrary: σ rule: subst_ML.induct)
apply(simp_all add:list_eq_iff_nth_eq)
apply(subgoal_tac "(subst_ml σ' o VML 0 ## σ) = VML 0 ## (subst_ml σ' o σ)")
apply simp
apply(rule ext)
apply(simp add: lift_ML_subst_ml)
done
text{* Maybe this should be the def of lift: *}
lemma lift_is_subst_ml: "lift k v = subst_ml (λn. if n<k then n else n+1) v"
by(induct k v rule:lift_ml.induct)(simp_all add:list_eq_iff_nth_eq)
lemma subst_ml_comp: "subst_ml σ (subst_ml σ' v) = subst_ml (σ o σ') v"
by(induct σ' v rule:subst_ml.induct)(simp_all add:list_eq_iff_nth_eq)
lemma subst_kernel:
"closedML 0 v ==> subst (λn. V(σ n)) (v!) = (subst_ml σ v)!"
apply (induct v arbitrary: σ rule:kernel.induct)
apply (simp_all add:list_eq_iff_nth_eq)
apply(simp add: rev_nth)
defer
apply(simp add: rev_nth)
apply(simp add: rev_nth)
apply(simp add: rev_nth)
apply(erule_tac x="λn. case n of 0 => 0 | Suc k => Suc(σ k)" in meta_allE)
apply(erule_tac meta_impE)
apply(rule closed_ML_subst_ML2[where k="Suc 0"])
apply (metis closed_ML_lift)
apply simp
apply(subgoal_tac "(λn. V(case n of 0 => 0 | Suc k => Suc (σ k))) = (V 0 ## (λn. V(σ n)))")
apply (simp add:subst_ml_subst_ML)
defer
apply(simp add:expand_fun_eq split:nat.split)
apply(simp add:lift_is_subst_ml subst_ml_comp)
apply(rule arg_cong[where f = kernel])
apply(subgoal_tac "(nat_case 0 (λk. Suc (σ k)) o Suc) = Suc o σ")
prefer 2 apply(simp add:expand_fun_eq split:nat.split)
apply(subgoal_tac "(subst_ml (nat_case 0 (λk. Suc (σ k))) o
(λn. if n = 0 then VU 0 [] else VML (n - 1)))
= (λn. if n = 0 then VU 0 [] else VML (n - 1))")
apply simp
apply(simp add: expand_fun_eq)
done
lemma if_cong0: "If x y z = If x y z"
by simp
lemma kernel_subst1:
"closedML 0 v ==> closedML (Suc 0) u ==>
kernel(u[v/0]) = (kernel((lift 0 u)[VU 0 []/0]))[v!/0]"
proof(induct u arbitrary:v rule:kernel.induct)
case (3 w)
show ?case (is "?L = ?R")
proof -
have "?L = Λ(lift 0 (w[liftML 0 v/Suc 0])[VU 0 []/0] !)"
by (simp cong:if_cong0)
also have "… = Λ((lift 0 w)[liftML 0 (lift 0 v)/Suc 0][VU 0 []/0]!)"
by(simp only: lift_subst_ML1 lift_lift_ML_comm)
also have "… = Λ(substML (λn. if n=0 then VU 0 [] else
if n=Suc 0 then lift 0 v else VML (n - 2)) (lift 0 w) !)"
apply simp
apply(rule arg_cong[where f = kernel])
apply(rule subst_ML_comp2)
using 3
apply auto
done
also have "… = Λ((lift 0 w)[VU 0 []/0][lift 0 v/0]!)"
apply simp
apply(rule arg_cong[where f = kernel])
apply(rule subst_ML_comp2[symmetric])
using 3
apply auto
done
also have "… = Λ((lift_ml 0 ((lift_ml 0 w)[VU 0 []/0]))[VU 0 []/0]![(lift 0 v)!/0])"
apply(rule arg_cong[where f = Λ])
apply(rule 3(1))
apply (metis closed_ML_lift 3(2))
apply(subgoal_tac "closedML (Suc(Suc 0)) w")
defer
using 3
apply force
apply(subgoal_tac "closedML (Suc (Suc 0)) (lift 0 w)")
defer
apply(erule closed_ML_lift)
apply(erule closed_ML_subst_ML2)
apply simp
done
also have "… = Λ((lift_ml 0 (lift_ml 0 w)[VU 1 []/0])[VU 0 []/0]![(lift 0 v)!/0])" (is "_ = ?M")
apply(subgoal_tac "lift_ml 0 (lift_ml 0 w[VU 0 []/0])[VU 0 []/0] =
lift_ml 0 (lift_ml 0 w)[VU 1 []/0][VU 0 []/0]")
apply simp
apply(subst lift_subst_ML)
apply(simp add:comp_def if_distrib[where f="lift_ml 0"] cong:if_cong)
done
finally have "?L = ?M" .
have "?R = Λ (subst (V 0 ## subst_decr 0 (v!))
(lift 0 (lift_ml 0 w[VU 0 []/Suc 0])[VU 0 []/0]!))"
apply(subgoal_tac "(VML 0 ## (λn. if n = 0 then VU 0 [] else VML (n - Suc 0))) = subst_decr_ML (Suc 0) (VU 0 [])")
apply(simp cong:if_cong)
apply(simp add:expand_fun_eq cons_ML_def split:nat.splits)
done
also have "… = Λ (subst (V 0 ## subst_decr 0 (v!))
((lift 0 (lift_ml 0 w))[VU 1 []/Suc 0][VU 0 []/0]!))"
apply(subgoal_tac "lift 0 (lift 0 w[VU 0 []/Suc 0]) = lift 0 (lift 0 w)[VU 1 []/Suc 0]")
apply simp
apply(subst lift_subst_ML)
apply(simp add:comp_def if_distrib[where f="lift_ml 0"] cong:if_cong)
done
also have "(lift_ml 0 (lift_ml 0 w))[VU 1 []/Suc 0][VU 0 []/0] =
(lift 0 (lift_ml 0 w))[VU 0 []/0][VU 1 []/ 0]" (is "?l = ?r")
proof -
have "?l = substML (λn. if n= 0 then VU 0 [] else if n = 1 then VU 1 [] else
VML (n - 2))
(lift_ml 0 (lift_ml 0 w))"
by(auto intro!:subst_ML_comp2)
also have "… = ?r" by(auto intro!:subst_ML_comp2[symmetric])
finally show ?thesis .
qed
also have "Λ (subst (V 0 ## subst_decr 0 (v!)) (?r !)) = ?M"
proof-
have "subst (subst_decr (Suc 0) (lift_tm 0 (kernel v))) (lift_ml 0 (lift_ml 0 w)[VU 0 []/0][VU 1 []/0]!) =
subst (subst_decr 0 (kernel(lift_ml 0 v))) (lift_ml 0 (lift_ml 0 w)[VU 1 []/0][VU 0 []/0]!)" (is "?a = ?b")
proof-
def pi == "λn::nat. if n = 0 then 1 else if n = 1 then 0 else n"
have "(λi. V (pi i)[lift 0 (v!)/0]) = subst_decr (Suc 0) (lift 0 (v!))"
by(rule ext)(simp add:pi_def)
hence "?a =
subst (subst_decr 0 (lift_tm 0 (kernel v))) (subst (λ n. V(pi n)) (lift_ml 0 (lift_ml 0 w)[VU 0 []/0][VU 1 []/0]!))"
apply(subst subst_comp[OF _ _ refl])
prefer 3 apply simp
using 3(3)
apply simp
apply(rule pure_kernel)
apply(rule closed_ML_subst_ML2[where k="Suc 0"])
apply(rule closed_ML_subst_ML2[where k="Suc(Suc 0)"])
apply simp
apply simp
apply simp
apply simp
done
also have "… =
(subst_ml pi (lift_ml 0 (lift_ml 0 w)[VU 0 []/0][VU 1 []/0]))![lift_tm 0 (v!)/0]"
apply(subst subst_kernel)
using 3 apply auto
apply(rule closed_ML_subst_ML2[where k="Suc 0"])
apply(rule closed_ML_subst_ML2[where k="Suc(Suc 0)"])
apply simp
apply simp
apply simp
done
also have "… = (subst_ml pi (lift_ml 0 (lift_ml 0 w)[VU 0 []/0][VU 1 []/0]))![lift 0 v!/0]"
proof -
have "lift 0 (v!) = lift 0 v!" by (metis 3(2) kernel_lift_tm)
thus ?thesis by (simp cong:if_cong)
qed
also have "… = ?b"
proof-
have 1: "subst_ml pi (lift 0 (lift 0 w)) = lift 0 (lift 0 w)"
apply(simp add:lift_is_subst_ml subst_ml_comp)
apply(subgoal_tac "pi o (Suc o Suc) = (Suc o Suc)")
apply(simp)
apply(simp add:pi_def expand_fun_eq)
done
have "subst_ml pi (lift_ml 0 (lift_ml 0 w)[VU 0 []/0][VU 1 []/0]) =
lift_ml 0 (lift_ml 0 w)[VU 1 []/0][VU 0 []/0]"
apply(subst subst_ml_subst_ML)
apply(subst subst_ml_subst_ML)
apply(subst 1)
apply(subst subst_ML_comp)
apply(rule subst_ML_comp2[symmetric])
apply(auto simp:pi_def)
done
thus ?thesis by simp
qed
finally show ?thesis .
qed
thus ?thesis by(simp cong:if_cong0 add:shift_subst_decr)
qed
finally have "?R = ?M" .
then show "?L = ?R" using `?L = ?M` by metis
qed
qed (simp_all add:list_eq_iff_nth_eq, (simp_all add:rev_nth)?)
section {*Compiler \label{sec:Compiler}*}
axiomatization arity :: "cname => nat"
primrec compile :: "tm => (nat => ml) => ml"
where
"compile (V x) σ = σ x"
| "compile (C nm) σ = Clo (CML nm) [] (arity nm)"
| "compile (s • t) σ = apply (compile s σ) (compile t σ)"
| "compile (Λ t) σ = Clo (LamML (compile t (VML 0 ## σ))) [] 1"
text{* Compiler for open terms and for terms with fixed free variables: *}
definition "comp_open t = compile t VML"
abbreviation "comp_fixed t ≡ compile t (λi. VU i [])"
text{* Compiled rules: *}
lemma size_args_less_size_tm[simp]: "s ∈ set (args_tm t) ==> size s < size t"
by(induct t) auto
fun comp_pat where
"comp_pat t =
(case head_tm t of
C nm => CU nm (map comp_pat (rev (args_tm t)))
| V X => VML X)"
declare comp_pat.simps[simp del] size_args_less_size_tm[simp del]
lemma comp_pat_V[simp]: "comp_pat(V X) = VML X"
by(simp add:comp_pat.simps)
lemma comp_pat_C[simp]:
"comp_pat(C nm •• ts) = CU nm (map comp_pat (rev ts))"
by(simp add:comp_pat.simps)
lemma comp_pat_C_Nil[simp]: "comp_pat(C nm) = CU nm []"
by(simp add:comp_pat.simps)
defs compR_def:
"compR ≡ (λ(nm,ts,t). (nm, map comp_pat (rev ts), comp_open t)) ` R"
lemma fv_ML_comp_open: "pure t ==> fvML(comp_open t) = fv t"
by(induct t pred:pure) (simp_all add:comp_open_def)
lemma fv_ML_comp_pat: "pattern t ==> fvML(comp_pat t) = fv t"
by(induct t pred:pattern)(simp_all add:comp_open_def)
lemma fv_compR_aux:
"(nm,ts,t') : R ==> x ∈ fvML (comp_open t')
==> ∃t∈set ts. x ∈ fvML(comp_pat t)"
apply(frule pure_R)
apply(simp add:fv_ML_comp_open)
apply(frule (1) fv_R)
apply clarsimp
apply(rule bexI) prefer 2 apply assumption
apply(drule pattern_R)
apply(simp add:fv_ML_comp_pat)
done
lemma fv_compR:
"(nm,vs,v) : compR ==> x ∈ fvML v ==> ∃u∈set vs. x ∈ fvML u"
by(fastsimp simp add:compR_def image_def dest: fv_compR_aux)
lemma lift_compile:
"pure t ==> ∀σ k. lift k (compile t σ) = compile t (lift k o σ)"
apply(induct pred:pure)
apply simp_all
apply clarsimp
apply(rule_tac f = "compile t" in arg_cong)
apply(rule ext)
apply (clarsimp simp: lift_lift_ML_comm)
done
lemma subst_ML_compile:
"pure t ==> substML σ' (compile t σ) = compile t (substML σ' o σ)"
apply(induct arbitrary: σ σ' pred:pure)
apply simp_all
apply(erule_tac x="VML 0 ## σ'" in meta_allE)
apply(erule_tac x= "VML 0 ## (liftML 0 o σ)" in meta_allE)
apply(rule_tac f = "compile t" in arg_cong)
apply(rule ext)
apply (auto simp add:subst_ML_ext lift_ML_subst_ML)
done
theorem kernel_compile:
"pure t ==> ∀i. σ i = VU i [] ==> (compile t σ)! = t"
apply(induct arbitrary: σ pred:pure)
apply simp_all
apply(subst lift_compile) apply simp
apply(subst subst_ML_compile) apply simp
apply(subgoal_tac "(substML (λn. if n = 0 then VU 0 [] else VML (n - 1)) o
(lift 0 o VML 0 ## σ)) = (λa. VU a [])")
apply(simp)
apply(rule ext)
apply(simp)
done
lemma kernel_subst_ML_pat:
"pure t ==> pattern t ==> ∀i. closedML 0 (σ i) ==>
(substML σ (comp_pat t))! = subst (kernel o σ) t"
apply(induct arbitrary: σ pred:pure)
apply simp_all
apply(frule pattern_At_decomp)
apply(frule pattern_AtD12)
apply clarsimp
apply(subst comp_pat.simps)
apply(simp add: rev_map)
done
lemma kernel_subst_ML:
"pure t ==> ∀i. closedML 0 (σ i) ==>
(substML σ (comp_open t))! = subst (kernel o σ) t"
proof(induct arbitrary: σ pred:pure)
case (Lam t)
have "lift 0 o VML = VML" by (simp add:expand_fun_eq)
hence "(substML σ (comp_open (Λ t)))! =
Λ (substML (lift 0 o VML 0 ## σ) (comp_open t)[VU 0 []/0]!)"
using Lam by(simp add: lift_subst_ML comp_open_def lift_compile)
also have "… = Λ (subst (V 0 ## (kernel o σ)) t)" using Lam
by(simp add: subst_ML_comp subst_ext kernel_lift_tm)
also have "… = subst (kernel o σ) (Λ t)" by simp
finally show ?case .
qed (simp_all add:comp_open_def)
lemma kernel_subst_ML_pat_map:
"∀t ∈ set ts. pure t ==> patterns ts ==> ∀i. closedML 0 (σ i) ==>
map kernel (map (substML σ) (map comp_pat ts)) =
map (subst (kernel o σ)) ts"
by(simp add:list_eq_iff_nth_eq kernel_subst_ML_pat)
lemma compR_Red_tm: "(nm, vs, v) : compR ==> ∀ i. closedML 0 (σ i)
==> C nm •• (map (substML σ) (rev vs))! ->* (substML σ v)!"
apply(auto simp add:compR_def rev_map simp del: map_map)
apply(frule pure_R)
apply(subst kernel_subst_ML) apply fast+
apply(subst kernel_subst_ML_pat_map)
apply fast
apply(fast dest:pattern_R)
apply assumption
apply(rule r_into_rtrancl)
apply(erule Red_tm.intros)
done
section "Correctness"
lemma eq_Red_tm_trans: "s = t ==> t -> t' ==> s -> t'"
by simp
text{* Soundness of reduction: *}
theorem fixes v :: ml shows Red_ml_sound:
"v => v' ==> closedML 0 v ==> v! ->* v'! ∧ closedML 0 v'" and
"vs => vs' ==> ∀v∈set vs. closedML 0 v ==>
vs! ->* vs'! ∧ (∀v'∈set vs'. closedML 0 v')"
proof(induct rule:Red_ml_Red_ml_list.inducts)
fix u v
let ?v = "AML (LamML u) [v]"
assume cl: "closedML 0 (AML (LamML u) [v])"
let ?u' = "(lift_ml 0 u)[VU 0 []/0]"
have "?v! = (Λ((?u')!)) • (v !)" by simp
also have "… -> (?u' !)[v!/0]" (is "_ -> ?R") by(rule Red_tm.intros)
also(eq_Red_tm_trans) have "?R = u[v/0]!" using cl
apply(cut_tac u = "u" and v = "v" in kernel_subst1)
apply(simp_all)
done
finally have "kernel(AML (LamML u) [v]) ->* kernel(u[v/0])" (is ?A)
by(rule r_into_rtrancl)
moreover have "closedML 0 (u[v/0])" (is "?C")
proof -
let ?σ = "λn. if n = 0 then v else VML (n - 1)"
let ?σ' = "λn. v"
have clu: "closedML (Suc 0) u" and clv: "closedML 0 v" using cl by simp+
have "closedML 0 (substML ?σ' u)"
by (metis closed_ML_subst_ML clv)
hence "closedML 0 (substML ?σ u)"
using subst_ML_coincidence[OF clu, of ?σ ?σ'] by auto
thus ?thesis by simp
qed
ultimately show "?A ∧ ?C" ..
next
fix σ :: "nat => ml" and nm vs v
assume σ: "∀i. closedML 0 (σ i)" and compR: "(nm, vs, v) ∈ compR"
have "map (subst V) (map (substML σ) (rev vs)!) = map (substML σ) (rev vs)!"
by(simp add:list_eq_iff_nth_eq subst_V_kernel closed_ML_subst_ML[OF σ])
with compR_Red_tm[OF compR σ]
have "(C nm) •• ((map (substML σ) (rev vs)) !) ->* (substML σ v)!"
by(simp add:subst_V_kernel closed_ML_subst_ML[OF σ])
hence "AML (CML nm) (map (substML σ) vs)! ->* substML σ v!" (is ?A)
by(simp add:rev_map)
moreover
have "closedML 0 (substML σ v)" (is ?C) by(metis closed_ML_subst_ML σ)
ultimately show "?A ∧ ?C" ..
qed (auto simp:Reds_tm_list_foldl_At Red_tm_rev rev_map[symmetric])
theorem Red_term_sound:
"t => t' ==> closedML 0 t ==> kernelt t ->* kernelt t' ∧ closedML 0 t'"
proof(induct rule:Red_term.inducts)
case term_C thus ?case
by (auto simp:closed_tm_ML_foldl_At)
next
case term_V thus ?case
by (auto simp:closed_tm_ML_foldl_At)
next
case (term_Clo vf vs n)
hence "(lift 0 vf!) •• map kernel (rev (map (lift 0) vs))
= lift 0 (vf! •• (rev vs)!)"
apply (simp add:kernel_lift_tm list_eq_iff_nth_eq)
apply(simp add:rev_nth rev_map kernel_lift_tm)
done
hence "term (Clo vf vs n)! ->*
Λ (term (apply (lift 0 (Clo vf vs n)) (VU 0 [])))!"
using term_Clo
by(simp del:lift_foldl_At add: r_into_rtrancl Red_tm.intros(2))
moreover
have "closedML 0 (Λ (term (apply (lift 0 (Clo vf vs n)) (VU 0 []))))"
using term_Clo by simp
ultimately show ?case ..
next
case ctxt_term thus ?case by simp (metis Red_ml_sound)
qed auto
corollary kernel_inv:
"(t :: tm) =>* t' ==> closedML 0 t ==> t! ->* t'! ∧ closedML 0 t' "
apply(induct rule: rtrancl.induct)
apply (metis rtrancl_eq_or_trancl)
apply (metis Red_term_sound rtrancl_trans)
done
lemma closed_ML_compile:
"pure t ==> ∀i. closedML n (σ i) ==> closedML n (compile t σ)"
proof(induct arbitrary:n σ pred:pure)
case (Lam t)
have 1: "∀i. closedML (Suc n) ((VML 0 ## σ) i)" using Lam(3-)
by (auto simp: closed_ML_Suc)
show ?case using Lam(2)[OF 1] by (simp del:apply_cons_ML)
qed simp_all
theorem nbe_correct: fixes t :: tm
assumes "pure t" and "term (comp_fixed t) =>* t'" and "pure t'" shows "t ->* t'"
proof -
have ML_cl: "closedML 0 (term (comp_fixed t))"
by (simp add: closed_ML_compile[OF `pure t`])
have "(term (comp_fixed t))! = t"
using kernel_compile[OF `pure t`] by simp
moreover have "term (comp_fixed t)! ->* t'!"
using kernel_inv[OF assms(2) ML_cl] by auto
ultimately have "t ->* t'!" by simp
thus ?thesis using kernel_pure[OF `pure t'`] by simp
qed
section "Normal Forms"
inductive normal :: "tm => bool" where
"∀t∈set ts. normal t ==> normal(V x •• ts)" |
"normal t ==> normal(Λ t)" |
"∀t∈set ts. normal t ==>
∀σ. ∀(nm',ls,r)∈R. ¬(nm = nm' ∧ take (size ls) ts = map (subst σ) ls)
==> normal(C nm •• ts)"
fun C_normal_ML :: "ml => bool" ("C'_normalML") where
"C_normalML(CU nm vs) =
((∀v∈set vs. C_normalML v) ∧ no_match_compR nm vs)" |
"C_normalML (CML _) = True" |
"C_normalML (VML _) = True" |
"C_normalML (AML v vs) = (C_normalML v ∧ (∀v ∈ set vs. C_normalML v))" |
"C_normalML (LamML v) = C_normalML v" |
"C_normalML (VU x vs) = (∀v ∈ set vs. C_normalML v)" |
"C_normalML (Clo v vs _) = (C_normalML v ∧ (∀v ∈ set vs. C_normalML v))" |
"C_normalML (apply u v) = (C_normalML u ∧ C_normalML v)"
fun size_tm :: "tm => nat" where
"size_tm (C _) = 1" |
"size_tm (At s t) = size_tm s + size_tm t + 1" |
"size_tm _ = 0"
lemma size_tm_foldl_At: "size_tm(t •• ts) = size_tm t + list_size size_tm ts"
by (induct ts arbitrary:t) auto
lemma termination_no_match:
"i < length ss ==> ss ! i = C nm •• ts
==> listsum (map size_tm ts) < listsum (map size_tm ss)"
apply(subgoal_tac "C nm •• ts : set ss")
apply(drule listsum_map_remove1[of _ _ size_tm])
apply(simp add:size_tm_foldl_At list_size_conv_listsum)
apply (metis in_set_conv_nth)
done
declare conj_cong [fundef_cong]
function no_match :: "tm list => tm list => bool" where
"no_match ps ts =
(∃i < min (size ts) (size ps).
∃nm nm' rs rs'. ps!i = (C nm) •• rs ∧ ts!i = (C nm') •• rs' ∧
(nm=nm' --> no_match rs rs'))"
by pat_completeness auto
termination
apply(relation "measure(%(ts::tm list,_). ∑t\<leftarrow>ts. size_tm t)")
apply (auto simp:termination_no_match)
done
declare no_match.simps[simp del]
abbreviation
"no_match_R nm ts ≡ ∀(nm',ps,t)∈ R. nm=nm' --> no_match ps ts"
lemma no_match: "no_match ps ts ==> ¬(∃σ. map (subst σ) ps = ts)"
proof(induct ps ts rule:no_match.induct)
case (1 ps ts)
thus ?case
apply auto
apply(subst (asm) no_match.simps[of ps])
apply fastsimp
done
qed
lemma no_match_take: "no_match ps ts ==> no_match ps (take (size ps) ts)"
apply(subst (asm) no_match.simps)
apply(subst no_match.simps)
apply fastsimp
done
fun dterm_ML :: "ml => tm" ("dtermML") where
"dtermML (CU nm vs) = C nm •• map dtermML (rev vs)" |
"dtermML _ = V 0"
fun dterm :: "tm => tm" where
"dterm (V n) = V n" |
"dterm (C nm) = C nm" |
"dterm (s • t) = dterm s • dterm t" |
"dterm (Λ t) = Λ (dterm t)" |
"dterm (term v) = dtermML v"
lemma dterm_pure[simp]: "pure t ==> dterm t = t"
by (induct pred:pure) auto
lemma map_dterm_pure[simp]: "∀t∈set ts. pure t ==> map dterm ts = ts"
by (induct ts) auto
lemma map_dterm_term[simp]: "map dterm (map term vs) = map dtermML vs"
by (induct vs) auto
lemma dterm_foldl_At[simp]: "dterm(t •• ts) = dterm t •• map dterm ts"
by(induct ts arbitrary: t) auto
lemma no_match_coincide:
"no_matchML ps vs ==>
no_match (map dtermML (rev ps)) (map dtermML (rev vs))"
apply(induct ps vs rule:no_match_ML.induct)
apply(rotate_tac 1)
apply(subst (asm) no_match_ML.simps)
apply (elim exE conjE)
apply(case_tac "nm=nm'")
prefer 2
apply(subst no_match.simps)
apply(rule_tac x=i in exI)
apply rule
apply (simp (no_asm))
apply (metis min_less_iff_conj)
apply(simp add:min_less_iff_conj nth_map)
apply safe
apply(erule_tac x=i in meta_allE)
apply(erule_tac x=nm' in meta_allE)
apply(erule_tac x=nm' in meta_allE)
apply(erule_tac x="vs" in meta_allE)
apply(erule_tac x="vs'" in meta_allE)
apply(subst no_match.simps)
apply(rule_tac x=i in exI)
apply rule
apply (simp (no_asm))
apply (metis min_less_iff_conj)
apply(rule_tac x=nm' in exI)
apply(rule_tac x=nm' in exI)
apply(rule_tac x="map dtermML (rev vs)" in exI)
apply(rule_tac x="map dtermML (rev vs')" in exI)
apply(simp)
done
lemma dterm_ML_comp_patD:
"pattern t ==> dtermML (comp_pat t) = C nm •• rs ==> ∃ts. t = C nm •• ts"
by(induct pred:pattern) simp_all
lemma no_match_R_coincide_aux[rule_format]: "patterns ts ==>
no_match (map (dtermML o comp_pat) ts) rs --> no_match ts rs"
apply(induct ts rs rule:no_match.induct)
apply(subst (1 2) no_match.simps)
apply clarsimp
apply(rule_tac x=i in exI)
apply simp
apply(rule_tac x=nm in exI)
apply(cut_tac t = "ps!i" in dterm_ML_comp_patD, simp, assumption)
apply(clarsimp)
apply(erule_tac x = i in meta_allE)
apply(erule_tac x = nm' in meta_allE)
apply(erule_tac x = nm' in meta_allE)
apply(erule_tac x = tsa in meta_allE)
apply(erule_tac x = rs' in meta_allE)
apply (simp add:rev_map)
apply (metis in_set_conv_nth pattern_At_vecD)
done
lemma no_match_R_coincide:
"no_match_compR nm (rev vs) ==> no_match_R nm (map dtermML vs)"
apply auto
apply(drule_tac x="(nm, map comp_pat (rev aa), comp_open b)" in bspec)
unfolding compR_def
apply (simp add:image_def)
apply (force)
apply (simp)
apply(drule no_match_coincide)
apply(frule pure_R)
apply(drule pattern_R)
apply(clarsimp simp add: rev_map no_match.simps[of _ "map dtermML vs"])
apply(rule_tac x=i in exI)
apply simp
apply(cut_tac t = "aa!i" in dterm_ML_comp_patD, simp, assumption)
apply clarsimp
apply(auto simp: rev_map)
apply(rule no_match_R_coincide_aux)
prefer 2 apply assumption
apply (metis in_set_conv_nth pattern_At_vecD)
done
inductive C_normal :: "tm => bool" where
"∀t∈set ts. C_normal t ==> C_normal(V x •• ts)" |
"C_normal t ==> C_normal(Λ t)" |
"C_normalML v ==> C_normal(term v)" |
"∀t∈set ts. C_normal t ==> no_match_R nm (map dterm ts)
==> C_normal(C nm •• ts)"
declare C_normal.intros[simp]
lemma C_normal_term[simp]: "C_normal(term v) = C_normalML v"
apply (auto)
apply(erule C_normal.cases)
apply auto
done
lemma [simp]: "C_normal(Λ t) = C_normal t"
apply (auto)
apply(erule C_normal.cases)
apply auto
done
lemma [simp]: "C_normal(V x)"
using C_normal.intros(1)[of "[]" x]
by simp
lemma [simp]: "dterm (dtermML v) = dtermML v"
apply(induct v rule:dterm_ML.induct)
apply simp_all
done
lemma "u=>(v::ml) ==> True" and
Red_ml_list_length: "vs => vs' ==> length vs = length vs'"
by(induct rule: Red_ml_Red_ml_list.inducts) simp_all
lemma "(v::ml) => v' ==> True" and
Red_ml_list_nth: "(vs::ml list) => vs'
==> ∃v' k. k<size vs ∧ vs!k => v' ∧ vs' = vs[k := v']"
apply (induct rule: Red_ml_Red_ml_list.inducts)
apply (auto split:nat.splits)
done
lemma Red_ml_list_pres_no_match:
"no_matchML ps vs ==> vs => vs' ==> no_matchML ps vs'"
proof(induct ps vs arbitrary: vs' rule:no_match_ML.induct)
case (1 vs os)
show ?case using 1(2-3)
apply-
apply(frule Red_ml_list_length)
apply(rotate_tac -2)
apply(subst (asm) no_match_ML.simps)
apply clarify
apply(rename_tac i nm nm' us us')
apply(subst no_match_ML.simps)
apply(rule_tac x=i in exI)
apply (simp)
apply(drule Red_ml_list_nth)
apply clarify
apply(rename_tac k)
apply(case_tac "k = length os - Suc i")
prefer 2
apply(rule_tac x=nm' in exI)
apply(rule_tac x=us' in exI)
apply (simp add: rev_nth nth_list_update)
apply (simp add: rev_nth)
apply(erule Red_ml.cases)
apply simp_all
apply(fastsimp intro: 1(1) simp add:rev_nth)
done
qed
lemma no_match_ML_subst_ML[rule_format]:
"∀v∈set vs. ∀x∈fvML v. C_normalML (σ x) ==>
no_matchML ps vs --> no_matchML ps (map (substML σ) vs)"
apply(induct ps vs rule:no_match_ML.induct)
apply simp
apply(subst (1 2) no_match_ML.simps)
apply clarsimp
apply(rule_tac x=i in exI)
apply simp
apply(rule_tac x=nm' in exI)
apply(rule_tac x="map (substML σ) vs'" in exI)
apply (auto simp:rev_nth)
apply(erule_tac x = i in meta_allE)
apply(erule_tac x = nm' in meta_allE)
apply(erule_tac x = nm' in meta_allE)
apply(erule_tac x = vs in meta_allE)
apply(erule_tac x = vs' in meta_allE)
apply simp
apply (metis UN_I fv_ML.simps(5) in_set_conv_nth length_rev rev_nth set_rev)
done
lemma lift_is_CUD:
"liftML k v = CU nm vs' ==> ∃vs. v = CU nm vs ∧ vs' = map (liftML k) vs"
by(cases v) auto
lemma no_match_ML_lift_ML:
"no_matchML ps (map (liftML k) vs) = no_matchML ps vs"
apply(induct ps vs rule:no_match_ML.induct)
apply simp
apply(subst (1 2) no_match_ML.simps)
apply rule
apply clarsimp
apply(rule_tac x=i in exI)
apply (simp add:rev_nth)
apply(drule lift_is_CUD)
apply fastsimp
apply clarsimp
apply(rule_tac x=i in exI)
apply simp
apply(rule_tac x=nm' in exI)
apply(rule_tac x="map (liftML k) vs'" in exI)
apply (fastsimp simp:rev_nth)
done
lemma C_normal_ML_lift_ML: "C_normalML(liftML k v) = C_normalML v"
by(induct v arbitrary: k rule:C_normal_ML.induct)(auto simp:no_match_ML_lift_ML)
lemma no_match_compR_Cons:
"no_match_compR nm vs ==> no_match_compR nm (v # vs)"
apply auto
apply(drule bspec, assumption)
apply simp
apply(subst (asm) no_match_ML.simps)
apply(subst no_match_ML.simps)
apply clarsimp
apply(rule_tac x=i in exI)
apply (simp add:nth_append)
done
lemma C_normal_ML_comp_open: "pure t ==> C_normalML(comp_open t)"
by (induct pred:pure) (auto simp:comp_open_def)
lemma C_normal_compR_rhs: "(nm, vs, v) ∈ compR ==> C_normalML v"
by(auto simp: compR_def image_def Bex_def pure_R C_normal_ML_comp_open)
lemma C_normal_ML_subst_ML:
"C_normalML (substML σ v) ==> (∀x∈fvML v. C_normalML (σ x))"
proof(induct σ v rule:subst_ML.induct)
case 4 thus ?case
by(simp del:apply_cons_ML)(force simp add: C_normal_ML_lift_ML)
qed auto
lemma C_normal_ML_subst_ML_iff: "C_normalML v ==>
C_normalML (substML σ v) <-> (∀x∈fvML v. C_normalML (σ x))"
proof(induct σ v rule:subst_ML.induct)
case 4 thus ?case
by(simp del:apply_cons_ML)(force simp add: C_normal_ML_lift_ML)
next
case 5 thus ?case by simp (blast intro: no_match_ML_subst_ML)
qed auto
lemma C_normal_ML_inv: "v => v' ==> C_normalML v ==> C_normalML v'" and
"vs => vs' ==> ∀v∈set vs. C_normalML v ==> ∀v'∈set vs'. C_normalML v'"
apply(induct rule:Red_ml_Red_ml_list.inducts)
apply(simp_all add: C_normal_ML_subst_ML_iff)
apply(metis C_normal_ML_subst_ML C_normal_compR_rhs
fv_compR C_normal_ML_subst_ML_iff)
apply(blast intro!:no_match_compR_Cons)
apply(blast dest:Red_ml_list_pres_no_match)
done
lemma Red_term_hnf_induct[consumes 1]:
assumes "(t::tm) => t'"
"!!nm vs ts. P ((term (CU nm vs)) •• ts) ((C nm •• map term (rev vs)) •• ts)"
"!!x vs ts. P (term (VU x vs) •• ts) ((V x •• map term (rev vs)) •• ts)"
"!!vf vs n ts.
P (term (Clo vf vs n) •• ts)
((Λ (term (apply (lift 0 (Clo vf vs n)) (VU 0 [])))) •• ts)"
"!!t t' ts. [|t => t'; P t t'|] ==> P (Λ t •• ts) (Λ t' •• ts)"
"!!v v' ts. v => v' ==> P (term v •• ts) (term v' •• ts)"
"!!x i t' ts. i<size ts ==> ts!i => t' ==> P (ts!i) (t')
==> P (V x •• ts) (V x •• ts[i:=t'])"
"!!nm i t' ts. i<size ts ==> ts!i => t' ==> P (ts!i) (t')
==> P (C nm •• ts) (C nm •• ts[i:=t'])"
"!!t i t' ts. i<size ts ==> ts!i => t' ==> P (ts!i) (t')
==> P (Λ t •• ts) (Λ t •• ts[i:=t'])"
"!!v i t' ts. i<size ts ==> ts!i => t' ==> P (ts!i) (t')
==> P (term v •• ts) (term v •• (ts[i:=t']))"
shows "P t t'"
proof-
{ fix ts from assms have "P (t •• ts) (t' •• ts)"
proof(induct arbitrary: ts rule:Red_term.induct)
case term_C thus ?case by metis
next
case term_V thus ?case by metis
next
case term_Clo thus ?case by metis
next
case ctxt_Lam thus ?case by simp (metis foldl_Nil)
next
case (ctxt_At1 s s' t ts)
thus ?case using ctxt_At1(2)[of "t#ts"] by simp
next
case (ctxt_At2 t t' s ts)
{ fix n rs assume "s = V n •• rs"
hence ?case using ctxt_At2(8)[of "size rs" "rs @ t # ts" t' n] ctxt_At2
by simp (metis foldl_Nil)
} moreover
{ fix nm rs assume "s = C nm •• rs"
hence ?case using ctxt_At2(9)[of "size rs" "rs @ t # ts" t' nm] ctxt_At2
by simp (metis foldl_Nil)
} moreover
{ fix r rs assume "s = Λ r •• rs"
hence ?case using ctxt_At2(10)[of "size rs" "rs @ t # ts" t'] ctxt_At2
by simp (metis foldl_Nil)
} moreover
{ fix v rs assume "s = term v •• rs"
hence ?case using ctxt_At2(11)[of "size rs" "rs @ t # ts" t'] ctxt_At2
by simp (metis foldl_Nil)
} ultimately show ?case using tm_vector_cases[of s] by blast
qed
}
from this[of "[]"] show ?thesis by simp
qed
corollary Red_term_hnf_cases[consumes 1]:
assumes "(t::tm) => t'"
"!!nm vs ts.
t = term (CU nm vs) •• ts ==> t' = (C nm •• map term (rev vs)) •• ts ==> P"
"!!x vs ts.
t = term (VU x vs) •• ts ==> t' = (V x •• map term (rev vs)) •• ts ==> P"
"!!vf vs n ts. t = term (Clo vf vs n) •• ts ==>
t' = Λ (term (apply (lift 0 (Clo vf vs n)) (VU 0 []))) •• ts ==> P"
"!!s s' ts. t = Λ s •• ts ==> t' = Λ s' •• ts ==> s => s' ==> P"
"!!v v' ts. t = term v •• ts ==> t' = term v' •• ts ==> v => v' ==> P"
"!!x i r' ts. i<size ts ==> ts!i => r'
==> t = V x •• ts ==> t' = V x •• ts[i:=r'] ==> P"
"!!nm i r' ts. i<size ts ==> ts!i => r'
==> t = C nm •• ts ==> t' = C nm •• ts[i:=r'] ==> P"
"!!s i r' ts. i<size ts ==> ts!i => r'
==> t = Λ s •• ts ==> t' = Λ s •• ts[i:=r'] ==> P"
"!!v i r' ts. i<size ts ==> ts!i => r'
==> t = term v •• ts ==> t' = term v •• (ts[i:=r']) ==> P"
shows "P" using assms
apply -
apply(induct rule:Red_term_hnf_induct)
apply metis+
done
lemma [simp]: "C_normal(term v •• ts) <-> C_normalML v ∧ ts = []"
by(fastsimp elim: C_normal.cases)
lemma [simp]: "C_normal(Λ t •• ts) <-> C_normal t ∧ ts = []"
by(fastsimp elim: C_normal.cases)
lemma [simp]: "C_normal(C nm •• ts) <->
(∀t∈set ts. C_normal t) ∧ no_match_R nm (map dterm ts)"
by(fastsimp elim: C_normal.cases)
lemma [simp]: "C_normal(V x •• ts) <-> (∀t ∈ set ts. C_normal t)"
by(fastsimp elim: C_normal.cases)
lemma no_match_ML_lift:
"no_matchML ps vs --> no_matchML ps (map (lift k) vs)"
apply(induct ps vs rule:no_match_ML.induct)
apply simp
apply(subst (1 2) no_match_ML.simps)
apply clarsimp
apply(rule_tac x=i in exI)
apply simp
apply(rule_tac x=nm' in exI)
apply(rule_tac x="map (lift k) vs'" in exI)
apply (fastsimp simp:rev_nth)
done
lemma no_match_compR_lift:
"no_match_compR nm vs ==> no_match_compR nm (map (lift k) vs)"
by (fastsimp simp: no_match_ML_lift)
lemma [simp]: "C_normalML v ==> C_normalML(lift k v)"
apply(induct v arbitrary:k rule:lift_ml.induct)
apply(simp_all add:no_match_compR_lift)
done
declare [[simp_depth_limit = 10]]
lemma Red_term_pres_no_match:
"[|i < length ts; ts ! i => t'; no_match ps dts; dts = (map dterm ts)|]
==> no_match ps (map dterm (ts[i := t']))"
proof(induct ps dts arbitrary: ts i t' rule:no_match.induct)
case (1 ps dts ts i t')
from `no_match ps dts` `dts = map dterm ts`
obtain j nm nm' rs rs' where ob: "j < size ts" "j < size ps"
"ps!j = C nm •• rs" "dterm (ts!j) = C nm' •• rs'"
"nm = nm' --> no_match rs rs'"
by (subst (asm) no_match.simps) fastsimp
show ?case
proof (subst no_match.simps)
show "∃k<min (length (map dterm (ts[i := t']))) (length ps).
∃nm nm' rs rs'. ps!k = C nm •• rs ∧
map dterm (ts[i := t']) ! k = C nm' •• rs' ∧
(nm = nm' --> no_match rs rs')"
(is "∃k < ?m. ?P k")
proof-
{ assume [simp]: "j=i"
have "∃rs'. dterm t' = C nm' •• rs' ∧ (nm = nm' --> no_match rs rs')"
using `ts ! i => t'`
proof(cases rule:Red_term_hnf_cases)
case (5 v v' ts'')
then obtain vs where [simp]:
"v = CU nm' vs" "rs' = map dtermML (rev vs) @ map dterm ts''"
using ob by(cases v) auto
obtain vs' where [simp]: "v' = CU nm' vs'" "vs => vs'"
using `v=>v'` by(rule Red_ml.cases) auto
obtain v' k where [arith]: "k<size vs" and "vs!k => v'"
and [simp]: "vs' = vs[k := v']"
using Red_ml_list_nth[OF `vs=>vs'`] by fastsimp
show ?thesis (is "∃rs'. ?P rs' ∧ ?Q rs'")
proof
let ?rs' = "map dterm ((map term (rev vs) @ ts'')[(size vs - k - 1):=term v'])"
have "?P ?rs'" using ob 5
by(simp add: list_update_append map_update[symmetric] rev_update)
moreover have "?Q ?rs'"
apply rule
apply(rule "1.hyps"[OF _ ob(3)])
using "1.prems" 5 ob
apply (auto simp:nth_append rev_nth ctxt_term[OF `vs!k => v'`] simp del: map_map)
done
ultimately show "?P ?rs' ∧ ?Q ?rs'" ..
qed
next
case (7 nm'' k r' ts'')
show ?thesis (is "∃rs'. ?P rs'")
proof
show "?P(map dterm (ts''[k := r']))"
using 7 ob
apply clarsimp
apply(rule "1.hyps"[OF _ ob(3)])
using 7 "1.prems" ob apply auto
done
qed
next
case (9 v k r' ts'')
then obtain vs where [simp]: "v = CU nm' vs" "rs' = map dtermML (rev vs) @ map dterm ts''"
using ob by(cases v) auto
show ?thesis (is "∃rs'. ?P rs' ∧ ?Q rs'")
proof
let ?rs' = "map dterm ((map term (rev vs) @ ts'')[k+size vs:=r'])"
have "?P ?rs'" using ob 9 by (auto simp: list_update_append)
moreover have "?Q ?rs'"
apply rule
apply(rule "1.hyps"[OF _ ob(3)])
using 9 "1.prems" ob by (auto simp:nth_append simp del: map_map)
ultimately show "?P ?rs' ∧ ?Q ?rs'" ..
qed
qed (insert ob, auto simp del: map_map)
}
hence "∃rs'. dterm (ts[i := t'] ! j) = C nm' •• rs' ∧ (nm = nm' --> no_match rs rs')"
using `i < size ts` ob by(simp add:nth_list_update)
hence "?P j" using prems by auto
moreover have "j < ?m" using `j < length ts` `j < size ps` by simp
ultimately show ?thesis by blast
qed
qed
qed
declare [[simp_depth_limit = 50]]
lemma listsimps_eq_0_iff: "listsum ns = (0::nat) <-> (∀ n ∈ set ns. n = 0)"
by(metis listsum sum_eq_0_conv)
lemma elem_le_listsum_nat: "k<size ns ==> ns!k <= listsum(ns::nat list)"
apply(induct ns arbitrary: k)
apply(auto simp:nth_Cons')
apply(metis diff_less less_imp_diff_less nat_neq_iff not_less_eq trans_le_add2)
done
lemma listsum_update: "k<size ns ==>
listsum (ns[k := (n::nat)]) = listsum ns + n - ns!k"
apply(induct ns arbitrary:k)
apply (auto split:nat.split)
apply(drule elem_le_listsum_nat)
apply arith
done
lemma Red_term_pres_no_match_it:
"[| ∀ i < length ts. (ts ! i, ts' ! i) : Red_term ^^ (ns!i);
size ts' = size ts; size ns = size ts;
no_match ps (map dterm ts)|]
==> no_match ps (map dterm ts')"
proof(induct n ≡ "listsum ns" arbitrary: ts ns)
case 0
hence "∀i < size ts. ns!i = 0" by (simp add:listsimps_eq_0_iff)
with 0 show ?case by simp (metis nth_equalityI)
next
case (Suc n)
then have "listsum ns ≠ 0" by arith
then obtain k l where "k<size ts" and [simp]: "ns!k = Suc l"
by(simp add:listsimps_eq_0_iff)
(metis Suc(4) gr0_implies_Suc in_set_conv_nth)
let ?ns = "ns[k := l]"
have "n = listsum ?ns" using Suc(6) `k<size ts` `size ns = size ts`
by (simp add:listsum_update)
obtain t' where "ts!k => t'" "(t', ts'!k) : Red_term^^l"
using Suc(2) `k<size ts` `size ns = size ts` `ns!k = Suc l`
by (metis rel_pow_Suc_E2)
then have 1: "∀i<size(ts[k:=t']). (ts[k:=t']!i, ts'!i) : Red_term^^(?ns!i)"
using Suc(2) `k<size ts` `size ns = size ts`
by (auto simp add:nth_list_update)
note nm1 = Red_term_pres_no_match[OF `k<size ts` `ts!k => t'` Suc(5)]
show ?case by(rule Suc(1)[OF 1 _ _ nm1 `n = listsum ?ns`])
(simp_all add: `size ts' = size ts` `size ns = size ts`)
qed
lemma Red_term_pres_no_match_star:
assumes "∀i < length(ts::tm list). ts ! i =>* ts' ! i" and "size ts' = size ts"
and "no_match ps (map dterm ts)"
shows "no_match ps (map dterm ts')"
proof-
let ?P = "%ns. size ns = size ts ∧
(∀i < length ts.(ts!i, ts'!i) : Red_term^^(ns!i))"
have "∃ns. ?P ns" using assms(1)
by(subst Skolem_list_nth[symmetric])
(simp add:rtrancl_power)
from someI_ex[OF this] show ?thesis
by(fast intro: Red_term_pres_no_match_it[OF _ assms(2) _ assms(3)])
qed
lemma not_pure_term[simp]: "¬ pure(term v)"
proof
assume "pure(term v)" thus False
proof cases qed auto
qed
abbreviation RedMLs :: "tm list => tm list => bool" (infix "[=>*]" 50) where
"ss [=>*] ts ≡ size ss = size ts ∧ (∀i<size ss. ss!i =>* ts!i)"
fun C_U_args :: "tm => tm list" ("CU'_args") where
"CU_args(s • t) = CU_args s @ [t]" |
"CU_args(term(CU nm vs)) = map term (rev vs)" |
"CU_args _ = []"
lemma [simp]: "CU_args(C nm •• ts) = ts"
by (induct ts rule:rev_induct) auto
lemma redts_term_cong: "v =>* v' ==> term v =>* term v'"
apply(erule converse_rtrancl_induct)
apply(rule rtrancl_refl)
apply(fast intro: converse_rtrancl_into_rtrancl dest: ctxt_term)
done
lemma C_Red_term_ML:
"v => v' ==> C_normalML v ==> dtermML v = C nm •• ts
==> dtermML v' = C nm •• map dterm (CU_args(term v')) ∧
(∀t∈set(CU_args(term v)). C_normal t) ∧
CU_args(term v) [=>*] CU_args(term v') ∧
ts = map dterm (CU_args(term v))" and
"(vs:: ml list) => vs' ==> i < length vs ==> vs ! i =>* vs' ! i"
apply(induct arbitrary: nm ts and i rule:Red_ml_Red_ml_list.inducts)
apply(simp_all add:Red_ml_list_length del: map_map)
apply(frule Red_ml_list_length)
apply(simp add: redts_term_cong rev_nth del: map_map)
apply(simp add:nth_Cons' r_into_rtrancl del: map_map)
apply(simp add:nth_Cons')
done
lemma C_redt: "t => t' ==> C_normal t ==>
C_normal t' ∧ (dterm t = C nm •• ts -->
(∃ts'. ts' = map dterm (CU_args t') ∧ dterm t' = C nm •• ts' &
(∀t∈set(CU_args t). C_normal t) ∧
CU_args t [=>*] CU_args t' ∧ ts = map dterm (CU_args t)))"
apply(induct arbitrary: ts nm rule:Red_term_hnf_induct)
apply (simp_all del: map_map)
apply (metis no_match_R_coincide rev_rev_ident)
apply clarsimp
apply rule
apply (metis C_normal_ML_inv)
apply clarify
apply(drule (2) C_Red_term_ML)
apply clarsimp
apply clarsimp
apply (metis List.set.simps(2) insert_code mem_def predicate1D set_update_subset_insert)
apply clarsimp
apply(rule)
apply (metis List.set.simps(2) insert_code mem_def predicate1D set_update_subset_insert)
apply rule
apply clarify
apply(drule bspec, assumption)
apply simp
apply(subst no_match.simps)
apply(subst (asm) no_match.simps)
apply clarsimp
apply(rename_tac j nm nm' rs rs')
apply(rule_tac x=j in exI)
apply simp
apply(case_tac "i=j")
apply simp
apply(rule_tac x=nm' in exI)
apply(erule_tac x=rs' in meta_allE)
apply(erule_tac x=nm' in meta_allE)
apply clarsimp
apply(metis Red_term_pres_no_match_star)
apply (auto simp:nth_list_update)
done
lemma C_redts: "t =>* t' ==> C_normal t ==>
C_normal t' ∧ (dterm t = C nm •• ts -->
(∃ts'. dterm t' = C nm •• ts' ∧
(∀t∈set(CU_args t). C_normal t) ∧ CU_args t [=>*] CU_args t' ∧
ts' = map dterm (CU_args t') ∧ ts = map dterm (CU_args t)))"
apply(induct arbitrary: nm ts rule:converse_rtrancl_induct)
apply simp
using tm_vector_cases[of t']
apply(elim disjE)
apply clarsimp
apply clarsimp
apply clarsimp
apply clarsimp
apply(case_tac v)
apply simp
apply simp
apply simp
apply simp
apply clarsimp
apply simp
apply simp
apply simp
apply simp
apply(frule_tac nm=nm and ts="ts" in C_redt)
apply assumption
apply clarify
apply rule
apply metis
apply clarify
apply simp
apply rule
apply metis
apply simp
apply (metis rtrancl_trans)
done
lemma no_match_preserved:
"∀t∈set ts. C_normal t ==> ts [=>*] ts'
==> no_match ps os ==> os = map dterm ts ==> no_match ps (map dterm ts')"
proof(induct ps os arbitrary: ts ts' rule: no_match.induct)
case (1 ps os)
obtain i nm nm' ps' os' where "ps!i = C nm •• ps'" "i < size ps" "i < size os" "os!i = C nm' •• os'" "nm=nm' --> no_match ps' os'"
using 1(4) no_match.simps[of ps os] by fastsimp
note 1(5)[simp]
have "C_normal (ts ! i)" using 1(2) `i < size os` by auto
have "ts!i =>* ts'!i" using 1(3) `i < size os` by auto
have "dterm (ts ! i) = C nm' •• os'" using `os!i = C nm' •• os'` `i < size os`
by (simp add:nth_map)
from C_redts [OF `ts!i =>* ts'!i` `C_normal (ts!i)`] this obtain ss' rs rs' :: "tm list"
where "∀t∈set rs. C_normal t"
"dterm (ts' ! i) = C nm' •• ss'" "length rs = length rs'"
"∀i<length rs. rs ! i =>* rs' ! i" "ss' = map dterm rs'" "os' = map dterm rs"
by fastsimp
show ?case
apply(subst no_match.simps)
apply(rule_tac x=i in exI)
using prems
apply clarsimp
apply(rule 1(1)[of i nm' _ nm' "map dterm rs" rs])
apply simp_all
done
qed
lemma Lam_Red_term_itE:
"(Λ t, t') : Red_term^^i ==> ∃t''. t' = Λ t'' ∧ (t,t'') : Red_term^^i"
apply(induct i arbitrary: t')apply simp
apply(erule rel_pow_Suc_E)
apply(erule Red_term.cases)
apply (simp_all)
apply blast+
done
lemma Red_term_it: "(V x •• rs, r) : Red_term^^i
==> ∃ts is. r = V x •• ts ∧ size ts = size rs & size is = size rs ∧
(∀j<size ts. (rs!j, ts!j) : Red_term^^(is!j) ∧ is!j <= i)"
proof(induct i arbitrary:rs)
case 0
moreover
have "∃is. length is = length rs ∧
(∀j<size rs. (rs!j, rs!j) ∈ Red_term ^^ is!j ∧ is!j = 0)" (is "∃is. ?P is")
proof
show "?P(replicate (size rs) 0)" by simp
qed
ultimately show ?case by auto
next
case (Suc i rs)
from `(V x •• rs, r) ∈ Red_term ^^ Suc i`
obtain r' where r': "V x •• rs => r'" and "(r',r) ∈ Red_term ^^ i"
by (metis rel_pow_Suc_D2)
from r' have "∃k<size rs. ∃s. rs!k => s ∧ r' = V x •• rs[k:=s]"
proof(induct rs arbitrary: r' rule:rev_induct)
case Nil thus ?case by(fastsimp elim: Red_term.cases)
next
case (snoc r rs)
hence "(V x •• rs) • r => r'" by simp
thus ?case
proof(cases rule:Red_term.cases)
case (ctxt_At1 s s' t)
then obtain k s'' where "k<length rs" "rs ! k => s''" "s' = V x •• rs[k := s'']"
using snoc(1) by force
then show ?thesis (is "∃k < ?n. ∃s. ?P k s")
proof-
have "k<?n ∧ ?P k s''" using prems
by (simp add:nth_append) (metis last_snoc butlast_snoc list_update_append1)
thus ?thesis by blast
qed
next
case (ctxt_At2 t t' s)
then show ?thesis (is "∃k < ?n. ∃s. ?P k s")
proof-
have "size rs<?n ∧ ?P (size rs) t'" using prems by simp
thus ?thesis by blast
qed
qed auto
qed
then obtain k s where "k<size rs" "rs!k => s" and [simp]: "r' = V x •• rs[k:=s]" by metis
from Suc(1)[of "rs[k:=s]"] `(r',r) ∈ Red_term ^^ i`
show ?case using `k<size rs` `rs!k => s`
apply auto
apply(rule_tac x="is[k := Suc(is!k)]" in exI)
apply (auto simp:nth_list_update)
apply(erule_tac x=k in allE)
apply auto
apply (metis rel_pow_Suc_I2 relpow.simps(2))
done
qed
lemma C_Red_term_it: "(C nm •• rs, r) : Red_term^^i
==> ∃ts is. r = C nm •• ts ∧ size ts = size rs ∧ size is = size rs ∧
(∀j<size ts. (rs!j, ts!j) ∈ Red_term^^(is!j) ∧ is!j ≤ i)"
proof(induct i arbitrary:rs)
case 0
moreover
have "∃is. length is = length rs ∧
(∀j<size rs. (rs!j, rs!j) ∈ Red_term ^^ is!j ∧ is!j = 0)" (is "∃is. ?P is")
proof
show "?P(replicate (size rs) 0)" by simp
qed
ultimately show ?case by auto
next
case (Suc i rs)
from `(C nm •• rs, r) ∈ Red_term ^^ Suc i`
obtain r' where r': "C nm •• rs => r'" and "(r',r) ∈ Red_term ^^ i"
by (metis rel_pow_Suc_D2)
from r' have "∃k<size rs. ∃s. rs!k => s ∧ r' = C nm •• rs[k:=s]"
proof(induct rs arbitrary: r' rule:rev_induct)
case Nil thus ?case by(fastsimp elim: Red_term.cases)
next
case (snoc r rs)
hence "(C nm •• rs) • r => r'" by simp
thus ?case
proof(cases rule:Red_term.cases)
case (ctxt_At1 s s' t)
then obtain k s'' where "k<length rs" "rs ! k => s''" "s' = C nm •• rs[k := s'']"
using snoc(1) by force
then show ?thesis (is "∃k < ?n. ∃s. ?P k s")
proof-
have "k<?n ∧ ?P k s''" using prems
by (simp add:nth_append) (metis last_snoc butlast_snoc list_update_append1)
thus ?thesis by blast
qed
next
case (ctxt_At2 t t' s)
then show ?thesis (is "∃k < ?n. ∃s. ?P k s")
proof-
have "size rs<?n ∧ ?P (size rs) t'" using prems by simp
thus ?thesis by blast
qed
qed auto
qed
then obtain k s where "k<size rs" "rs!k => s" and [simp]: "r' = C nm •• rs[k:=s]" by metis
from Suc(1)[of "rs[k:=s]"] `(r',r) ∈ Red_term ^^ i`
show ?case using `k<size rs` `rs!k => s`
apply auto
apply(rule_tac x="is[k := Suc(is!k)]" in exI)
apply (auto simp:nth_list_update)
apply(erule_tac x=k in allE)
apply auto
apply (metis rel_pow_Suc_I2 relpow.simps(2))
done
qed
lemma pure_At[simp]: "pure(s • t) <-> pure s ∧ pure t"
by(fastsimp elim: pure.cases)
lemma pure_foldl_At[simp]: "pure(s •• ts) <-> pure s ∧ (∀t∈set ts. pure t)"
by(induct ts arbitrary: s) auto
lemma nbe_C_normal_ML:
assumes "term v =>* t'" "C_normalML v" "pure t'" shows "normal t'"
proof -
{ fix t t' i v
assume "(t,t') : Red_term^^i"
hence "t = term v ==> C_normalML v ==> pure t' ==> normal t'"
proof(induct i arbitrary: t t' v rule:less_induct)
case (less k)
show ?case
proof (cases k)
case 0 thus ?thesis using less by auto
next
case (Suc i)
then obtain i' s where "t => s" "(s,t') : Red_term^^i'" and [arith]: "i' <= i"
by (metis eq_imp_le less(5) Suc rel_pow_Suc_D2)
hence "term v => s" using Suc less by simp
thus ?thesis
proof cases
case (term_C nm vs)
have 0:"no_match_compR nm vs" using prems by auto
let ?n = "size vs"
have 1: "(C nm •• map term (rev vs),t') : Red_term^^i'"
using term_C `(s,t') : Red_term^^i'` by simp
with C_Red_term_it[OF 1]
obtain ts ks where [simp]: "t' = C nm •• ts"
and sz: "size ts = ?n ∧ size ks = ?n ∧
(∀i<?n. (term((rev vs)!i), ts!i) : Red_term^^(ks!i) ∧ ks ! i ≤ i')"
by(auto cong:conj_cong)
have pure_ts: "∀t∈set ts. pure t" using `pure t'` by simp
{ fix i assume "i<size vs"
moreover hence "(term((rev vs)!i), ts!i) : Red_term^^(ks!i)" by(metis sz)
ultimately have "normal (ts!i)"
apply -
apply(rule less(1))
prefer 5 apply assumption
using sz Suc apply fastsimp
apply(rule refl)
using less term_C
apply(auto)
apply (metis in_set_conv_nth length_rev set_rev)
apply (metis in_set_conv_nth pure_ts sz)
done
} note 2 = this
have 3: "no_match_R nm (map dterm (map term (rev vs)))"
apply(subst map_dterm_term)
apply(rule no_match_R_coincide) using 0 by simp
have 4: "map term (rev vs) [=>*] ts"
proof -
have "(C nm •• map term (rev vs),t'): Red_term^^i'" using prems by auto
from C_Red_term_it[OF this] obtain ts' "is"
where "t' = C nm •• ts'" "length ts' = ?n ∧ length is =?n ∧
(∀j< ?n. (map term (rev vs) ! j, ts' ! j) ∈ Red_term ^^ is ! j ∧ is ! j ≤ i')"
using prems by auto
from `t' = C nm •• ts'` `t' = C nm •• ts` have "ts = ts'" by simp
show ?thesis using prems by (auto simp: rtrancl_is_UN_rel_pow)
qed
have 5: "∀t∈set(map term vs). C_normal t" using prems by auto
have "no_match_R nm (map dterm ts)"
apply auto
apply(subgoal_tac "no_match aa (map dterm (map term (rev vs)))")
prefer 2
using 3 apply blast
using 4 5 no_match_preserved[OF _ _ _ refl, of "map term (rev vs)" "ts"] by simp
hence 6: "no_match_R nm ts" by(metis map_dterm_pure[OF pure_ts])
then show "normal t'"
apply(simp)
apply(rule normal.intros(3))
using 2 sz apply(fastsimp simp:set_conv_nth)
apply auto
apply(subgoal_tac "no_match aa (take (size aa) ts)")
apply (metis no_match)
apply(fastsimp intro:no_match_take)
done
next
case (term_V x vs)
let ?n = "size vs"
have 1: "(V x •• map term (rev vs),t') : Red_term^^i'" using term_V `(s,t') : Red_term^^i'` by simp
with Red_term_it[OF 1] obtain ts "is" where [simp]: "t' = V x •• ts" and 2: "length ts = ?n ∧
length is = ?n ∧ (∀j<?n. (term (rev vs ! j), ts ! j) ∈ Red_term ^^ is ! j ∧ is ! j ≤ i')"
by (auto cong:conj_cong)
have "∀j<?n. normal(ts!j)"
proof(clarify)
fix j assume 0: "j < ?n"
then have "is!j < k" using `k=Suc i` 2 by auto
have red: "(term (rev vs ! j), ts ! j) ∈ Red_term ^^ is ! j" using `j < ?n` 2 by auto
have pure: "pure (ts ! j)" using `pure t'` 0 2 by auto
have Cnm: "C_normalML (rev vs ! j)" using less term_V by simp (metis 0 in_set_conv_nth length_rev set_rev)
from less(1)[OF `is!j < k` refl Cnm pure red] show "normal(ts!j)" .
qed
note 3=this
show ?thesis by simp (metis normal.intros(1) in_set_conv_nth 2 3)
next
case (term_Clo f vs n)
let ?u = "apply (lift 0 (Clo f vs n)) (VU 0 [])"
from term_Clo `(s,t') : Red_term^^i'`
obtain t'' where [simp]: "t' = Λ t''" and 1: "(term ?u, t'') : Red_term^^i'" by(metis Lam_Red_term_itE)
have "i' < k" using `k = Suc i` by arith
have "pure t''" using `pure t'` by simp
have "C_normalML ?u" using less term_Clo by(simp)
from less(1)[OF `i' < k` refl `C_normalML ?u` `pure t''` 1] show ?thesis by(simp add:normal.intros)
next
case (ctxt_term u u')
have "i' < k" using `k = Suc i` by arith
have "C_normalML u'" by (rule C_normal_ML_inv)
(insert less ctxt_term, simp_all)
have "(term u', t') ∈ Red_term ^^ i'" using prems by auto
from less(1)[OF `i' < k` refl `C_normalML u'` `pure t'` this] show ?thesis .
qed auto
qed
qed
}
thus ?thesis using assms(2-) rtrancl_imp_rel_pow[OF assms(1)] by blast
qed
lemma C_normal_ML_compile:
"pure t ==> ∀i. C_normalML(σ i) ==> C_normalML (compile t σ)"
by(induct t arbitrary: σ) (simp_all add: C_normal_ML_lift_ML)
corollary nbe_normal:
"pure t ==> term(comp_fixed t) =>* t' ==> pure t' ==> normal t'"
apply(erule nbe_C_normal_ML)
apply(simp add: C_normal_ML_compile)
apply assumption
done
section{* Refinements *}
text{* We ensure that all occurrences of @{term "CU nm vs"} satisfy
the invariant @{prop"size vs = arity nm"}. *}
text{* A constructor value: *}
fun CUs :: "ml => bool" where
"CUs(CU nm vs) = (size vs = arity nm ∧ (∀v∈set vs. CUs v))" |
"CUs _ = False"
lemma size_foldl_At: "size(C nm •• ts) = size ts + listsum(map size ts)"
by(induct ts rule:rev_induct) auto
lemma termination_linpats:
"i < length ts ==> ts!i = C nm •• ts'
==> length ts' + listsum (map size ts') < length ts + listsum (map size ts)"
apply(subgoal_tac "C nm •• ts' : set ts")
prefer 2 apply (metis in_set_conv_nth)
apply(drule listsum_map_remove1[of _ _ size])
apply(simp add:size_foldl_At)
apply (metis gr_implies_not0 length_0_conv)
done
text{* Linear patterns: *}
function linpats :: "tm list => bool" where
"linpats ts <->
(ALL i<size ts. (EX x. ts!i = V x) |
(EX nm ts'. ts!i = C nm •• ts' ∧ arity nm = size ts' ∧ linpats ts')) &
(ALL i<size ts. ALL j<size ts. i≠j --> fv(ts!i) ∩ fv(ts!j) = {})"
by pat_completeness auto
termination
apply(relation "measure(%ts. size ts + (SUM t<-ts. size t))")
apply (auto simp:termination_linpats)
done
declare linpats.simps[simp del]
lemma eq_lists_iff_eq_nth:
"size xs = size ys ==> (xs=ys) = (ALL i<size xs. xs!i = ys!i)"
by (metis nth_equalityI)
lemma pattern_subst_ML_coincidence:
"pattern t ==> ALL i:fv t. σ i = σ' i
==> subst_ML σ (comp_pat t) = subst_ML σ' (comp_pat t)"
by(induct pred:pattern) auto
lemma linpats_pattern: "linpats ts ==> patterns ts"
proof(induct ts rule:linpats.induct)
case (1 ts)
show ?case
proof
fix t assume "t : set ts"
then obtain i where "i < size ts" and [simp]: "t = ts!i"
by (auto simp: in_set_conv_nth)
hence "(EX x. t = V x) | (EX nm ts'. t = C nm •• ts' ∧ arity nm = size ts' & linpats ts')"
(is "?V | ?C")
using 1(2) by(simp add:linpats.simps[of ts])
thus "pattern t"
proof
assume "?V" thus ?thesis by(auto simp:pat_V)
next
assume "?C" thus ?thesis using 1(1) `i < size ts`
by auto (metis pat_C)
qed
qed
qed
lemma no_match_ML_swap_rev:
"length ps = length vs ==> no_matchML ps (rev vs) ==> no_matchML (rev ps) vs"
apply(clarsimp simp: no_match_ML.simps[of ps] no_match_ML.simps[of _ vs])
apply(rule_tac x="size ps - i - 1" in exI)
apply (fastsimp simp:rev_nth)
done
lemma no_match_ML_aux:
"ALL v : set cvs. CUs v ==> linpats ps ==> size ps = size cvs ==>
∀σ. map (substML σ) (map comp_pat ps) ≠ cvs ==>
no_matchML (map comp_pat ps) cvs"
apply(induct ps arbitrary: cvs rule:linpats.induct)
apply(frule linpats_pattern)
apply(subst (asm) linpats.simps) back
apply auto
apply(case_tac "ALL i<size ts. EX σ. substML σ (comp_pat (ts!i)) = cvs!i")
apply(clarsimp simp:Skolem_list_nth)
apply(rename_tac "σs")
apply(erule_tac x="%x. (σs!(THE i. i<size ts & x : fv(ts!i)))x" in allE)
apply(clarsimp simp:eq_lists_iff_eq_nth)
apply(rotate_tac -3)
apply(erule_tac x=i in allE)
apply simp
apply(rotate_tac -1)
apply(drule sym)
apply simp
apply(erule contrapos_np)
apply(rule pattern_subst_ML_coincidence)
apply (metis in_set_conv_nth)
apply clarsimp
apply(rule_tac a=i in theI2)
apply simp
apply (metis disjoint_iff_not_equal)
apply (metis disjoint_iff_not_equal)
apply clarsimp
apply(subst no_match_ML.simps)
apply(rule_tac x="size ts - i - 1" in exI)
apply simp
apply rule
apply simp
apply(subgoal_tac "~(EX x. ts!i = V x)")
prefer 2
apply fastsimp
apply(subgoal_tac "EX nm ts'. ts!i = C nm •• ts' & size ts' = arity nm & linpats ts'")
prefer 2
apply fastsimp
apply clarsimp
apply(rule_tac x=nm in exI)
apply(subgoal_tac "EX nm' vs'. cvs!i = CU nm' vs' & size vs' = arity nm' & (ALL v' : set vs'. CUs v')")
prefer 2
apply(drule_tac x="cvs!i" in bspec)
apply simp
apply(case_tac "cvs!i")
apply simp_all
apply (clarsimp simp:rev_nth rev_map[symmetric])
apply(erule_tac x=i in meta_allE)
apply(erule_tac x=nm' in meta_allE)
apply(erule_tac x="ts'" in meta_allE)
apply(erule_tac x="rev vs'" in meta_allE)
apply simp
apply(subgoal_tac "no_matchML (map comp_pat ts') (rev vs')")
apply(rule no_match_ML_swap_rev)
apply simp
apply assumption
apply(erule_tac meta_mp)
apply (metis rev_map rev_rev_ident)
done
end