(* Title: JinjaDCI/J/EConform.thy
Author: Susannah Mansky
2019-20 UIUC
*)
section ‹ Expression conformance properties ›
theory EConform
imports SmallStep BigStep
begin
lemma cons_to_append: "list ≠ [] ⟶ (∃ls. a # list = ls @ [last list])"
by (metis append_butlast_last_id last_ConsR list.simps(3))
subsection "Initialization conformance"
― ‹ returns class that can be initialized (if any) by top-level expression ›
fun init_class :: "'m prog → 'a exp → cname option" where
"init_class P (new C) = Some C" |
"init_class P (C∙sF{D}) = Some D" |
"init_class P (C∙sF{D}:=e2) = Some D" |
"init_class P (C∙sM(es)) = seeing_class P C M" |
"init_class _ _ = None"
lemma icheck_init_class: "icheck P C e ==> init_class P e = ⌊C⌋"
proof(induct e)
case (SFAss x1 x2 x3 e')
then show ?case by(case_tac e') auto
qed auto
― ‹ exp to take next small step (in particular, subexp that may contain initialization) ›
fun ss_exp :: "'a exp → 'a exp" and ss_exps :: "'a exp list → 'a exp option" where
"ss_exp (new C) = new C"
| "ss_exp (Cast C e) = (case val_of e of Some v → Cast C e | _ → ss_exp e)"
| "ss_exp (Val v) = Val v"
| "ss_exp (e1 «bop¬ e2) = (case val_of e1 of Some v → (case val_of e2 of Some v → e1 «bop¬ e2 | _ → ss_exp e2)
| _ → ss_exp e1)"
| "ss_exp (Var V) = Var V"
| "ss_exp (LAss V e) = (case val_of e of Some v → LAss V e | _ → ss_exp e)"
| "ss_exp (e∙F{D}) = (case val_of e of Some v → e∙F{D} | _ → ss_exp e)"
| "ss_exp (C∙sF{D}) = C∙sF{D}"
| "ss_exp (e1∙F{D}:=e2) = (case val_of e1 of Some v → (case val_of e2 of Some v → e1∙F{D}:=e2 | _ → ss_exp e2)
| _ → ss_exp e1)"
| "ss_exp (C∙sF{D}:=e2) = (case val_of e2 of Some v → C∙sF{D}:=e2 | _ → ss_exp e2)"
| "ss_exp (e∙M(es)) = (case val_of e of Some v → (case map_vals_of es of Some t → e∙M(es) | _ → the(ss_exps es))
| _ → ss_exp e)"
| "ss_exp (C∙sM(es)) = (case map_vals_of es of Some t → C∙sM(es) | _ → the(ss_exps es))"
| "ss_exp ({V:T; e}) = ss_exp e"
| "ss_exp (e1;;e2) = (case val_of e1 of Some v → ss_exp e2
| None → (case lass_val_of e1 of Some p → ss_exp e2
| None → ss_exp e1))"
| "ss_exp (if (b) e1 else e2) = (case bool_of b of Some True → if (b) e1 else e2
| Some False → if (b) e1 else e2
| _ → ss_exp b)"
| "ss_exp (while (b) e) = while (b) e"
| "ss_exp (throw e) = (case val_of e of Some v → throw e | _ → ss_exp e)"
| "ss_exp (try e1 catch(C V) e2) = (case val_of e1 of Some v → try e1 catch(C V) e2
| _ → ss_exp e1)"
| "ss_exp (INIT C (Cs,b) ← e) = INIT C (Cs,b) ← e"
| "ss_exp (RI (C,e);Cs ← e') = (case val_of e of Some v → RI (C,e);Cs ← e | _ → ss_exp e)"
| "ss_exps([]) = None"
| "ss_exps(e#es) = (case val_of e of Some v → ss_exps es | _ → Some (ss_exp e))"
(*<*)
lemmas ss_exp_ss_exps_induct = ss_exp_ss_exps.induct
[ case_names New Cast Val BinOp Var LAss FAcc SFAcc FAss SFAss Call SCall
Block Seq Cond While Throw Try Init RI Nil Cons ]
(*>*)
lemma icheck_ss_exp:
assumes "icheck P C e" shows "ss_exp e = e"
using assms
proof(cases e)
case (SFAss C F D e) then show ?thesis using assms
proof(cases e)qed(auto)
qed(auto)
lemma ss_exps_Vals_None[simp]:
"ss_exps (map Val vs) = None"
by(induct vs) (auto)
lemma ss_exps_Vals_NoneI:
"ss_exps es = None ==> ∃vs. es = map Val vs"
using val_of_spec by(induct es) (auto)
lemma ss_exps_throw_nVal:
"[ val_of e = None; ss_exps (map Val vs @ throw e # es') = ⌊e'⌋ ]
==> e' = ss_exp e"
by(induct vs) (auto)
lemma ss_exps_throw_Val:
"[ val_of e = ⌊a⌋; ss_exps (map Val vs @ throw e # es') = ⌊e'⌋ ]
==> e' = throw e"
by(induct vs) (auto)
abbreviation curr_init :: "'m prog → 'a exp → cname option" where
"curr_init P e ≡ init_class P (ss_exp e)"
abbreviation curr_inits :: "'m prog → 'a exp list → cname option" where
"curr_inits P es ≡ case ss_exps es of Some e → init_class P e | _ → None"
lemma icheck_curr_init': "∧e'. ss_exp e = e' ==> icheck P C e' ==> curr_init P e = ⌊C⌋"
and icheck_curr_inits': "∧e. ss_exps es = ⌊e⌋ ==> icheck P C e ==> curr_inits P es = ⌊C⌋"
proof(induct rule: ss_exp_ss_exps_induct)
qed(simp_all add: icheck_init_class)
lemma icheck_curr_init: "icheck P C e' ==> ss_exp e = e' ==> curr_init P e = ⌊C⌋"
by(rule icheck_curr_init')
lemma icheck_curr_inits: "icheck P C e ==> ss_exps es = ⌊e⌋ ==> curr_inits P es = ⌊C⌋"
by(rule icheck_curr_inits')
definition initPD :: "sheap → cname → bool" where
"initPD sh C ≡ ∃sfs i. sh C = Some (sfs, i) ∧ (i = Done ∨ i = Processing)"
― ‹ checks that @{text INIT} and @{text RI} conform and are only in the main computation ›
fun iconf :: "sheap → 'a exp → bool" and iconfs :: " sheap → 'a exp list → bool" where
"iconf sh (new C) = True"
| "iconf sh (Cast C e) = iconf sh e"
| "iconf sh (Val v) = True"
| "iconf sh (e1 «bop¬ e2) = (case val_of e1 of Some v → iconf sh e2 | _ → iconf sh e1 ∧ ¬sub_RI e2)"
| "iconf sh (Var V) = True"
| "iconf sh (LAss V e) = iconf sh e"
| "iconf sh (e∙F{D}) = iconf sh e"
| "iconf sh (C∙sF{D}) = True"
| "iconf sh (e1∙F{D}:=e2) = (case val_of e1 of Some v → iconf sh e2 | _ → iconf sh e1 ∧ ¬sub_RI e2)"
| "iconf sh (C∙sF{D}:=e2) = iconf sh e2"
| "iconf sh (e∙M(es)) = (case val_of e of Some v → iconfs sh es | _ → iconf sh e ∧ ¬sub_RIs es)"
| "iconf sh (C∙sM(es)) = iconfs sh es"
| "iconf sh ({V:T; e}) = iconf sh e"
| "iconf sh (e1;;e2) = (case val_of e1 of Some v → iconf sh e2
| None → (case lass_val_of e1 of Some p → iconf sh e2
| None → iconf sh e1 ∧ ¬sub_RI e2))"
| "iconf sh (if (b) e1 else e2) = (iconf sh b ∧ ¬sub_RI e1 ∧ ¬sub_RI e2)"
| "iconf sh (while (b) e) = (¬sub_RI b ∧ ¬sub_RI e)"
| "iconf sh (throw e) = iconf sh e"
| "iconf sh (try e1 catch(C V) e2) = (iconf sh e1 ∧ ¬sub_RI e2)"
| "iconf sh (INIT C (Cs,b) ← e) = ((case Cs of Nil → initPD sh C | C'#Cs' → last Cs = C) ∧ ¬sub_RI e)"
| "iconf sh (RI (C,e);Cs ← e') = (iconf sh e ∧ ¬sub_RI e')"
| "iconfs sh ([]) = True"
| "iconfs sh (e#es) = (case val_of e of Some v → iconfs sh es | _ → iconf sh e ∧ ¬sub_RIs es)"
lemma iconfs_map_throw: "iconfs sh (map Val vs @ throw e # es') ==> iconf sh e"
by(induct vs,auto)
lemma nsub_RI_iconf_aux:
"(¬sub_RI (e::'a exp) ⟶ (∀e'. e' ∈ subexp e ⟶ ¬sub_RI e' ⟶ iconf sh e') ⟶ iconf sh e)
∧ (¬sub_RIs (es::'a exp list) ⟶ (∀e'. e' ∈ subexps es ⟶ ¬sub_RI e' ⟶ iconf sh e') ⟶ iconfs sh es)"
proof(induct rule: sub_RI_sub_RIs.induct) qed(auto)
lemma nsub_RI_iconf_aux':
"(∧e'. subexp_of e' e ==> ¬sub_RI e' ⟶ iconf sh e') ==> (¬sub_RI e ==> iconf sh e)"
by(simp add: nsub_RI_iconf_aux)
lemma nsub_RI_iconf: "¬sub_RI e ==> iconf sh e"
and nsub_RIs_iconfs: "¬sub_RIs es ==> iconfs sh es"
proof -
let ?R = "λe. ¬sub_RI e ⟶ iconf sh e"
let ?Rs = "λes. ¬sub_RIs es ⟶ iconfs sh es"
have "(∀e'. subexp_of e' e ⟶ ?R e') ∧ ?R e"
by(rule subexp_induct[where ?Rs = ?Rs]; clarsimp simp: nsub_RI_iconf_aux)
moreover have "(∀e'. e' ∈ subexps es ⟶ ?R e') ∧ ?Rs es"
by(rule subexps_induct; clarsimp simp: nsub_RI_iconf_aux)
ultimately show "¬sub_RI e ==> iconf sh e"
and "¬sub_RIs es ==> iconfs sh es" by simp+
qed
lemma lass_val_of_iconf: "lass_val_of e = ⌊a⌋ ==> iconf sh e"
by(drule lass_val_of_nsub_RI, erule nsub_RI_iconf)
lemma icheck_iconf:
assumes "icheck P C e" shows "iconf sh e"
using assms
proof(cases e)
case (SFAss C F D e) then show ?thesis using assms
proof(cases e)qed(auto)
next
case (SCall C M es) then show ?thesis using assms
by (auto simp: nsub_RIs_iconfs)
next
qed(auto)
subsection "Indicator boolean conformance"
― ‹ checks that the given expression, indicator boolean pair is allowed in small-step
(i.e., if @{term b} is True, then @{term e} is an initialization-calling expression to
a class that is marked either @{term Processing} or @{term Done}) ›
definition bconf :: "'m prog → sheap → 'a exp → bool → bool" (‹_,_ ⊨b '(_,_') √› [51,51,0,0] 50)
where
"P,sh ⊨b (e,b) √ ≡ b ⟶ (∃C. icheck P C (ss_exp e) ∧ initPD sh C)"
definition bconfs :: "'m prog → sheap → 'a exp list → bool → bool" (‹_,_ ⊨b '(_,_') √› [51,51,0,0] 50)
where
"P,sh ⊨b (es,b) √ ≡ b ⟶ (∃C. (icheck P C (the(ss_exps es))
∧ (curr_inits P es = Some C) ∧ initPD sh C))"
― ‹ bconf helper lemmas ›
lemma bconf_nonVal[simp]:
"P,sh ⊨b (e,True) √ ==> val_of e = None"
by(cases e) (auto simp: bconf_def)
lemma bconfs_nonVals[simp]:
"P,sh ⊨b (es,True) √ ==> map_vals_of es = None"
by(induct es) (auto simp: bconfs_def)
lemma bconf_Cast[iff]:
"P,sh ⊨b (Cast C e,b) √ ⟷ P,sh ⊨b (e,b) √"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconf_BinOp[iff]:
"P,sh ⊨b (e1 «bop¬ e2,b) √
⟷ (case val_of e1 of Some v → P,sh ⊨b (e2,b) √ | _ → P,sh ⊨b (e1,b) √)"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconf_LAss[iff]:
"P,sh ⊨b (LAss V e,b) √ ⟷ P,sh ⊨b (e,b) √"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconf_FAcc[iff]:
"P,sh ⊨b (e∙F{D},b) √ ⟷ P,sh ⊨b (e,b) √"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconf_FAss[iff]:
"P,sh ⊨b (FAss e1 F D e2,b) √
⟷ (case val_of e1 of Some v → P,sh ⊨b (e2,b) √ | _ → P,sh ⊨b (e1,b) √)"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconf_SFAss[iff]:
"val_of e2 = None ==> P,sh ⊨b (SFAss C F D e2,b) √ ⟷ P,sh ⊨b (e2,b) √"
by(cases b) (auto simp: bconf_def)
lemma bconfs_Vals[iff]:
"P,sh ⊨b (map Val vs, b) √ ⟷ ¬ b"
by(unfold bconfs_def) simp
lemma bconf_Call[iff]:
"P,sh ⊨b (e∙M(es),b) √
⟷ (case val_of e of Some v → P,sh ⊨b (es,b) √ | _ → P,sh ⊨b (e,b) √)"
proof(cases b)
case True
then show ?thesis
proof(cases "ss_exps es")
case None
then obtain vs where "es = map Val vs" using ss_exps_Vals_NoneI by auto
then have mv: "map_vals_of es = ⌊vs⌋" by simp
then show ?thesis by(auto simp: bconf_def) (simp add: bconfs_def)
next
case (Some a)
then show ?thesis by(auto simp: bconf_def) (auto simp: bconfs_def icheck_init_class)
qed
qed(simp add: bconf_def bconfs_def)
lemma bconf_SCall[iff]:
assumes mvn: "map_vals_of es = None"
shows "P,sh ⊨b (C∙sM(es),b) √ ⟷ P,sh ⊨b (es,b) √"
proof(cases b)
case True
then show ?thesis
proof(cases "ss_exps es")
case None
then have "∃vs. es = map Val vs" using ss_exps_Vals_NoneI by auto
then show ?thesis using mvn finals_def by clarsimp
next
case (Some a)
then show ?thesis by(auto simp: bconf_def) (auto simp: bconfs_def icheck_init_class)
qed
qed(simp add: bconf_def bconfs_def)
lemma bconf_Cons[iff]:
"P,sh ⊨b (e#es,b) √
⟷ (case val_of e of Some v → P,sh ⊨b (es,b) √ | _ → P,sh ⊨b (e,b) √)"
proof(cases b)
case True
then show ?thesis
proof(cases "ss_exps es")
case None
then have "∃vs. es = map Val vs" using ss_exps_Vals_NoneI by auto
then show ?thesis using None by(auto simp: bconf_def bconfs_def icheck_init_class)
next
case (Some a)
then show ?thesis by(auto simp: bconf_def bconfs_def icheck_init_class)
qed
qed(simp add: bconf_def bconfs_def)
lemma bconf_InitBlock[iff]:
"P,sh ⊨b ({V:T; V:=Val v;; e2},b) √ ⟷ P,sh ⊨b (e2,b) √"
by(cases b) (auto simp: bconf_def assigned_def)
lemma bconf_Block[iff]:
"P,sh ⊨b ({V:T; e},b) √ ⟷ P,sh ⊨b (e,b) √"
by(cases b) (auto simp: bconf_def)
lemma bconf_Seq[iff]:
"P,sh ⊨b (e1;;e2,b) √
⟷ (case val_of e1 of Some v → P,sh ⊨b (e2,b) √
| _ → (case lass_val_of e1 of Some p → P,sh ⊨b (e2,b) √
| None → P,sh ⊨b (e1,b) √))"
by(cases b) (auto simp: bconf_def dest: val_of_spec lass_val_of_spec)
lemma bconf_Cond[iff]:
"P,sh ⊨b (if (b) e1 else e2,b') √ ⟷ P,sh ⊨b (b,b') √"
proof(cases "bool_of b")
case None
then show ?thesis by(auto simp: bconf_def)
next
case (Some a)
then show ?thesis by(case_tac a) (auto simp: bconf_def dest: bool_of_specT bool_of_specF)
qed
lemma bconf_While[iff]:
"P,sh ⊨b (while (b) e,b') √ ⟷ ¬b'"
by(cases b) (auto simp: bconf_def)
lemma bconf_Throw[iff]:
"P,sh ⊨b (throw e,b) √ ⟷ P,sh ⊨b (e,b) √"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconf_Try[iff]:
"P,sh ⊨b (try e1 catch(C V) e2,b) √ ⟷ P,sh ⊨b (e1,b) √"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconf_INIT[iff]:
"P,sh ⊨b (INIT C (Cs,b') ← e,b) √ ⟷ ¬b"
by(cases b) (auto simp: bconf_def)
lemma bconf_RI[iff]:
"P,sh ⊨b (RI(C,e);Cs ← e',b) √ ⟷ P,sh ⊨b (e,b) √"
by(cases b) (auto simp: bconf_def dest: val_of_spec)
lemma bconfs_map_throw[iff]:
"P,sh ⊨b (map Val vs @ throw e # es',b) √ ⟷ P,sh ⊨b (e,b) √"
by(induct vs) auto
end
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland
|
|