| author | paulson | 
| Tue, 28 Jun 2005 15:28:30 +0200 | |
| changeset 16589 | 24c32abc8b84 | 
| parent 16444 | 80c8f742c6fc | 
| child 16848 | 1c8a5bb7c688 | 
| permissions | -rw-r--r-- | 
| 6118 | 1  | 
(* Title: Pure/General/name_space.ML  | 
| 5012 | 2  | 
ID: $Id$  | 
3  | 
Author: Markus Wenzel, TU Muenchen  | 
|
4  | 
||
| 16137 | 5  | 
Generic name spaces with declared and hidden entries. Unknown names  | 
| 
16341
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
6  | 
are considered global; no support for absolute addressing.  | 
| 16137 | 7  | 
*)  | 
8  | 
||
9  | 
type bstring = string; (*names to be bound / internalized*)  | 
|
10  | 
type xstring = string; (*externalized names / to be printed*)  | 
|
| 5012 | 11  | 
|
| 16137 | 12  | 
signature BASIC_NAME_SPACE =  | 
13  | 
sig  | 
|
14  | 
val long_names: bool ref  | 
|
15  | 
val short_names: bool ref  | 
|
16  | 
val unique_names: bool ref  | 
|
17  | 
end;  | 
|
| 5012 | 18  | 
|
19  | 
signature NAME_SPACE =  | 
|
20  | 
sig  | 
|
| 16137 | 21  | 
include BASIC_NAME_SPACE  | 
| 9120 | 22  | 
val hidden: string -> string  | 
| 16137 | 23  | 
val separator: string (*single char*)  | 
24  | 
val is_qualified: string -> bool  | 
|
25  | 
val pack: string list -> string  | 
|
| 5012 | 26  | 
val unpack: string -> string list  | 
| 16137 | 27  | 
val append: string -> string -> string  | 
28  | 
val qualified: string -> string -> string  | 
|
| 5012 | 29  | 
val base: string -> string  | 
| 16137 | 30  | 
val drop_base: string -> string  | 
| 11829 | 31  | 
val map_base: (string -> string) -> string -> string  | 
| 16137 | 32  | 
val suffixes_prefixes: 'a list -> 'a list list  | 
| 5012 | 33  | 
val accesses: string -> string list  | 
| 13332 | 34  | 
val accesses': string -> string list  | 
| 5012 | 35  | 
type T  | 
36  | 
val empty: T  | 
|
| 16137 | 37  | 
val valid_accesses: T -> string -> xstring list  | 
38  | 
val intern: T -> xstring -> string  | 
|
39  | 
val extern: T -> string -> xstring  | 
|
40  | 
val hide: bool -> string -> T -> T  | 
|
| 5012 | 41  | 
val merge: T * T -> T  | 
| 16137 | 42  | 
val dest: T -> (string * xstring list) list  | 
43  | 
type naming  | 
|
44  | 
val path_of: naming -> string  | 
|
45  | 
val full: naming -> bstring -> string  | 
|
46  | 
val declare: naming -> string -> T -> T  | 
|
47  | 
val default_naming: naming  | 
|
48  | 
val add_path: string -> naming -> naming  | 
|
49  | 
val qualified_names: naming -> naming  | 
|
50  | 
val no_base_names: naming -> naming  | 
|
51  | 
val custom_accesses: (string list -> string list list) -> naming -> naming  | 
|
52  | 
val set_policy: (string -> bstring -> string) * (string list -> string list list) ->  | 
|
53  | 
naming -> naming  | 
|
| 
16341
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
54  | 
type 'a table = T * 'a Symtab.table  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
55  | 
val empty_table: 'a table  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
56  | 
val extend_table: naming -> 'a table * (bstring * 'a) list -> 'a table  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
57  | 
  val merge_tables: ('a * 'a -> bool) -> 'a table * 'a table -> 'a table
 | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
58  | 
val extern_table: 'a table -> (xstring * 'a) list  | 
| 5012 | 59  | 
end;  | 
60  | 
||
61  | 
structure NameSpace: NAME_SPACE =  | 
|
62  | 
struct  | 
|
63  | 
||
64  | 
(** long identifiers **)  | 
|
65  | 
||
| 16137 | 66  | 
fun hidden name = "??." ^ name;  | 
67  | 
val is_hidden = String.isPrefix "??."  | 
|
68  | 
||
| 5012 | 69  | 
val separator = ".";  | 
| 16137 | 70  | 
val is_qualified = exists_string (equal separator);  | 
| 5012 | 71  | 
|
| 16137 | 72  | 
val pack = space_implode separator;  | 
| 5012 | 73  | 
val unpack = space_explode separator;  | 
74  | 
||
| 16137 | 75  | 
fun append name1 "" = name1  | 
76  | 
| append "" name2 = name2  | 
|
77  | 
| append name1 name2 = name1 ^ separator ^ name2;  | 
|
78  | 
||
79  | 
fun qualified path name =  | 
|
80  | 
if path = "" orelse name = "" then name  | 
|
81  | 
else path ^ separator ^ name;  | 
|
| 11829 | 82  | 
|
| 16137 | 83  | 
fun base "" = ""  | 
84  | 
| base name = List.last (unpack name);  | 
|
| 11829 | 85  | 
|
| 16137 | 86  | 
fun drop_base "" = ""  | 
87  | 
| drop_base name = pack (#1 (split_last (unpack name)));  | 
|
| 5012 | 88  | 
|
| 16137 | 89  | 
fun map_base _ "" = ""  | 
90  | 
| map_base f name =  | 
|
91  | 
let val names = unpack name  | 
|
92  | 
in pack (map_nth_elem (length names - 1) f names) end;  | 
|
93  | 
||
94  | 
fun suffixes_prefixes xs =  | 
|
| 5012 | 95  | 
let  | 
| 16137 | 96  | 
val (qs, b) = split_last xs;  | 
97  | 
val sfxs = Library.suffixes1 xs;  | 
|
98  | 
val pfxs = map (fn x => x @ [b]) (Library.prefixes1 qs);  | 
|
99  | 
in sfxs @ pfxs end;  | 
|
| 5012 | 100  | 
|
| 16137 | 101  | 
val accesses = map pack o suffixes_prefixes o unpack;  | 
| 13332 | 102  | 
val accesses' = map pack o Library.suffixes1 o unpack;  | 
103  | 
||
| 5012 | 104  | 
|
105  | 
||
106  | 
(** name spaces **)  | 
|
107  | 
||
108  | 
(* datatype T *)  | 
|
109  | 
||
110  | 
datatype T =  | 
|
| 8728 | 111  | 
NameSpace of (string list * string list) Symtab.table;  | 
| 5012 | 112  | 
|
113  | 
val empty = NameSpace Symtab.empty;  | 
|
114  | 
||
| 16137 | 115  | 
fun lookup (NameSpace tab) xname =  | 
116  | 
(case Symtab.lookup (tab, xname) of  | 
|
117  | 
NONE => (xname, true)  | 
|
118  | 
| SOME ([], []) => (xname, true)  | 
|
119  | 
| SOME ([name], _) => (name, true)  | 
|
120  | 
| SOME (name :: _, _) => (name, false)  | 
|
121  | 
| SOME ([], name' :: _) => (hidden name', true));  | 
|
| 8728 | 122  | 
|
| 16444 | 123  | 
fun valid_accesses (NameSpace tab) name = Symtab.fold (fn (xname, (names, _)) =>  | 
124  | 
if not (null names) andalso hd names = name then cons xname else I) tab [];  | 
|
| 8728 | 125  | 
|
126  | 
||
| 16137 | 127  | 
(* intern and extern *)  | 
128  | 
||
129  | 
fun intern space xname = #1 (lookup space xname);  | 
|
130  | 
||
131  | 
val long_names = ref false;  | 
|
132  | 
val short_names = ref false;  | 
|
133  | 
val unique_names = ref true;  | 
|
134  | 
||
135  | 
fun extern space name =  | 
|
136  | 
let  | 
|
137  | 
fun valid unique xname =  | 
|
138  | 
let val (name', uniq) = lookup space xname  | 
|
139  | 
in name = name' andalso (uniq orelse (not unique)) end;  | 
|
| 8728 | 140  | 
|
| 16137 | 141  | 
fun ex [] = if valid false name then name else hidden name  | 
142  | 
| ex (nm :: nms) = if valid (! unique_names) nm then nm else ex nms;  | 
|
143  | 
in  | 
|
144  | 
if ! long_names then name  | 
|
145  | 
else if ! short_names then base name  | 
|
146  | 
else ex (accesses' name)  | 
|
147  | 
end;  | 
|
148  | 
||
| 5012 | 149  | 
|
| 16137 | 150  | 
(* basic operations *)  | 
151  | 
||
152  | 
fun map_space f xname (NameSpace tab) =  | 
|
153  | 
NameSpace (Symtab.update ((xname, f (if_none (Symtab.lookup (tab, xname)) ([], []))), tab));  | 
|
154  | 
||
155  | 
fun del (name: string) = remove (op =) name;  | 
|
156  | 
fun add name names = name :: del name names;  | 
|
157  | 
||
158  | 
val del_name = map_space o apfst o del;  | 
|
159  | 
val add_name = map_space o apfst o add;  | 
|
160  | 
val add_name' = map_space o apsnd o add;  | 
|
| 8728 | 161  | 
|
162  | 
||
163  | 
(* hide *)  | 
|
| 5012 | 164  | 
|
| 16137 | 165  | 
fun hide fully name space =  | 
| 8728 | 166  | 
if not (is_qualified name) then  | 
167  | 
    error ("Attempt to hide global name " ^ quote name)
 | 
|
168  | 
else if is_hidden name then  | 
|
169  | 
    error ("Attempt to hide hidden name " ^ quote name)
 | 
|
| 16137 | 170  | 
else  | 
171  | 
let val names = valid_accesses space name in  | 
|
172  | 
space  | 
|
173  | 
|> add_name' name name  | 
|
174  | 
|> fold (del_name name) (if fully then names else names inter_string [base name])  | 
|
175  | 
end;  | 
|
| 5012 | 176  | 
|
177  | 
||
| 16137 | 178  | 
(* merge *)  | 
| 5012 | 179  | 
|
| 16444 | 180  | 
fun merge (NameSpace tab1, space2) = Symtab.fold (fn (xname, (names1, names1')) =>  | 
181  | 
xname |> map_space (fn (names2, names2') =>  | 
|
182  | 
(merge_lists' names2 names1, merge_lists' names2' names1'))) tab1 space2;  | 
|
| 6845 | 183  | 
|
| 5012 | 184  | 
|
185  | 
(* dest *)  | 
|
186  | 
||
| 15531 | 187  | 
fun dest_entry (xname, ([], _)) = NONE  | 
188  | 
| dest_entry (xname, (name :: _, _)) = SOME (name, xname);  | 
|
| 8728 | 189  | 
|
| 5012 | 190  | 
fun dest (NameSpace tab) =  | 
191  | 
map (apsnd (sort (int_ord o pairself size)))  | 
|
| 15570 | 192  | 
(Symtab.dest (Symtab.make_multi (List.mapPartial dest_entry (Symtab.dest tab))));  | 
| 5012 | 193  | 
|
194  | 
||
| 16137 | 195  | 
|
196  | 
(** naming contexts **)  | 
|
197  | 
||
198  | 
(* datatype naming *)  | 
|
199  | 
||
200  | 
datatype naming = Naming of  | 
|
201  | 
string * ((string -> string -> string) * (string list -> string list list));  | 
|
202  | 
||
203  | 
fun path_of (Naming (path, _)) = path;  | 
|
204  | 
||
205  | 
||
206  | 
(* declarations *)  | 
|
207  | 
||
208  | 
fun full (Naming (path, (qualify, _))) = qualify path;  | 
|
209  | 
||
210  | 
fun declare (Naming (_, (_, accs))) name space =  | 
|
211  | 
if is_hidden name then  | 
|
212  | 
    error ("Attempt to declare hidden name " ^ quote name)
 | 
|
213  | 
else  | 
|
214  | 
let val names = unpack name in  | 
|
215  | 
conditional (null names orelse exists (equal "") names) (fn () =>  | 
|
216  | 
        error ("Bad name declaration " ^ quote name));
 | 
|
217  | 
fold (add_name name) (map pack (accs names)) space  | 
|
218  | 
end;  | 
|
219  | 
||
220  | 
||
221  | 
(* manipulate namings *)  | 
|
222  | 
||
223  | 
fun reject_qualified name =  | 
|
224  | 
if is_qualified name then  | 
|
225  | 
    error ("Attempt to declare qualified name " ^ quote name)
 | 
|
226  | 
else name;  | 
|
227  | 
||
228  | 
val default_naming =  | 
|
229  | 
  Naming ("", (fn path => qualified path o reject_qualified, suffixes_prefixes));
 | 
|
230  | 
||
231  | 
fun add_path elems (Naming (path, policy)) =  | 
|
232  | 
  if elems = "//" then Naming ("", (qualified, #2 policy))
 | 
|
233  | 
  else if elems = "/" then Naming ("", policy)
 | 
|
234  | 
else if elems = ".." then Naming (drop_base path, policy)  | 
|
235  | 
else Naming (append path elems, policy);  | 
|
236  | 
||
237  | 
fun qualified_names (Naming (path, (_, accs))) = Naming (path, (qualified, accs));  | 
|
238  | 
||
239  | 
fun no_base_names (Naming (path, (qualify, accs))) =  | 
|
240  | 
Naming (path, (qualify, filter_out (fn [_] => true | _ => false) o accs));  | 
|
241  | 
||
242  | 
fun custom_accesses accs (Naming (path, (qualify, _))) = Naming (path, (qualify, accs));  | 
|
243  | 
fun set_policy policy (Naming (path, _)) = Naming (path, policy);  | 
|
244  | 
||
245  | 
||
| 
16341
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
246  | 
|
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
247  | 
(** name spaces coupled with symbol tables **)  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
248  | 
|
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
249  | 
type 'a table = T * 'a Symtab.table;  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
250  | 
|
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
251  | 
val empty_table = (empty, Symtab.empty);  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
252  | 
|
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
253  | 
fun extend_table naming ((space, tab), bentries) =  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
254  | 
let val entries = map (apfst (full naming)) bentries  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
255  | 
in (fold (declare naming o #1) entries space, Symtab.extend (tab, entries)) end;  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
256  | 
|
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
257  | 
fun merge_tables eq ((space1, tab1), (space2, tab2)) =  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
258  | 
(merge (space1, space2), (Symtab.merge eq (tab1, tab2)));  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
259  | 
|
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
260  | 
fun extern_table (space, tab) =  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
261  | 
Library.sort_wrt #1 (map (apfst (extern space)) (Symtab.dest tab));  | 
| 
 
e573e5167eda
added type NameSpace.table with basic operations;
 
wenzelm 
parents: 
16262 
diff
changeset
 | 
262  | 
|
| 5012 | 263  | 
end;  | 
| 5175 | 264  | 
|
| 16137 | 265  | 
structure BasicNameSpace: BASIC_NAME_SPACE = NameSpace;  | 
266  | 
open BasicNameSpace;  |