src/Pure/Thy/thy_info.ML
changeset 24190 b400ec231fde
parent 24186 d7f267b806c9
child 24209 8a2c8d623e43
equal deleted inserted replaced
24189:1fa9852643a3 24190:b400ec231fde
    86   |> add_deps name parents;
    86   |> add_deps name parents;
    87 
    87 
    88 
    88 
    89 (* thy database *)
    89 (* thy database *)
    90 
    90 
    91 type master = (Path.T * File.ident) * (Path.T * File.ident) option;
       
    92 
       
    93 type deps =
    91 type deps =
    94   {update_time: int,            (*symbolic time of update; negative value means outdated*)
    92   {update_time: int,                      (*symbolic time of update; negative value means outdated*)
    95     master: master option,      (*master dependencies for thy + attached ML file*)
    93     master: (Path.T * File.ident) option, (*master dependencies for thy file*)
    96     text: string list,          (*source text for thy*)
    94     text: string list,                    (*source text for thy*)
    97     parents: string list,       (*source specification of parents (partially qualified)*)
    95     parents: string list,                 (*source specification of parents (partially qualified)*)
    98     files:                      (*auxiliary files: source path, physical path + identifier*)
    96       (*auxiliary files: source path, physical path + identifier*)
    99       (Path.T * (Path.T * File.ident) option) list};
    97     files: (Path.T * (Path.T * File.ident) option) list};
   100 
    98 
   101 fun make_deps update_time master text parents files : deps =
    99 fun make_deps update_time master text parents files : deps =
   102   {update_time = update_time, master = master, text = text, parents = parents, files = files};
   100   {update_time = update_time, master = master, text = text, parents = parents, files = files};
   103 
   101 
   104 fun init_deps master text parents files =
   102 fun init_deps master text parents files =
   105   SOME (make_deps ~1 master text parents (map (rpair NONE) files));
   103   SOME (make_deps ~1 master text parents (map (rpair NONE) files));
   106 
   104 
   107 fun master_idents (NONE: master option) = []
   105 fun master_dir NONE = Path.current
   108   | master_idents (SOME ((_, thy_id), NONE)) = [thy_id]
   106   | master_dir (SOME (path, _)) = Path.dir path;
   109   | master_idents (SOME ((_, thy_id), SOME (_, ml_id))) = [thy_id, ml_id];
       
   110 
       
   111 fun master_dir (NONE: master option) = Path.current
       
   112   | master_dir (SOME ((path, _), _)) = Path.dir path;
       
   113 
   107 
   114 fun master_dir' (d: deps option) = the_default Path.current (Option.map (master_dir o #master) d);
   108 fun master_dir' (d: deps option) = the_default Path.current (Option.map (master_dir o #master) d);
   115 fun master_dir'' d = the_default Path.current (Option.map master_dir' d);
   109 fun master_dir'' d = the_default Path.current (Option.map master_dir' d);
   116 
   110 
   117 fun base_name s = Path.implode (Path.base (Path.explode s));
   111 fun base_name s = Path.implode (Path.base (Path.explode s));
   162 
   156 
   163 fun loaded_files name =
   157 fun loaded_files name =
   164   (case get_deps name of
   158   (case get_deps name of
   165     NONE => []
   159     NONE => []
   166   | SOME {master, files, ...} =>
   160   | SOME {master, files, ...} =>
   167       (case master of SOME ((thy_path, _), _) => [thy_path] | NONE => []) @
   161       (case master of SOME (thy_path, _) => [thy_path] | NONE => []) @
   168       (map_filter (Option.map #1 o #2) files));
   162       (map_filter (Option.map #1 o #2) files));
   169 
   163 
   170 fun get_parents name =
   164 fun get_parents name =
   171   thy_graph Graph.imm_preds name handle Graph.UNDEF _ =>
   165   thy_graph Graph.imm_preds name handle Graph.UNDEF _ =>
   172     error (loader_msg "nothing known about theory" [name]);
   166     error (loader_msg "nothing known about theory" [name]);
   225 
   219 
   226 fun check_files name =
   220 fun check_files name =
   227   let
   221   let
   228     val files = (case get_deps name of SOME {files, ...} => files | NONE => []);
   222     val files = (case get_deps name of SOME {files, ...} => files | NONE => []);
   229     val missing_files = map_filter (fn (path, NONE) => SOME (Path.implode path) | _ => NONE) files;
   223     val missing_files = map_filter (fn (path, NONE) => SOME (Path.implode path) | _ => NONE) files;
   230     val _ =
   224     val _ = null missing_files orelse
   231       if null missing_files then ()
   225       error (loader_msg "unresolved dependencies of theory" [name] ^
   232       else warning (loader_msg "unresolved dependencies of theory" [name] ^
       
   233         " on file(s): " ^ commas_quote missing_files);
   226         " on file(s): " ^ commas_quote missing_files);
   234   in files end;
   227   in () end;
   235 
   228 
   236 
   229 
   237 (* maintain update_time *)
   230 (* maintain update_time *)
   238 
   231 
   239 local
   232 local
   308 (* load_thy *)
   301 (* load_thy *)
   309 
   302 
   310 fun required_by _ [] = ""
   303 fun required_by _ [] = ""
   311   | required_by s initiators = s ^ "(required by " ^ show_path (rev initiators) ^ ")";
   304   | required_by s initiators = s ^ "(required by " ^ show_path (rev initiators) ^ ")";
   312 
   305 
   313 fun load_thy ml time upd_time initiators dir name =
   306 fun load_thy time upd_time initiators dir name =
   314   let
   307   let
   315     val _ = priority ("Loading theory " ^ quote name ^ required_by " " initiators);
   308     val _ = priority ("Loading theory " ^ quote name ^ required_by " " initiators);
   316     val (pos, text, files) =
   309     val (pos, text, files) =
   317       (case get_deps name of
   310       (case get_deps name of
   318         SOME {master = SOME ((master_path, _), _), text as _ :: _, files, ...} =>
   311         SOME {master = SOME (master_path, _), text as _ :: _, files, ...} =>
   319           (Position.path master_path, text, files)
   312           (Position.path master_path, text, files)
   320       | _ => error (loader_msg "corrupted dependency information" [name]));
   313       | _ => error (loader_msg "corrupted dependency information" [name]));
   321     val _ = touch_thy name;
   314     val _ = touch_thy name;
   322     val _ = CRITICAL (fn () =>
   315     val _ = CRITICAL (fn () =>
   323       change_deps name (Option.map (fn {master, text, parents, files, ...} =>
   316       change_deps name (Option.map (fn {master, text, parents, files, ...} =>
   324         make_deps upd_time master text parents files)));
   317         make_deps upd_time master text parents files)));
   325     val _ = ThyLoad.load_thy dir name pos text ml (time orelse ! Output.timing);
   318     val _ = ThyLoad.load_thy dir name pos text (time orelse ! Output.timing);
   326     val _ = check_files name;
       
   327   in
   319   in
   328     CRITICAL (fn () =>
   320     CRITICAL (fn () =>
   329      (change_deps name
   321      (change_deps name
   330         (Option.map (fn {update_time, master, parents, files, ...} =>
   322         (Option.map (fn {update_time, master, parents, files, ...} =>
   331           make_deps update_time master [] parents files));
   323           make_deps update_time master [] parents files));
   347 
   339 
   348 fun check_deps dir name =
   340 fun check_deps dir name =
   349   (case lookup_deps name of
   341   (case lookup_deps name of
   350     SOME NONE => (true, NONE, get_parents name)
   342     SOME NONE => (true, NONE, get_parents name)
   351   | NONE =>
   343   | NONE =>
   352       let val {master, text, imports = parents, uses = files} = ThyLoad.deps_thy dir name true
   344       let val {master, text, imports = parents, uses = files} = ThyLoad.deps_thy dir name
   353       in (false, init_deps (SOME master) text parents files, parents) end
   345       in (false, init_deps (SOME master) text parents files, parents) end
   354   | SOME (deps as SOME {update_time, master, text, parents, files}) =>
   346   | SOME (deps as SOME {update_time, master, text, parents, files}) =>
   355       let val master' as SOME ((thy_path, _), _) = SOME (ThyLoad.check_thy dir name true) in
   347       let
   356         if master_idents master <> master_idents master'
   348         val (thy_path, thy_id) = ThyLoad.check_thy dir name;
   357         then
   349         val master' = SOME (thy_path, thy_id);
       
   350       in
       
   351         if Option.map #2 master <> SOME thy_id then
   358           let val {text = text', imports = parents', uses = files', ...} =
   352           let val {text = text', imports = parents', uses = files', ...} =
   359             ThyLoad.deps_thy dir name true;
   353             ThyLoad.deps_thy dir name;
   360           in (false, init_deps master' text' parents' files', parents') end
   354           in (false, init_deps master' text' parents' files', parents') end
   361         else
   355         else
   362           let
   356           let
   363             val files' = map (check_ml master') files;
   357             val files' = map (check_ml master') files;
   364             val current = update_time >= 0 andalso forall (is_some o snd) files';
   358             val current = update_time >= 0 andalso forall (is_some o snd) files';
   399           val _ = change_thys (new_deps name parent_names (deps, theory));
   393           val _ = change_thys (new_deps name parent_names (deps, theory));
   400 
   394 
   401           val upd_time = serial ();
   395           val upd_time = serial ();
   402           val tasks_graph'' = tasks_graph' |> new_deps name parent_names
   396           val tasks_graph'' = tasks_graph' |> new_deps name parent_names
   403            (if all_current then Task.Finished
   397            (if all_current then Task.Finished
   404             else Task.Task (fn () => load_thy true time upd_time initiators dir' name));
   398             else Task.Task (fn () => load_thy time upd_time initiators dir' name));
   405           val tasks_len'' = if all_current then tasks_len' else tasks_len' + 1;
   399           val tasks_len'' = if all_current then tasks_len' else tasks_len' + 1;
   406         in (all_current, (tasks_graph'', tasks_len'')) end)
   400         in (all_current, (tasks_graph'', tasks_len'')) end)
   407   end;
   401   end;
   408 
   402 
   409 end;
   403 end;
   482     end;
   476     end;
   483 
   477 
   484 
   478 
   485 (* begin / end theory *)
   479 (* begin / end theory *)
   486 
   480 
   487 fun check_uses name uses =
       
   488   let val illegal = map (fn ext => Path.ext ext (Path.basic name)) ("" :: ThyLoad.ml_exts) in
       
   489     (case find_first (member (op =) illegal o Path.base o Path.expand o #1) uses of
       
   490       NONE => ()
       
   491     | SOME (path, _) => error ("Illegal use of theory ML file: " ^ quote (Path.implode path)))
       
   492   end;
       
   493 
       
   494 fun begin_theory name parents uses int =
   481 fun begin_theory name parents uses int =
   495   let
   482   let
   496     val parent_names = map base_name parents;
   483     val parent_names = map base_name parents;
   497     val dir = master_dir'' (lookup_deps name);
   484     val dir = master_dir'' (lookup_deps name);
   498     val _ = check_unfinished error name;
   485     val _ = check_unfinished error name;
   499     val _ = if int then use_thys_dir dir parents else ();
   486     val _ = if int then use_thys_dir dir parents else ();
   500     (* FIXME tmp *)
   487     (* FIXME tmp *)
   501     val _ = CRITICAL (fn () =>
   488     val _ = CRITICAL (fn () =>
   502       ML_Context.set_context (SOME (Context.Theory (get_theory (List.last parent_names)))));
   489       ML_Context.set_context (SOME (Context.Theory (get_theory (List.last parent_names)))));
   503     val _ = check_uses name uses;
       
   504 
   490 
   505     val theory = Theory.begin_theory name (map get_theory parent_names);
   491     val theory = Theory.begin_theory name (map get_theory parent_names);
   506 
   492 
   507     val deps =
   493     val deps =
   508       if known_thy name then get_deps name
   494       if known_thy name then get_deps name
   519   in theory'' end;
   505   in theory'' end;
   520 
   506 
   521 fun end_theory theory =
   507 fun end_theory theory =
   522   let
   508   let
   523     val name = Context.theory_name theory;
   509     val name = Context.theory_name theory;
       
   510     val _ = check_files name;
   524     val theory' = Theory.end_theory theory;
   511     val theory' = Theory.end_theory theory;
   525     val _ = change_thy name (fn (deps, _) => (deps, SOME theory'));
   512     val _ = change_thy name (fn (deps, _) => (deps, SOME theory'));
   526   in theory' end;
   513   in theory' end;
   527 
   514 
   528 
   515 
   533     val _ = priority ("Registering theory " ^ quote name);
   520     val _ = priority ("Registering theory " ^ quote name);
   534     val _ = get_theory name;
   521     val _ = get_theory name;
   535     val _ = map get_theory (get_parents name);
   522     val _ = map get_theory (get_parents name);
   536     val _ = check_unfinished error name;
   523     val _ = check_unfinished error name;
   537     val _ = touch_thy name;
   524     val _ = touch_thy name;
   538     val files = check_files name;
   525     val master = #master (ThyLoad.deps_thy Path.current name);
   539     val master = #master (ThyLoad.deps_thy Path.current name false);
       
   540     val upd_time = serial ();
   526     val upd_time = serial ();
   541   in
   527   in
   542     CRITICAL (fn () =>
   528     CRITICAL (fn () =>
   543      (change_deps name
   529      (change_deps name (Option.map
   544         (Option.map (fn {parents, ...} => make_deps upd_time (SOME master) [] parents files));
   530        (fn {parents, files, ...} => make_deps upd_time (SOME master) [] parents files));
   545       perform Update name))
   531       perform Update name))
   546   end;
   532   end;
   547 
   533 
   548 fun register_theory theory =
   534 fun register_theory theory =
   549   let
   535   let