1 signature PROTOCOL = sig
3 type ('i, 'o) operation =
8 type flags = {sequential: bool, bracket: bool, auto: bool (* ignored *)}
10 val default_flags : flags
11 val join_flags : flags -> flags -> flags
12 val print_flags : flags -> string
14 val add_operation : name -> ('i, 'o) operation -> flags -> unit
15 val get_operation : name -> int -> XML.tree -> XML.tree
18 structure Protocol: PROTOCOL = struct
21 type ('i, 'o) operation =
26 type flags = {sequential: bool, bracket: bool, auto: bool}
28 val default_flags = {sequential = false, bracket = false, auto = false}
31 {sequential = seq1, bracket = br1, auto = a1}
32 {sequential = seq2, bracket = br2, auto = a2} =
33 {sequential = seq1 orelse seq2, bracket = br1 orelse br2, auto = a1 orelse a2}
35 fun print_flags {sequential, bracket, auto} =
36 "({sequential=" ^ Markup.print_bool sequential ^ "," ^
37 "bracket=" ^ Markup.print_bool bracket ^ "," ^
38 "auto=" ^ Markup.print_bool auto ^ "})"
40 type raw_operation = int -> XML.tree -> XML.tree
42 exception GENERIC of string
45 Synchronized.var "libisabelle.operations" (Symtab.empty: raw_operation Symtab.table)
48 Synchronized.var "libisabelle.requests" (Inttab.empty: (unit -> unit) Inttab.table)
50 fun sequentialize name f =
52 val var = Synchronized.var ("libisabelle." ^ name) ()
54 fn x => Synchronized.change_result var (fn _ => (f x, ()))
57 fun bracketize f id x =
59 val start = [(Markup.functionN, "libisabelle_start"), ("id", Markup.print_int id)]
60 val stop = [(Markup.functionN, "libisabelle_stop"), ("id", Markup.print_int id)]
61 val _ = Output.protocol_message start []
63 val _ = Output.protocol_message stop []
66 fun add_operation name {from_lib, to_lib, action} {sequential, bracket, ...} =
69 case Codec.decode from_lib tree of
70 Codec.Success i => Codec.encode to_lib (action i)
71 | Codec.Failure (msg, _) => raise Fail ("decoding input failed for operation " ^ name ^ ": " ^ msg)
73 |> (if bracket then bracketize else I)
74 |> (if sequential then sequentialize name else I)
76 Synchronized.change operations (Symtab.update (name, raw'))
79 fun get_operation name =
80 case Symtab.lookup (Synchronized.value operations) name of
81 SOME operation => operation
82 | NONE => fn _ => raise Fail "libisabelle: unknown command"
84 val _ = Isabelle_Process.protocol_command "libisabelle"
85 (fn id :: name :: [arg] =>
87 val id = Markup.parse_int id
88 val response = [(Markup.functionN, "libisabelle_response"), ("id", Markup.print_int id)]
89 val args = YXML.parse arg
92 val future = Future.fork (fn () =>
94 val res = Exn.interruptible_capture (f id) args
95 val yxml = YXML.string_of (Codec.encode (Codec.exn_result Codec.id) res)
97 Output.protocol_message response [yxml]
100 Synchronized.change requests (Inttab.update_new (id, fn () => Future.cancel future))
103 exec (get_operation name)
106 val _ = Isabelle_Process.protocol_command "libisabelle_cancel"
109 fun remove id tab = (Inttab.lookup tab id, Inttab.delete_safe id tab)
111 map Markup.parse_int ids
113 |> Synchronized.change_result requests
114 |> map (fn NONE => () | SOME f => f ())