lib: add generic lemmas from SELFOUR-584 updates

Mainly concerning word_ctz and enumeration_both.
This commit is contained in:
Rafal Kolanski 2018-06-13 18:54:38 +10:00
parent a837d38012
commit d4996217b3
6 changed files with 138 additions and 3 deletions

View File

@ -1088,6 +1088,8 @@ lemmas corres_split_noop_rhs
lemmas corres_split_noop_rhs2
= corres_split_nor[THEN corres_add_noop_lhs2]
lemmas corres_split_dc = corres_split[where r'=dc, simplified]
lemma isLeft_case_sum:
"isLeft v \<Longrightarrow> (case v of Inl v' \<Rightarrow> f v' | Inr v' \<Rightarrow> g v') = f (theLeft v)"
by (clarsimp simp: isLeft_def)
@ -1111,6 +1113,34 @@ lemma corres_return_eq_same:
apply (simp add: corres_underlying_def return_def)
done
lemmas corres_discard_r =
corres_symb_exec_r [where P'=P' and Q'="\<lambda>_. P'" for P', simplified]
lemmas corres_returnTT = corres_return[where P=\<top> and P'=\<top>, THEN iffD2]
lemma corres_assert_gen_asm:
"\<lbrakk> F \<Longrightarrow> corres_underlying sr nf nf' r P Q f (g ()) \<rbrakk>
\<Longrightarrow> corres_underlying sr nf nf' r (P and (\<lambda>_. F)) Q f (assert F >>= g)"
by (simp add: corres_gen_asm)
lemma corres_assert_gen_asm2:
"\<lbrakk> F \<Longrightarrow> corres_underlying sr nf nf' r P Q f (g ()) \<rbrakk>
\<Longrightarrow> corres_underlying sr nf nf' r P (Q and (\<lambda>_. F)) f (assert F >>= g)"
by (simp add: corres_gen_asm2)
lemma corres_add_guard:
"\<lbrakk>\<And>s s'. \<lbrakk>Q s; Q' s'; (s, s') \<in> sr\<rbrakk> \<Longrightarrow> P s \<and> P' s';
corres_underlying sr nf nf' r (Q and P) (Q' and P') f g\<rbrakk> \<Longrightarrow>
corres_underlying sr nf nf' r Q Q' f g"
by (auto simp: corres_underlying_def)
(* safer non-rewrite version of corres_gets *)
lemma corres_gets_trivial:
"\<lbrakk>\<And>s s'. (s,s') \<in> sr \<Longrightarrow> f s = f' s' \<rbrakk>
\<Longrightarrow> corres_underlying sr nf nf' op = \<top> \<top> (gets f) (gets f')"
unfolding corres_underlying_def gets_def get_def return_def bind_def
by clarsimp
text {* Some setup of specialised methods. *}
lemma (in strengthen_implementation) wpfix_strengthen_corres_guard_imp:

View File

@ -336,6 +336,9 @@ lemma fromIntegral_simp3[simp]: "fromIntegral = ucast"
apply (simp add: unat_def)
done
lemma fromIntegral_simp_nat[simp]: "(fromIntegral :: nat \<Rightarrow> nat) = id"
by (simp add: fromIntegral_def fromInteger_nat toInteger_nat)
definition
infix_apply :: "'a \<Rightarrow> ('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> 'b \<Rightarrow> 'c" ("_ `~_~` _" [81, 100, 80] 80) where
infix_apply_def[simp]:

View File

@ -471,4 +471,46 @@ lemma foldl_fun_or_alt:
apply clarsimp
by (simp add: foldl_map)
lemma length_takeWhile_less:
"\<exists>x\<in>set xs. \<not> P x \<Longrightarrow> length (takeWhile P xs) < length xs"
by (induct xs) (auto split: if_splits)
(* FIXME move to Word_Lib (note needs lemmas from Lib/LemmaBucket) *)
lemma word_ctz_le:
"word_ctz (w :: ('a::len word)) \<le> LENGTH('a)"
apply (clarsimp simp: word_ctz_def)
apply (rule nat_le_Suc_less_imp[where y="LENGTH('a) + 1" , simplified])
apply (rule order_le_less_trans[OF List.length_takeWhile_le])
apply simp
done
(* FIXME move to Word_Lib (note needs lemmas from Lib/LemmaBucket) *)
lemma word_ctz_less:
"w \<noteq> 0 \<Longrightarrow> word_ctz (w :: ('a::len word)) < LENGTH('a)"
apply (clarsimp simp: word_ctz_def eq_zero_set_bl)
apply (rule order_less_le_trans[OF length_takeWhile_less])
apply fastforce+
done
lemma suc_le_pow_2:
"1 < (n::nat) \<Longrightarrow> Suc n < 2 ^ n"
by (induct n; clarsimp)
(case_tac "n = 1"; clarsimp)
lemma word_ctz_not_minus_1:
"1 < LENGTH('a) \<Longrightarrow> of_nat (word_ctz (w :: ('a :: len) word)) \<noteq> (- 1 :: ('a::len) word)"
apply (cut_tac w=w in word_ctz_le)
apply (subst word_unat.Rep_inject[symmetric])
apply (subst unat_of_nat_eq)
apply (erule order_le_less_trans, fastforce)
apply (subst unat_minus_one_word)
apply (rule less_imp_neq)
apply (erule order_le_less_trans)
apply (subst less_eq_Suc_le)
apply (subst le_diff_conv2, fastforce)
apply (clarsimp simp: le_diff_conv2 less_eq_Suc_le[symmetric] suc_le_pow_2)
done
lemmas word_ctz_not_minus_1_32 = word_ctz_not_minus_1[where 'a=32, simplified]
end

View File

@ -800,11 +800,11 @@ lemma no_fail_returnOK [simp, wp]:
text {* Empty results implies non-failure *}
lemma empty_fail_modify [simp]:
lemma empty_fail_modify [simp, wp]:
"empty_fail (modify f)"
by (simp add: empty_fail_def simpler_modify_def)
lemma empty_fail_gets [simp]:
lemma empty_fail_gets [simp, wp]:
"empty_fail (gets f)"
by (simp add: empty_fail_def simpler_gets_def)
@ -826,7 +826,7 @@ lemma empty_fail_bind [simp]:
apply (clarsimp simp: ex_in_conv [symmetric])
done
lemma empty_fail_return [simp]:
lemma empty_fail_return [simp, wp]:
"empty_fail (return x)"
by (simp add: empty_fail_def return_def)

View File

@ -196,6 +196,16 @@ lemma monadic_rewrite_symb_exec_r:
apply simp
done
lemma monadic_rewrite_symb_exec_r':
"\<lbrakk> \<And>s. \<lbrace>op = s\<rbrace> m \<lbrace>\<lambda>r. op = s\<rbrace>; no_fail P m;
\<And>rv. monadic_rewrite F False (Q rv) x (y rv);
\<lbrace>P\<rbrace> m \<lbrace>Q\<rbrace> \<rbrakk>
\<Longrightarrow> monadic_rewrite F False P x (m >>= y)"
apply (rule monadic_rewrite_imp)
apply (rule monadic_rewrite_symb_exec_r; assumption)
apply simp
done
lemma monadic_rewrite_symb_exec_l'':
"\<lbrakk> \<And>s. \<lbrace>op = s\<rbrace> m \<lbrace>\<lambda>r. op = s\<rbrace>; empty_fail m;
\<not> F \<longrightarrow> no_fail P' m;

View File

@ -610,6 +610,46 @@ lemma upto_enum_set_conv2:
shows "set [a .e. b] = {a .. b}"
by auto
lemma fromEnum_upto_nth:
fixes start :: "'a :: enumeration_both"
assumes "n < length [start .e. end]"
shows "fromEnum ([start .e. end] ! n) = fromEnum start + n"
proof -
have less_sub: "\<And>m k m' n. \<lbrakk> (n::nat) < m - k ; m \<le> m' \<rbrakk> \<Longrightarrow> n < m' - k" by fastforce
note upt_Suc[simp del]
show ?thesis using assms
by (fastforce simp: upto_enum_red from_to_enum
dest: less_sub[where m'="Suc (fromEnum maxBound)"] intro: maxBound_is_bound)
qed
lemma length_upto_enum_le_maxBound:
fixes start :: "'a :: enumeration_both"
shows "length [start .e. end] \<le> Suc (fromEnum (maxBound :: 'a))"
apply (clarsimp simp add: upto_enum_red split: if_splits)
apply (rule le_imp_diff_le[OF maxBound_is_bound[of "end"]])
done
lemma less_length_upto_enum_maxBoundD:
fixes start :: "'a :: enumeration_both"
assumes "n < length [start .e. end]"
shows "n \<le> fromEnum (maxBound :: 'a)"
using assms
by (simp add: upto_enum_red less_Suc_eq_le
le_trans[OF _ le_imp_diff_le[OF maxBound_is_bound[of "end"]]]
split: if_splits)
lemma fromEnum_eq_iff:
"(fromEnum e = fromEnum f) = (e = f)"
proof -
have a: "e \<in> set enum" by auto
have b: "f \<in> set enum" by auto
from nth_the_index[OF a] nth_the_index[OF b] show ?thesis unfolding fromEnum_def by metis
qed
lemma maxBound_is_bound':
"i = fromEnum (e::('a::enum)) \<Longrightarrow> i \<le> fromEnum (maxBound::('a::enum))"
by (clarsimp simp: maxBound_is_bound)
lemma of_nat_unat [simp]:
"of_nat \<circ> unat = id"
by (rule ext, simp)
@ -5590,4 +5630,14 @@ lemma sign_extend_eq:
"w && mask (Suc n) = v && mask (Suc n) \<Longrightarrow> sign_extend n w = sign_extend n v"
by (rule word_eqI, fastforce dest: word_eqD simp: sign_extend_bitwise_if' word_size)
lemma unat_minus_one_word:
"unat (-1 :: 'a :: len word) = 2 ^ len_of TYPE('a) - 1"
by (subst minus_one_word)
(subst unat_sub_if', clarsimp)
lemma of_nat_eq_signed_scast:
"(of_nat x = (y :: ('a::len) signed word))
= (of_nat x = (scast y :: 'a word))"
by (metis scast_of_nat scast_scast_id(2))
end