summaryrefslogtreecommitdiff
path: root/src/Names.ml
blob: 1308eccc06b0e279d8f9f4ba259835e2a2b8f437 (plain)
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
open Identifiers

module Disambiguator = IdGen ()

(** See the comments for [Name] *)
type path_elem = Ident of string | Disambiguator of Disambiguator.id
[@@deriving show, ord]

type name = path_elem list [@@deriving show, ord]
(** A name such as: `std::collections::vector` (which would be represented as
    [[Ident "std"; Ident "collections"; Ident "vector"]])


    A name really is a list of strings. However, we sometimes need to
    introduce unique indices to disambiguate. This mostly happens because
    of "impl" blocks in Rust:
      ```
      impl<T> List<T> {
        ...
      }
      ```
   
    A type in Rust can have several "impl" blocks, and those blocks can
    contain items with similar names. For this reason, we need to disambiguate
    them with unique indices. Rustc calls those "disambiguators". In rustc, this
    gives names like this:
    - `betree_main::betree::NodeIdCounter{impl#0}::new`
    - note that impl blocks can be nested, and macros sometimes generate
      weird names (which require disambiguation):
      `betree_main::betree_utils::_#1::{impl#0}::deserialize::{impl#0}`
   
    Finally, the paths used by rustc are a lot more precise and explicit than
    those we expose in LLBC: for instance, every identifier belongs to a specific
    namespace (value namespace, type namespace, etc.), and is coupled with a
    disambiguator.
   
    On our side, we want to stay high-level and simple: we use string identifiers
    as much as possible, insert disambiguators only when necessary (whenever
    we find an "impl" block, typically) and check that the disambiguator is useless
    in the other situations (i.e., the disambiguator is always equal to 0).
   
    Moreover, the items are uniquely disambiguated by their (integer) ids
    (`TypeDeclId.id`, etc.), and when extracting the code we have to deal with
    name clashes anyway. Still, we might want to be more precise in the future.
   
    Also note that the first path element in the name is always the crate name.
 *)

let to_name (ls : string list) : name = List.map (fun s -> Ident s) ls

type module_name = name [@@deriving show, ord]

type type_name = name [@@deriving show, ord]

type fun_name = name [@@deriving show, ord]

(** Filter the disambiguators equal to 0 in a name *)
let filter_disambiguators_zero (n : name) : name =
  let pred (pe : path_elem) : bool =
    match pe with Ident _ -> true | Disambiguator d -> d <> Disambiguator.zero
  in
  List.filter pred n

(** Filter the disambiguators in a name *)
let filter_disambiguators (n : name) : name =
  let pred (pe : path_elem) : bool =
    match pe with Ident _ -> true | Disambiguator _ -> false
  in
  List.filter pred n

let as_ident (pe : path_elem) : string =
  match pe with
  | Ident s -> s
  | Disambiguator _ -> raise (Failure "Improper variant")

let path_elem_to_string (pe : path_elem) : string =
  match pe with
  | Ident s -> s
  | Disambiguator d -> "{" ^ Disambiguator.to_string d ^ "}"

let name_to_string (name : name) : string =
  String.concat "::" (List.map path_elem_to_string name)