-
Notifications
You must be signed in to change notification settings - Fork 0
/
Verif_bst.v
993 lines (963 loc) · 28.8 KB
/
Verif_bst.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
Require Import VST.floyd.proofauto.
Require Import VST.floyd.library.
(* CompCert-generated representation of bst.c *)
Require Import bst.
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
Require Import Coq.Program.Equality.
(* Require Import StructTact.StructTactics. *)
Require Import my_tactics.
Require Import bst_spec.
Require Import bst_holes.
(* BST representations *)
Definition t_bst := Tstruct _bst noattr.
Fixpoint bst_rep (b: bst Z) (p: val): mpred :=
match b with
| leaf => (!! (p = nullval)) && emp
| node (k, v) l r =>
EX pl pr: val,
malloc_token Ews t_bst p *
data_at Ews t_bst (Vint (Int.repr k), (Vint (Int.repr v), (pl, pr))) p *
bst_rep l pl *
bst_rep r pr
end.
Theorem generalize_node_rep : forall (p pl pr: val) k v l r,
(malloc_token Ews t_bst p *
data_at Ews t_bst (Vint (Int.repr k), (Vint (Int.repr v), (pl, pr))) p *
bst_rep l pl *
bst_rep r pr
|-- bst_rep (node (k,v) l r) p
)%logic.
Proof.
intros.
expand bst_rep.
repeat EExists.
entailer!.
Qed.
Fixpoint bst_hole_rep (b: bst_hole Z) (p pHole: val): mpred :=
match b with
| hole => (!! (p = pHole)) && emp
| node_hole_l (k, v) l r =>
EX pl pr: val,
malloc_token Ews t_bst p *
data_at Ews t_bst (Vint (Int.repr k), (Vint (Int.repr v), (pl, pr))) p *
bst_hole_rep l pl pHole *
bst_rep r pr
| node_hole_r (k, v) l r =>
EX pl pr: val,
malloc_token Ews t_bst p *
data_at Ews t_bst (Vint (Int.repr k), (Vint (Int.repr v), (pl, pr))) p *
bst_rep l pl *
bst_hole_rep r pr pHole
end.
Definition ptr_to_bst_rep b p := EX q, data_at Ews (tptr t_bst) q p * bst_rep b q.
Theorem generalize_ptr_to_node_rep : forall b p q,
data_at Ews (tptr t_bst) q p * bst_rep b q |-- ptr_to_bst_rep b p.
Proof.
intros.
unfold ptr_to_bst_rep.
EExists.
entailer!.
Qed.
Fixpoint ptr_to_bst_hole_rep b p pHole :=
match b with
| hole => !! (p = pHole) && emp
| node_hole_l (k,v) l r =>
EX (q pr: val),
data_at Ews (tptr t_bst) q p *
malloc_token Ews t_bst q *
field_at Ews t_bst [StructField _key] (Vint (Int.repr k)) q *
field_at Ews t_bst [StructField _val] (Vint (Int.repr v)) q *
field_at Ews t_bst [StructField _right] pr q *
ptr_to_bst_hole_rep l (field_address t_bst [StructField _left] q) pHole *
bst_rep r pr
| node_hole_r (k,v) l r =>
EX (q pl: val),
data_at Ews (tptr t_bst) q p *
malloc_token Ews t_bst q *
field_at Ews t_bst [StructField _key] (Vint (Int.repr k)) q *
field_at Ews t_bst [StructField _val] (Vint (Int.repr v)) q *
field_at Ews t_bst [StructField _left] pl q *
bst_rep l pl *
ptr_to_bst_hole_rep r (field_address t_bst [StructField _right] q) pHole
end.
Lemma bst_rep_local_prop: forall b p,
bst_rep b p |-- !! (is_pointer_or_null p /\ (p = nullval <-> b = leaf)).
Proof.
intros b p. induction b; unfold bst_rep.
- entailer!. tauto.
- destruct a.
fold bst_rep.
entailer.
entailer!.
split.
+ intro; subst.
eapply field_compatible_nullval. eassumption.
+ discriminate.
Qed.
Hint Resolve bst_rep_local_prop : saturate_local.
Lemma bst_rep_valid_pointer: forall b p,
bst_rep b p |-- valid_pointer p.
Proof.
intros b p. induction b; unfold bst_rep; try destruct a; entailer.
Qed.
Hint Resolve bst_rep_valid_pointer : valid_pointer.
(* Function specifications *)
Definition new_bst_spec: ident * funspec :=
DECLARE _new_bst
WITH k: Z, v: Z, gv: globals
PRE [tint, tint]
PROP (repable_signed k; repable_signed v)
PARAMS (Vint (Int.repr k); Vint (Int.repr v)) GLOBALS (gv)
SEP (mem_mgr gv)
POST [tptr t_bst]
EX p: val,
PROP ()
RETURN (p)
SEP (bst_rep (node (k, v) leaf leaf) p; mem_mgr gv).
Definition search_bst_spec: ident * funspec :=
DECLARE _search_bst
WITH head: val, k: Z, b: bst Z, gv: globals
PRE [tptr t_bst, tint]
PROP (repable_signed k;
bin_tree_forall b (fun n => repable_signed (fst n));
well_ordered b)
PARAMS (head; Vint (Int.repr k)) GLOBALS (gv)
SEP (bst_rep b head; mem_mgr gv)
POST [tptr t_bst]
EX vret,
PROP ()
RETURN (vret)
SEP (bst_hole_rep (search_make_hole k b) head vret; bst_rep (search k b) vret; mem_mgr gv).
Definition insert_bst_spec: ident * funspec :=
DECLARE _insert_bst
WITH bst_ptr: val, head: val, k: Z, v: Z, b: bst Z, gv: globals
PRE [tptr (tptr t_bst), tint, tint]
PROP (repable_signed k; repable_signed v;
bin_tree_forall b (fun n => repable_signed (fst n));
well_ordered b)
PARAMS (bst_ptr; Vint (Int.repr k); Vint (Int.repr v)) GLOBALS (gv)
SEP (data_at Ews (tptr t_bst) head bst_ptr;
bst_rep b head;
mem_mgr gv)
POST [tvoid]
EX new_bst: val,
PROP ()
RETURN ()
SEP (data_at Ews (tptr t_bst) new_bst bst_ptr;
bst_rep (insert k v b) new_bst;
mem_mgr gv).
Definition pop_min_spec: ident * funspec :=
DECLARE _pop_min
WITH bst_ptr: val, head: val, a: (Z * Z), l: bst Z, r: bst Z, gv: globals
PRE [tptr (tptr t_bst)]
PROP (bin_tree_forall (node a l r) (fun n => repable_signed (fst n));
well_ordered (node a l r))
PARAMS (bst_ptr) GLOBALS (gv)
SEP (data_at Ews (tptr t_bst) head bst_ptr;
bst_rep (node a l r) head;
mem_mgr gv)
POST [tptr t_bst]
EX min: val, EX new_bst: val, EX r': bst Z,
PROP ()
RETURN (min)
SEP (data_at Ews (tptr t_bst) new_bst bst_ptr;
bst_rep (rm_min a l r) new_bst;
(* Does this need to be a hole instead? *)
bst_rep (node (get_min a l r) leaf r') min;
mem_mgr gv).
Definition delete_bst_spec: ident * funspec :=
DECLARE _delete_bst
WITH parent_ptr: val, parent: val, k: Z, b: bst Z, gv: globals
PRE [tptr (tptr t_bst), tint]
PROP (repable_signed k;
bin_tree_forall b (fun n => repable_signed (fst n));
well_ordered b)
PARAMS (parent_ptr; Vint (Int.repr k)) GLOBALS (gv)
SEP (data_at Ews (tptr t_bst) parent parent_ptr;
bst_rep b parent;
mem_mgr gv)
POST [tvoid]
EX new_bst: val,
PROP ()
RETURN ()
SEP (data_at Ews (tptr t_bst) new_bst parent_ptr;
bst_rep (delete k b) new_bst;
mem_mgr gv).
Definition Gprog: funspecs :=
ltac:(with_library prog [new_bst_spec; search_bst_spec; insert_bst_spec; pop_min_spec; delete_bst_spec]).
(* Proofs of C functions *)
Theorem hole_rep_fuse_left : forall b k curr_k v l r (curr head pl pr: val),
well_ordered b ->
search_path k b (node (curr_k, v) l r) ->
k < curr_k ->
bst_hole_rep (bst_subtract_path k b (node (curr_k, v) l r)) head curr *
malloc_token Ews t_bst curr *
data_at Ews t_bst (Vint (Int.repr curr_k), (Vint (Int.repr v), (pl, pr))) curr *
bst_rep r pr
|-- bst_hole_rep (bst_subtract_path k b l) head pl.
Proof.
intros.
generalize dependent head.
induction b; intros.
- inv H0.
- simpl. destruct_pair.
find_Z_compare_destruct.
+ apply search_path_is_subtree in H0.
apply wo_node_eq in H0; [|assumption].
invc H0.
destruct l.
* simpl.
rewrite Zaux.Zcompare_Lt by assumption.
simpl.
Exists pl pr.
entailer!.
* simpl.
destruct_pair.
rewrite Z.compare_refl.
rewrite Zaux.Zcompare_Lt.
-- simpl.
Exists pl pr.
entailer!.
-- inv H.
inv H5.
simpl in *; assumption.
+ simpl in *.
Intros head_pl head_pr.
sep_apply IHb1.
* inv H. assumption.
* eapply path_shrink_l; eassumption.
* destruct l.
-- simpl.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ eapply path_extract_ord_l; eassumption.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ apply search_path_is_subtree in H0.
apply wo_subtree_left in H0; try assumption.
apply is_subtree_up_left in H0.
inv H.
eapply subtree_forall in H0; [|eassumption].
inv H0.
simpl in *; assumption.
+ simpl in *.
Intros head_pl head_pr.
sep_apply IHb2.
* inv H. assumption.
* eapply path_shrink_r; eassumption + lia.
* destruct l.
-- simpl.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ eapply path_extract_ord_r; try eassumption; lia.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ apply search_path_is_subtree in H0.
apply wo_subtree_right in H0; try assumption.
apply is_subtree_up_left in H0.
inv H.
eapply subtree_forall in H0; [|eassumption].
inv H0.
simpl in *; lia.
Qed.
Theorem hole_rep_fuse_right : forall b k curr_k v l r (curr head pl pr: val),
well_ordered b ->
search_path k b (node (curr_k, v) l r) ->
k > curr_k ->
bst_hole_rep (bst_subtract_path k b (node (curr_k, v) l r)) head curr *
malloc_token Ews t_bst curr *
data_at Ews t_bst (Vint (Int.repr curr_k), (Vint (Int.repr v), (pl, pr))) curr *
bst_rep l pl
|-- bst_hole_rep (bst_subtract_path k b r) head pr.
Proof.
intros.
generalize dependent head.
induction b; intros.
- inv H0.
- simpl. destruct_pair.
find_Z_compare_destruct.
+ apply search_path_is_subtree in H0.
apply wo_node_eq in H0; [|assumption].
invc H0.
destruct r.
* simpl.
rewrite Zaux.Zcompare_Gt by lia.
simpl.
Exists pl pr.
entailer!.
* simpl.
destruct_pair.
rewrite Z.compare_refl.
rewrite Zaux.Zcompare_Gt.
-- simpl.
Exists pl pr.
entailer!.
-- inv H.
inv H6.
simpl in *; lia.
+ simpl in *.
Intros head_pl head_pr.
sep_apply IHb1.
* inv H. assumption.
* eapply path_shrink_l; eassumption.
* destruct r.
-- simpl.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ eapply path_extract_ord_l; eassumption.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ apply search_path_is_subtree in H0.
apply wo_subtree_left in H0; try assumption.
apply is_subtree_up_right in H0.
inv H.
eapply subtree_forall in H0; [|eassumption].
inv H0.
simpl in *; assumption.
+ simpl in *.
Intros head_pl head_pr.
sep_apply IHb2.
* inv H. assumption.
* eapply path_shrink_r; eassumption + lia.
* destruct r.
-- simpl.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ eapply path_extract_ord_r; try eassumption; lia.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists head_pl head_pr.
entailer!.
++ apply search_path_is_subtree in H0.
apply wo_subtree_right in H0; try assumption.
apply is_subtree_up_right in H0.
inv H.
eapply subtree_forall in H0; [|eassumption].
inv H0.
simpl in *; lia.
Qed.
Theorem body_search_bst: semax_body Vprog Gprog f_search_bst search_bst_spec.
Proof.
start_function.
forward_loop (
EX curr_b curr,
PROP (search_path k b curr_b)
LOCAL (
gvars gv; temp _bst__1 curr;
temp _key (Vint (Int.repr k)))
SEP (
bst_hole_rep (bst_subtract_path k b curr_b) head curr;
bst_rep curr_b curr; mem_mgr gv)
).
{ repeat EExists.
entailer!.
- constructor.
- rewrite bst_subtract_path_b_b.
unfold bst_hole_rep.
entailer!. }
Intros curr_b curr.
forward_if.
{ forward.
simplify_assumps; subst.
rewrite search_path_fail by assumption.
EExists.
entailer!.
simpl.
entailer!. }
assert_PROP (curr_b <> leaf) by (expand bst_rep; entailer!; find_contradiction).
destruct curr_b as [|[curr_k v] l r]; [contradiction|].
expand bst_rep.
Intros pl pr.
forward.
forward_if.
{ assert (k = curr_k).
{ apply repr_inj_signed; try assumption.
apply search_path_is_subtree in H2.
pose proof (subtree_forall _ _ _ H2 H0) as H11.
inv H11; simpl in *; assumption. }
subst.
forward.
EExists.
simpl.
entailer!.
erewrite search_path_success by eassumption.
sep_apply generalize_node_rep.
cancel. }
forward.
forward_if.
- assert (k < curr_k).
{ rewrite <- Int.signed_repr.
- assumption.
- apply search_path_is_subtree in H2.
eapply subtree_forall in H2; [|eassumption].
inv H2.
simpl in H10; assumption. }
forward.
Exists l pl.
entailer!.
+ eapply path_step_down_l; eassumption.
+ apply hole_rep_fuse_left; assumption.
- assert (k > curr_k).
{ apply search_path_is_subtree in H2.
pose proof (subtree_forall _ _ _ H2 H0) as H8.
rewrite Int.signed_repr in H6.
+ enough (k <> curr_k). lia.
apply repr_inj_signed'; try assumption.
inv H8; simpl in *; assumption.
+ inv H8; simpl in *; assumption. }
forward.
Exists r pr.
entailer!.
+ eapply path_step_down_r; [eassumption|lia].
+ apply hole_rep_fuse_right; assumption.
Qed.
Theorem body_insert_bst: semax_body Vprog Gprog f_insert_bst insert_bst_spec.
Proof.
start_function.
forward_loop (
EX curr_b curr_ptr,
PROP (search_path k b curr_b)
LOCAL (
gvars gv; temp _bst__1 curr_ptr;
temp _key (Vint (Int.repr k));
temp _val (Vint (Int.repr v)))
SEP (
ptr_to_bst_hole_rep (bst_subtract_path k b curr_b) bst_ptr curr_ptr;
ptr_to_bst_rep curr_b curr_ptr;
mem_mgr gv)
).
{ Exists b bst_ptr.
entailer!.
- constructor.
- rewrite bst_subtract_path_b_b.
simpl.
entailer!.
unfold ptr_to_bst_rep.
Exists head.
entailer!. }
unfold ptr_to_bst_rep.
Intros curr_b curr_ptr curr.
forward.
forward_if.
{ subst.
forward_call.
Intros vret.
repeat forward.
simplify_assumps; subst.
simpl bst_rep at 2; entailer!.
revert H3.
clear.
generalize dependent bst_ptr.
induction b; intros.
- simpl.
Intros pl pr.
Exists vret pl pr.
entailer!.
- simpl bst_subtract_path.
destruct_pair.
find_Z_compare_destruct.
+ apply search_path_fail in H3.
simpl in H3.
rewrite Z.compare_refl in H3.
discriminate H3.
+ simpl bst_subtract_path in *.
simpl ptr_to_bst_hole_rep.
Intros q pr.
sep_apply IHb1.
* inv H3; [assumption | lia].
* Intros a.
Exists q.
entailer!.
simpl.
rewrite Zaux.Zcompare_Lt by assumption.
simpl.
Exists a pr.
entailer!.
unfold_data_at (data_at _ _ _ q).
entailer!.
+ simpl bst_subtract_path in *.
simpl ptr_to_bst_hole_rep.
Intros q pl.
sep_apply IHb2.
* inv H3; [lia | assumption].
* Intros a.
Exists q.
entailer!.
simpl.
rewrite Zaux.Zcompare_Gt by lia.
simpl.
Exists pl a.
entailer!.
unfold_data_at (data_at _ _ _ q).
entailer!. }
assert_PROP (curr_b <> leaf) by (expand bst_rep; entailer!; find_contradiction).
destruct curr_b as [|[curr_k curr_v] l r]; [contradiction|].
expand bst_rep.
Intros pl pr.
repeat forward.
forward_if. {
repeat forward.
assert (k = curr_k).
{ apply repr_inj_signed; try assumption.
apply search_path_is_subtree in H3.
eapply subtree_forall in H3; [|eassumption].
inv H3; simpl in *; assumption. }
subst.
simpl.
sep_apply generalize_node_rep.
sep_apply generalize_ptr_to_node_rep.
assert ((
ptr_to_bst_rep (insert curr_k v b) bst_ptr * mem_mgr gv
=
EX a : val,
data_at Ews (tptr t_bst) a bst_ptr *
(bst_rep (insert curr_k v b) a * mem_mgr gv)
)%logic) by (apply pred_ext; unfold ptr_to_bst_rep; Intros q; Exists q; entailer!);
rewrite <- H14; clear H14.
entailer!.
revert bst_ptr H2 H3.
clear.
induction b; intros.
- inv H3.
- simpl.
destruct_pair.
find_Z_compare_destruct.
+ simpl.
entailer!.
apply search_path_is_subtree in H3.
apply wo_node_eq in H3; [|assumption].
inv H3.
entailer!.
+ simpl.
Intros q pr.
sep_apply IHb1.
* inv H2; assumption.
* inv H3; lia + assumption.
* unfold ptr_to_bst_rep.
Intros pl.
Exists q.
entailer!.
simpl.
Exists pl pr.
unfold_data_at (data_at _ _ _ q).
entailer!.
+ simpl.
Intros q pl.
sep_apply IHb2.
* inv H2; assumption.
* inv H3; lia + assumption.
* unfold ptr_to_bst_rep.
Intros pr.
Exists q.
entailer!.
simpl.
Exists pl pr.
unfold_data_at (data_at _ _ _ q).
entailer!. }
repeat forward.
forward_if.
{ assert (k < curr_k).
{ rewrite <- Int.signed_repr.
- assumption.
- apply search_path_is_subtree in H3.
eapply subtree_forall in H3; [|eassumption].
inv H3.
simpl in *; assumption. }
repeat forward.
simpl offset_val.
entailer!.
Exists l (field_address t_bst [StructField _left] curr).
entailer!.
- eapply path_step_down_l; eassumption.
- sep_apply generalize_node_rep.
simpl bst_subtract_path.
revert bst_ptr H2 H3.
clear - H8.
induction b; intros; [inv H3|].
simpl.
Intros pl pr.
destruct_pair.
find_Z_compare_destruct.
+ apply search_path_is_subtree in H3.
apply wo_node_eq in H3; [|assumption].
inv H3.
simplify_assumps; subst.
destruct l.
* simpl.
rewrite Zaux.Zcompare_Lt by assumption.
simpl.
unfold ptr_to_bst_rep.
Exists curr pr pl.
expand bst_rep.
unfold_data_at (data_at _ _ _ curr).
entailer!.
* simpl.
destruct_pair.
Intros pl' pr'.
rewrite Z.compare_refl.
rewrite Zaux.Zcompare_Lt.
-- simpl.
unfold ptr_to_bst_rep.
Exists curr pr pl.
unfold_data_at (data_at _ _ _ curr).
entailer!.
apply generalize_node_rep.
-- inv H2.
inv H5.
simpl in H3; assumption.
+ simpl.
Intros q pr'.
sep_apply generalize_node_rep.
sep_apply IHb1.
* inv H2; assumption.
* inv H3; lia + assumption.
* cancel.
destruct l.
-- simpl.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists q pr'.
entailer!.
++ inv H3; lia.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists q pr'.
entailer!.
++ inv H3; try lia.
apply search_path_is_subtree in H9.
apply subtree_well_ordered in H9; [|inv H2; assumption].
inv H9.
inv H6.
simpl in H5; lia.
+ simpl.
Intros q pl'.
sep_apply generalize_node_rep.
sep_apply IHb2.
* inv H2; assumption.
* eapply path_shrink_r; try eassumption; lia.
* cancel.
destruct l.
-- simpl.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists q pl'.
entailer!.
++ inv H3; try lia.
apply search_path_is_subtree in H9.
eapply subtree_forall in H9; [| inv H2; eassumption].
inv H9.
simpl in H5; lia.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists q pl'.
entailer!.
++ apply search_path_is_subtree in H3.
apply wo_subtree_right in H3; [|assumption|lia].
apply is_subtree_up_left in H3.
eapply subtree_forall in H3; [|inv H2; eassumption].
inv H3.
simpl in H5; lia. }
{ assert (k > curr_k).
{ apply search_path_is_subtree in H3.
eapply subtree_forall in H3; [|eassumption].
rewrite Int.signed_repr in H7.
+ enough (k <> curr_k). lia.
apply repr_inj_signed'; try assumption.
inv H3; simpl in *; assumption.
+ inv H3; simpl in *; assumption. }
repeat forward.
simpl offset_val.
entailer!.
Exists r (field_address t_bst [StructField _right] curr).
entailer!.
- eapply path_step_down_r; eassumption + lia.
- sep_apply generalize_node_rep.
simpl bst_subtract_path.
revert bst_ptr H2 H3.
clear - H8.
induction b; intros; [inv H3|].
simpl.
Intros pl pr.
destruct_pair.
find_Z_compare_destruct.
+ apply search_path_is_subtree in H3.
apply wo_node_eq in H3; [|assumption].
inv H3.
simplify_assumps; subst.
destruct r.
* simpl.
rewrite Zaux.Zcompare_Gt by lia.
simpl.
unfold ptr_to_bst_rep.
Exists curr pl pr.
expand bst_rep.
unfold_data_at (data_at _ _ _ curr).
entailer!.
* simpl.
destruct_pair.
Intros pl' pr'.
rewrite Z.compare_refl.
rewrite Zaux.Zcompare_Gt.
-- simpl.
unfold ptr_to_bst_rep.
Exists curr pl pr.
unfold_data_at (data_at _ _ _ curr).
entailer!.
apply generalize_node_rep.
-- inv H2.
inv H6.
simpl in H3; lia.
+ simpl.
Intros q pr'.
sep_apply generalize_node_rep.
sep_apply IHb1.
* inv H2; assumption.
* eapply path_shrink_l; eassumption.
* cancel.
destruct r.
-- simpl.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists q pr'.
entailer!.
++ eapply path_extract_ord_l; eassumption.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Lt.
++ simpl.
Exists q pr'.
entailer!.
++ inv H3.
** lia.
** apply search_path_is_subtree in H9.
apply is_subtree_up_right in H9.
eapply subtree_forall in H9; [| inv H2; eassumption].
inv H9.
simpl in H5; lia.
** apply search_path_is_subtree in H9.
eapply subtree_forall in H9; [| inv H2; eassumption].
inv H9.
simpl in H5; lia.
+ simpl.
Intros q pl'.
sep_apply generalize_node_rep.
sep_apply IHb2.
* inv H2; assumption.
* eapply path_shrink_r; try eassumption; lia.
* cancel.
destruct r.
-- simpl.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists q pl'.
entailer!.
++ inv H3; lia.
-- simpl.
destruct_pair.
rewrite Zaux.Zcompare_Gt.
++ simpl.
Exists q pl'.
entailer!.
++ apply search_path_is_subtree in H3.
apply wo_subtree_right in H3; [|assumption|lia].
apply is_subtree_up_right in H3.
eapply subtree_forall in H3; [|inv H2; eassumption].
inv H3.
simpl in H5; lia. }
Qed.
(* Proofs incomplete / outdated beyond this point *)
Theorem body_pop_min: semax_body Vprog Gprog f_pop_min pop_min_spec.
Proof.
start_function.
forward_loop (
EX a' l' r' curr_ptr min_z,
PROP (
min_z = fst (get_min a l r);
search_path min_z (node a l r) (node a' l' r'))
LOCAL (
gvars gv; temp _bst_ptr curr_ptr)
SEP (
ptr_to_bst_hole_rep (bst_subtract_path min_z (node a l r) (node a' l' r')) bst_ptr curr_ptr;
ptr_to_bst_rep (node a' l' r') curr_ptr;
mem_mgr gv)
).
{
entailer!.
Exists a l r bst_ptr (fst (get_min a l r)).
entailer!.
- constructor.
- simpl.
destruct_pair.
Intros pl pr.
rewrite Z.compare_refl.
unfold ptr_to_bst_rep, ptr_to_bst_hole_rep.
expand bst_rep.
Exists head pl pr.
entailer!.
}
unfold ptr_to_bst_rep.
Intros a' l' r' curr_ptr min_z curr.
expand bst_rep.
destruct_pair.
Intros pl pr.
repeat forward.
forward_if.
{
repeat forward.
simpl offset_val.
assert_PROP (l' <> leaf) by (entailer!; find_contradiction).
destruct l' as [|l'a l'l l'r]; [contradiction|].
entailer!.
simplify_assumps; subst.
Exists l'a l'l l'r (field_address t_bst [StructField _left] curr) (fst (get_min a l r)).
entailer!.
- eapply path_step_down_l; [eassumption|].
apply get_min_is_min in H0.
admit.
-
sep_apply generalize_node_rep.
simpl bst_subtract_path.
repeat destruct_pair.
rewrite Zaux.Zcompare_Lt.
rewrite Zaux.Zcompare_Lt.
+ clear - H0 H2.
simpl.
Intros pl pr pl0 pr0 q pr1.
Exists pl0 pr0.
cancel.
unfold ptr_to_bst_rep.
Exists pl.
expand bst_rep.
Exists q pr1.
cancel.
unfold_data_at (data_at _ _ _ curr).
cancel.
revert z3 z4 r H0 H2 pl0.
induction l; intros.
* simpl in H2. inv H2; lia.
*
simpl in *.
destruct_pair.
rewrite Zaux.Zcompare_Lt.
rewrite Zaux.Zcompare_Lt.
{
simpl.
Intros q0 pr2. Exists q0 pr2.
sep_apply (IHl1 z5 z6 l2).
- inv H0; assumption.
- eapply path_shrink_l; [| |eassumption].
+ admit.
+ admit.
- admit.
}
admit.
admit.
+ admit.
+ admit.
}
repeat forward.
simplify_assumps; subst.
simpl bst_subtract_path.
destruct_pair.
rewrite Zaux.Zcompare_Lt. (* Since search_path puts z towards the min *)
simpl ptr_to_bst_hole_rep.
Intros q pr0. (* generalize pr0? *)
Exists curr q.
(* EExists. *)
expand bst_rep.
destruct (get_min (z1, z2) l r) eqn:H_min.
(* Exists nullval. *)
(* EExists. *)
(* entailer!. *)
clear - H0 H2 H_min.
revert pr0.
induction l; intros.
- simpl in *.
inv H_min; subst.
inv H2; subst; try lia.
simplify_assumps; subst.
Admitted.
Theorem body_delete_bst: semax_body Vprog Gprog f_delete_bst delete_bst_spec.
Proof.
start_function.
forward.
forward_if.
{
forward.
EExists.
simplify_assumps; subst.
entailer!.
}
assert_PROP (b <> leaf) by (expand bst_rep; entailer!; find_contradiction).
destruct b as [|[parent_k v] l r]; [contradiction|].
expand bst_rep.
Intros pl pr.
repeat (forward + forward_if).
{
assert_PROP (r <> leaf) by (expand bst_rep; entailer!; find_contradiction).
destruct r as [|ra rl rr]; [contradiction|].
assert_PROP (field_compatible t_bst [StructField _right] parent) by entailer!.
forward_call(
field_address t_bst [StructField _right] parent,
pr, ra, rl, rr, gv).
- unfold_data_at (data_at _ _ _ parent).
entailer!.
- split.
+ inv H0; assumption.
+ inv H1; assumption.
- Intros vret.
expand bst_rep.
destruct (get_min ra rl rr) eqn:H_min.
Intros pl0 pr0.
repeat forward.
forward_call(t_bst, fst (fst vret), gv).
{ entailer!.
apply field_compatible_nullval1 in H15.
destruct (eq_dec (fst (fst vret)) nullval); [contradiction|].
entailer!. }
Exists parent.
entailer!.
enough (k = parent_k).
subst.
simpl.
rewrite Z.compare_refl.
assert_PROP (l <> leaf) by (expand bst_rep; entailer!; find_contradiction).
destruct l as [|la ll lr]; [contradiction|].
expand bst_rep.
destruct la.
rewrite H_min.
Exists pl (snd (fst vret)).
Intros pl0 pr1; Exists pl0 pr1.
unfold_data_at (data_at _ _ _ parent).
entailer!.
admit.
admit.
}
Admitted.