wenzelm@50686
|
1 |
(* Title: Pure/Tools/build.ML
|
wenzelm@48418
|
2 |
Author: Makarius
|
wenzelm@48418
|
3 |
|
wenzelm@48418
|
4 |
Build Isabelle sessions.
|
wenzelm@48418
|
5 |
*)
|
wenzelm@48418
|
6 |
|
wenzelm@48418
|
7 |
signature BUILD =
|
wenzelm@48418
|
8 |
sig
|
wenzelm@48731
|
9 |
val build: string -> unit
|
wenzelm@48418
|
10 |
end;
|
wenzelm@48418
|
11 |
|
wenzelm@48418
|
12 |
structure Build: BUILD =
|
wenzelm@48418
|
13 |
struct
|
wenzelm@48418
|
14 |
|
wenzelm@51662
|
15 |
(* command timings *)
|
wenzelm@51662
|
16 |
|
wenzelm@56615
|
17 |
type timings = ((string * Time.time) Inttab.table) Symtab.table; (*file -> offset -> name, time*)
|
wenzelm@51662
|
18 |
|
wenzelm@51662
|
19 |
val empty_timings: timings = Symtab.empty;
|
wenzelm@51662
|
20 |
|
wenzelm@51662
|
21 |
fun update_timings props =
|
wenzelm@51662
|
22 |
(case Markup.parse_command_timing_properties props of
|
wenzelm@51662
|
23 |
SOME ({file, offset, name}, time) =>
|
wenzelm@51666
|
24 |
Symtab.map_default (file, Inttab.empty)
|
wenzelm@62826
|
25 |
(Inttab.map_default (offset, (name, time)) (fn (_, t) => (name, t + time)))
|
wenzelm@51662
|
26 |
| NONE => I);
|
wenzelm@51662
|
27 |
|
wenzelm@51662
|
28 |
fun approximative_id name pos =
|
wenzelm@51662
|
29 |
(case (Position.file_of pos, Position.offset_of pos) of
|
wenzelm@51662
|
30 |
(SOME file, SOME offset) =>
|
wenzelm@51662
|
31 |
if name = "" then NONE else SOME {file = file, offset = offset, name = name}
|
wenzelm@51662
|
32 |
| _ => NONE);
|
wenzelm@51662
|
33 |
|
wenzelm@65058
|
34 |
fun get_timings timings tr =
|
wenzelm@51662
|
35 |
(case approximative_id (Toplevel.name_of tr) (Toplevel.pos_of tr) of
|
wenzelm@51662
|
36 |
SOME {file, offset, name} =>
|
wenzelm@51662
|
37 |
(case Symtab.lookup timings file of
|
wenzelm@51662
|
38 |
SOME offsets =>
|
wenzelm@51662
|
39 |
(case Inttab.lookup offsets offset of
|
wenzelm@51662
|
40 |
SOME (name', time) => if name = name' then SOME time else NONE
|
wenzelm@51662
|
41 |
| NONE => NONE)
|
wenzelm@51662
|
42 |
| NONE => NONE)
|
wenzelm@65058
|
43 |
| NONE => NONE)
|
wenzelm@65058
|
44 |
|> the_default Time.zeroTime;
|
wenzelm@51662
|
45 |
|
wenzelm@51662
|
46 |
|
wenzelm@52052
|
47 |
(* session timing *)
|
wenzelm@52052
|
48 |
|
wenzelm@52052
|
49 |
fun session_timing name verbose f x =
|
wenzelm@52052
|
50 |
let
|
wenzelm@52052
|
51 |
val start = Timing.start ();
|
wenzelm@52052
|
52 |
val y = f x;
|
wenzelm@52052
|
53 |
val timing = Timing.result start;
|
wenzelm@52052
|
54 |
|
wenzelm@62925
|
55 |
val threads = string_of_int (Multithreading.max_threads ());
|
wenzelm@52052
|
56 |
val factor = Time.toReal (#cpu timing) / Time.toReal (#elapsed timing)
|
wenzelm@52052
|
57 |
|> Real.fmt (StringCvt.FIX (SOME 2));
|
wenzelm@52052
|
58 |
|
wenzelm@52052
|
59 |
val timing_props =
|
wenzelm@52052
|
60 |
[("threads", threads)] @ Markup.timing_properties timing @ [("factor", factor)];
|
wenzelm@52052
|
61 |
val _ = writeln ("\fTiming = " ^ YXML.string_of_body (XML.Encode.properties timing_props));
|
wenzelm@52052
|
62 |
val _ =
|
wenzelm@52052
|
63 |
if verbose then
|
wenzelm@52052
|
64 |
Output.physical_stderr ("Timing " ^ name ^ " (" ^
|
wenzelm@52052
|
65 |
threads ^ " threads, " ^ Timing.message timing ^ ", factor " ^ factor ^ ")\n")
|
wenzelm@52052
|
66 |
else ();
|
wenzelm@52052
|
67 |
in y end;
|
wenzelm@52052
|
68 |
|
wenzelm@52052
|
69 |
|
wenzelm@50683
|
70 |
(* protocol messages *)
|
wenzelm@50683
|
71 |
|
wenzelm@51662
|
72 |
fun inline_message a args =
|
wenzelm@51662
|
73 |
writeln ("\f" ^ a ^ " = " ^ YXML.string_of_body (XML.Encode.properties args));
|
wenzelm@50683
|
74 |
|
wenzelm@50683
|
75 |
fun protocol_message props output =
|
wenzelm@51216
|
76 |
(case props of
|
wenzelm@51216
|
77 |
function :: args =>
|
wenzelm@51662
|
78 |
if function = Markup.ML_statistics orelse function = Markup.task_statistics then
|
wenzelm@51662
|
79 |
inline_message (#2 function) args
|
wenzelm@51662
|
80 |
else if function = Markup.command_timing then
|
wenzelm@51662
|
81 |
let
|
wenzelm@51662
|
82 |
val name = the_default "" (Properties.get args Markup.nameN);
|
wenzelm@51662
|
83 |
val pos = Position.of_properties args;
|
wenzelm@51662
|
84 |
val {elapsed, ...} = Markup.parse_timing_properties args;
|
wenzelm@62793
|
85 |
val is_significant =
|
wenzelm@62793
|
86 |
Timing.is_relevant_time elapsed andalso
|
wenzelm@62826
|
87 |
elapsed >= Options.default_seconds "command_timing_threshold";
|
wenzelm@51662
|
88 |
in
|
wenzelm@62793
|
89 |
if is_significant then
|
wenzelm@59149
|
90 |
(case approximative_id name pos of
|
wenzelm@59149
|
91 |
SOME id => inline_message (#2 function) (Markup.command_timing_properties id elapsed)
|
wenzelm@59149
|
92 |
| NONE => ())
|
wenzelm@59149
|
93 |
else ()
|
wenzelm@51662
|
94 |
end
|
wenzelm@51216
|
95 |
else
|
wenzelm@51216
|
96 |
(case Markup.dest_loading_theory props of
|
wenzelm@51216
|
97 |
SOME name => writeln ("\floading_theory = " ^ name)
|
wenzelm@51661
|
98 |
| NONE => raise Output.Protocol_Message props)
|
wenzelm@51661
|
99 |
| [] => raise Output.Protocol_Message props);
|
wenzelm@51045
|
100 |
|
wenzelm@50683
|
101 |
|
wenzelm@65307
|
102 |
(* build theories *)
|
wenzelm@50683
|
103 |
|
wenzelm@65445
|
104 |
fun build_theories symbols last_timing qualifier master_dir (options, thys) =
|
wenzelm@59366
|
105 |
let
|
wenzelm@59366
|
106 |
val condition = space_explode "," (Options.string options "condition");
|
wenzelm@59366
|
107 |
val conds = filter_out (can getenv_strict) condition;
|
wenzelm@59366
|
108 |
in
|
wenzelm@59366
|
109 |
if null conds then
|
wenzelm@63827
|
110 |
(if Options.bool options "checkpoint" then ML_Heap.share_common_data () else ();
|
wenzelm@63827
|
111 |
Options.set_default options;
|
wenzelm@62714
|
112 |
Isabelle_Process.init_options ();
|
wenzelm@64599
|
113 |
Future.fork I;
|
wenzelm@59366
|
114 |
(Thy_Info.use_theories {
|
wenzelm@59366
|
115 |
document = Present.document_enabled (Options.string options "document"),
|
wenzelm@61381
|
116 |
symbols = symbols,
|
wenzelm@59366
|
117 |
last_timing = last_timing,
|
wenzelm@65445
|
118 |
qualifier = qualifier,
|
wenzelm@59366
|
119 |
master_dir = master_dir}
|
wenzelm@64308
|
120 |
|>
|
wenzelm@64308
|
121 |
(case Options.string options "profiling" of
|
wenzelm@64308
|
122 |
"" => I
|
wenzelm@64308
|
123 |
| "time" => profile_time
|
wenzelm@64308
|
124 |
| "allocations" => profile_allocations
|
wenzelm@64308
|
125 |
| bad => error ("Bad profiling option: " ^ quote bad))
|
wenzelm@59366
|
126 |
|> Unsynchronized.setmp print_mode
|
wenzelm@62714
|
127 |
(space_explode "," (Options.string options "print_mode") @ print_mode_value ())) thys)
|
wenzelm@59366
|
128 |
else
|
wenzelm@59366
|
129 |
Output.physical_stderr ("Skipping theories " ^ commas_quote (map #1 thys) ^
|
wenzelm@59366
|
130 |
" (undefined " ^ commas conds ^ ")\n")
|
wenzelm@59366
|
131 |
end;
|
wenzelm@59366
|
132 |
|
wenzelm@65307
|
133 |
|
wenzelm@65307
|
134 |
(* build session *)
|
wenzelm@65307
|
135 |
|
wenzelm@65307
|
136 |
datatype args = Args of
|
wenzelm@65307
|
137 |
{symbol_codes: (string * int) list,
|
wenzelm@65307
|
138 |
command_timings: Properties.T list,
|
wenzelm@65307
|
139 |
do_output: bool,
|
wenzelm@65307
|
140 |
verbose: bool,
|
wenzelm@65307
|
141 |
browser_info: Path.T,
|
wenzelm@65307
|
142 |
document_files: (Path.T * Path.T) list,
|
wenzelm@65307
|
143 |
graph_file: Path.T,
|
wenzelm@65307
|
144 |
parent_name: string,
|
wenzelm@65307
|
145 |
chapter: string,
|
wenzelm@65307
|
146 |
name: string,
|
wenzelm@65307
|
147 |
master_dir: Path.T,
|
wenzelm@65431
|
148 |
theories: (Options.T * (string * Position.T) list) list,
|
wenzelm@65457
|
149 |
global_theories: (string * string) list,
|
wenzelm@66712
|
150 |
loaded_theories: string list,
|
wenzelm@65431
|
151 |
known_theories: (string * string) list};
|
wenzelm@65307
|
152 |
|
wenzelm@65307
|
153 |
fun decode_args yxml =
|
wenzelm@62630
|
154 |
let
|
wenzelm@65307
|
155 |
open XML.Decode;
|
wenzelm@65517
|
156 |
val position = Position.of_properties o properties;
|
wenzelm@62630
|
157 |
val (symbol_codes, (command_timings, (do_output, (verbose, (browser_info,
|
wenzelm@65431
|
158 |
(document_files, (graph_file, (parent_name, (chapter, (name, (master_dir,
|
wenzelm@65441
|
159 |
(theories, (global_theories, (loaded_theories, known_theories)))))))))))))) =
|
wenzelm@65307
|
160 |
pair (list (pair string int)) (pair (list properties) (pair bool (pair bool (pair string
|
wenzelm@65307
|
161 |
(pair (list (pair string string)) (pair string (pair string (pair string (pair string
|
wenzelm@65431
|
162 |
(pair string
|
wenzelm@65517
|
163 |
(pair (((list (pair Options.decode (list (pair string position))))))
|
wenzelm@65457
|
164 |
(pair (list (pair string string))
|
wenzelm@66712
|
165 |
(pair (list string) (list (pair string string)))))))))))))))
|
wenzelm@65307
|
166 |
(YXML.parse_body yxml);
|
wenzelm@65307
|
167 |
in
|
wenzelm@65307
|
168 |
Args {symbol_codes = symbol_codes, command_timings = command_timings, do_output = do_output,
|
wenzelm@65307
|
169 |
verbose = verbose, browser_info = Path.explode browser_info,
|
wenzelm@65307
|
170 |
document_files = map (apply2 Path.explode) document_files,
|
wenzelm@65307
|
171 |
graph_file = Path.explode graph_file, parent_name = parent_name, chapter = chapter,
|
wenzelm@65431
|
172 |
name = name, master_dir = Path.explode master_dir, theories = theories,
|
wenzelm@65441
|
173 |
global_theories = global_theories, loaded_theories = loaded_theories,
|
wenzelm@65431
|
174 |
known_theories = known_theories}
|
wenzelm@65307
|
175 |
end;
|
wenzelm@48418
|
176 |
|
wenzelm@65307
|
177 |
fun build_session (Args {symbol_codes, command_timings, do_output, verbose, browser_info,
|
wenzelm@65441
|
178 |
document_files, graph_file, parent_name, chapter, name, master_dir, theories,
|
wenzelm@65441
|
179 |
global_theories, loaded_theories, known_theories}) =
|
wenzelm@65307
|
180 |
let
|
wenzelm@62630
|
181 |
val symbols = HTML.make_symbols symbol_codes;
|
wenzelm@51941
|
182 |
|
wenzelm@65441
|
183 |
val _ =
|
wenzelm@65478
|
184 |
Resources.init_session_base
|
wenzelm@65532
|
185 |
{global_theories = global_theories,
|
wenzelm@65441
|
186 |
loaded_theories = loaded_theories,
|
wenzelm@65441
|
187 |
known_theories = known_theories};
|
wenzelm@65431
|
188 |
|
wenzelm@62630
|
189 |
val _ =
|
wenzelm@62630
|
190 |
Session.init
|
wenzelm@62630
|
191 |
symbols
|
wenzelm@62630
|
192 |
do_output
|
wenzelm@62630
|
193 |
(Options.default_bool "browser_info")
|
wenzelm@65307
|
194 |
browser_info
|
wenzelm@62630
|
195 |
(Options.default_string "document")
|
wenzelm@62630
|
196 |
(Options.default_string "document_output")
|
wenzelm@62630
|
197 |
(Present.document_variants (Options.default_string "document_variants"))
|
wenzelm@65307
|
198 |
document_files
|
wenzelm@65307
|
199 |
graph_file
|
wenzelm@65307
|
200 |
parent_name
|
wenzelm@65307
|
201 |
(chapter, name)
|
wenzelm@62630
|
202 |
verbose;
|
wenzelm@49911
|
203 |
|
wenzelm@65058
|
204 |
val last_timing = get_timings (fold update_timings command_timings empty_timings);
|
wenzelm@51218
|
205 |
|
wenzelm@62630
|
206 |
val res1 =
|
wenzelm@62630
|
207 |
theories |>
|
wenzelm@65445
|
208 |
(List.app (build_theories symbols last_timing name master_dir)
|
wenzelm@62630
|
209 |
|> session_timing name verbose
|
wenzelm@62630
|
210 |
|> Exn.capture);
|
wenzelm@62630
|
211 |
val res2 = Exn.capture Session.finish ();
|
wenzelm@65431
|
212 |
|
wenzelm@65478
|
213 |
val _ = Resources.finish_session_base ();
|
wenzelm@62630
|
214 |
val _ = Par_Exn.release_all [res1, res2];
|
wenzelm@65307
|
215 |
in () end;
|
wenzelm@48673
|
216 |
|
wenzelm@65307
|
217 |
(*command-line tool*)
|
wenzelm@65307
|
218 |
fun build args_file =
|
wenzelm@65307
|
219 |
let
|
wenzelm@65307
|
220 |
val _ = SHA1.test_samples ();
|
wenzelm@65307
|
221 |
val _ = Options.load_default ();
|
wenzelm@65307
|
222 |
val _ = Isabelle_Process.init_options ();
|
wenzelm@65936
|
223 |
val args = decode_args (File.read (Path.explode args_file));
|
wenzelm@66048
|
224 |
fun error_message msg = writeln ("\ferror_message = " ^ encode_lines (YXML.content_of msg));
|
wenzelm@65307
|
225 |
val _ =
|
wenzelm@65307
|
226 |
Unsynchronized.setmp Private_Output.protocol_message_fn protocol_message
|
wenzelm@65934
|
227 |
build_session args
|
wenzelm@65948
|
228 |
handle exn => (List.app error_message (Runtime.exn_message_list exn); Exn.reraise exn);
|
wenzelm@62630
|
229 |
val _ = Options.reset_default ();
|
wenzelm@62630
|
230 |
in () end;
|
wenzelm@48418
|
231 |
|
wenzelm@65307
|
232 |
(*PIDE version*)
|
wenzelm@65307
|
233 |
val _ =
|
wenzelm@65307
|
234 |
Isabelle_Process.protocol_command "build_session"
|
wenzelm@65313
|
235 |
(fn [args_yxml] =>
|
wenzelm@65307
|
236 |
let
|
wenzelm@65313
|
237 |
val args = decode_args args_yxml;
|
wenzelm@65307
|
238 |
val result = (build_session args; "") handle exn =>
|
wenzelm@65307
|
239 |
(Runtime.exn_message exn handle _ (*sic!*) =>
|
wenzelm@65307
|
240 |
"Exception raised, but failed to print details!");
|
wenzelm@65313
|
241 |
in Output.protocol_message Markup.build_session_finished [result] end | _ => raise Match);
|
wenzelm@59366
|
242 |
|
wenzelm@48418
|
243 |
end;
|