| author | blanchet |
| Thu, 29 Oct 2009 15:23:25 +0100 | |
| changeset 33570 | 14f2880e7ccf |
| parent 33225 | 0496565527bd |
| child 34096 | e438a5875c16 |
| permissions | -rw-r--r-- |
|
30173
eabece26b89b
moved isabelle_process.ML, isabelle_process.scala, isar.ML, session.ML to Pure/System/ (together with associated Isar commands);
wenzelm
parents:
29522
diff
changeset
|
1 |
(* Title: Pure/System/isabelle_process.ML |
|
25528
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
2 |
Author: Makarius |
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
3 |
|
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
4 |
Isabelle process wrapper -- interaction via external program. |
| 25631 | 5 |
|
6 |
General format of process output: |
|
7 |
||
| 29327 | 8 |
(1) unmarked stdout/stderr, no line structure (output should be |
| 25842 | 9 |
processed immediately as it arrives); |
| 25631 | 10 |
|
| 29327 | 11 |
(2) properly marked-up messages, e.g. for writeln channel |
| 25810 | 12 |
|
13 |
"\002A" ^ props ^ "\002,\n" ^ text ^ "\002.\n" |
|
14 |
||
| 25841 | 15 |
where the props consist of name=value lines terminated by "\002,\n" |
| 25810 | 16 |
each, and the remaining text is any number of lines (output is |
| 25842 | 17 |
supposed to be processed in one piece); |
| 25841 | 18 |
|
| 29327 | 19 |
(3) special init message holds "pid" and "session" property; |
20 |
||
21 |
(4) message content is encoded in YXML format. |
|
|
25528
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
22 |
*) |
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
23 |
|
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
24 |
signature ISABELLE_PROCESS = |
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
25 |
sig |
|
26574
560d07845442
support "YXML" mode for output transfer notation;
wenzelm
parents:
26550
diff
changeset
|
26 |
val isabelle_processN: string |
| 28044 | 27 |
val init: string -> unit |
|
25528
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
28 |
end; |
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
29 |
|
| 31797 | 30 |
structure Isabelle_Process: ISABELLE_PROCESS = |
|
25528
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
31 |
struct |
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
32 |
|
| 26550 | 33 |
(* print modes *) |
| 25554 | 34 |
|
| 25748 | 35 |
val isabelle_processN = "isabelle_process"; |
36 |
||
| 26550 | 37 |
val _ = Output.add_mode isabelle_processN Output.default_output Output.default_escape; |
| 28036 | 38 |
val _ = Markup.add_mode isabelle_processN YXML.output_markup; |
| 25841 | 39 |
|
40 |
||
41 |
(* message markup *) |
|
42 |
||
| 26527 | 43 |
fun special ch = Symbol.STX ^ ch; |
| 25810 | 44 |
val special_sep = special ","; |
| 25576 | 45 |
val special_end = special "."; |
| 25554 | 46 |
|
| 25841 | 47 |
local |
| 25810 | 48 |
|
|
26574
560d07845442
support "YXML" mode for output transfer notation;
wenzelm
parents:
26550
diff
changeset
|
49 |
fun clean_string bad str = |
|
560d07845442
support "YXML" mode for output transfer notation;
wenzelm
parents:
26550
diff
changeset
|
50 |
if exists_string (member (op =) bad) str then |
|
560d07845442
support "YXML" mode for output transfer notation;
wenzelm
parents:
26550
diff
changeset
|
51 |
translate_string (fn c => if member (op =) bad c then Symbol.DEL else c) str |
|
560d07845442
support "YXML" mode for output transfer notation;
wenzelm
parents:
26550
diff
changeset
|
52 |
else str; |
|
560d07845442
support "YXML" mode for output transfer notation;
wenzelm
parents:
26550
diff
changeset
|
53 |
|
| 26550 | 54 |
fun message_props props = |
|
26574
560d07845442
support "YXML" mode for output transfer notation;
wenzelm
parents:
26550
diff
changeset
|
55 |
let val clean = clean_string [Symbol.STX, "\n", "\r"] |
| 25841 | 56 |
in implode (map (fn (x, y) => clean x ^ "=" ^ clean y ^ special_sep ^ "\n") props) end; |
57 |
||
| 29327 | 58 |
fun message_pos trees = trees |> get_first |
59 |
(fn XML.Elem (name, atts, ts) => |
|
60 |
if name = Markup.positionN then SOME (Position.of_properties atts) |
|
61 |
else message_pos ts |
|
62 |
| _ => NONE); |
|
| 25554 | 63 |
|
64 |
in |
|
65 |
||
|
29522
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
66 |
fun message _ _ "" = () |
|
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
67 |
| message out_stream ch body = |
| 27844 | 68 |
let |
| 29328 | 69 |
val pos = the_default Position.none (message_pos (YXML.parse_body body)); |
| 27844 | 70 |
val props = |
71 |
Position.properties_of (Position.thread_data ()) |
|
72 |
|> Position.default_properties pos; |
|
|
29522
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
73 |
val txt = clean_string [Symbol.STX] body; |
|
33225
0496565527bd
non-critical output -- ship message in one piece;
wenzelm
parents:
32793
diff
changeset
|
74 |
val msg = special ch ^ message_props props ^ txt ^ special_end ^ "\n"; |
|
0496565527bd
non-critical output -- ship message in one piece;
wenzelm
parents:
32793
diff
changeset
|
75 |
in TextIO.output (out_stream, msg) end; |
| 25554 | 76 |
|
| 28044 | 77 |
fun init_message out_stream = |
| 25841 | 78 |
let |
| 28491 | 79 |
val pid = (Markup.pidN, process_id ()); |
| 27972 | 80 |
val session = (Markup.sessionN, List.last (Session.id ()) handle List.Empty => "unknown"); |
|
29522
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
81 |
val text = Session.welcome (); |
|
33225
0496565527bd
non-critical output -- ship message in one piece;
wenzelm
parents:
32793
diff
changeset
|
82 |
val msg = special "A" ^ message_props [pid, session] ^ text ^ special_end ^ "\n"; |
|
0496565527bd
non-critical output -- ship message in one piece;
wenzelm
parents:
32793
diff
changeset
|
83 |
in TextIO.output (out_stream, msg) end; |
| 25748 | 84 |
|
| 25554 | 85 |
end; |
86 |
||
87 |
||
| 25841 | 88 |
(* channels *) |
89 |
||
| 28188 | 90 |
local |
91 |
||
92 |
fun auto_flush stream = |
|
93 |
let |
|
|
28189
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
94 |
val _ = TextIO.StreamIO.setBufferMode (TextIO.getOutstream stream, IO.BLOCK_BUF); |
| 28188 | 95 |
fun loop () = |
96 |
(OS.Process.sleep (Time.fromMilliseconds 50); try TextIO.flushOut stream; loop ()); |
|
97 |
in loop end; |
|
98 |
||
99 |
in |
|
100 |
||
| 28044 | 101 |
fun setup_channels out = |
|
28189
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
102 |
let |
|
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
103 |
val out_stream = |
|
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
104 |
if out = "-" then TextIO.stdOut |
|
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
105 |
else |
|
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
106 |
let |
|
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
107 |
val path = File.platform_path (Path.explode out); |
|
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
108 |
val out_stream = TextIO.openOut path; (*fifo blocks until reader is ready*) |
|
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
109 |
val _ = OS.FileSys.remove path; (*prevent alien access, indicate writer is ready*) |
| 28242 | 110 |
val _ = SimpleThread.fork false (auto_flush TextIO.stdOut); |
|
28189
fbad2eb5be9e
auto_flush: uniform block buffering for all output streams;
wenzelm
parents:
28188
diff
changeset
|
111 |
in out_stream end; |
| 28242 | 112 |
val _ = SimpleThread.fork false (auto_flush out_stream); |
113 |
val _ = SimpleThread.fork false (auto_flush TextIO.stdErr); |
|
| 28044 | 114 |
in |
|
29522
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
115 |
Output.status_fn := message out_stream "B"; |
|
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
116 |
Output.writeln_fn := message out_stream "C"; |
|
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
117 |
Output.priority_fn := message out_stream "D"; |
|
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
118 |
Output.tracing_fn := message out_stream "E"; |
|
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
119 |
Output.warning_fn := message out_stream "F"; |
|
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
120 |
Output.error_fn := message out_stream "G"; |
|
793766d4c1b5
moved message markup into Scala layer -- reduced redundancy;
wenzelm
parents:
29328
diff
changeset
|
121 |
Output.debug_fn := message out_stream "H"; |
| 28498 | 122 |
Output.prompt_fn := ignore; |
| 28044 | 123 |
out_stream |
124 |
end; |
|
| 25841 | 125 |
|
| 28188 | 126 |
end; |
127 |
||
| 25841 | 128 |
|
| 25554 | 129 |
(* init *) |
130 |
||
| 28044 | 131 |
fun init out = |
| 32738 | 132 |
(Unsynchronized.change print_mode (update (op =) isabelle_processN); |
| 28044 | 133 |
setup_channels out |> init_message; |
| 28342 | 134 |
OuterKeyword.report (); |
| 32793 | 135 |
Isar_Document.init (); |
|
31384
ce169bd37fc0
IsabelleProcess: emit status "ready" after initialization and reports;
wenzelm
parents:
30173
diff
changeset
|
136 |
Output.status (Markup.markup Markup.ready ""); |
| 26643 | 137 |
Isar.toplevel_loop {init = true, welcome = false, sync = true, secure = true});
|
|
25528
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
138 |
|
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
139 |
end; |