4 Names of basic logical entities (variables etc.).
12 val bound: int -> string
13 val is_bound: string -> bool
14 val internal: string -> string
15 val dest_internal: string -> string
16 val skolem: string -> string
17 val dest_skolem: string -> string
18 val clean_index: string * int -> string * int
19 val clean: string -> string
22 val make_context: string list -> context
23 val declare: string -> context -> context
24 val is_declared: context -> string -> bool
25 val invent: context -> string -> int -> string list
26 val invent_names: context -> string -> 'a list -> (string * 'a) list
27 val invent_list: string list -> string -> int -> string list
28 val variant: string -> context -> string * context
29 val variant_list: string list -> string list -> string list
30 val desymbolize: bool -> string -> string
33 structure Name: NAME =
36 (** common defaults **)
44 (** special variable names **)
48 (*names for numbered variables --
49 preserves order wrt. int_ord vs. string_ord, avoids allocating new strings*)
51 val small_int = Vector.tabulate (1000, fn i =>
52 let val leading = if i < 10 then "00" else if i < 100 then "0" else ""
53 in ":" ^ leading ^ string_of_int i end);
56 if n < 1000 then Vector.sub (small_int, n)
57 else ":" ^ bound (n div 1000) ^ Vector.sub (small_int, n mod 1000);
59 val is_bound = String.isPrefix ":";
64 val internal = suffix "_";
65 val dest_internal = unsuffix "_";
67 val skolem = suffix "__";
68 val dest_skolem = unsuffix "__";
70 fun clean_index (x, i) =
71 (case try dest_internal x of
73 | SOME x' => clean_index (x', i + 1));
75 fun clean x = #1 (clean_index (x, 0));
79 (** generating fresh names **)
84 Context of string option Symtab.table; (*declared names with latest renaming*)
86 fun declare x (Context tab) =
87 Context (Symtab.default (clean x, NONE) tab);
89 fun declare_renaming (x, x') (Context tab) =
90 Context (Symtab.update (clean x, SOME (clean x')) tab);
92 fun is_declared (Context tab) = Symtab.defined tab;
93 fun declared (Context tab) = Symtab.lookup tab;
95 val context = Context Symtab.empty |> fold declare ["", "'"];
96 fun make_context used = fold declare used context;
105 let val x' = Symbol.bump_string x
106 in if is_declared ctxt x then invs x' n else x :: invs x' (n - 1) end;
109 fun invent_names ctxt x xs = invent ctxt x (length xs) ~~ xs;
111 val invent_list = invent o make_context;
116 (*makes a variant of a name distinct from already used names in a
117 context; preserves a suffix of underscores "_"*)
118 fun variant name ctxt =
121 (case declared ctxt x of
123 | SOME x' => vary (Symbol.bump_string (the_default x x')));
125 val (x, n) = clean_index (name, 0);
127 if not (is_declared ctxt x) then (x, declare x ctxt)
130 val x0 = Symbol.bump_init x;
133 |> x0 <> x' ? declare_renaming (x0, x')
136 in (x' ^ replicate_string n "_", ctxt') end;
138 fun variant_list used names = #1 (make_context used |> fold_map variant names);
141 (* names conforming to typical requirements of identifiers in the world outside *)
143 fun desymbolize upper "" = if upper then "X" else "x"
144 | desymbolize upper s =
146 val xs as (x :: _) = Symbol.explode s;
148 if Symbol.is_ascii_letter x orelse Symbol.is_symbolic x then xs
151 Symbol.is_ascii_letter x orelse Symbol.is_ascii_digit x;
153 | sep (xs as "_" :: _) = xs
154 | sep xs = "_" :: xs;
155 fun desep ("_" :: xs) = xs
158 if is_valid x then x :: xs
160 (case Symbol.decode x of
161 Symbol.Sym name => "_" :: raw_explode name @ sep xs
164 if upper then nth_map 0 Symbol.to_ascii_upper cs
166 (if forall Symbol.is_ascii_upper cs then map else nth_map 0)
167 Symbol.to_ascii_lower cs;
168 in fold_rev desymb ys [] |> desep |> upper_lower |> implode end;