@@ -15,10 +15,13 @@ Import ListNotations.
1515Inductive provable (g:Global.t): LCSet.t -> LogicalConstraints.t -> Prop :=
1616| solvable_SMT: forall lc it, provable g lc it.
1717
18+ (* Helper function to get a list of resources from the contex *)
19+ Definition ctx_resources_list (l: (list (Resource.t * Z)) * Z) : list Resource.t :=
20+ List.map fst (fst l).
21+
1822(* Helper function to get a set of resources from the contex *)
19- Definition ctx_resources_set (l:((list (Resource.t * Z)) * Z)) : ResSet.t
20- :=
21- Resource.set_from_list (List.map fst (fst l)).
23+ Definition ctx_resources_set (l: (list (Resource.t * Z)) * Z) : ResSet.t :=
24+ Resource.set_from_list (ctx_resources_list l).
2225
2326Inductive term_is_struct: Terms.term BaseTypes.t -> Prop :=
2427| term_is_struct_intro: forall tag fields,
@@ -521,6 +524,34 @@ Inductive unfold_one (globals:Global.t): Resource.t -> ResSet.t -> Prop :=
521524 iout)
522525 out_res.
523526
527+ Definition apply_for_subsumed (iinit: init) (f : init -> bool) : bool :=
528+ match iinit with
529+ | Init => f Init
530+ | Uninit => f Uninit || f Init
531+ end .
532+
533+ Lemma apply_for_subsumed_spec:
534+ forall iinit f t, apply_for_subsumed iinit f = true ->
535+ exists iinit', subsumed (Owned t iinit) (Owned t iinit') /\ f iinit' = true.
536+ Proof .
537+ intros iinit f t H.
538+ unfold apply_for_subsumed in H.
539+ destruct iinit.
540+ - exists Init; split.
541+ + apply Subsumed_equal.
542+ reflexivity.
543+ + apply H.
544+ - apply orb_true_iff in H as [H | H].
545+ + exists Uninit; split.
546+ * apply Subsumed_equal.
547+ reflexivity.
548+ * apply H.
549+ + exists Init; split.
550+ * apply Subsumed_owned.
551+ reflexivity.
552+ * apply H.
553+ Qed .
554+
524555(* Computable version of unfold_one predicate *)
525556Definition unfold_one_fun (globals:Global.t) (r : Resource.t) (out_res: list Resource.t) : bool :=
526557 match r with
@@ -532,9 +563,10 @@ Definition unfold_one_fun (globals:Global.t) (r : Resource.t) (out_res: list Res
532563 match SymMap.find isym globals.(Global .struct_decls) with
533564 | Some sdecl =>
534565 (List.length sdecl =? List.length out_res) &&
535- List.forallb
536- (fun '(piece, r) => struct_piece_to_resource_fun piece iinit ipointer iargs isym iout r)
537- (List.combine sdecl out_res)
566+ apply_for_subsumed iinit (fun iinit' =>
567+ List.forallb
568+ (fun '(piece, r) => struct_piece_to_resource_fun piece iinit' ipointer iargs isym iout r)
569+ (List.combine sdecl out_res))
538570 | None => false
539571 end
540572 | _ => false
@@ -559,9 +591,10 @@ Proof.
559591 apply SymMap.find_2 in Hf.
560592 assert (piece_def : Memory.struct_piece) by (repeat constructor).
561593 assert (res_def : Resource.t) by (repeat constructor).
562- eapply unfold_one_struct with (iinit' := i).
563- { apply Subsumed_equal.
564- reflexivity. }
594+ apply apply_for_subsumed_spec with (t := Struct s) in H.
595+ destruct H as [i' [Hi H]].
596+ eapply unfold_one_struct with (iinit' := i').
597+ { apply Hi. }
565598 { apply Hf. }
566599 intros r; split.
567600 - intros Hr.
@@ -616,6 +649,87 @@ Inductive unfold_all (globals:Global.t): ResSet.t -> ResSet.t -> Prop :=
616649 ResSet.Equal input output ->
617650 unfold_all globals input output.
618651
652+ Lemma unfold_one_Proper : Proper (eq ==> eq ==> ResSet.Equal ==> iff) unfold_one.
653+ Proof .
654+ intros globals globals' Hglobals r r' Hr rs rs' Hrs.
655+ subst r' globals'.
656+ enough (forall r rs rs', ResSet.Equal rs rs' -> unfold_one globals r rs -> unfold_one globals r rs') as H.
657+ { split; intros H1.
658+ - eapply H.
659+ + apply Hrs.
660+ + apply H1.
661+ - eapply H.
662+ + symmetry; apply Hrs.
663+ + apply H1. }
664+ clear.
665+ intros r rs rs' Hrs H.
666+ inversion H; subst; clear H.
667+ econstructor; eauto.
668+ intros r; split; intros Hr.
669+ - apply H2.
670+ eapply ResSetDecide.F.In_m.
671+ + reflexivity.
672+ + apply Hrs.
673+ + apply Hr.
674+ - eapply ResSetDecide.F.In_m.
675+ + reflexivity.
676+ + symmetry.
677+ apply Hrs.
678+ + apply H2, Hr.
679+ Qed .
680+
681+ Lemma unfold_all_Proper : Proper (eq ==> ResSet.Equal ==> ResSet.Equal ==> iff) unfold_all.
682+ Proof .
683+ intros globals globals' Hglobals r1 r1' Hr1 r2 r2' Hr2.
684+ subst globals'.
685+ enough (forall r1 r1' r2 r2', ResSet.Equal r1 r1' -> ResSet.Equal r2 r2' ->
686+ unfold_all globals r1 r2 -> unfold_all globals r1' r2') as H.
687+ { split; intros H1.
688+ - eapply H.
689+ + apply Hr1.
690+ + apply Hr2.
691+ + apply H1.
692+ - eapply H.
693+ + symmetry; apply Hr1.
694+ + symmetry; apply Hr2.
695+ + apply H1. }
696+ clear.
697+ intros r1 r1' r2 r2' Hr1 Hr2 H.
698+ revert r1' r2' Hr1 Hr2.
699+ induction H; intros r1' r2' Hr1 Hr2.
700+ - eapply unfold_all_step with (input' := input').
701+ + apply Hr1, H.
702+ + apply H0.
703+ + ResSetDecide.fsetdec.
704+ + apply IHunfold_all.
705+ * reflexivity.
706+ * apply Hr2.
707+ - apply unfold_all_fixpoint.
708+ + intros H1.
709+ apply H.
710+ destruct H1 as [r [Hr H1]].
711+ exists r; split; try assumption.
712+ apply Hr1, Hr.
713+ + transitivity input.
714+ { apply Equivalence_Symmetric, Hr1. }
715+ transitivity output.
716+ { apply H0. }
717+ apply Hr2.
718+ Qed .
719+
720+ Lemma unfold_all_singleton_eq:
721+ forall globals r output,
722+ unfold_all globals (Resource.set_from_list [r]) output <->
723+ unfold_all globals (ResSet.singleton r) output.
724+ Proof .
725+ intros globals r output.
726+ eapply unfold_all_Proper.
727+ - reflexivity.
728+ - cbn.
729+ ResSetDecide.fsetdec.
730+ - reflexivity.
731+ Qed .
732+
619733(* A version of `unfold_all`, using hints *)
620734Inductive unfold_all_explicit (globals:Global.t):
621735 list (Resource.t * unpack_result) -> ResSet.t -> ResSet.t -> Prop :=
@@ -746,6 +860,40 @@ Qed.
746860Definition unfold_step_flatten (l : list unfold_step): unfold_changed :=
747861 List.concat (List.map fst l).
748862
863+ Definition get_resources_from_log (log_entries : log) : list Resource.t :=
864+ List.fold_right (fun log_entry rs =>
865+ match log_entry with
866+ | PredicateRequest _ _ _ (p, o) _ _ => (Request.P p, o) :: rs
867+ | UnfoldResources _ _ _ _ => rs (* probably shouldn't happen *)
868+ end ) [] log_entries.
869+
870+ Definition resource_set_init (r : Resource.t) : Resource.t :=
871+ match r with
872+ | (Request.P {| Predicate.name := Request.Owned t _;
873+ Predicate.pointer := p;
874+ Predicate.iargs := args |}, out) =>
875+ (Request.P {| Predicate.name := Request.Owned t Init;
876+ Predicate.pointer := p;
877+ Predicate.iargs := args |}, out)
878+ | r => r
879+ end .
880+
881+ Definition resource_set_correct_init_status (c : Context.t) (r : Resource.t) : Resource.t :=
882+ if List.existsb (fun r' => bool_of_sum (Resource_as_DecidableType.eq_dec r r')) (ctx_resources_list c.(resources))
883+ then r
884+ else resource_set_init r.
885+
886+ Fixpoint get_hints_from_log_entry (log_entry : log_entry) : unfold_changed :=
887+ match log_entry with
888+ | PredicateRequest _ _ _ _ [] _ => []
889+ | PredicateRequest ic _ _ (p, o) log_entries _ =>
890+ let r := (Request.P p, o) in
891+ let unfolded_r := List.map (resource_set_correct_init_status ic) (get_resources_from_log log_entries) in
892+ let hints_inner := List.concat (List.map get_hints_from_log_entry log_entries) in
893+ (r, UnpackRES unfolded_r) :: hints_inner
894+ | UnfoldResources _ _ _ _ => [] (* probably shouldn't happen *)
895+ end .
896+
749897(** Inductive predicate which defines correctness of resource unfolding step *)
750898Inductive unfold_step : Context.t -> Context .t -> Prop :=
751899| simple_unfold_step:
0 commit comments