From 1613330540c7fd77a8d5848b7cca2a93dc584643 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 27 Oct 2023 08:08:14 +0200 Subject: [PATCH 1/5] Refactor typedtree traverse to use compiler traverse Signed-off-by: Paul-Elliot --- src/.ocamlformat-ignore | 1 + src/loader/implementation.ml | 391 ++++++++----------------------- src/loader/typedtree_traverse.ml | 68 ++++++ 3 files changed, 163 insertions(+), 297 deletions(-) create mode 100644 src/loader/typedtree_traverse.ml diff --git a/src/.ocamlformat-ignore b/src/.ocamlformat-ignore index 501dc4631b..5a278fe4ae 100644 --- a/src/.ocamlformat-ignore +++ b/src/.ocamlformat-ignore @@ -6,6 +6,7 @@ loader/cmt.ml loader/cmti.ml loader/doc_attr.ml loader/implementation.ml +loader/typedtree_traverse.ml loader/lookup_def.ml loader/lookup_def.mli loader/odoc_loader.ml diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 86818a8637..0e1b02ca3f 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -4,340 +4,140 @@ let pos_of_loc loc = (loc.Location.loc_start.pos_cnum, loc.loc_end.pos_cnum) -type annotations = - | LocalDefinition of Ident.t - | LocalValue of Ident.t - | DefJmp of Shape.Uid.t - let counter = let c = ref 0 in fun () -> incr c; !c -module Analysis = struct +module Env = struct open Typedtree open Odoc_model.Paths - type env = Ident_env.t * Location.t Shape.Uid.Tbl.t - - let env_wrap : (Ident_env.t -> Ident_env.t) -> env -> env = - fun f (env, uid_to_loc) -> (f env, uid_to_loc) - - let get_env : env -> Ident_env.t = fun (env, _) -> env - - let get_uid_to_loc : env -> Location.t Shape.Uid.Tbl.t = - fun (_, uid_to_loc) -> uid_to_loc - - let rec structure env parent acc str = - let env' = env_wrap (Ident_env.add_structure_tree_items parent str) env in - List.fold_left (structure_item env' parent) acc str.str_items + let rec structure env parent str = + let env' = Ident_env.add_structure_tree_items parent str env in + List.iter (structure_item env' parent) str.str_items - and signature env parent acc sg = - let env' = env_wrap (Ident_env.add_signature_tree_items parent sg) env in - List.fold_left (signature_item env' parent) acc sg.sig_items + and signature env parent sg = + let env' = Ident_env.add_signature_tree_items parent sg env in + List.iter (signature_item env' parent) sg.sig_items - and signature_item env parent acc item = + and signature_item env parent item = match item.sig_desc with - | Tsig_value vd -> value_description env parent acc vd - | Tsig_type (_, tds) -> type_declarations env parent acc tds - | Tsig_typesubst tds -> type_declarations env parent acc tds - | Tsig_typext _ -> acc - | Tsig_exception e -> exception_ env parent acc e - | Tsig_module mb -> module_declaration env parent acc mb - | Tsig_modsubst ms -> module_substitution env parent acc ms - | Tsig_recmodule mbs -> module_declarations env parent acc mbs - | Tsig_modtype mtd -> module_type_declaration env parent acc mtd - | Tsig_modtypesubst mtd -> module_type_declaration env parent acc mtd - | Tsig_open _ -> acc - | Tsig_include _ -> acc - | Tsig_class cd -> class_description env parent acc cd - | Tsig_class_type ctd -> class_type_declaration env parent acc ctd - | Tsig_attribute _ -> acc - - and value_description _env _parent acc _vd = acc - - (* and type_declaration _env _parent _td = [] *) - - and type_declarations _env _parent acc _tds = acc - - and exception_ _env _parent acc _e = acc - - and module_declaration env _parent acc md = + | Tsig_module mb -> module_declaration env parent mb + | Tsig_recmodule mbs -> module_declarations env parent mbs + | Tsig_modtype mtd -> module_type_declaration env parent mtd + | Tsig_modtypesubst mtd -> module_type_declaration env parent mtd + | Tsig_value _ | Tsig_type _ | Tsig_typesubst _ | Tsig_typext _ + | Tsig_exception _ | Tsig_modsubst _ | Tsig_open _ | Tsig_include _ + | Tsig_class _ | Tsig_class_type _ | Tsig_attribute _ -> + () + + and module_declaration env _parent md = match md.md_id with - | None -> acc + | None -> () | Some mb_id -> - let id = Ident_env.find_module_identifier (get_env env) mb_id in - module_type env (id :> Identifier.Signature.t) acc md.md_type - - and module_declarations env parent acc mds = - List.fold_left (module_declaration env parent) acc mds + let id = Ident_env.find_module_identifier env mb_id in + module_type env (id :> Identifier.Signature.t) md.md_type - and module_substitution _env _parent acc _ms = acc + and module_declarations env parent mds = + List.iter (module_declaration env parent) mds - and module_type_declaration env _parent acc mtd = - let id = Ident_env.find_module_type (get_env env) mtd.mtd_id in + and module_type_declaration env _parent mtd = + let id = Ident_env.find_module_type env mtd.mtd_id in match mtd.mtd_type with - | None -> acc - | Some mty -> module_type env (id :> Identifier.Signature.t) acc mty - - and class_description _env _parent acc _cd = acc - - and class_type_declaration _env _parent acc _ctd = acc + | None -> () + | Some mty -> module_type env (id :> Identifier.Signature.t) mty - and structure_item env parent acc item = + and structure_item env parent item = match item.str_desc with - | Tstr_eval (e, _) -> expression env acc e - | Tstr_value (_, vbs) -> value_bindings env parent acc vbs - | Tstr_module mb -> module_binding env parent acc mb - | Tstr_recmodule mbs -> module_bindings env parent acc mbs - | Tstr_modtype mtd -> module_type_decl env parent acc mtd - | Tstr_open _ -> acc - | Tstr_class _ -> acc - | Tstr_class_type _ -> acc - | Tstr_include _ -> acc - | Tstr_attribute _ -> acc - | Tstr_primitive _ -> acc - | Tstr_type (_, tds) -> type_declarations env parent acc tds - | Tstr_typext _ -> acc - | Tstr_exception _ -> acc - - and value_bindings env _parent acc vbs = - List.fold_left (value_binding env) acc vbs - - and pattern : type a. env -> _ -> a general_pattern -> _ = - fun env acc p -> - let maybe_localvalue id loc = - match Ident_env.identifier_of_loc (get_env env) loc with - | None -> Some (LocalDefinition id, pos_of_loc loc) - | Some _ -> None - in - match p.pat_desc with - | Tpat_any -> acc - | Tpat_var (id, loc) -> ( - match maybe_localvalue id loc.loc with - | Some x -> x :: acc - | None -> acc) - | Tpat_alias (p, id, loc) -> ( - match maybe_localvalue id loc.loc with - | Some x -> x :: pattern env acc p - | None -> pattern env acc p) - | Tpat_constant _ -> acc - | Tpat_tuple ps -> List.fold_left (pattern env) acc ps - | Tpat_construct (_, _, ps, _) -> List.fold_left (pattern env) acc ps - | Tpat_variant (_, None, _) -> acc - | Tpat_variant (_, Some p, _) -> pattern env acc p - | Tpat_record (fields, _) -> - List.fold_left (fun acc (_, _, p) -> pattern env acc p) acc fields - | Tpat_array ps -> List.fold_left (pattern env) acc ps - | Tpat_or (p1, p2, _) -> - let acc = pattern env acc p1 in - pattern env acc p2 - | Tpat_lazy p -> pattern env acc p - | Tpat_exception p -> pattern env acc p - | Tpat_value p -> pattern env acc (p :> pattern) - - and value_binding env acc vb = - let acc = pattern env acc vb.vb_pat in - expression env acc vb.vb_expr - - and expression env acc { exp_desc; exp_loc; _ } = - match exp_desc with - | Texp_ident (p, _, value_description) -> ( - if exp_loc.loc_ghost then acc - else - (* Only generate anchor if the uid is in the location table. We don't - link to modules outside of the compilation unit. *) - match - Shape.Uid.Tbl.find_opt (get_uid_to_loc env) - value_description.val_uid - with - | Some _ -> - (DefJmp value_description.val_uid, pos_of_loc exp_loc) :: acc - | None -> ( - match p with - | Pident id -> (LocalValue id, pos_of_loc exp_loc) :: acc - | _ -> acc)) - | Texp_constant _ -> acc - | Texp_let (_, vbs, e) -> - let acc = List.fold_left (value_binding env) acc vbs in - expression env acc e - | Texp_function f -> List.fold_left (case env) acc f.cases - | Texp_match (e, cases, _) -> - let acc = expression env acc e in - List.fold_left (case env) acc cases - | Texp_try (e, cases) -> - let acc = expression env acc e in - List.fold_left (case env) acc cases - | Texp_tuple es -> List.fold_left (expression env) acc es - | Texp_construct (_, cons_description, es) -> - let acc = - if exp_loc.loc_ghost then acc - else - match - Shape.Uid.Tbl.find_opt (get_uid_to_loc env) - cons_description.cstr_uid - with - | Some _ -> - (DefJmp cons_description.cstr_uid, pos_of_loc exp_loc) :: acc - | None -> acc - in - List.fold_left (expression env) acc es - | Texp_variant (_, Some e) -> expression env acc e - | Texp_variant (_, None) -> acc - | Texp_record { fields; extended_expression; _ } -> - let acc = - match extended_expression with - | None -> acc - | Some expr -> expression env acc expr - in - List.fold_left (record_fields env) acc (Array.to_list fields) - | Texp_field (e, _, _) -> expression env acc e - | Texp_setfield (e1, _, _, e2) -> - let acc = expression env acc e1 in - expression env acc e2 - | Texp_array es -> List.fold_left (expression env) acc es - | Texp_ifthenelse (e1, e2, e3) -> - let acc = - match e3 with Some e -> expression env acc e | None -> acc - in - let acc = expression env acc e1 in - expression env acc e2 - | Texp_sequence (e1, e2) -> - let acc = expression env acc e1 in - expression env acc e2 - | Texp_while (e1, e2) -> - let acc = expression env acc e1 in - expression env acc e2 - | Texp_for (id, p, e1, e2, _, e3) -> - let acc = (LocalValue id, pos_of_loc p.ppat_loc) :: acc in - let acc = expression env acc e1 in - let acc = expression env acc e2 in - expression env acc e3 - | Texp_send (e, _) -> expression env acc e - | Texp_new _ -> acc - | Texp_instvar (_, _, _) -> acc - | Texp_setinstvar (_, _, _, e) -> expression env acc e - | Texp_override (_, es) -> - List.fold_left (fun acc (_, _, e) -> expression env acc e) acc es - | Texp_letmodule (_, _, _, _m, e) -> expression env acc e - | Texp_letexception (_, e) -> expression env acc e -#if OCAML_VERSION < (5,1,0) - | Texp_assert e -#else - | Texp_assert (e, _) -#endif - -> expression env acc e - | Texp_lazy e -> expression env acc e - | Texp_object (_, _) -> acc - | Texp_pack _ -> acc - | Texp_letop { let_; ands; body; _ } -> - let acc = case env acc body in - let acc = binding_op env acc let_ in - List.fold_left (binding_op env) acc ands - | Texp_unreachable -> acc - | Texp_extension_constructor _ -> acc - | Texp_open (_, e) -> expression env acc e - | Texp_apply (e, es) -> - let acc = expression env acc e in - List.fold_left - (fun acc -> function _, Some e -> expression env acc e | _ -> acc) - acc es - - and binding_op env acc = function - | { bop_exp; _ } -> expression env acc bop_exp - - and record_fields env acc f = - match f with - | _, Overridden (_, e) -> expression env acc e - | _, Kept _ -> acc - - and case : type a. env -> _ -> a Typedtree.case -> _ = - fun env acc c -> - let acc = pattern env acc c.c_lhs in - match c.c_guard with - | None -> expression env acc c.c_rhs - | Some e -> - let acc = expression env acc e in - expression env acc c.c_rhs - - and module_type_decl env _parent acc mtd = - let id = Ident_env.find_module_type (get_env env) mtd.mtd_id in + | Tstr_module mb -> module_binding env parent mb + | Tstr_recmodule mbs -> module_bindings env parent mbs + | Tstr_modtype mtd -> module_type_decl env parent mtd + | Tstr_open _ | Tstr_value _ | Tstr_class _ | Tstr_eval _ + | Tstr_class_type _ | Tstr_include _ | Tstr_attribute _ | Tstr_primitive _ + | Tstr_type _ | Tstr_typext _ | Tstr_exception _ -> + () + + and module_type_decl env _parent mtd = + let id = Ident_env.find_module_type env mtd.mtd_id in match mtd.mtd_type with - | None -> acc - | Some mty -> module_type env (id :> Identifier.Signature.t) acc mty + | None -> () + | Some mty -> module_type env (id :> Identifier.Signature.t) mty - and module_type env (parent : Identifier.Signature.t) acc mty = + and module_type env (parent : Identifier.Signature.t) mty = match mty.mty_desc with - | Tmty_signature sg -> - signature env (parent : Identifier.Signature.t) acc sg - | Tmty_with (mty, _) -> module_type env parent acc mty - | Tmty_ident _ -> acc - | Tmty_functor (_, t) -> module_type env parent acc t - | Tmty_alias _ -> acc - | Tmty_typeof _ -> acc + | Tmty_signature sg -> signature env (parent : Identifier.Signature.t) sg + | Tmty_with (mty, _) -> module_type env parent mty + | Tmty_functor (_, t) -> module_type env parent t + | Tmty_ident _ | Tmty_alias _ | Tmty_typeof _ -> () - and module_bindings env parent acc mbs = - List.fold_left (module_binding env parent) acc mbs + and module_bindings env parent mbs = List.iter (module_binding env parent) mbs - and module_binding env _parent acc mb = + and module_binding env _parent mb = match mb.mb_id with - | None -> acc + | None -> () | Some id -> - let id = Ident_env.find_module_identifier (get_env env) id in + let id = Ident_env.find_module_identifier env id in let id = (id :> Identifier.Module.t) in let inner = match unwrap_module_expr_desc mb.mb_expr.mod_desc with - | Tmod_ident (_p, _) -> acc + | Tmod_ident (_p, _) -> () | _ -> let id = (id :> Identifier.Signature.t) in - module_expr env id acc mb.mb_expr + module_expr env id mb.mb_expr in inner - and module_expr env parent acc mexpr = + and module_expr env parent mexpr = match mexpr.mod_desc with - | Tmod_ident _ -> acc - | Tmod_structure str -> structure env parent acc str + | Tmod_ident _ -> () + | Tmod_structure str -> structure env parent str | Tmod_functor (parameter, res) -> let open Odoc_model.Names in - let acc, env = + let env = match parameter with - | Unit -> (acc, env) + | Unit -> env | Named (id_opt, _, arg) -> ( match id_opt with | Some id -> let env = - env_wrap - (Ident_env.add_parameter parent id - (ModuleName.of_ident id)) + Ident_env.add_parameter parent id (ModuleName.of_ident id) env in - let id = Ident_env.find_module_identifier (get_env env) id in - (module_type env (id :> Identifier.Signature.t) acc arg, env) - | None -> (acc, env)) + let id = Ident_env.find_module_identifier env id in + module_type env (id :> Identifier.Signature.t) arg; + env + | None -> env) in - module_expr env (Odoc_model.Paths.Identifier.Mk.result parent) acc res + module_expr env (Odoc_model.Paths.Identifier.Mk.result parent) res | Tmod_constraint (me, _, constr, _) -> - let acc = + let () = match constr with - | Tmodtype_implicit -> acc - | Tmodtype_explicit mt -> module_type env parent acc mt + | Tmodtype_implicit -> () + | Tmodtype_explicit mt -> module_type env parent mt in - module_expr env parent acc me - | _ -> acc + module_expr env parent me + | _ -> () and unwrap_module_expr_desc = function | Tmod_constraint (mexpr, _, Tmodtype_implicit, _) -> unwrap_module_expr_desc mexpr.mod_desc | desc -> desc + + let of_structure (id : Odoc_model.Paths.Identifier.RootModule.t) + (s : Typedtree.structure) = + let env = Ident_env.empty () in + let () = structure env (id :> Odoc_model.Paths.Identifier.Signature.t) s in + env end -let postprocess_poses source_id poses uid_to_id uid_to_loc = +let postprocess_poses source_id poses uid_to_id uid_to_loc : + Odoc_model.Lang.Source_info.infos = let local_def_anchors = List.filter_map (function - | LocalDefinition id, _ -> + | Typedtree_traverse.Analysis.Definition id, _ -> let name = Odoc_model.Names.LocalName.make_std (Printf.sprintf "local_%s_%d" (Ident.name id) (counter ())) @@ -353,16 +153,16 @@ let postprocess_poses source_id poses uid_to_id uid_to_loc = let poses = List.filter_map (function - | LocalDefinition id, loc -> + | Typedtree_traverse.Analysis.Definition id, loc -> Some ( Odoc_model.Lang.Source_info.Definition (List.assoc id local_def_anchors), loc ) - | LocalValue uniq, loc -> ( + | Value (LocalValue uniq), loc -> ( match List.assoc_opt uniq local_def_anchors with | Some anchor -> Some (Value anchor, loc) | None -> None) - | DefJmp x, loc -> ( + | Value (DefJmp x), loc -> ( match Shape.Uid.Map.find_opt x uid_to_id with | Some id -> Some (Value id, loc) | None -> None)) @@ -457,21 +257,13 @@ let anchor_of_identifier id = in anchor_of_identifier [] id |> String.concat "." -let of_cmt (source_id : Odoc_model.Paths.Identifier.SourcePage.t) +(** Returns an environment (containing a [loc] to [id] map) and an [uid] to [id] + maps. *) +let id_maps_of_cmt (source_id : Odoc_model.Paths.Identifier.SourcePage.t) (id : Odoc_model.Paths.Identifier.RootModule.t) (structure : Typedtree.structure) (uid_to_loc : Warnings.loc Types.Uid.Tbl.t) = - let env = Ident_env.empty () in - let vs = - Analysis.structure (env, uid_to_loc) - (id :> Odoc_model.Paths.Identifier.Signature.t) - [] structure - |> List.rev - (* Information are accumulated in a list. We need to have the - first info first in the list, to assign anchors with increasing - numbers, so that adding some content at the end of a file does - not modify the anchors for existing anchors. *) - in + let env = Env.of_structure id structure in let uid_to_loc_map = Shape.Uid.Tbl.to_map uid_to_loc in let uid_to_id : Odoc_model.Paths.Identifier.SourceLocation.t Shape.Uid.Map.t = Shape.Uid.Map.filter_map @@ -503,8 +295,7 @@ let of_cmt (source_id : Odoc_model.Paths.Identifier.SourcePage.t) | None -> None) uid_to_loc_map in - - (uid_to_id, postprocess_poses source_id vs uid_to_id uid_to_loc) + (uid_to_id, env) let read_cmt_infos source_id_opt id cmt_info = match Odoc_model.Compat.shape_of_cmt_infos cmt_info with @@ -512,8 +303,16 @@ let read_cmt_infos source_id_opt id cmt_info = let uid_to_loc = cmt_info.cmt_uid_to_loc in match (source_id_opt, cmt_info.cmt_annots) with | Some source_id, Implementation impl -> - let map, source_infos = - of_cmt source_id id impl uid_to_loc + let map, env = id_maps_of_cmt source_id id impl uid_to_loc in + let occ_infos = + Typedtree_traverse.of_cmt env uid_to_loc impl |> List.rev + (* Information are accumulated in a list. We need to have the + first info first in the list, to assign anchors with increasing + numbers, so that adding some content at the end of a file does + not modify the anchors for existing anchors. *) + in + let source_infos = + postprocess_poses source_id occ_infos map uid_to_loc in ( Some (shape, map), Some @@ -524,8 +323,6 @@ let read_cmt_infos source_id_opt id cmt_info = | _, _ -> (Some (shape, Odoc_model.Compat.empty_map), None)) | None -> (None, None) - - #else let read_cmt_infos _source_id_opt _id _cmt_info = diff --git a/src/loader/typedtree_traverse.ml b/src/loader/typedtree_traverse.ml new file mode 100644 index 0000000000..a362dee57a --- /dev/null +++ b/src/loader/typedtree_traverse.ml @@ -0,0 +1,68 @@ +#if OCAML_VERSION >= (4, 14, 0) + +let pos_of_loc loc = (loc.Location.loc_start.pos_cnum, loc.loc_end.pos_cnum) + +module Analysis = struct + type value_implementation = LocalValue of Ident.t | DefJmp of Shape.Uid.t + + type annotation = Definition of Ident.t | Value of value_implementation + + let expr uid_to_loc poses expr = + let exp_loc = expr.Typedtree.exp_loc in + if exp_loc.loc_ghost then () + else + match expr.exp_desc with + | Texp_ident (p, _, value_description) -> ( + let implementation = + match + Shape.Uid.Tbl.find_opt uid_to_loc value_description.val_uid + with + | Some _ -> Some (DefJmp value_description.val_uid) + | None -> ( + match p with Pident id -> Some (LocalValue id) | _ -> None) + in + match implementation with + | None -> () + | Some impl -> poses := (Value impl, pos_of_loc exp_loc) :: !poses) + | _ -> () + + let pat env (type a) poses : a Typedtree.general_pattern -> unit = function + | { Typedtree.pat_desc; pat_loc; _ } when not pat_loc.loc_ghost -> + let maybe_localvalue id loc = + match Ident_env.identifier_of_loc env loc with + | None -> Some (Definition id, pos_of_loc loc) + | Some _ -> None + in + let () = + match pat_desc with + | Tpat_var (id, loc) -> ( + match maybe_localvalue id loc.loc with + | Some x -> poses := x :: !poses + | None -> ()) + | Tpat_alias (_, id, loc) -> ( + match maybe_localvalue id loc.loc with + | Some x -> poses := x :: !poses + | None -> ()) + | _ -> () + in + () + | _ -> () +end + +let of_cmt env uid_to_loc structure = + let poses = ref [] in + let expr iterator e = + Analysis.expr uid_to_loc poses e; + Tast_iterator.default_iterator.expr iterator e + in + let pat iterator e = + Analysis.pat env poses e; + Tast_iterator.default_iterator.pat iterator e + in + let iterator = { Tast_iterator.default_iterator with expr; pat } in + iterator.structure iterator structure; + !poses + +#else + +#endif From 4354ad6db1c684200cc7f1e2ba1d02fbaca78dd8 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 27 Oct 2023 16:50:00 +0200 Subject: [PATCH 2/5] Source code: Avoid having two anchors at an identical location Signed-off-by: Paul-Elliot --- src/loader/implementation.ml | 119 +++++++++++++++++-------------- src/loader/typedtree_traverse.ml | 6 +- test/sources/source.t/run.t | 6 +- 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 0e1b02ca3f..2ed25471cb 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -132,39 +132,54 @@ module Env = struct env end -let postprocess_poses source_id poses uid_to_id uid_to_loc : +module LocHashtbl = Hashtbl.Make (struct + type t = Location.t + let equal l1 l2 = l1 = l2 + let hash = Hashtbl.hash +end) + +module IdentHashtbl = Hashtbl.Make (struct + type t = Ident.t + let equal l1 l2 = l1 = l2 + let hash = Hashtbl.hash +end) + +(* generate a [loc_to_id] and an [ident_to_id] map *) +let local_maps source_id poses = + let loc_tbl = LocHashtbl.create 10 and ident_to_id = IdentHashtbl.create 10 in + List.iter + (function + | Typedtree_traverse.Analysis.Definition id, loc -> + let name = + Odoc_model.Names.LocalName.make_std + (Printf.sprintf "local_%s_%d" (Ident.name id) (counter ())) + in + let identifier = + Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name) + in + IdentHashtbl.add ident_to_id id identifier; + LocHashtbl.add loc_tbl loc identifier + | _ -> ()) + poses; + (loc_tbl, ident_to_id) + +let postprocess_poses poses ident_to_id loc_to_id uid_to_id uid_to_loc : Odoc_model.Lang.Source_info.infos = - let local_def_anchors = - List.filter_map - (function - | Typedtree_traverse.Analysis.Definition id, _ -> - let name = - Odoc_model.Names.LocalName.make_std - (Printf.sprintf "local_%s_%d" (Ident.name id) (counter ())) - in - let identifier = - Odoc_model.Paths.Identifier.Mk.source_location_int - (source_id, name) - in - Some (id, identifier) - | _ -> None) - poses - in let poses = List.filter_map (function | Typedtree_traverse.Analysis.Definition id, loc -> Some ( Odoc_model.Lang.Source_info.Definition - (List.assoc id local_def_anchors), - loc ) + (IdentHashtbl.find ident_to_id id), + pos_of_loc loc ) | Value (LocalValue uniq), loc -> ( - match List.assoc_opt uniq local_def_anchors with - | Some anchor -> Some (Value anchor, loc) + match IdentHashtbl.find_opt ident_to_id uniq with + | Some anchor -> Some (Value anchor, pos_of_loc loc) | None -> None) | Value (DefJmp x), loc -> ( match Shape.Uid.Map.find_opt x uid_to_id with - | Some id -> Some (Value id, loc) + | Some id -> Some (Value id, pos_of_loc loc) | None -> None)) poses in @@ -173,7 +188,7 @@ let postprocess_poses source_id poses uid_to_id uid_to_loc : (fun uid id acc -> let loc_opt = Shape.Uid.Tbl.find_opt uid_to_loc uid in match loc_opt with - | Some loc -> + | Some loc when not (LocHashtbl.mem loc_to_id loc) -> (Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc | _ -> acc) uid_to_id [] @@ -259,43 +274,39 @@ let anchor_of_identifier id = (** Returns an environment (containing a [loc] to [id] map) and an [uid] to [id] maps. *) -let id_maps_of_cmt (source_id : Odoc_model.Paths.Identifier.SourcePage.t) - (id : Odoc_model.Paths.Identifier.RootModule.t) - (structure : Typedtree.structure) - (uid_to_loc : Warnings.loc Types.Uid.Tbl.t) = - let env = Env.of_structure id structure in +let id_map_of_cmt env (source_id : Odoc_model.Paths.Identifier.SourcePage.t) + (uid_to_loc : Warnings.loc Types.Uid.Tbl.t) local_loc_to_id = let uid_to_loc_map = Shape.Uid.Tbl.to_map uid_to_loc in + let mk_id name = + Some + (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) + :> Odoc_model.Paths.Identifier.SourceLocation.t) + in let uid_to_id : Odoc_model.Paths.Identifier.SourceLocation.t Shape.Uid.Map.t = Shape.Uid.Map.filter_map (fun uid loc -> if loc.Location.loc_ghost then None else let identifier = Ident_env.identifier_of_loc env loc in - let anchor = - match identifier with - | Some x -> - Some - (Odoc_model.Names.DefName.make_std (anchor_of_identifier x)) - | None -> ( - match uid with - | Compilation_unit _ -> None - | Item _ -> - let name = - Odoc_model.Names.DefName.make_std - (Printf.sprintf "def_%d" (counter ())) - in - Some name - | _ -> None) - in - match anchor with - | Some a -> - Some - (Odoc_model.Paths.Identifier.Mk.source_location (source_id, a) - :> Odoc_model.Paths.Identifier.SourceLocation.t) - | None -> None) + match identifier with + | Some x -> + mk_id (Odoc_model.Names.DefName.make_std (anchor_of_identifier x)) + | None -> ( + match uid with + | Compilation_unit _ -> None + | Item _ -> ( + match LocHashtbl.find_opt local_loc_to_id loc with + | Some anchor -> Some anchor + | None -> + let name = + Odoc_model.Names.DefName.make_std + (Printf.sprintf "def_%d" (counter ())) + in + mk_id name) + | _ -> None)) uid_to_loc_map in - (uid_to_id, env) + uid_to_id let read_cmt_infos source_id_opt id cmt_info = match Odoc_model.Compat.shape_of_cmt_infos cmt_info with @@ -303,7 +314,7 @@ let read_cmt_infos source_id_opt id cmt_info = let uid_to_loc = cmt_info.cmt_uid_to_loc in match (source_id_opt, cmt_info.cmt_annots) with | Some source_id, Implementation impl -> - let map, env = id_maps_of_cmt source_id id impl uid_to_loc in + let env = Env.of_structure id impl in let occ_infos = Typedtree_traverse.of_cmt env uid_to_loc impl |> List.rev (* Information are accumulated in a list. We need to have the @@ -311,8 +322,10 @@ let read_cmt_infos source_id_opt id cmt_info = numbers, so that adding some content at the end of a file does not modify the anchors for existing anchors. *) in + let loc_to_id, ident_to_id = local_maps source_id occ_infos in + let map = id_map_of_cmt env source_id uid_to_loc loc_to_id in let source_infos = - postprocess_poses source_id occ_infos map uid_to_loc + postprocess_poses occ_infos ident_to_id loc_to_id map uid_to_loc in ( Some (shape, map), Some diff --git a/src/loader/typedtree_traverse.ml b/src/loader/typedtree_traverse.ml index a362dee57a..164035bb3b 100644 --- a/src/loader/typedtree_traverse.ml +++ b/src/loader/typedtree_traverse.ml @@ -1,7 +1,5 @@ #if OCAML_VERSION >= (4, 14, 0) -let pos_of_loc loc = (loc.Location.loc_start.pos_cnum, loc.loc_end.pos_cnum) - module Analysis = struct type value_implementation = LocalValue of Ident.t | DefJmp of Shape.Uid.t @@ -23,14 +21,14 @@ module Analysis = struct in match implementation with | None -> () - | Some impl -> poses := (Value impl, pos_of_loc exp_loc) :: !poses) + | Some impl -> poses := (Value impl, exp_loc) :: !poses) | _ -> () let pat env (type a) poses : a Typedtree.general_pattern -> unit = function | { Typedtree.pat_desc; pat_loc; _ } when not pat_loc.loc_ghost -> let maybe_localvalue id loc = match Ident_env.identifier_of_loc env loc with - | None -> Some (Definition id, pos_of_loc loc) + | None -> Some (Definition id, loc) | Some _ -> None in let () = diff --git a/test/sources/source.t/run.t b/test/sources/source.t/run.t index 7d7186a80b..ec829b8280 100644 --- a/test/sources/source.t/run.t +++ b/test/sources/source.t/run.t @@ -279,9 +279,9 @@ Ids generated in the source code: id="val-{x}2" id="val-y" id="val-z" - id="local_a_2" + id="local_a_1" id="val-z'" - id="local_a_3" + id="local_a_2" id="module-A" id="module-B" id="module-type-T" @@ -303,7 +303,7 @@ Ids generated in the source code: id="module-F.argument-1-M.module-A" id="module-F.module-B" id="module-FM" - id="def_1" + id="def_3" id="module-FF" id="module-FF2" id="module-FF2.argument-1-A.module-E" From 91c07c0e60c9b12bec2f72646fbb44f11e4ad47a Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Tue, 31 Oct 2023 15:29:28 +0100 Subject: [PATCH 3/5] Render source code: tidy up info extraction Signed-off-by: Paul-Elliot --- src/loader/ident_env.cppo.ml | 3 + src/loader/ident_env.cppo.mli | 5 +- src/loader/implementation.ml | 157 +++++++++++++++++----------------- test/sources/source.t/run.t | 4 + 4 files changed, 90 insertions(+), 79 deletions(-) diff --git a/src/loader/ident_env.cppo.ml b/src/loader/ident_env.cppo.ml index c03fa70b5f..0d2dea858f 100644 --- a/src/loader/ident_env.cppo.ml +++ b/src/loader/ident_env.cppo.ml @@ -605,6 +605,9 @@ let add_items : Id.Signature.t -> item list -> t -> t = fun parent items env -> let identifier_of_loc : t -> Location.t -> Odoc_model.Paths.Identifier.t option = fun env loc -> try Some (LocHashtbl.find env.loc_to_ident loc) with Not_found -> None +let iter_located_identifier : t -> (Location.t -> Odoc_model.Paths.Identifier.t -> unit) -> unit = fun env f -> + LocHashtbl.iter f env.loc_to_ident + let add_signature_tree_items : Paths.Identifier.Signature.t -> Typedtree.signature -> t -> t = fun parent sg env -> let items = extract_signature_tree_items false sg.sig_items |> flatten_includes in diff --git a/src/loader/ident_env.cppo.mli b/src/loader/ident_env.cppo.mli index 5a109be660..316e135f63 100644 --- a/src/loader/ident_env.cppo.mli +++ b/src/loader/ident_env.cppo.mli @@ -77,7 +77,10 @@ module Fragment : sig val read_type : Longident.t -> Paths.Fragment.Type.t end -val identifier_of_loc : t -> Location.t -> Odoc_model.Paths.Identifier.t option +val identifier_of_loc : t -> Location.t -> Paths.Identifier.t option (** Each generated id has its location stored. This allows to get back the id knowing only the location. This is used to generate links to source from the resolution of a shape. *) + +val iter_located_identifier : t -> (Location.t -> Paths.Identifier.t -> unit) -> unit +(** Iter on all stored pair [location]-[identifier]. *) diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 2ed25471cb..46598274a7 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -144,10 +144,11 @@ module IdentHashtbl = Hashtbl.Make (struct let hash = Hashtbl.hash end) -(* generate a [loc_to_id] and an [ident_to_id] map *) -let local_maps source_id poses = - let loc_tbl = LocHashtbl.create 10 and ident_to_id = IdentHashtbl.create 10 in - List.iter +(* populate a [loc_to_id] and an [ident_to_id] map with local informations. Also + removes the definitions from the list, since their information has been taken + into account *) +let process_local_defs source_id poses loc_tbl ident_to_id = + List.filter_map (function | Typedtree_traverse.Analysis.Definition id, loc -> let name = @@ -158,43 +159,13 @@ let local_maps source_id poses = Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name) in IdentHashtbl.add ident_to_id id identifier; - LocHashtbl.add loc_tbl loc identifier - | _ -> ()) - poses; - (loc_tbl, ident_to_id) - -let postprocess_poses poses ident_to_id loc_to_id uid_to_id uid_to_loc : - Odoc_model.Lang.Source_info.infos = - let poses = - List.filter_map - (function - | Typedtree_traverse.Analysis.Definition id, loc -> - Some - ( Odoc_model.Lang.Source_info.Definition - (IdentHashtbl.find ident_to_id id), - pos_of_loc loc ) - | Value (LocalValue uniq), loc -> ( - match IdentHashtbl.find_opt ident_to_id uniq with - | Some anchor -> Some (Value anchor, pos_of_loc loc) - | None -> None) - | Value (DefJmp x), loc -> ( - match Shape.Uid.Map.find_opt x uid_to_id with - | Some id -> Some (Value id, pos_of_loc loc) - | None -> None)) - poses - in - let defs = - Shape.Uid.Map.fold - (fun uid id acc -> - let loc_opt = Shape.Uid.Tbl.find_opt uid_to_loc uid in - match loc_opt with - | Some loc when not (LocHashtbl.mem loc_to_id loc) -> - (Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc - | _ -> acc) - uid_to_id [] - in - defs @ poses + LocHashtbl.add loc_tbl loc identifier; + None + | x -> Some x) + poses +(* In order to turn an identifier into a source identifier, we need to generate + a unique anchor for any identifier. *) let anchor_of_identifier id = let open Odoc_document.Url in let open Odoc_model.Paths in @@ -272,41 +243,65 @@ let anchor_of_identifier id = in anchor_of_identifier [] id |> String.concat "." -(** Returns an environment (containing a [loc] to [id] map) and an [uid] to [id] - maps. *) -let id_map_of_cmt env (source_id : Odoc_model.Paths.Identifier.SourcePage.t) - (uid_to_loc : Warnings.loc Types.Uid.Tbl.t) local_loc_to_id = - let uid_to_loc_map = Shape.Uid.Tbl.to_map uid_to_loc in - let mk_id name = - Some - (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) - :> Odoc_model.Paths.Identifier.SourceLocation.t) +(* Adds the global defs from the odoc environment to [loc_to_id] table *) +let process_global_defs env source_id loc_to_id = + let mk_src_id id = + let name = Odoc_model.Names.DefName.make_std (anchor_of_identifier id) in + (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) + :> Odoc_model.Paths.Identifier.SourceLocation.t) in - let uid_to_id : Odoc_model.Paths.Identifier.SourceLocation.t Shape.Uid.Map.t = - Shape.Uid.Map.filter_map - (fun uid loc -> - if loc.Location.loc_ghost then None - else - let identifier = Ident_env.identifier_of_loc env loc in - match identifier with - | Some x -> - mk_id (Odoc_model.Names.DefName.make_std (anchor_of_identifier x)) - | None -> ( - match uid with - | Compilation_unit _ -> None - | Item _ -> ( - match LocHashtbl.find_opt local_loc_to_id loc with - | Some anchor -> Some anchor - | None -> - let name = - Odoc_model.Names.DefName.make_std - (Printf.sprintf "def_%d" (counter ())) - in - mk_id name) - | _ -> None)) - uid_to_loc_map + Ident_env.iter_located_identifier env @@ fun loc id -> + LocHashtbl.add loc_to_id loc (mk_src_id id) + +(* The [uid_to_id] is useful as when resolving a shape, we get the uid. *) +let build_uid_to_id source_id uid_to_loc loc_to_id = + let uid_to_loc_map = Shape.Uid.Tbl.to_map uid_to_loc in + let mk_src_id () = + let name = + Odoc_model.Names.DefName.make_std (Printf.sprintf "def_%d" (counter ())) + in + (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) + :> Odoc_model.Paths.Identifier.SourceLocation.t) in - uid_to_id + Shape.Uid.Map.filter_map + (fun uid loc -> + if loc.Location.loc_ghost then None + else + match LocHashtbl.find_opt loc_to_id loc with + | Some id -> Some id + | None -> ( + (* In case there is no entry for the location of the uid, we add one. *) + match uid with + | Item _ -> + let id = mk_src_id () in + LocHashtbl.add loc_to_id loc id; + Some id + | Compilation_unit _ -> None + | _ -> None)) + uid_to_loc_map + +(* Turns [Typedtree_traverse] occurrence information into proper source infos *) +let process_occurrences poses uid_to_id ident_to_id = + List.filter_map + (function + | Typedtree_traverse.Analysis.Value (LocalValue uniq), loc -> ( + match IdentHashtbl.find_opt ident_to_id uniq with + | Some anchor -> + Some (Odoc_model.Lang.Source_info.Value anchor, pos_of_loc loc) + | None -> None) + | Value (DefJmp x), loc -> ( + match Shape.Uid.Map.find_opt x uid_to_id with + | Some id -> Some (Value id, pos_of_loc loc) + | None -> None) + | Definition _, _ -> None) + poses + +(* Add definition source info from the [loc_to_id] table *) +let add_definitions occurrences loc_to_id = + LocHashtbl.fold + (fun loc id acc -> + (Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc) + loc_to_id occurrences let read_cmt_infos source_id_opt id cmt_info = match Odoc_model.Compat.shape_of_cmt_infos cmt_info with @@ -322,12 +317,18 @@ let read_cmt_infos source_id_opt id cmt_info = numbers, so that adding some content at the end of a file does not modify the anchors for existing anchors. *) in - let loc_to_id, ident_to_id = local_maps source_id occ_infos in - let map = id_map_of_cmt env source_id uid_to_loc loc_to_id in - let source_infos = - postprocess_poses occ_infos ident_to_id loc_to_id map uid_to_loc + let loc_to_id = LocHashtbl.create 10 + and ident_to_id = IdentHashtbl.create 10 in + let occurrences = + process_local_defs source_id occ_infos loc_to_id ident_to_id + in + let () = process_global_defs env source_id loc_to_id in + let uid_to_id = build_uid_to_id source_id uid_to_loc loc_to_id in + let occurrences = + process_occurrences occurrences uid_to_id ident_to_id in - ( Some (shape, map), + let source_infos = add_definitions occurrences loc_to_id in + ( Some (shape, uid_to_id), Some { Odoc_model.Lang.Source_info.id = source_id; diff --git a/test/sources/source.t/run.t b/test/sources/source.t/run.t index ec829b8280..f350b1b810 100644 --- a/test/sources/source.t/run.t +++ b/test/sources/source.t/run.t @@ -272,9 +272,13 @@ Ids generated in the source code: id="L61" id="type-t" id="type-truc" + id="type-truc.constructor-A" + id="type-truc.constructor-B" id="val-xazaz" id="module-Yoyo" id="module-Yoyo.type-bli" + id="module-Yoyo.type-bli.constructor-Aa" + id="module-Yoyo.type-bli.constructor-Bb" id="val-segr" id="val-{x}2" id="val-y" From bedeb0c9b38527416ee1f81c3b49bbb70db67a9e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Wed, 1 Nov 2023 09:20:03 +0100 Subject: [PATCH 4/5] Render source code: tidy up info extraction 2 Signed-off-by: Paul-Elliot --- src/loader/implementation.ml | 73 ++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 46598274a7..6b8bc6c9f6 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -144,11 +144,12 @@ module IdentHashtbl = Hashtbl.Make (struct let hash = Hashtbl.hash end) -(* populate a [loc_to_id] and an [ident_to_id] map with local informations. Also - removes the definitions from the list, since their information has been taken - into account *) -let process_local_defs source_id poses loc_tbl ident_to_id = - List.filter_map +module UidHashtbl = Shape.Uid.Tbl + +(* Adds the local definitions found in traverse infos to the [loc_to_id] and + [ident_to_id] tables. *) +let populate_local_defs source_id poses loc_to_id ident_to_id = + List.iter (function | Typedtree_traverse.Analysis.Definition id, loc -> let name = @@ -159,9 +160,8 @@ let process_local_defs source_id poses loc_tbl ident_to_id = Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name) in IdentHashtbl.add ident_to_id id identifier; - LocHashtbl.add loc_tbl loc identifier; - None - | x -> Some x) + LocHashtbl.add loc_to_id loc identifier + | _ -> ()) poses (* In order to turn an identifier into a source identifier, we need to generate @@ -243,19 +243,18 @@ let anchor_of_identifier id = in anchor_of_identifier [] id |> String.concat "." -(* Adds the global defs from the odoc environment to [loc_to_id] table *) -let process_global_defs env source_id loc_to_id = +(* Adds the global definitions, found in the [uid_to_loc], to the [loc_to_id] + and [uid_to_id] tables. *) +let populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id = let mk_src_id id = let name = Odoc_model.Names.DefName.make_std (anchor_of_identifier id) in (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) :> Odoc_model.Paths.Identifier.SourceLocation.t) in - Ident_env.iter_located_identifier env @@ fun loc id -> - LocHashtbl.add loc_to_id loc (mk_src_id id) - -(* The [uid_to_id] is useful as when resolving a shape, we get the uid. *) -let build_uid_to_id source_id uid_to_loc loc_to_id = - let uid_to_loc_map = Shape.Uid.Tbl.to_map uid_to_loc in + let () = + Ident_env.iter_located_identifier env @@ fun loc id -> + LocHashtbl.add loc_to_id loc (mk_src_id id) + in let mk_src_id () = let name = Odoc_model.Names.DefName.make_std (Printf.sprintf "def_%d" (counter ())) @@ -263,24 +262,25 @@ let build_uid_to_id source_id uid_to_loc loc_to_id = (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) :> Odoc_model.Paths.Identifier.SourceLocation.t) in - Shape.Uid.Map.filter_map + Shape.Uid.Tbl.iter (fun uid loc -> - if loc.Location.loc_ghost then None + if loc.Location.loc_ghost then () else match LocHashtbl.find_opt loc_to_id loc with - | Some id -> Some id + | Some id -> UidHashtbl.add uid_to_id uid id | None -> ( (* In case there is no entry for the location of the uid, we add one. *) match uid with | Item _ -> let id = mk_src_id () in LocHashtbl.add loc_to_id loc id; - Some id - | Compilation_unit _ -> None - | _ -> None)) - uid_to_loc_map + UidHashtbl.add uid_to_id uid id + | Compilation_unit _ -> () + | _ -> ())) + uid_to_loc -(* Turns [Typedtree_traverse] occurrence information into proper source infos *) +(* Extract [Typedtree_traverse] occurrence information and turn them into proper + source infos *) let process_occurrences poses uid_to_id ident_to_id = List.filter_map (function @@ -290,14 +290,14 @@ let process_occurrences poses uid_to_id ident_to_id = Some (Odoc_model.Lang.Source_info.Value anchor, pos_of_loc loc) | None -> None) | Value (DefJmp x), loc -> ( - match Shape.Uid.Map.find_opt x uid_to_id with + match UidHashtbl.find_opt uid_to_id x with | Some id -> Some (Value id, pos_of_loc loc) | None -> None) | Definition _, _ -> None) poses (* Add definition source info from the [loc_to_id] table *) -let add_definitions occurrences loc_to_id = +let add_definitions loc_to_id occurrences = LocHashtbl.fold (fun loc id acc -> (Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc) @@ -310,7 +310,7 @@ let read_cmt_infos source_id_opt id cmt_info = match (source_id_opt, cmt_info.cmt_annots) with | Some source_id, Implementation impl -> let env = Env.of_structure id impl in - let occ_infos = + let traverse_infos = Typedtree_traverse.of_cmt env uid_to_loc impl |> List.rev (* Information are accumulated in a list. We need to have the first info first in the list, to assign anchors with increasing @@ -318,17 +318,18 @@ let read_cmt_infos source_id_opt id cmt_info = not modify the anchors for existing anchors. *) in let loc_to_id = LocHashtbl.create 10 - and ident_to_id = IdentHashtbl.create 10 in - let occurrences = - process_local_defs source_id occ_infos loc_to_id ident_to_id + and ident_to_id = IdentHashtbl.create 10 + and uid_to_id = UidHashtbl.create 10 in + let () = + (* populate [loc_to_id], [ident_to_id] and [uid_to_id] *) + populate_local_defs source_id traverse_infos loc_to_id ident_to_id; + populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id in - let () = process_global_defs env source_id loc_to_id in - let uid_to_id = build_uid_to_id source_id uid_to_loc loc_to_id in - let occurrences = - process_occurrences occurrences uid_to_id ident_to_id + let source_infos = + process_occurrences traverse_infos uid_to_id ident_to_id + |> add_definitions loc_to_id in - let source_infos = add_definitions occurrences loc_to_id in - ( Some (shape, uid_to_id), + ( Some (shape, Shape.Uid.Tbl.to_map uid_to_id), Some { Odoc_model.Lang.Source_info.id = source_id; From 78cfd57b71cb232b77f437e0d98635c1086da6ad Mon Sep 17 00:00:00 2001 From: Jon Ludlam Date: Tue, 7 Nov 2023 14:18:26 +0000 Subject: [PATCH 5/5] Format --- src/loader/ident_env.cppo.mli | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/loader/ident_env.cppo.mli b/src/loader/ident_env.cppo.mli index 316e135f63..2be505ca18 100644 --- a/src/loader/ident_env.cppo.mli +++ b/src/loader/ident_env.cppo.mli @@ -82,5 +82,6 @@ val identifier_of_loc : t -> Location.t -> Paths.Identifier.t option knowing only the location. This is used to generate links to source from the resolution of a shape. *) -val iter_located_identifier : t -> (Location.t -> Paths.Identifier.t -> unit) -> unit +val iter_located_identifier : + t -> (Location.t -> Paths.Identifier.t -> unit) -> unit (** Iter on all stored pair [location]-[identifier]. *)