src/Pure/General/name_space.ML
author wenzelm
Sun, 18 Mar 2012 13:04:22 +0100
changeset 47876 421760a1efe7
parent 47874 3094745a41ef
child 47892 f35f654f297d
permissions -rw-r--r--
maintain generic context naming in structure Name_Space (NB: empty = default_naming, init = local_naming);
more explicit Context.generic for Name_Space.declare/define and derivatives (NB: naming changed after Proof_Context.init_global);
prefer Context.pretty in low-level operations of structure Sorts/Type (defer full Syntax.init_pretty until error output);
simplified signatures;
     1 (*  Title:      Pure/General/name_space.ML
     2     Author:     Markus Wenzel, TU Muenchen
     3 
     4 Generic name spaces with declared and hidden entries.  Unknown names
     5 are considered global; no support for absolute addressing.
     6 *)
     7 
     8 type xstring = string;    (*external names*)
     9 
    10 signature NAME_SPACE =
    11 sig
    12   val hidden: string -> string
    13   val is_hidden: string -> bool
    14   type T
    15   val empty: string -> T
    16   val kind_of: T -> string
    17   val defined_entry: T -> string -> bool
    18   val the_entry: T -> string ->
    19     {concealed: bool, group: serial option, theory_name: string, pos: Position.T, id: serial}
    20   val entry_ord: T -> string * string -> order
    21   val markup: T -> string -> Markup.T
    22   val is_concealed: T -> string -> bool
    23   val intern: T -> xstring -> string
    24   val names_long_default: bool Unsynchronized.ref
    25   val names_long_raw: Config.raw
    26   val names_long: bool Config.T
    27   val names_short_default: bool Unsynchronized.ref
    28   val names_short_raw: Config.raw
    29   val names_short: bool Config.T
    30   val names_unique_default: bool Unsynchronized.ref
    31   val names_unique_raw: Config.raw
    32   val names_unique: bool Config.T
    33   val extern: Proof.context -> T -> string -> xstring
    34   val hide: bool -> string -> T -> T
    35   val merge: T * T -> T
    36   type naming
    37   val conceal: naming -> naming
    38   val get_group: naming -> serial option
    39   val set_group: serial option -> naming -> naming
    40   val set_theory_name: string -> naming -> naming
    41   val new_group: naming -> naming
    42   val reset_group: naming -> naming
    43   val add_path: string -> naming -> naming
    44   val root_path: naming -> naming
    45   val parent_path: naming -> naming
    46   val mandatory_path: string -> naming -> naming
    47   val qualified_path: bool -> binding -> naming -> naming
    48   val default_naming: naming
    49   val local_naming: naming
    50   val transform_binding: naming -> binding -> binding
    51   val full_name: naming -> binding -> string
    52   val alias: naming -> binding -> string -> T -> T
    53   val naming_of: Context.generic -> naming
    54   val map_naming: (naming -> naming) -> Context.generic -> Context.generic
    55   val declare: Context.generic -> bool -> binding -> T -> string * T
    56   type 'a table = T * 'a Symtab.table
    57   val check: Context.generic -> 'a table -> xstring * Position.T -> string * 'a
    58   val get: 'a table -> string -> 'a
    59   val define: Context.generic -> bool -> binding * 'a -> 'a table -> string * 'a table
    60   val empty_table: string -> 'a table
    61   val merge_tables: 'a table * 'a table -> 'a table
    62   val join_tables: (string -> 'a * 'a -> 'a) (*Symtab.SAME*) ->
    63     'a table * 'a table -> 'a table
    64   val dest_table: Proof.context -> 'a table -> (string * 'a) list
    65   val extern_table: Proof.context -> 'a table -> (xstring * 'a) list
    66 end;
    67 
    68 structure Name_Space: NAME_SPACE =
    69 struct
    70 
    71 
    72 (** name spaces **)
    73 
    74 (* hidden entries *)
    75 
    76 fun hidden name = "??." ^ name;
    77 val is_hidden = String.isPrefix "??.";
    78 
    79 
    80 (* datatype entry *)
    81 
    82 type entry =
    83  {concealed: bool,
    84   group: serial option,
    85   theory_name: string,
    86   pos: Position.T,
    87   id: serial};
    88 
    89 fun entry_markup def kind (name, {pos, id, ...}: entry) =
    90   Markup.properties (Position.entity_properties_of def id pos) (Isabelle_Markup.entity kind name);
    91 
    92 fun print_entry def kind (name, entry) =
    93   quote (Markup.markup (entry_markup def kind (name, entry)) name);
    94 
    95 fun err_dup kind entry1 entry2 =
    96   error ("Duplicate " ^ kind ^ " declaration " ^
    97     print_entry true kind entry1 ^ " vs. " ^ print_entry true kind entry2);
    98 
    99 fun undefined kind name = "Undefined " ^ kind ^ ": " ^ quote name;
   100 
   101 
   102 (* datatype T *)
   103 
   104 datatype T =
   105   Name_Space of
   106    {kind: string,
   107     internals: (string list * string list) Symtab.table,  (*visible, hidden*)
   108     entries: (xstring list * entry) Symtab.table};        (*externals, entry*)
   109 
   110 fun make_name_space (kind, internals, entries) =
   111   Name_Space {kind = kind, internals = internals, entries = entries};
   112 
   113 fun map_name_space f (Name_Space {kind = kind, internals = internals, entries = entries}) =
   114   make_name_space (f (kind, internals, entries));
   115 
   116 fun map_internals f xname = map_name_space (fn (kind, internals, entries) =>
   117   (kind, Symtab.map_default (xname, ([], [])) f internals, entries));
   118 
   119 
   120 fun empty kind = make_name_space (kind, Symtab.empty, Symtab.empty);
   121 
   122 fun kind_of (Name_Space {kind, ...}) = kind;
   123 
   124 fun defined_entry (Name_Space {entries, ...}) = Symtab.defined entries;
   125 
   126 fun the_entry (Name_Space {kind, entries, ...}) name =
   127   (case Symtab.lookup entries name of
   128     NONE => error ("Unknown " ^ kind ^ " " ^ quote name)
   129   | SOME (_, entry) => entry);
   130 
   131 fun entry_ord space = int_ord o pairself (#id o the_entry space);
   132 
   133 fun markup (Name_Space {kind, entries, ...}) name =
   134   (case Symtab.lookup entries name of
   135     NONE => Isabelle_Markup.hilite
   136   | SOME (_, entry) => entry_markup false kind (name, entry));
   137 
   138 fun is_concealed space name = #concealed (the_entry space name);
   139 
   140 
   141 (* name accesses *)
   142 
   143 fun lookup (Name_Space {internals, ...}) xname =
   144   (case Symtab.lookup internals xname of
   145     NONE => (xname, true)
   146   | SOME ([], []) => (xname, true)
   147   | SOME ([name], _) => (name, true)
   148   | SOME (name :: _, _) => (name, false)
   149   | SOME ([], name' :: _) => (hidden name', true));
   150 
   151 fun get_accesses (Name_Space {entries, ...}) name =
   152   (case Symtab.lookup entries name of
   153     NONE => [name]
   154   | SOME (externals, _) => externals);
   155 
   156 fun valid_accesses (Name_Space {internals, ...}) name =
   157   Symtab.fold (fn (xname, (names, _)) =>
   158     if not (null names) andalso hd names = name then cons xname else I) internals [];
   159 
   160 
   161 (* intern and extern *)
   162 
   163 fun intern space xname = #1 (lookup space xname);
   164 
   165 
   166 val names_long_default = Unsynchronized.ref false;
   167 val names_long_raw = Config.declare "names_long" (fn _ => Config.Bool (! names_long_default));
   168 val names_long = Config.bool names_long_raw;
   169 
   170 val names_short_default = Unsynchronized.ref false;
   171 val names_short_raw = Config.declare "names_short" (fn _ => Config.Bool (! names_short_default));
   172 val names_short = Config.bool names_short_raw;
   173 
   174 val names_unique_default = Unsynchronized.ref true;
   175 val names_unique_raw = Config.declare "names_unique" (fn _ => Config.Bool (! names_unique_default));
   176 val names_unique = Config.bool names_unique_raw;
   177 
   178 fun extern ctxt space name =
   179   let
   180     val names_long = Config.get ctxt names_long;
   181     val names_short = Config.get ctxt names_short;
   182     val names_unique = Config.get ctxt names_unique;
   183 
   184     fun valid require_unique xname =
   185       let val (name', is_unique) = lookup space xname
   186       in name = name' andalso (not require_unique orelse is_unique) end;
   187 
   188     fun ext [] = if valid false name then name else hidden name
   189       | ext (nm :: nms) = if valid names_unique nm then nm else ext nms;
   190   in
   191     if names_long then name
   192     else if names_short then Long_Name.base_name name
   193     else ext (get_accesses space name)
   194   end;
   195 
   196 
   197 (* modify internals *)
   198 
   199 val del_name = map_internals o apfst o remove (op =);
   200 fun del_name_extra name =
   201   map_internals (apfst (fn [] => [] | x :: xs => x :: remove (op =) name xs));
   202 val add_name = map_internals o apfst o update (op =);
   203 val add_name' = map_internals o apsnd o update (op =);
   204 
   205 
   206 (* hide *)
   207 
   208 fun hide fully name space =
   209   if not (Long_Name.is_qualified name) then
   210     error ("Attempt to hide global name " ^ quote name)
   211   else if is_hidden name then
   212     error ("Attempt to hide hidden name " ^ quote name)
   213   else
   214     let val names = valid_accesses space name in
   215       space
   216       |> add_name' name name
   217       |> fold (del_name name)
   218         (if fully then names else inter (op =) [Long_Name.base_name name] names)
   219       |> fold (del_name_extra name) (get_accesses space name)
   220     end;
   221 
   222 
   223 (* merge *)
   224 
   225 fun merge
   226   (Name_Space {kind = kind1, internals = internals1, entries = entries1},
   227     Name_Space {kind = kind2, internals = internals2, entries = entries2}) =
   228   let
   229     val kind' =
   230       if kind1 = kind2 then kind1
   231       else error ("Attempt to merge different kinds of name spaces " ^
   232         quote kind1 ^ " vs. " ^ quote kind2);
   233     val internals' = (internals1, internals2) |> Symtab.join
   234       (K (fn ((names1, names1'), (names2, names2')) =>
   235         if pointer_eq (names1, names2) andalso pointer_eq (names1', names2')
   236         then raise Symtab.SAME
   237         else (Library.merge (op =) (names1, names2), Library.merge (op =) (names1', names2'))));
   238     val entries' = (entries1, entries2) |> Symtab.join
   239       (fn name => fn ((_, entry1), (_, entry2)) =>
   240         if #id entry1 = #id entry2 then raise Symtab.SAME
   241         else err_dup kind' (name, entry1) (name, entry2));
   242   in make_name_space (kind', internals', entries') end;
   243 
   244 
   245 
   246 (** naming context **)
   247 
   248 (* datatype naming *)
   249 
   250 datatype naming = Naming of
   251  {conceal: bool,
   252   group: serial option,
   253   theory_name: string,
   254   path: (string * bool) list};
   255 
   256 fun make_naming (conceal, group, theory_name, path) =
   257   Naming {conceal = conceal, group = group, theory_name = theory_name, path = path};
   258 
   259 fun map_naming f (Naming {conceal, group, theory_name, path}) =
   260   make_naming (f (conceal, group, theory_name, path));
   261 
   262 fun map_path f = map_naming (fn (conceal, group, theory_name, path) =>
   263   (conceal, group, theory_name, f path));
   264 
   265 
   266 val conceal = map_naming (fn (_, group, theory_name, path) =>
   267   (true, group, theory_name, path));
   268 
   269 fun set_theory_name theory_name = map_naming (fn (conceal, group, _, path) =>
   270   (conceal, group, theory_name, path));
   271 
   272 
   273 fun get_group (Naming {group, ...}) = group;
   274 
   275 fun set_group group = map_naming (fn (conceal, _, theory_name, path) =>
   276   (conceal, group, theory_name, path));
   277 
   278 fun new_group naming = set_group (SOME (serial ())) naming;
   279 val reset_group = set_group NONE;
   280 
   281 fun add_path elems = map_path (fn path => path @ [(elems, false)]);
   282 val root_path = map_path (fn _ => []);
   283 val parent_path = map_path (perhaps (try (#1 o split_last)));
   284 fun mandatory_path elems = map_path (fn path => path @ [(elems, true)]);
   285 
   286 fun qualified_path mandatory binding = map_path (fn path =>
   287   path @ #2 (Binding.dest (Binding.qualified mandatory "" binding)));
   288 
   289 val default_naming = make_naming (false, NONE, "", []);
   290 val local_naming = default_naming |> add_path "local";
   291 
   292 
   293 (* full name *)
   294 
   295 fun err_bad binding = error (Binding.bad binding);
   296 
   297 fun transform_binding (Naming {conceal = true, ...}) = Binding.conceal
   298   | transform_binding _ = I;
   299 
   300 fun name_spec (naming as Naming {path, ...}) raw_binding =
   301   let
   302     val binding = transform_binding naming raw_binding;
   303     val (concealed, prefix, name) = Binding.dest binding;
   304     val _ = Long_Name.is_qualified name andalso err_bad binding;
   305 
   306     val spec1 = maps (fn (a, b) => map (rpair b) (Long_Name.explode a)) (path @ prefix);
   307     val spec2 = if name = "" then [] else [(name, true)];
   308     val spec = spec1 @ spec2;
   309     val _ =
   310       exists (fn (a, _) => a = "" orelse a = "??" orelse exists_string (fn s => s = "\"") a) spec
   311       andalso err_bad binding;
   312   in (concealed, if null spec2 then [] else spec) end;
   313 
   314 fun full_name naming =
   315   name_spec naming #> #2 #> map #1 #> Long_Name.implode;
   316 
   317 
   318 (* accesses *)
   319 
   320 fun mandatory xs = map_filter (fn (x, true) => SOME x | _ => NONE) xs;
   321 
   322 fun mandatory_prefixes xs = mandatory xs :: mandatory_prefixes1 xs
   323 and mandatory_prefixes1 [] = []
   324   | mandatory_prefixes1 ((x, true) :: xs) = map (cons x) (mandatory_prefixes1 xs)
   325   | mandatory_prefixes1 ((x, false) :: xs) = map (cons x) (mandatory_prefixes xs);
   326 
   327 fun mandatory_suffixes xs = map rev (mandatory_prefixes (rev xs));
   328 
   329 fun accesses naming binding =
   330   let
   331     val spec = #2 (name_spec naming binding);
   332     val sfxs = mandatory_suffixes spec;
   333     val pfxs = mandatory_prefixes spec;
   334   in pairself (map Long_Name.implode) (sfxs @ pfxs, sfxs) end;
   335 
   336 
   337 (* alias *)
   338 
   339 fun alias naming binding name space =
   340   let
   341     val (accs, accs') = accesses naming binding;
   342     val space' = space
   343       |> fold (add_name name) accs
   344       |> map_name_space (fn (kind, internals, entries) =>
   345         let
   346           val _ = Symtab.defined entries name orelse error (undefined kind name);
   347           val entries' = entries
   348             |> Symtab.map_entry name (fn (externals, entry) =>
   349               (Library.merge (op =) (externals, accs'), entry))
   350         in (kind, internals, entries') end);
   351   in space' end;
   352 
   353 
   354 
   355 (** context naming **)
   356 
   357 structure Data_Args =
   358 struct
   359   type T = naming;
   360   val empty = default_naming;
   361   fun extend _ = default_naming;
   362   fun merge _ = default_naming;
   363   fun init _ = local_naming;
   364 end;
   365 
   366 structure Global_Naming = Theory_Data(Data_Args);
   367 structure Local_Naming = Proof_Data(Data_Args);
   368 
   369 fun naming_of (Context.Theory thy) = Global_Naming.get thy
   370   | naming_of (Context.Proof ctxt) = Local_Naming.get ctxt;
   371 
   372 fun map_naming f (Context.Theory thy) = Context.Theory (Global_Naming.map f thy)
   373   | map_naming f (Context.Proof ctxt) = Context.Proof (Local_Naming.map f ctxt);
   374 
   375 
   376 
   377 (** entry definition **)
   378 
   379 (* declaration *)
   380 
   381 fun new_entry strict (name, (externals, entry)) =
   382   map_name_space (fn (kind, internals, entries) =>
   383     let
   384       val entries' =
   385         (if strict then Symtab.update_new else Symtab.update) (name, (externals, entry)) entries
   386           handle Symtab.DUP dup =>
   387             err_dup kind (dup, #2 (the (Symtab.lookup entries dup))) (name, entry);
   388     in (kind, internals, entries') end);
   389 
   390 fun declare context strict binding space =
   391   let
   392     val naming = naming_of context;
   393     val Naming {group, theory_name, ...} = naming;
   394     val (concealed, spec) = name_spec naming binding;
   395     val (accs, accs') = accesses naming binding;
   396 
   397     val name = Long_Name.implode (map fst spec);
   398     val _ = name = "" andalso err_bad binding;
   399 
   400     val pos = Position.default (Binding.pos_of binding);
   401     val entry =
   402      {concealed = concealed,
   403       group = group,
   404       theory_name = theory_name,
   405       pos = pos,
   406       id = serial ()};
   407     val space' = space
   408       |> fold (add_name name) accs
   409       |> new_entry strict (name, (accs', entry));
   410     val _ =
   411       Context_Position.report_generic context pos
   412         (entry_markup true (kind_of space) (name, entry));
   413   in (name, space') end;
   414 
   415 
   416 (* definition in symbol table *)
   417 
   418 type 'a table = T * 'a Symtab.table;
   419 
   420 fun check context (space, tab) (xname, pos) =
   421   let val name = intern space xname in
   422     (case Symtab.lookup tab name of
   423       SOME x => (Context_Position.report_generic context pos (markup space name); (name, x))
   424     | NONE => error (undefined (kind_of space) name ^ Position.str_of pos))
   425   end;
   426 
   427 fun get (space, tab) name =
   428   (case Symtab.lookup tab name of
   429     SOME x => x
   430   | NONE => error (undefined (kind_of space) name));
   431 
   432 fun define context strict (binding, x) (space, tab) =
   433   let val (name, space') = declare context strict binding space
   434   in (name, (space', Symtab.update (name, x) tab)) end;
   435 
   436 fun empty_table kind = (empty kind, Symtab.empty);
   437 
   438 fun merge_tables ((space1, tab1), (space2, tab2)) =
   439   (merge (space1, space2), Symtab.merge (K true) (tab1, tab2));
   440 
   441 fun join_tables f ((space1, tab1), (space2, tab2)) =
   442   (merge (space1, space2), Symtab.join f (tab1, tab2));
   443 
   444 fun ext_table ctxt (space, tab) =
   445   Symtab.fold (fn (name, x) => cons ((name, extern ctxt space name), x)) tab []
   446   |> Library.sort_wrt (#2 o #1);
   447 
   448 fun dest_table ctxt tab = map (apfst #1) (ext_table ctxt tab);
   449 fun extern_table ctxt tab = map (apfst #2) (ext_table ctxt tab);
   450 
   451 end;
   452