src/Pure/proof_general.ML
author wenzelm
Sun, 06 Jun 2004 18:35:26 +0200
changeset 14880 7586233bd4bd
parent 14827 d973e7f820cb
child 14902 bef0dc694c48
permissions -rw-r--r--
Symbol.output;
wenzelm@12780
     1
(*  Title:      Pure/proof_general.ML
wenzelm@12778
     2
    ID:         $Id$
wenzelm@14675
     3
    Author:     David Aspinall and Markus Wenzel
wenzelm@12778
     4
    License:    GPL (GNU GENERAL PUBLIC LICENSE)
wenzelm@12778
     5
nipkow@14566
     6
Isabelle configuration for Proof General (see http://proofgeneral.inf.ed.ac.uk).
wenzelm@12778
     7
*)
wenzelm@12778
     8
wenzelm@12778
     9
signature PROOF_GENERAL =
wenzelm@12778
    10
sig
wenzelm@12778
    11
  val setup: (theory -> theory) list
wenzelm@12778
    12
  val update_thy_only: string -> unit
wenzelm@12778
    13
  val try_update_thy_only: string -> unit
wenzelm@13391
    14
  val inform_file_retracted: string -> unit
wenzelm@12778
    15
  val inform_file_processed: string -> unit
berghofe@13728
    16
  val options: (string * (string * (string * (unit -> string) * (string -> unit)))) list ref
berghofe@13728
    17
  val process_pgip: string -> unit
wenzelm@12778
    18
  val thms_containing: string list -> unit
wenzelm@12778
    19
  val help: unit -> unit
wenzelm@12778
    20
  val show_context: unit -> theory
wenzelm@12778
    21
  val kill_goal: unit -> unit
wenzelm@12778
    22
  val repeat_undo: int -> unit
wenzelm@12778
    23
  val isa_restart: unit -> unit
wenzelm@12833
    24
  val full_proofs: bool -> unit
wenzelm@12778
    25
  val init: bool -> unit
wenzelm@12778
    26
  val write_keywords: string -> unit
wenzelm@12778
    27
end;
wenzelm@12778
    28
wenzelm@12778
    29
structure ProofGeneral: PROOF_GENERAL =
wenzelm@12778
    30
struct
wenzelm@12778
    31
wenzelm@12778
    32
(* print modes *)
wenzelm@12778
    33
wenzelm@12778
    34
val proof_generalN = "ProofGeneral";
wenzelm@12778
    35
val xsymbolsN = "xsymbols";
wenzelm@13538
    36
val thm_depsN = "thm_deps";
wenzelm@12778
    37
berghofe@13728
    38
val pgml_version_supported = "1.0";
wenzelm@12778
    39
val pgmlN = "PGML";
wenzelm@12778
    40
fun pgml () = pgmlN mem_string ! print_mode;
wenzelm@12778
    41
wenzelm@12778
    42
wenzelm@12778
    43
(* text output *)
wenzelm@12778
    44
wenzelm@12778
    45
local
wenzelm@12778
    46
wenzelm@14827
    47
fun xsym_output "\\" = "\\\\"
wenzelm@14827
    48
  | xsym_output s = if Symbol.is_raw s then Symbol.decode_raw s else s;
wenzelm@14827
    49
wenzelm@12778
    50
fun xsymbols_output s =
wenzelm@12778
    51
  if xsymbolsN mem_string ! print_mode andalso exists_string (equal "\\") s then
wenzelm@12778
    52
    let val syms = Symbol.explode s
wenzelm@14827
    53
    in (implode (map xsym_output syms), real (Symbol.length syms)) end
wenzelm@14880
    54
  else Symbol.default_output s;
wenzelm@12778
    55
wenzelm@12778
    56
fun pgml_output (s, len) =
wenzelm@12778
    57
  if pgml () then (XML.text s, len)
wenzelm@12778
    58
  else (s, len);
wenzelm@12778
    59
wenzelm@12778
    60
in
wenzelm@12778
    61
wenzelm@14827
    62
fun setup_xsymbols_output () = Output.add_mode proof_generalN
wenzelm@14827
    63
  (pgml_output o xsymbols_output, Symbol.default_indent, Symbol.default_raw);
wenzelm@12778
    64
wenzelm@12778
    65
end;
wenzelm@12778
    66
wenzelm@12778
    67
wenzelm@12778
    68
(* token translations *)
wenzelm@12778
    69
wenzelm@12778
    70
local
wenzelm@12778
    71
wenzelm@12778
    72
val end_tag = oct_char "350";
wenzelm@12778
    73
val class_tag = ("class", oct_char "351");
wenzelm@12778
    74
val tfree_tag = ("tfree", oct_char "352");
wenzelm@12778
    75
val tvar_tag = ("tvar", oct_char "353");
wenzelm@12778
    76
val free_tag = ("free", oct_char "354");
wenzelm@12778
    77
val bound_tag = ("bound", oct_char "355");
wenzelm@12778
    78
val var_tag = ("var", oct_char "356");
wenzelm@12778
    79
val skolem_tag = ("skolem", oct_char "357");
wenzelm@12778
    80
wenzelm@12778
    81
fun xml_atom kind x = XML.element "atom" [("kind", kind)] [XML.text x];
wenzelm@12778
    82
wenzelm@12778
    83
fun tagit (kind, bg_tag) x =
wenzelm@12778
    84
  (if pgml () then xml_atom kind x else bg_tag ^ x ^ end_tag,
wenzelm@12778
    85
    real (Symbol.length (Symbol.explode x)));
wenzelm@12778
    86
wenzelm@12778
    87
fun free_or_skolem x =
wenzelm@12778
    88
  (case try Syntax.dest_skolem x of
wenzelm@12778
    89
    None => tagit free_tag x
wenzelm@12778
    90
  | Some x' => tagit skolem_tag x');
wenzelm@12778
    91
wenzelm@12778
    92
fun var_or_skolem s =
wenzelm@12778
    93
  (case Syntax.read_var s of
wenzelm@12778
    94
    Var ((x, i), _) =>
wenzelm@12778
    95
      (case try Syntax.dest_skolem x of
wenzelm@12778
    96
        None => tagit var_tag s
wenzelm@12778
    97
      | Some x' => tagit skolem_tag (Syntax.string_of_vname (x', i)))
wenzelm@12778
    98
  | _ => tagit var_tag s);
wenzelm@12778
    99
wenzelm@12778
   100
val proof_general_trans =
wenzelm@12778
   101
 Syntax.tokentrans_mode proof_generalN
wenzelm@12778
   102
  [("class", tagit class_tag),
wenzelm@12778
   103
   ("tfree", tagit tfree_tag),
wenzelm@12778
   104
   ("tvar", tagit tvar_tag),
wenzelm@12778
   105
   ("free", free_or_skolem),
wenzelm@12778
   106
   ("bound", tagit bound_tag),
wenzelm@12778
   107
   ("var", var_or_skolem)];
wenzelm@12778
   108
wenzelm@12778
   109
in val setup = [Theory.add_tokentrfuns proof_general_trans] end;
wenzelm@12778
   110
wenzelm@12778
   111
wenzelm@12778
   112
(* messages and notification *)
wenzelm@12778
   113
wenzelm@12778
   114
local
wenzelm@12778
   115
wenzelm@12778
   116
fun decorated_output bg en prfx =
wenzelm@12778
   117
  writeln_default o enclose bg en o prefix_lines prfx;
wenzelm@12778
   118
wenzelm@12778
   119
fun message kind bg en prfx s =
wenzelm@12778
   120
  if pgml () then writeln_default (XML.element kind [] [prefix_lines prfx s])
wenzelm@12778
   121
  else decorated_output bg en prfx s;
wenzelm@12778
   122
wenzelm@13526
   123
in
wenzelm@13526
   124
wenzelm@12778
   125
val notify = message "notify" (oct_char "360") (oct_char "361") "";
wenzelm@12778
   126
wenzelm@12778
   127
fun setup_messages () =
wenzelm@12778
   128
 (writeln_fn := message "output" "" "" "";
wenzelm@12778
   129
  priority_fn := message "information" (oct_char "360") (oct_char "361") "";
wenzelm@12778
   130
  tracing_fn := message "tracing" (oct_char "360" ^ oct_char "375") (oct_char "361") "";
wenzelm@12778
   131
  warning_fn := message "warning" (oct_char "362") (oct_char "363") "### ";
wenzelm@12778
   132
  error_fn := message "error" (oct_char "364") (oct_char "365") "*** ");
wenzelm@12778
   133
wenzelm@12778
   134
fun tell_clear_goals () = notify "Proof General, please clear the goals buffer.";
wenzelm@12778
   135
fun tell_clear_response () = notify "Proof General, please clear the response buffer.";
wenzelm@12778
   136
fun tell_file msg path = notify ("Proof General, " ^ msg ^ " " ^ quote (File.sysify_path path));
wenzelm@12778
   137
wenzelm@12778
   138
end;
wenzelm@12778
   139
wenzelm@12778
   140
wenzelm@12778
   141
(* theory / proof state output *)
wenzelm@12778
   142
wenzelm@12778
   143
local
wenzelm@12778
   144
wenzelm@12778
   145
fun tmp_markers f =
wenzelm@12778
   146
  setmp Display.current_goals_markers (oct_char "366", oct_char "367", "") f ();
wenzelm@12778
   147
wenzelm@12778
   148
fun statedisplay prts =
wenzelm@12778
   149
  writeln_default (XML.element "statedisplay" [] [Pretty.string_of (Pretty.chunks prts)]);
wenzelm@12778
   150
wenzelm@12778
   151
fun print_current_goals n m st =
wenzelm@12778
   152
  if pgml () then statedisplay (Display.pretty_current_goals n m st)
wenzelm@12778
   153
  else tmp_markers (fn () => Display.print_current_goals_default n m st);
wenzelm@12778
   154
wenzelm@12778
   155
fun print_state b st =
wenzelm@12778
   156
  if pgml () then statedisplay (Toplevel.pretty_state b st)
wenzelm@12778
   157
  else tmp_markers (fn () => Toplevel.print_state_default b st);
wenzelm@12778
   158
wenzelm@12778
   159
in
wenzelm@12778
   160
wenzelm@12778
   161
fun setup_state () =
wenzelm@12778
   162
 (Display.print_current_goals_fn := print_current_goals;
wenzelm@12778
   163
  Toplevel.print_state_fn := print_state;
wenzelm@12778
   164
  Toplevel.prompt_state_fn := (suffix (oct_char "372") o Toplevel.prompt_state_default));
wenzelm@12778
   165
wenzelm@12778
   166
end;
wenzelm@12778
   167
wenzelm@12778
   168
wenzelm@13538
   169
(* theorem dependency output *)
wenzelm@13526
   170
wenzelm@13526
   171
local
wenzelm@13526
   172
wenzelm@13545
   173
val spaces_quote = space_implode " " o map quote;
wenzelm@13545
   174
wenzelm@13526
   175
fun tell_thm_deps ths =
wenzelm@13538
   176
  conditional (thm_depsN mem_string ! print_mode) (fn () =>
wenzelm@13538
   177
    let
wenzelm@13545
   178
      val names = map Thm.name_of_thm ths \ "";
wenzelm@13545
   179
      val deps = Symtab.keys (foldl (uncurry Proofterm.thms_of_proof)
wenzelm@13545
   180
          (Symtab.empty, map Thm.proof_of ths)) \ "";
wenzelm@13538
   181
    in
wenzelm@13545
   182
      if null names orelse null deps then ()
wenzelm@13545
   183
      else notify ("Proof General, theorem dependencies of " ^ spaces_quote names ^ " are "
wenzelm@13545
   184
        ^ spaces_quote deps)
wenzelm@13538
   185
    end);
wenzelm@13526
   186
wenzelm@13526
   187
in
wenzelm@13526
   188
wenzelm@13526
   189
fun setup_present_hook () =
wenzelm@13526
   190
  Present.add_hook (fn _ => fn res => tell_thm_deps (flat (map #2 res)));
wenzelm@13526
   191
wenzelm@13526
   192
end;
wenzelm@13526
   193
wenzelm@13526
   194
wenzelm@12778
   195
(* theory loader actions *)
wenzelm@12778
   196
wenzelm@12778
   197
local
wenzelm@12778
   198
wenzelm@12778
   199
fun add_master_files name files =
wenzelm@12778
   200
  let val masters = [ThyLoad.thy_path name, ThyLoad.ml_path name]
wenzelm@12778
   201
  in masters @ gen_rems (op = o pairself Path.base) (files, masters) end;
wenzelm@12778
   202
wenzelm@12778
   203
fun trace_action action name =
wenzelm@12778
   204
  if action = ThyInfo.Update then
wenzelm@12778
   205
    seq (tell_file "this file is loaded:") (ThyInfo.loaded_files name)
wenzelm@12778
   206
  else if action = ThyInfo.Outdate orelse action = ThyInfo.Remove then
wenzelm@12778
   207
    seq (tell_file "you can unlock the file") (add_master_files name (ThyInfo.loaded_files name))
wenzelm@12778
   208
  else ();
wenzelm@12778
   209
wenzelm@12778
   210
in
wenzelm@12778
   211
  fun setup_thy_loader () = ThyInfo.add_hook trace_action;
wenzelm@12778
   212
  fun sync_thy_loader () = seq (trace_action ThyInfo.Update) (ThyInfo.names ());
wenzelm@12778
   213
end;
wenzelm@12778
   214
wenzelm@12778
   215
wenzelm@12778
   216
(* prepare theory context *)
wenzelm@12778
   217
wenzelm@12778
   218
val thy_name = Path.pack o Path.drop_ext o Path.base o Path.unpack;
wenzelm@12778
   219
val update_thy_only = setmp MetaSimplifier.trace_simp false ThyInfo.update_thy_only;
wenzelm@12778
   220
wenzelm@12778
   221
fun which_context () =
wenzelm@12778
   222
  (case Context.get_context () of
wenzelm@12778
   223
    Some thy => "  Using current (dynamic!) one: " ^
wenzelm@12778
   224
      (case try PureThy.get_name thy of Some name => quote name | None => "<unnamed>")
wenzelm@12778
   225
  | None => "");
wenzelm@12778
   226
wenzelm@12778
   227
fun try_update_thy_only file =
wenzelm@12778
   228
  ThyLoad.cond_add_path (Path.dir (Path.unpack file)) (fn () =>
wenzelm@12778
   229
    let val name = thy_name file in
wenzelm@12778
   230
      if is_some (ThyLoad.check_file (ThyLoad.thy_path name)) then update_thy_only name
wenzelm@12778
   231
      else warning ("Unkown theory context of ML file." ^ which_context ())
wenzelm@12778
   232
    end) ();
wenzelm@12778
   233
wenzelm@12778
   234
wenzelm@12778
   235
(* get informed about files *)
wenzelm@12778
   236
wenzelm@13391
   237
val inform_file_retracted = ThyInfo.if_known_thy ThyInfo.remove_thy o thy_name;
wenzelm@13391
   238
val inform_file_processed = ThyInfo.if_known_thy ThyInfo.touch_child_thys o thy_name;
wenzelm@12778
   239
wenzelm@12778
   240
fun proper_inform_file_processed file state =
wenzelm@12778
   241
  let val name = thy_name file in
wenzelm@13391
   242
    ThyInfo.if_known_thy ThyInfo.touch_child_thys name;
wenzelm@12778
   243
    if not (Toplevel.is_toplevel state) then
wenzelm@12778
   244
      warning ("Not at toplevel -- cannot register theory " ^ quote name)
wenzelm@14827
   245
    else transform_error ThyInfo.pretend_use_thy_only name handle ERROR_MESSAGE msg =>
wenzelm@12778
   246
      (warning msg; warning ("Failed to register theory " ^ quote name))
wenzelm@12778
   247
  end;
wenzelm@12778
   248
wenzelm@12778
   249
berghofe@13728
   250
(* options *)
berghofe@13728
   251
berghofe@13728
   252
fun nat_option r = ("nat",
berghofe@13728
   253
  (fn () => string_of_int (!r)),
berghofe@13728
   254
  (fn s => (case Syntax.read_nat s of
berghofe@13728
   255
       None => error "nat_option: illegal value"
berghofe@13728
   256
     | Some i => r := i)));
berghofe@13728
   257
berghofe@13728
   258
fun bool_option r = ("boolean",
berghofe@13728
   259
  (fn () => Bool.toString (!r)),
berghofe@13728
   260
  (fn "false" => r := false | "true" => r := true
berghofe@13728
   261
    | _ => error "bool_option: illegal value"));
berghofe@13728
   262
berghofe@13728
   263
val proof_option = ("boolean",
berghofe@13728
   264
  (fn () => Bool.toString (!proofs >= 2)),
berghofe@13728
   265
  (fn "false" => proofs := 1 | "true" => proofs := 2
berghofe@13728
   266
    | _ => error "proof_option: illegal value"));
berghofe@13728
   267
berghofe@13728
   268
val thm_deps_option = ("boolean",
berghofe@13728
   269
  (fn () => Bool.toString ("thm_deps" mem !print_mode)),
berghofe@13728
   270
  (fn "false" => print_mode := Library.gen_rems (op =) (!print_mode, ["thm_deps"])
berghofe@13728
   271
    | "true" => print_mode := (["thm_deps"] @ !print_mode)
berghofe@13728
   272
    | _ => error "thm_deps_option: illegal value"));
berghofe@13728
   273
berghofe@13728
   274
val print_depth_option = ("nat",
berghofe@13728
   275
  (fn () => "10"),
berghofe@13728
   276
  (fn s => (case Syntax.read_nat s of
berghofe@13728
   277
       None => error "print_depth_option: illegal value"
berghofe@13728
   278
     | Some i => print_depth i)));
berghofe@13728
   279
berghofe@13728
   280
val options = ref
berghofe@13728
   281
  [("show-types", ("Whether to show types in Isabelle.",
berghofe@13728
   282
      bool_option show_types)),
berghofe@13728
   283
   ("show-sorts", ("Whether to show sorts in Isabelle.",
berghofe@13728
   284
      bool_option show_sorts)),
wenzelm@14707
   285
   ("show-structs", ("Whether to show implicit structures in Isabelle.",
wenzelm@14707
   286
      bool_option show_structs)),
berghofe@13728
   287
   ("show-consts", ("Whether to show types of consts in Isabelle goals.",
berghofe@13728
   288
      bool_option show_consts)),
berghofe@13728
   289
   ("long-names", ("Whether to show fully qualified names in Isabelle.",
berghofe@13728
   290
      bool_option long_names)),
berghofe@13884
   291
   ("show-brackets", ("Whether to show full bracketing in Isabelle.",
berghofe@13884
   292
      bool_option show_brackets)),
berghofe@13728
   293
   ("eta-contract", ("Whether to print terms eta-contracted in Isabelle.",
berghofe@13728
   294
      bool_option Syntax.eta_contract)),
berghofe@13728
   295
   ("trace-simplifier", ("Whether to trace the Simplifier in Isabelle.",
berghofe@13728
   296
      bool_option trace_simp)),
berghofe@13728
   297
   ("trace-rules", ("Whether to trace the standard rules in Isabelle.",
berghofe@13728
   298
      bool_option trace_rules)),
berghofe@13728
   299
   ("quick-and-dirty", ("Whether to take a few short cuts occasionally.",
berghofe@13728
   300
      bool_option quick_and_dirty)),
berghofe@13728
   301
   ("full-proofs", ("Whether to record full proof objects internally.",
berghofe@13728
   302
      proof_option)),
berghofe@13728
   303
   ("trace-unification", ("Whether to output error diagnostics during unification.",
berghofe@13728
   304
      bool_option Pattern.trace_unify_fail)),
berghofe@13728
   305
   ("show-main-goal", ("Whether to show main goal.",
berghofe@13728
   306
      bool_option Proof.show_main_goal)),
berghofe@13728
   307
   ("global-timing", ("Whether to enable timing in Isabelle.",
wenzelm@14827
   308
      bool_option Output.timing)),
berghofe@13728
   309
   ("theorem-dependencies", ("Whether to track theorem dependencies within Proof General.",
berghofe@13728
   310
      thm_deps_option)),
berghofe@13728
   311
   ("goals-limit", ("Setting for maximum number of goals printed in Isabelle.",
berghofe@13728
   312
      nat_option goals_limit)),
berghofe@13728
   313
   ("prems-limit", ("Setting for maximum number of premises printed in Isabelle/Isar.",
berghofe@13728
   314
      nat_option ProofContext.prems_limit)),
berghofe@13728
   315
   ("print-depth", ("Setting for the ML print depth in Isabelle.",
berghofe@13728
   316
      print_depth_option))];
berghofe@13728
   317
berghofe@13728
   318
wenzelm@14675
   319
(* sending PGIP commands to the interface *)
berghofe@13728
   320
berghofe@13728
   321
fun issue_pgip pgips = notify (XML.element "pgip" [] pgips);
berghofe@13728
   322
wenzelm@14725
   323
fun usespgml () =
berghofe@13728
   324
  issue_pgip [XML.element "usespgml" [("version", pgml_version_supported)] []];
berghofe@13728
   325
wenzelm@14675
   326
(*NB: the default returned here is actually the current value, so
wenzelm@14675
   327
  repeated uses of <askprefs> will not work correctly*)
wenzelm@14725
   328
fun show_options () = issue_pgip (map
nipkow@14568
   329
  (fn (name, (descr, (ty, get, _))) => (XML.element "oldhaspref"
berghofe@13728
   330
    [("type", ty), ("descr", descr), ("default", get ())] [name])) (!options));
berghofe@13728
   331
berghofe@13728
   332
fun set_option name value = (case assoc (!options, name) of
berghofe@13728
   333
      None => warning ("Unknown option: " ^ quote name)
berghofe@13728
   334
    | Some (_, (_, _, set)) => set value);
berghofe@13728
   335
berghofe@13728
   336
fun get_option name = (case assoc (!options, name) of
berghofe@13728
   337
      None => warning ("Unknown option: " ^ quote name)
wenzelm@14725
   338
    | Some (_, (_, get, _)) =>
wenzelm@14725
   339
        issue_pgip [XML.element "prefval" [("name", name)] [get ()]]);
berghofe@13728
   340
berghofe@13728
   341
wenzelm@14675
   342
(* processing PGIP commands from the interface *)
berghofe@13728
   343
wenzelm@14675
   344
(*FIXME: matching on attributes is a bit too strict here*)
berghofe@13728
   345
berghofe@13728
   346
fun process_pgip_element pgip = (case pgip of
berghofe@13728
   347
      XML.Elem ("askpgml", _, []) => usespgml ()
berghofe@13728
   348
    | XML.Elem ("askprefs", _, [])  => show_options ()
berghofe@13728
   349
    | XML.Elem ("getpref", [("name", name)], []) => get_option name
berghofe@13728
   350
    | XML.Elem ("setpref", [("name", name)], [XML.Text value]) =>
berghofe@13728
   351
        set_option name value
berghofe@13728
   352
    | XML.Elem (e, _, _) => warning ("Unrecognized PGIP command: " ^ e)
berghofe@13728
   353
    | XML.Text t => warning ("Unrecognized PGIP command:\n" ^ t));
berghofe@13728
   354
berghofe@13728
   355
fun process_pgip s = (case XML.tree_of_string s of
berghofe@13728
   356
    XML.Elem ("pgip", _, pgips) => seq process_pgip_element pgips
berghofe@13728
   357
  | _ => warning ("Invalid PGIP packet received\n" ^ s));
berghofe@13728
   358
berghofe@13728
   359
wenzelm@12778
   360
(* misc commands for ProofGeneral/isa *)
wenzelm@12778
   361
wenzelm@12778
   362
fun thms_containing ss =
wenzelm@13284
   363
  ProofContext.print_thms_containing (ProofContext.init (the_context ())) None ss;
wenzelm@12778
   364
wenzelm@12778
   365
val welcome = priority o Session.welcome;
wenzelm@12778
   366
val help = welcome;
wenzelm@12778
   367
val show_context = Context.the_context;
wenzelm@12778
   368
wenzelm@12778
   369
fun kill_goal () = (Goals.reset_goals (); tell_clear_goals ());
wenzelm@12778
   370
wenzelm@12778
   371
fun no_print_goals f = setmp Display.print_current_goals_fn (fn _ => fn _ => fn _ => ()) f;
wenzelm@12778
   372
wenzelm@12778
   373
fun repeat_undo 0 = ()
wenzelm@12778
   374
  | repeat_undo 1 = undo ()
wenzelm@12778
   375
  | repeat_undo n = (no_print_goals undo (); repeat_undo (n - 1));
wenzelm@12778
   376
wenzelm@12778
   377
wenzelm@12778
   378
(* restart top-level loop (keeps most state information) *)
wenzelm@12778
   379
wenzelm@12778
   380
local
wenzelm@12778
   381
wenzelm@12778
   382
fun restart isar =
wenzelm@12778
   383
 (if isar then tell_clear_goals () else kill_goal ();
wenzelm@12778
   384
  tell_clear_response ();
wenzelm@12778
   385
  welcome ());
wenzelm@12778
   386
wenzelm@12778
   387
in
wenzelm@12778
   388
wenzelm@12778
   389
fun isa_restart () = restart false;
wenzelm@12778
   390
fun isar_restart () = (sync_thy_loader (); restart true; raise Toplevel.RESTART);
wenzelm@12778
   391
wenzelm@12778
   392
end;
wenzelm@12778
   393
wenzelm@12778
   394
wenzelm@12833
   395
fun full_proofs true = proofs := 2
wenzelm@12833
   396
  | full_proofs false = proofs := 1;
wenzelm@12833
   397
wenzelm@12833
   398
wenzelm@12778
   399
(* outer syntax *)
wenzelm@12778
   400
wenzelm@12778
   401
local structure P = OuterParse and K = OuterSyntax.Keyword in
wenzelm@12778
   402
wenzelm@12778
   403
val undoP =
wenzelm@12778
   404
  OuterSyntax.improper_command "ProofGeneral.undo" "(internal)" K.control
wenzelm@12778
   405
    (Scan.succeed (Toplevel.no_timing o IsarCmd.undo));
wenzelm@12778
   406
wenzelm@12778
   407
val context_thy_onlyP =
wenzelm@12778
   408
  OuterSyntax.improper_command "ProofGeneral.context_thy_only" "(internal)" K.control
wenzelm@12778
   409
    (P.name >> (Toplevel.no_timing oo IsarThy.init_context update_thy_only));
wenzelm@12778
   410
wenzelm@12778
   411
val try_context_thy_onlyP =
wenzelm@12778
   412
  OuterSyntax.improper_command "ProofGeneral.try_context_thy_only" "(internal)" K.control
wenzelm@12778
   413
    (P.name >> (Toplevel.no_timing oo
wenzelm@12778
   414
      (Toplevel.imperative (K ()) oo IsarThy.init_context try_update_thy_only)));
wenzelm@12778
   415
wenzelm@12778
   416
val restartP =
wenzelm@12778
   417
  OuterSyntax.improper_command "ProofGeneral.restart" "(internal)" K.control
wenzelm@12778
   418
    (P.opt_unit >> (Toplevel.no_timing oo K (Toplevel.imperative isar_restart)));
wenzelm@12778
   419
wenzelm@12778
   420
val kill_proofP =
wenzelm@12778
   421
  OuterSyntax.improper_command "ProofGeneral.kill_proof" "(internal)" K.control
wenzelm@12778
   422
    (Scan.succeed (Toplevel.no_timing o IsarCmd.kill_proof_notify tell_clear_goals));
wenzelm@12778
   423
wenzelm@12778
   424
val inform_file_processedP =
wenzelm@12778
   425
  OuterSyntax.improper_command "ProofGeneral.inform_file_processed" "(internal)" K.control
wenzelm@12778
   426
    (P.name >> (Toplevel.no_timing oo
wenzelm@12778
   427
      (fn name => Toplevel.keep (proper_inform_file_processed name))));
wenzelm@12778
   428
wenzelm@12778
   429
val inform_file_retractedP =
wenzelm@12778
   430
  OuterSyntax.improper_command "ProofGeneral.inform_file_retracted" "(internal)" K.control
wenzelm@12778
   431
    (P.name >> (Toplevel.no_timing oo
wenzelm@12778
   432
      (fn name => Toplevel.imperative (fn () => inform_file_retracted name))));
wenzelm@12778
   433
wenzelm@14725
   434
val process_pgipP =
wenzelm@14725
   435
  OuterSyntax.improper_command "ProofGeneral.process_pgip" "(internal)" K.control
wenzelm@14725
   436
    (P.text >> (Toplevel.no_timing oo
wenzelm@14725
   437
      (fn txt => Toplevel.imperative (fn () => process_pgip txt))));
wenzelm@14725
   438
wenzelm@12778
   439
fun init_outer_syntax () = OuterSyntax.add_parsers
wenzelm@14675
   440
 [undoP, restartP, kill_proofP, context_thy_onlyP, try_context_thy_onlyP,
wenzelm@14725
   441
  inform_file_processedP, inform_file_retractedP, process_pgipP];
wenzelm@12778
   442
wenzelm@12778
   443
end;
wenzelm@12778
   444
wenzelm@12778
   445
wenzelm@12778
   446
(* init *)
wenzelm@12778
   447
wenzelm@12778
   448
val initialized = ref false;
wenzelm@12778
   449
wenzelm@12778
   450
fun init isar =
wenzelm@12778
   451
 (conditional (not (! initialized)) (fn () =>
wenzelm@12778
   452
   (if isar then setmp warning_fn (K ()) init_outer_syntax () else ();
wenzelm@12778
   453
    setup_xsymbols_output ();
wenzelm@12778
   454
    setup_messages ();
wenzelm@12778
   455
    setup_state ();
wenzelm@12778
   456
    setup_thy_loader ();
wenzelm@13526
   457
    setup_present_hook ();
wenzelm@12778
   458
    set initialized; ()));
wenzelm@12778
   459
  sync_thy_loader ();
wenzelm@12778
   460
  print_mode := proof_generalN :: (! print_mode \ proof_generalN);
wenzelm@12778
   461
  set quick_and_dirty;
wenzelm@12778
   462
  ThmDeps.enable ();
wenzelm@12778
   463
  if isar then ml_prompts "ML> " "ML# "
wenzelm@12778
   464
  else ml_prompts ("> " ^ oct_char "372") ("- " ^ oct_char "373");
wenzelm@12778
   465
  if isar then (welcome (); Isar.sync_main ()) else isa_restart ());
wenzelm@12778
   466
wenzelm@12778
   467
wenzelm@12778
   468
wenzelm@12778
   469
(** generate keyword classification file **)
wenzelm@12778
   470
wenzelm@12778
   471
local
wenzelm@12778
   472
wenzelm@12778
   473
val regexp_meta = explode ".*+?[]^$";
wenzelm@12778
   474
val regexp_quote = implode o map (fn c => if c mem regexp_meta then "\\\\" ^ c else c) o explode;
wenzelm@12778
   475
wenzelm@12778
   476
fun defconst name strs =
wenzelm@12778
   477
  "\n(defconst isar-keywords-" ^ name ^
wenzelm@12778
   478
  "\n  '(" ^ space_implode "\n    " (map (quote o regexp_quote) strs) ^ "))\n";
wenzelm@12778
   479
wenzelm@12778
   480
fun make_elisp_commands commands kind =
wenzelm@12778
   481
  defconst kind (mapfilter (fn (c, _, k, _) => if k = kind then Some c else None) commands);
wenzelm@12778
   482
wenzelm@12778
   483
fun make_elisp_syntax (keywords, commands) =
wenzelm@12778
   484
  ";;\n\
wenzelm@12778
   485
  \;; Keyword classification tables for Isabelle/Isar.\n\
wenzelm@12778
   486
  \;; This file was generated by " ^ Session.name () ^ " -- DO NOT EDIT!\n\
wenzelm@12778
   487
  \;;\n\
wenzelm@12778
   488
  \;; $" ^ "Id$\n\
wenzelm@12778
   489
  \;;\n" ^
wenzelm@12778
   490
  defconst "major" (map #1 commands) ^
wenzelm@14675
   491
  defconst "minor" (filter Syntax.is_ascii_identifier keywords) ^
wenzelm@12778
   492
  implode (map (make_elisp_commands commands) OuterSyntax.Keyword.kinds) ^
wenzelm@12778
   493
  "\n(provide 'isar-keywords)\n";
wenzelm@12778
   494
wenzelm@12778
   495
in
wenzelm@12778
   496
wenzelm@12778
   497
fun write_keywords s =
wenzelm@12778
   498
  (init_outer_syntax ();
wenzelm@12778
   499
    File.write (Path.unpack ("isar-keywords" ^ (if s = "" then "" else "-" ^ s) ^".el"))
wenzelm@12778
   500
      (make_elisp_syntax (OuterSyntax.dest_keywords (), OuterSyntax.dest_parsers ())));
wenzelm@12778
   501
wenzelm@12778
   502
end;
wenzelm@12778
   503
wenzelm@12778
   504
end;