Library topsy_hmAlloc
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq.
Require Import ZArith_ext ssrnat_ext.
Require Import integral_type bipl seplog.
Require Import topsy_hm topsy_hmAlloc_prg.
Require Import expr_b_dp.
Import seplog_Z_m.assert_m.expr_m.
Import seplog_Z_m.assert_m.
Import seplog_Z_m.
Local Close Scope positive_scope.
Local Open Scope heap_scope.
Local Open Scope seplog_expr_scope.
Local Open Scope seplog_assert_scope.
Local Open Scope seplog_cmd_scope.
Local Open Scope seplog_hoare_scope.
Require Import ZArith_ext ssrnat_ext.
Require Import integral_type bipl seplog.
Require Import topsy_hm topsy_hmAlloc_prg.
Require Import expr_b_dp.
Import seplog_Z_m.assert_m.expr_m.
Import seplog_Z_m.assert_m.
Import seplog_Z_m.
Local Close Scope positive_scope.
Local Open Scope heap_scope.
Local Open Scope seplog_expr_scope.
Local Open Scope seplog_assert_scope.
Local Open Scope seplog_cmd_scope.
Local Open Scope seplog_hoare_scope.
this file contains:
- 1. the verification of list traversal (findFree)
- 2. the verification of compaction (compact, original version and optimization)
- 3. the verification of splitting (split)
- 4. the verification of the allocation function (hmAlloc)
Local Close Scope Z_scope.
Definition findFree_specif := forall adr x sizex size,
size > 0 -> adr > 0 ->
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s }}
findFree size entry fnd sz stts
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
((exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y \&& nat_e y \> null ]b_s)
\/
[ var_e entry \= null ]b_s) }}.
Lemma findFree_verif : findFree_specif.
Proof.
rewrite /findFree_specif => adr x sizex size H H0.
rewrite /findFree.
entry <- var_e hmStart;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\ [ var_e entry \= nat_e adr ]b_s ).
move: H1 => [l [Hl [Hl' Hb]]].
exists l.
by Resolve_topsy.
stts <-* (entry -.> status);
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\ [ var_e entry \= nat_e adr ]b_s /\
[ var_e stts \= Allocated \|| var_e stts \= Free ]b_s).
move: H1 => [x0 [H1 [H4 [H2 [H6 H5]]]]].
destruct x0 as [|p x0]; first by rewrite //= in H4.
destruct p.
exists (hlstat_bool2expr b).
apply mapsto_strictly_exact; split.
- case: H1 => h1 [h2 [H1 [H7 [H3 H9]]]].
inversion_clear H3.
+ subst b nxt.
case_sepcon H13.
rewrite /= in H13_h31; case_sepcon H13_h31.
Compose_sepcon h311 (h312 \U h32 \U h4 \U h2); last by done.
rewrite /status; by Mapsto.
+ subst b nxt.
rewrite /= in H13; case_sepcon H13.
Compose_sepcon h31 (h32 \U h4 \U h2); last by done.
rewrite /status; by Mapsto.
- exists ((n, b) :: x0).
Resolve_topsy.
destruct b; rewrite eval_b_upd_subst; by omegab.
fnd <- cst_e 0
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\ [ var_e entry \= nat_e adr ]b_s /\
[ var_e stts \= Allocated \|| var_e stts \= Free ]b_s /\
[ var_e fnd \= nat_e 0 ]b_s).
case: H1 => x0 [H1 [H4 [H2 [H7 [H6 H5]]]]].
exists x0.
by Resolve_topsy.
while ((var_e entry \!= null) \&& (var_e fnd \!= cst_e 1
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\
(exists bloc_adr,
[ var_e entry \= nat_e bloc_adr ]b_s /\
((bloc_adr = 0 /\ [ var_e fnd \= nat_e 0 ]b_s) \/
(bloc_adr = get_endl l adr /\
[ var_e fnd \= nat_e 0 ]b_s /\
bloc_adr > 0) \/
(exists bloc_size bloc_status,
bloc_adr > 0 /\
In_hl l (bloc_adr, bloc_size, bloc_status) adr /\
[ var_e fnd \= nat_e 0 ]b_s) \/
exists bloc_size, bloc_size >= size /\
In_hl l (bloc_adr, bloc_size, topsy_hm.free) adr /\
[ var_e fnd \= nat_e 1 ]b_s /\
bloc_adr > 0))).
rewrite /while.entails => s h [l [H1 [H4 [H2 [H8 [H7 [H6 H5]]]]]]].
exists l; Resolve_topsy.
case : l H1 H4 => [|[n b] tl] H1 H4; first by done.
exists adr; Resolve_topsy.
right; right; left; exists n, b; Resolve_topsy.
by rewrite /= !eqxx.
rewrite /while.entails => s h [[x0 [H2 [H3 [H4 [H5 [x1 [H6 H8]]]]]]] H1].
exists x0; Resolve_topsy.
case: H8.
- case => ? H7; subst x1.
right; by omegab.
- case.
+ case => H7 [H8 H11].
move: (get_endl_gt x0 adr) => H9.
have H10 : [ var_e entry \!= null \&& var_e fnd \!= cst_e 1%Z ]b_s by omegab.
rewrite /hoare_m.eval_b in H1.
by rewrite H10 in H1.
+ case.
* case => x2 [x3 [H8 [H9 H10]]].
move: (get_endl_gt x0 adr) => H7.
have H11 : [ var_e entry \!= null \&& var_e fnd \!= cst_e 1%Z ]b_s by omegab.
rewrite /hoare_m.eval_b in H1.
by rewrite H11 in H1.
* move => [x2 [H7 [H10 [H11 H12]]]].
left; exists x1, x2; by Resolve_topsy.
stts <-* (entry -.> status);
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\
(exists bloc_adr, [ var_e entry \= nat_e bloc_adr ]b_s /\
((bloc_adr = get_endl l adr /\
[ var_e fnd \= nat_e O ]b_s /\
[ var_e stts \= Allocated ]b_s /\
bloc_adr > O) \/
exists bloc_size bloc_status,
In_hl l (bloc_adr, bloc_size, bloc_status) adr /\
[ var_e fnd \= nat_e O ]b_s /\
[ var_e stts \= hlstat_bool2expr bloc_status ]b_s /\
bloc_adr > O))).
move: H1 => [[x0 [H2 [H5 [H3 [H6 [x1 [H4 H8]]]]]]] H9].
case: H8.
- case => H1 H7; subst x1.
suff : False by done. omegab.
- case.
+ case => H1 [H7 H12].
subst x1.
exists Allocated.
apply mapsto_strictly_exact; split.
* move/hl_getstat_last : H2 => H2; case_sepcon H2.
Compose_sepcon h1 h2; [rewrite /status; by Mapsto | done].
* rewrite /wp_assign; exists x0.
split; first by Heap_List_equiv.
split; first by assumption.
Resolve_topsy.
exists (get_endl x0 adr).
Resolve_topsy.
left; by Resolve_topsy.
+ case.
* case => x2 [x3 [H8 [H11 H1]]].
case/In_hl_destruct : (H11) => [x4 [x5 [Hx0 H13]]].
exists (hlstat_bool2expr x3).
apply mapsto_strictly_exact; split.
rewrite Hx0 in H2; move/hl_getstatus : H2 => H10; case_sepcon H10.
Compose_sepcon h1 h2; [rewrite /status; by Mapsto | done].
rewrite /wp_assign; exists x0.
split; first by Heap_List_equiv.
Resolve_topsy.
exists (get_endl x4 adr); Resolve_topsy.
right; exists x2, x3; Resolve_topsy.
by rewrite H13.
destruct x3; rewrite eval_b_upd_subst; omegab.
by rewrite H13.
* case => x2 [H1 [H11 [H13 H8]]].
case/In_hl_destruct : (H11) => [x3 [x4 [H12 H14]]].
exists Free.
apply mapsto_strictly_exact; split.
rewrite H12 in H2; move/hl_getstatus : H2 => H2; case_sepcon H2.
Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign; exists x0.
split; first by Heap_List_equiv.
split; first by assumption.
Resolve_topsy.
exists (get_endl x3 adr); Resolve_topsy.
right; exists x2, topsy_hm.free; Resolve_topsy.
by rewrite H14.
by rewrite H14.
ENTRYSIZE entry sz;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\
(exists bloc_adr,
[ var_e entry \= nat_e bloc_adr ]b_s /\
((bloc_adr = get_endl l adr /\
[ var_e fnd \= nat_e 0 ]b_s /\
[ var_e stts \= Allocated ]b_s /\
bloc_adr > 0 /\
[ var_e sz \= nat_e 0 ]b_s) \/
exists bloc_size bloc_status,
In_hl l (bloc_adr, bloc_size, bloc_status) adr /\
[ var_e fnd \= nat_e 0 ]b_s /\
[ var_e stts \= hlstat_bool2expr bloc_status ]b_s /\
bloc_adr > 0 /\
[ var_e sz \= nat_e bloc_size ]b_s))).
rewrite /ENTRYSIZE.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\
(exists bloc_adr, [ var_e entry \= nat_e bloc_adr ]b_s /\
((bloc_adr = get_endl l adr /\
[ var_e fnd \= nat_e 0 ]b_s /\
[ var_e stts \= Allocated ]b_s /\
bloc_adr > 0 /\
[ var_e sz \= nat_e 0 ]b_s ) \/
(exists bloc_size bloc_status,
In_hl l (bloc_adr, bloc_size, bloc_status) adr /\
[ var_e fnd \= nat_e 0 ]b_s /\
[ var_e stts \= hlstat_bool2expr bloc_status ]b_s /\
bloc_adr > 0 /\
[ var_e sz \= nat_e (bloc_adr + 2 + bloc_size) ]b_s)))).
move: H1 => [x0 [H1 [H4 [H2 [H5 [x1 [H7 H9]]]]]]].
case: H9.
- case => [H11 [H3 [H8 H10]]].
exists null.
apply mapsto_strictly_exact; split.
move/hl_getnext_last : H1 => H1; case_sepcon H1.
Compose_sepcon h1 h2; [rewrite /next; by Mapsto | done].
rewrite /wp_assign; exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
left; by Resolve_topsy.
- move => [x2 [x3 [H10 [H11 [H3 H8]]]]].
move/In_hl_destruct : (H10) => [x4 [x5 [H9 H12]]].
exists (nat_e (x1 + 2 + x2)).
apply mapsto_strictly_exact; split.
rewrite H9 in H1; move/hl_getnext : H1 => H6.
case_sepcon H6.
Compose_sepcon h1 h2; last by done.
rewrite /next; by Mapsto.
rewrite /wp_assign; exists x0; Resolve_topsy.
exists (get_endl x4 adr); Resolve_topsy.
right; exists x2, x3; split.
by rewrite H12.
Resolve_topsy.
destruct x3; rewrite eval_b_upd_subst; by omegab.
by rewrite H12.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\ [ var_e hmStart \= nat_e adr ]b_s /\
[ var_e result \= null ]b_s /\
(exists bloc_adr, [ var_e entry \= nat_e bloc_adr ]b_s /\
((bloc_adr = get_endl l adr /\
[ var_e fnd \= nat_e 0 ]b_s /\
[ var_e stts \= Allocated ]b_s /\
bloc_adr > 0 /\
[ var_e sz \= nat_e 0 \- nat_e bloc_adr \- nat_e 2 ]b_s) \/
exists bloc_size bloc_status,
In_hl l (bloc_adr, bloc_size, bloc_status) adr /\
[ var_e fnd \= nat_e 0 ]b_s /\
[ var_e stts \= hlstat_bool2expr bloc_status ]b_s /\
bloc_adr > 0 /\
[ var_e sz \= nat_e bloc_size ]b_s))).
move: H1 => [x0 [H1 [H4 [H2 [H5 [x1 [H7 H3]]]]]]].
case: H3.
- move => [H10 [H3 [H11 [H8 H9]]]].
exists x0; Resolve_topsy.
exists (get_endl x0 adr); Resolve_topsy.
left; Resolve_topsy.
by omegab.
- move => [x2 [x3 [H9 [H10 [H3 [H11 H8]]]]]].
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
right; exists x2, x3; Resolve_topsy.
rewrite eval_b_upd_subst; by destruct x3; omegab.
ifte ((var_e stts \= Free) \&& (var_e sz \>= nat_e size)) thendo
Step TT.
Step TT.
move => s h [[x0 [H1 [H2 [H5 [H3 [x1 [H6 H8]]]]]]] H4].
case: H8.
- move => [H8 [H12 [H7 [H13 H10]]]].
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
left; by Resolve_topsy.
- move => [x2 [x3 [H8 [H11 [H7 [H12 H9]]]]]].
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
right; exists x2, x3; by Resolve_topsy.
Step TT.
rewrite /while.entails => s h [[x0 [H3 [H2 [H5 [H1 [x1 [H6 H8]]]]]]] H4].
exists x0; Resolve_topsy.
case: H8 => H7.
- move: H7 => [H12 [H7 [H13 [H10 H11]]]].
have H8 : [ nat_e 0 \> var_e sz ]b_s by omegab.
by rewrite H8 in H4.
- exists x1; by Resolve_topsy.
Step TT.
Step TT.
move => s h [[x0 [H2 [H5 [H3 [H6 [x1 [H8 H7]]]]]]] H9].
exists x0; split.
by apply Heap_List_inde_store with s.
Resolve_topsy.
exists x1; Resolve_topsy.
case: H7.
- move => [H4 [H12 [H1 [H13 H10]]]].
suff : False by done. omegab.
- move => [x2 [[] [H11 [H1 [H12 [H10 H13]]]]]].
+ simpl hlstat_bool2expr in H12.
right; right; right; exists x2.
split; first by omegab.
split; first by assumption.
rewrite eval_b_upd_subst; by intuition.
+ suff : False by done. omegab.
elsedo
(entry <-* (entry -.> next))).
Step TT.
rewrite /while.entails => s h [[x0 [H2 [H5 [H1 [H6 [x1 [H8 H4]]]]]]] H3].
case: H4.
- move => [H11 [H7 [H12 [H9 H14]]]].
exists (nat_e 0).
apply mapsto_strictly_exact; split.
move/hl_getnext_last : H2 => H2; case_sepcon H2.
Compose_sepcon h1 h2; [rewrite /next; by Mapsto | done].
rewrite /wp_assign.
exists x0; split.
by apply Heap_List_inde_store with s.
Resolve_topsy.
exists 0; Resolve_topsy.
left; by Resolve_topsy.
- case => [x2 [x3 [H11 [H7 [H12 [H9 H13]]]]]].
exists (nat_e (x1 + 2 +x2)).
apply mapsto_strictly_exact; split.
move/In_hl_destruct : H11 => [x4 [x5 [H15 H14]]].
rewrite H15 in H2.
move/hl_getnext : H2 => [h1 [h2 [H4 [H16 [H10 H17]]]]].
Compose_sepcon h1 h2; last by done.
rewrite /next; by Mapsto.
rewrite /wp_assign.
exists x0; split.
by apply Heap_List_inde_store with s.
Resolve_topsy.
exists (x1 + 2 + x2); Resolve_topsy.
move/In_hl_destruct : H11 => [x4 [x5 [H15 H14]]].
case: x5 H15 => [|[n b] x5] H15.
+ right; left; split.
by rewrite H15 get_endl_app H14.
split.
rewrite eval_b_upd_subst; by omegab.
ssromega.
+ right; right; left; exists n, b.
split; first by ssromega.
split.
rewrite H15; apply In_hl_or_app; right => /=.
case: ifP => // _.
by rewrite H14 /= !eqxx.
by rewrite eval_b_upd_subst; omegab.
Qed.
Definition brk := 10.
Definition tmp := 11.
Definition cstts := 12.
Definition nstts := 13.
Definition compact'_specif:= forall adr size x sizex,
size > 0 -> adr > 0 ->
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null \&& var_e cptr \= nat_e adr ]b_s }}
compact' cptr nptr brk tmp cstts nstts
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s }}.
Lemma compact'_verif: compact'_specif.
Proof.
rewrite /compact'_specif /compact' => adr size x sizex H H0.
while (var_e cptr \!= null) (
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
(exists cptr_value, [ var_e cptr \= nat_e cptr_value ]b_s /\
(cptr_value = 0 \/
cptr_value = get_endl l adr \/
exists cptr_size cptr_status, In_hl l (cptr_value, cptr_size, cptr_status) adr))).
rewrite /while.entails => s h [x0 [H2 [H5 H6]]].
exists x0.
split; first by assumption.
split; first by assumption.
split; first by omegab.
exists adr.
split; first by omegab.
case: x0 H2 H5 => [| [n b] x0] H2 H5.
- by rewrite /= in H5.
- right; right; exists n, b => /=.
by rewrite !eqxx.
rewrite /while.entails => s h [[x0 [H2 [H3 [H4 H5]]]] H6].
exists x0; by Resolve_topsy.
nptr <-* (cptr -.> next);
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
(exists cptr_value nptr_value,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e nptr \= nat_e nptr_value ]b_s /\
((cptr_value = get_endl l adr /\
nptr_value = 0) \/
exists cptr_size cptr_status,
In_hl l (cptr_value, cptr_size, cptr_status) adr /\
nptr_value = cptr_value + 2 + cptr_size))).
move: H1 => [[l [Hl [Hl' [Hs [cptr [Hs' [Hcptr' | [Hcptr' | [cptr_size [cptr_status Hl'']]]]]]]]]] Hcptr].
- subst cptr; by omegab.
- exists (nat_e 0).
apply mapsto_strictly_exact; split.
+ move/hl_getnext_last : Hl => Hl; case_sepcon Hl.
Compose_sepcon h1 h2; [rewrite /next; by Mapsto | done].
+ exists l; Resolve_topsy.
exists cptr, 0; by Resolve_topsy.
- exists (nat_e (cptr + 2 + cptr_size)).
apply mapsto_strictly_exact; split.
move/In_hl_destruct : Hl'' => [x0 [x1 [H5 H6]]].
rewrite H5 in Hl.
move/hl_getnext : Hl => H4'.
case_sepcon H4'.
Compose_sepcon h1 h2; [rewrite /next; by Mapsto | done].
exists l; Resolve_topsy.
exists cptr, (cptr + 2 + cptr_size); Resolve_topsy.
right; by exists cptr_size, cptr_status.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null \&& var_e brk \= nat_e 1 ]b_s /\
(exists cptr_value nptr_value,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e nptr \= nat_e nptr_value ]b_s /\
((cptr_value = get_endl l adr /\
nptr_value = 0) \/
exists cptr_size cptr_status,
In_hl l (cptr_value,cptr_size,cptr_status) adr /\
nptr_value = cptr_value + 2 + cptr_size))).
case: H1 => l [Hl [Hl' [Hb [cptr_value [nptr_value [Hcptr [Hnptr Htmp]]]]]]].
rewrite /wp_assign.
exists l; Resolve_topsy.
exists cptr_value, nptr_value; by Resolve_topsy.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null \&& var_e brk \= nat_e 1 ]b_s /\
(exists cptr_value nptr_value cstts_value,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e nptr \= nat_e nptr_value ]b_s /\
[ var_e cstts \= cstts_value ]b_s /\
((cptr_value = get_endl l adr /\
nptr_value = 0 /\
cstts_value = Allocated) \/
exists cptr_size cptr_status,
In_hl l (cptr_value,cptr_size,cptr_status) adr /\
nptr_value = cptr_value + 2 + cptr_size /\
cstts_value = (hlstat_bool2expr cptr_status)))).
case: H1 => l [Hl [Hl' [Hb [cptr_value [nptr_value [Hcptr [Hnptr []]]]]]]].
- case=> Hcptr_value Hnptr_value.
exists Allocated.
apply mapsto_strictly_exact; split.
move/hl_getstat_last : Hl => Hl; case_sepcon Hl.
Compose_sepcon h1 h2; [rewrite /status; by Mapsto | done].
exists l; Resolve_topsy.
exists cptr_value, nptr_value, Allocated; by Resolve_topsy.
- case=> cptr_size [cptr_status [Hl'' Hnptr_value]].
exists (hlstat_bool2expr cptr_status).
apply mapsto_strictly_exact; split.
move/In_hl_destruct : Hl'' => [l1 [l2 [Hl1l2 Hcptr_value]]].
rewrite Hl1l2 in Hl; move/hl_getstatus : Hl => Hl; case_sepcon Hl.
Compose_sepcon h1 h2; [rewrite /status; by Mapsto | done].
exists l; Resolve_topsy.
exists cptr_value, nptr_value, (hlstat_bool2expr cptr_status); Resolve_topsy.
by destruct cptr_status; Resolve_topsy.
right; exists cptr_size, cptr_status; by Resolve_topsy.
while ((var_e cstts \= Free) \&& (var_e nptr \!= null) \&& (var_e brk \= nat_e 1)) (
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
((exists cptr_value cptr_size brk_value,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e nptr \= nat_e (cptr_value + 2 + cptr_size) ]b_s /\
[ var_e cstts \= Free ]b_s /\
[ var_e brk \= nat_e brk_value ]b_s /\
In_hl l (cptr_value,cptr_size,topsy_hm.free) adr /\
((cptr_value + 2 + cptr_size = get_endl l adr /\ (brk_value = 0 \/ brk_value = 1)) \/
(exists nptr_size nptr_status,
In_hl l (cptr_value + 2 + cptr_size,nptr_size,nptr_status) adr /\
((nptr_status = true /\ brk_value = 1) \/
(nptr_status = false /\ (brk_value = 1 \/ brk_value = 0)))))) \/
(exists cptr_value nptr_value cstts_value,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e nptr \= nat_e nptr_value ]b_s /\
[ var_e cstts \= Allocated ]b_s /\
[ var_e brk \= nat_e 1 ]b_s /\
((cptr_value = get_endl l adr /\
nptr_value = 0 /\
cstts_value = Allocated) \/
(exists cptr_size cptr_status,
In_hl l (cptr_value,cptr_size,cptr_status) adr /\
nptr_value = cptr_value + 2 + cptr_size))))).
case : H1 => x0 [H2 [H5 [H7 [x1 [x2 [x3 [H13 [H11 [H12 H10]]]]]]]]].
exists x0; Resolve_topsy.
case: H10.
- case => H4 [H13' Hx3]; subst x3.
right; exists x1, x2, Allocated; by Resolve_topsy.
- case => x4 [[] [H4 [Hx2 Hx3]]]; subst x2 x3.
+ left; exists x1, x4, 1; Resolve_topsy.
move/In_hl_destruct : H4 => [x2 [x3 [Hx0 Hx1]]].
case : x3 Hx0 => [| [n b] x3] Hx0.
* left; rewrite Hx0 get_endl_app /=; ssromega.
* right; exists n, b.
split; last by destruct b; Resolve_topsy.
rewrite Hx0; apply In_hl_or_app; right => /=.
have : get_endl x2 adr != x1 + 2 + x4 by apply/eqP; ssromega.
move/negbTE => -> /=.
by rewrite Hx1 !eqxx.
+ right; exists x1, (x1 + 2 + x4), Allocated; Resolve_topsy.
right; by exists x4, false.
nstts <-* (nptr -.> status);
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
(exists cptr_value cptr_size brk_value,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e nptr \= nat_e (cptr_value + 2 + cptr_size) ]b_s /\
[ var_e cstts \= Free ]b_s /\
[ var_e brk \= nat_e brk_value ]b_s /\
In_hl l (cptr_value,cptr_size,topsy_hm.free) adr /\
((cptr_value + 2 + cptr_size = get_endl l adr /\ (brk_value = 0 \/ brk_value = 1) /\
[ var_e nstts \= Allocated ]b_s) \/
exists nptr_size nptr_status,
In_hl l (cptr_value + 2 + cptr_size,nptr_size,nptr_status) adr /\
((nptr_status = true /\ brk_value = 1) \/
(nptr_status = false /\ (brk_value = 1 \/ brk_value = 0))) /\
[ var_e nstts \= hlstat_bool2expr nptr_status ]b_s))).
case : H1 => [[x0 [H3 [H6 [H7 H8]]]] H2].
case : H8.
- case => cptr_val [cptr_sz [brk_val [H12 [H13 [H14 [H15 [H17 H16]]]]]]].
case: H16.
+ case => H15' H16.
exists Allocated.
rewrite /status.
apply mapsto_strictly_exact; split.
* move/hl_getstat_last : H3 => H3; case_sepcon H3.
Compose_sepcon h1 h2; [by Mapsto | done].
* rewrite /wp_assign; exists x0.
Resolve_topsy.
exists cptr_val, cptr_sz, brk_val; Resolve_topsy.
left; by Resolve_topsy.
+ case => x4 [x5 [H15' H16]].
exists (hlstat_bool2expr x5).
rewrite /status.
apply mapsto_strictly_exact; split.
* case/In_hl_destruct : H15' => x6 [x7 [H17' H18]].
rewrite H17' in H3; move/hl_getstatus : H3 => H3; case_sepcon H3.
Compose_sepcon h1 h2; [rewrite H18 in H3_h1; by Mapsto | done].
* rewrite /wp_assign; exists x0.
Resolve_topsy.
exists cptr_val, cptr_sz, brk_val; Resolve_topsy.
right; exists x4, x5; by destruct x5; Resolve_topsy.
- case => cptr_val [nptr_val [cstts_val [H12 [H13 [H14 [H15 H16]]]]]].
suff : False by done. omegab.
ifte (var_e nstts \!= Free) thendo (
Step TT.
brk <- nat_e 0
Step TT.
move=> s h H2.
case : H2 => [[x0 [H3 [H6 [H7 [x1 [x2 [x3 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]]] H4].
rewrite /wp_assign.
exists x0; Resolve_topsy.
left.
case: H13.
- case => H13 [H15 H16].
exists x1, x2, 0; by Resolve_topsy.
- case => x4 [x5 [H13 [H15 H16]]].
exists x1; exists x2, 0; Resolve_topsy.
right; exists x4, x5; Resolve_topsy.
destruct x5; omegab.
) elsedo (
tmp <-* nptr -.> next;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
(exists cptr_value cptr_size brk_value,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e nptr \= nat_e (cptr_value + 2 + cptr_size) ]b_s /\
[ var_e cstts \= Free ]b_s /\
[ var_e brk \= nat_e brk_value ]b_s /\
In_hl l (cptr_value, cptr_size, topsy_hm.free) adr /\
exists nptr_size nptr_status,
In_hl l (cptr_value + 2 + cptr_size, nptr_size, nptr_status) adr /\
(nptr_status = true /\ brk_value = 1) /\
[ var_e tmp \= nat_e (cptr_value + 2 + cptr_size + 2 + nptr_size) ]b_s)).
case : H1 => [[x0 [H3 [H6 [H7 [x1 [x2 [x3 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]]] H4].
case : H13.
- case => H13 [H15 H16].
suff : False by done. omegab.
- case => x4 [x5 [H13 [H15 H16]]].
destruct x5.
+ exists (nat_e (x1 + 2 + x2 + 2 + x4)).
rewrite /next.
apply mapsto_strictly_exact; split.
* case/In_hl_destruct : H13 => x5 [x6 [H5 H17]].
rewrite H5 in H3.
move/hl_getnext : H3 => H14.
case_sepcon H14.
Compose_sepcon h1 h2; last by done.
rewrite H17 in H14_h1; by Mapsto.
* exists x0; Resolve_topsy.
exists x1, x2, 1.
case: H15 => [ [_ H14] | [] // ].
subst x3; Resolve_topsy.
exists x4, true; by Resolve_topsy.
+ case: H15 => H5.
* by case: H5.
* suff : False by done. omegab.
cptr -.> next *<- var_e tmp ;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
(exists cptr_value cptr_size,
[ var_e cptr \= nat_e cptr_value ]b_s /\
[ var_e cstts \= Free ]b_s /\
[ var_e brk \= nat_e 1 ]b_s /\
In_hl l (cptr_value, cptr_size, topsy_hm.free) adr /\
[ var_e tmp \= nat_e (cptr_value + 2 + cptr_size) ]b_s)).
case : H1 => x0 [H2 [H5 [H6 [x1 [x2 [x3 [H10 [H11 [H12 [H13 [H14 [x4 [x5 [H15 [[H16 H18] H17]]]]]]]]]]]]]]].
case: (In_hl_next _ _ _ _ _ _ _ H14 H15) => x6 [x7 [H4 Hx1]].
subst x5 x3.
rewrite H4 /topsy_hm.free in H2.
case: (Heap_List_compaction x6 x7 x2 x4 _ s h H2) => x3 mem_s_h.
exists x3.
case_sepcon mem_s_h; Compose_sepcon h1 h2.
by rewrite /next; Mapsto.
move: mem_s_h_h2; apply monotony_imp => h' Hh'.
rewrite /next in Hh'; by Mapsto.
exists (x6 ++ (x2 + x4 + 2, topsy_hm.free) :: x7).
split; first by assumption.
split.
- rewrite H4 in H5.
case/In_hl_app_or : H5 => H18.
+ by apply In_hl_or_app; left.
+ apply In_hl_or_app; right.
move: H18.
rewrite /= /alloc /topsy_hm.free /= -andbA andbC /= -andbA andbC /=.
rewrite (_ : get_endl x6 adr + 2 + (x2 + x4 + 2) = get_endl x6 adr + 2 + x2 + 2 + x4) //; ssromega.
- Resolve_topsy.
exists x1, (x2 + 2 + x4); Resolve_topsy.
apply In_hl_or_app; right => /=.
rewrite Hx1 (_ : x2 + x4 + 2 = x2 + 2 + x4) //; last by ssromega.
by rewrite !eqxx.
nptr <- (var_e tmp)
Step TT.
move=> s h H2.
rewrite /wp_assign.
case : H2 => x0 [H2 [H5 [H3 [x1 [x2 [H9 [H11 [H7 [H8 H6]]]]]]]]].
exists x0; Resolve_topsy.
left; exists x1, x2, 1; Resolve_topsy.
case/In_hl_destruct : H8 => x3 [x4 [Hx0 H13]].
case : x4 Hx0 => [|[n b] x4] Hx0.
- left; rewrite Hx0 get_endl_app /= H13; tauto.
- right; exists n, b; split.
rewrite Hx0; apply In_hl_or_app; right => /=.
case: ifP => // _.
by rewrite H13 !eqxx.
destruct b; tauto.
)
);
cptr <-* (cptr -.> next)
).
Step TT.
rewrite /while.entails; move=> s h [[x0 [H3 [H6 [H7 H8]]]] H4].
case : H8.
- case => x1 [x2 [x3 [H12 [H5 [H11 [H9 [H10 H14]]]]]]].
case : H14.
+ case => H13 H14.
rewrite /next.
exists (nat_e (x1 + 2 + x2)).
apply mapsto_strictly_exact; split.
case/In_hl_destruct : H10 => x4 [x5 [H8 H16]].
rewrite H8 in H3; move/hl_getnext : H3 => H2'.
case_sepcon H2'; Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists (x1 + 2 + x2); by Resolve_topsy.
+ case => x4 [x5 [H13 H14]].
rewrite /next.
exists (nat_e (x1 + 2 + x2)).
apply mapsto_strictly_exact; split.
case/In_hl_destruct : H10 => x6 [x7 [H8 H16]].
rewrite H8 in H3; move/hl_getnext : H3 => H2'.
case_sepcon H2'; Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists (x1 + 2 + x2); Resolve_topsy.
right; right; by exists x4, x5.
- case => x1 [x2 [x3 [H5 [H11 [H9 [H10 H13]]]]]].
case: H13.
+ case => H12 [H14 H15].
unfold next.
exists (nat_e 0).
apply mapsto_strictly_exact; split.
move/hl_getnext_last : H3 => H3; case_sepcon H3.
subst x1 x2 x3.
Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists 0; by Resolve_topsy.
+ case => x4 [x5 [H12 H13]].
exists (nat_e (x1 + 2 + x4)).
unfold next.
apply mapsto_strictly_exact; split.
case/In_hl_destruct : H12 => x6 [x7 [H8 H15]].
rewrite H8 in H3; move/hl_getnext : H3 => H2'.
case_sepcon H2'; Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists (x1 + 2 + x4); Resolve_topsy.
right.
case/In_hl_destruct : H12 => x6 [x7 [H8 H15]].
case: x7 H8 => [|[n b] x7] H8.
* left; by rewrite H8 get_endl_app /= H15.
* right; exists n, b.
rewrite H8; apply In_hl_or_app; right => /=.
have : get_endl x6 adr <> x1 + 2 + x4 by ssromega.
move/eqP/negbTE => -> /=.
rewrite (_ : get_endl x6 adr + 2 + x4 = x1 + 2 + x4); last by congruence.
by rewrite !eqxx.
Qed.
Definition compact_specif := forall adr size sizex x,
size > 0 -> adr > 0 ->
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null \&& var_e cptr \= nat_e adr ]b_s }}
compact cptr nptr stts
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s }}.
Lemma compact_verif : compact_specif.
Proof.
unfold compact_specif.
intros.
unfold compact.
while (var_e cptr \!= null) (
Step (fun s h => exists l,
Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
(cur_adr = 0 \/
(cur_adr = get_endl l adr /\
cur_adr > 0) \/
(exists cur_size cur_status, In_hl l (cur_adr, cur_size, cur_status) adr /\
cur_adr > 0))).
rewrite /while.entails => s h [x0 [H1 [H4 H3]]].
exists x0; Resolve_topsy.
exists adr.
split; first by omegab.
case: x0 H1 H4 => [| [n b] x0] H1 H4.
- by rewrite /= in H4.
- right; right; exists n, b; split; last by done.
by rewrite /= !eqxx.
rewrite /while.entails => s h [[x0 [H2 [H3 [H4 H5]]]] H1].
exists x0; by Resolve_topsy.
stts <-* (cptr -.> status);
Step (fun s h => exists l,
Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
((cur_adr = get_endl l adr /\
cur_adr > 0 /\
[ var_e stts \= Allocated ]b_s) \/
(exists cur_size cur_status, In_hl l (cur_adr, cur_size, cur_status) adr /\
[ var_e stts \= hlstat_bool2expr cur_status ]b_s /\
cur_adr > 0))).
case : H1 => [[x0 [H2 [H4 [H5 [x1 [H8 H7]]]]]] H3].
case: H7 => [?|].
- subst x1; by omegab.
- case.
+ case => Hx1 H9.
exists (nat_e 0).
rewrite /status.
apply mapsto_strictly_exact; split.
move/hl_getstat_last : H2 => H2; case_sepcon H2.
Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
left; by Resolve_topsy.
+ case => x2 [x3 [In_hl_x0 H9]].
case/In_hl_destruct : (In_hl_x0) => x4 [x5 [H10 H11]].
rewrite /status.
exists (hlstat_bool2expr x3).
apply mapsto_strictly_exact; split.
* rewrite H10 in H2; move/hl_getstatus : H2 => H2; case_sepcon H2.
Compose_sepcon h1 h2; [by Mapsto | done].
* rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
right; exists x2, x3; Resolve_topsy.
by destruct x3; Resolve_topsy.
ifte (var_e stts \= Free) thendo (
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
((cur_adr = get_endl l adr /\ cur_adr > 0 ) \/
(exists cur_size cur_status, In_hl l (cur_adr, cur_size, cur_status) adr /\
cur_adr > 0))).
nptr <-* (cptr -.> next);
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
(exists cur_size, In_hl l (cur_adr, cur_size, topsy_hm.free) adr /\
[ var_e nptr \= nat_e (cur_adr + 2 + cur_size) ]b_s /\
cur_adr > 0)).
case : H1 => [[x0 [H2 [H4 [H5 [x1 [H6 H7]]]]]] H3].
case : H7.
- case => H7 [H10 H11].
suff : False by done. omegab.
- case => x2 [[] [H7 [H11 H10]]].
+ exists (nat_e (x1 + 2 + x2)).
unfold next.
apply mapsto_strictly_exact; split.
* case/In_hl_destruct : H7 => x3 [x4 [Hx0 H9]].
rewrite Hx0 in H2; move/hl_getnext : H2 => H12.
case_sepcon H12; Compose_sepcon h1 h2; [by Mapsto | done].
* rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
exists x2; by Resolve_topsy.
+ suff : False by done. omegab.
stts <-* (nptr -.> status);
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
(exists cur_size, In_hl l (cur_adr, cur_size, topsy_hm.free) adr /\
[ var_e nptr \= nat_e (cur_adr + 2 + cur_size) ]b_s /\
cur_adr > 0 /\ (
(exists next_size next_status,
In_hl l ((cur_adr + 2 + cur_size), next_size, next_status) adr /\
[ var_e stts \= hlstat_bool2expr next_status ]b_s) \/
(cur_adr + 2 + cur_size = get_endl l adr /\
[ var_e stts \= Allocated ]b_s)))).
case : H1 => x0 [H1 [H4 [H7 [x1 [H5 [x2 [H6 [H8 H9]]]]]]]].
case/In_hl_destruct : (H6) => x3 [x4 [H10 Hx1]].
case: x4 H10 => [|[n b] x4] H10.
- exists Allocated.
rewrite /status.
apply mapsto_strictly_exact; split.
+ rewrite H10 in H1; move/hl_getstat_last : H1 => H1; case_sepcon H1.
Compose_sepcon h1 h2; last by done.
rewrite get_endl_app in H1_h1; by Mapsto.
+ rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
exists x2; Resolve_topsy.
right; Resolve_topsy.
by rewrite -Hx1 H10 get_endl_app.
- exists (hlstat_bool2expr b).
rewrite /status.
apply mapsto_strictly_exact; split.
+ rewrite H10 in H1; Hl_getstatus H1 n H2; last by done.
rewrite get_endl_app [get_endl _]/= in H2_h1; by Mapsto.
+ exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
exists x2; Resolve_topsy.
left; exists n, b; split.
* rewrite H10; apply In_hl_or_app; right => /=.
have : get_endl x3 adr <> x1 + 2 + x2 by ssromega.
move/eqP/negbTE => -> /=.
by rewrite Hx1 !eqxx.
* by destruct b; Resolve_topsy.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
exists cur_size, In_hl l (cur_adr, cur_size, topsy_hm.free) adr /\
[ var_e nptr \= nat_e (cur_adr + 2 + cur_size) ]b_s /\
cur_adr > 0 /\ (
(exists next_size next_status,
In_hl l (cur_adr + 2 + cur_size, next_size, next_status) adr /\
[ var_e stts \= hlstat_bool2expr next_status ]b_s) \/
(cur_adr + 2 + cur_size = get_endl l adr /\
[ var_e stts \= Allocated ]b_s))).
done.
stts <-* (nptr -.> next);
rewrite /while.entails => s h [[x0 [H2 [H3 [H4 [x1 [H5 [x2 [H6 [H7 [H8 H9]]]]]]]]]] H1].
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
right; by exists x2, topsy_hm.free.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
exists cur_size, In_hl l (cur_adr, cur_size, topsy_hm.free) adr /\
[ var_e nptr \= nat_e (cur_adr + 2 + cur_size) ]b_s /\
cur_adr > 0 /\
exists next_size,
In_hl l (cur_adr + 2 + cur_size, next_size, topsy_hm.free) adr /\
[ var_e stts \= nat_e (cur_adr + 2 + cur_size + 2 + next_size) ]b_s).
case : H1 => [[x0 [H2 [H4 [H5 [x1 [H6 [x2 [H7 [H8 [H9 H11]]]]]]]]]] H3].
case: H11.
- case => x3 [x4 [H11 H12]].
destruct x4.
+ case/In_hl_destruct : (H11) => x4 [x5 [Hx0 H14]].
exists (nat_e (x1 + 2 + x2 + 2 +x3)).
rewrite /next.
apply mapsto_strictly_exact; split.
* rewrite Hx0 in H2; move/hl_getnext : H2 => H2.
case_sepcon H2; Compose_sepcon h1 h2; [by Mapsto | done].
* rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
exists x2; Resolve_topsy.
exists x3; Resolve_topsy.
+ suff : False by done. omegab.
- case => H11 H12.
suff : False by done. omegab.
(cptr -.> next) *<- var_e stts;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
exists cur_size,
In_hl l (cur_adr, cur_size, topsy_hm.free) adr /\
cur_adr > 0 /\
[ var_e stts \= nat_e (cur_adr + 2 + cur_size) ]b_s).
case : H1 => x0 [H1 [H4 [H5 [x1 [H6 [x2 [H7 [H8 [H9 [x3 [H10 H11]]]]]]]]]]].
case: (In_hl_next _ _ _ _ _ _ _ H7 H10) => x4 [x7 [H12 H13]].
rewrite /next.
rewrite H12 in H1; case/Heap_List_compaction : H1 => x5 H14.
case_sepcon H14.
exists x5.
Compose_sepcon h1 h2.
- by Mapsto.
- move: H14_h2; apply monotony_imp => h' Hh'; first by Mapsto.
exists (x4 ++ (x2 + x3 + 2, topsy_hm.free) :: x7).
split; first by done.
split.
* rewrite H12 in H4; case/In_hl_app_or : H4 => H4.
- apply In_hl_or_app; by left.
- apply In_hl_or_app; right.
move: H4.
rewrite /= /alloc /topsy_hm.free /= -andbA andbC /= -andbA andbC /=.
rewrite (_ : get_endl _ adr + 2 + (x2 + x3 + 2) = get_endl x4 adr + 2 + x2 + 2 + x3) //; ssromega.
* Resolve_topsy.
exists x1; Resolve_topsy.
exists (x2 + x3 + 2); split.
- apply In_hl_or_app; right => /=.
by rewrite -H13 !eqxx.
- split; [assumption | omegab].
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists cur_adr, [ var_e cptr \= nat_e cur_adr ]b_s /\
exists cur_size,
In_hl l (cur_adr, cur_size, topsy_hm.free) adr /\
cur_adr > 0 /\
[ var_e nptr \= nat_e (cur_adr + 2 + cur_size) ]b_s).
case : H1 => x0 [H1 [H4 [H5 [x1 [H6 [x2 [H8 [H9 H2]]]]]]]].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
exists x2; by Resolve_topsy.
Step TT.
rewrite /while.entails => s h [x0 [H1 [H4 [H5 [x1 [H6 [x2 [H8 [H9 H2]]]]]]]]].
case/In_hl_destruct : (H8) => x3 [x4 [H10 H11]].
case : x4 H10 => [|[n b] x4] H10.
- exists Allocated.
rewrite /status.
apply mapsto_strictly_exact; split.
+ move/hl_getstat_last : H1 => H1; case_sepcon H1.
rewrite H10 get_endl_app /= H11 in H1_h1.
Compose_sepcon h1 h2; [by Mapsto | done].
+ rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
exists x2; Resolve_topsy.
right; Resolve_topsy.
by rewrite H10 get_endl_app H11.
- exists (hlstat_bool2expr b).
rewrite /status.
apply mapsto_strictly_exact; split.
+ rewrite H10 in H1; Hl_getstatus H1 n H3; last by done.
rewrite get_endl_app [get_endl _]/= in H3_h1; by Mapsto.
+ rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
exists x2; Resolve_topsy.
left; exists n, b; split.
* rewrite H10; apply In_hl_or_app; right => /=.
have : get_endl x3 adr <> x1 + 2 + x2 by ssromega.
move/eqP/negbTE => -> /=.
by rewrite H11 !eqxx.
* by destruct b; Resolve_topsy.
elsedo
skip;
Step TT.
rewrite /while.entails => s h [[x0 [H2 [H5 [H7 [x1 [H6 H8]]]]]] H3].
exists x0; Resolve_topsy.
exists x1; Resolve_topsy.
case: H8.
- left; tauto.
- case => x2 [x3 [H11 [H10 H12]]].
right; exists x2, x3; by Resolve_topsy.
cptr <-* (cptr -.> next)).
Step TT.
rewrite /while.entails => s h [x0 [H1 [H4 [H2 [x1 [H5 H6]]]]]].
rewrite /next.
case: H6.
- case => H6 H8.
exists (nat_e 0).
apply mapsto_strictly_exact; split.
move/hl_getnext_last : H1 => H3; case_sepcon H3.
Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists 0; by Resolve_topsy.
- case => x2 [x3 [H6 H8]].
case/In_hl_destruct : H6 => x4 [x5 [H9 Hx1]].
exists (nat_e (x1 + 2 + x2)).
apply mapsto_strictly_exact; split.
+ rewrite H9 in H1; move/hl_getnext : H1 => H3.
case_sepcon H3; Compose_sepcon h1 h2; [by Mapsto | done].
+ rewrite /wp_assign.
exists x0; Resolve_topsy.
exists (x1 + 2 + x2); Resolve_topsy.
case : x5 H9 => [|[n b] x5] H9.
* right; left.
rewrite H9 get_endl_app Hx1 /=; ssromega.
* right; right; exists n, b.
split; last by ssromega.
rewrite H9; apply In_hl_or_app; right => /=.
have : get_endl x4 adr <> x1 + 2 + x2 by ssromega.
move/eqP/negbTE => -> /=.
by rewrite Hx1 !eqxx.
Qed.
Definition split_specif := forall adr size sizex x,
size > 0 -> adr > 0 ->
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x }}
split entry size cptr sz
{{ fun s h => exists l, In_hl l (x, sizex, alloc) adr /\
exists y, y > 0 /\ [ var_e entry \= nat_e y ]b_s /\
exists size'', size'' >= size /\
(Heap_List l adr ** Array (y + 2) size'') s h /\
In_hl l (y, size'', alloc) adr /\ y <> x }}.
Lemma split_verif : split_specif.
Proof.
rewrite /split_specif.
intros.
rewrite /split.
ENTRYSIZE entry sz;
rewrite /ENTRYSIZE /LEFTOVER.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x /\
[ var_e sz \= nat_e size'' ]b_s).
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x /\
[ var_e sz \= nat_e (y + 2 + size'') ]b_s).
case : H1 => x0 [H1 [H4 [H2 [x1 [x2 [H7 [H8 [H10 [H6 H5]]]]]]]]].
exists (nat_e (x1 + 2 + x2)).
rewrite /next.
apply mapsto_strictly_exact; split.
case/In_hl_destruct : H8 => x3 [x4 [H11 H12]].
rewrite H11 in H1; move/hl_getnext : H1 => H2'.
case_sepcon H2'; Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1, x2; by Resolve_topsy.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x /\
[ var_e sz \= nat_e size'' ]b_s).
case : H1 => x0 [H1 [H4 [H2 [x1 [x2 [H7 [H8 [H10 [H6 [H5 H9]]]]]]]]]].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1, x2; by Resolve_topsy.
Step TT.
Step TT.
move=> s h [[x0 [H1 [H4 [H2 [x1 [x2 [H7 [H8 [H10 [H6 [H5 H9]]]]]]]]]]] H1'].
suff : False by done. omegab.
Step TT.
rewrite /while.entails => *; tauto.
ifte (var_e sz \>= (nat_e size \+ nat_e LEFTOVER \+ nat_e 2)) thendo (
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x).
cptr <- var_e entry \+ nat_e 2 \+ nat_e size;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x /\
[ var_e sz \= nat_e size'' ]b_s /\
size'' >= size + LEFTOVER + 2 /\
[ var_e cptr \= nat_e (y + 2 + size) ]b_s).
unfold LEFTOVER.
case : H1 => [[x0 [H1 [H4 [H2 [x1 [x2 [H7 [H8 [H10 [H6 [H5 H9]]]]]]]]]]] H1'].
rewrite /wp_assign.
exists x0; Resolve_topsy.
exists x1, x2; Resolve_topsy; by omegab.
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x /\
[ var_e sz \= nat_e (y + 2 + size'') ]b_s /\
size'' >= size + LEFTOVER + 2 /\
[ var_e cptr \= nat_e (y + 2 + size) ]b_s).
case : H1 => x0 [H1 [H4 [H2 [x1 [x2 [H7 [H8 [H9 [H11 [H12 [H13 [H14 H15]]]]]]]]]]]].
exists (nat_e (x1 + 2 + x2)).
rewrite /next.
apply mapsto_strictly_exact; split.
case/In_hl_destruct : H8 => x3 [x4 [Hx0 Hx1]].
rewrite Hx0 in H1; move/hl_getnext : H1 => H2'.
case_sepcon H2'; Compose_sepcon h1 h2; [by Mapsto | done].
rewrite /wp_assign.
exists x0; Resolve_topsy.
by exists x1, x2; Resolve_topsy.
(cptr -.> next) *<- var_e sz;
Step (fun s h => exists e'',
(cptr -.> status |~> e'' **
(cptr -.> status |~> Free -*
(fun s0 h0 => exists e''0,
(entry -.> next |~> e''0 **
(entry -.> next |~> var_e cptr -*
(fun s1 h1 => exists l, Heap_List l adr s h1 /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s1 /\
exists y size'',
size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s1 /\
y > 0 /\ y <> x))) s0 h0))) s h).
case : H1 => x0 [H1 [H2 [H3 [x1 [x2 [H4 [H5 [H6 [H7 [H8 [H9 [H10 H11]]]]]]]]]]]].
rewrite (_ : x2 = size + 2 + (x2 - 2 - size)) in H5; last by ssromega.
case/In_hl_destruct : H5 => x3 [x4 [H3' H15]].
rewrite H3' in H1; case/Heap_List_splitting : H1 => x5 H16.
exists x5.
case_sepcon H16.
rewrite /next.
Compose_sepcon h1 h2.
rewrite H15 in H16_h1; by Mapsto.
rewrite /status.
move: H16_h2; apply assert_m.monotony_imp.
move=> h' Hh'; by Mapsto.
move=> h' Hh'.
case: Hh' => x6 H18.
exists x6.
case_sepcon H18.
Compose_sepcon h'1 h'2; first by Mapsto.
move: H18_h'2; apply monotony_imp.
move=> h'' Hh''; by Mapsto.
move=> h'' Hh''.
case: Hh'' => x7 H21.
exists x7.
case_sepcon H21.
Compose_sepcon h''1 h''2; first by Mapsto.
move: H21_h''2; apply monotony_imp.
move=> h''' Hh'''; by Mapsto.
move=> h''' Hh'''.
exists (x3 ++ (size, true) :: (x2 - 2 - size, true) :: x4).
split; first by assumption.
Resolve_topsy.
- rewrite H3' in H2; case/In_hl_app_or : H2 => H2.
- apply In_hl_or_app; by left.
- apply In_hl_or_app; right.
move: H2.
do 2 rewrite /= /alloc /topsy_hm.free /= -andbA andbC /=.
by rewrite !addnA.
exists x1, size; Resolve_topsy.
apply In_hl_or_app; right => /=.
by rewrite H15 !eqxx.
Step (fun s0 h0 => exists e'',
(entry -.> next |~> e'' **
(entry -.> next |~> var_e cptr -*
(fun s h => exists l,
Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0 /\ y <> x))) s0 h0).
assumption.
(entry -.> next) *<- var_e cptr)
Step TT.
by apply hoare_prop_m.entails_id.
elsedo
skip
Step TT.
rewrite /while.entails => s h [[x0 [H1 [H4 [H2 [x1 [x2 [H7 [H8 [H10 [H6 [H5 H9]]]]]]]]]]] H1'].
exists x0; Resolve_topsy.
exists x1, x2; by Resolve_topsy.
(entry -.> status) *<- Allocated.
Step TT.
rewrite /while.entails => s h [x0 [H1 [H2 [H3 [x1 [x2 [H4 [H5 [H6 [H7 H8]]]]]]]]]].
case/In_hl_destruct : H5 => x3 [x4 [H11 H12]].
rewrite H11 in H1; case/hl_free2alloc : H1 => x5 H1.
case_sepcon H1.
exists x5.
rewrite /status.
Compose_sepcon h1 h2; first by Mapsto.
move: H1_h2; apply monotony_imp => h' Hh'; first by Mapsto.
case_sepcon Hh'.
exists (x3 ++ (x2,false) :: x4).
Resolve_topsy.
- rewrite H11 in H2; case/In_hl_app_or : H2 => H2.
- apply In_hl_or_app; by left.
- rewrite /= /alloc /topsy_hm.free /= -andbA andbC /= in H2.
apply In_hl_or_app; right => /=.
have : get_endl x3 adr <> x by lia.
by move/eqP/negbTE => ->.
- exists x1; Resolve_topsy.
exists x2; Resolve_topsy.
Compose_sepcon h'1 h'2; [done | by Array_equiv].
apply In_hl_or_app; right.
by rewrite /= H12 !eqxx.
Qed.
Definition hmAlloc_specif := forall adr x sizex size, adr > 0 -> size > 0 ->
{{ fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr ]b_s }}
hmAlloc result size entry cptr fnd stts nptr sz
{{ fun s h =>
(exists l y, y > 0 /\ [ var_e result \= nat_e (y + 2) ]b_s /\
exists size'', size'' >= size /\
(Heap_List l adr ** Array (y + 2) size'') s h /\
In_hl l (x, sizex, alloc) adr /\ In_hl l (y, size'', alloc) adr /\
x <> y)
\/
(exists l, [ var_e result \= nat_e 0 ]b_s /\
Heap_List l adr s h /\ In_hl l (x, sizex, alloc) adr) }}.
Lemma hmAlloc_verif: hmAlloc_specif.
Proof.
rewrite /hmAlloc_specif /hmAlloc => adr x sizex size H H0.
result <- null;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s).
case : H1 => x0 [H1 [H4 H5]].
rewrite /wp_assign.
exists x0; by Resolve_topsy.
findFree size entry fnd sz stts;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
((exists y size'',
size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ (var_e entry \= nat_e y) ]b_s /\
y > 0) \/
[ var_e entry \= null ]b_s)).
move: (findFree_verif adr x sizex size H0 H) => H1.
Step TT. - rewrite /while.entails => s h [x0 [H2 [H4 [H3 H6]]]] {H1}.
exists x0; Resolve_topsy.
case : H6 => H1.
+ case : H1 => x1 [x2 [H5 [H7 H1]]].
left; exists x1, x2; Resolve_topsy.
omegab.
+ by right.
- by apply hoare_prop_m.entails_id.
ifte (var_e entry \= null) thendo (
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s /\
((exists y size'', size'' >= size /\
In_hl l (y, size'', topsy_hm.free) adr /\
[ var_e entry \= nat_e y ]b_s /\
y > 0) \/ [ var_e entry \= null ]b_s)).
cptr <- var_e hmStart;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr ]b_s /\ [ var_e result \= null ]b_s /\
[ var_e entry \= null ]b_s /\ [ var_e cptr \= var_e hmStart ]b_s).
case : H1 => [[x0 [H2 [H5 [H4 H7]]]] H6].
case : H7.
- case => x1 [x2 [H7 [H9 [H11 H8]]]].
suff : False by done. omegab.
- exists x0; by Resolve_topsy.
compact cptr nptr stts;
Step (fun s h => exists l, Heap_List l adr s h /\
In_hl l (x, sizex, alloc) adr /\
[ var_e hmStart \= nat_e adr \&& var_e result \= null ]b_s).
move: (compact_verif adr size sizex x H0 H) => H1.
Step TT.
- rewrite /while.entails => {H1} s h [x0 [H1 [H4 H2]]].
exists x0; by Resolve_topsy.
- rewrite /while.entails => s h [x0 [H2 [H5 [H9 [H7 [H6 H4]]]]]].
exists x0; by Resolve_topsy.
move: (findFree_verif adr x sizex size H0 H) => H1.
findFree size entry fnd sz stts
Step TT. - rewrite /while.entails => s h [x0 [H2 [H5 [H7 H3]]]].
exists x0; Resolve_topsy.
case : H3 => H4.
+ case : H4 => x1 [x2 [H3 [H8 H4]]].
left; exists x1, x2; Resolve_topsy.
by omegab.
+ by right.
- done.
) elsedo
skip
Step TT.
rewrite /while.entails; intros; tauto.
ifte (var_e entry \= null) thendo (
Step TT.
result <- HM_ALLOCFAILED
Step TT.
move=> s h H1.
rewrite /wp_assign.
case : H1 => [[x0 [H2 [H5 [H3 H7]]]] H4].
case : H7 => H1.
- case : H1 => x1 [x2 [H7 [H9 [H11 H8]]]].
suff : False by done. omegab.
- right; exists x0; by Resolve_topsy.
) elsedo (
split entry size cptr sz;
Step (fun s h => exists l y, y > 0 /\
[ var_e entry \= nat_e y ]b_s /\
exists size', size' >= size /\
(Heap_List l adr ** Array (y + 2) size') s h /\
In_hl l (x, sizex, alloc) adr /\
In_hl l (y, size', alloc) adr /\ x <> y).
move: (split_verif adr size sizex x H0 H) => H1.
Step TT. - rewrite /while.entails => {H1} s h [x0 [H1 [x1 [H2 [H3 [x2 [H4 [H5 [H6 H7]]]]]]]]].
exists x0, x1; Resolve_topsy.
exists x2; by Resolve_topsy.
- rewrite /while.entails => {H1} s h [[x0 [H2 [H5 [H7 H1]]]] H3].
case : H1 => H4.
+ case: H4 => x1 [x2 [H8 [H9 H11]]].
exists x0; Resolve_topsy.
exists x1, x2; Resolve_topsy.
tauto.
omegab.
by apply (In_hl_dif _ _ _ _ _ _ H5 H9).
+ by omegab.
result <- var_e entry \+ nat_e 2
).
Step TT.
rewrite /wp_assign => s h [x0 [x1 [H2 [H3 [x2 [H4 [H5 [H6 [H7 H8]]]]]]]]].
left; exists x0, x1; Resolve_topsy.
exists x2; Resolve_topsy.
case_sepcon H5.
Compose_sepcon h1 h2.
by Resolve_topsy.
by Array_equiv.
Qed.