src/Pure/Isar/isar_document.ML
author wenzelm
Sat, 17 Oct 2009 17:18:59 +0200
changeset 32971 55ba9b6648ef
parent 32793 24ba50c14ec5
child 33223 d27956b4d3b4
permissions -rw-r--r--
less pervasive names;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/Isar/isar_document.ML
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     3
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     4
Interactive Isar documents.
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     5
*)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     6
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     7
signature ISAR_DOCUMENT =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     8
sig
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
     9
  type state_id = string
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    10
  type command_id = string
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    11
  type document_id = string
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    12
  val define_command: command_id -> Toplevel.transition -> unit
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    13
  val begin_document: document_id -> Path.T -> unit
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    14
  val end_document: document_id -> unit
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    15
  val edit_document: document_id -> document_id -> (command_id * command_id option) list -> unit
32793
24ba50c14ec5 actually perform Isar_Document.init on startup;
wenzelm
parents: 32738
diff changeset
    16
  val init: unit -> unit
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    17
end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    18
32467
4dab52ca1402 modernized Isar_Document;
wenzelm
parents: 31443
diff changeset
    19
structure Isar_Document: ISAR_DOCUMENT =
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    20
struct
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    21
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    22
(* unique identifiers *)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    23
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    24
type state_id = string;
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    25
type command_id = string;
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    26
type document_id = string;
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    27
31443
c23663825e23 uniform (short) ids on both sides;
wenzelm
parents: 29520
diff changeset
    28
fun make_id () = "i" ^ serial_string ();
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    29
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    30
fun err_dup kind id = error ("Duplicate " ^ kind ^ ": " ^ quote id);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    31
fun err_undef kind id = error ("Unknown " ^ kind ^ ": " ^ quote id);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    32
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    33
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    34
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    35
(** documents **)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    36
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    37
(* command entries *)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    38
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    39
datatype entry = Entry of {next: command_id option, state: state_id option};
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    40
fun make_entry next state = Entry {next = next, state = state};
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    41
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    42
fun the_entry entries (id: command_id) =
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    43
  (case Symtab.lookup entries id of
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    44
    NONE => err_undef "document entry" id
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    45
  | SOME (Entry entry) => entry);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    46
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    47
fun put_entry (id: command_id, entry: entry) = Symtab.update (id, entry);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    48
29489
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
    49
fun put_entry_state (id: command_id) state entries =
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
    50
  let val {next, ...} = the_entry entries id
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
    51
  in put_entry (id, make_entry next state) entries end;
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
    52
29490
wenzelm
parents: 29489
diff changeset
    53
fun reset_entry_state id = put_entry_state id NONE;
wenzelm
parents: 29489
diff changeset
    54
fun set_entry_state (id, state_id) = put_entry_state id (SOME state_id);
29489
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
    55
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
    56
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    57
(* document *)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    58
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    59
datatype document = Document of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    60
 {dir: Path.T,                    (*master directory*)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    61
  name: string,                   (*theory name*)
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    62
  start: command_id,              (*empty start command*)
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    63
  entries: entry Symtab.table};   (*unique command entries indexed by command_id*)
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    64
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    65
fun make_document dir name start entries =
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    66
  Document {dir = dir, name = name, start = start, entries = entries};
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    67
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    68
fun map_entries f (Document {dir, name, start, entries}) =
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    69
  make_document dir name start (f entries);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    70
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    71
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    72
(* iterate entries *)
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    73
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
    74
fun fold_entries id0 f (Document {entries, ...}) =
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    75
  let
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    76
    fun apply NONE x = x
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
    77
      | apply (SOME id) x =
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
    78
          let val entry = the_entry entries id
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
    79
          in apply (#next entry) (f (id, entry) x) end;
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
    80
  in if Symtab.defined entries id0 then apply (SOME id0) else I end;
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    81
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
    82
fun first_entry P (Document {start, entries, ...}) =
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    83
  let
29517
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
    84
    fun first _ NONE = NONE
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
    85
      | first prev (SOME id) =
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
    86
          let val entry = the_entry entries id
29519
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
    87
          in if P (id, entry) then SOME (prev, id, entry) else first (SOME id) (#next entry) end;
29517
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
    88
  in first NONE (SOME start) end;
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    89
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    90
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    91
(* modify entries *)
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    92
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    93
fun insert_after (id: command_id) (id2: command_id) = map_entries (fn entries =>
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    94
  let val {next, state} = the_entry entries id in
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    95
    entries
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    96
    |> put_entry (id, make_entry (SOME id2) state)
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
    97
    |> put_entry (id2, make_entry next NONE)
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    98
  end);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    99
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   100
fun delete_after (id: command_id) = map_entries (fn entries =>
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   101
  let val {next, state} = the_entry entries id in
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   102
    (case next of
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   103
      NONE => error ("No next entry to delete: " ^ quote id)
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   104
    | SOME id2 =>
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   105
        entries |>
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   106
          (case #next (the_entry entries id2) of
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   107
            NONE => put_entry (id, make_entry NONE state)
29490
wenzelm
parents: 29489
diff changeset
   108
          | SOME id3 => put_entry (id, make_entry (SOME id3) state) #> reset_entry_state id3))
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   109
  end);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   110
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   111
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   112
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   113
(** global configuration **)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   114
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   115
local
32738
15bb09ca0378 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32573
diff changeset
   116
  val global_states = Unsynchronized.ref (Symtab.empty: Toplevel.state option future Symtab.table);
15bb09ca0378 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32573
diff changeset
   117
  val global_commands = Unsynchronized.ref (Symtab.empty: Toplevel.transition Symtab.table);
15bb09ca0378 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32573
diff changeset
   118
  val global_documents = Unsynchronized.ref (Symtab.empty: document Symtab.table);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   119
in
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   120
32738
15bb09ca0378 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32573
diff changeset
   121
fun change_states f = NAMED_CRITICAL "Isar" (fn () => Unsynchronized.change global_states f);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   122
fun get_states () = NAMED_CRITICAL "Isar" (fn () => ! global_states);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   123
32738
15bb09ca0378 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32573
diff changeset
   124
fun change_commands f = NAMED_CRITICAL "Isar" (fn () => Unsynchronized.change global_commands f);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   125
fun get_commands () = NAMED_CRITICAL "Isar" (fn () => ! global_commands);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   126
32738
15bb09ca0378 explicit indication of Unsynchronized.ref;
wenzelm
parents: 32573
diff changeset
   127
fun change_documents f = NAMED_CRITICAL "Isar" (fn () => Unsynchronized.change global_documents f);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   128
fun get_documents () = NAMED_CRITICAL "Isar" (fn () => ! global_documents);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   129
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   130
fun init () = NAMED_CRITICAL "Isar" (fn () =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   131
 (global_states := Symtab.empty;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   132
  global_commands := Symtab.empty;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   133
  global_documents := Symtab.empty));
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   134
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   135
end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   136
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   137
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   138
(* state *)
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   139
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   140
val empty_state = Future.value (SOME Toplevel.toplevel);
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   141
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   142
fun define_state (id: state_id) =
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   143
  change_states (Symtab.update_new (id, empty_state))
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   144
    handle Symtab.DUP dup => err_dup "state" dup;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   145
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   146
fun put_state (id: state_id) state = change_states (Symtab.update (id, state));
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   147
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   148
fun the_state (id: state_id) =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   149
  (case Symtab.lookup (get_states ()) id of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   150
    NONE => err_undef "state" id
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   151
  | SOME state => state);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   152
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   153
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   154
(* command *)
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   155
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   156
fun define_command id tr =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   157
  change_commands (Symtab.update_new (id, Toplevel.put_id id tr))
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   158
    handle Symtab.DUP dup => err_dup "command" dup;
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   159
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   160
fun the_command (id: command_id) =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   161
  (case Symtab.lookup (get_commands ()) id of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   162
    NONE => err_undef "command" id
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   163
  | SOME tr => tr);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   164
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   165
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   166
(* document *)
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   167
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   168
fun define_document (id: document_id) document =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   169
  change_documents (Symtab.update_new (id, document))
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   170
    handle Symtab.DUP dup => err_dup "document" dup;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   171
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   172
fun the_document (id: document_id) =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   173
  (case Symtab.lookup (get_documents ()) id of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   174
    NONE => err_undef "document" id
29517
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
   175
  | SOME document => document);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   176
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   177
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   178
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   179
(** main operations **)
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   180
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   181
(* begin/end document *)
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   182
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   183
fun begin_document (id: document_id) path =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   184
  let
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   185
    val (dir, name) = ThyLoad.split_thy_path path;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   186
    val _ = define_command id Toplevel.empty;
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   187
    val _ = define_state id;
29484
15863d782ae3 misc cleanup and simplification;
wenzelm
parents: 29468
diff changeset
   188
    val entries = Symtab.make [(id, make_entry NONE (SOME id))];
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   189
    val _ = define_document id (make_document dir name id entries);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   190
  in () end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   191
29519
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   192
fun end_document (id: document_id) =
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   193
  let
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   194
    val document as Document {name, ...} = the_document id;
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   195
    val end_state =
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   196
      the_state (the (#state (#3 (the
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   197
        (first_entry (fn (_, {next, ...}) => is_none next) document)))));
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   198
    val _ =
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   199
      Future.fork_deps [end_state] (fn () =>
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   200
        (case Future.join end_state of
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   201
          SOME st =>
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   202
           (Toplevel.run_command name (Toplevel.put_id id (Toplevel.commit_exit Position.none)) st;
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   203
            ThyInfo.touch_child_thys name;
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   204
            ThyInfo.register_thy name)
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   205
        | NONE => error ("Failed to finish theory " ^ quote name)));
29519
4dff3b11f64d provide end_document;
wenzelm
parents: 29517
diff changeset
   206
  in () end;
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   207
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   208
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   209
(* document editing *)
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   210
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   211
local
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   212
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   213
fun is_changed entries' (id, {next = _, state}) =
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   214
  (case try (the_entry entries') id of
29517
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
   215
    NONE => true
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
   216
  | SOME {next = _, state = state'} => state' <> state);
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   217
29517
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
   218
fun new_state name (id, _) (state_id, updates) =
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   219
  let
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   220
    val state_id' = make_id ();
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   221
    val _ = define_state state_id';
29517
d7648f30f923 run command: check theory name for init;
wenzelm
parents: 29507
diff changeset
   222
    val tr = Toplevel.put_id state_id' (the_command id);
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   223
    fun make_state' () =
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   224
      let
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   225
        val state = the_state state_id;
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   226
        val state' =
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   227
          Future.fork_deps [state] (fn () =>
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   228
            (case Future.join state of
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   229
              NONE => NONE
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   230
            | SOME st => Toplevel.run_command name tr st));
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   231
      in put_state state_id' state' end;
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   232
  in (state_id', ((id, state_id'), make_state') :: updates) end;
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   233
29489
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
   234
fun report_updates _ [] = ()
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
   235
  | report_updates (document_id: document_id) updates =
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
   236
      implode (map (fn (id, state_id) => Markup.markup (Markup.edit id state_id) "") updates)
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
   237
      |> Markup.markup (Markup.edits document_id)
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
   238
      |> Output.status;
5dfe03f423c4 edit_document: proper edits/edit markup, including the document id;
wenzelm
parents: 29487
diff changeset
   239
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   240
in
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   241
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   242
fun edit_document (old_id: document_id) (new_id: document_id) edits =
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   243
  let
29520
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   244
    val old_document as Document {name, entries = old_entries, ...} = the_document old_id;
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   245
    val new_document as Document {entries = new_entries, ...} = old_document
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   246
      |> fold (fn (id, SOME id2) => insert_after id id2 | (id, NONE) => delete_after id) edits;
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   247
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   248
    fun cancel_old id = fold_entries id
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   249
      (fn (_, {state = SOME state_id, ...}) => K (Future.cancel (the_state state_id)) | _ => K ())
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   250
      old_document ();
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   251
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   252
    val (updates, new_document') =
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   253
      (case first_entry (is_changed old_entries) new_document of
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   254
        NONE =>
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   255
          (case first_entry (is_changed new_entries) old_document of
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   256
            NONE => ([], new_document)
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   257
          | SOME (_, id, _) => (cancel_old id; ([], new_document)))
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   258
      | SOME (prev, id, _) =>
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   259
          let
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   260
            val _ = cancel_old id;
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   261
            val prev_state_id = the (#state (the_entry new_entries (the prev)));
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   262
            val (_, updates) = fold_entries id (new_state name) new_document (prev_state_id, []);
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   263
            val new_document' = new_document |> map_entries (fold (set_entry_state o #1) updates);
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   264
          in (rev updates, new_document') end);
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   265
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   266
    val _ = define_document new_id new_document';
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   267
    val _ = report_updates new_id (map #1 updates);
7402322256b0 define_state: use empty_state;
wenzelm
parents: 29519
diff changeset
   268
    val _ = List.app (fn (_, run) => run ()) updates;
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   269
  in () end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   270
29507
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   271
end;
1684a9c4554f fold_entries: non-optional start, permissive;
wenzelm
parents: 29499
diff changeset
   272
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   273
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   274
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   275
(** concrete syntax **)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   276
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   277
local structure P = OuterParse structure V = ValueParse in
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   278
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   279
val _ =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   280
  OuterSyntax.internal_command "Isar.define_command"
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   281
    (P.string -- P.string >> (fn (id, text) =>
32573
62b5b538408d Isar.define_command: identify transaction;
wenzelm
parents: 32467
diff changeset
   282
      Toplevel.position (Position.id_only id) o
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   283
      Toplevel.imperative (fn () =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   284
        define_command id (OuterSyntax.prepare_command (Position.id id) text))));
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   285
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   286
val _ =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   287
  OuterSyntax.internal_command "Isar.begin_document"
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   288
    (P.string -- P.string >> (fn (id, path) =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   289
      Toplevel.imperative (fn () => begin_document id (Path.explode path))));
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   290
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   291
val _ =
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   292
  OuterSyntax.internal_command "Isar.end_document"
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   293
    (P.string >> (fn id => Toplevel.imperative (fn () => end_document id)));
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   294
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   295
val _ =
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   296
  OuterSyntax.internal_command "Isar.edit_document"
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   297
    (P.string -- P.string -- V.list (P.string -- (P.string >> SOME) || P.string >> rpair NONE)
29499
2819ba5f0c32 command 'Isar.edit_document': actually invoke edit_document;
wenzelm
parents: 29490
diff changeset
   298
      >> (fn ((id, new_id), edits) => Toplevel.imperative (fn () => edit_document id new_id edits)));
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   299
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   300
end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   301
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   302
end;
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   303