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