src/Pure/Thy/thy_info.ML
changeset 24151 255f76dcc16b
parent 24133 75063f96618f
child 24175 38a15a3a1aad
equal deleted inserted replaced
24150:ed724867099a 24151:255f76dcc16b
    90 (* thy database *)
    90 (* thy database *)
    91 
    91 
    92 type master = (Path.T * File.ident) * (Path.T * File.ident) option;
    92 type master = (Path.T * File.ident) * (Path.T * File.ident) option;
    93 
    93 
    94 type deps =
    94 type deps =
    95   {outdated: bool,              (*entry considered outdated*)
    95   {update_time: int,            (*symbolic time of last update; < 0 means outdated*)
    96     master: master option,      (*master dependencies for thy + attached ML file*)
    96     master: master option,      (*master dependencies for thy + attached ML file*)
    97     text: string list,          (*source text for thy*)
    97     text: string list,          (*source text for thy*)
    98     parents: string list,       (*source specification of parents (partially qualified)*)
    98     parents: string list,       (*source specification of parents (partially qualified)*)
    99     files:                      (*auxiliary files: source path, physical path + identifier*)
    99     files:                      (*auxiliary files: source path, physical path + identifier*)
   100       (Path.T * (Path.T * File.ident) option) list};
   100       (Path.T * (Path.T * File.ident) option) list};
   101 
   101 
   102 fun make_deps outdated master text parents files : deps =
   102 fun make_deps update_time master text parents files : deps =
   103   {outdated = outdated, master = master, text = text, parents = parents, files = files};
   103   {update_time = update_time, master = master, text = text, parents = parents, files = files};
   104 
   104 
   105 fun init_deps master text parents files =
   105 fun init_deps master text parents files =
   106   SOME (make_deps true master text parents (map (rpair NONE) files));
   106   SOME (make_deps ~1 master text parents (map (rpair NONE) files));
   107 
   107 
   108 fun master_idents (NONE: master option) = []
   108 fun master_idents (NONE: master option) = []
   109   | master_idents (SOME ((_, thy_id), NONE)) = [thy_id]
   109   | master_idents (SOME ((_, thy_id), NONE)) = [thy_id]
   110   | master_idents (SOME ((_, thy_id), SOME (_, ml_id))) = [thy_id, ml_id];
   110   | master_idents (SOME ((_, thy_id), SOME (_, ml_id))) = [thy_id, ml_id];
   111 
   111 
   233       else warning (loader_msg "unresolved dependencies of theory" [name] ^
   233       else warning (loader_msg "unresolved dependencies of theory" [name] ^
   234         " on file(s): " ^ commas_quote missing_files);
   234         " on file(s): " ^ commas_quote missing_files);
   235   in files end;
   235   in files end;
   236 
   236 
   237 
   237 
   238 (* maintain 'outdated' flag *)
   238 (* maintain update_time *)
   239 
   239 
   240 local
   240 local
   241 
   241 
   242 fun is_outdated name =
   242 fun is_outdated name =
   243   (case lookup_deps name of
   243   (case lookup_deps name of
   244     SOME (SOME {outdated, ...}) => outdated
   244     SOME (SOME {update_time, ...}) => update_time < 0
   245   | _ => false);
   245   | _ => false);
   246 
   246 
   247 fun outdate_thy name =
   247 fun outdate_thy name =
   248   if is_finished name orelse is_outdated name then ()
   248   if is_finished name orelse is_outdated name then ()
   249   else CRITICAL (fn () =>
   249   else CRITICAL (fn () =>
   250    (change_deps name (Option.map (fn {outdated = _, master, text, parents, files} =>
   250    (change_deps name (Option.map (fn {master, text, parents, files, ...} =>
   251     make_deps true master text parents files)); perform Outdate name));
   251     make_deps ~1 master text parents files)); perform Outdate name));
   252 
   252 
   253 fun check_unfinished name =
   253 fun check_unfinished name =
   254   if is_finished name then (warning (loader_msg "tried to touch finished theory" [name]); NONE)
   254   if is_finished name then (warning (loader_msg "tried to touch finished theory" [name]); NONE)
   255   else SOME name;
   255   else SOME name;
   256 
   256 
   269 
   269 
   270 (* load_file *)
   270 (* load_file *)
   271 
   271 
   272 local
   272 local
   273 
   273 
   274 fun provide path name info (deps as SOME {outdated, master, text, parents, files}) =
   274 fun provide path name info (deps as SOME {update_time, master, text, parents, files}) =
   275      (if AList.defined (op =) files path then ()
   275      (if AList.defined (op =) files path then ()
   276       else warning (loader_msg "undeclared dependency of theory" [name] ^
   276       else warning (loader_msg "undeclared dependency of theory" [name] ^
   277         " on file: " ^ quote (Path.implode path));
   277         " on file: " ^ quote (Path.implode path));
   278       SOME (make_deps outdated master text parents (AList.update (op =) (path, SOME info) files)))
   278       SOME (make_deps update_time master text parents
       
   279         (AList.update (op =) (path, SOME info) files)))
   279   | provide _ _ _ NONE = NONE;
   280   | provide _ _ _ NONE = NONE;
   280 
   281 
   281 fun run_file path =
   282 fun run_file path =
   282   (case Option.map (Context.theory_name o Context.the_theory) (ML_Context.get_context ()) of
   283   (case Option.map (Context.theory_name o Context.the_theory) (ML_Context.get_context ()) of
   283     NONE => (ThyLoad.load_ml Path.current path; ())
   284     NONE => (ThyLoad.load_ml Path.current path; ())
   308 (* load_thy *)
   309 (* load_thy *)
   309 
   310 
   310 fun required_by _ [] = ""
   311 fun required_by _ [] = ""
   311   | required_by s initiators = s ^ "(required by " ^ show_path (rev initiators) ^ ")";
   312   | required_by s initiators = s ^ "(required by " ^ show_path (rev initiators) ^ ")";
   312 
   313 
   313 fun load_thy ml time initiators dir name =
   314 fun load_thy ml time upd_time initiators dir name =
   314   let
   315   let
   315     val _ = priority ("Loading theory " ^ quote name ^ required_by " " initiators);
   316     val _ = priority ("Loading theory " ^ quote name ^ required_by " " initiators);
   316     val (pos, text, files) =
   317     val (pos, text, files) =
   317       (case get_deps name of
   318       (case get_deps name of
   318         SOME {master = SOME ((master_path, _), _), text, files, ...} =>
   319         SOME {master = SOME ((master_path, _), _), text, files, ...} =>
   319           (Position.path master_path, text, files)
   320           (Position.path master_path, text, files)
   320       | _ => error (loader_msg "corrupted dependency information" [name]));
   321       | _ => error (loader_msg "corrupted dependency information" [name]));
   321     val _ = touch_thy name;
   322     val _ = touch_thy name;
       
   323     val _ = CRITICAL (fn () =>
       
   324       change_deps name (Option.map (fn {master, text, parents, files, ...} =>
       
   325         make_deps upd_time master text parents files)));
   322     val _ = ThyLoad.load_thy dir name pos text ml (time orelse ! Output.timing);
   326     val _ = ThyLoad.load_thy dir name pos text ml (time orelse ! Output.timing);
   323     val _ = check_files name;
   327     val _ = check_files name;
   324   in
   328   in
   325     CRITICAL (fn () =>
   329     CRITICAL (fn () =>
   326      (change_deps name
   330      (change_deps name
   327         (Option.map (fn {master, parents, files, ...} => make_deps false master [] parents files));
   331         (Option.map (fn {update_time, master, parents, files, ...} =>
       
   332           make_deps update_time master [] parents files));
   328       perform Update name))
   333       perform Update name))
   329   end;
   334   end;
   330 
   335 
   331 
   336 
   332 (* require_thy -- checking database entries wrt. the file-system *)
   337 (* require_thy -- checking database entries wrt. the file-system *)
   345   (case lookup_deps name of
   350   (case lookup_deps name of
   346     SOME NONE => (true, NONE, get_parents name)
   351     SOME NONE => (true, NONE, get_parents name)
   347   | NONE =>
   352   | NONE =>
   348       let val {master, text, imports = parents, uses = files} = ThyLoad.deps_thy dir name ml
   353       let val {master, text, imports = parents, uses = files} = ThyLoad.deps_thy dir name ml
   349       in (false, init_deps (SOME master) text parents files, parents) end
   354       in (false, init_deps (SOME master) text parents files, parents) end
   350   | SOME (deps as SOME {outdated, master, text, parents, files}) =>
   355   | SOME (deps as SOME {update_time, master, text, parents, files}) =>
   351       if not strict andalso can get_theory name then (true, deps, parents)
   356       if not strict andalso can get_theory name then (true, deps, parents)
   352       else
   357       else
   353         let val master' = SOME (ThyLoad.check_thy dir name ml) in
   358         let val master' = SOME (ThyLoad.check_thy dir name ml) in
   354           if master_idents master <> master_idents master'
   359           if master_idents master <> master_idents master'
   355           then
   360           then
   357               ThyLoad.deps_thy dir name ml;
   362               ThyLoad.deps_thy dir name ml;
   358             in (false, init_deps master' text' parents' files', parents') end
   363             in (false, init_deps master' text' parents' files', parents') end
   359           else
   364           else
   360             let
   365             let
   361               val checked_files = map (check_ml master') files;
   366               val checked_files = map (check_ml master') files;
   362               val current = not outdated andalso forall (is_some o snd) checked_files;
   367               val current = update_time >= 0 andalso forall (is_some o snd) checked_files;
   363               val deps' = SOME (make_deps (not current) master' text parents checked_files);
   368               val update_time' = if current then update_time else ~1;
       
   369               val deps' = SOME (make_deps update_time' master' text parents checked_files);
   364             in (current, deps', parents) end
   370             in (current, deps', parents) end
   365         end);
   371         end);
   366 
   372 
   367 in
   373 in
   368 
   374 
   389           val (parents_current, (tasks_graph', tasks_len')) =
   395           val (parents_current, (tasks_graph', tasks_len')) =
   390             require_thys true time (strict andalso keep_strict) keep_strict
   396             require_thys true time (strict andalso keep_strict) keep_strict
   391               (name :: initiators) (Path.append dir (master_dir' deps)) parents tasks;
   397               (name :: initiators) (Path.append dir (master_dir' deps)) parents tasks;
   392 
   398 
   393           val all_current = current andalso parents_current;
   399           val all_current = current andalso parents_current;
   394           val thy = if all_current then SOME (get_theory name) else NONE;
   400           val theory = if all_current then SOME (get_theory name) else NONE;
   395           val _ = change_thys (new_deps name parent_names (deps, thy));
   401           val _ = change_thys (new_deps name parent_names (deps, theory));
   396 
   402 
       
   403           val upd_time = serial ();
   397           val tasks_graph'' = tasks_graph' |> new_deps name parent_names
   404           val tasks_graph'' = tasks_graph' |> new_deps name parent_names
   398            (if all_current then Task.Finished
   405            (if all_current then Task.Finished
   399             else Task.Task (fn () => load_thy ml time initiators dir' name));
   406             else Task.Task (fn () => load_thy ml time upd_time initiators dir' name));
   400           val tasks_len'' = if all_current then tasks_len' else tasks_len' + 1;
   407           val tasks_len'' = if all_current then tasks_len' else tasks_len' + 1;
   401         in (all_current, (tasks_graph'', tasks_len'')) end)
   408         in (all_current, (tasks_graph'', tasks_len'')) end)
   402   end;
   409   end;
   403 
   410 
   404 end;
   411 end;
   418   | max_task _ task' = task';
   425   | max_task _ task' = task';
   419 
   426 
   420 fun next_task G =
   427 fun next_task G =
   421   let
   428   let
   422     val tasks = Graph.minimals G |> map (fn name =>
   429     val tasks = Graph.minimals G |> map (fn name =>
   423       (name, (Graph.get_node G name, length (Graph.imm_succs G name))))
   430       (name, (Graph.get_node G name, length (Graph.imm_succs G name))));
   424     val finished = filter (Task.is_finished o fst o snd) tasks;
   431     val finished = filter (Task.is_finished o fst o snd) tasks;
   425   in
   432   in
   426     if not (null finished) then next_task (Graph.del_nodes (map fst finished) G)
   433     if not (null finished) then next_task (Graph.del_nodes (map fst finished) G)
   427     else if null tasks then ((Task.Finished, I), G)
   434     else if null tasks then ((Task.Finished, I), G)
   428     else
   435     else
   496     (* FIXME tmp *)
   503     (* FIXME tmp *)
   497     val _ = CRITICAL (fn () =>
   504     val _ = CRITICAL (fn () =>
   498       ML_Context.set_context (SOME (Context.Theory (get_theory (List.last parent_names)))));
   505       ML_Context.set_context (SOME (Context.Theory (get_theory (List.last parent_names)))));
   499     val _ = check_uses name uses;
   506     val _ = check_uses name uses;
   500 
   507 
   501     val theory =
   508     val theory = Theory.begin_theory name (map get_theory parent_names);
   502       Theory.begin_theory name (map get_theory parent_names)
       
   503       |> Present.begin_theory dir uses;
       
   504 
   509 
   505     val deps =
   510     val deps =
   506       if known_thy name then get_deps name
   511       if known_thy name then get_deps name
   507       else init_deps NONE [] parents (map #1 uses);
   512       else init_deps NONE [] parents (map #1 uses);
   508     val _ = change_thys (new_deps name parent_names (deps, NONE));
   513     val _ = change_thys (new_deps name parent_names (deps, NONE));
   509 
   514 
       
   515     val update_time = (case deps of NONE => 0 | SOME {update_time, ...} => update_time);
       
   516     val theory' = Present.begin_theory update_time dir uses theory;
       
   517 
   510     val uses_now = map_filter (fn (x, true) => SOME x | _ => NONE) uses;
   518     val uses_now = map_filter (fn (x, true) => SOME x | _ => NONE) uses;
   511     val ((), theory') =
   519     val ((), theory'') =
   512       ML_Context.pass_context (Context.Theory theory) (List.app (load_file false)) uses_now
   520       ML_Context.pass_context (Context.Theory theory') (List.app (load_file false)) uses_now
   513       ||> Context.the_theory;
   521       ||> Context.the_theory;
   514   in theory' end;
   522   in theory'' end;
   515 
   523 
   516 fun end_theory theory =
   524 fun end_theory theory =
   517   let
   525   let
   518     val name = Context.theory_name theory;
   526     val name = Context.theory_name theory;
   519     val theory' = Theory.end_theory theory;
   527     val theory' = Theory.end_theory theory;
   530     val _ = map get_theory (get_parents name);
   538     val _ = map get_theory (get_parents name);
   531     val _ = check_unfinished error name;
   539     val _ = check_unfinished error name;
   532     val _ = touch_thy name;
   540     val _ = touch_thy name;
   533     val files = check_files name;
   541     val files = check_files name;
   534     val master = #master (ThyLoad.deps_thy Path.current name false);
   542     val master = #master (ThyLoad.deps_thy Path.current name false);
       
   543     val upd_time = serial ();
   535   in
   544   in
   536     CRITICAL (fn () =>
   545     CRITICAL (fn () =>
   537      (change_deps name
   546      (change_deps name
   538         (Option.map (fn {parents, ...} => make_deps false (SOME master) [] parents files));
   547         (Option.map (fn {parents, ...} => make_deps upd_time (SOME master) [] parents files));
   539       perform Update name))
   548       perform Update name))
   540   end;
   549   end;
   541 
   550 
   542 fun register_theory theory =
   551 fun register_theory theory =
   543   let
   552   let