src/Pure/ML/ml_env.ML
author wenzelm
Wed Apr 06 16:33:33 2016 +0200 (2016-04-06)
changeset 62889 99c7f31615c2
parent 62876 507c90523113
child 62902 3c0f53eae166
permissions -rw-r--r--
clarified modules;
tuned signature;
wenzelm@31325
     1
(*  Title:      Pure/ML/ml_env.ML
wenzelm@31325
     2
    Author:     Makarius
wenzelm@31325
     3
wenzelm@56275
     4
Toplevel environment for Standard ML and Isabelle/ML within the
wenzelm@56275
     5
implicit context.
wenzelm@31325
     6
*)
wenzelm@31325
     7
wenzelm@31325
     8
signature ML_ENV =
wenzelm@31325
     9
sig
wenzelm@31325
    10
  val inherit: Context.generic -> Context.generic -> Context.generic
wenzelm@59127
    11
  val forget_structure: string -> Context.generic -> Context.generic
wenzelm@60746
    12
  val add_breakpoint: serial * (bool Unsynchronized.ref * Position.T) ->
wenzelm@60746
    13
    Context.generic -> Context.generic
wenzelm@60746
    14
  val get_breakpoint: Context.generic -> serial -> (bool Unsynchronized.ref * Position.T) option
wenzelm@62873
    15
  val init_bootstrap: Context.generic -> Context.generic
wenzelm@60858
    16
  val add_name_space: {SML: bool} -> ML_Name_Space.T -> Context.generic -> Context.generic
wenzelm@62495
    17
  val make_name_space: {SML: bool, exchange: bool} -> ML_Name_Space.T
wenzelm@62495
    18
  val context: ML_Compiler0.context
wenzelm@62495
    19
  val name_space: ML_Name_Space.T
wenzelm@36163
    20
  val check_functor: string -> unit
wenzelm@31325
    21
end
wenzelm@31325
    22
wenzelm@31325
    23
structure ML_Env: ML_ENV =
wenzelm@31325
    24
struct
wenzelm@31325
    25
wenzelm@31328
    26
(* context data *)
wenzelm@31328
    27
wenzelm@56275
    28
type tables =
wenzelm@56275
    29
  ML_Name_Space.valueVal Symtab.table *
wenzelm@56275
    30
  ML_Name_Space.typeVal Symtab.table *
wenzelm@56275
    31
  ML_Name_Space.fixityVal Symtab.table *
wenzelm@56275
    32
  ML_Name_Space.structureVal Symtab.table *
wenzelm@56275
    33
  ML_Name_Space.signatureVal Symtab.table *
wenzelm@56275
    34
  ML_Name_Space.functorVal Symtab.table;
wenzelm@56275
    35
wenzelm@56275
    36
fun merge_tables
wenzelm@56275
    37
  ((val1, type1, fixity1, structure1, signature1, functor1),
wenzelm@56275
    38
   (val2, type2, fixity2, structure2, signature2, functor2)) : tables =
wenzelm@56275
    39
  (Symtab.merge (K true) (val1, val2),
wenzelm@56275
    40
   Symtab.merge (K true) (type1, type2),
wenzelm@56275
    41
   Symtab.merge (K true) (fixity1, fixity2),
wenzelm@56275
    42
   Symtab.merge (K true) (structure1, structure2),
wenzelm@56275
    43
   Symtab.merge (K true) (signature1, signature2),
wenzelm@56275
    44
   Symtab.merge (K true) (functor1, functor2));
wenzelm@56275
    45
wenzelm@60746
    46
type data =
wenzelm@60746
    47
 {bootstrap: bool,
wenzelm@60746
    48
  tables: tables,
wenzelm@60746
    49
  sml_tables: tables,
wenzelm@60746
    50
  breakpoints: (bool Unsynchronized.ref * Position.T) Inttab.table};
wenzelm@56275
    51
wenzelm@60746
    52
fun make_data (bootstrap, tables, sml_tables, breakpoints) : data =
wenzelm@60746
    53
  {bootstrap = bootstrap, tables = tables, sml_tables = sml_tables, breakpoints = breakpoints};
wenzelm@56275
    54
wenzelm@33519
    55
structure Env = Generic_Data
wenzelm@31325
    56
(
wenzelm@56275
    57
  type T = data
wenzelm@56275
    58
  val empty =
wenzelm@56275
    59
    make_data (true,
wenzelm@56275
    60
      (Symtab.empty, Symtab.empty, Symtab.empty, Symtab.empty, Symtab.empty, Symtab.empty),
wenzelm@62839
    61
      (Symtab.make ML_Name_Space.sml_val,
wenzelm@62839
    62
       Symtab.make ML_Name_Space.sml_type,
wenzelm@62839
    63
       Symtab.make ML_Name_Space.sml_fixity,
wenzelm@62839
    64
       Symtab.make ML_Name_Space.sml_structure,
wenzelm@62839
    65
       Symtab.make ML_Name_Space.sml_signature,
wenzelm@62839
    66
       Symtab.make ML_Name_Space.sml_functor),
wenzelm@60746
    67
      Inttab.empty);
wenzelm@60746
    68
  fun extend (data : T) = make_data (false, #tables data, #sml_tables data, #breakpoints data);
wenzelm@56275
    69
  fun merge (data : T * T) =
wenzelm@56275
    70
    make_data (false,
wenzelm@59058
    71
      merge_tables (apply2 #tables data),
wenzelm@60746
    72
      merge_tables (apply2 #sml_tables data),
wenzelm@60746
    73
      Inttab.merge (K true) (apply2 #breakpoints data));
wenzelm@31325
    74
);
wenzelm@31325
    75
wenzelm@31325
    76
val inherit = Env.put o Env.get;
wenzelm@31325
    77
wenzelm@59127
    78
fun forget_structure name =
wenzelm@60746
    79
  Env.map (fn {bootstrap, tables, sml_tables, breakpoints} =>
wenzelm@59127
    80
    let
wenzelm@62657
    81
      val _ = if bootstrap then ML_Name_Space.forget_structure name else ();
wenzelm@59127
    82
      val tables' =
wenzelm@59127
    83
        (#1 tables, #2 tables, #3 tables, Symtab.delete_safe name (#4 tables), #5 tables, #6 tables);
wenzelm@60746
    84
    in make_data (bootstrap, tables', sml_tables, breakpoints) end);
wenzelm@60746
    85
wenzelm@60746
    86
fun add_breakpoint breakpoint =
wenzelm@60746
    87
  Env.map (fn {bootstrap, tables, sml_tables, breakpoints} =>
wenzelm@60746
    88
    let val breakpoints' = Inttab.update_new breakpoint breakpoints;
wenzelm@60746
    89
    in make_data (bootstrap, tables, sml_tables, breakpoints') end);
wenzelm@60746
    90
wenzelm@60746
    91
val get_breakpoint = Inttab.lookup o #breakpoints o Env.get;
wenzelm@59127
    92
wenzelm@31328
    93
wenzelm@56618
    94
(* name space *)
wenzelm@56275
    95
wenzelm@62873
    96
val init_bootstrap =
wenzelm@62873
    97
  Env.map (fn {bootstrap, tables, sml_tables, breakpoints} =>
wenzelm@62873
    98
    let
wenzelm@62873
    99
      val sml_tables' =
wenzelm@62873
   100
        sml_tables |> (fn (val1, type1, fixity1, structure1, signature1, functor1) =>
wenzelm@62873
   101
            let
wenzelm@62873
   102
              val val2 =
wenzelm@62873
   103
                fold (fn (x, y) =>
wenzelm@62875
   104
                  member (op =) ML_Name_Space.bootstrap_values x ? Symtab.update (x, y))
wenzelm@62873
   105
                (#allVal ML_Name_Space.global ()) val1;
wenzelm@62873
   106
              val structure2 =
wenzelm@62873
   107
                fold (fn (x, y) =>
wenzelm@62875
   108
                  member (op =) ML_Name_Space.bootstrap_structures x ? Symtab.update (x, y))
wenzelm@62873
   109
                (#allStruct ML_Name_Space.global ()) structure1;
wenzelm@62873
   110
            in (val2, type1, fixity1, structure2, signature1, functor1) end);
wenzelm@62873
   111
    in make_data (bootstrap, tables, sml_tables', breakpoints) end);
wenzelm@62873
   112
wenzelm@60858
   113
fun add_name_space {SML} (space: ML_Name_Space.T) =
wenzelm@60858
   114
  Env.map (fn {bootstrap, tables, sml_tables, breakpoints} =>
wenzelm@60858
   115
    let
wenzelm@60858
   116
      val (tables', sml_tables') =
wenzelm@60858
   117
        (tables, sml_tables) |> (if SML then apsnd else apfst)
wenzelm@60858
   118
          (fn (val1, type1, fixity1, structure1, signature1, functor1) =>
wenzelm@60858
   119
            let
wenzelm@60858
   120
              val val2 = fold Symtab.update (#allVal space ()) val1;
wenzelm@60858
   121
              val type2 = fold Symtab.update (#allType space ()) type1;
wenzelm@60858
   122
              val fixity2 = fold Symtab.update (#allFix space ()) fixity1;
wenzelm@60858
   123
              val structure2 = fold Symtab.update (#allStruct space ()) structure1;
wenzelm@60858
   124
              val signature2 = fold Symtab.update (#allSig space ()) signature1;
wenzelm@60858
   125
              val functor2 = fold Symtab.update (#allFunct space ()) functor1;
wenzelm@60858
   126
            in (val2, type2, fixity2, structure2, signature2, functor2) end);
wenzelm@60858
   127
    in make_data (bootstrap, tables', sml_tables', breakpoints) end);
wenzelm@60858
   128
wenzelm@62495
   129
fun make_name_space {SML, exchange} : ML_Name_Space.T =
wenzelm@31325
   130
  let
wenzelm@31325
   131
    fun lookup sel1 sel2 name =
wenzelm@56618
   132
      if SML then
wenzelm@62876
   133
        Context.the_generic_context ()
wenzelm@56618
   134
        |> (fn context => Symtab.lookup (sel1 (#sml_tables (Env.get context))) name)
wenzelm@56618
   135
      else
wenzelm@62889
   136
        Context.get_generic_context ()
wenzelm@56618
   137
        |> (fn NONE => NONE | SOME context => Symtab.lookup (sel1 (#tables (Env.get context))) name)
wenzelm@56618
   138
        |> (fn NONE => sel2 ML_Name_Space.global name | some => some);
wenzelm@31325
   139
wenzelm@31325
   140
    fun all sel1 sel2 () =
wenzelm@56618
   141
      (if SML then
wenzelm@62876
   142
        Context.the_generic_context ()
wenzelm@56618
   143
        |> (fn context => Symtab.dest (sel1 (#sml_tables (Env.get context))))
wenzelm@56618
   144
      else
wenzelm@62889
   145
        Context.get_generic_context ()
wenzelm@56618
   146
        |> (fn NONE => [] | SOME context => Symtab.dest (sel1 (#tables (Env.get context))))
wenzelm@56618
   147
        |> append (sel2 ML_Name_Space.global ()))
wenzelm@59058
   148
      |> sort_distinct (string_ord o apply2 #1);
wenzelm@31325
   149
wenzelm@31325
   150
    fun enter ap1 sel2 entry =
wenzelm@56618
   151
      if SML <> exchange then
wenzelm@60746
   152
        Context.>> (Env.map (fn {bootstrap, tables, sml_tables, breakpoints} =>
wenzelm@56618
   153
          let val sml_tables' = ap1 (Symtab.update entry) sml_tables
wenzelm@60746
   154
          in make_data (bootstrap, tables, sml_tables', breakpoints) end))
wenzelm@62889
   155
      else if is_some (Context.get_generic_context ()) then
wenzelm@60746
   156
        Context.>> (Env.map (fn {bootstrap, tables, sml_tables, breakpoints} =>
wenzelm@56203
   157
          let
wenzelm@56275
   158
            val _ = if bootstrap then sel2 ML_Name_Space.global entry else ();
wenzelm@56275
   159
            val tables' = ap1 (Symtab.update entry) tables;
wenzelm@60746
   160
          in make_data (bootstrap, tables', sml_tables, breakpoints) end))
wenzelm@31325
   161
      else sel2 ML_Name_Space.global entry;
wenzelm@31325
   162
  in
wenzelm@31325
   163
   {lookupVal    = lookup #1 #lookupVal,
wenzelm@31325
   164
    lookupType   = lookup #2 #lookupType,
wenzelm@31325
   165
    lookupFix    = lookup #3 #lookupFix,
wenzelm@31325
   166
    lookupStruct = lookup #4 #lookupStruct,
wenzelm@31325
   167
    lookupSig    = lookup #5 #lookupSig,
wenzelm@31325
   168
    lookupFunct  = lookup #6 #lookupFunct,
wenzelm@31325
   169
    enterVal     = enter (fn h => fn (a, b, c, d, e, f) => (h a, b, c, d, e, f)) #enterVal,
wenzelm@31325
   170
    enterType    = enter (fn h => fn (a, b, c, d, e, f) => (a, h b, c, d, e, f)) #enterType,
wenzelm@31325
   171
    enterFix     = enter (fn h => fn (a, b, c, d, e, f) => (a, b, h c, d, e, f)) #enterFix,
wenzelm@31325
   172
    enterStruct  = enter (fn h => fn (a, b, c, d, e, f) => (a, b, c, h d, e, f)) #enterStruct,
wenzelm@31325
   173
    enterSig     = enter (fn h => fn (a, b, c, d, e, f) => (a, b, c, d, h e, f)) #enterSig,
wenzelm@31325
   174
    enterFunct   = enter (fn h => fn (a, b, c, d, e, f) => (a, b, c, d, e, h f)) #enterFunct,
wenzelm@31325
   175
    allVal       = all #1 #allVal,
wenzelm@31325
   176
    allType      = all #2 #allType,
wenzelm@31325
   177
    allFix       = all #3 #allFix,
wenzelm@31325
   178
    allStruct    = all #4 #allStruct,
wenzelm@31325
   179
    allSig       = all #5 #allSig,
wenzelm@31325
   180
    allFunct     = all #6 #allFunct}
wenzelm@31325
   181
  end;
wenzelm@31325
   182
wenzelm@62495
   183
val context: ML_Compiler0.context =
wenzelm@62495
   184
 {name_space = make_name_space {SML = false, exchange = false},
wenzelm@62716
   185
  print_depth = NONE,
wenzelm@62493
   186
  here = Position.here oo Position.line_file,
wenzelm@31325
   187
  print = writeln,
wenzelm@31325
   188
  error = error};
wenzelm@31325
   189
wenzelm@62495
   190
val name_space = #name_space context;
wenzelm@56618
   191
wenzelm@62495
   192
val is_functor = is_some o #lookupFunct name_space;
wenzelm@36163
   193
wenzelm@36163
   194
fun check_functor name =
wenzelm@36165
   195
  if not (is_functor "Table") (*mask dummy version of name_space*) orelse is_functor name then ()
wenzelm@36163
   196
  else error ("Unknown ML functor: " ^ quote name);
wenzelm@36163
   197
wenzelm@31325
   198
end;