src/Pure/PIDE/command.ML
changeset 58923 cb9b69cca999
parent 58862 63a16e98cc14
child 58928 23d0ffd48006
equal deleted inserted replaced
58922:1f500b18c4c6 58923:cb9b69cca999
     6 
     6 
     7 signature COMMAND =
     7 signature COMMAND =
     8 sig
     8 sig
     9   type blob = (string * (SHA1.digest * string list) option) Exn.result
     9   type blob = (string * (SHA1.digest * string list) option) Exn.result
    10   val read_file: Path.T -> Position.T -> Path.T -> Token.file
    10   val read_file: Path.T -> Position.T -> Path.T -> Token.file
    11   val read: (unit -> theory) -> Path.T -> blob list -> Token.T list -> Toplevel.transition
    11   val read: Keyword.keywords -> Path.T-> (unit -> theory) -> blob list -> Token.T list ->
       
    12     Toplevel.transition
    12   type eval
    13   type eval
    13   val eval_eq: eval * eval -> bool
    14   val eval_eq: eval * eval -> bool
    14   val eval_running: eval -> bool
    15   val eval_running: eval -> bool
    15   val eval_finished: eval -> bool
    16   val eval_finished: eval -> bool
    16   val eval_result_state: eval -> Toplevel.state
    17   val eval_result_state: eval -> Toplevel.state
    17   val eval: (unit -> theory) -> Path.T -> blob list -> Token.T list -> eval -> eval
    18   val eval: Keyword.keywords -> Path.T -> (unit -> theory) -> blob list -> Token.T list ->
       
    19     eval -> eval
    18   type print
    20   type print
    19   val print: bool -> (string * string list) list -> string ->
    21   val print: bool -> (string * string list) list -> Keyword.keywords -> string ->
    20     eval -> print list -> print list option
    22     eval -> print list -> print list option
    21   type print_fn = Toplevel.transition -> Toplevel.state -> unit
    23   type print_fn = Toplevel.transition -> Toplevel.state -> unit
    22   type print_function =
    24   type print_function =
    23     {command_name: string, args: string list, exec_id: Document_ID.exec} ->
    25     {keywords: Keyword.keywords, command_name: string, args: string list, exec_id: Document_ID.exec} ->
    24       {delay: Time.time option, pri: int, persistent: bool, strict: bool, print_fn: print_fn} option
    26       {delay: Time.time option, pri: int, persistent: bool, strict: bool, print_fn: print_fn} option
    25   val print_function: string -> print_function -> unit
    27   val print_function: string -> print_function -> unit
    26   val no_print_function: string -> unit
    28   val no_print_function: string -> unit
    27   type exec = eval * print list
    29   type exec = eval * print list
    28   val no_exec: exec
    30   val no_exec: exec
   118       (case Position.get_id (Position.thread_data ()) of
   120       (case Position.get_id (Position.thread_data ()) of
   119         NONE => I
   121         NONE => I
   120       | SOME exec_id => Position.put_id exec_id);
   122       | SOME exec_id => Position.put_id exec_id);
   121   in {src_path = src_path, lines = lines, digest = digest, pos = file_pos} end
   123   in {src_path = src_path, lines = lines, digest = digest, pos = file_pos} end
   122 
   124 
   123 fun resolve_files master_dir blobs toks =
   125 fun resolve_files keywords master_dir blobs toks =
   124   (case Outer_Syntax.parse_spans toks of
   126   (case Outer_Syntax.parse_spans toks of
   125     [span] => span
   127     [span] => span
   126       |> Command_Span.resolve_files (fn cmd => fn (path, pos) =>
   128       |> Command_Span.resolve_files keywords (fn cmd => fn (path, pos) =>
   127         let
   129         let
   128           fun make_file src_path (Exn.Res (file_node, NONE)) =
   130           fun make_file src_path (Exn.Res (file_node, NONE)) =
   129                 Exn.interruptible_capture (fn () =>
   131                 Exn.interruptible_capture (fn () =>
   130                   read_file_node file_node master_dir pos src_path) ()
   132                   read_file_node file_node master_dir pos src_path) ()
   131             | make_file src_path (Exn.Res (file_node, SOME (digest, lines))) =
   133             | make_file src_path (Exn.Res (file_node, SOME (digest, lines))) =
   132                (Position.reports [(pos, Markup.language_path), (pos, Markup.path file_node)];
   134                (Position.reports [(pos, Markup.language_path), (pos, Markup.path file_node)];
   133                 Exn.Res (blob_file src_path lines digest file_node))
   135                 Exn.Res (blob_file src_path lines digest file_node))
   134             | make_file _ (Exn.Exn e) = Exn.Exn e;
   136             | make_file _ (Exn.Exn e) = Exn.Exn e;
   135           val src_paths = Keyword.command_files cmd path;
   137           val src_paths = Keyword.command_files keywords cmd path;
   136         in
   138         in
   137           if null blobs then
   139           if null blobs then
   138             map2 make_file src_paths (map (K (Exn.Res ("", NONE))) src_paths)
   140             map2 make_file src_paths (map (K (Exn.Res ("", NONE))) src_paths)
   139           else if length src_paths = length blobs then
   141           else if length src_paths = length blobs then
   140             map2 make_file src_paths blobs
   142             map2 make_file src_paths blobs
   143       |> Command_Span.content
   145       |> Command_Span.content
   144   | _ => toks);
   146   | _ => toks);
   145 
   147 
   146 in
   148 in
   147 
   149 
   148 fun read init master_dir blobs span =
   150 fun read keywords master_dir init blobs span =
   149   let
   151   let
   150     val syntax = #2 (Outer_Syntax.get_syntax ());
   152     val syntax = #2 (Outer_Syntax.get_syntax ());
   151     val command_reports = Outer_Syntax.command_reports syntax;
   153     val command_reports = Outer_Syntax.command_reports syntax;
   152 
   154 
   153     val proper_range = Token.range_of (#1 (take_suffix Token.is_improper span));
   155     val proper_range = Token.range_of (#1 (take_suffix Token.is_improper span));
   159     val (is_malformed, token_reports) = Thy_Syntax.reports_of_tokens span;
   161     val (is_malformed, token_reports) = Thy_Syntax.reports_of_tokens span;
   160     val _ = Position.reports_text (token_reports @ maps command_reports span);
   162     val _ = Position.reports_text (token_reports @ maps command_reports span);
   161   in
   163   in
   162     if is_malformed then Toplevel.malformed pos "Malformed command syntax"
   164     if is_malformed then Toplevel.malformed pos "Malformed command syntax"
   163     else
   165     else
   164       (case Outer_Syntax.read_spans syntax (resolve_files master_dir blobs span) of
   166       (case Outer_Syntax.read_spans syntax (resolve_files keywords master_dir blobs span) of
   165         [tr] => Toplevel.modify_init init tr
   167         [tr] => Toplevel.modify_init init tr
   166       | [] => Toplevel.ignored (#1 (Token.range_of span))
   168       | [] => Toplevel.ignored (#1 (Token.range_of span))
   167       | _ => Toplevel.malformed (#1 proper_range) "Exactly one command expected")
   169       | _ => Toplevel.malformed (#1 proper_range) "Exactly one command expected")
   168       handle ERROR msg => Toplevel.malformed (#1 proper_range) msg
   170       handle ERROR msg => Toplevel.malformed (#1 proper_range) msg
   169   end;
   171   end;
   189 fun eval_result (Eval {eval_process, ...}) = memo_result eval_process;
   191 fun eval_result (Eval {eval_process, ...}) = memo_result eval_process;
   190 val eval_result_state = #state o eval_result;
   192 val eval_result_state = #state o eval_result;
   191 
   193 
   192 local
   194 local
   193 
   195 
   194 fun reset_state tr st0 = Toplevel.setmp_thread_position tr (fn () =>
   196 fun reset_state keywords tr st0 = Toplevel.setmp_thread_position tr (fn () =>
   195   let
   197   let
   196     val name = Toplevel.name_of tr;
   198     val name = Toplevel.name_of tr;
   197     val res =
   199     val res =
   198       if Keyword.is_theory_body name then Toplevel.reset_theory st0
   200       if Keyword.is_theory_body keywords name then Toplevel.reset_theory st0
   199       else if Keyword.is_proof name then Toplevel.reset_proof st0
   201       else if Keyword.is_proof keywords name then Toplevel.reset_proof st0
   200       else NONE;
   202       else NONE;
   201   in
   203   in
   202     (case res of
   204     (case res of
   203       NONE => st0
   205       NONE => st0
   204     | SOME st => (Output.error_message (Toplevel.type_error tr st0 ^ " -- using reset state"); st))
   206     | SOME st => (Output.error_message (Toplevel.type_error tr st0 ^ " -- using reset state"); st))
   205   end) ();
   207   end) ();
   206 
   208 
   207 fun run int tr st =
   209 fun run keywords int tr st =
   208   if Goal.future_enabled 1 andalso Keyword.is_diag (Toplevel.name_of tr) then
   210   if Goal.future_enabled 1 andalso Keyword.is_diag keywords (Toplevel.name_of tr) then
   209     (Execution.fork {name = "Toplevel.diag", pos = Toplevel.pos_of tr, pri = ~1}
   211     (Execution.fork {name = "Toplevel.diag", pos = Toplevel.pos_of tr, pri = ~1}
   210       (fn () => Toplevel.command_exception int tr st); ([], SOME st))
   212       (fn () => Toplevel.command_exception int tr st); ([], SOME st))
   211   else Toplevel.command_errors int tr st;
   213   else Toplevel.command_errors int tr st;
   212 
   214 
   213 fun check_cmts span tr st' =
   215 fun check_cmts span tr st' =
   228 fun proof_status tr st =
   230 fun proof_status tr st =
   229   (case try Toplevel.proof_of st of
   231   (case try Toplevel.proof_of st of
   230     SOME prf => status tr (Proof.status_markup prf)
   232     SOME prf => status tr (Proof.status_markup prf)
   231   | NONE => ());
   233   | NONE => ());
   232 
   234 
   233 fun eval_state span tr ({malformed, state, ...}: eval_state) =
   235 fun eval_state keywords span tr ({malformed, state, ...}: eval_state) =
   234   if malformed then
   236   if malformed then
   235     {failed = true, malformed = malformed, command = tr, state = Toplevel.toplevel}
   237     {failed = true, malformed = malformed, command = tr, state = Toplevel.toplevel}
   236   else
   238   else
   237     let
   239     let
   238       val _ = Multithreading.interrupted ();
   240       val _ = Multithreading.interrupted ();
   239 
   241 
   240       val malformed' = Toplevel.is_malformed tr;
   242       val malformed' = Toplevel.is_malformed tr;
   241       val st = reset_state tr state;
   243       val st = reset_state keywords tr state;
   242 
   244 
   243       val _ = status tr Markup.running;
   245       val _ = status tr Markup.running;
   244       val (errs1, result) = run true tr st;
   246       val (errs1, result) = run keywords true tr st;
   245       val errs2 = (case result of NONE => [] | SOME st' => check_cmts span tr st');
   247       val errs2 = (case result of NONE => [] | SOME st' => check_cmts span tr st');
   246       val errs = errs1 @ errs2;
   248       val errs = errs1 @ errs2;
   247       val _ = List.app (Future.error_message (Toplevel.pos_of tr)) errs;
   249       val _ = List.app (Future.error_message (Toplevel.pos_of tr)) errs;
   248     in
   250     in
   249       (case result of
   251       (case result of
   260           in {failed = false, malformed = malformed', command = tr, state = st'} end)
   262           in {failed = false, malformed = malformed', command = tr, state = st'} end)
   261     end;
   263     end;
   262 
   264 
   263 in
   265 in
   264 
   266 
   265 fun eval init master_dir blobs span eval0 =
   267 fun eval keywords master_dir init blobs span eval0 =
   266   let
   268   let
   267     val exec_id = Document_ID.make ();
   269     val exec_id = Document_ID.make ();
   268     fun process () =
   270     fun process () =
   269       let
   271       let
   270         val tr =
   272         val tr =
   271           Position.setmp_thread_data (Position.id_only (Document_ID.print exec_id))
   273           Position.setmp_thread_data (Position.id_only (Document_ID.print exec_id))
   272             (fn () => read init master_dir blobs span |> Toplevel.exec_id exec_id) ();
   274             (fn () => read keywords master_dir init blobs span |> Toplevel.exec_id exec_id) ();
   273       in eval_state span tr (eval_result eval0) end;
   275       in eval_state keywords span tr (eval_result eval0) end;
   274   in Eval {exec_id = exec_id, eval_process = memo exec_id process} end;
   276   in Eval {exec_id = exec_id, eval_process = memo exec_id process} end;
   275 
   277 
   276 end;
   278 end;
   277 
   279 
   278 
   280 
   286 val print_eq = op = o pairself print_exec_id;
   288 val print_eq = op = o pairself print_exec_id;
   287 
   289 
   288 type print_fn = Toplevel.transition -> Toplevel.state -> unit;
   290 type print_fn = Toplevel.transition -> Toplevel.state -> unit;
   289 
   291 
   290 type print_function =
   292 type print_function =
   291   {command_name: string, args: string list, exec_id: Document_ID.exec} ->
   293   {keywords: Keyword.keywords, command_name: string, args: string list, exec_id: Document_ID.exec} ->
   292     {delay: Time.time option, pri: int, persistent: bool, strict: bool, print_fn: print_fn} option;
   294     {delay: Time.time option, pri: int, persistent: bool, strict: bool, print_fn: print_fn} option;
   293 
   295 
   294 local
   296 local
   295 
   297 
   296 val print_functions =
   298 val print_functions =
   308 
   310 
   309 val overlay_ord = prod_ord string_ord (list_ord string_ord);
   311 val overlay_ord = prod_ord string_ord (list_ord string_ord);
   310 
   312 
   311 in
   313 in
   312 
   314 
   313 fun print command_visible command_overlays command_name eval old_prints =
   315 fun print command_visible command_overlays keywords command_name eval old_prints =
   314   let
   316   let
   315     val print_functions = Synchronized.value print_functions;
   317     val print_functions = Synchronized.value print_functions;
   316 
   318 
   317     fun make_print name args {delay, pri, persistent, strict, print_fn} =
   319     fun make_print name args {delay, pri, persistent, strict, print_fn} =
   318       let
   320       let
   336       make_print name args {delay = NONE, pri = 0, persistent = false,
   338       make_print name args {delay = NONE, pri = 0, persistent = false,
   337         strict = false, print_fn = fn _ => fn _ => reraise exn};
   339         strict = false, print_fn = fn _ => fn _ => reraise exn};
   338 
   340 
   339     fun new_print name args get_pr =
   341     fun new_print name args get_pr =
   340       let
   342       let
   341         val params = {command_name = command_name, args = args, exec_id = eval_exec_id eval};
   343         val params =
       
   344          {keywords = keywords,
       
   345           command_name = command_name,
       
   346           args = args,
       
   347           exec_id = eval_exec_id eval};
   342       in
   348       in
   343         (case Exn.capture (Runtime.controlled_execution NONE get_pr) params of
   349         (case Exn.capture (Runtime.controlled_execution NONE get_pr) params of
   344           Exn.Res NONE => NONE
   350           Exn.Res NONE => NONE
   345         | Exn.Res (SOME pr) => SOME (make_print name args pr)
   351         | Exn.Res (SOME pr) => SOME (make_print name args pr)
   346         | Exn.Exn exn => SOME (bad_print name args exn))
   352         | Exn.Exn exn => SOME (bad_print name args exn))
   383           print_fn = fn _ => fn _ => Execution.fork_prints exec_id}
   389           print_fn = fn _ => fn _ => Execution.fork_prints exec_id}
   384       else NONE);
   390       else NONE);
   385 
   391 
   386 val _ =
   392 val _ =
   387   print_function "print_state"
   393   print_function "print_state"
   388     (fn {command_name, ...} =>
   394     (fn {keywords, command_name, ...} =>
   389       if Keyword.is_printed command_name then
   395       if Keyword.is_printed keywords command_name then
   390         SOME {delay = NONE, pri = 1, persistent = false, strict = true,
   396         SOME {delay = NONE, pri = 1, persistent = false, strict = true,
   391           print_fn = fn _ => fn st => if Toplevel.is_proof st then Toplevel.print_state st else ()}
   397           print_fn = fn _ => fn st => if Toplevel.is_proof st then Toplevel.print_state st else ()}
   392       else NONE);
   398       else NONE);
   393 
   399 
   394 
   400