From ee72aad77b419fe6e80d6f4fa5f2228579debc26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Tue, 25 Apr 2023 15:46:29 +0200
Subject: [PATCH] [kernel] update hook on annotations

This reverts commit 0bd1d1f0c17fb811469aa8b57fb4bd8f4acbc83b.
---
 src/kernel_services/ast_data/annotations.ml   | 192 +++++++++++++-----
 .../plugin_entry_points/emitter.ml            |  32 ++-
 .../plugin_entry_points/emitter.mli           |  12 --
 3 files changed, 150 insertions(+), 86 deletions(-)

diff --git a/src/kernel_services/ast_data/annotations.ml b/src/kernel_services/ast_data/annotations.ml
index e2b814dc187..4f049e0bf0d 100644
--- a/src/kernel_services/ast_data/annotations.ml
+++ b/src/kernel_services/ast_data/annotations.ml
@@ -67,6 +67,9 @@ let find_englobing_kf ?kf stmt =
 (** {2 Internal State} *)
 (**************************************************************************)
 
+module Changed = Hook.Make()
+let add_hook_on_change = Changed.extend
+
 module Usable_emitter = struct
   include Emitter.Usable_emitter
   let local_clear _ h = Hashtbl.clear h
@@ -155,19 +158,6 @@ let () =
        let kf = find_englobing_kf stmt in
        List.iter (fun a -> clear_linked_to_annot kf stmt e a) !l)
 
-let add_hook_on_change f =
-  begin
-    let notify _ _ _ = f () in
-    Globals.add_hook_on_update notify ;
-    Globals.add_hook_on_remove notify ;
-    Model_fields.add_hook_on_update notify ;
-    Model_fields.add_hook_on_remove notify ;
-    Funspecs.add_hook_on_update notify ;
-    Funspecs.add_hook_on_remove notify ;
-    Code_annots.add_hook_on_update notify ;
-    Code_annots.add_hook_on_remove notify ;
-  end
-
 (**************************************************************************)
 (** {2 Getting annotations} *)
 (**************************************************************************)
@@ -448,7 +438,8 @@ let pre_register_funspec ?tbl ?(emitter=Emitter.end_user) ?(force=false) kf =
           tbl;
     *)
     List.iter Property_status.register
-      (Property.ip_of_spec kf Kglobal ~active:[] spec)
+      (Property.ip_of_spec kf Kglobal ~active:[] spec);
+    Changed.apply();
   end
 
 let register_funspec ?emitter ?force kf =
@@ -780,7 +771,7 @@ let remove_code_annot_internal e ?(remove_statuses=true) ?kf stmt ca =
 (**************************************************************************)
 
 (* If this function gets exported, please turn e into an Emitter.t *)
-let remove_model_field (e:Usable_emitter.t) m =
+let do_remove_model_field (e:Usable_emitter.t) m =
   try
     let ty = m.mi_base_type in
     let h = Model_fields.find ty in
@@ -802,7 +793,7 @@ let remove_global e a =
          if Emitter.Usable_emitter.equal e e' then begin
            Globals.remove a;
            (match a with
-            | Dmodel_annot (m,_) -> remove_model_field e m
+            | Dmodel_annot (m,_) -> do_remove_model_field e m
             | _ -> ());
            let file = Ast.get () in
            file.globals <-
@@ -810,12 +801,14 @@ let remove_global e a =
                (fun a' ->
                   not (Global.equal (GAnnot(a, Global_annotation.loc a)) a'))
                file.globals;
-           Globals.apply_hooks_on_remove e a ()
+           Globals.apply_hooks_on_remove e a ();
+           Changed.apply();
          end)
       h;
   with Not_found ->
     ()
 
+(* internal use only *)
 let remove_in_funspec e kf set_spec =
   try
     let tbl = Funspecs.find kf in
@@ -828,7 +821,8 @@ let remove_in_funspec e kf set_spec =
           Format.printf "For emitter %a: %a@."
             Emitter.Usable_emitter.pretty e
             Cil_printer.pp_funspec spec) tbl; *)
-      set_spec spec tbl
+      set_spec spec tbl;
+      Changed.apply()
     with Not_found -> ()
   with Not_found ->
     assert false
@@ -858,7 +852,8 @@ let remove_behavior ?(force=false) e kf bhv =
   in
   remove_in_funspec e kf set_spec
 
-let remove_decreases e kf =
+(* internal use only *)
+let do_remove_decreases e kf =
   let set_spec spec _tbl =
     match spec.spec_variant with
     | None -> ()
@@ -868,7 +863,12 @@ let remove_decreases e kf =
   in
   remove_in_funspec e kf set_spec
 
-let remove_terminates e kf =
+let remove_decreases e kf =
+  do_remove_decreases e kf;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_terminates e kf =
   let set_spec spec _tbl =
     match spec.spec_terminates with
     | None -> ()
@@ -878,21 +878,36 @@ let remove_terminates e kf =
   in
   remove_in_funspec e kf set_spec
 
-let remove_complete e kf l =
+let remove_terminates e kf =
+  do_remove_terminates e kf;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_complete e kf l =
   let set_spec spec _tbl =
     spec.spec_complete_behaviors <- filterq l spec.spec_complete_behaviors
   in
   remove_in_funspec e kf set_spec;
   Property_status.remove (Property.ip_of_complete kf Kglobal ~active:[] l)
 
-let remove_disjoint e kf l =
+let remove_complete e kf l =
+  do_remove_complete e kf l;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_disjoint e kf l =
   let set_spec spec _tbl =
     spec.spec_disjoint_behaviors <- filterq l spec.spec_disjoint_behaviors
   in
   remove_in_funspec e kf set_spec;
   Property_status.remove (Property.ip_of_disjoint kf Kglobal ~active:[] l)
 
-let remove_requires e kf p =
+let remove_disjoint e kf l =
+  do_remove_disjoint e kf l;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_requires e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -904,7 +919,12 @@ let remove_requires e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_assumes e kf p =
+let remove_requires e kf p =
+  do_remove_requires e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_assumes e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -916,7 +936,12 @@ let remove_assumes e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_ensures e kf p =
+let remove_assumes e kf p =
+  do_remove_assumes e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_ensures e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -928,7 +953,12 @@ let remove_ensures e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_allocates e kf p =
+let remove_ensures e kf p =
+  do_remove_ensures e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_allocates e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -942,7 +972,12 @@ let remove_allocates e kf p =
   in
   remove_in_funspec e kf set_spec
 
-let remove_extended e kf ext =
+let remove_allocates e kf p =
+  do_remove_allocates e kf p;
+  Changed.apply()
+
+(* internal use only *)
+let do_remove_extended e kf ext =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -953,8 +988,12 @@ let remove_extended e kf ext =
   in
   remove_in_funspec e kf set_spec
 
+let remove_extended e kf ext =
+  do_remove_extended e kf ext;
+  Changed.apply()
 
-let remove_assigns e kf p =
+(* internal use only *)
+let do_remove_assigns e kf p =
   let set_spec spec _tbl =
     List.iter
       (fun b ->
@@ -976,12 +1015,17 @@ let remove_assigns e kf p =
   in
   remove_in_funspec e kf set_spec
 
+let remove_assigns e kf p =
+  do_remove_assigns e kf p;
+  Changed.apply()
+
 let remove_behavior_components e kf b =
-  List.iter (remove_requires e kf) b.b_requires;
-  List.iter (remove_assumes e kf) b.b_assumes;
-  List.iter (remove_ensures e kf) b.b_post_cond;
-  remove_assigns e kf b.b_assigns;
-  remove_allocates e kf b.b_allocation
+  List.iter (do_remove_requires e kf) b.b_requires;
+  List.iter (do_remove_assumes e kf) b.b_assumes;
+  List.iter (do_remove_ensures e kf) b.b_post_cond;
+  do_remove_assigns e kf b.b_assigns;
+  do_remove_allocates e kf b.b_allocation;
+  Changed.apply()
 
 (**************************************************************************)
 (** {2 Adding annotations} *)
@@ -1093,7 +1137,8 @@ let mk_spec bhv variant terminates complete disjoint =
     spec_complete_behaviors = complete;
     spec_disjoint_behaviors = disjoint; }
 
-let add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs =
+(* internal use only *)
+let do_add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   let existing_behaviors = emit_spec.spec_behavior in
@@ -1160,10 +1205,15 @@ let add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs =
       bhvs
   end
 
+let add_behaviors ?register_children e kf ?stmt ?active bhvs =
+  do_add_behaviors ?register_children e kf ?stmt ?active bhvs;
+  Changed.apply()
+
 exception AlreadySpecified of string list
 
-let add_decreases ?(force=false) e kf v =
-  if force then remove_decreases e kf ;
+(* internal use only *)
+let do_add_decreases ?(force=false) e kf v =
+  if force then do_remove_decreases e kf ;
   let full_spec = get_spec_all kf () in
   let emit_spec = get_spec_e e kf () in
   (match full_spec.spec_variant with
@@ -1172,8 +1222,14 @@ let add_decreases ?(force=false) e kf v =
    | _ -> emit_spec.spec_variant <- Some v);
   Property_status.register (Property.ip_of_decreases kf Kglobal v)
 
-let add_terminates ?(force=false) e kf ?stmt ?active t =
-  if force then remove_terminates e kf ;
+(* internal use only *)
+let add_decreases ?force e kf v =
+  do_add_decreases ?force e kf v;
+  Changed.apply()
+
+(* internal use only *)
+let do_add_terminates ?(force=false) e kf ?stmt ?active t =
+  if force then do_remove_terminates e kf ;
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   (match full_spec.spec_terminates with
@@ -1182,6 +1238,10 @@ let add_terminates ?(force=false) e kf ?stmt ?active t =
    | _ -> emit_spec.spec_terminates <- Some t);
   Property_status.register (Property.ip_of_terminates kf (kinstr stmt) t)
 
+let add_terminates ?force e kf ?stmt ?active t =
+  do_add_terminates ?force e kf ?stmt ?active t;
+  Changed.apply()
+
 let check_bhv_name spec name =
   if name = Cil.default_behavior_name then begin
     Kernel.fatal
@@ -1195,7 +1255,8 @@ let check_bhv_name spec name =
       name
   end
 
-let add_complete e kf ?stmt ?active l =
+(* internal use only *)
+let do_add_complete e kf ?stmt ?active l =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   if List.mem l full_spec.spec_complete_behaviors then
@@ -1211,7 +1272,12 @@ let add_complete e kf ?stmt ?active l =
       (Property.ip_of_complete kf (kinstr stmt) ~active l)
   end
 
-let add_disjoint e kf ?stmt ?active l =
+let add_complete e kf ?stmt ?active l =
+  do_add_complete e kf ?stmt ?active l;
+  Changed.apply()
+
+(* internal use only *)
+let do_add_disjoint e kf ?stmt ?active l =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let emit_spec = get_spec_e e kf ?stmt ?active () in
   if List.mem l full_spec.spec_disjoint_behaviors then
@@ -1226,6 +1292,10 @@ let add_disjoint e kf ?stmt ?active l =
     Property_status.register (Property.ip_of_disjoint kf (kinstr stmt) ~active l)
   end
 
+let add_disjoint e kf ?stmt ?active l =
+  do_add_disjoint e kf ?stmt ?active l;
+  Changed.apply()
+
 let add_spec ?register_children ?(force=false) e kf ?stmt ?active spec =
   let full_spec = get_spec_all kf ?stmt ?active () in
   let conflicts =
@@ -1241,20 +1311,22 @@ let add_spec ?register_children ?(force=false) e kf ?stmt ?active spec =
      | _ -> [])
   in
   if not force && conflicts <> [] then raise (AlreadySpecified conflicts) ;
-  add_behaviors ?register_children e kf ?stmt ?active spec.spec_behavior;
+  do_add_behaviors ?register_children e kf ?stmt ?active spec.spec_behavior;
   Option.iter
-    (fun variant -> add_decreases ~force e kf variant)
+    (fun variant -> do_add_decreases ~force e kf variant)
     spec.spec_variant;
   Option.iter
-    (fun terminates -> add_terminates ~force e kf ?stmt ?active terminates)
+    (fun terminates -> do_add_terminates ~force e kf ?stmt ?active terminates)
     spec.spec_terminates;
   List.iter
-    (fun complete -> add_complete e kf ?stmt ?active complete)
+    (fun complete -> do_add_complete e kf ?stmt ?active complete)
     spec.spec_complete_behaviors;
   List.iter
-    (fun disjoint -> add_disjoint e kf ?stmt ?active disjoint)
-    spec.spec_disjoint_behaviors
+    (fun disjoint -> do_add_disjoint e kf ?stmt ?active disjoint)
+    spec.spec_disjoint_behaviors;
+  Changed.apply()
 
+(* internal use only *)
 let extend_behavior
     e kf ?stmt ?active ?(behavior=Cil.default_behavior_name) set_bhv =
   (* Kernel.feedback "Function %a, behavior %s" Kf.pretty kf bhv_name;*)
@@ -1276,7 +1348,8 @@ let extend_behavior
   Property_status.remove ip;
   set_bhv b b';
   let ip = Property.ip_of_behavior kf (kinstr stmt) ~active b in
-  Property_status.register ip
+  Property_status.register ip;
+  Changed.apply()
 
 let add_requires e kf ?stmt ?active ?behavior l =
   let set_bhv _ bhv =
@@ -1410,7 +1483,8 @@ let add_extended e kf ?stmt ?active ?behavior ext =
 
 (** {3 Adding code annotations} *)
 
-let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
+(* internal use only *)
+let do_add_code_annot ~keep_empty emitter ?kf stmt ca =
   (*  Kernel.feedback "%a: adding code annot %a with stmt %a (%d)"
       Project.pretty (Project.current ())
       Code_annotation.pretty ca
@@ -1455,18 +1529,18 @@ let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
      | [ { annot_content = AStmtSpec _ } ] ->
        let register_children = true in
        let active = bhvs in
-       add_behaviors
+       do_add_behaviors
          ~register_children emitter kf ~stmt ~active spec.spec_behavior;
        if spec.spec_variant <> None then
          Kernel.fatal
            "statement contract cannot have a decrease clause";
        Option.iter
-         (add_terminates emitter kf ~stmt ~active) spec.spec_terminates;
+         (do_add_terminates emitter kf ~stmt ~active) spec.spec_terminates;
        List.iter
-         (add_complete emitter kf ~stmt ~active)
+         (do_add_complete emitter kf ~stmt ~active)
          spec.spec_complete_behaviors;
        List.iter
-         (add_disjoint emitter kf ~stmt ~active)
+         (do_add_disjoint emitter kf ~stmt ~active)
          spec.spec_disjoint_behaviors;
        (* By construction, we have exactly one contract
           corresponding to our criterion and emitter. *)
@@ -1570,6 +1644,10 @@ let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
   | APragma _ | AExtended _ ->
     fill_tables ca (Property.ip_of_code_annot kf stmt ca)
 
+let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca =
+  do_add_code_annot ~keep_empty emitter ?kf stmt ca;
+  Changed.apply()
+
 let add_assert e ?kf stmt a =
   let a = Logic_const.toplevel_predicate ~kind:Assert a in
   let a = Logic_const.new_code_annotation (AAssert ([],a)) in
@@ -1667,7 +1745,8 @@ let add_model_field e m =
     try Emitter.Usable_emitter.Hashtbl.find h e
     with Not_found -> []
   in
-  Emitter.Usable_emitter.Hashtbl.replace h e (m::l)
+  Emitter.Usable_emitter.Hashtbl.replace h e (m::l);
+  Changed.apply()
 
 let unsafe_add_global e a =
   (*  Kernel.feedback "adding global %a in project %a"
@@ -1682,7 +1761,8 @@ let unsafe_add_global e a =
 
 let add_global e a =
   unsafe_add_global e a;
-  if Ast.is_computed() then insert_global_in_ast a
+  if Ast.is_computed() then insert_global_in_ast a;
+  Changed.apply()
 
 (**************************************************************************)
 (** {2 Other useful functions} *)
@@ -1779,7 +1859,9 @@ let code_annot_of_kf kf = match kf.fundec with
 
 (* don't export the possibility to removing an annotation without associated
    statuses. This is purely internal. *)
-let remove_code_annot e ?kf stmt ca = remove_code_annot_internal e ?kf stmt ca
+let remove_code_annot e ?kf stmt ca =
+  remove_code_annot_internal e ?kf stmt ca;
+  Changed.apply()
 
 (*
   Local Variables:
diff --git a/src/kernel_services/plugin_entry_points/emitter.ml b/src/kernel_services/plugin_entry_points/emitter.ml
index e4938ddf54d..6f7d97ede62 100644
--- a/src/kernel_services/plugin_entry_points/emitter.ml
+++ b/src/kernel_services/plugin_entry_points/emitter.ml
@@ -508,8 +508,9 @@ module Make_table
     (Info: sig include State_builder.Info_with_size val kinds: kind list end) =
 struct
 
-  module Update_hooks = Hook.Build(struct type t = E.t * H.key * D.t end)
   module Remove_hooks = Hook.Build(struct type t = E.t * H.key * D.t end)
+  let add_hook_on_remove f = Remove_hooks.extend (fun (e, k, d) -> f e k d)
+  let apply_hooks_on_remove e k d = Remove_hooks.apply (e, k, d)
 
   (* this list is computed after defining [self] *)
   let static_dependencies = ref []
@@ -565,7 +566,7 @@ struct
             H.iter
               (fun k h ->
                  if not (Remove_hooks.is_empty ()) then
-                   E.Hashtbl.iter (fun e x -> Remove_hooks.apply (e,k,x)) h;
+                   E.Hashtbl.iter (fun e x -> apply_hooks_on_remove e k x) h;
                  E.local_clear k h)
               tbl;
           end else begin
@@ -595,7 +596,7 @@ struct
                      Info.name
                      Project.pretty (Project.current ());
                    E.Hashtbl.remove h e;
-                   Remove_hooks.apply (e,k,x);
+                   apply_hooks_on_remove e k x
                  with Not_found ->
                    assert false)
               !to_be_removed
@@ -610,17 +611,6 @@ struct
         let dependencies = self :: dependencies
       end)
 
-  let add_hook_on_update f = Update_hooks.extend (fun (e, k, d) -> f e k d)
-  let add_hook_on_remove f = Remove_hooks.extend (fun (e, k, d) -> f e k d)
-  let apply_hooks_on_update e k d = Update_hooks.apply (e, k, d)
-  let apply_hooks_on_remove e k d = Remove_hooks.apply (e, k, d)
-
-  let notify f k =
-    try
-      let tbl = H.find !state k in
-      E.Hashtbl.iter (fun e v -> f e k v) tbl;
-    with Not_found -> ()
-
   let add_kind k =
     try
       let l = Hashtbl.find kinds k in
@@ -641,6 +631,7 @@ struct
     Cmdline.run_after_early_stage
       (fun () -> static_dependencies := get_dependencies ())
 
+  let add key v = H.add !state key v
   let find key = H.find !state key
   let mem key = H.mem !state key
   let iter f = H.iter f !state
@@ -648,12 +639,15 @@ struct
   let to_seq () = H.to_seq !state
   let iter_sorted ~cmp f = H.iter_sorted ~cmp f !state
   let fold_sorted ~cmp f acc = H.fold_sorted ~cmp f !state acc
-  let add key v =
-    H.add !state key v ;
-    if not (Update_hooks.is_empty ()) then notify apply_hooks_on_update key
   let remove key =
-    if not (Remove_hooks.is_empty ()) then notify apply_hooks_on_remove key ;
-    H.remove !state key
+    if not (Remove_hooks.is_empty ()) then begin
+      try
+        let tbl = find key in
+        E.Hashtbl.iter (fun e v -> apply_hooks_on_remove e key v) tbl;
+      with Not_found ->
+        ()
+    end;
+    H.remove !state key;
 
 end
 
diff --git a/src/kernel_services/plugin_entry_points/emitter.mli b/src/kernel_services/plugin_entry_points/emitter.mli
index dbcd4c4fc72..6215281eb6f 100644
--- a/src/kernel_services/plugin_entry_points/emitter.mli
+++ b/src/kernel_services/plugin_entry_points/emitter.mli
@@ -143,26 +143,14 @@ sig
     cmp: (H.key -> H.key -> int) ->
     (H.key -> internal_tbl -> 'a -> 'a) -> 'a -> 'a
   val remove: H.key -> unit
-
-  val add_hook_on_update: (E.t -> H.key -> D.t -> unit) -> unit
-  (** Register a hook to be applied whenever a binding is added or updated
-      into the table.
-      @since Frama-C+dev *)
-
   val add_hook_on_remove: (E.t -> H.key -> D.t -> unit) -> unit
   (** Register a hook to be applied whenever a binding is removed from the table.
       @since Fluorine-20130401 *)
 
-  val apply_hooks_on_update: E.t -> H.key -> D.t -> unit
-  (** This function must be called on each binding which is updated in the
-      table without directly calling the function {!remove}.
-      @since Frama-C+dev *)
-
   val apply_hooks_on_remove: E.t -> H.key -> D.t -> unit
   (** This function must be called on each binding which is removed from the
       table without directly calling the function {!remove}.
       @since Fluorine-20130401 *)
-
 end
 
 (*
-- 
GitLab