# Theory JMM_Common

```(*  Title:      JinjaThreads/MM/JMM_Common.thy
Author:     Andreas Lochbihler
*)

section ‹JMM Instantiation with Jinja -- common parts›

theory JMM_Common
imports
JMM_Framework
JMM_Typesafe
"../Common/BinOp"
"../Common/ExternalCallWF"
begin

context heap begin

lemma heap_copy_loc_not_New: assumes "heap_copy_loc a a' al h ob h'"
shows "NewHeapElem a'' x ∈ set ob ⟹ False"
using assms
by(auto elim: heap_copy_loc.cases)

lemma heap_copies_not_New:
assumes "heap_copies a a' als h obs h'"
and "NewHeapElem a'' x ∈ set obs"
shows "False"
using assms
by induct(auto dest: heap_copy_loc_not_New)

assumes "heap_clone P h a h' ⌊(obs, a')⌋"
and "obs ! i = NewHeapElem a'' x" "i < length obs"
and "obs ! j = NewHeapElem a'' x'" "j < length obs"
shows "i = j"
using assms
apply cases
apply(fastforce simp add: nth_Cons' gr0_conv_Suc in_set_conv_nth split: if_split_asm dest: heap_copies_not_New)+
done

"⟦ P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩;
⦃ta⦄⇘o⇙ ! i = NewHeapElem a' x; i < length ⦃ta⦄⇘o⇙;
⦃ta⦄⇘o⇙ ! j = NewHeapElem a' x'; j < length ⦃ta⦄⇘o⇙ ⟧
⟹ i = j"

"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h;
⦃ta⦄⇘o⇙ ! i = NewHeapElem a' x; i < length ⦃ta⦄⇘o⇙;
⦃ta⦄⇘o⇙ ! j = NewHeapElem a' x'; j < length ⦃ta⦄⇘o⇙ ⟧
⟹ i = j"

assumes "heap_copy_loc a a' al h obs h'"
and "P,h ⊢ a@al : T"
shows "ad = a ∧ al'= al"
using assms by cases auto

assumes "heap_copies a a' als h obs h'"
and "list_all2 (λal T. P,h ⊢ a@al : T) als Ts"
shows "ad = a ∧ al' ∈ set als"
using assms
proof(induct arbitrary: Ts)
case Nil thus ?case by simp
next
case (Cons al h ob h' als obs h'')
from ‹list_all2 (λal T. P,h ⊢ a@al : T) (al # als) Ts›
obtain T Ts' where Ts [simp]: "Ts = T # Ts'"
and "P,h ⊢ a@al : T"
and "list_all2 (λal T. P,h ⊢ a@al : T) als Ts'"
show ?case unfolding set_append Un_iff
proof
with ‹heap_copy_loc a a' al h ob h'›
have "ad = a ∧ al'= al" using ‹P,h ⊢ a@al : T›
thus ?thesis by simp
next
moreover from ‹heap_copy_loc a a' al h ob h'›
have "h ⊴ h'" by(rule hext_heap_copy_loc)
from ‹list_all2 (λal T. P,h ⊢ a@al : T) als Ts'›
have "list_all2 (λal T. P,h' ⊢ a@al : T) als Ts'"
by(rule List.list_all2_mono)(rule addr_loc_type_hext_mono[OF _ ‹h ⊴ h'›])
ultimately have "ad = a ∧ al' ∈ set als" by(rule Cons)
thus ?thesis by simp
qed
qed

assumes clone: "heap_clone P h a h' ⌊(obs, a')⌋"
using clone
proof cases
case (ObjClone C H' FDTs obs')
let ?als = "map (λ((F, D), Tm). CField D F) FDTs"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs"
note ‹heap_copies a a' ?als H' obs' h'›
moreover
from ‹obs = NewHeapElem a' (Class_type C) # obs'› read
moreover
from ‹(H', a') ∈ allocate h (Class_type C)› have "h ⊴ H'" by(rule hext_allocate)
hence "typeof_addr H' a = ⌊Class_type C⌋" using ‹typeof_addr h a = ⌊Class_type C⌋›
hence type: "list_all2 (λal T. P,H' ⊢ a@al : T) ?als ?Ts"
using ‹P ⊢ C has_fields FDTs›
unfolding list_all2_map1 list_all2_map2 list_all2_same
ultimately have "ad = a ∧ al ∈ set ?als" by(rule heap_copies_read_typeable)
hence [simp]: "ad = a" and "al ∈ set ?als" by simp_all
then obtain F D T where [simp]: "al = CField D F" and "((F, D), T) ∈ set FDTs" by auto
with type ‹h ⊴ H'› ‹typeof_addr h a = ⌊Class_type C⌋› show ?thesis
unfolding list_all2_map1 list_all2_map2 list_all2_same
next
case (ArrClone T n H' FDTs obs')
let ?als = "map (λ((F, D), Tfm). CField D F) FDTs @ map ACell [0..<n]"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs @ replicate n T"
note FDTs = ‹P ⊢ Object has_fields FDTs›
note ‹heap_copies a a' ?als H' obs' h'›
moreover from ‹obs = NewHeapElem a' (Array_type T n) # obs'› read
moreover from ‹(H', a') ∈ allocate h (Array_type T n)›
have "h ⊴ H'" by(rule hext_allocate)
with ‹typeof_addr h a = ⌊Array_type T n⌋›
have type': "typeof_addr H' a = ⌊Array_type T n⌋"
hence type: "list_all2 (λal T. P,H' ⊢ a@al : T) ?als ?Ts" using FDTs
by(fastforce intro: list_all2_all_nthI addr_loc_type.intros simp add: has_field_def list_all2_append list_all2_map1 list_all2_map2 list_all2_same dest: weak_map_of_SomeI)
ultimately have "ad = a ∧ al ∈ set ?als" by(rule heap_copies_read_typeable)
hence [simp]: "ad = a" and "al ∈ set ?als" by simp_all
hence "al ∈ set (map (λ((F, D), Tfm). CField D F) FDTs) ∨ al ∈ set (map ACell [0..<n])" by simp
thus ?thesis
proof
assume "al ∈ set (map (λ((F, D), Tfm). CField D F) FDTs)"
then obtain F D Tfm where [simp]: "al = CField D F" and "((F, D), Tfm) ∈ set FDTs" by auto
with type type' ‹h ⊴ H'› ‹typeof_addr h a = ⌊Array_type T n⌋› show ?thesis
next
assume "al ∈ set (map ACell [0..<n])"
then obtain n' where [simp]: "al = ACell n'" and "n' < n" by auto
with type type' ‹h ⊴ H'› ‹typeof_addr h a = ⌊Array_type T n⌋›
qed
qed

assumes red: "P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩"
shows "∃T'. P,h ⊢ ad@al : T'"

end

context heap_conf begin

assumes "heap_clone P h a h' ⌊(obs, a')⌋"
and "hconf h"
shows "NewHeapElem a'' x ∈ set obs ⟹ a'' = a' ∧ typeof_addr h' a' = Some x"
using assms
by(fastforce elim!: heap_clone.cases dest: allocate_SomeD hext_heap_copies heap_copies_not_New typeof_addr_is_type elim: hext_objD hext_arrD)

"⟦ P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩; NewHeapElem a' x ∈ set ⦃ta⦄⇘o⇙; hconf h ⟧
⟹ typeof_addr h' a' = Some x"

"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h; NewHeapElem a' x ∈ set ⦃ta⦄⇘o⇙;
is_native P (the (typeof_addr h a)) M; hconf h ⟧
⟹ typeof_addr h' a' = Some x"
apply(auto simp add: is_native.simps external_WT_defs.simps red_external_aggr_def split: if_split_asm)
done

end

context heap_conf begin

lemma heap_copy_loc_non_speculative_typeable:
and sc: "non_speculative P vs (llist_of (map NormalAction obs))"
and vs: "vs_conf P h vs"
and hconf: "hconf h"
and wt: "P,h ⊢ ad@al : T" "P,h ⊢ ad'@al : T"
proof -
from obs sc have "v ∈ vs (ad, al)" by auto
with vs wt have v: "P,h ⊢ v :≤ T" by(blast dest: vs_confD addr_loc_type_fun)+
thus ?thesis using "write" unfolding obs by(rule heap_base.heap_copy_loc.intros)
qed

lemma heap_copy_loc_non_speculative_vs_conf:
and sc: "non_speculative P vs (llist_of (take n (map NormalAction obs)))"
and vs: "vs_conf P h vs"
and hconf: "hconf h"
and wt: "P,h ⊢ ad@al : T" "P,h ⊢ ad'@al : T"
shows "vs_conf P h' (w_values P vs (take n (map NormalAction obs)))"
proof -
from "write" have hext: "h ⊴ h'" by(rule hext_heap_write)
with vs have vs': "vs_conf P h' vs" by(rule vs_conf_hext)
show ?thesis
proof(cases "n > 0")
case True
with obs sc have "v ∈ vs (ad, al)" by(auto simp add: take_Cons')
with vs wt have v: "P,h ⊢ v :≤ T" by(blast dest: vs_confD addr_loc_type_fun)+
with hext wt have "P,h' ⊢ ad'@al : T" "P,h' ⊢ v :≤ T"
thus ?thesis using vs' obs
by(auto simp add: take_Cons' intro!: vs_confI split: if_split_asm dest: vs_confD)
next
case False thus ?thesis using vs' by simp
qed
qed

lemma heap_copies_non_speculative_typeable:
and "non_speculative P vs (llist_of (map NormalAction obs))"
and "vs_conf P h vs"
and "hconf h"
and "list_all2 (λal T. P,h ⊢ ad@al : T) als Ts" "list_all2 (λal T. P,h ⊢ ad'@al : T) als Ts"
using assms
proof(induct arbitrary: Ts vs)
case Nil show ?case by(auto intro: heap_base.heap_copies.intros)
next
case (Cons al h ob h' als obs h'')
note sc = ‹non_speculative P vs (llist_of (map NormalAction (ob @ obs)))›
and vs = ‹vs_conf P h vs›
and hconf = ‹hconf h›
and wt = ‹list_all2 (λal T. P,h ⊢ ad@al : T) (al # als) Ts› ‹list_all2 (λal T. P,h ⊢ ad'@al : T) (al # als) Ts›

have sc1: "non_speculative P vs (llist_of (map NormalAction ob))"
and sc2: "non_speculative P (w_values P vs (map NormalAction ob)) (llist_of (map NormalAction obs))"
using sc by(simp_all add: non_speculative_lappend lappend_llist_of_llist_of[symmetric] del: lappend_llist_of_llist_of)
from wt obtain T Ts' where Ts: "Ts = T # Ts'"
and wt1: "P,h ⊢ ad@al : T" "P,h ⊢ ad'@al : T"
and wt2: "list_all2 (λal T. P,h ⊢ ad@al : T) als Ts'" "list_all2 (λal T. P,h ⊢ ad'@al : T) als Ts'"
from ‹heap_copy_loc ad ad' al h ob h'› sc1 vs hconf wt1
by(rule heap_copy_loc_non_speculative_typeable)+
from heap_copy_loc_non_speculative_vs_conf[OF ‹heap_copy_loc ad ad' al h ob h'› _ vs hconf wt1, of "length ob"] sc1
have vs': "vs_conf P h' (w_values P vs (map NormalAction ob))" by simp

have "h ⊴ h'" by(rule hext_heap_copy_loc)
with wt2 have wt2': "list_all2 (λal T. P,h' ⊢ ad@al : T) als Ts'" "list_all2 (λal T. P,h' ⊢ ad'@al : T) als Ts'"
by -(erule List.list_all2_mono[OF _ addr_loc_type_hext_mono], assumption+)+

from copy hconf wt1 have hconf': "hconf h'"

from sc2 vs' hconf' wt2' have "heap_base.heap_copies (heap_read_typed P) heap_write ad ad' als h' obs h''" by(rule Cons)
with copy show ?case by(rule heap_base.heap_copies.Cons)
qed

lemma heap_copies_non_speculative_vs_conf:
and "non_speculative P vs (llist_of (take n (map NormalAction obs)))"
and "vs_conf P h vs"
and "hconf h"
and "list_all2 (λal T. P,h ⊢ ad@al : T) als Ts" "list_all2 (λal T. P,h ⊢ ad'@al : T) als Ts"
shows "vs_conf P h' (w_values P vs (take n (map NormalAction obs)))"
using assms
proof(induction arbitrary: Ts vs n)
case Nil thus ?case by simp
next
case (Cons al h ob h' als obs h'')
note sc = ‹non_speculative P vs (llist_of (take n (map NormalAction (ob @ obs))))›
and vs = ‹vs_conf P h vs›
and hconf = ‹hconf h›
and wt = ‹list_all2 (λal T. P,h ⊢ ad@al : T) (al # als) Ts› ‹list_all2 (λal T. P,h ⊢ ad'@al : T) (al # als) Ts›
let ?vs' = "w_values P vs (take n (map NormalAction ob))"

from sc have sc1: "non_speculative P vs (llist_of (take n (map NormalAction ob)))"
and sc2: "non_speculative P ?vs' (llist_of (take (n - length ob) (map NormalAction obs)))"
by(simp_all add: lappend_llist_of_llist_of[symmetric] non_speculative_lappend del: lappend_llist_of_llist_of)

from wt obtain T Ts' where Ts: "Ts = T # Ts'"
and wt1: "P,h ⊢ ad@al : T" "P,h ⊢ ad'@al : T"
and wt2: "list_all2 (λal T. P,h ⊢ ad@al : T) als Ts'" "list_all2 (λal T. P,h ⊢ ad'@al : T) als Ts'"

from hcl sc1 vs hconf wt1 have vs': "vs_conf P h' ?vs'" by(rule heap_copy_loc_non_speculative_vs_conf)

show ?case
proof(cases "n < length ob")
case True
from ‹heap_copies ad ad' als h' obs h''› have "h' ⊴ h''" by(rule hext_heap_copies)
with vs' have "vs_conf P h'' ?vs'" by(rule vs_conf_hext)
thus ?thesis using True by simp
next
case False
note sc2 vs'
moreover from False sc1 have sc1': "non_speculative P vs (llist_of (map NormalAction ob))" by simp
using vs hconf wt1 by(rule heap_copy_loc_non_speculative_typeable)
hence "hconf h'" using hconf wt1
moreover
from hcl have "h ⊴ h'" by(rule hext_heap_copy_loc)
with wt2 have wt2': "list_all2 (λal T. P,h' ⊢ ad@al : T) als Ts'" "list_all2 (λal T. P,h' ⊢ ad'@al : T) als Ts'"
by -(erule List.list_all2_mono[OF _ addr_loc_type_hext_mono], assumption+)+
ultimately have "vs_conf P h'' (w_values P ?vs' (take (n - length ob) (map NormalAction obs)))"
by(rule Cons.IH)
with False show ?thesis by simp
qed
qed

lemma heap_clone_non_speculative_typeable_Some:
and sc: "non_speculative P vs (llist_of (map NormalAction obs))"
and vs: "vs_conf P h vs"
and hconf: "hconf h"
using clone
proof(cases)
case (ObjClone C h'' FDTs obs')
note FDTs = ‹P ⊢ C has_fields FDTs›
and obs = ‹obs = NewHeapElem ad' (Class_type C) # obs'›
let ?als = "map (λ((F, D), Tfm). CField D F) FDTs"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs"
from ‹(h'', ad') ∈ allocate h (Class_type C)› have hext: "h ⊴ h''" by(rule hext_heap_ops)

moreover from sc have "non_speculative P ?vs (llist_of (map NormalAction obs'))"
moreover from ‹P ⊢ C has_fields FDTs›
have "is_class P C" by(rule has_fields_is_class)
hence "is_htype P (Class_type C)" by simp
with vs ‹(h'', ad') ∈ allocate h (Class_type C)›
have "vs_conf P h'' ?vs" by(rule vs_conf_allocate)
moreover from ‹(h'', ad') ∈ allocate h (Class_type C)› hconf ‹is_htype P (Class_type C)›
have "hconf h''" by(rule hconf_allocate_mono)
moreover from type FDTs have "list_all2 (λal T. P,h'' ⊢ ad@al : T) ?als ?Ts"
unfolding list_all2_map1 list_all2_map2 list_all2_same
moreover from ‹(h'', ad') ∈ allocate h (Class_type C)› ‹is_htype P (Class_type C)›
with FDTs have "list_all2 (λal T. P,h'' ⊢ ad'@al : T) ?als ?Ts"
unfolding list_all2_map1 list_all2_map2 list_all2_same
ultimately
have copy: "heap_base.heap_copies (heap_read_typed P) heap_write ad ad' (map (λ((F, D), Tfm). CField D F) FDTs) h'' obs' h'"
by(rule heap_copies_non_speculative_typeable)+
show ?thesis unfolding obs by(rule heap_base.heap_clone.intros)
next
case (ArrClone T n h'' FDTs obs')
note obs = ‹obs = NewHeapElem ad' (Array_type T n) # obs'›
and new = ‹(h'', ad') ∈ allocate h (Array_type T n)›
and FDTs = ‹P ⊢ Object has_fields FDTs›
let ?als = "map (λ((F, D), Tfm). CField D F) FDTs @ map ACell [0..<n]"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs @ replicate n T"
from new have hext: "h ⊴ h''" by(rule hext_heap_ops)

moreover from sc have "non_speculative P ?vs (llist_of (map NormalAction obs'))" by(simp add: obs)
moreover from ‹typeof_addr h ad = ⌊Array_type T n⌋› ‹hconf h› have "is_htype P (Array_type T n)"
with vs new have "vs_conf P h'' ?vs" by(rule vs_conf_allocate)
moreover from new hconf ‹is_htype P (Array_type T n)› have "hconf h''" by(rule hconf_allocate_mono)
moreover
from type FDTs have "list_all2 (λal T. P,h'' ⊢ ad@al : T) ?als ?Ts"
by(fastforce intro: list_all2_all_nthI addr_loc_type.intros simp add: has_field_def list_all2_append list_all2_map1 list_all2_map2 list_all2_same dest: weak_map_of_SomeI)
moreover from new ‹is_htype P (Array_type T n)›
by(auto dest: allocate_SomeD)
hence "list_all2 (λal T. P,h'' ⊢ ad'@al : T) ?als ?Ts" using FDTs
by(fastforce intro: list_all2_all_nthI addr_loc_type.intros simp add: has_field_def list_all2_append list_all2_map1 list_all2_map2 list_all2_same dest: weak_map_of_SomeI)
ultimately have copy: "heap_base.heap_copies (heap_read_typed P) heap_write ad ad' (map (λ((F, D), Tfm). CField D F) FDTs @ map ACell [0..<n]) h'' obs' h'"
by(rule heap_copies_non_speculative_typeable)+
from ‹typeof_addr h ad = ⌊Array_type T n⌋› new FDTs copy show ?thesis
unfolding obs by(rule heap_base.heap_clone.ArrClone)
qed

lemma heap_clone_non_speculative_vs_conf_Some:
and sc: "non_speculative P vs (llist_of (take n (map NormalAction obs)))"
and vs: "vs_conf P h vs"
and hconf: "hconf h"
shows "vs_conf P h' (w_values P vs (take n (map NormalAction obs)))"
using clone
proof(cases)
case (ObjClone C h'' FDTs obs')
note FDTs = ‹P ⊢ C has_fields FDTs›
and obs = ‹obs = NewHeapElem ad' (Class_type C) # obs'›
let ?als = "map (λ((F, D), Tfm). CField D F) FDTs"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs"
from ‹(h'', ad') ∈ allocate h (Class_type C)› have hext: "h ⊴ h''" by(rule hext_heap_ops)

moreover from sc have "non_speculative P ?vs (llist_of (take (n - 1) (map NormalAction obs')))"
by(simp add: obs take_Cons' split: if_split_asm)
moreover from ‹P ⊢ C has_fields FDTs›
have "is_class P C" by(rule has_fields_is_class)
hence "is_htype P (Class_type C)" by simp
with vs ‹(h'', ad') ∈ allocate h (Class_type C)›
have "vs_conf P h'' ?vs" by(rule vs_conf_allocate)
moreover from ‹(h'', ad') ∈ allocate h (Class_type C)› hconf ‹is_htype P (Class_type C)›
have "hconf h''" by(rule hconf_allocate_mono)
moreover from type FDTs have "list_all2 (λal T. P,h'' ⊢ ad@al : T) ?als ?Ts"
unfolding list_all2_map1 list_all2_map2 list_all2_same
moreover from ‹(h'', ad') ∈ allocate h (Class_type C)› ‹is_htype P (Class_type C)›
with FDTs have "list_all2 (λal T. P,h'' ⊢ ad'@al : T) ?als ?Ts"
unfolding list_all2_map1 list_all2_map2 list_all2_same
ultimately
have vs': "vs_conf P h' (w_values P ?vs (take (n - 1) (map NormalAction obs')))"
by(rule heap_copies_non_speculative_vs_conf)
show ?thesis
proof(cases "n > 0")
case True
with obs vs' show ?thesis by(simp add: take_Cons')
next
case False
from ‹heap_copies ad ad' ?als h'' obs' h'› have "h'' ⊴ h'" by(rule hext_heap_copies)
with ‹h ⊴ h''› have "h ⊴ h'" by(rule hext_trans)
with vs have "vs_conf P h' vs" by(rule vs_conf_hext)
thus ?thesis using False by simp
qed
next
case (ArrClone T N h'' FDTs obs')
note obs = ‹obs = NewHeapElem ad' (Array_type T N) # obs'›
and new = ‹(h'', ad') ∈ allocate h (Array_type T N)›
and FDTs = ‹P ⊢ Object has_fields FDTs›
let ?als = "map (λ((F, D), Tfm). CField D F) FDTs @ map ACell [0..<N]"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs @ replicate N T"
from new have hext: "h ⊴ h''" by(rule hext_heap_ops)

moreover from sc have "non_speculative P ?vs (llist_of (take (n - 1) (map NormalAction obs')))"
by(simp add: obs take_Cons' split: if_split_asm)
moreover from ‹typeof_addr h ad = ⌊Array_type T N⌋› ‹hconf h› have "is_htype P (Array_type T N)"
with vs new have "vs_conf P h'' ?vs" by(rule vs_conf_allocate)
moreover from new hconf ‹is_htype P (Array_type T N)› have "hconf h''" by(rule hconf_allocate_mono)
moreover
from type FDTs have "list_all2 (λal T. P,h'' ⊢ ad@al : T) ?als ?Ts"
by(fastforce intro: list_all2_all_nthI addr_loc_type.intros simp add: has_field_def list_all2_append list_all2_map1 list_all2_map2 list_all2_same dest: weak_map_of_SomeI)
moreover from new ‹is_htype P (Array_type T N)›
by(auto dest: allocate_SomeD)
hence "list_all2 (λal T. P,h'' ⊢ ad'@al : T) ?als ?Ts" using FDTs
by(fastforce intro: list_all2_all_nthI addr_loc_type.intros simp add: has_field_def list_all2_append list_all2_map1 list_all2_map2 list_all2_same dest: weak_map_of_SomeI)
ultimately have vs': "vs_conf P h' (w_values P ?vs (take (n - 1) (map NormalAction obs')))"
by(rule heap_copies_non_speculative_vs_conf)
show ?thesis
proof(cases "n > 0")
case True
with obs vs' show ?thesis by(simp add: take_Cons')
next
case False
from ‹heap_copies ad ad' ?als h'' obs' h'› have "h'' ⊴ h'" by(rule hext_heap_copies)
with ‹h ⊴ h''› have "h ⊴ h'" by(rule hext_trans)
with vs have "vs_conf P h' vs" by(rule vs_conf_hext)
thus ?thesis using False by simp
qed
qed

lemma heap_clone_non_speculative_typeable_None:
assumes "heap_clone P h ad h' None"
using assms
by(cases)(blast intro: heap_base.heap_clone.intros)+

lemma red_external_non_speculative_typeable:
assumes red: "P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩"
and sc: "non_speculative P Vs (llist_of (map NormalAction ⦃ta⦄⇘o⇙))"
and vs: "vs_conf P h Vs"
and hconf: "hconf h"
using assms
by(cases)(auto intro: heap_base.red_external.intros heap_clone_non_speculative_typeable_None heap_clone_non_speculative_typeable_Some dest: hext_heap_clone elim: vs_conf_hext)

lemma red_external_non_speculative_vs_conf:
assumes red: "P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩"
and sc: "non_speculative P Vs (llist_of (take n (map NormalAction ⦃ta⦄⇘o⇙)))"
and vs: "vs_conf P h Vs"
and hconf: "hconf h"
shows "vs_conf P h' (w_values P Vs (take n (map NormalAction ⦃ta⦄⇘o⇙)))"
using assms
by(cases)(auto intro: heap_base.red_external.intros heap_clone_non_speculative_vs_conf_Some dest: hext_heap_clone elim: vs_conf_hext simp add: take_Cons')

lemma red_external_aggr_non_speculative_typeable:
assumes red: "(ta, va, h') ∈ red_external_aggr P t a M vs h"
and sc: "non_speculative P Vs (llist_of (map NormalAction ⦃ta⦄⇘o⇙))"
and vs: "vs_conf P h Vs"
and hconf: "hconf h"
and native: "is_native P (the (typeof_addr h a)) M"
using assms
by(cases "the (typeof_addr h a)")(auto 4 3 simp add: is_native.simps external_WT_defs.simps red_external_aggr_def heap_base.red_external_aggr_def split: if_split_asm split del: if_split del: disjCI intro: heap_clone_non_speculative_typeable_None heap_clone_non_speculative_typeable_Some dest: sees_method_decl_above)

lemma red_external_aggr_non_speculative_vs_conf:
assumes red: "(ta, va, h') ∈ red_external_aggr P t a M vs h"
and sc: "non_speculative P Vs (llist_of (take n (map NormalAction ⦃ta⦄⇘o⇙)))"
and vs: "vs_conf P h Vs"
and hconf: "hconf h"
and native: "is_native P (the (typeof_addr h a)) M"
shows "vs_conf P h' (w_values P Vs (take n (map NormalAction ⦃ta⦄⇘o⇙)))"
using assms
by(cases "the (typeof_addr h a)")(auto 4 3 simp add: is_native.simps external_WT_defs.simps red_external_aggr_def heap_base.red_external_aggr_def take_Cons' split: if_split_asm split del: if_split del: disjCI intro: heap_clone_non_speculative_vs_conf_Some dest: hext_heap_clone elim: vs_conf_hext dest: sees_method_decl_above)

end

declare split_paired_Ex [simp del]
declare eq_upto_seq_inconsist_simps [simp]

context heap_progress begin

and vs: "vs_conf P h vs"
and type: "P,h ⊢ a@al : T" "P,h ⊢ a'@al : T"
and hconf: "hconf h"
and copy: "heap_copy_loc a a' al h obs h'"
and i: "i < length obs"
and v: "v' ∈ w_values P vs (map NormalAction (take i obs)) (a'', al'')"
shows "∃obs' h''. heap_copy_loc a a' al h obs' h'' ∧ i < length obs' ∧ take i obs' = take i obs ∧
obs' ! i = ReadMem a'' al'' v' ∧ length obs' ≤ length obs ∧
non_speculative P vs (llist_of (map NormalAction obs'))"
using copy
proof cases
case (1 v'')
with read i have [simp]: "i = 0" "v'' = v" "a'' = a" "al'' = al"
from v have "v' ∈ vs (a, al)" by simp
with vs type have conf: "P,h ⊢ v' :≤ T" by(auto dest: addr_loc_type_fun vs_confD)
let ?obs'' = "[ReadMem a al v', WriteMem a' al v']"
from hrt type(1) conf hconf have "heap_read h a al v'" by(rule heap_read_typeableD)
moreover from heap_write_total[OF hconf type(2) conf]
obtain h'' where "heap_write h a' al v' h''" ..
ultimately have "heap_copy_loc a a' al h ?obs'' h''" ..
thus ?thesis using 1 ‹v' ∈ vs (a, al)› by(auto)
qed

and copies: "heap_copies a a' als h obs h'"
and vs: "vs_conf P h vs"
and type1: "list_all2 (λal T. P,h ⊢ a@al : T) als Ts"
and type2: "list_all2 (λal T. P,h ⊢ a'@al : T) als Ts"
and hconf: "hconf h"
and i: "i < length obs"
and v: "v' ∈ w_values P vs (map NormalAction (take i obs)) (a'', al'')"
and ns: "non_speculative P vs (llist_of (map NormalAction (take i obs)))"
shows "∃obs' h''. heap_copies a a' als h obs' h'' ∧ i < length obs' ∧ take i obs' = take i obs ∧
obs' ! i = ReadMem a'' al'' v' ∧ length obs' ≤ length obs"
(is "?concl als h obs vs i")
using copies vs type1 type2 hconf i read v ns
proof(induction arbitrary: Ts vs i)
case Nil thus ?case by simp
next
case (Cons al h ob h' als obs h'' Ts vs)
note copy = ‹heap_copy_loc a a' al h ob h'›
note vs = ‹vs_conf P h vs›
note type1 = ‹list_all2 (λal T. P,h ⊢ a@al : T) (al # als) Ts›
and type2 = ‹list_all2 (λal T. P,h ⊢ a'@al : T) (al # als) Ts›
note hconf = ‹hconf h›
note i = ‹i < length (ob @ obs)›
note read = ‹(ob @ obs) ! i = ReadMem a'' al'' v›
note v = ‹v' ∈ w_values P vs (map NormalAction (take i (ob @ obs))) (a'', al'')›
note ns = ‹non_speculative P vs (llist_of (map NormalAction (take i (ob @ obs))))›

from type1 obtain T Ts' where Ts: "Ts = T # Ts'"
and type1': "P,h ⊢ a@al : T"
and type1'': "list_all2 (λal T. P,h ⊢ a@al : T) als Ts'"
from type2 Ts have type2': "P,h ⊢ a'@al : T"
and type2'': "list_all2 (λal T. P,h ⊢ a'@al : T) als Ts'"
by simp_all
show ?case
proof(cases "i < length ob")
case True
have "ob ! i = ReadMem a'' al'' v"
and "v' ∈ w_values P vs (map NormalAction (take i ob)) (a'', al'')" by(simp_all add: nth_append)
from heap_copy_loc_non_speculative_read[OF hrt vs type1' type2' hconf copy True this]
obtain ob' H'' where copy': "heap_copy_loc a a' al h ob' H''"
and i': "i < length ob'" and "take i ob' = take i ob"
and "ob' ! i = ReadMem a'' al'' v'"
and "length ob' ≤ length ob"
and ns: "non_speculative P vs (llist_of (map NormalAction ob'))" by blast
moreover {
from copy' have hext: "h ⊴ H''" by(rule hext_heap_copy_loc)
have "hconf H''"
moreover
from type1'' have "list_all2 (λal T. P,H'' ⊢ a@al : T) als Ts'"
moreover from type2'' have "list_all2 (λal T. P,H'' ⊢ a'@al : T) als Ts'"
moreover note calculation }
from heap_copies_progress[OF this]
obtain obs' h''' where *: "heap_copies a a' als H'' obs' h'''" by blast
moreover note heap_copies_length[OF *]
moreover note heap_copy_loc_length[OF copy']
moreover note heap_copies_length[OF ‹heap_copies a a' als h' obs h''›]
ultimately show ?thesis using True by(auto intro!: heap_copies.Cons exI simp add: nth_append)
next
case False
let ?vs' = "w_values P vs (map NormalAction ob)"
let ?i' = "i - length ob"

from ns False obtain ns': "non_speculative P vs (llist_of (map NormalAction ob))"
and ns'': "non_speculative P ?vs' (llist_of (map NormalAction (take ?i' obs)))"
by(simp add: lappend_llist_of_llist_of[symmetric] non_speculative_lappend del: lappend_llist_of_llist_of)

from heap_copy_loc_non_speculative_vs_conf[OF copy _ vs hconf type1' type2', where n="length ob"] ns'
have "vs_conf P h' ?vs'" by simp
moreover
from copy have hext: "h ⊴ h'" by(rule hext_heap_copy_loc)
from type1'' have "list_all2 (λal T. P,h' ⊢ a@al : T) als Ts'"
moreover from type2'' have "list_all2 (λal T. P,h' ⊢ a'@al : T) als Ts'"
moreover have "hconf h'"
moreover from i False have "?i' < length obs" by simp
moreover from v False have "v' ∈ w_values P ?vs' (map NormalAction (take ?i' obs)) (a'', al'')" by(simp)
ultimately have "?concl als h' obs ?vs' ?i'" using ns'' by(rule Cons.IH)
thus ?thesis using False copy by safe(auto intro!: heap_copies.Cons exI simp add: nth_append)
qed
qed

and clone: "heap_clone P h a h' ⌊(obs, a')⌋"
and vs: "vs_conf P h vs"
and hconf: "hconf h"
and i: "i < length obs"
and v: "v' ∈ w_values P vs (map NormalAction (take i obs)) (a'', al'')"
and ns: "non_speculative P vs (llist_of (map NormalAction (take i obs)))"
shows "∃obs' h''. heap_clone P h a h'' ⌊(obs', a')⌋ ∧ i < length obs' ∧ take i obs' = take i obs ∧
obs' ! i = ReadMem a'' al'' v' ∧ length obs' ≤ length obs"
using clone
proof cases
case (ObjClone C h'' FDTs obs')

note obs = ‹obs = NewHeapElem a' (Class_type C) # obs'›
note FDTs = ‹P ⊢ C has_fields FDTs›
let ?als = "map (λ((F, D), Tm). CField D F) FDTs"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs"
let ?vs = "w_value P vs (NormalAction (NewHeapElem a' (Class_type C)) :: ('addr, 'thread_id) obs_event action)"
let ?i = "i - 1"
from i read obs have i_0: "i > 0" by(simp add: nth_Cons' split: if_split_asm)

from ‹P ⊢ C has_fields FDTs› have "is_class P C" by(rule has_fields_is_class)
with ‹(h'', a') ∈ allocate h (Class_type C)›
have type_a': "typeof_addr h'' a' = ⌊Class_type C⌋" and hext: "h ⊴ h''"
by(auto dest: allocate_SomeD hext_allocate)

note ‹heap_copies a a' ?als h'' obs' h'›
moreover from ‹typeof_addr h a = ⌊Class_type C⌋› hconf have "is_htype P (Class_type C)"
with vs ‹(h'', a') ∈ allocate h (Class_type C)›
have "vs_conf P h'' ?vs" by(rule vs_conf_allocate)
moreover
from hext ‹typeof_addr h a = ⌊Class_type C⌋›
hence "list_all2 (λal T. P,h'' ⊢ a@al : T) ?als ?Ts" using FDTs
unfolding list_all2_map1 list_all2_map2 list_all2_same
moreover from FDTs type_a'
have "list_all2 (λal T. P,h'' ⊢ a'@al : T) ?als ?Ts"
unfolding list_all2_map1 list_all2_map2 list_all2_same
moreover from ‹(h'', a') ∈ allocate h (Class_type C)› hconf ‹is_htype P (Class_type C)›
have "hconf h''" by(rule hconf_allocate_mono)
moreover from i read i_0 obs have "?i < length obs'" "obs' ! ?i = ReadMem a'' al'' v" by simp_all
moreover from v i_0 obs
have "v' ∈ w_values P ?vs (map NormalAction (take ?i obs')) (a'', al'')" by(simp add: take_Cons')
moreover from ns i_0 obs
have "non_speculative P ?vs (llist_of (map NormalAction (take ?i obs')))" by(simp add: take_Cons')
ultimately have "∃obs'' h'''. heap_copies a a' ?als h'' obs'' h''' ∧
?i < length obs'' ∧ take ?i obs'' = take ?i obs' ∧ obs'' ! ?i = ReadMem a'' al'' v' ∧
length obs'' ≤ length obs'"
thus ?thesis using ‹typeof_addr h a = ⌊Class_type C⌋› ‹(h'', a') ∈ allocate h (Class_type C)› FDTs obs i_0
by(auto 4 4 intro: heap_clone.ObjClone simp add: take_Cons')
next
case (ArrClone T n h'' FDTs obs')

note obs = ‹obs = NewHeapElem a' (Array_type T n) # obs'›
note FDTs = ‹P ⊢ Object has_fields FDTs›
let ?als = "map (λ((F, D), Tfm). CField D F) FDTs @ map ACell [0..<n]"
let ?Ts = "map (λ(FD, T). fst (the (map_of FDTs FD))) FDTs @ replicate n T"
let ?vs = "w_value P vs (NormalAction (NewHeapElem a' (Array_type T n)) :: ('addr, 'thread_id) obs_event action)"
let ?i = "i - 1"
from i read obs have i_0: "i > 0" by(simp add: nth_Cons' split: if_split_asm)

from ‹typeof_addr h a = ⌊Array_type T n⌋› hconf
have "is_htype P (Array_type T n)" by(rule typeof_addr_is_type)
with ‹(h'', a') ∈ allocate h (Array_type T n)›
have type_a': "typeof_addr h'' a' = ⌊Array_type T n⌋"
and hext: "h ⊴ h''"
by(auto dest: allocate_SomeD hext_allocate)

note ‹heap_copies a a' ?als h'' obs' h'›
moreover from vs ‹(h'', a') ∈ allocate h (Array_type T n)› ‹is_htype P (Array_type T n)›
have "vs_conf P h'' ?vs" by(rule vs_conf_allocate)
moreover from hext ‹typeof_addr h a = ⌊Array_type T n⌋›
have type'a: "typeof_addr h'' a = ⌊Array_type T n⌋"
by(auto intro: hext_arrD)
from type'a FDTs have "list_all2 (λal T. P,h'' ⊢ a@al : T) ?als ?Ts"
by(fastforce intro: list_all2_all_nthI addr_loc_type.intros simp add: has_field_def list_all2_append list_all2_map1 list_all2_map2 list_all2_same dest: weak_map_of_SomeI)
moreover from type_a' FDTs
have "list_all2 (λal T. P,h'' ⊢ a'@al : T) ?als ?Ts"
by(fastforce intro: list_all2_all_nthI addr_loc_type.intros simp add: has_field_def list_all2_append list_all2_map1 list_all2_map2 list_all2_same dest: weak_map_of_SomeI)
moreover from ‹(h'', a') ∈ allocate h (Array_type T n)› hconf ‹is_htype P (Array_type T n)›
have "hconf h''" by(rule hconf_allocate_mono)
moreover from i read i_0 obs have "?i < length obs'" "obs' ! ?i = ReadMem a'' al'' v" by simp_all
moreover from v i_0 obs
have "v' ∈ w_values P ?vs (map NormalAction (take ?i obs')) (a'', al'')" by(simp add: take_Cons')
moreover from ns i_0 obs
have "non_speculative P ?vs (llist_of (map NormalAction (take ?i obs')))" by(simp add: take_Cons')
ultimately have "∃obs'' h'''. heap_copies a a' ?als h'' obs'' h''' ∧
?i < length obs'' ∧ take ?i obs'' = take ?i obs' ∧ obs'' ! ?i = ReadMem a'' al'' v' ∧
length obs'' ≤ length obs'"
thus ?thesis using ‹typeof_addr h a = ⌊Array_type T n⌋› ‹(h'', a') ∈ allocate h (Array_type T n)› FDTs obs i_0
by(auto 4 4 intro: heap_clone.ArrClone simp add: take_Cons')
qed

and vs: "vs_conf P (shr s) vs"
and red: "P,t ⊢ ⟨a∙M(vs'), shr s⟩ -ta→ext ⟨va,h'⟩"
and aok: "final_thread.actions_ok final s t ta"
and hconf: "hconf (shr s)"
and i: "i < length ⦃ta⦄⇘o⇙"
and v: "v' ∈ w_values P vs (map NormalAction (take i ⦃ta⦄⇘o⇙)) (a'', al'')"
and ns: "non_speculative P vs (llist_of (map NormalAction (take i ⦃ta⦄⇘o⇙)))"
shows "∃ta'' va'' h''. P,t ⊢ ⟨a∙M(vs'), shr s⟩ -ta''→ext ⟨va'', h''⟩ ∧ final_thread.actions_ok final s t ta'' ∧
i < length ⦃ta''⦄⇘o⇙ ∧ take i ⦃ta''⦄⇘o⇙ = take i ⦃ta⦄⇘o⇙ ∧
⦃ta''⦄⇘o⇙ ! i = ReadMem a'' al'' v' ∧ length ⦃ta''⦄⇘o⇙ ≤ length ⦃ta⦄⇘o⇙"
proof cases
case [simp]: (RedClone obs a')
from heap_clone_non_speculative_read[OF hrt ‹heap_clone P (shr s) a h' ⌊(obs, a')⌋› vs hconf, of i a'' al'' v v'] i read v ns
show ?thesis using aok

and vs: "vs_conf P (shr s) vs"
and red: "(ta, va, h') ∈ red_external_aggr P t a M vs' (shr s)"
and native: "is_native P (the (typeof_addr (shr s) a)) M"
and aok: "final_thread.actions_ok final s t ta"
and hconf: "hconf (shr s)"
and i: "i < length ⦃ta⦄⇘o⇙"
and v: "v' ∈ w_values P vs (map NormalAction (take i ⦃ta⦄⇘o⇙)) (a'', al'')"
and ns: "non_speculative P vs (llist_of (map NormalAction (take i ⦃ta⦄⇘o⇙)))"
shows "∃ta'' va'' h''. (ta'', va'', h'') ∈ red_external_aggr P t a M vs' (shr s) ∧ final_thread.actions_ok final s t ta'' ∧
i < length ⦃ta''⦄⇘o⇙ ∧ take i ⦃ta''⦄⇘o⇙ = take i ⦃ta⦄⇘o⇙ ∧
⦃ta''⦄⇘o⇙ ! i = ReadMem a'' al'' v' ∧ length ⦃ta''⦄⇘o⇙ ≤ length ⦃ta⦄⇘o⇙"
using red native aok hconf i read v ns
apply(simp add: red_external_aggr_def final_thread.actions_ok_iff ex_disj_distrib conj_disj_distribR split nth_Cons' del: if_split split: if_split_asm disj_split_asm)
apply(drule heap_clone_non_speculative_read[OF hrt _ vs hconf, of _ _ _ _ i a'' al'' v v'])
apply simp_all
apply(fastforce)
done

end

declare split_paired_Ex [simp]
declare eq_upto_seq_inconsist_simps [simp del]

context allocated_heap begin

lemma heap_copy_loc_allocated_same:
assumes "heap_copy_loc a a' al h obs h'"
shows "allocated h' = allocated h"
using assms
by cases(auto del: subsetI simp: heap_write_allocated_same)

lemma heap_copy_loc_allocated_mono:
"heap_copy_loc a a' al h obs h' ⟹ allocated h ⊆ allocated h'"

lemma heap_copies_allocated_same:
assumes "heap_copies a a' al h obs h'"
shows "allocated h' = allocated h"
using assms

lemma heap_copies_allocated_mono:
"heap_copies a a' al h obs h' ⟹ allocated h ⊆ allocated h'"

lemma heap_clone_allocated_mono:
assumes "heap_clone P h a h' aobs"
shows "allocated h ⊆ allocated h'"
using assms
by cases(blast del: subsetI intro: heap_copies_allocated_mono allocate_allocated_mono intro: subset_trans)+

lemma red_external_allocated_mono:
assumes "P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩"
shows "allocated h ⊆ allocated h'"
using assms
by(cases)(blast del: subsetI intro: heap_clone_allocated_mono heap_write_allocated_same)+

lemma red_external_aggr_allocated_mono:
"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h; is_native P (the (typeof_addr h a)) M ⟧
⟹ allocated h ⊆ allocated h'"
by(cases "the (typeof_addr h a)")(auto simp add: is_native.simps external_WT_defs.simps red_external_aggr_def split: if_split_asm dest: heap_clone_allocated_mono sees_method_decl_above)

lemma heap_clone_allocatedD:
assumes "heap_clone P h a h' ⌊(obs, a')⌋"
and "NewHeapElem a'' x ∈ set obs"
shows "a'' ∈ allocated h' ∧ a'' ∉ allocated h"
using assms
by cases(auto dest: allocate_allocatedD heap_copies_allocated_mono heap_copies_not_New)

lemma red_external_allocatedD:
"⟦ P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩; NewHeapElem a' x ∈ set ⦃ta⦄⇘o⇙ ⟧
⟹ a' ∈ allocated h' ∧ a' ∉ allocated h"
by(erule red_external.cases)(auto dest: heap_clone_allocatedD)

lemma red_external_aggr_allocatedD:
"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h; NewHeapElem a' x ∈ set ⦃ta⦄⇘o⇙;
is_native P (the (typeof_addr h a)) M ⟧
⟹ a' ∈ allocated h' ∧ a' ∉ allocated h"
by(auto simp add: is_native.simps external_WT_defs.simps red_external_aggr_def split: if_split_asm dest: heap_clone_allocatedD sees_method_decl_above)

lemma heap_clone_NewHeapElemD:
assumes "heap_clone P h a h' ⌊(obs, a')⌋"
shows "∃CTn. NewHeapElem ad CTn ∈ set obs"
using assms
by cases(auto dest!: allocate_allocatedD heap_copies_allocated_same)

lemma heap_clone_fail_allocated_same:
assumes "heap_clone P h a h' None"
shows "allocated h' = allocated h"
using assms
by(cases)(auto)

lemma red_external_NewHeapElemD:
"⟦ P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩; a' ∈ allocated h'; a' ∉ allocated h ⟧
⟹ ∃CTn. NewHeapElem a' CTn ∈ set ⦃ta⦄⇘o⇙"
by(erule red_external.cases)(auto dest: heap_clone_NewHeapElemD heap_clone_fail_allocated_same)

lemma red_external_aggr_NewHeapElemD:
"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h; a' ∈ allocated h'; a' ∉ allocated h;
is_native P (the (typeof_addr h a)) M ⟧
⟹ ∃CTn. NewHeapElem a' CTn ∈ set ⦃ta⦄⇘o⇙"
by(cases "the (typeof_addr h a)")(auto simp add: is_native.simps external_WT_defs.simps red_external_aggr_def split: if_split_asm dest: heap_clone_fail_allocated_same heap_clone_NewHeapElemD sees_method_decl_above)

end

context heap_base begin

assumes ok: "start_heap_ok"
shows "binop bop v1 v2 = ⌊Inl v⌋ ⟹ ka_Val v ⊆ ka_Val v1 ∪ ka_Val v2 ∪ set start_addrs"
and "binop bop v1 v2 = ⌊Inr a⌋ ⟹ a ∈ ka_Val v1 ∪ ka_Val v2 ∪ set start_addrs"
apply(cases bop, auto split: if_split_asm)[1]
done

assumes "heap_copy_loc a a' al h ob h'"
using assms by cases simp

assumes "heap_copies a a' als h obs h'"
using assms

assumes "heap_clone P h a h' ⌊(obs, a')⌋"
using assms

"⟦ P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va,h'⟩; ReadMem ad al v ∈ set ⦃ta⦄⇘o⇙ ⟧

"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h; ReadMem ad al v ∈ set ⦃ta⦄⇘o⇙ ⟧
done

assumes "heap_copy_loc a a' al h ob h'"
and "ob ! n = WriteMem ad al' (Addr a'')" "n < length ob"
shows "a'' ∈ new_obs_addrs (take n ob)"
using assms

assumes "heap_copies a a' als h obs h'"
and "obs ! n = WriteMem ad al (Addr a'')" "n < length obs"
shows "a'' ∈ new_obs_addrs (take n obs)"
using assms

assumes "heap_clone P h a h' ⌊(obs, a')⌋"
and "obs ! n = WriteMem ad al (Addr a'')" "n < length obs"
shows "a'' ∈ new_obs_addrs (take n obs)"
using assms

"⟦ P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va,h'⟩; ⦃ta⦄⇘o⇙ ! n = WriteMem ad al (Addr a'); n < length ⦃ta⦄⇘o⇙ ⟧

"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h;
⦃ta⦄⇘o⇙ ! n = WriteMem ad al (Addr a'); n < length ⦃ta⦄⇘o⇙ ⟧
done

assumes ok: "start_heap_ok"
and red: "P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩"
shows "(case va of RetVal v ⇒ ka_Val v | RetExc a ⇒ {a} | RetStaySame ⇒ {}) ⊆ {thread_id2addr t, a} ∪ (⋃(ka_Val ` set vs)) ∪ set start_addrs ∪ new_obs_addrs ⦃ta⦄⇘o⇙"
using red

assumes ok: "start_heap_ok"
and red: "(ta, va, h') ∈ red_external_aggr P t a M vs h" "is_native P (the (typeof_addr h a)) M"
shows "(case va of RetVal v ⇒ ka_Val v | RetExc a ⇒ {a} | RetStaySame ⇒ {}) ⊆ {thread_id2addr t, a} ∪ (⋃(ka_Val ` set vs)) ∪ set start_addrs ∪ new_obs_addrs ⦃ta⦄⇘o⇙"
using red
apply(auto simp add: is_native.simps elim!: external_WT_defs.cases dest: sees_method_decl_above)
done

"⟦ P,t ⊢ ⟨a∙M(vs), h⟩ -ta→ext ⟨va, h'⟩; NewThread t' (C, M', a') h'' ∈ set ⦃ta⦄⇘t⇙ ⟧
by(erule red_external.cases) simp_all

"⟦ (ta, va, h') ∈ red_external_aggr P t a M vs h;
NewThread t' (C, M', a') h'' ∈ set ⦃ta⦄⇘t⇙ ⟧
apply(auto simp add: red_external_aggr_def split: if_split_asm)
done

end

locale heap'' =
heap'
spurious_wakeups
P
and spurious_wakeups :: bool
and empty_heap :: "'heap"
and allocate :: "'heap ⇒ htype ⇒ ('heap × 'addr) set"
and P :: "'m prog"
+
assumes allocate_typeof_addr_SomeD: "⟦ (h', a) ∈ allocate h hT; typeof_addr a ≠ None ⟧ ⟹ typeof_addr a = ⌊hT⌋"
begin

lemma heap_copy_loc_New_type_match:
"⟦ h.heap_copy_loc a a' al h obs h'; NewHeapElem ad CTn ∈ set obs; typeof_addr ad ≠ None ⟧
by(erule h.heap_copy_loc.cases) simp

lemma heap_copies_New_type_match:
"⟦ h.heap_copies a a' als h obs h'; NewHeapElem ad CTn ∈ set obs; typeof_addr ad ≠ None ⟧
by(induct rule: h.heap_copies.induct)(auto dest: heap_copy_loc_New_type_match)

lemma heap_clone_New_type_match:
"⟦ h.heap_clone P h a h' ⌊(obs, a')⌋; NewHeapElem ad CTn ∈ set obs; typeof_addr ad ≠ None ⟧

lemma red_external_New_type_match:
"⟦ h.red_external P t a M vs h ta va h'; NewHeapElem ad CTn ∈ set ⦃ta⦄⇘o⇙; typeof_addr ad ≠ None ⟧