Theory DefAss

(*  Title:      JinjaDCI/J/DefAss.thy
    Author:     Tobias Nipkow, Susannah Mansky
    Copyright   2003 Technische Universitaet Muenchen, 2019-20 UIUC

    Based on the Jinja theory J/DefAss.thy by Tobias Nipkow
*)

section ‹ Definite assignment ›

theory DefAss imports BigStep begin

subsection "Hypersets"

type_synonym 'a hyperset = "'a set option"

definition hyperUn :: "'a hyperset ⇒ 'a hyperset ⇒ 'a hyperset"   (infixl ‹⊔› 65)
where
  "A ⊔ B  ≡  case A of None ⇒ None
                 | ⌊A⌋ ⇒ (case B of None ⇒ None | ⌊B⌋ ⇒ ⌊A ∪ B⌋)"

definition hyperInt :: "'a hyperset ⇒ 'a hyperset ⇒ 'a hyperset"   (infixl ‹⊓› 70)
where
  "A ⊓ B  ≡  case A of None ⇒ B
                 | ⌊A⌋ ⇒ (case B of None ⇒ ⌊A⌋ | ⌊B⌋ ⇒ ⌊A ∩ B⌋)"

definition hyperDiff1 :: "'a hyperset ⇒ 'a ⇒ 'a hyperset"   (infixl ‹⊖› 65)
where
  "A ⊖ a  ≡  case A of None ⇒ None | ⌊A⌋ ⇒ ⌊A - {a}⌋"

definition hyper_isin :: "'a ⇒ 'a hyperset ⇒ bool"   (infix ‹∈∈› 50)
where
  "a ∈∈ A  ≡  case A of None ⇒ True | ⌊A⌋ ⇒ a ∈ A"

definition hyper_subset :: "'a hyperset ⇒ 'a hyperset ⇒ bool"   (infix ‹⊑› 50)
where
  "A ⊑ B  ≡  case B of None ⇒ True
                 | ⌊B⌋ ⇒ (case A of None ⇒ False | ⌊A⌋ ⇒ A ⊆ B)"

lemmas hyperset_defs =
 hyperUn_def hyperInt_def hyperDiff1_def hyper_isin_def hyper_subset_def

lemma [simp]: "⌊{}⌋ ⊔ A = A  ∧  A ⊔ ⌊{}⌋ = A"
(*<*)by(simp add:hyperset_defs)(*>*)

lemma [simp]: "⌊A⌋ ⊔ ⌊B⌋ = ⌊A ∪ B⌋ ∧ ⌊A⌋ ⊖ a = ⌊A - {a}⌋"
(*<*)by(simp add:hyperset_defs)(*>*)

lemma [simp]: "None ⊔ A = None ∧ A ⊔ None = None"
(*<*)by(simp add:hyperset_defs)(*>*)

lemma [simp]: "a ∈∈ None ∧ None ⊖ a = None"
(*<*)by(simp add:hyperset_defs)(*>*)

lemma hyper_isin_union: "x ∈∈ ⌊A⌋ ⟹ x ∈∈ ⌊A⌋ ⊔ B"
 by(case_tac B, auto simp: hyper_isin_def)

lemma hyperUn_assoc: "(A ⊔ B) ⊔ C = A ⊔ (B ⊔ C)"
(*<*)by(simp add:hyperset_defs Un_assoc)(*>*)

lemma hyper_insert_comm: "A ⊔ ⌊{a}⌋ = ⌊{a}⌋ ⊔ A ∧ A ⊔ (⌊{a}⌋ ⊔ B) = ⌊{a}⌋ ⊔ (A ⊔ B)"
(*<*)by(simp add:hyperset_defs)(*>*)

lemma hyper_comm: "A ⊔ B = B ⊔ A ∧ A ⊔ B ⊔ C = B ⊔ A ⊔ C"
(*<*)
proof(cases A)
  case SomeA: Some then show ?thesis
  proof(cases B)
    case SomeB: Some with SomeA show ?thesis
    proof(cases C)
      case SomeC: Some with SomeA SomeB show ?thesis
        by(simp add: Un_left_commute Un_commute)
    qed (simp add: Un_commute)
  qed simp
qed simp
(*>*)

subsection "Definite assignment"

primrec
  𝒜  :: "'a exp ⇒ 'a hyperset"
  and 𝒜s :: "'a exp list ⇒ 'a hyperset"
where
  "𝒜 (new C) = ⌊{}⌋"
| "𝒜 (Cast C e) = 𝒜 e"
| "𝒜 (Val v) = ⌊{}⌋"
| "𝒜 (e1 «bop» e2) = 𝒜 e1 ⊔ 𝒜 e2"
| "𝒜 (Var V) = ⌊{}⌋"
| "𝒜 (LAss V e) = ⌊{V}⌋ ⊔ 𝒜 e"
| "𝒜 (e∙F{D}) = 𝒜 e"
| "𝒜 (C∙sF{D}) = ⌊{}⌋"
| "𝒜 (e1∙F{D}:=e2) = 𝒜 e1 ⊔ 𝒜 e2"
| "𝒜 (C∙sF{D}:=e2) = 𝒜 e2"
| "𝒜 (e∙M(es)) = 𝒜 e ⊔ 𝒜s es"
| "𝒜 (C∙sM(es)) = 𝒜s es"
| "𝒜 ({V:T; e}) = 𝒜 e ⊖ V"
| "𝒜 (e1;;e2) = 𝒜 e1 ⊔ 𝒜 e2"
| "𝒜 (if (e) e1 else e2) =  𝒜 e ⊔ (𝒜 e1 ⊓ 𝒜 e2)"
| "𝒜 (while (b) e) = 𝒜 b"
| "𝒜 (throw e) = None"
| "𝒜 (try e1 catch(C V) e2) = 𝒜 e1 ⊓ (𝒜 e2 ⊖ V)"
| "𝒜 (INIT C (Cs,b) ← e) = ⌊{}⌋"
| "𝒜 (RI (C,e);Cs ← e') = 𝒜 e"

| "𝒜s ([]) = ⌊{}⌋"
| "𝒜s (e#es) = 𝒜 e ⊔ 𝒜s es"

primrec
  𝒟  :: "'a exp ⇒ 'a hyperset ⇒ bool"
  and 𝒟s :: "'a exp list ⇒ 'a hyperset ⇒ bool"
where
  "𝒟 (new C) A = True"
| "𝒟 (Cast C e) A = 𝒟 e A"
| "𝒟 (Val v) A = True"
| "𝒟 (e1 «bop» e2) A = (𝒟 e1 A ∧ 𝒟 e2 (A ⊔ 𝒜 e1))"
| "𝒟 (Var V) A = (V ∈∈ A)"
| "𝒟 (LAss V e) A = 𝒟 e A"
| "𝒟 (e∙F{D}) A = 𝒟 e A"
| "𝒟 (C∙sF{D}) A = True"
| "𝒟 (e1∙F{D}:=e2) A = (𝒟 e1 A ∧ 𝒟 e2 (A ⊔ 𝒜 e1))"
| "𝒟 (C∙sF{D}:=e2) A = 𝒟 e2 A"
| "𝒟 (e∙M(es)) A = (𝒟 e A ∧ 𝒟s es (A ⊔ 𝒜 e))"
| "𝒟 (C∙sM(es)) A = 𝒟s es A"
| "𝒟 ({V:T; e}) A = 𝒟 e (A ⊖ V)"
| "𝒟 (e1;;e2) A = (𝒟 e1 A ∧ 𝒟 e2 (A ⊔ 𝒜 e1))"
| "𝒟 (if (e) e1 else e2) A =
  (𝒟 e A ∧ 𝒟 e1 (A ⊔ 𝒜 e) ∧ 𝒟 e2 (A ⊔ 𝒜 e))"
| "𝒟 (while (e) c) A = (𝒟 e A ∧ 𝒟 c (A ⊔ 𝒜 e))"
| "𝒟 (throw e) A = 𝒟 e A"
| "𝒟 (try e1 catch(C V) e2) A = (𝒟 e1 A ∧ 𝒟 e2 (A ⊔ ⌊{V}⌋))"
| "𝒟 (INIT C (Cs,b) ← e) A = 𝒟 e A"
| "𝒟 (RI (C,e);Cs ← e') A = (𝒟 e A ∧ 𝒟 e' A)"

| "𝒟s ([]) A = True"
| "𝒟s (e#es) A = (𝒟 e A ∧ 𝒟s es (A ⊔ 𝒜 e))"

lemma As_map_Val[simp]: "𝒜s (map Val vs) = ⌊{}⌋"
(*<*)by (induct vs) simp_all(*>*)

lemma D_append[iff]: "⋀A. 𝒟s (es @ es') A = (𝒟s es A ∧ 𝒟s es' (A ⊔ 𝒜s es))"
(*<*)by (induct es type:list) (auto simp:hyperUn_assoc)(*>*)


lemma A_fv: "⋀A. 𝒜 e = ⌊A⌋ ⟹ A ⊆ fv e"
and  "⋀A. 𝒜s es = ⌊A⌋ ⟹ A ⊆ fvs es"
(*<*)
by (induct e and es rule: 𝒜.induct 𝒜s.induct)
   (fastforce simp add:hyperset_defs)+
(*>*)


lemma sqUn_lem: "A ⊑ A' ⟹ A ⊔ B ⊑ A' ⊔ B"
(*<*)by(simp add:hyperset_defs) blast(*>*)

lemma diff_lem: "A ⊑ A' ⟹ A ⊖ b ⊑ A' ⊖ b"
(*<*)by(simp add:hyperset_defs) blast(*>*)

(* This order of the premises avoids looping of the simplifier *)
lemma D_mono: "⋀A A'. A ⊑ A' ⟹ 𝒟 e A ⟹ 𝒟 (e::'a exp) A'"
and Ds_mono: "⋀A A'. A ⊑ A' ⟹ 𝒟s es A ⟹ 𝒟s (es::'a exp list) A'"
(*<*)
proof(induct e and es rule: 𝒟.induct 𝒟s.induct)
  case BinOp then show ?case by simp (iprover dest:sqUn_lem)
next
  case Var then show ?case by (fastforce simp add:hyperset_defs)
next
  case FAss then show ?case by simp (iprover dest:sqUn_lem)
next
  case Call then show ?case by simp (iprover dest:sqUn_lem)
next
  case Block then show ?case by simp (iprover dest:diff_lem)
next
  case Seq then show ?case by simp (iprover dest:sqUn_lem)
next
  case Cond then show ?case by simp (iprover dest:sqUn_lem)
next
  case While then show ?case by simp (iprover dest:sqUn_lem)
next
  case TryCatch then show ?case by simp (iprover dest:sqUn_lem)
next
  case Cons_exp then show ?case by simp (iprover dest:sqUn_lem)
qed simp_all
(*>*)

(* And this is the order of premises preferred during application: *)
lemma D_mono': "𝒟 e A ⟹ A ⊑ A' ⟹ 𝒟 e A'"
and Ds_mono': "𝒟s es A ⟹ A ⊑ A' ⟹ 𝒟s es A'"
(*<*)by(blast intro:D_mono, blast intro:Ds_mono)(*>*)


lemma Ds_Vals: "𝒟s (map Val vs) A" by(induct vs, auto)

end