src/Pure/Isar/isar_document.ML
author wenzelm
Tue, 13 Jan 2009 22:20:49 +0100
changeset 29468 c9bb4e06d173
parent 29467 d98fe0c504a8
child 29484 15863d782ae3
permissions -rw-r--r--
misc internal rearrangements; fold_entries: really start from start, or optional position; added find_first_entries, find_first_entries; insert_entry: always invalidate next state; added refresh_states (partial version);
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
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    16
end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    17
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    18
structure IsarDocument: ISAR_DOCUMENT =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    19
struct
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    20
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    21
29459
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
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    24
type document_id = string;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    25
type command_id = string;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    26
type state_id = string;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    27
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    28
fun new_id () = "isabelle:" ^ 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
(** execution states **)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    35
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    36
(* command status *)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    37
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    38
datatype status =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    39
  Unprocessed |
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    40
  Running of Toplevel.state option future |
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    41
  Failed |
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    42
  Finished of Toplevel.state;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    43
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    44
fun markup_status Unprocessed = Markup.unprocessed
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    45
  | markup_status (Running future) = Markup.running (Task_Queue.str_of_task (Future.task_of future))
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    46
  | markup_status Failed = Markup.failed
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    47
  | markup_status (Finished _) = Markup.finished;
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    48
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    49
fun update_status retry tr state status =
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    50
  (case status of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    51
    Unprocessed => SOME (Running (Future.fork_pri 1 (fn () =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    52
      (case Toplevel.transition true tr state of
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    53
        NONE => (Toplevel.error_msg tr (ERROR "Cannot terminate here!", ""); NONE)
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    54
      | SOME (_, SOME err) => (Toplevel.error_msg tr err; NONE)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    55
      | SOME (state', NONE) => SOME state'))))
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    56
  | Running future =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    57
      (case Future.peek future of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    58
        NONE => NONE
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    59
      | SOME (Exn.Result NONE) => SOME Failed
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    60
      | SOME (Exn.Result (SOME state')) => SOME (Finished state')
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    61
      | SOME (Exn.Exn exn) => (Toplevel.error_msg tr (exn, ""); SOME Failed))
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    62
  | Failed => if retry then SOME Unprocessed else NONE
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    63
  | _ => NONE);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    64
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    65
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    66
(* state *)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    67
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    68
datatype state = State of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    69
 {prev: state_id option,
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    70
  command: command_id,
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    71
  status: status};
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    72
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    73
fun make_state prev command status = State {prev = prev, command = command, status = status};
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    74
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    75
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    76
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    77
(** documents **)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    78
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    79
(* command entries *)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    80
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    81
datatype entry = Entry of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    82
 {prev: command_id option,
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    83
  next: command_id option,
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
    84
  state: state_id option};
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    85
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    86
fun make_entry prev next state = Entry {prev = prev, next = next, state = state};
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
    87
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    88
fun the_entry entries (id: command_id) =
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    89
  (case Symtab.lookup entries id of
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    90
    NONE => err_undef "document entry" id
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    91
  | SOME (Entry entry) => entry);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    92
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    93
fun put_entry (id: command_id, entry: entry) = Symtab.update (id, entry);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    94
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    95
fun map_entry (id: command_id) f entries =
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    96
  let
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    97
    val {prev, next, state} = the_entry entries id;
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    98
    val (prev', next', state') = f (prev, next, state);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
    99
  in put_entry (id, make_entry prev' next' state') entries end;
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   100
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   101
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   102
(* document *)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   103
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   104
datatype document = Document of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   105
 {dir: Path.T,                    (*master directory*)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   106
  name: string,                   (*theory name*)
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   107
  start: command_id,              (*empty start command*)
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   108
  entries: entry Symtab.table};   (*unique command entries indexed by command_id*)
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   109
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   110
fun make_document dir name start entries =
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   111
  Document {dir = dir, name = name, start = start, entries = entries};
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   112
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   113
fun map_entries f (Document {dir, name, start, entries}) =
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   114
  make_document dir name start (f entries);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   115
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   116
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   117
(* iterating entries *)
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   118
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   119
fun fold_entries opt_id f (Document {start, entries, ...}) =
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   120
  let
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   121
    fun apply NONE x = x
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   122
      | apply (SOME id) x = apply (#next (the_entry entries id)) (f id x);
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   123
  in if is_some opt_id then apply opt_id else apply (SOME start) end;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   124
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   125
fun get_first_entries opt_id f (Document {start, entries, ...}) =
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   126
  let
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   127
    fun get NONE = NONE
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   128
      | get (SOME id) = (case f id of NONE => get (#next (the_entry entries id)) | some => some);
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   129
  in if is_some opt_id then get opt_id else get (SOME start) end;
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   130
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   131
fun find_first_entries opt_id P =
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   132
  get_first_entries opt_id (fn x => if P x then SOME x else NONE);
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   133
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   134
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   135
(* modify entries *)
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   136
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   137
fun insert_entry (id: command_id, id2: command_id) = map_entries (fn entries =>
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   138
  let val {prev, next, state} = the_entry entries id in
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   139
    entries |>
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   140
      (case next of
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   141
        NONE => put_entry (id2, make_entry (SOME id) NONE NONE)
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   142
      | SOME id3 =>
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   143
          put_entry (id, make_entry prev (SOME id2) state) #>
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   144
          put_entry (id2, make_entry (SOME id) (SOME id3) NONE) #>
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   145
          put_entry (id3, make_entry (SOME id2) (#next (the_entry entries id3)) NONE))
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   146
  end);
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   147
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   148
fun delete_after (id: command_id) = map_entries (fn entries =>
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   149
  let val {prev, next, state} = the_entry entries id in
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   150
    entries |>
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   151
      (case next of
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   152
        NONE => error ("Missing next entry: " ^ quote id)
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   153
      | SOME id2 =>
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   154
          (case #next (the_entry entries id2) of
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   155
            NONE => put_entry (id, make_entry prev NONE state)
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   156
          | SOME id3 =>
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   157
              put_entry (id, make_entry prev (SOME id3) state) #>
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   158
              put_entry (id3, make_entry (SOME id) (#next (the_entry entries id3)) NONE)))
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   159
  end);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   160
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   161
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   162
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   163
(** global configuration **)
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
local
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   166
  val global_states = ref (Symtab.empty: state Symtab.table);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   167
  val global_commands = ref (Symtab.empty: Toplevel.transition Symtab.table);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   168
  val global_documents = ref (Symtab.empty: document Symtab.table);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   169
in
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   170
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   171
fun change_states f = NAMED_CRITICAL "Isar" (fn () => change global_states f);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   172
fun get_states () = NAMED_CRITICAL "Isar" (fn () => ! global_states);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   173
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   174
fun change_commands f = NAMED_CRITICAL "Isar" (fn () => change global_commands f);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   175
fun get_commands () = NAMED_CRITICAL "Isar" (fn () => ! global_commands);
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
fun change_documents f = NAMED_CRITICAL "Isar" (fn () => change global_documents f);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   178
fun get_documents () = NAMED_CRITICAL "Isar" (fn () => ! global_documents);
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   179
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   180
fun init () = NAMED_CRITICAL "Isar" (fn () =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   181
 (global_states := Symtab.empty;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   182
  global_commands := Symtab.empty;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   183
  global_documents := Symtab.empty));
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   184
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   185
end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   186
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   187
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   188
fun define_state (id: state_id) state =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   189
  change_states (Symtab.update_new (id, state))
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   190
    handle Symtab.DUP dup => err_dup "state" dup;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   191
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   192
fun the_state (id: state_id) =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   193
  (case Symtab.lookup (get_states ()) id of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   194
    NONE => err_undef "state" id
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   195
  | SOME (State state) => state);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   196
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   197
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   198
fun define_command id tr =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   199
  change_commands (Symtab.update_new (id, Toplevel.put_id id tr))
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   200
    handle Symtab.DUP dup => err_dup ("command " ^ Toplevel.name_of tr) dup;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   201
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   202
fun the_command (id: command_id) =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   203
  (case Symtab.lookup (get_commands ()) id of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   204
    NONE => err_undef "command" id
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   205
  | SOME tr => tr);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   206
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   207
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   208
fun define_document (id: document_id) document =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   209
  change_documents (Symtab.update_new (id, document))
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   210
    handle Symtab.DUP dup => err_dup "document" dup;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   211
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   212
fun the_document (id: document_id) =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   213
  (case Symtab.lookup (get_documents ()) id of
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   214
    NONE => err_undef "document" id
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   215
  | SOME (Document doc) => doc);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   216
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   217
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   218
(* begin/end document *)
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   219
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   220
fun begin_document (id: document_id) path =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   221
  let
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   222
    val (dir, name) = ThyLoad.split_thy_path path;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   223
    val _ = define_command id Toplevel.empty;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   224
    val _ = define_state id (make_state NONE id (Finished Toplevel.toplevel));
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   225
    val entries = Symtab.make [(id, make_entry NONE NONE (SOME id))];
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   226
    val _ = define_document id (make_document dir name id entries);
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   227
  in () end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   228
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   229
fun end_document (id: document_id) = error "FIXME";
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   230
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   231
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   232
(* document editing *)
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   233
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   234
fun refresh_states old_document new_document =
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   235
  let
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   236
    val Document {entries = old_entries, ...} = old_document;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   237
    val Document {entries = new_entries, ...} = new_document;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   238
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   239
    fun is_changed id =
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   240
      (case try (the_entry new_entries) id of
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   241
        SOME {state = SOME _, ...} => false
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   242
      | _ => true);
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   243
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   244
    fun cancel_state id () =
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   245
      (case the_entry old_entries id of
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   246
        {state = SOME state_id, ...} =>
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   247
          (case the_state state_id of
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   248
            {status = Running future, ...} => Future.cancel future
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   249
          | _ => ())
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   250
      | _ => ());
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   251
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   252
    fun new_state id (prev_state_id, new_states) =
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   253
      let
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   254
        val state_id = new_id ();
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   255
        val state = make_state prev_state_id id Unprocessed;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   256
        val _ = define_state state_id state;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   257
      in (SOME state_id, (state_id, state) :: new_states) end;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   258
  in
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   259
    (case find_first_entries NONE is_changed old_document of
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   260
      NONE => new_document
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   261
    | SOME id =>
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   262
        let
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   263
          val _ = fold_entries (SOME id) cancel_state old_document ();
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   264
          val (_, new_states) = fold_entries (SOME id) new_state new_document (NONE, []);
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   265
          (* FIXME update states *)
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   266
        in new_document end)
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   267
  end;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   268
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   269
fun edit_document (id: document_id) (id': document_id) edits =
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   270
  let
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   271
    val document = Document (the_document id);
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   272
    val document' =
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   273
      document
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   274
      |> fold (fn (id, SOME id2) => insert_entry (id, id2) | (id, NONE) => delete_after id) edits
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   275
      |> refresh_states document;
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   276
    val _ = define_document id' document';
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   277
  in () end;
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
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   280
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   281
(** concrete syntax **)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   282
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   283
local structure P = OuterParse structure V = ValueParse in
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   284
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   285
val _ =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   286
  OuterSyntax.internal_command "Isar.define_command"
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   287
    (P.string -- P.string >> (fn (id, text) =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   288
      Toplevel.imperative (fn () =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   289
        define_command id (OuterSyntax.prepare_command (Position.id id) text))));
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 _ =
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   292
  OuterSyntax.internal_command "Isar.begin_document"
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   293
    (P.string -- P.string >> (fn (id, path) =>
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   294
      Toplevel.imperative (fn () => begin_document id (Path.explode path))));
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   295
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   296
val _ =
29468
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   297
  OuterSyntax.internal_command "Isar.end_document"
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   298
    (P.string >> (fn id => Toplevel.imperative (fn () => end_document id)));
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   299
c9bb4e06d173 misc internal rearrangements;
wenzelm
parents: 29467
diff changeset
   300
val _ =
29459
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   301
  OuterSyntax.internal_command "Isar.edit_document"
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   302
    (P.string -- P.string -- V.list (P.string -- (P.string >> SOME) || P.string >> rpair NONE)
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   303
      >> (fn ((id, new_id), edits) => Toplevel.imperative (fn () => end_document id new_id edits)));
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   304
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   305
end;
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   306
8acad4f0a727 added Isar/isar_document.ML: Interactive Isar documents.
wenzelm
parents:
diff changeset
   307
end;
29467
d98fe0c504a8 replaced sys_error by plain error;
wenzelm
parents: 29459
diff changeset
   308