Skip to content

Commit f0efca1

Browse files
committed
Add name mangling module for new scheme.
1 parent 60de9a5 commit f0efca1

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
type path_item =
2+
| Module of string
3+
| AnonymousFunction of int * int * string option
4+
| NamedFunction of string
5+
| AnonymousModule of int * int * string option
6+
7+
(* Create a path representing Foo.Bar.baz
8+
as
9+
let n = [Module "Foo"; Module "Bar"; NamedFunction "baz"]
10+
*)
11+
type path = path_item list
12+
13+
let is_out_char = function
14+
| '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z' | '_' -> true
15+
| _ -> false
16+
17+
let upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
18+
let hex = "0123456789abcdef"
19+
20+
(** Encode a length as base-26 number using [[A-Z]] *)
21+
let rec encode_len buf len =
22+
let r = len mod 26 and q = len / 26 in
23+
if q > 0 then encode_len buf q;
24+
Buffer.add_char buf upper.[r]
25+
26+
let encode_char buf c =
27+
let c = Char.code c in
28+
let h = (c lsr 4) land 0xf and l = c land 0xf in
29+
Buffer.add_char buf (hex.[h]);
30+
Buffer.add_char buf (hex.[l])
31+
32+
type encode_state = Raw | Enc
33+
34+
let encode (sym : string) =
35+
let raw = Buffer.create (String.length sym)
36+
and enc = Buffer.create (2 * String.length sym)
37+
and ins_pos = ref 0 in
38+
let rec aux i = function
39+
| _ when i >= String.length sym ->
40+
Printf.sprintf "%s_%s" (Buffer.contents enc) (Buffer.contents raw)
41+
| Raw ->
42+
if is_out_char sym.[i] then (
43+
Buffer.add_char raw sym.[i];
44+
incr ins_pos;
45+
aux (i + 1) Raw)
46+
else (
47+
encode_len enc !ins_pos;
48+
encode_char enc sym.[i];
49+
aux (i + 1) Enc)
50+
| Enc ->
51+
if is_out_char sym.[i] then (
52+
Buffer.add_char raw sym.[i];
53+
ins_pos := 1;
54+
aux (i + 1) Raw)
55+
else (
56+
encode_char enc sym.[i];
57+
aux (i + 1) Enc)
58+
in
59+
aux 0 Raw
60+
61+
let mangle_chunk = function
62+
| Module sym ->
63+
let pref, rsym =
64+
if String.for_all is_out_char sym then ("", sym) else ("u", encode sym)
65+
in
66+
Printf.sprintf "%s%d%s" pref (String.length rsym) rsym
67+
| NamedFunction sym ->
68+
let pref, rsym =
69+
if String.for_all is_out_char sym then ("", sym) else ("u", encode sym)
70+
in
71+
Printf.sprintf "%s%d%s" pref (String.length rsym) rsym
72+
| AnonymousFunction (line, col, file_opt) ->
73+
let file_name = Option.value ~default:"" file_opt in
74+
let ts = Printf.sprintf "%s_%d_%d" file_name line col in
75+
Printf.sprintf "%d%s" (String.length ts) ts
76+
| AnonymousModule (line, col, file_opt) ->
77+
let file_name = Option.value ~default:"" file_opt in
78+
let ts = Printf.sprintf "%s_%d_%d" file_name line col in
79+
Printf.sprintf "%d%s" (String.length ts) ts
80+
81+
let mangle_path (path : path) : string =
82+
let b = Buffer.create 10 in
83+
List.iter (fun s -> Buffer.add_string b (mangle_chunk s)) path;
84+
Buffer.contents b
85+
86+
let mangle_path_with_prefix (path : path) : string =
87+
let b = Buffer.create 10 in
88+
Buffer.add_string b "_O";
89+
List.iter (fun s -> Buffer.add_string b (mangle_chunk s)) path;
90+
Buffer.contents b
91+
92+
let mangle_comp_unit (cu : Compilation_unit.t) : string =
93+
let for_pack_prefix, name, flattened_instance_args = Compilation_unit.flatten cu in
94+
let name = Compilation_unit.Name.to_string name in
95+
if not (Compilation_unit.Prefix.is_empty for_pack_prefix)
96+
then begin
97+
assert (flattened_instance_args = []);
98+
let pack_names =
99+
Compilation_unit.Prefix.to_list for_pack_prefix
100+
|> List.map (fun x -> Module (Compilation_unit.Name.to_string x))
101+
in
102+
mangle_path_with_prefix (Module name :: (pack_names @ [Module name]))
103+
end else begin
104+
(* TODO For Parameterised libraries??? *)
105+
let instance_separator = "____" in
106+
let instance_separator_depth_char = '_' in
107+
let arg_segments =
108+
List.map
109+
(fun (depth, _param, value) ->
110+
let extra_separators =
111+
String.make depth instance_separator_depth_char
112+
in
113+
let value = value |> Compilation_unit.Name.to_string in
114+
Module (String.concat "" [instance_separator; extra_separators; value]))
115+
flattened_instance_args
116+
in
117+
mangle_path ((Module name) :: arg_segments)
118+
end
119+
120+
let mangle_ident (cu : Compilation_unit.t) (path : path) =
121+
let b = Buffer.create 10 in
122+
Buffer.add_string b (mangle_comp_unit cu);
123+
Buffer.add_string b (mangle_path path);
124+
Buffer.contents b
125+

0 commit comments

Comments
 (0)