src/Pure/Thy/thy_read.ML
changeset 1291 e173be970d27
parent 1262 8f40ff1299d8
child 1308 396ef8aa37b7
equal deleted inserted replaced
1290:ee8f41456d28 1291:e173be970d27
     7 Functions for reading theory files, and storing and retrieving theories,
     7 Functions for reading theory files, and storing and retrieving theories,
     8 theorems and the global simplifier set.
     8 theorems and the global simplifier set.
     9 *)
     9 *)
    10 
    10 
    11 (*Type for theory storage*)
    11 (*Type for theory storage*)
    12 datatype thy_info = ThyInfo of {path: string,
    12 datatype thy_info =
    13                                 children: string list,
    13   ThyInfo of {path: string,
    14                                 thy_time: string option,
    14               children: string list, parents: string list,
    15                                 ml_time: string option,
    15               thy_time: string option, ml_time: string option,
    16                                 theory: theory option,
    16               theory: theory option, thms: thm Symtab.table,
    17                                 thms: thm Symtab.table,
    17               thy_ss: Simplifier.simpset option,
    18                                 thy_ss: Simplifier.simpset option,
    18               simpset: Simplifier.simpset option};
    19                                 simpset: Simplifier.simpset option};
       
    20       (*meaning of special values:
    19       (*meaning of special values:
    21         thy_time, ml_time = None     theory file has not been read yet
    20         thy_time, ml_time = None     theory file has not been read yet
    22                           = Some ""  theory was read but has either been marked
    21                           = Some ""  theory was read but has either been marked
    23                                      as outdated or there is no such file for
    22                                      as outdated or there is no such file for
    24                                      this theory (see e.g. 'virtual' theories
    23                                      this theory (see e.g. 'virtual' theories
    25                                      like Pure or theories without a ML file)
    24                                      like Pure or theories without a ML file)
    26         theory = None  theory has not been read yet
    25         theory = None  theory has not been read yet
       
    26 
       
    27         parents: While 'children' contains all theories the theory depends
       
    28                  on (i.e. also ones quoted in the .thy file),
       
    29                  'parents' only contains the theories which were used to form
       
    30                  the base of this theory.
       
    31 
       
    32         origin of the simpsets:
       
    33         thy_ss: snapshot of !Simpset.simpset after .thy file was read
       
    34         simpset: snapshot of !Simpset.simpset after .ML file was read
    27        *)
    35        *)
    28 
    36 
    29 signature READTHY =
    37 signature READTHY =
    30 sig
    38 sig
    31   datatype basetype = Thy  of string
    39   datatype basetype = Thy  of string
    42   val mk_base        : basetype list -> string -> bool -> theory
    50   val mk_base        : basetype list -> string -> bool -> theory
    43   val store_theory   : theory * string -> unit
    51   val store_theory   : theory * string -> unit
    44 
    52 
    45   val theory_of_sign: Sign.sg -> theory
    53   val theory_of_sign: Sign.sg -> theory
    46   val theory_of_thm: thm -> theory
    54   val theory_of_thm: thm -> theory
       
    55   val children_of: string -> string list
       
    56   val parents_of: string -> string list
       
    57 
    47   val store_thm: string * thm -> thm
    58   val store_thm: string * thm -> thm
    48   val bind_thm: string * thm -> unit
    59   val bind_thm: string * thm -> unit
    49   val qed: string -> unit
    60   val qed: string -> unit
    50   val qed_thm: thm ref
    61   val qed_thm: thm ref
    51   val qed_goal: string -> theory -> string -> (thm list -> tactic list) -> unit
    62   val qed_goal: string -> theory -> string -> (thm list -> tactic list) -> unit
    53                  -> unit
    64                  -> unit
    54   val get_thm: theory -> string -> thm
    65   val get_thm: theory -> string -> thm
    55   val thms_of: theory -> (string * thm) list
    66   val thms_of: theory -> (string * thm) list
    56   val simpset_of: string -> Simplifier.simpset
    67   val simpset_of: string -> Simplifier.simpset
    57   val print_theory: theory -> unit
    68   val print_theory: theory -> unit
       
    69 
       
    70   val gif_path       : string ref
       
    71   val chart00_path   : string ref
       
    72   val make_html      : bool ref
       
    73   val init_html: unit -> unit
       
    74   val make_chart: unit -> unit
    58 end;
    75 end;
    59 
    76 
    60 
    77 
    61 functor ReadthyFun(structure ThySyn: THY_SYN and ThmDB: THMDB): READTHY =
    78 functor ReadthyFun(structure ThySyn: THY_SYN and ThmDB: THMDB): READTHY =
    62 struct
    79 struct
    64 open ThmDB Simplifier;
    81 open ThmDB Simplifier;
    65 
    82 
    66 datatype basetype = Thy  of string
    83 datatype basetype = Thy  of string
    67                   | File of string;
    84                   | File of string;
    68 
    85 
    69 val loaded_thys = ref (Symtab.make [("ProtoPure",
    86 val loaded_thys =
    70                                      ThyInfo {path = "",
    87   ref (Symtab.make [("ProtoPure",
    71                                        children = ["Pure", "CPure"],
    88                      ThyInfo {path = "",
    72                                        thy_time = Some "", ml_time = Some "",
    89                               children = ["Pure", "CPure"], parents = [],
    73                                        theory = Some proto_pure_thy,
    90                               thy_time = Some "", ml_time = Some "",
    74                                        thms = Symtab.null,
    91                               theory = Some proto_pure_thy, thms = Symtab.null,
    75                                        thy_ss = None, simpset = None}),
    92                               thy_ss = None, simpset = None}),
    76                                     ("Pure", ThyInfo {path = "", children = [],
    93                     ("Pure",
    77                                        thy_time = Some "", ml_time = Some "",
    94                      ThyInfo {path = "", children = [],
    78                                        theory = Some pure_thy,
    95                               parents = ["ProtoPure"],
    79                                        thms = Symtab.null,
    96                               thy_time = Some "", ml_time = Some "",
    80                                        thy_ss = None, simpset = None}),
    97                               theory = Some pure_thy, thms = Symtab.null,
    81                                     ("CPure", ThyInfo {path = "",
    98                               thy_ss = None, simpset = None}),
    82                                        children = [],
    99                     ("CPure",
    83                                        thy_time = Some "", ml_time = Some "",
   100                      ThyInfo {path = "",
    84                                        theory = Some cpure_thy,
   101                               children = [], parents = ["ProtoPure"],
    85                                        thms = Symtab.null,
   102                               thy_time = Some "", ml_time = Some "",
    86                                        thy_ss = None, simpset = None})
   103                               theory = Some cpure_thy,
    87                                    ]);
   104                               thms = Symtab.null,
    88 
   105                               thy_ss = None, simpset = None})
    89 val loadpath = ref ["."];           (*default search path for theory files *)
   106                    ]);
    90 
   107 
    91 val delete_tmpfiles = ref true;         (*remove temporary files after use *)
   108 val loadpath = ref ["."];              (*default search path for theory files*)
       
   109 
       
   110 val delete_tmpfiles = ref true;            (*remove temporary files after use*)
       
   111 
       
   112 
       
   113 (*Set location of graphics for HTML files
       
   114   (When this is executed for the first time we are in $ISABELLE/Pure/Thy.
       
   115    This path is converted to $ISABELLE/Tools by removing the last two
       
   116    directories and appending "Tools". All subsequently made ReadThy
       
   117    structures inherit this value.)
       
   118 *)
       
   119 val gif_path = ref (tack_on ("/" ^
       
   120   space_implode "/" (rev (tl (tl (rev (space_explode "/" (pwd ())))))))
       
   121   "Tools");
       
   122 
       
   123 (*Location of theory-list.txt and 00-chart.html (normally set by init_html)*)
       
   124 val chart00_path = ref "";     
       
   125 
       
   126 val make_html = ref false;      (*don't make HTML versions of loaded theories*)
       
   127 
       
   128 (*HTML file of theory currently being read
       
   129   (Initialized by thyfile2html; used by use_thy and store_thm)*)
       
   130 val cur_htmlfile = ref None : outstream option ref;
       
   131                                    
    92 
   132 
    93 (*Make name of the output ML file for a theory *)
   133 (*Make name of the output ML file for a theory *)
    94 fun out_name tname = "." ^ tname ^ ".thy.ML";
   134 fun out_name tname = "." ^ tname ^ ".thy.ML";
    95 
   135 
    96 (*Read a file specified by thy_file containing theory thy *)
   136 (*Read a file specified by thy_file containing theory thy *)
   134           else
   174           else
   135             (false, false)
   175             (false, false)
   136        end
   176        end
   137     | None => (false, false)
   177     | None => (false, false)
   138 
   178 
       
   179 (*Get all direct descendants of a theory*)
       
   180 fun children_of t =
       
   181   case get_thyinfo t of Some (ThyInfo {children, ...}) => children
       
   182                       | _ => [];
       
   183 
   139 (*Get all direct ancestors of a theory*)
   184 (*Get all direct ancestors of a theory*)
   140 fun get_parents child =
   185 fun parents_of t =
   141   let fun has_child (tname, ThyInfo {children, theory, ...}) = 
   186   case get_thyinfo t of Some (ThyInfo {parents, ...}) => parents
   142         if child mem children then Some tname else None;
   187                       | _ => [];
   143   in mapfilter has_child (Symtab.dest (!loaded_thys)) end;
       
   144 
   188 
   145 (*Get all descendants of a theory list *)
   189 (*Get all descendants of a theory list *)
   146 fun get_descendants [] = []
   190 fun get_descendants [] = []
   147   | get_descendants (t :: ts) =
   191   | get_descendants (t :: ts) =
   148       let val tinfo = get_thyinfo t
   192       let val children = children_of t
   149       in if is_some tinfo then
   193       in children union (get_descendants (children union ts)) end;
   150            let val ThyInfo {children, ...} = the tinfo
       
   151            in children union (get_descendants (children union ts))
       
   152            end
       
   153          else []
       
   154       end;
       
   155 
   194 
   156 (*Get theory object for a loaded theory *)
   195 (*Get theory object for a loaded theory *)
   157 fun get_theory name =
   196 fun theory_of name =
   158   let val ThyInfo {theory, ...} = the (get_thyinfo name)
   197   let val ThyInfo {theory, ...} = the (get_thyinfo name)
   159   in the theory end;
   198   in the theory end;
       
   199 
       
   200 (*Get path where theory's files are located*)
       
   201 fun path_of tname =
       
   202   let val ThyInfo {path, ...} = the (get_thyinfo tname)
       
   203   in path end;
   160 
   204 
   161 exception FILE_NOT_FOUND;   (*raised by find_file *)
   205 exception FILE_NOT_FOUND;   (*raised by find_file *)
   162 
   206 
   163 (*Find a file using a list of paths if no absolute or relative path is
   207 (*Find a file using a list of paths if no absolute or relative path is
   164   specified.*)
   208   specified.*)
   165 fun find_file "" name =
   209 fun find_file "" name =
   166       let fun find_it (curr :: paths) =
   210       let fun find_it (cur :: paths) =
   167                 if file_exists (tack_on curr name) then
   211                 if file_exists (tack_on cur name) then
   168                     tack_on curr name
   212                   (if cur = "." then name else tack_on cur name)
   169                 else
   213                 else
   170                     find_it paths
   214                   find_it paths
   171            | find_it [] = ""
   215            | find_it [] = ""
   172       in find_it (!loadpath) end
   216       in find_it (!loadpath) end
   173   | find_file path name =
   217   | find_file path name =
   174       if file_exists (tack_on path name) then tack_on path name
   218       if file_exists (tack_on path name) then tack_on path name
   175                                          else "";
   219                                          else "";
   217      else new_filename ()
   261      else new_filename ()
   218   end;
   262   end;
   219 
   263 
   220 (*Remove theory from all child lists in loaded_thys *)
   264 (*Remove theory from all child lists in loaded_thys *)
   221 fun unlink_thy tname =
   265 fun unlink_thy tname =
   222   let fun remove (ThyInfo {path, children, thy_time, ml_time, theory, thms,
   266   let fun remove (ThyInfo {path, children, parents, thy_time, ml_time,
   223                            thy_ss, simpset}) =
   267                            theory, thms, thy_ss, simpset}) =
   224         ThyInfo {path = path, children = children \ tname,
   268         ThyInfo {path = path, children = children \ tname, parents = parents,
   225                  thy_time = thy_time, ml_time = ml_time, theory = theory, 
   269                  thy_time = thy_time, ml_time = ml_time, theory = theory, 
   226                  thms = thms, thy_ss = thy_ss, simpset = simpset}
   270                  thms = thms, thy_ss = thy_ss, simpset = simpset}
   227   in loaded_thys := Symtab.map remove (!loaded_thys) end;
   271   in loaded_thys := Symtab.map remove (!loaded_thys) end;
   228 
   272 
   229 (*Remove a theory from loaded_thys *)
   273 (*Remove a theory from loaded_thys *)
   232                  (Symtab.dest (!loaded_thys)));
   276                  (Symtab.dest (!loaded_thys)));
   233 
   277 
   234 (*Change thy_time and ml_time for an existent item *)
   278 (*Change thy_time and ml_time for an existent item *)
   235 fun set_info tname thy_time ml_time =
   279 fun set_info tname thy_time ml_time =
   236   let val tinfo = case Symtab.lookup (!loaded_thys, tname) of
   280   let val tinfo = case Symtab.lookup (!loaded_thys, tname) of
   237           Some (ThyInfo {path, children, theory, thms, thy_ss, simpset,...}) =>
   281           Some (ThyInfo {path, children, parents, theory, thms,
   238             ThyInfo {path = path, children = children,
   282                          thy_ss, simpset,...}) =>
       
   283             ThyInfo {path = path, children = children, parents = parents,
   239                      thy_time = thy_time, ml_time = ml_time,
   284                      thy_time = thy_time, ml_time = ml_time,
   240                      theory = theory, thms = thms,
   285                      theory = theory, thms = thms,
   241                      thy_ss = thy_ss, simpset = simpset}
   286                      thy_ss = thy_ss, simpset = simpset}
   242         | None => ThyInfo {path = "", children = [],
   287         | None => error ("set_info: theory " ^ tname ^ " not found");
   243                            thy_time = thy_time, ml_time = ml_time,
       
   244                            theory = None, thms = Symtab.null,
       
   245                            thy_ss = None, simpset = None};
       
   246   in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys)
   288   in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys)
   247   end;
   289   end;
   248 
   290 
   249 (*Mark theory as changed since last read if it has been completly read *)
   291 (*Mark theory as changed since last read if it has been completly read *)
   250 fun mark_outdated tname =
   292 fun mark_outdated tname =
   251   let val t = get_thyinfo tname;
   293   let val t = get_thyinfo tname;
   252   in if is_none t then ()
   294   in if is_none t then ()
   253      else let val ThyInfo {thy_time, ml_time, ...} = the t
   295      else
   254           in set_info tname
   296        let val ThyInfo {thy_time, ml_time, ...} = the t
   255                       (if is_none thy_time then None else Some "")
   297        in set_info tname (if is_none thy_time then None else Some "")
   256                       (if is_none ml_time then None else Some "")
   298                          (if is_none ml_time then None else Some "")
   257                       
   299        end
   258           end
   300   end;
   259   end;
   301 
       
   302 (*Make head of HTML dependency charts
       
   303   Parameters are:
       
   304     file: HTML file
       
   305     tname: theory name
       
   306     suffix: suffix of complementary chart
       
   307             (sup if this head is for a sub-chart, sub if it is for a sup-chart;
       
   308              empty for Pure and CPure sub-charts)
       
   309     gif_path: relative path to directory containing GIFs
       
   310     chart00_path: relative path to directory containing main theory chart
       
   311 *)
       
   312 fun mk_charthead file tname title green_arrow gif_path chart00_path package =
       
   313   output (file,
       
   314    "<HTML><HEAD><TITLE>" ^ title ^ " of " ^ tname ^
       
   315    "</TITLE></HEAD>\n<H2>" ^ title ^ " of theory " ^ tname ^
       
   316    "</H2>\nThe name of every theory is linked to its theory file<BR>\n" ^
       
   317    "<IMG SRC = \"" ^ tack_on gif_path "red_arrow.gif\
       
   318    \\" ALT = \\/></A> stands for subtheories (child theories)<BR>\n\
       
   319    \<IMG SRC = \"" ^ tack_on gif_path "blue_arrow.gif\
       
   320    \\" ALT = /\\></A> stands for supertheories (parent theories)\n" ^
       
   321    (if not green_arrow then "" else
       
   322       "<BR><IMG SRC = \"" ^ tack_on gif_path "green_arrow.gif\
       
   323       \\" ALT = &gt;></A> stands for repeated subtrees") ^
       
   324    "<P><A HREF = \"" ^ tack_on chart00_path "00-chart.html\
       
   325    \\">Back</A> to the main theory chart of " ^ package ^ ".\n<HR>\n<PRE>");
       
   326 
       
   327 (*Convert .thy file to HTML and make chart of its super-theories*)
       
   328 fun thyfile2html tpath tname =
       
   329   let
       
   330     val gif_path = relative_path tpath (!gif_path);
       
   331     val package = hd (rev (space_explode "/" (!chart00_path)));
       
   332     val chart00_path = relative_path tpath (!chart00_path);
       
   333 
       
   334     (*Make list of all theories and all theories that own a .thy file*)
       
   335     fun list_theories [] theories thy_files = (theories, thy_files)
       
   336       | list_theories ((tname, ThyInfo {thy_time, ...}) :: ts)
       
   337                       theories thy_files =
       
   338           list_theories ts (tname :: theories)
       
   339             (if is_some thy_time andalso the thy_time <> "" then
       
   340                tname :: thy_files
       
   341              else thy_files);
       
   342 
       
   343     val (theories, thy_files) =
       
   344       list_theories (Symtab.dest (!loaded_thys)) [] [];
       
   345 
       
   346     (*Do the conversion*)
       
   347     fun gettext thy_file  =
       
   348       let
       
   349         (*Convert special HTML characters ('&', '>', and '<')*)
       
   350         val file =
       
   351           explode (execute ("sed -e 's/\\&/\\&amp;/g' -e 's/>/\\&gt;/g' \
       
   352                             \-e 's/</\\&lt;/g' " ^ thy_file));
       
   353 
       
   354         (*Isolate first (possibly nested) comment;
       
   355           skip all leading whitespaces*)
       
   356         val (comment, file') =
       
   357           let fun first_comment ("*" :: ")" :: cs) co 1 = (co ^ "*)", cs)
       
   358                 | first_comment ("*" :: ")" :: cs) co d =
       
   359                     first_comment cs (co ^ "*)") (d-1)
       
   360                 | first_comment ("(" :: "*" :: cs) co d =
       
   361                     first_comment cs (co ^ "(*") (d+1)
       
   362                 | first_comment (" "  :: cs) "" 0 = first_comment cs "" 0
       
   363                 | first_comment ("\n" :: cs) "" 0 = first_comment cs "" 0
       
   364                 | first_comment ("\t" :: cs) "" 0 = first_comment cs "" 0
       
   365                 | first_comment cs           "" 0 = ("", cs)
       
   366                 | first_comment (c :: cs) co d =
       
   367                     first_comment cs (co ^ implode [c]) d
       
   368                 | first_comment [] co _ =
       
   369                     error ("Unexpected end of file " ^ tname ^ ".thy.");
       
   370           in first_comment file "" 0 end;
       
   371 
       
   372         (*Process line defining theory's ancestors;
       
   373           convert valid theory names to links to their HTML file*)
       
   374         val (ancestors, body) =
       
   375           let
       
   376             fun make_links l result =
       
   377               let val (pre, letter) = take_prefix (not o is_letter) l;
       
   378 
       
   379                   val (id, rest) =
       
   380                     take_prefix (is_quasi_letter orf is_digit) letter;
       
   381 
       
   382                   val id = implode id;
       
   383 
       
   384                   (*Make a HTML link out of a theory name*)
       
   385                   fun make_link t =
       
   386                     let val path = path_of t;
       
   387                     in "<A HREF = \"" ^
       
   388                        tack_on (relative_path tpath path) t ^
       
   389                        ".html\">" ^ t ^ "</A>" end;
       
   390               in if not (id mem theories) then (result, implode l)
       
   391                  else if id mem thy_files then
       
   392                    make_links rest (result ^ implode pre ^ make_link id)
       
   393                  else make_links rest (result ^ implode pre ^ id)
       
   394               end;
       
   395 
       
   396             val (pre, rest) = take_prefix (fn c => c <> "=") file';
       
   397 
       
   398             val (ancestors, body) =
       
   399               if null rest then
       
   400                 error ("Missing \"=\" in file " ^ tname ^ ".thy.\n\
       
   401                        \(Make sure that the last line ends with a linebreak.)")
       
   402               else
       
   403                 make_links rest "";
       
   404           in (implode pre ^ ancestors, body) end;
       
   405       in "<HTML><HEAD><TITLE>" ^ tname ^ ".thy</TITLE></HEAD>\n\n<BODY>\n" ^
       
   406          "<H2>" ^ tname ^ ".thy</H2>\n<A HREF = \"" ^
       
   407          tack_on chart00_path "00-chart.html\
       
   408          \\">Back</A> to the main theory chart of " ^ package ^
       
   409          ".\n<HR>\n\n<PRE>\n" ^ comment ^ ancestors ^ body ^
       
   410          "</PRE>\n<HR><H2>Theorems proved in <A HREF = \"" ^ tname ^
       
   411          ".ML\">" ^ tname ^ ".ML</A>:</H2>\n"
       
   412       end;
       
   413 
       
   414     (** Make chart of super-theories **)
       
   415 
       
   416     val sup_out = open_out (tack_on tpath tname ^ "_sup.html");
       
   417     val sub_out = open_out (tack_on tpath tname ^ "_sub.html");
       
   418 
       
   419     (*Theories that already have been listed in this chart*)
       
   420     val listed = ref [];
       
   421 
       
   422     val wanted_theories =
       
   423       filter (fn s => s mem thy_files orelse s = "Pure" orelse s = "CPure")
       
   424              theories;
       
   425 
       
   426     (*Make nested list of theories*)
       
   427     fun list_ancestors tname level continued =
       
   428       let
       
   429         fun mk_entry [] = ()
       
   430           | mk_entry (t::ts) =
       
   431             let
       
   432               val is_pure = t = "Pure" orelse t = "CPure";
       
   433               val path = path_of t;
       
   434               val rel_path = if is_pure then chart00_path
       
   435                              else relative_path tpath path;
       
   436 
       
   437               fun mk_offset [] cur =
       
   438                     if level < cur then error "Error in mk_offset"
       
   439                     else implode (replicate (level - cur) "    ")
       
   440                 | mk_offset (l::ls) cur =
       
   441                     implode (replicate (l - cur) "    ") ^ "|   " ^
       
   442                     mk_offset ls (l+1);
       
   443             in output (sup_out,
       
   444                  " " ^ mk_offset continued 0 ^
       
   445                  "\\__" ^ (if is_pure then t else "<A HREF=\"" ^ 
       
   446                              tack_on rel_path t ^ ".html\">" ^ t ^ "</A>") ^
       
   447                  " <A HREF = \"" ^ tack_on rel_path t ^
       
   448                  "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^
       
   449                  tack_on gif_path "red_arrow.gif\" ALT = \\/></A>" ^
       
   450                  (if is_pure then ""
       
   451                   else "<A HREF = \"" ^ tack_on rel_path t ^
       
   452                        "_sup.html\"><IMG ALIGN=TOP SRC = \"" ^
       
   453                        tack_on gif_path "blue_arrow.gif\
       
   454                        \\" ALT = /\\></A>"));
       
   455               if t mem (!listed) andalso not (null (parents_of t)) then
       
   456                 output (sup_out,
       
   457                   "<A HREF = \"" ^ tack_on rel_path t ^ "_sup.html\">\
       
   458                   \<IMG ALIGN=TOP SRC = \"" ^
       
   459                   tack_on gif_path "green_arrow.gif\" ALT = &gt;></A>\n")
       
   460               else (output (sup_out, "\n");
       
   461                     listed := t :: (!listed);
       
   462                     list_ancestors t (level+1) (if null ts then continued
       
   463                                                 else continued @ [level]);
       
   464                     mk_entry ts)
       
   465             end;
       
   466 
       
   467         val relatives =
       
   468           filter (fn s => s mem wanted_theories) (parents_of tname);
       
   469       in mk_entry relatives end;
       
   470   in if is_some (!cur_htmlfile) then
       
   471        error "thyfile2html: Last theory's HTML has not been closed."
       
   472      else ();
       
   473      cur_htmlfile := Some (open_out (tack_on tpath tname ^ ".html"));
       
   474      output (the (!cur_htmlfile), gettext (tack_on tpath tname ^ ".thy"));
       
   475 
       
   476      mk_charthead sup_out tname "Ancestors" true gif_path chart00_path package;
       
   477      output(sup_out,
       
   478        "<A HREF=\"" ^ tname ^ ".html\">" ^ tname ^ "</A> \
       
   479        \<A HREF = \"" ^ tname ^ "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^
       
   480        tack_on gif_path "red_arrow.gif\" ALT = \\/></A>\n");
       
   481      list_ancestors tname 0 [];
       
   482      output (sup_out, "</PRE><HR></BODY></HTML>");
       
   483      close_out sup_out;
       
   484 
       
   485      mk_charthead sub_out tname "Children" false gif_path chart00_path package;
       
   486      output(sub_out,
       
   487        "<A HREF=\"" ^ tname ^ ".html\">" ^ tname ^ "</A> \
       
   488        \<A HREF = \"" ^ tname ^ "_sup.html\"><IMG SRC = \"" ^
       
   489        tack_on gif_path "blue_arrow.gif\" ALT = \\/></A>\n");
       
   490      close_out sub_out
       
   491   end;
       
   492 
   260 
   493 
   261 (*Read .thy and .ML files that haven't been read yet or have changed since
   494 (*Read .thy and .ML files that haven't been read yet or have changed since
   262   they were last read;
   495   they were last read;
   263   loaded_thys is a thy_info list ref containing all theories that have
   496   loaded_thys is a thy_info list ref containing all theories that have
   264   completly been read by this and preceeding use_thy calls.
   497   completly been read by this and preceeding use_thy calls.
   268     val (path, tname) = split_filename name;
   501     val (path, tname) = split_filename name;
   269     val (thy_file, ml_file) = get_filenames path tname;
   502     val (thy_file, ml_file) = get_filenames path tname;
   270     val (abs_path, _) = if thy_file = "" then split_filename ml_file
   503     val (abs_path, _) = if thy_file = "" then split_filename ml_file
   271                         else split_filename thy_file;
   504                         else split_filename thy_file;
   272     val (thy_uptodate, ml_uptodate) = thy_unchanged tname thy_file ml_file;
   505     val (thy_uptodate, ml_uptodate) = thy_unchanged tname thy_file ml_file;
       
   506     val old_parents = parents_of tname;
   273 
   507 
   274     (*Set absolute path for loaded theory *)
   508     (*Set absolute path for loaded theory *)
   275     fun set_path () =
   509     fun set_path () =
   276       let val ThyInfo {children, thy_time, ml_time, theory, thms, thy_ss,
   510       let val ThyInfo {children, parents, thy_time, ml_time, theory, thms,
   277                        simpset, ...} =
   511                        thy_ss, simpset, ...} =
   278             the (Symtab.lookup (!loaded_thys, tname));
   512             the (Symtab.lookup (!loaded_thys, tname));
   279       in loaded_thys := Symtab.update ((tname,
   513       in loaded_thys := Symtab.update ((tname,
   280                           ThyInfo {path = abs_path, children = children,
   514                           ThyInfo {path = abs_path,
       
   515                                    children = children, parents = parents,
   281                                    thy_time = thy_time, ml_time = ml_time,
   516                                    thy_time = thy_time, ml_time = ml_time,
   282                                    theory = theory, thms = thms,
   517                                    theory = theory, thms = thms,
   283                                    thy_ss = thy_ss, simpset = simpset}),
   518                                    thy_ss = thy_ss, simpset = simpset}),
   284                           !loaded_thys)
   519                           !loaded_thys)
   285       end;
   520       end;
   286 
   521 
   287     (*Mark all direct descendants of a theory as changed *)
   522     (*Mark all direct descendants of a theory as changed *)
   288     fun mark_children thy =
   523     fun mark_children thy =
   289       let val ThyInfo {children, ...} = the (get_thyinfo thy);
   524       let val children = children_of thy;
   290           val present = filter (is_some o get_thyinfo) children;
   525           val present = filter (is_some o get_thyinfo) children;
   291           val loaded = filter already_loaded present;
   526           val loaded = filter already_loaded present;
   292       in if loaded <> [] then
   527       in if loaded <> [] then
   293            writeln ("The following children of theory " ^ (quote thy)
   528            writeln ("The following children of theory " ^ (quote thy)
   294                     ^ " are now out-of-date: "
   529                     ^ " are now out-of-date: "
   299 
   534 
   300     (*Remove theorems associated with a theory*)
   535     (*Remove theorems associated with a theory*)
   301     fun delete_thms () =
   536     fun delete_thms () =
   302       let
   537       let
   303         val tinfo = case get_thyinfo tname of
   538         val tinfo = case get_thyinfo tname of
   304             Some (ThyInfo {path, children, thy_time, ml_time, theory, thy_ss,
   539             Some (ThyInfo {path, children, parents, thy_time, ml_time, theory,
   305                            simpset, ...}) =>
   540                            thy_ss, simpset, ...}) =>
   306               ThyInfo {path = path, children = children,
   541               ThyInfo {path = path, children = children, parents = parents,
   307                        thy_time = thy_time, ml_time = ml_time,
   542                        thy_time = thy_time, ml_time = ml_time,
   308                        theory = theory, thms = Symtab.null,
   543                        theory = theory, thms = Symtab.null,
   309                        thy_ss = thy_ss, simpset = simpset}
   544                        thy_ss = thy_ss, simpset = simpset}
   310           | None => ThyInfo {path = "", children = [],
   545           | None => ThyInfo {path = "", children = [], parents = [],
   311                              thy_time = None, ml_time = None,
   546                              thy_time = None, ml_time = None,
   312                              theory = None, thms = Symtab.null,
   547                              theory = None, thms = Symtab.null,
   313                              thy_ss = None, simpset = None};
   548                              thy_ss = None, simpset = None};
   314 
   549 
   315         val ThyInfo {theory, ...} = tinfo;
   550         val ThyInfo {theory, ...} = tinfo;
   318              Some t => delete_thm_db t
   553              Some t => delete_thm_db t
   319            | None => ()
   554            | None => ()
   320       end;
   555       end;
   321 
   556 
   322     fun save_thy_ss () =
   557     fun save_thy_ss () =
   323       let val ThyInfo {path, children, thy_time, ml_time, theory, thms,
   558       let val ThyInfo {path, children, parents, thy_time, ml_time,
   324                        simpset, ...} = the (get_thyinfo tname);
   559                        theory, thms, simpset, ...} = the (get_thyinfo tname);
   325       in loaded_thys := Symtab.update
   560       in loaded_thys := Symtab.update
   326            ((tname, ThyInfo {path = path, children = children,
   561            ((tname, ThyInfo {path = path,
       
   562                              children = children, parents = parents,
   327                              thy_time = thy_time, ml_time = ml_time,
   563                              thy_time = thy_time, ml_time = ml_time,
   328                              theory = theory, thms = thms,
   564                              theory = theory, thms = thms,
   329                              thy_ss = Some (!Simplifier.simpset),
   565                              thy_ss = Some (!Simplifier.simpset),
   330                              simpset = simpset}),
   566                              simpset = simpset}),
   331             !loaded_thys)
   567             !loaded_thys)
   332       end;
   568       end;
   333 
   569 
   334     fun save_simpset () =
   570     fun save_simpset () =
   335       let val ThyInfo {path, children, thy_time, ml_time, theory, thms,
   571       let val ThyInfo {path, children, parents, thy_time, ml_time,
   336                        thy_ss, ...} = the (get_thyinfo tname);
   572                        theory, thms, thy_ss, ...} = the (get_thyinfo tname);
   337       in loaded_thys := Symtab.update
   573       in loaded_thys := Symtab.update
   338            ((tname, ThyInfo {path = path, children = children,
   574            ((tname, ThyInfo {path = path,
       
   575                              children = children, parents = parents,
   339                              thy_time = thy_time, ml_time = ml_time,
   576                              thy_time = thy_time, ml_time = ml_time,
   340                              theory = theory, thms = thms,
   577                              theory = theory, thms = thms,
   341                              thy_ss = thy_ss,
   578                              thy_ss = thy_ss,
   342                              simpset = Some (!Simplifier.simpset)}),
   579                              simpset = Some (!Simplifier.simpset)}),
   343             !loaded_thys)
   580             !loaded_thys)
   344       end;
   581       end;
   345 
   582 
       
   583    (*Add theory to file listing all loaded theories (for 00-chart.html)
       
   584      and to the sub-charts of its parents*)
       
   585    fun mk_html () =
       
   586      let val new_parents = parents_of tname \\ old_parents;
       
   587 
       
   588          (*Add child to parents' sub-theory charts*)
       
   589          fun add_to_parents t =
       
   590            let val is_pure = t = "Pure" orelse t = "CPure";
       
   591                val path = if is_pure then (!chart00_path) else path_of t;
       
   592 
       
   593                val gif_path = relative_path path (!gif_path);
       
   594                val rel_path = relative_path path abs_path;
       
   595 
       
   596                val out = open_append (tack_on path t ^ "_sub.html");
       
   597            in output (out,
       
   598                 " |\n \\__<A HREF=\"" ^ tack_on rel_path tname ^ ".html\">" ^
       
   599                 tname ^ "</A> <A HREF = \"" ^
       
   600                 tack_on rel_path tname ^
       
   601                 "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^
       
   602                 tack_on gif_path "red_arrow.gif\" ALT = \\/></A>\
       
   603                 \<A HREF = \"" ^ tack_on rel_path tname ^ "_sup.html\">\
       
   604                 \<IMG ALIGN=TOP SRC = \"" ^ tack_on gif_path "blue_arrow.gif\
       
   605                 \\" ALT = /\\></A>\n");
       
   606               close_out out
       
   607            end;
       
   608 
       
   609          val theory_list =
       
   610            open_append (tack_on (!chart00_path) "theory_list.txt");
       
   611      in output (theory_list, tname ^ " " ^ abs_path ^ "\n");
       
   612         close_out theory_list;
       
   613 
       
   614         seq add_to_parents new_parents
       
   615      end
   346   in if thy_uptodate andalso ml_uptodate then ()
   616   in if thy_uptodate andalso ml_uptodate then ()
   347      else
   617      else
   348      (
   618       (if thy_file = "" then ()
   349        if thy_file = "" then ()
       
   350        else if thy_uptodate then
   619        else if thy_uptodate then
   351          simpset := let val ThyInfo {thy_ss, ...} = the (get_thyinfo tname);
   620          simpset := let val ThyInfo {thy_ss, ...} = the (get_thyinfo tname);
   352                     in the thy_ss end
   621                     in the thy_ss end
   353        else
   622        else
   354          (writeln ("Reading \"" ^ name ^ ".thy\"");
   623          (writeln ("Reading \"" ^ name ^ ".thy\"");
       
   624 
   355           delete_thms ();
   625           delete_thms ();
   356           read_thy tname thy_file;
   626           read_thy tname thy_file;
   357           use (out_name tname);
   627           use (out_name tname);
   358           save_thy_ss ();
   628           save_thy_ss ();
   359 
   629 
   360           if not (!delete_tmpfiles) then ()
   630           if not (!delete_tmpfiles) then ()
   361           else delete_file (out_name tname)
   631           else delete_file (out_name tname);
       
   632 
       
   633           if not (!make_html) then ()
       
   634           else thyfile2html abs_path tname
   362          );
   635          );
   363 
   636 
   364        set_info tname (Some (file_info thy_file)) None;
   637        set_info tname (Some (file_info thy_file)) None;
   365                                        (*mark thy_file as successfully loaded*)
   638                                        (*mark thy_file as successfully loaded*)
   366 
   639 
   373        use_string
   646        use_string
   374          ["val _ = store_theory (" ^ tname ^ ".thy, " ^ quote tname ^ ");"];
   647          ["val _ = store_theory (" ^ tname ^ ".thy, " ^ quote tname ^ ");"];
   375 
   648 
   376        (*Store axioms of theory
   649        (*Store axioms of theory
   377          (but only if it's not a copy of an older theory)*)
   650          (but only if it's not a copy of an older theory)*)
   378        let val parents = get_parents tname;
   651        let val parents = parents_of tname;
   379            val fst_thy = get_theory (hd parents);
   652            val this_thy = theory_of tname;
   380            val this_thy = get_theory tname;
       
   381            val axioms =
   653            val axioms =
   382              if length parents = 1
   654              if length parents = 1
   383                 andalso Sign.eq_sg (sign_of fst_thy, sign_of this_thy) then []
   655                 andalso Sign.eq_sg (sign_of (theory_of (hd parents)),
       
   656                                     sign_of this_thy) then []
   384              else axioms_of this_thy;
   657              else axioms_of this_thy;
   385        in map store_thm_db axioms end;
   658        in map store_thm_db axioms end;
       
   659 
       
   660        (*Add theory to list of all loaded theories (for 00-chart.html)
       
   661          and add it to its parents' sub-charts*)
       
   662        if !make_html then
       
   663          let val path = path_of tname;
       
   664          in if path = "" then mk_html ()    (*first time theory has been read*)
       
   665             else ()
       
   666          end
       
   667        else ();
   386 
   668 
   387        (*Now set the correct info*)
   669        (*Now set the correct info*)
   388        set_info tname (Some (file_info thy_file)) (Some (file_info ml_file));
   670        set_info tname (Some (file_info thy_file)) (Some (file_info ml_file));
   389        set_path ();
   671        set_path ();
   390 
   672 
   391        (*Mark theories that have to be reloaded*)
   673        (*Mark theories that have to be reloaded*)
   392        mark_children tname
   674        mark_children tname;
       
   675 
       
   676        (*Close HTML file*)
       
   677        case !cur_htmlfile of
       
   678            Some out => (output (out, "<HR></BODY></HTML>\n");
       
   679                         close_out out;
       
   680                         cur_htmlfile := None)
       
   681          | None => ()
   393       )
   682       )
   394   end;
   683   end;
   395 
   684 
   396 fun time_use_thy tname = timeit(fn()=>
   685 fun time_use_thy tname = timeit(fn()=>
   397    (writeln("\n**** Starting Theory " ^ tname ^ " ****");
   686    (writeln("\n**** Starting Theory " ^ tname ^ " ****");
   403   all theories that depend on them *)
   692   all theories that depend on them *)
   404 fun update () =
   693 fun update () =
   405   let (*List theories in the order they have to be loaded *)
   694   let (*List theories in the order they have to be loaded *)
   406       fun load_order [] result = result
   695       fun load_order [] result = result
   407         | load_order thys result =
   696         | load_order thys result =
   408             let fun next_level (t :: ts) =
   697             let fun next_level [] = []
   409                       let val thy = get_thyinfo t
   698                   | next_level (t :: ts) =
   410                       in if is_some thy then
   699                       let val children = children_of t
   411                              let val ThyInfo {children, ...} = the thy
   700                       in children union (next_level ts) end;
   412                              in children union (next_level ts) end
   701 
   413                          else next_level ts
   702                 val descendants = next_level thys;
   414                       end
   703             in load_order descendants ((result \\ descendants) @ descendants)
   415                   | next_level [] = [];
   704             end;
   416 
       
   417                 val children = next_level thys;
       
   418             in load_order children ((result \\ children) @ children) end;
       
   419 
   705 
   420       fun reload_changed (t :: ts) =
   706       fun reload_changed (t :: ts) =
   421             let val thy = get_thyinfo t;
   707             let fun abspath () = case get_thyinfo t of
   422 
   708                                      Some (ThyInfo {path, ...}) => path
   423                 fun abspath () =
   709                                    | None => "";
   424                   if is_some thy then
       
   425                     let val ThyInfo {path, ...} = the thy in path end
       
   426                   else "";
       
   427 
   710 
   428                 val (thy_file, ml_file) = get_filenames (abspath ()) t;
   711                 val (thy_file, ml_file) = get_filenames (abspath ()) t;
   429                 val (thy_uptodate, ml_uptodate) =
   712                 val (thy_uptodate, ml_uptodate) =
   430                         thy_unchanged t thy_file ml_file;
   713                         thy_unchanged t thy_file ml_file;
   431             in if thy_uptodate andalso ml_uptodate then ()
   714             in if thy_uptodate andalso ml_uptodate then ()
   451   end;
   734   end;
   452 
   735 
   453 (*Merge theories to build a base for a new theory.
   736 (*Merge theories to build a base for a new theory.
   454   Base members are only loaded if they are missing.*)
   737   Base members are only loaded if they are missing.*)
   455 fun mk_base bases child mk_draft =
   738 fun mk_base bases child mk_draft =
   456   let (*Show the cycle that would be created by add_child *)
   739   let (*Show the cycle that would be created by add_child*)
   457       fun show_cycle base =
   740       fun show_cycle base =
   458         let fun find_it result curr =
   741         let fun find_it result curr =
   459               let val tinfo = get_thyinfo curr
   742               let val tinfo = get_thyinfo curr
   460               in if base = curr then
   743               in if base = curr then
   461                    error ("Cyclic dependency of theories: "
   744                    error ("Cyclic dependency of theories: "
   466                    end
   749                    end
   467                  else ()
   750                  else ()
   468               end
   751               end
   469         in find_it "" child end;
   752         in find_it "" child end;
   470 
   753 
   471       (*Check if a cycle would be created by add_child *)
   754       (*Check if a cycle would be created by add_child*)
   472       fun find_cycle base =
   755       fun find_cycle base =
   473         if base mem (get_descendants [child]) then show_cycle base
   756         if base mem (get_descendants [child]) then show_cycle base
   474         else ();
   757         else ();
   475 
   758 
   476       (*Add child to child list of base *)
   759       (*Add child to child list of base*)
   477       fun add_child base =
   760       fun add_child base =
   478         let val tinfo =
   761         let val tinfo =
   479               case Symtab.lookup (!loaded_thys, base) of
   762               case Symtab.lookup (!loaded_thys, base) of
   480                   Some (ThyInfo {path, children, thy_time, ml_time,
   763                   Some (ThyInfo {path, children, parents, thy_time, ml_time,
   481                            theory, thms, thy_ss, simpset}) =>
   764                            theory, thms, thy_ss, simpset}) =>
   482                     ThyInfo {path = path, children = child ins children,
   765                     ThyInfo {path = path,
       
   766                              children = child ins children, parents = parents,
   483                              thy_time = thy_time, ml_time = ml_time,
   767                              thy_time = thy_time, ml_time = ml_time,
   484                              theory = theory, thms = thms,
   768                              theory = theory, thms = thms,
   485                              thy_ss = thy_ss, simpset = simpset}
   769                              thy_ss = thy_ss, simpset = simpset}
   486                 | None => ThyInfo {path = "", children = [child],
   770                 | None => ThyInfo {path = "", children = [child], parents = [],
   487                                    thy_time = None, ml_time = None,
   771                                    thy_time = None, ml_time = None,
   488                                    theory = None, thms = Symtab.null,
   772                                    theory = None, thms = Symtab.null,
   489                                    thy_ss = None, simpset = None};
   773                                    thy_ss = None, simpset = None};
   490         in loaded_thys := Symtab.update ((base, tinfo), !loaded_thys) end;
   774         in loaded_thys := Symtab.update ((base, tinfo), !loaded_thys) end;
   491 
   775 
   514         in simpset end;
   798         in simpset end;
   515 
   799 
   516       (*Load all needed files and make a list of all real theories *)
   800       (*Load all needed files and make a list of all real theories *)
   517       fun load_base (Thy b :: bs) =
   801       fun load_base (Thy b :: bs) =
   518            (load b;
   802            (load b;
   519             b :: (load_base bs))
   803             b :: load_base bs)
   520         | load_base (File b :: bs) =
   804         | load_base (File b :: bs) =
   521            (load b;
   805            (load b;
   522             load_base bs)                    (*don't add it to mergelist *)
   806             load_base bs)                    (*don't add it to mergelist *)
   523         | load_base [] = [];
   807         | load_base [] = [];
   524 
   808 
   525       val dummy = unlink_thy child;
   809       val dummy = unlink_thy child;
   526       val mergelist = load_base bases;
   810       val mergelist = load_base bases;
   527 
   811 
       
   812       val dummy =
       
   813         let val tinfo = case Symtab.lookup (!loaded_thys, child) of
       
   814               Some (ThyInfo {path, children, thy_time, ml_time, theory, thms,
       
   815                              thy_ss, simpset, ...}) =>
       
   816                  ThyInfo {path = path,
       
   817                           children = children, parents = mergelist,
       
   818                           thy_time = thy_time, ml_time = ml_time,
       
   819                           theory = theory, thms = thms,
       
   820                           thy_ss = thy_ss, simpset = simpset}
       
   821              | None => error ("set_parents: theory " ^ child ^ " not found");
       
   822         in loaded_thys := Symtab.update ((child, tinfo), !loaded_thys) end;
       
   823 
   528       val base_thy = (writeln ("Loading theory " ^ (quote child));
   824       val base_thy = (writeln ("Loading theory " ^ (quote child));
   529                       merge_thy_list mk_draft (map get_theory mergelist));
   825                       merge_thy_list mk_draft (map theory_of mergelist));
   530  in simpset := foldr merge_ss (mapfilter get_simpset mergelist, empty_ss);
   826  in simpset := foldr merge_ss (mapfilter get_simpset mergelist, empty_ss);
   531     base_thy
   827     base_thy
   532  end;
   828  end;
   533 
   829 
   534 (*Change theory object for an existent item of loaded_thys
   830 (*Change theory object for an existent item of loaded_thys*)
   535   or create a new item*)
       
   536 fun store_theory (thy, tname) =
   831 fun store_theory (thy, tname) =
   537   let val tinfo = case Symtab.lookup (!loaded_thys, tname) of
   832   let val tinfo = case Symtab.lookup (!loaded_thys, tname) of
   538                Some (ThyInfo {path, children, thy_time, ml_time, thms,
   833                Some (ThyInfo {path, children, parents, thy_time, ml_time, thms,
   539                               thy_ss, simpset, ...}) =>
   834                               thy_ss, simpset, ...}) =>
   540                  ThyInfo {path = path, children = children,
   835                  ThyInfo {path = path, children = children, parents = parents,
   541                           thy_time = thy_time, ml_time = ml_time,
   836                           thy_time = thy_time, ml_time = ml_time,
   542                           theory = Some thy, thms = thms,
   837                           theory = Some thy, thms = thms,
   543                           thy_ss = thy_ss, simpset = simpset}
   838                           thy_ss = thy_ss, simpset = simpset}
   544              | None => ThyInfo {path = "", children = [],
   839              | None => error ("store_theory: theory " ^ tname ^ " not found");
   545                                 thy_time = None, ml_time = None,
       
   546                                 theory = Some thy, thms = Symtab.null,
       
   547                                 thy_ss = None, simpset = None};
       
   548   in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys)
   840   in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys)
   549   end;
   841   end;
   550 
   842 
   551 
   843 
   552 (** store and retrieve theorems **)
   844 (** store and retrieve theorems **)
   581 val theory_of_thm = theory_of_sign o #sign o rep_thm;
   873 val theory_of_thm = theory_of_sign o #sign o rep_thm;
   582 
   874 
   583 
   875 
   584 (* Store theorems *)
   876 (* Store theorems *)
   585 
   877 
   586 (*Store a theorem in the thy_info of its theory*)
   878 (*Store a theorem in the thy_info of its theory,
       
   879   and in the theory's HTML file*)
   587 fun store_thm (name, thm) =
   880 fun store_thm (name, thm) =
   588   let
   881   let
   589     val (thy_name, ThyInfo {path, children, thy_time, ml_time, theory, thms,
   882     val (thy_name, ThyInfo {path, children, parents, thy_time, ml_time,
   590                             thy_ss, simpset}) =
   883                             theory, thms, thy_ss, simpset}) =
   591       thyinfo_of_sign (#sign (rep_thm thm));
   884       thyinfo_of_sign (#sign (rep_thm thm));
   592 
   885 
   593     val (thms', duplicate) = (Symtab.update_new ((name, thm), thms), false)
   886     val (thms', duplicate) = (Symtab.update_new ((name, thm), thms), false)
   594       handle Symtab.DUPLICATE s => 
   887       handle Symtab.DUPLICATE s => 
   595         (if eq_thm (the (Symtab.lookup (thms, name)), thm) then 
   888         (if eq_thm (the (Symtab.lookup (thms, name)), thm) then 
   596            (writeln ("Warning: Theory database already contains copy of\
   889            (writeln ("Warning: Theory database already contains copy of\
   597                      \ theorem " ^ quote name);
   890                      \ theorem " ^ quote name);
   598             (thms, true))
   891             (thms, true))
   599          else error ("Duplicate theorem name " ^ quote s
   892          else error ("Duplicate theorem name " ^ quote s
   600                      ^ " used in theory database"));
   893                      ^ " used in theory database"));
       
   894 
       
   895     fun thm_to_html () =
       
   896       let fun escape []       = ""
       
   897             | escape ("<"::s) = "&lt;" ^ escape s
       
   898             | escape (">"::s) = "&gt;" ^ escape s
       
   899             | escape ("&"::s) = "&amp;" ^ escape s
       
   900             | escape (c::s)   = c ^ escape s;
       
   901       in case !cur_htmlfile of
       
   902              Some out =>
       
   903                output (out, "<EM>" ^ name ^ "</EM>\n<PRE>" ^
       
   904                             escape (explode (string_of_thm (freeze thm))) ^
       
   905                             "</PRE><P>\n")
       
   906            | None => ()
       
   907       end;
   601   in
   908   in
   602     loaded_thys := Symtab.update
   909     loaded_thys := Symtab.update
   603      ((thy_name, ThyInfo {path = path, children = children,
   910      ((thy_name, ThyInfo {path = path, children = children, parents = parents,
   604                           thy_time = thy_time, ml_time = ml_time,
   911                           thy_time = thy_time, ml_time = ml_time,
   605                           theory = theory, thms = thms',
   912                           theory = theory, thms = thms',
   606                           thy_ss = thy_ss, simpset = simpset}),
   913                           thy_ss = thy_ss, simpset = simpset}),
   607       !loaded_thys);
   914       !loaded_thys);
       
   915     thm_to_html ();
   608     if duplicate then thm else store_thm_db (name, thm)
   916     if duplicate then thm else store_thm_db (name, thm)
   609   end;
   917   end;
   610 
   918 
   611 (*Store result of proof in loaded_thys and as ML value*)
   919 (*Store result of proof in loaded_thys and as ML value*)
   612 
   920 
   613 val qed_thm = ref flexpair_def(*dummy*);
   921 val qed_thm = ref flexpair_def(*dummy*);
   614 
   922 
   615 fun bind_thm (name, thm) =
   923 fun bind_thm (name, thm) =
   616   (qed_thm := standard thm;
   924  (qed_thm := standard thm;
   617    use_string ["val " ^name^ " = store_thm (" ^quote name^", !qed_thm);"]);
   925   store_thm (name, standard thm);
       
   926   use_string ["val " ^ name ^ " = !qed_thm;"]);
   618 
   927 
   619 fun qed name =
   928 fun qed name =
   620   use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^ ", result ());"];
   929  (qed_thm := result ();
       
   930   store_thm (name, !qed_thm);
       
   931   use_string ["val " ^ name ^ " = !qed_thm;"]);
   621 
   932 
   622 fun qed_goal name thy agoal tacsf =
   933 fun qed_goal name thy agoal tacsf =
   623   (qed_thm := prove_goal thy agoal tacsf;
   934  (qed_thm := prove_goal thy agoal tacsf;
   624    use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]);
   935   store_thm (name, !qed_thm);
       
   936   use_string ["val " ^ name ^ " = !qed_thm;"]);
   625 
   937 
   626 fun qed_goalw name thy rths agoal tacsf =
   938 fun qed_goalw name thy rths agoal tacsf =
   627   (qed_thm := prove_goalw thy rths agoal tacsf;
   939  (qed_thm := prove_goalw thy rths agoal tacsf;
   628    use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]);
   940   store_thm (name, !qed_thm);
       
   941   use_string ["val " ^ name ^ " = !qed_thm;"]);
   629 
   942 
   630 
   943 
   631 (* Retrieve theorems *)
   944 (* Retrieve theorems *)
   632 
   945 
   633 (*Get all theorems belonging to a given theory*)
   946 (*Get all theorems belonging to a given theory*)
   646         | get [] ng searched =
   959         | get [] ng searched =
   647             get (ng \\ searched) [] searched
   960             get (ng \\ searched) [] searched
   648         | get (t::ts) ng searched =
   961         | get (t::ts) ng searched =
   649             (case Symtab.lookup (thmtab_of_name t, name) of
   962             (case Symtab.lookup (thmtab_of_name t, name) of
   650                  Some thm => thm
   963                  Some thm => thm
   651                | None => get ts (ng union (get_parents t)) (t::searched));
   964                | None => get ts (ng union (parents_of t)) (t::searched));
   652 
   965 
   653       val (tname, _) = thyinfo_of_sign (sign_of thy);
   966       val (tname, _) = thyinfo_of_sign (sign_of thy);
   654   in get [tname] [] [] end;
   967   in get [tname] [] [] end;
   655 
   968 
   656 (*Get stored theorems of a theory*)
   969 (*Get stored theorems of a theory*)
   675     Pretty.writeln (Pretty.big_list "stored theorems:" (map prt_thm thms))
   988     Pretty.writeln (Pretty.big_list "stored theorems:" (map prt_thm thms))
   676   end;
   989   end;
   677 
   990 
   678 fun print_theory thy = (Drule.print_theory thy; print_thms thy);
   991 fun print_theory thy = (Drule.print_theory thy; print_thms thy);
   679 
   992 
       
   993 
       
   994 (* Misc HTML functions *)
       
   995 
       
   996 (*Init HTML generator by setting paths and creating new files*)
       
   997 fun init_html () =
       
   998   let val pure_out = open_out "Pure_sub.html";
       
   999       val cpure_out = open_out "CPure_sub.html";
       
  1000       val theory_list = close_out (open_out "theory_list.txt");
       
  1001 
       
  1002       val rel_gif_path = relative_path (pwd ()) (!gif_path);
       
  1003       val package = hd (rev (space_explode "/" (pwd ())));
       
  1004   in make_html := true;
       
  1005      chart00_path := pwd();
       
  1006      writeln ("Setting path for 00-chart.html to " ^ quote (!chart00_path) ^
       
  1007               "\nGIF path has been set to " ^ quote (!gif_path));
       
  1008 
       
  1009      mk_charthead pure_out "Pure" "Children" false rel_gif_path "" package;
       
  1010      mk_charthead cpure_out "CPure" "Children" false rel_gif_path "" package;
       
  1011      output (pure_out, "Pure\n");
       
  1012      output (cpure_out, "CPure\n");
       
  1013      close_out pure_out;
       
  1014      close_out cpure_out
       
  1015   end;
       
  1016 
       
  1017 (*Generate 00-chart.html*)
       
  1018 fun make_chart () = if not (!make_html) then () else
       
  1019   let val theory_list = open_in (tack_on (!chart00_path) "theory_list.txt");
       
  1020       val theories = space_explode "\n" (input (theory_list, 999999));
       
  1021       val dummy = close_in theory_list;
       
  1022 
       
  1023       (*Path to Isabelle's main directory = $gif_path/.. *)
       
  1024       val base_path = "/" ^
       
  1025         space_implode "/" (rev (tl (rev (space_explode "/" (!gif_path)))));
       
  1026 
       
  1027       val gif_path = relative_path (!chart00_path) (!gif_path);
       
  1028 
       
  1029       (*Make entry for main chart of all theories.*)
       
  1030       fun main_entries [] curdir =
       
  1031             implode (replicate (length curdir -1) "</UL>\n")
       
  1032         | main_entries (t::ts) curdir =
       
  1033             let
       
  1034               val (name, path) = take_prefix (not_equal " ") (explode t);
       
  1035 
       
  1036               val tname = implode name
       
  1037               val tpath =
       
  1038                 tack_on (relative_path (!chart00_path) (implode (tl path)))
       
  1039                         tname;
       
  1040               val subdir = space_explode "/"
       
  1041                                  (relative_path base_path (implode (tl path)));
       
  1042               val level_diff = length subdir - length curdir;
       
  1043             in "\n" ^
       
  1044                (if subdir <> curdir then
       
  1045                   (implode (if level_diff > 0 then
       
  1046                               replicate level_diff "<UL>\n"
       
  1047                             else if level_diff < 0 then
       
  1048                               replicate (~level_diff) "</UL>\n"
       
  1049                             else []) ^
       
  1050                   "<H3>" ^ space_implode "/" subdir ^ "</H3>\n")
       
  1051                 else "") ^
       
  1052                "<A HREF = \"" ^ tpath ^ "_sub.html\"><IMG SRC = \"" ^
       
  1053                tack_on gif_path "red_arrow.gif\" ALT = \\/></A>" ^
       
  1054                "<A HREF = \"" ^ tpath ^ "_sup.html\"><IMG SRC = \"" ^
       
  1055                tack_on gif_path "blue_arrow.gif\
       
  1056                \\" ALT = /\\></A> <A HREF = \"" ^ tpath ^
       
  1057                ".html\">" ^ tname ^ "</A><BR>\n" ^
       
  1058                main_entries ts subdir
       
  1059             end;
       
  1060 
       
  1061       val out = open_out (tack_on (!chart00_path) "00-chart.html");
       
  1062       val subdir = relative_path base_path (!chart00_path);
       
  1063   in output (out,
       
  1064        "<HTML><HEAD><TITLE>Isabelle/" ^ subdir ^ "</TITLE></HEAD>\n\
       
  1065        \<H2>Isabelle/" ^ subdir ^ "</H2>\n\
       
  1066        \The name of every theory is linked to its theory file<BR>\n\
       
  1067        \<IMG SRC = \"" ^ tack_on gif_path "red_arrow.gif\
       
  1068        \\" ALT = \\/></A> stands for subtheories (child theories)<BR>\n\
       
  1069        \<IMG SRC = \"" ^ tack_on gif_path "blue_arrow.gif\
       
  1070        \\" ALT = /\\></A> stands for supertheories (parent theories)\n\
       
  1071        \<P><A HREF = \"" ^
       
  1072        tack_on (relative_path (!chart00_path) base_path) "logics.html\">\
       
  1073        \Back</A> to the index of Isabelle logics.\n<HR>" ^
       
  1074        main_entries theories (space_explode "/" base_path) ^
       
  1075        "</BODY></HTML>\n");
       
  1076      close_out out
       
  1077   end;
   680 end;
  1078 end;