summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSon Ho2023-01-21 16:45:11 +0100
committerSon HO2023-06-04 21:54:38 +0200
commitd67375c62c7486bb531de616cf6978467c67ee46 (patch)
treeae297aa5fab356893b270a8f989eb801482daefb
parent0436980177c786a7f608cca27844ac3228912a11 (diff)
Add a more interesting example
Diffstat (limited to '')
-rw-r--r--backends/hol4/Test.sml70
1 files changed, 69 insertions, 1 deletions
diff --git a/backends/hol4/Test.sml b/backends/hol4/Test.sml
index 55915fbc..b16b67fb 100644
--- a/backends/hol4/Test.sml
+++ b/backends/hol4/Test.sml
@@ -1391,7 +1391,75 @@ Proof
progress >> progress
QED
-(* *)
+(* Example from the hashmap *)
+val _ = new_constant ("insert", “: u32 -> 't -> (u32 # 't) list_t -> (u32 # 't) list_t result”)
+val insert_def = new_axiom ("insert_def", “
+ insert (key : u32) (value : 't) (ls : (u32 # 't) list_t) : (u32 # 't) list_t result =
+ case ls of
+ | ListCons (ckey, cvalue) tl =>
+ if ckey = key
+ then Return (ListCons (ckey, value) tl)
+ else
+ do
+ tl0 <- insert key value tl;
+ Return (ListCons (ckey, cvalue) tl0)
+ od
+ | ListNil => Return (ListCons (key, value) ListNil)
+ ”)
+
+(* Property that keys are pairwise distinct *)
+val distinct_keys_def = Define ‘
+ distinct_keys (ls : (u32 # 't) list) =
+ !i j.
+ i < LENGTH ls ==>
+ j < LENGTH ls ==>
+ FST (EL i ls) = FST (EL j ls) ==>
+ i = j
+’
+
+val lookup_raw_def = Define ‘
+ lookup_raw key [] = NONE /\
+ lookup_raw key ((k, v) :: ls) =
+ if k = key then SOME v else lookup_raw key ls
+’
+
+val lookup_def = Define ‘
+ lookup key ls = lookup_raw key (list_t_v ls)
+’
+
+Theorem insert_lem:
+ !ls key value.
+ (* The keys are pairwise distinct *)
+ distinct_keys (list_t_v ls) ==>
+ case insert key value ls of
+ | Return ls1 =>
+ (* We updated the binding *)
+ lookup key ls1 = SOME value /\
+ (* The other bindings are left unchanged *)
+ (!k. k <> key ==> lookup k ls = lookup k ls1)
+ | Fail _ => F
+ | Loop => F
+Proof
+ Induct_on ‘ls’ >> rw [list_t_v_def] >~ [‘ListNil’] >>
+ PURE_ONCE_REWRITE_TAC [insert_def] >> rw []
+ >- (rw [lookup_def, lookup_raw_def, list_t_v_def])
+ >- (rw [lookup_def, lookup_raw_def, list_t_v_def]) >>
+ CASE_TAC >> rw []
+ >- (rw [lookup_def, lookup_raw_def, list_t_v_def])
+ >- (rw [lookup_def, lookup_raw_def, list_t_v_def]) >>
+ progress
+ >- (
+ fs [distinct_keys_def] >>
+ rpt strip_tac >>
+ first_assum (qspecl_then [‘SUC i’, ‘SUC j’] ASSUME_TAC) >>
+ fs []
+ (* Alternative: *)
+ (*
+ PURE_ONCE_REWRITE_TAC [GSYM prim_recTheory.INV_SUC_EQ] >>
+ first_assum irule >> fs []
+ *)) >>
+ fs [lookup_def, lookup_raw_def, list_t_v_def]
+QED
(***
* Example of how to get rid of the fuel in practice