src/Pure/Isar/named_target.ML
author haftmann
Wed, 02 Jul 2014 08:03:50 +0200
changeset 58827 b640e50c91a1
parent 58826 cc309f3c0490
child 59180 85ec71012df8
permissions -rw-r--r--
optional exit hook for theory-like targets
wenzelm@42830
     1
(*  Title:      Pure/Isar/named_target.ML
wenzelm@20894
     2
    Author:     Makarius
wenzelm@30451
     3
    Author:     Florian Haftmann, TU Muenchen
wenzelm@20894
     4
wenzelm@47943
     5
Targets for theory, locale, class -- at the bottom the nested structure.
wenzelm@20894
     6
*)
wenzelm@20894
     7
haftmann@38586
     8
signature NAMED_TARGET =
haftmann@38530
     9
sig
haftmann@53277
    10
  val is_theory: local_theory -> bool
haftmann@58524
    11
  val locale_of: local_theory -> string option
haftmann@58537
    12
  val bottom_locale_of: local_theory -> string option
haftmann@58524
    13
  val class_of: local_theory -> string option
haftmann@58523
    14
  val init: string -> theory -> local_theory
haftmann@38614
    15
  val theory_init: theory -> local_theory
haftmann@58827
    16
  val theory_like_init: (local_theory -> local_theory) -> theory -> local_theory
haftmann@58825
    17
  val begin: xstring * Position.T -> theory -> local_theory
haftmann@58825
    18
  val exit: local_theory -> theory
haftmann@58825
    19
  val switch: (xstring * Position.T) option -> Context.generic
haftmann@58825
    20
    -> (local_theory -> Context.generic) * local_theory
haftmann@38530
    21
end;
haftmann@38530
    22
haftmann@38586
    23
structure Named_Target: NAMED_TARGET =
haftmann@38530
    24
struct
haftmann@38530
    25
haftmann@38530
    26
(* context data *)
haftmann@38530
    27
haftmann@38530
    28
structure Data = Proof_Data
haftmann@38530
    29
(
haftmann@58538
    30
  type T = (string * bool) option;
haftmann@38617
    31
  fun init _ = NONE;
haftmann@38530
    32
);
haftmann@38530
    33
haftmann@58538
    34
val get_bottom_data = Data.get;
haftmann@58537
    35
haftmann@58537
    36
fun get_data lthy =
haftmann@58519
    37
  if Local_Theory.level lthy = 1
haftmann@58537
    38
  then get_bottom_data lthy
haftmann@58519
    39
  else NONE;
haftmann@38530
    40
haftmann@58527
    41
fun is_theory lthy =
haftmann@58537
    42
  case get_data lthy of
haftmann@58538
    43
    SOME ("", _) => true
haftmann@58527
    44
  | _ => false;
haftmann@53277
    45
haftmann@58826
    46
fun target_of lthy =
haftmann@58826
    47
  case get_data lthy of
haftmann@58826
    48
    NONE => error "Not in a named target"
haftmann@58826
    49
  | SOME (target, _) => target;
haftmann@58826
    50
haftmann@58538
    51
fun locale_name_of NONE = NONE
haftmann@58538
    52
  | locale_name_of (SOME ("", _)) = NONE
haftmann@58538
    53
  | locale_name_of (SOME (locale, _)) = SOME locale;
haftmann@58537
    54
haftmann@58538
    55
val locale_of = locale_name_of o get_data;
haftmann@58538
    56
haftmann@58538
    57
val bottom_locale_of = locale_name_of o get_bottom_data;
haftmann@58524
    58
haftmann@58524
    59
fun class_of lthy =
haftmann@58537
    60
  case get_data lthy of
haftmann@58538
    61
    SOME (class, true) => SOME class
haftmann@58524
    62
  | _ => NONE;
haftmann@58524
    63
haftmann@38530
    64
haftmann@38542
    65
(* define *)
haftmann@38542
    66
haftmann@58416
    67
fun locale_foundation locale (((b, U), mx), (b_def, rhs)) params =
wenzelm@48173
    68
  Generic_Target.background_foundation (((b, U), NoSyn), (b_def, rhs)) params
haftmann@58416
    69
  #-> (fn (lhs, def) => Generic_Target.locale_const locale Syntax.mode_default ((b, mx), lhs)
wenzelm@48166
    70
    #> pair (lhs, def));
haftmann@38542
    71
haftmann@58416
    72
fun class_foundation class (((b, U), mx), (b_def, rhs)) params =
wenzelm@48173
    73
  Generic_Target.background_foundation (((b, U), NoSyn), (b_def, rhs)) params
haftmann@58416
    74
  #-> (fn (lhs, def) => Class.const class ((b, mx), lhs) params
wenzelm@48166
    75
    #> pair (lhs, def));
haftmann@38542
    76
haftmann@58538
    77
fun foundation ("", _) = Generic_Target.theory_foundation
haftmann@58538
    78
  | foundation (locale, false) = locale_foundation locale
haftmann@58538
    79
  | foundation (class, true) = class_foundation class;
haftmann@38527
    80
wenzelm@24939
    81
haftmann@38532
    82
(* notes *)
haftmann@38532
    83
haftmann@58538
    84
fun notes ("", _) = Generic_Target.theory_notes
haftmann@58538
    85
  | notes (locale, _) = Generic_Target.locale_notes locale;
haftmann@38532
    86
haftmann@38532
    87
haftmann@38532
    88
(* abbrev *)
haftmann@38532
    89
haftmann@58460
    90
fun locale_abbrev locale prmode (b, mx) global_rhs params =
haftmann@58502
    91
  Generic_Target.background_abbrev (b, global_rhs) (snd params)
haftmann@58416
    92
  #-> (fn (lhs, _) => Generic_Target.locale_const locale prmode ((b, mx), lhs));
haftmann@38532
    93
haftmann@58460
    94
fun class_abbrev class prmode (b, mx) global_rhs params =
haftmann@58502
    95
  Generic_Target.background_abbrev (b, global_rhs) (snd params)
haftmann@58503
    96
  #-> (fn (lhs, rhs) => Class.abbrev class prmode ((b, mx), lhs) rhs params);
haftmann@58408
    97
haftmann@58538
    98
fun abbrev ("", _) = Generic_Target.theory_abbrev
haftmann@58538
    99
  | abbrev (locale, false) = locale_abbrev locale
haftmann@58538
   100
  | abbrev (class, true) = class_abbrev class;
haftmann@38532
   101
haftmann@38532
   102
wenzelm@48122
   103
(* declaration *)
wenzelm@48122
   104
haftmann@58538
   105
fun declaration ("", _) flags decl = Generic_Target.theory_declaration decl
haftmann@58538
   106
  | declaration (locale, _) flags decl = Generic_Target.locale_declaration locale flags decl;
wenzelm@48122
   107
wenzelm@48122
   108
haftmann@58065
   109
(* subscription *)
haftmann@58065
   110
haftmann@58538
   111
fun subscription ("", _) = Generic_Target.theory_registration
haftmann@58538
   112
  | subscription (locale, _) = Generic_Target.locale_dependency locale;
haftmann@58065
   113
haftmann@58065
   114
haftmann@38532
   115
(* pretty *)
haftmann@38532
   116
haftmann@58538
   117
fun pretty (target, is_class) ctxt =
haftmann@38532
   118
  let
haftmann@38532
   119
    val target_name =
wenzelm@57105
   120
      [Pretty.keyword1 (if is_class then "class" else "locale"), Pretty.brk 1,
wenzelm@53240
   121
        Locale.pretty_name ctxt target];
wenzelm@46224
   122
    val fixes =
wenzelm@46224
   123
      map (fn (x, T) => (Binding.name x, SOME T, NoSyn))
wenzelm@46224
   124
        (#1 (Proof_Context.inferred_fixes ctxt));
wenzelm@46224
   125
    val assumes =
wenzelm@46224
   126
      map (fn A => (Attrib.empty_binding, [(Thm.term_of A, [])]))
wenzelm@46224
   127
        (Assumption.all_assms_of ctxt);
haftmann@38532
   128
    val elems =
haftmann@38532
   129
      (if null fixes then [] else [Element.Fixes fixes]) @
haftmann@38532
   130
      (if null assumes then [] else [Element.Assumes assumes]);
wenzelm@41032
   131
    val body_elems =
haftmann@58538
   132
      if target = "" then []
haftmann@39863
   133
      else if null elems then [Pretty.block target_name]
haftmann@39863
   134
      else [Pretty.block (Pretty.fbreaks (Pretty.block (target_name @ [Pretty.str " ="]) ::
wenzelm@41032
   135
        map (Pretty.chunks o Element.pretty_ctxt ctxt) elems))];
haftmann@38532
   136
  in
wenzelm@57105
   137
    Pretty.block [Pretty.keyword1 "theory", Pretty.brk 1,
wenzelm@43231
   138
      Pretty.str (Context.theory_name (Proof_Context.theory_of ctxt))] :: body_elems
haftmann@38532
   139
  end;
haftmann@38532
   140
haftmann@38532
   141
haftmann@38604
   142
(* init *)
wenzelm@20894
   143
haftmann@58538
   144
fun make_name_data _ "" = ("", false)
haftmann@58538
   145
  | make_name_data thy target =
haftmann@58538
   146
      if Locale.defined thy target
haftmann@58538
   147
      then (target, Class.is_class thy target)
haftmann@58538
   148
      else error ("No such locale: " ^ quote target);
haftmann@58538
   149
haftmann@58538
   150
fun init_context ("", _) = Proof_Context.init_global
haftmann@58538
   151
  | init_context (locale, false) = Locale.init locale
haftmann@58538
   152
  | init_context (class, true) = Class.init class;
haftmann@25462
   153
haftmann@58827
   154
fun gen_init before_exit target thy =
haftmann@39863
   155
  let
haftmann@58538
   156
    val name_data = make_name_data thy target;
wenzelm@47938
   157
    val naming = Sign.naming_of thy
wenzelm@47938
   158
      |> Name_Space.mandatory_path (Long_Name.base_name target);
haftmann@39863
   159
  in
haftmann@39863
   160
    thy
wenzelm@57398
   161
    |> Sign.change_begin
haftmann@58538
   162
    |> init_context name_data
haftmann@58827
   163
    |> is_none before_exit ? Data.put (SOME name_data)
wenzelm@47938
   164
    |> Local_Theory.init naming
haftmann@58538
   165
       {define = Generic_Target.define (foundation name_data),
haftmann@58538
   166
        notes = Generic_Target.notes (notes name_data),
haftmann@58538
   167
        abbrev = Generic_Target.abbrev (abbrev name_data),
haftmann@58538
   168
        declaration = declaration name_data,
haftmann@58538
   169
        subscription = subscription name_data,
haftmann@58538
   170
        pretty = pretty name_data,
haftmann@58827
   171
        exit = the_default I before_exit
haftmann@58827
   172
          #> Local_Theory.target_of #> Sign.change_end_local}
haftmann@39863
   173
  end;
haftmann@38471
   174
haftmann@58827
   175
val init = gen_init NONE
haftmann@58827
   176
haftmann@58523
   177
val theory_init = init "";
wenzelm@25291
   178
haftmann@58827
   179
fun theory_like_init before_exit = gen_init (SOME before_exit) "";
haftmann@58827
   180
haftmann@58825
   181
haftmann@58825
   182
(* toplevel interaction *)
haftmann@58825
   183
haftmann@58825
   184
fun begin ("-", _) thy = theory_init thy
haftmann@58825
   185
  | begin target thy = init (Locale.check thy target) thy;
haftmann@58825
   186
haftmann@58825
   187
val exit = Local_Theory.assert_bottom true #> Local_Theory.exit_global;
haftmann@58825
   188
haftmann@58825
   189
fun switch NONE (Context.Theory thy) =
haftmann@58825
   190
      (Context.Theory o exit, theory_init thy)
haftmann@58825
   191
  | switch (SOME name) (Context.Theory thy) =
haftmann@58825
   192
      (Context.Theory o exit, begin name thy)
haftmann@58825
   193
  | switch NONE (Context.Proof lthy) =
haftmann@58825
   194
      (Context.Proof o Local_Theory.restore, lthy)
haftmann@58825
   195
  | switch (SOME name) (Context.Proof lthy) =
haftmann@58826
   196
      (Context.Proof o init (target_of lthy) o exit,
haftmann@58825
   197
        (begin name o exit o Local_Theory.assert_nonbrittle) lthy);
wenzelm@33282
   198
wenzelm@20894
   199
end;