230 val _ = Output.urgent_message ("Loading theory " ^ quote name ^ required_by " " initiators); |
230 val _ = Output.urgent_message ("Loading theory " ^ quote name ^ required_by " " initiators); |
231 |
231 |
232 val {master = (thy_path, _), imports} = deps; |
232 val {master = (thy_path, _), imports} = deps; |
233 val dir = Path.dir thy_path; |
233 val dir = Path.dir thy_path; |
234 val pos = Path.position thy_path; |
234 val pos = Path.position thy_path; |
235 val uses = map (apfst Path.explode) (#3 (Thy_Header.read pos text)); |
235 val (_, _, uses) = Thy_Header.read pos text; |
236 fun init _ = |
236 fun init _ = |
237 Thy_Load.begin_theory dir name imports parent_thys uses |
237 Thy_Load.begin_theory dir name imports parent_thys uses |
238 |> Present.begin_theory update_time dir uses; |
238 |> Present.begin_theory update_time dir uses; |
239 |
239 |
240 val (after_load, theory) = Outer_Syntax.load_thy name init pos text; |
240 val (after_load, theory) = Outer_Syntax.load_thy name init pos text; |
249 |
249 |
250 in (theory, after_load') end; |
250 in (theory, after_load') end; |
251 |
251 |
252 fun check_deps dir name = |
252 fun check_deps dir name = |
253 (case lookup_deps name of |
253 (case lookup_deps name of |
254 SOME NONE => (true, NONE, get_parents name, NONE) |
254 SOME NONE => (true, NONE, get_parents name) |
255 | NONE => |
255 | NONE => |
256 let val {master, text, imports, ...} = Thy_Load.deps_thy dir name |
256 let val {master, text, imports, ...} = Thy_Load.check_thy dir name |
257 in (false, SOME (make_deps master imports), imports, SOME text) end |
257 in (false, SOME (make_deps master imports, text), imports) end |
258 | SOME (SOME {master, imports}) => |
258 | SOME (SOME {master, imports}) => |
259 let val master' = Thy_Load.check_thy dir name in |
259 let |
260 if #2 master <> #2 master' then |
260 val {master = master', text = text', imports = imports', ...} = Thy_Load.check_thy dir name; |
261 let val {text = text', imports = imports', ...} = Thy_Load.deps_thy dir name; |
261 val deps' = SOME (make_deps master' imports', text'); |
262 in (false, SOME (make_deps master' imports'), imports', SOME text') end |
262 val current = |
263 else |
263 #2 master = #2 master' andalso |
264 let |
264 (case lookup_theory name of |
265 val current = |
265 NONE => false |
266 (case lookup_theory name of |
266 | SOME theory => Thy_Load.all_current theory); |
267 NONE => false |
267 in (current, deps', imports') end); |
268 | SOME theory => Thy_Load.all_current theory); |
|
269 val deps' = SOME (make_deps master' imports); |
|
270 in (current, deps', imports, NONE) end |
|
271 end); |
|
272 |
268 |
273 in |
269 in |
274 |
270 |
275 fun require_thys initiators dir strs tasks = |
271 fun require_thys initiators dir strs tasks = |
276 fold_map (require_thy initiators dir) strs tasks |>> forall I |
272 fold_map (require_thy initiators dir) strs tasks |>> forall I |
283 in |
279 in |
284 (case try (Graph.get_node tasks) name of |
280 (case try (Graph.get_node tasks) name of |
285 SOME task => (task_finished task, tasks) |
281 SOME task => (task_finished task, tasks) |
286 | NONE => |
282 | NONE => |
287 let |
283 let |
288 val (current, deps, imports, opt_text) = check_deps dir' name |
284 val (current, deps, imports) = check_deps dir' name |
289 handle ERROR msg => cat_error msg |
285 handle ERROR msg => cat_error msg |
290 (loader_msg "the error(s) above occurred while examining theory" [name] ^ |
286 (loader_msg "the error(s) above occurred while examining theory" [name] ^ |
291 required_by "\n" initiators); |
287 required_by "\n" initiators); |
292 |
288 |
293 val parents = map base_name imports; |
289 val parents = map base_name imports; |
294 val (parents_current, tasks') = |
290 val (parents_current, tasks') = |
295 require_thys (name :: initiators) (Path.append dir (master_dir deps)) imports tasks; |
291 require_thys (name :: initiators) |
|
292 (Path.append dir (master_dir (Option.map #1 deps))) imports tasks; |
296 |
293 |
297 val all_current = current andalso parents_current; |
294 val all_current = current andalso parents_current; |
298 val task = |
295 val task = |
299 if all_current then Finished (get_theory name) |
296 if all_current then Finished (get_theory name) |
300 else |
297 else |
301 (case deps of |
298 (case deps of |
302 NONE => raise Fail "Malformed deps" |
299 NONE => raise Fail "Malformed deps" |
303 | SOME (dep as {master = (thy_path, _), ...}) => |
300 | SOME (dep, text) => |
304 let |
301 let val update_time = serial () |
305 val text = (case opt_text of SOME text => text | NONE => File.read thy_path); |
|
306 val update_time = serial (); |
|
307 in Task (parents, load_thy initiators update_time dep text name) end); |
302 in Task (parents, load_thy initiators update_time dep text name) end); |
308 in (all_current, new_entry name parents task tasks') end) |
303 in (all_current, new_entry name parents task tasks') end) |
309 end; |
304 end; |
310 |
305 |
311 end; |
306 end; |
334 (* register theory *) |
329 (* register theory *) |
335 |
330 |
336 fun register_thy theory = |
331 fun register_thy theory = |
337 let |
332 let |
338 val name = Context.theory_name theory; |
333 val name = Context.theory_name theory; |
339 val master = Thy_Load.check_thy (Thy_Load.master_directory theory) name; |
334 val {master, ...} = Thy_Load.check_thy (Thy_Load.master_directory theory) name; |
340 val parents = map Context.theory_name (Theory.parents_of theory); |
335 val parents = map Context.theory_name (Theory.parents_of theory); |
341 val imports = Thy_Load.imports_of theory; |
336 val imports = Thy_Load.imports_of theory; |
342 val deps = make_deps master imports; |
337 val deps = make_deps master imports; |
343 in |
338 in |
344 NAMED_CRITICAL "Thy_Info" (fn () => |
339 NAMED_CRITICAL "Thy_Info" (fn () => |