author | wenzelm |
Thu, 22 Jul 2010 14:59:27 +0200 | |
changeset 37906 | 4195727a1f6c |
parent 34307 | 9074aa7d06e0 |
child 40627 | becf5d5187cc |
permissions | -rw-r--r-- |
20089 | 1 |
(* Title: Pure/name.ML |
2 |
Author: Makarius |
|
3 |
||
28965 | 4 |
Names of basic logical entities (variables etc.). |
20089 | 5 |
*) |
6 |
||
7 |
signature NAME = |
|
8 |
sig |
|
24849 | 9 |
val uu: string |
10 |
val aT: string |
|
30584
7e839627b9e7
Name.of_binding: proper full_name (with checks) before projecting base name;
wenzelm
parents:
29006
diff
changeset
|
11 |
val of_binding: binding -> string |
20089 | 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 |
|
20 |
type context |
|
21 |
val context: context |
|
20158 | 22 |
val make_context: string list -> context |
20089 | 23 |
val declare: string -> context -> context |
20158 | 24 |
val is_declared: context -> string -> bool |
20089 | 25 |
val invents: context -> string -> int -> string list |
20192
956cd30ef3be
renamed Name.give_names to Name.names and moved Name.alphanum to Symbol.alphanum
haftmann
parents:
20174
diff
changeset
|
26 |
val names: context -> string -> 'a list -> (string * 'a) list |
20089 | 27 |
val invent_list: string list -> string -> int -> string list |
28 |
val variants: string list -> context -> string list * context |
|
29 |
val variant_list: string list -> string list -> string list |
|
30 |
val variant: string list -> string -> string |
|
31035 | 31 |
val desymbolize: bool -> string -> string |
20089 | 32 |
end; |
33 |
||
34 |
structure Name: NAME = |
|
35 |
struct |
|
36 |
||
24849 | 37 |
(** common defaults **) |
38 |
||
39 |
val uu = "uu"; |
|
40 |
val aT = "'a"; |
|
41 |
||
42 |
||
20089 | 43 |
|
44 |
(** special variable names **) |
|
45 |
||
30584
7e839627b9e7
Name.of_binding: proper full_name (with checks) before projecting base name;
wenzelm
parents:
29006
diff
changeset
|
46 |
(* checked binding *) |
7e839627b9e7
Name.of_binding: proper full_name (with checks) before projecting base name;
wenzelm
parents:
29006
diff
changeset
|
47 |
|
33095
bbd52d2f8696
renamed NameSpace to Name_Space -- also to emphasize its subtle change in semantics;
wenzelm
parents:
31035
diff
changeset
|
48 |
val of_binding = Long_Name.base_name o Name_Space.full_name Name_Space.default_naming; |
30584
7e839627b9e7
Name.of_binding: proper full_name (with checks) before projecting base name;
wenzelm
parents:
29006
diff
changeset
|
49 |
|
7e839627b9e7
Name.of_binding: proper full_name (with checks) before projecting base name;
wenzelm
parents:
29006
diff
changeset
|
50 |
|
20089 | 51 |
(* encoded bounds *) |
52 |
||
53 |
(*names for numbered variables -- |
|
54 |
preserves order wrt. int_ord vs. string_ord, avoids allocating new strings*) |
|
55 |
||
56 |
val small_int = Vector.tabulate (1000, fn i => |
|
57 |
let val leading = if i < 10 then "00" else if i < 100 then "0" else "" |
|
58 |
in ":" ^ leading ^ string_of_int i end); |
|
59 |
||
60 |
fun bound n = |
|
61 |
if n < 1000 then Vector.sub (small_int, n) |
|
62 |
else ":" ^ bound (n div 1000) ^ Vector.sub (small_int, n mod 1000); |
|
63 |
||
64 |
val is_bound = String.isPrefix ":"; |
|
65 |
||
66 |
||
67 |
(* internal names *) |
|
68 |
||
69 |
val internal = suffix "_"; |
|
70 |
val dest_internal = unsuffix "_"; |
|
71 |
||
72 |
val skolem = suffix "__"; |
|
73 |
val dest_skolem = unsuffix "__"; |
|
74 |
||
20099 | 75 |
fun clean_index (x, i) = |
76 |
(case try dest_internal x of |
|
77 |
NONE => (x, i) |
|
78 |
| SOME x' => clean_index (x', i + 1)); |
|
20089 | 79 |
|
80 |
fun clean x = #1 (clean_index (x, 0)); |
|
81 |
||
82 |
||
83 |
||
84 |
(** generating fresh names **) |
|
85 |
||
86 |
(* context *) |
|
87 |
||
88 |
datatype context = |
|
89 |
Context of string option Symtab.table; (*declared names with latest renaming*) |
|
90 |
||
20099 | 91 |
fun declare x (Context tab) = |
92 |
Context (Symtab.default (clean x, NONE) tab); |
|
93 |
||
94 |
fun declare_renaming (x, x') (Context tab) = |
|
95 |
Context (Symtab.update (clean x, SOME (clean x')) tab); |
|
20089 | 96 |
|
20158 | 97 |
fun is_declared (Context tab) = Symtab.defined tab; |
20089 | 98 |
fun declared (Context tab) = Symtab.lookup tab; |
99 |
||
20121 | 100 |
val context = Context Symtab.empty |> fold declare ["", "'"]; |
20089 | 101 |
fun make_context used = fold declare used context; |
102 |
||
103 |
||
104 |
(* invents *) |
|
105 |
||
106 |
fun invents ctxt = |
|
107 |
let |
|
108 |
fun invs _ 0 = [] |
|
109 |
| invs x n = |
|
110 |
let val x' = Symbol.bump_string x in |
|
20158 | 111 |
if is_declared ctxt x then invs x' n |
20089 | 112 |
else x :: invs x' (n - 1) |
113 |
end; |
|
20099 | 114 |
in invs o clean end; |
20089 | 115 |
|
20198 | 116 |
fun names ctxt x xs = invents ctxt x (length xs) ~~ xs; |
117 |
||
20089 | 118 |
val invent_list = invents o make_context; |
119 |
||
120 |
||
121 |
(* variants *) |
|
122 |
||
123 |
(*makes a variant of a name distinct from already used names in a |
|
124 |
context; preserves a suffix of underscores "_"*) |
|
125 |
val variants = fold_map (fn name => fn ctxt => |
|
126 |
let |
|
127 |
fun vary x = |
|
128 |
(case declared ctxt x of |
|
129 |
NONE => x |
|
130 |
| SOME x' => vary (Symbol.bump_string (the_default x x'))); |
|
131 |
||
20121 | 132 |
val (x, n) = clean_index (name, 0); |
20089 | 133 |
val (x', ctxt') = |
20158 | 134 |
if not (is_declared ctxt x) then (x, declare x ctxt) |
20089 | 135 |
else |
136 |
let |
|
137 |
val x0 = Symbol.bump_init x; |
|
138 |
val x' = vary x0; |
|
139 |
val ctxt' = ctxt |
|
21565 | 140 |
|> x0 <> x' ? declare_renaming (x0, x') |
20089 | 141 |
|> declare x'; |
142 |
in (x', ctxt') end; |
|
143 |
in (x' ^ replicate_string n "_", ctxt') end); |
|
144 |
||
145 |
fun variant_list used names = #1 (make_context used |> variants names); |
|
146 |
fun variant used = singleton (variant_list used); |
|
147 |
||
31013 | 148 |
|
31035 | 149 |
(* names conforming to typical requirements of identifiers in the world outside *) |
31013 | 150 |
|
31035 | 151 |
fun desymbolize upper "" = if upper then "X" else "x" |
152 |
| desymbolize upper s = |
|
31013 | 153 |
let |
31035 | 154 |
val xs as (x :: _) = Symbol.explode s; |
33547 | 155 |
val ys = |
156 |
if Symbol.is_ascii_letter x orelse Symbol.is_symbolic x then xs |
|
31013 | 157 |
else "x" :: xs; |
158 |
fun is_valid x = |
|
34307 | 159 |
Symbol.is_ascii_letter x orelse Symbol.is_ascii_digit x; |
31013 | 160 |
fun sep [] = [] |
161 |
| sep (xs as "_" :: _) = xs |
|
162 |
| sep xs = "_" :: xs; |
|
31035 | 163 |
fun desep ("_" :: xs) = xs |
164 |
| desep xs = xs; |
|
33547 | 165 |
fun desymb x xs = |
166 |
if is_valid x then x :: xs |
|
31013 | 167 |
else |
33547 | 168 |
(case Symbol.decode x of |
169 |
Symbol.Sym name => "_" :: explode name @ sep xs |
|
170 |
| _ => sep xs); |
|
171 |
fun upper_lower cs = |
|
172 |
if upper then nth_map 0 Symbol.to_ascii_upper cs |
|
173 |
else |
|
174 |
(if forall Symbol.is_ascii_upper cs then map else nth_map 0) |
|
175 |
Symbol.to_ascii_lower cs; |
|
31035 | 176 |
in fold_rev desymb ys [] |> desep |> upper_lower |> implode end; |
31013 | 177 |
|
20089 | 178 |
end; |