src/Pure/Thy/thy_info.ML
changeset 7099 8142ccd13963
parent 7066 febce8eee487
child 7191 fcce2387ad6d
equal deleted inserted replaced
7098:86583034aacf 7099:8142ccd13963
    16   val use_thy: string -> unit
    16   val use_thy: string -> unit
    17   val update_thy: string -> unit
    17   val update_thy: string -> unit
    18   val remove_thy: string -> unit
    18   val remove_thy: string -> unit
    19   val time_use_thy: string -> unit
    19   val time_use_thy: string -> unit
    20   val use_thy_only: string -> unit
    20   val use_thy_only: string -> unit
       
    21   val update_thy_only: string -> unit
    21 end;
    22 end;
    22 
    23 
    23 signature THY_INFO =
    24 signature THY_INFO =
    24 sig
    25 sig
    25   include BASIC_THY_INFO
    26   include BASIC_THY_INFO
       
    27   datatype action = Update | Outdate | Remove
       
    28   val str_of_action: action -> string
       
    29   val add_hook: (action -> string -> unit) -> unit
    26   val names: unit -> string list
    30   val names: unit -> string list
    27   val get_theory: string -> theory
    31   val get_theory: string -> theory
    28   val put_theory: theory -> unit
       
    29   val get_preds: string -> string list
    32   val get_preds: string -> string list
    30   val loaded_files: string -> (Path.T * File.info) list
    33   val loaded_files: string -> (Path.T * File.info) list
       
    34   val touch_all_thys: unit -> unit
    31   val load_file: bool -> Path.T -> unit
    35   val load_file: bool -> Path.T -> unit
    32   val use_path: Path.T -> unit
    36   val use_path: Path.T -> unit
    33   val use: string -> unit
    37   val use: string -> unit
    34   val begin_theory: string -> string list -> (Path.T * bool) list -> theory
    38   val begin_theory: string -> string list -> (Path.T * bool) list -> theory
    35   val end_theory: theory -> theory
    39   val end_theory: theory -> theory
    39 
    43 
    40 structure ThyInfo: THY_INFO =
    44 structure ThyInfo: THY_INFO =
    41 struct
    45 struct
    42 
    46 
    43 
    47 
       
    48 (** theory loader actions and hooks **)
       
    49 
       
    50 datatype action = Update | Outdate | Remove;
       
    51 val str_of_action = fn Update => "Update" | Outdate => "Outdate" | Remove => "Remove";
       
    52 
       
    53 local
       
    54   val hooks = ref ([]: (action -> string -> unit) list);
       
    55 in
       
    56   fun add_hook f = hooks := f :: ! hooks;
       
    57   fun perform action name = seq (fn f => f action name) (! hooks);
       
    58 end;
       
    59 
       
    60 
       
    61 
    44 (** thy database **)
    62 (** thy database **)
    45 
    63 
    46 (* messages *)
    64 (* messages *)
    47 
    65 
    48 fun gen_msg txt [] = txt
    66 fun gen_msg txt [] = txt
   128   | _ => error (loader_msg "undefined theory entry for" [name]));
   146   | _ => error (loader_msg "undefined theory entry for" [name]));
   129 
   147 
   130 val theory_of_sign = get_theory o Sign.name_of;
   148 val theory_of_sign = get_theory o Sign.name_of;
   131 val theory_of_thm = theory_of_sign o Thm.sign_of_thm;
   149 val theory_of_thm = theory_of_sign o Thm.sign_of_thm;
   132 
   150 
   133 fun put_theory theory =
   151 fun put_theory name theory = change_thy name (fn (deps, _) => (deps, Some theory));
   134   change_thy (PureThy.get_name theory) (fn (deps, _) => (deps, Some theory));
       
   135 
   152 
   136 
   153 
   137 
   154 
   138 (** thy operations **)
   155 (** thy operations **)
   139 
   156 
   140 (* maintain 'outdated' flag *)
   157 (* maintain 'outdated' flag *)
       
   158 
       
   159 local
   141 
   160 
   142 fun is_outdated name =
   161 fun is_outdated name =
   143   (case lookup_deps name of
   162   (case lookup_deps name of
   144     Some (Some {outdated, ...}) => outdated
   163     Some (Some {outdated, ...}) => outdated
   145   | _ => false);
   164   | _ => false);
   146 
   165 
   147 fun outdate_thy name =
   166 fun outdate_thy name =
   148   if is_finished name then ()
   167   if is_finished name orelse is_outdated name then ()
   149   else change_deps name (apsome (fn {present, outdated = _, master, files} =>
   168   else (change_deps name (apsome (fn {present, outdated = _, master, files} =>
   150     make_deps present true master files));
   169     make_deps present true master files)); perform Outdate name);
       
   170 
       
   171 in
   151 
   172 
   152 fun touch_thy name =
   173 fun touch_thy name =
   153   if is_outdated name then ()
   174   if is_finished name then warning (loader_msg "tried to touch finished theory" [name])
   154   else if is_finished name then warning (loader_msg "tried to touch finished theory" [name])
   175   else seq outdate_thy (thy_graph Graph.all_succs [name]);
   155   else
   176 
   156     (case filter_out is_outdated (thy_graph Graph.all_succs [name]) \ name of
   177 fun touch_all_thys () = seq outdate_thy (get_names ());
   157       [] => outdate_thy name
   178 
   158     | names =>
   179 end;
   159        (warning (loader_msg "the following theories become out-of-date:" names);
       
   160         seq outdate_thy names; outdate_thy name));
       
   161 
       
   162 val untouch_deps = apsome (fn {present, outdated = _, master, files}: deps =>
       
   163   make_deps present false master files);
       
   164 
       
   165 
       
   166 (* load_thy *)
       
   167 
       
   168 fun required_by [] = ""
       
   169   | required_by initiators = " (required by " ^ show_path (rev initiators) ^ ")";
       
   170 
       
   171 fun load_thy ml time initiators dir name parents =
       
   172   let
       
   173     val _ = if name mem_string initiators then error (cycle_msg name (rev initiators)) else ();
       
   174     val _ = writeln ("Loading theory " ^ quote name ^ required_by initiators);
       
   175 
       
   176     val _ = seq touch_thy (thy_graph Graph.all_succs [name]);
       
   177     val master = ThyLoad.load_thy dir name ml time;
       
   178 
       
   179     val files = get_files name;
       
   180     val missing_files = mapfilter (fn (path, None) => Some (Path.pack path) | _ => None) files;
       
   181   in
       
   182     if null missing_files then ()
       
   183     else warning (loader_msg "unresolved dependencies of theory" [name] ^
       
   184       "\nfile(s): " ^ commas_quote missing_files);
       
   185     change_deps name (fn _ => Some (make_deps true false master files))
       
   186   end;
       
   187 
   180 
   188 
   181 
   189 (* load_file *)
   182 (* load_file *)
   190 
   183 
   191 fun run_file path =
   184 fun run_file path =
   216 val use_path = load_file false;
   209 val use_path = load_file false;
   217 val use = use_path o Path.unpack;
   210 val use = use_path o Path.unpack;
   218 val time_use = load_file true o Path.unpack;
   211 val time_use = load_file true o Path.unpack;
   219 
   212 
   220 
   213 
       
   214 (* load_thy *)
       
   215 
       
   216 fun required_by [] = ""
       
   217   | required_by initiators = " (required by " ^ show_path (rev initiators) ^ ")";
       
   218 
       
   219 fun load_thy ml time initiators dir name parents =
       
   220   let
       
   221     val _ = if name mem_string initiators then error (cycle_msg name (rev initiators)) else ();
       
   222     val _ = writeln ("Loading theory " ^ quote name ^ required_by initiators);
       
   223 
       
   224     val _ = touch_thy name;
       
   225     val master = ThyLoad.load_thy dir name ml time;
       
   226 
       
   227     val files = get_files name;
       
   228     val missing_files = mapfilter (fn (path, None) => Some (Path.pack path) | _ => None) files;
       
   229   in
       
   230     if null missing_files then ()
       
   231     else warning (loader_msg "unresolved dependencies of theory" [name] ^
       
   232       "\nfile(s): " ^ commas_quote missing_files);
       
   233     change_deps name (fn _ => Some (make_deps true false master files));
       
   234     perform Update name
       
   235   end;
       
   236 
       
   237 
   221 (* require_thy *)
   238 (* require_thy *)
   222 
   239 
   223 fun init_deps master files = Some (make_deps false false master (map (rpair None) files));
   240 fun init_deps master files = Some (make_deps false true master (map (rpair None) files));
   224 
   241 
   225 fun load_deps dir name ml =
   242 fun load_deps dir name ml =
   226   let val (master, (parents, files)) = ThyLoad.deps_thy dir name ml
   243   let val (master, (parents, files)) = ThyLoad.deps_thy dir name ml
   227   in (Some (init_deps master files), parents) end;
   244   in (Some (init_deps master files), parents) end;
   228 
   245 
   256         val dir = Path.append prfx (Path.dir path);
   273         val dir = Path.append prfx (Path.dir path);
   257         val req_parent =
   274         val req_parent =
   258           require_thy ml time (strict andalso keep_strict) keep_strict (name :: initiators) dir;
   275           require_thy ml time (strict andalso keep_strict) keep_strict (name :: initiators) dir;
   259 
   276 
   260         val (current, (new_deps, parents)) = current_deps ml strict dir name handle ERROR =>
   277         val (current, (new_deps, parents)) = current_deps ml strict dir name handle ERROR =>
   261           error (loader_msg "The error(s) above occurred while examining theory" [name] ^
   278           error (loader_msg "the error(s) above occurred while examining theory" [name] ^
   262             (if null initiators then "" else "\n" ^ required_by initiators));
   279             (if null initiators then "" else "\n" ^ required_by initiators));
   263         val (visited', parent_results) = foldl_map req_parent (name :: visited, parents);
   280         val (visited', parent_results) = foldl_map req_parent (name :: visited, parents);
   264 
   281 
   265         val result =
   282         val result =
   266           if current andalso forall #1 parent_results then true
   283           if current andalso forall #1 parent_results then true
   267           else
   284           else
   268             ((case new_deps of
   285             ((case new_deps of
   269               Some deps => change_thys (update_node name parents (untouch_deps deps, None))
   286               Some deps => change_thys (update_node name parents (deps, None))
   270             | None => ());
   287             | None => ());
   271               load_thy ml time initiators dir name parents;
   288              load_thy ml time initiators dir name parents;
   272               false);
   289              false);
   273       in (visited', (result, name)) end
   290       in (visited', (result, name)) end
   274   end;
   291   end;
   275 
   292 
   276 fun gen_use_thy req s =
   293 fun gen_use_thy req s =
   277   let val (_, (_, name)) = req [] Path.current ([], s)
   294   let val (_, (_, name)) = req [] Path.current ([], s)
   278   in Context.context (get_theory name) end;
   295   in Context.context (get_theory name) end;
   279 
   296 
   280 val weak_use_thy = gen_use_thy (require_thy true false false false);
   297 val weak_use_thy    = gen_use_thy (require_thy true false false false);
   281 val use_thy      = gen_use_thy (require_thy true false true false);
   298 val use_thy         = gen_use_thy (require_thy true false true false);
   282 val update_thy   = gen_use_thy (require_thy true false true true);
   299 val time_use_thy    = gen_use_thy (require_thy true true true false);
   283 val time_use_thy = gen_use_thy (require_thy true true true false);
   300 val use_thy_only    = gen_use_thy (require_thy false false true false);
   284 val use_thy_only = gen_use_thy (require_thy false false true false);
   301 val update_thy      = gen_use_thy (require_thy true false true true);
       
   302 val update_thy_only = gen_use_thy (require_thy false false true true);
   285 
   303 
   286 
   304 
   287 (* remove_thy *)
   305 (* remove_thy *)
   288 
   306 
   289 fun remove_thy name =
   307 fun remove_thy name =
   290   if is_finished name then error (loader_msg "cannot remove finished theory" [name])
   308   if is_finished name then error (loader_msg "cannot remove finished theory" [name])
   291   else
   309   else
   292     let val succs = thy_graph Graph.all_succs [name] in
   310     let val succs = thy_graph Graph.all_succs [name] in
   293       writeln (loader_msg "removing" succs);
   311       writeln (loader_msg "removing" succs);
   294       change_thys (Graph.del_nodes succs)
   312       change_thys (Graph.del_nodes succs);
       
   313       seq (perform Remove) succs
   295     end;
   314     end;
   296 
   315 
   297 
   316 
   298 (* begin / end theory *)
   317 (* begin / end theory *)
   299 
   318 
   308     val _ = change_thys (update_node name parents (init_deps [] [], Some theory));
   327     val _ = change_thys (update_node name parents (init_deps [] [], Some theory));
   309     val use_paths = mapfilter (fn (x, true) => Some x | _ => None) paths;
   328     val use_paths = mapfilter (fn (x, true) => Some x | _ => None) paths;
   310   in Context.setmp (Some theory) (seq use_path) use_paths; theory end;
   329   in Context.setmp (Some theory) (seq use_path) use_paths; theory end;
   311 
   330 
   312 fun end_theory theory =
   331 fun end_theory theory =
   313   let val theory' = PureThy.end_theory theory
   332   let
   314   in put_theory theory'; theory' end;
   333     val theory' = PureThy.end_theory theory;
       
   334     val name = PureThy.get_name theory;
       
   335   in put_theory name theory'; theory' end;
   315 
   336 
   316 
   337 
   317 (* finish all theories *)
   338 (* finish all theories *)
   318 
   339 
   319 fun finish () = change_thys (Graph.map_nodes (fn (_, entry) => (None, entry)));
   340 fun finish () = change_thys (Graph.map_nodes (fn (_, entry) => (None, entry)));
   341         handle Graph.DUPLICATE _ => err "duplicate theory entry" [])
   362         handle Graph.DUPLICATE _ => err "duplicate theory entry" [])
   342       |> add_deps name parent_names;
   363       |> add_deps name parent_names;
   343   in
   364   in
   344     if not (null nonfinished) then err "non-finished parent theories" nonfinished
   365     if not (null nonfinished) then err "non-finished parent theories" nonfinished
   345     else if not (null variants) then err "different versions of parent theories" variants
   366     else if not (null variants) then err "different versions of parent theories" variants
   346     else change_thys register
   367     else (change_thys register; perform Update name)
   347   end;
   368   end;
   348 
   369 
   349 
   370 
   350 (*final declarations of this structure*)
   371 (*final declarations of this structure*)
   351 val theory = get_theory;
   372 val theory = get_theory;