(* Title: Jinja/DefAss.thy ID: $Id: DefAss.html 1910 2004-05-19 04:46:04Z kleing $ Author: Tobias Nipkow Copyright 2003 Technische Universitaet Muenchen *) header {* \isaheader{Definite assignment} *} theory DefAss = BigStep: subsection "Hypersets" types 'a hyperset = "'a set option" constdefs hyperUn :: "'a hyperset => 'a hyperset => 'a hyperset" (infixl "\<squnion>" 65) "A \<squnion> B ≡ case A of None => None | ⌊A⌋ => (case B of None => None | ⌊B⌋ => ⌊A ∪ B⌋)" hyperInt :: "'a hyperset => 'a hyperset => 'a hyperset" (infixl "\<sqinter>" 70) "A \<sqinter> B ≡ case A of None => B | ⌊A⌋ => (case B of None => ⌊A⌋ | ⌊B⌋ => ⌊A ∩ B⌋)" hyperDiff1 :: "'a hyperset => 'a => 'a hyperset" (infixl "\<ominus>" 65) "A \<ominus> a ≡ case A of None => None | ⌊A⌋ => ⌊A - {a}⌋" hyper_isin :: "'a => 'a hyperset => bool" (infix "∈∈" 50) "a ∈∈ A ≡ case A of None => True | ⌊A⌋ => a ∈ A" hyper_subset :: "'a hyperset => 'a hyperset => bool" (infix "\<sqsubseteq>" 50) "A \<sqsubseteq> 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]: "⌊{}⌋ \<squnion> A = A ∧ A \<squnion> ⌊{}⌋ = A" (*<*)by(simp add:hyperset_defs)(*>*) lemma [simp]: "⌊A⌋ \<squnion> ⌊B⌋ = ⌊A ∪ B⌋ ∧ ⌊A⌋ \<ominus> a = ⌊A - {a}⌋" (*<*)by(simp add:hyperset_defs)(*>*) lemma [simp]: "None \<squnion> A = None ∧ A \<squnion> None = None" (*<*)by(simp add:hyperset_defs)(*>*) lemma [simp]: "a ∈∈ None ∧ None \<ominus> a = None" (*<*)by(simp add:hyperset_defs)(*>*) lemma hyperUn_assoc: "(A \<squnion> B) \<squnion> C = A \<squnion> (B \<squnion> C)" (*<*)by(simp add:hyperset_defs Un_assoc)(*>*) lemma hyper_insert_comm: "A \<squnion> ⌊{a}⌋ = ⌊{a}⌋ \<squnion> A ∧ A \<squnion> (⌊{a}⌋ \<squnion> B) = ⌊{a}⌋ \<squnion> (A \<squnion> B)" (*<*)by(simp add:hyperset_defs)(*>*) subsection "Definite assignment" consts \<A> :: "'a exp => 'a hyperset" \<A>s :: "'a exp list => 'a hyperset" \<D> :: "'a exp => 'a hyperset => bool" \<D>s :: "'a exp list => 'a hyperset => bool" primrec "\<A> (new C) = ⌊{}⌋" "\<A> (Cast C e) = \<A> e" "\<A> (Val v) = ⌊{}⌋" "\<A> (e1 «bop» e2) = \<A> e1 \<squnion> \<A> e2" "\<A> (Var V) = ⌊{}⌋" "\<A> (LAss V e) = ⌊{V}⌋ \<squnion> \<A> e" "\<A> (e\<bullet>F{D}) = \<A> e" "\<A> (e1\<bullet>F{D}:=e2) = \<A> e1 \<squnion> \<A> e2" "\<A> (e\<bullet>M(es)) = \<A> e \<squnion> \<A>s es" "\<A> ({V:T; e}) = \<A> e \<ominus> V" "\<A> (e1;;e2) = \<A> e1 \<squnion> \<A> e2" "\<A> (if (e) e1 else e2) = \<A> e \<squnion> (\<A> e1 \<sqinter> \<A> e2)" "\<A> (while (b) e) = \<A> b" "\<A> (throw e) = None" "\<A> (try e1 catch(C V) e2) = \<A> e1 \<sqinter> (\<A> e2 \<ominus> V)" "\<A>s ([]) = ⌊{}⌋" "\<A>s (e#es) = \<A> e \<squnion> \<A>s es" primrec "\<D> (new C) A = True" "\<D> (Cast C e) A = \<D> e A" "\<D> (Val v) A = True" "\<D> (e1 «bop» e2) A = (\<D> e1 A ∧ \<D> e2 (A \<squnion> \<A> e1))" "\<D> (Var V) A = (V ∈∈ A)" "\<D> (LAss V e) A = \<D> e A" "\<D> (e\<bullet>F{D}) A = \<D> e A" "\<D> (e1\<bullet>F{D}:=e2) A = (\<D> e1 A ∧ \<D> e2 (A \<squnion> \<A> e1))" "\<D> (e\<bullet>M(es)) A = (\<D> e A ∧ \<D>s es (A \<squnion> \<A> e))" "\<D> ({V:T; e}) A = \<D> e (A \<ominus> V)" "\<D> (e1;;e2) A = (\<D> e1 A ∧ \<D> e2 (A \<squnion> \<A> e1))" "\<D> (if (e) e1 else e2) A = (\<D> e A ∧ \<D> e1 (A \<squnion> \<A> e) ∧ \<D> e2 (A \<squnion> \<A> e))" "\<D> (while (e) c) A = (\<D> e A ∧ \<D> c (A \<squnion> \<A> e))" "\<D> (throw e) A = \<D> e A" "\<D> (try e1 catch(C V) e2) A = (\<D> e1 A ∧ \<D> e2 (A \<squnion> ⌊{V}⌋))" "\<D>s ([]) A = True" "\<D>s (e#es) A = (\<D> e A ∧ \<D>s es (A \<squnion> \<A> e))" lemma As_map_Val[simp]: "\<A>s (map Val vs) = ⌊{}⌋" (*<*)by (induct vs) simp_all(*>*) lemma D_append[iff]: "!!A. \<D>s (es @ es') A = (\<D>s es A ∧ \<D>s es' (A \<squnion> \<A>s es))" (*<*)by (induct es type:list) (auto simp:hyperUn_assoc)(*>*) lemma A_fv: "!!A. \<A> e = ⌊A⌋ ==> A ⊆ fv e" and "!!A. \<A>s es = ⌊A⌋ ==> A ⊆ fvs es" (*<*) apply(induct e and es) apply (simp_all add:hyperset_defs) apply blast+ done (*>*) lemma sqUn_lem: "A \<sqsubseteq> A' ==> A \<squnion> B \<sqsubseteq> A' \<squnion> B" (*<*)by(simp add:hyperset_defs) blast(*>*) lemma diff_lem: "A \<sqsubseteq> A' ==> A \<ominus> b \<sqsubseteq> A' \<ominus> b" (*<*)by(simp add:hyperset_defs) blast(*>*) (* This order of the premises avoids looping of the simplifier *) lemma D_mono: "!!A A'. A \<sqsubseteq> A' ==> \<D> e A ==> \<D> (e::'a exp) A'" and Ds_mono: "!!A A'. A \<sqsubseteq> A' ==> \<D>s es A ==> \<D>s (es::'a exp list) A'" (*<*) apply(induct e and es) apply simp apply simp apply simp apply simp apply (rules dest:sqUn_lem) apply (fastsimp simp add:hyperset_defs) apply simp apply simp apply simp apply (rules dest:sqUn_lem) apply simp apply (rules dest:sqUn_lem) apply simp apply (rules dest:diff_lem) apply simp apply (rules dest:sqUn_lem) apply simp apply (rules dest:sqUn_lem) apply simp apply (rules dest:sqUn_lem) apply simp apply simp apply (rules dest:sqUn_lem) apply simp apply simp apply (rules dest:sqUn_lem) done (*>*) (* And this is the order of premises preferred during application: *) lemma D_mono': "\<D> e A ==> A \<sqsubseteq> A' ==> \<D> e A'" and Ds_mono': "\<D>s es A ==> A \<sqsubseteq> A' ==> \<D>s es A'" (*<*)by(blast intro:D_mono, blast intro:Ds_mono)(*>*) (* text{* @{term"\<A>"} is sound w.r.t.\ the big step semantics: it computes a conservative approximation of the variables actually assigned to. *} lemma "P \<turnstile> 〈e,(h0,l0)〉 => 〈e',(h1,l1)〉 ==> (!!A. \<A> e = ⌊A⌋ ==> A ⊆ dom l1)" and "P \<turnstile> 〈es,(h0,l0)〉 [=>] 〈es',(h1,l1)〉 ==> (!!A. \<A>s es = ⌊A⌋ ==> A ⊆ dom l1)" proof (induct rule:eval_evals_induct) case LAss thus ?case apply(simp add:dom_def hyperset_defs) apply blast apply blast next case FAss thus ?case by simp (blast dest:eval_lcl_incr) next case BinOp thus ?case by simp (blast dest:eval_lcl_incr) next case Call thus ?case by simp (blast dest:evals_lcl_incr) next case Cons thus ?case by simp (blast dest:evals_lcl_incr) next case Block thus ?case by(simp del: fun_upd_apply) blast next case Seq thus ?case by simp (blast dest:eval_lcl_incr) next case CondT thus ?case by simp (blast dest:eval_lcl_incr) next case CondF thus ?case by simp (blast dest:eval_lcl_incr) next case Try thus ?case by(fastsimp dest!: eval_lcl_incr) next case TryCatch thus ?case by(fastsimp dest!: eval_lcl_incr) qed auto *) end
lemmas hyperset_defs:
A \<squnion> B == case A of None => None | ⌊A⌋ => case B of None => None | ⌊B⌋ => ⌊A Un B⌋
A \<sqinter> B == case A of None => B | ⌊A⌋ => case B of None => ⌊A⌋ | ⌊B⌋ => ⌊A Int B⌋
A \<ominus> a == case A of None => None | ⌊A⌋ => ⌊A - {a}⌋
a ∈∈ A == option_case True (op : a) A
A \<sqsubseteq> B == case B of None => True | ⌊B⌋ => case A of None => False | ⌊A⌋ => A <= B
lemma
⌊{}⌋ \<squnion> A = A & A \<squnion> ⌊{}⌋ = A
lemma
⌊A⌋ \<squnion> ⌊B⌋ = ⌊A Un B⌋ & ⌊A⌋ \<ominus> a = ⌊A - {a}⌋
lemma
None \<squnion> A = None & A \<squnion> None = None
lemma
a ∈∈ None & None \<ominus> a = None
lemma hyperUn_assoc:
A \<squnion> B \<squnion> C = A \<squnion> (B \<squnion> C)
lemma hyper_insert_comm:
A \<squnion> ⌊{a}⌋ = ⌊{a}⌋ \<squnion> A & A \<squnion> (⌊{a}⌋ \<squnion> B) = ⌊{a}⌋ \<squnion> (A \<squnion> B)
lemma As_map_Val:
\<A>s (map Val vs) = ⌊{}⌋
lemma D_append:
\<D>s (es @ es') A = (\<D>s es A & \<D>s es' (A \<squnion> \<A>s es))
lemma A_fv:
\<A> e = ⌊A⌋ ==> A <= fv e
and
\<A>s es = ⌊A⌋ ==> A <= fvs es
lemma sqUn_lem:
A \<sqsubseteq> A' ==> A \<squnion> B \<sqsubseteq> A' \<squnion> B
lemma diff_lem:
A \<sqsubseteq> A' ==> A \<ominus> b \<sqsubseteq> A' \<ominus> b
lemma D_mono:
[| A \<sqsubseteq> A'; \<D> e A |] ==> \<D> e A'
and Ds_mono:
[| A \<sqsubseteq> A'; \<D>s es A |] ==> \<D>s es A'
lemma D_mono':
[| \<D> e A; A \<sqsubseteq> A' |] ==> \<D> e A'
and Ds_mono':
[| \<D>s es A; A \<sqsubseteq> A' |] ==> \<D>s es A'