# HG changeset patch # User clasohm # Date 814539189 -3600 # Node ID e173be970d27c3d405e5d0d920269016cef54be0 # Parent ee8f41456d288c0989d9c7cf2e783d1e6dc7a5dd added generation of HTML files to thy_read.ML; removed old HTML package diff -r ee8f41456d28 -r e173be970d27 src/Pure/Thy/ROOT.ML --- a/src/Pure/Thy/ROOT.ML Tue Oct 24 13:41:06 1995 +0100 +++ b/src/Pure/Thy/ROOT.ML Tue Oct 24 13:53:09 1995 +0100 @@ -23,8 +23,8 @@ structure ThySyn = ThySynFun(val user_keywords = [] and user_sections = []); structure ThmDB = ThmDBFun(); -structure Readthy = ReadthyFun(structure ThySyn = ThySyn and ThmDB = ThmDB); -open ThmDB Readthy; +structure ReadThy = ReadthyFun(structure ThySyn = ThySyn and ThmDB = ThmDB); +open ThmDB ReadThy; (* hide functors; saves space in PolyML *) functor ThyScanFun() = struct end; @@ -34,8 +34,11 @@ fun init_thy_reader () = use_string ["structure ThmDB = ThmDBFun();", - "structure Readthy = ReadthyFun(structure ThySyn = ThySyn \ + "structure ReadThy = ReadthyFun(structure ThySyn = ThySyn \ \and ThmDB = ThmDB);", - "Readthy.loaded_thys := !loaded_thys;", + "ReadThy.loaded_thys := !loaded_thys;", + "ReadThy.gif_path := !gif_path;", + "ReadThy.chart00_path := !chart00_path;", + "ReadThy.make_html := !make_html;", "ThmDB.thm_db := !thm_db;", - "open ThmDB Readthy;"]; + "open ThmDB ReadThy;"]; diff -r ee8f41456d28 -r e173be970d27 src/Pure/Thy/blue_arrow.gif Binary file src/Pure/Thy/blue_arrow.gif has changed diff -r ee8f41456d28 -r e173be970d27 src/Pure/Thy/chart.ML --- a/src/Pure/Thy/chart.ML Tue Oct 24 13:41:06 1995 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,377 +0,0 @@ -(* ID: $Id$ - Author: Mateja Jamnik, University of Cambridge - Copyright 1995 University of Cambridge - - Generator of the dependency charts of Isabelle theories. -*) - - -(* -------------------- - Declaration of the variables carrying the name - of the location of source files: - - path - location where the generated HTML files - should be stored - srcpath - location where the source files are stored - (ie. the graphics files) - -------------------- *) - -val htmlpath = "/homes/lcp/html_isa/"; -val srcpath = "/homes/lcp/Isa/Theory/"; - - - -(* -------------------- - Notices that display the legend for every dependency - chart, and the link back to the main listing of all - theories. - -------------------- *) - -val notice1 = -"
\n"^"The name of the file is linked to the theory file
\n"; - -val notice2 = -"(sub)\n"^ -" stands for subtheories (child theories)
\n"^ - -"(super)\n"^ -" stands for supertheories (parent theories)
\n
\n"; - - -val back = "Back\n"^ -" to the original listing of all the theories.
\n
\n
\n"; - - - -(* -------------------- - Get a list of all theory files in Isabelle - that have been loaded. - -------------------- *) - -print_depth 1000; - -val theory_list = !loaded_thys; - -val files = Symtab.alist_of (theory_list); - - - -(* -------------------- - Get a list of all theory files and their children. - -------------------- *) - -fun subtheory (tname, ThyInfo{children,...}) = (tname,children); - -val subtheories = map subtheory (files); - - - -(* -------------------- - Extract a list of all theory files only. - -------------------- *) - -fun theory ( [], list ) = list - | theory ( (string, _)::rest, list ) = theory(rest, string::list); - - - -(* -------------------- - Use quick sort to sort the theories in - the alphabetic order. Variable a as the first - element of the list is used as a pivot value. - -------------------- *) - -fun quick [] = [] - | quick [x] = [x] - | quick (a::bs) = let - fun part (l,r,[]) : string list = (quick l) @ (a::quick r) - | part (l,r,x::xs) = if x<=a then part(x::l, r, xs) - else part(l, x::r, xs) - in part([], [], bs) end; - -val theories = quick(theory(subtheories,[])); - - - -(* -------------------- - Insert the identifier of the supertheory - matrix for every row. Also insert elements - into the list of identifier's parents in - alphabetic order. - -------------------- *) - -fun listins ( l, [], x:string ) = l@[x] - | listins ( l, e::r, x ) = if x>e then listins( l@[e], r, x ) - else if x<>e then l@[x,e]@r - else l@[x]@r; - - - -(* -------------------- - Arguments: - t - accumulator of the resulting supertheory matrix - result - temporary resulting matrix (up until now) - (e,ident) - a list of identifier and its child - The child e of subtheory matrix becomes identifier ident of - the supertheory matrix. The identifier ident of subtheory - matrix becomes the parent elem of supertheory matrix. - Call function: - - listins - -------------------- *) - -fun matins ( t, [], (ident:string, elem:string) ) = t@[(ident,[elem])] - | matins ( t, (x:string,y:string list)::b, - (ident:string, elem:string) ) = - if x=ident then t@[(x,listins([],y,elem))]@b - else matins (t@[(x,y)], b, (ident,elem)); - - - -(* -------------------- - Instantiate the identifier ident, and the list of - its children (e::l), where e is its first child. - Call function: - - matins - -------------------- *) - -fun rowins ( (ident, []), result ) = result - | rowins ( (ident, e::l), result ) = - rowins ( (ident, l), matins([],result,(e,ident)) ); - - - -(* -------------------- - Extract recursively one row at a time of the - subtheory matrix. - Call function: - -rowins - -------------------- *) - -fun matinv ( [], result ) = result - | matinv ( l::b, result ) = matinv( b, rowins(l, result) ); - - - -(* -------------------- - Holds the value of supertheory matrix. - Call function: - -matinv - -------------------- *) - -val supertheories = matinv ( subtheories, [] ); - - - - -(* ---------------------------------------------------------------------- *) - - - - -(* -------------------- - Entries for the main chart of all the theories. - Every theory name is a link to the theory definition. - Down arrow is a link to the subtheory chart of that theory. - Up arrow is a link to the supertheory chart of that theory. - -------------------- *) - -fun entries x = "\n"^ - "\n(sub)\n"^ - - "\n(super) \n"^ - ""^x^"
\n"; - -fun all_list x = map entries x; - - - -(* -------------------- - Convert a list of characters and strings - into a string. - -------------------- *) - -fun join ([],res) = res - | join (x::xs,res) = join(xs,res^x); - - - -val bottom = -"
\n\n"^ -"\n\n"; - - - -(* -------------------- - Find the row of the matrix into which - the parent (or children) theories - are going to be inserted. - -------------------- *) - -fun findline (_,[]) = [] - | findline (th:string,(id,row:string list)::mat) = - if th=id then row else findline(th,mat); - - - -(* -------------------- - Once a parent (or child) theory has been identified - make an entry for it with appropriate indentation and with - further links to its parent (or child) dependency chart. - It contains the subfunction: - - maketableentry - -------------------- *) - -fun dependencies (th, mat) = - let - val stringlist = findline(th,mat); - fun maketableentry name = - "
  • "^name^"\n"^ - " \n(sub) \n"^ - "\n(super)\n"^ - "\n" - in - map maketableentry stringlist - end; - - - -(* -------------------- - Create individual super- and sub-theory charts for - each theory. Store them in separate files. - It contains the subfunction: - - page - -------------------- *) - -fun pages ([],_,_,_) = 0 - | pages (th::theories,theorymatrix,suffix,headline) = - let - fun page th = - let - - (* Open files for output of individual charts. *) - - val outf_each = open_out (htmlpath^th^"_"^suffix^".html") - in - - (* Recursively write to the output files the *) - (* dependent theories with appropriate links *) - (* depending upon the suffix. *) - - output(outf_each, - - (* Heading of each dependency chart. *) - - "\n"^ - "

    "^headline^"

    \n\n"^notice1^notice2^back^ - "\n"^""^th^"\n"^ - (if suffix="sup" - then ("\n(sub)\n") - else ("\n(super)\n"))^ - "\n"^bottom); - - (* Close for output the individual *) - (* dependency charts. *) - - close_out (outf_each) - end; - in - - (* Anti-bugging technique to follow the *) - (* execution of the program. *) - - output(std_out,"theory: "^th^"\n"); - - - (* The main driver for the creation of the dependencies *) - (* which calls the functions page and pages. This will *) - (* go into depth of dependency of each theory with the *) - (* appropriate indentation. *) - - page(th); - pages(theories,theorymatrix,suffix,headline) - end; - - - - -(* ---------------------------------------------------------------------- *) - - - - -(* -------------------- - Generate the main chart 00-chart.html containing - the listing of all the theories and the links to charts. - -------------------- *) - -val outtext = htmlpath^"00-chart.html"; -val outfile = open_out outtext; - -val head = "\n\n"^outtext^ - "\n\n\n"^"\n"; - -val title = "

    Dependency Diagram

    \n\n"^notice1^notice2; -val page1part1 = "

    Subtheories and Supertheories

    \n
    \n\n"^ - join(all_list(theories),"")^"
    \n"; -val page1part3 = bottom; - -val tail = "\n"^""; - -output(outfile,head); -output(outfile,title); -output(outfile,page1part1); -output(outfile,page1part3); - - - -(* ---------------------------------------------------------------------- *) - - - -(* -------------------- - The main driver to create individual super- and sub-theory - charts for each individual theory. The arguments passed are: - - the list of all the theories - - the super- or sub-theory matrix - - the appropriate suffix sup or sub - - the title of the chart - It calls the function: - - pages - -------------------- *) - -pages(theories,subtheories,"sub","Subtheories"); -pages(theories,supertheories,"sup","Supertheories"); -output(outfile,tail); - - - -(* -------------------- - Close file for output. - -------------------- *) -close_out(outfile); diff -r ee8f41456d28 -r e173be970d27 src/Pure/Thy/red_arrow.gif Binary file src/Pure/Thy/red_arrow.gif has changed diff -r ee8f41456d28 -r e173be970d27 src/Pure/Thy/thy_read.ML --- a/src/Pure/Thy/thy_read.ML Tue Oct 24 13:41:06 1995 +0100 +++ b/src/Pure/Thy/thy_read.ML Tue Oct 24 13:53:09 1995 +0100 @@ -9,14 +9,13 @@ *) (*Type for theory storage*) -datatype thy_info = ThyInfo of {path: string, - children: string list, - thy_time: string option, - ml_time: string option, - theory: theory option, - thms: thm Symtab.table, - thy_ss: Simplifier.simpset option, - simpset: Simplifier.simpset option}; +datatype thy_info = + ThyInfo of {path: string, + children: string list, parents: string list, + thy_time: string option, ml_time: string option, + theory: theory option, thms: thm Symtab.table, + thy_ss: Simplifier.simpset option, + simpset: Simplifier.simpset option}; (*meaning of special values: thy_time, ml_time = None theory file has not been read yet = Some "" theory was read but has either been marked @@ -24,6 +23,15 @@ this theory (see e.g. 'virtual' theories like Pure or theories without a ML file) theory = None theory has not been read yet + + parents: While 'children' contains all theories the theory depends + on (i.e. also ones quoted in the .thy file), + 'parents' only contains the theories which were used to form + the base of this theory. + + origin of the simpsets: + thy_ss: snapshot of !Simpset.simpset after .thy file was read + simpset: snapshot of !Simpset.simpset after .ML file was read *) signature READTHY = @@ -44,6 +52,9 @@ val theory_of_sign: Sign.sg -> theory val theory_of_thm: thm -> theory + val children_of: string -> string list + val parents_of: string -> string list + val store_thm: string * thm -> thm val bind_thm: string * thm -> unit val qed: string -> unit @@ -55,6 +66,12 @@ val thms_of: theory -> (string * thm) list val simpset_of: string -> Simplifier.simpset val print_theory: theory -> unit + + val gif_path : string ref + val chart00_path : string ref + val make_html : bool ref + val init_html: unit -> unit + val make_chart: unit -> unit end; @@ -66,29 +83,52 @@ datatype basetype = Thy of string | File of string; -val loaded_thys = ref (Symtab.make [("ProtoPure", - ThyInfo {path = "", - children = ["Pure", "CPure"], - thy_time = Some "", ml_time = Some "", - theory = Some proto_pure_thy, - thms = Symtab.null, - thy_ss = None, simpset = None}), - ("Pure", ThyInfo {path = "", children = [], - thy_time = Some "", ml_time = Some "", - theory = Some pure_thy, - thms = Symtab.null, - thy_ss = None, simpset = None}), - ("CPure", ThyInfo {path = "", - children = [], - thy_time = Some "", ml_time = Some "", - theory = Some cpure_thy, - thms = Symtab.null, - thy_ss = None, simpset = None}) - ]); +val loaded_thys = + ref (Symtab.make [("ProtoPure", + ThyInfo {path = "", + children = ["Pure", "CPure"], parents = [], + thy_time = Some "", ml_time = Some "", + theory = Some proto_pure_thy, thms = Symtab.null, + thy_ss = None, simpset = None}), + ("Pure", + ThyInfo {path = "", children = [], + parents = ["ProtoPure"], + thy_time = Some "", ml_time = Some "", + theory = Some pure_thy, thms = Symtab.null, + thy_ss = None, simpset = None}), + ("CPure", + ThyInfo {path = "", + children = [], parents = ["ProtoPure"], + thy_time = Some "", ml_time = Some "", + theory = Some cpure_thy, + thms = Symtab.null, + thy_ss = None, simpset = None}) + ]); -val loadpath = ref ["."]; (*default search path for theory files *) +val loadpath = ref ["."]; (*default search path for theory files*) + +val delete_tmpfiles = ref true; (*remove temporary files after use*) + -val delete_tmpfiles = ref true; (*remove temporary files after use *) +(*Set location of graphics for HTML files + (When this is executed for the first time we are in $ISABELLE/Pure/Thy. + This path is converted to $ISABELLE/Tools by removing the last two + directories and appending "Tools". All subsequently made ReadThy + structures inherit this value.) +*) +val gif_path = ref (tack_on ("/" ^ + space_implode "/" (rev (tl (tl (rev (space_explode "/" (pwd ()))))))) + "Tools"); + +(*Location of theory-list.txt and 00-chart.html (normally set by init_html)*) +val chart00_path = ref ""; + +val make_html = ref false; (*don't make HTML versions of loaded theories*) + +(*HTML file of theory currently being read + (Initialized by thyfile2html; used by use_thy and store_thm)*) +val cur_htmlfile = ref None : outstream option ref; + (*Make name of the output ML file for a theory *) fun out_name tname = "." ^ tname ^ ".thy.ML"; @@ -136,38 +176,42 @@ end | None => (false, false) +(*Get all direct descendants of a theory*) +fun children_of t = + case get_thyinfo t of Some (ThyInfo {children, ...}) => children + | _ => []; + (*Get all direct ancestors of a theory*) -fun get_parents child = - let fun has_child (tname, ThyInfo {children, theory, ...}) = - if child mem children then Some tname else None; - in mapfilter has_child (Symtab.dest (!loaded_thys)) end; +fun parents_of t = + case get_thyinfo t of Some (ThyInfo {parents, ...}) => parents + | _ => []; (*Get all descendants of a theory list *) fun get_descendants [] = [] | get_descendants (t :: ts) = - let val tinfo = get_thyinfo t - in if is_some tinfo then - let val ThyInfo {children, ...} = the tinfo - in children union (get_descendants (children union ts)) - end - else [] - end; + let val children = children_of t + in children union (get_descendants (children union ts)) end; (*Get theory object for a loaded theory *) -fun get_theory name = +fun theory_of name = let val ThyInfo {theory, ...} = the (get_thyinfo name) in the theory end; +(*Get path where theory's files are located*) +fun path_of tname = + let val ThyInfo {path, ...} = the (get_thyinfo tname) + in path end; + exception FILE_NOT_FOUND; (*raised by find_file *) (*Find a file using a list of paths if no absolute or relative path is specified.*) fun find_file "" name = - let fun find_it (curr :: paths) = - if file_exists (tack_on curr name) then - tack_on curr name + let fun find_it (cur :: paths) = + if file_exists (tack_on cur name) then + (if cur = "." then name else tack_on cur name) else - find_it paths + find_it paths | find_it [] = "" in find_it (!loadpath) end | find_file path name = @@ -219,9 +263,9 @@ (*Remove theory from all child lists in loaded_thys *) fun unlink_thy tname = - let fun remove (ThyInfo {path, children, thy_time, ml_time, theory, thms, - thy_ss, simpset}) = - ThyInfo {path = path, children = children \ tname, + let fun remove (ThyInfo {path, children, parents, thy_time, ml_time, + theory, thms, thy_ss, simpset}) = + ThyInfo {path = path, children = children \ tname, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms, thy_ss = thy_ss, simpset = simpset} in loaded_thys := Symtab.map remove (!loaded_thys) end; @@ -234,15 +278,13 @@ (*Change thy_time and ml_time for an existent item *) fun set_info tname thy_time ml_time = let val tinfo = case Symtab.lookup (!loaded_thys, tname) of - Some (ThyInfo {path, children, theory, thms, thy_ss, simpset,...}) => - ThyInfo {path = path, children = children, + Some (ThyInfo {path, children, parents, theory, thms, + thy_ss, simpset,...}) => + ThyInfo {path = path, children = children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms, thy_ss = thy_ss, simpset = simpset} - | None => ThyInfo {path = "", children = [], - thy_time = thy_time, ml_time = ml_time, - theory = None, thms = Symtab.null, - thy_ss = None, simpset = None}; + | None => error ("set_info: theory " ^ tname ^ " not found"); in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) end; @@ -250,14 +292,205 @@ fun mark_outdated tname = let val t = get_thyinfo tname; in if is_none t then () - else let val ThyInfo {thy_time, ml_time, ...} = the t - in set_info tname - (if is_none thy_time then None else Some "") - (if is_none ml_time then None else Some "") - - end + else + let val ThyInfo {thy_time, ml_time, ...} = the t + in set_info tname (if is_none thy_time then None else Some "") + (if is_none ml_time then None else Some "") + end end; +(*Make head of HTML dependency charts + Parameters are: + file: HTML file + tname: theory name + suffix: suffix of complementary chart + (sup if this head is for a sub-chart, sub if it is for a sup-chart; + empty for Pure and CPure sub-charts) + gif_path: relative path to directory containing GIFs + chart00_path: relative path to directory containing main theory chart +*) +fun mk_charthead file tname title green_arrow gif_path chart00_path package = + output (file, + "" ^ title ^ " of " ^ tname ^ + "\n

    " ^ title ^ " of theory " ^ tname ^ + "

    \nThe name of every theory is linked to its theory file
    \n" ^ + "\\/ stands for subtheories (child theories)
    \n\ + \/\\ stands for supertheories (parent theories)\n" ^ + (if not green_arrow then "" else + "
    > stands for repeated subtrees") ^ + "

    Back to the main theory chart of " ^ package ^ ".\n


    \n
    ");
    +
    +(*Convert .thy file to HTML and make chart of its super-theories*)
    +fun thyfile2html tpath tname =
    +  let
    +    val gif_path = relative_path tpath (!gif_path);
    +    val package = hd (rev (space_explode "/" (!chart00_path)));
    +    val chart00_path = relative_path tpath (!chart00_path);
    +
    +    (*Make list of all theories and all theories that own a .thy file*)
    +    fun list_theories [] theories thy_files = (theories, thy_files)
    +      | list_theories ((tname, ThyInfo {thy_time, ...}) :: ts)
    +                      theories thy_files =
    +          list_theories ts (tname :: theories)
    +            (if is_some thy_time andalso the thy_time <> "" then
    +               tname :: thy_files
    +             else thy_files);
    +
    +    val (theories, thy_files) =
    +      list_theories (Symtab.dest (!loaded_thys)) [] [];
    +
    +    (*Do the conversion*)
    +    fun gettext thy_file  =
    +      let
    +        (*Convert special HTML characters ('&', '>', and '<')*)
    +        val file =
    +          explode (execute ("sed -e 's/\\&/\\&/g' -e 's/>/\\>/g' \
    +                            \-e 's/" ^ t ^ "" end;
    +              in if not (id mem theories) then (result, implode l)
    +                 else if id mem thy_files then
    +                   make_links rest (result ^ implode pre ^ make_link id)
    +                 else make_links rest (result ^ implode pre ^ id)
    +              end;
    +
    +            val (pre, rest) = take_prefix (fn c => c <> "=") file';
    +
    +            val (ancestors, body) =
    +              if null rest then
    +                error ("Missing \"=\" in file " ^ tname ^ ".thy.\n\
    +                       \(Make sure that the last line ends with a linebreak.)")
    +              else
    +                make_links rest "";
    +          in (implode pre ^ ancestors, body) end;
    +      in "" ^ tname ^ ".thy\n\n\n" ^
    +         "

    " ^ tname ^ ".thy

    \nBack to the main theory chart of " ^ package ^ + ".\n
    \n\n
    \n" ^ comment ^ ancestors ^ body ^
    +         "
    \n

    Theorems proved in " ^ tname ^ ".ML:

    \n" + end; + + (** Make chart of super-theories **) + + val sup_out = open_out (tack_on tpath tname ^ "_sup.html"); + val sub_out = open_out (tack_on tpath tname ^ "_sub.html"); + + (*Theories that already have been listed in this chart*) + val listed = ref []; + + val wanted_theories = + filter (fn s => s mem thy_files orelse s = "Pure" orelse s = "CPure") + theories; + + (*Make nested list of theories*) + fun list_ancestors tname level continued = + let + fun mk_entry [] = () + | mk_entry (t::ts) = + let + val is_pure = t = "Pure" orelse t = "CPure"; + val path = path_of t; + val rel_path = if is_pure then chart00_path + else relative_path tpath path; + + fun mk_offset [] cur = + if level < cur then error "Error in mk_offset" + else implode (replicate (level - cur) " ") + | mk_offset (l::ls) cur = + implode (replicate (l - cur) " ") ^ "| " ^ + mk_offset ls (l+1); + in output (sup_out, + " " ^ mk_offset continued 0 ^ + "\\__" ^ (if is_pure then t else "" ^ t ^ "") ^ + " \\/" ^ + (if is_pure then "" + else "/\\")); + if t mem (!listed) andalso not (null (parents_of t)) then + output (sup_out, + "\ + \>\n") + else (output (sup_out, "\n"); + listed := t :: (!listed); + list_ancestors t (level+1) (if null ts then continued + else continued @ [level]); + mk_entry ts) + end; + + val relatives = + filter (fn s => s mem wanted_theories) (parents_of tname); + in mk_entry relatives end; + in if is_some (!cur_htmlfile) then + error "thyfile2html: Last theory's HTML has not been closed." + else (); + cur_htmlfile := Some (open_out (tack_on tpath tname ^ ".html")); + output (the (!cur_htmlfile), gettext (tack_on tpath tname ^ ".thy")); + + mk_charthead sup_out tname "Ancestors" true gif_path chart00_path package; + output(sup_out, + "" ^ tname ^ " \ + \\\/\n"); + list_ancestors tname 0 []; + output (sup_out, "

    "); + close_out sup_out; + + mk_charthead sub_out tname "Children" false gif_path chart00_path package; + output(sub_out, + "" ^ tname ^ " \ + \\\/\n"); + close_out sub_out + end; + + (*Read .thy and .ML files that haven't been read yet or have changed since they were last read; loaded_thys is a thy_info list ref containing all theories that have @@ -270,14 +503,16 @@ val (abs_path, _) = if thy_file = "" then split_filename ml_file else split_filename thy_file; val (thy_uptodate, ml_uptodate) = thy_unchanged tname thy_file ml_file; + val old_parents = parents_of tname; (*Set absolute path for loaded theory *) fun set_path () = - let val ThyInfo {children, thy_time, ml_time, theory, thms, thy_ss, - simpset, ...} = + let val ThyInfo {children, parents, thy_time, ml_time, theory, thms, + thy_ss, simpset, ...} = the (Symtab.lookup (!loaded_thys, tname)); in loaded_thys := Symtab.update ((tname, - ThyInfo {path = abs_path, children = children, + ThyInfo {path = abs_path, + children = children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms, thy_ss = thy_ss, simpset = simpset}), @@ -286,7 +521,7 @@ (*Mark all direct descendants of a theory as changed *) fun mark_children thy = - let val ThyInfo {children, ...} = the (get_thyinfo thy); + let val children = children_of thy; val present = filter (is_some o get_thyinfo) children; val loaded = filter already_loaded present; in if loaded <> [] then @@ -301,13 +536,13 @@ fun delete_thms () = let val tinfo = case get_thyinfo tname of - Some (ThyInfo {path, children, thy_time, ml_time, theory, thy_ss, - simpset, ...}) => - ThyInfo {path = path, children = children, + Some (ThyInfo {path, children, parents, thy_time, ml_time, theory, + thy_ss, simpset, ...}) => + ThyInfo {path = path, children = children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = Symtab.null, thy_ss = thy_ss, simpset = simpset} - | None => ThyInfo {path = "", children = [], + | None => ThyInfo {path = "", children = [], parents = [], thy_time = None, ml_time = None, theory = None, thms = Symtab.null, thy_ss = None, simpset = None}; @@ -320,10 +555,11 @@ end; fun save_thy_ss () = - let val ThyInfo {path, children, thy_time, ml_time, theory, thms, - simpset, ...} = the (get_thyinfo tname); + let val ThyInfo {path, children, parents, thy_time, ml_time, + theory, thms, simpset, ...} = the (get_thyinfo tname); in loaded_thys := Symtab.update - ((tname, ThyInfo {path = path, children = children, + ((tname, ThyInfo {path = path, + children = children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms, thy_ss = Some (!Simplifier.simpset), @@ -332,10 +568,11 @@ end; fun save_simpset () = - let val ThyInfo {path, children, thy_time, ml_time, theory, thms, - thy_ss, ...} = the (get_thyinfo tname); + let val ThyInfo {path, children, parents, thy_time, ml_time, + theory, thms, thy_ss, ...} = the (get_thyinfo tname); in loaded_thys := Symtab.update - ((tname, ThyInfo {path = path, children = children, + ((tname, ThyInfo {path = path, + children = children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms, thy_ss = thy_ss, @@ -343,22 +580,58 @@ !loaded_thys) end; + (*Add theory to file listing all loaded theories (for 00-chart.html) + and to the sub-charts of its parents*) + fun mk_html () = + let val new_parents = parents_of tname \\ old_parents; + + (*Add child to parents' sub-theory charts*) + fun add_to_parents t = + let val is_pure = t = "Pure" orelse t = "CPure"; + val path = if is_pure then (!chart00_path) else path_of t; + + val gif_path = relative_path path (!gif_path); + val rel_path = relative_path path abs_path; + + val out = open_append (tack_on path t ^ "_sub.html"); + in output (out, + " |\n \\__" ^ + tname ^ " \\/\ + \\ + \/\\\n"); + close_out out + end; + + val theory_list = + open_append (tack_on (!chart00_path) "theory_list.txt"); + in output (theory_list, tname ^ " " ^ abs_path ^ "\n"); + close_out theory_list; + + seq add_to_parents new_parents + end in if thy_uptodate andalso ml_uptodate then () else - ( - if thy_file = "" then () + (if thy_file = "" then () else if thy_uptodate then simpset := let val ThyInfo {thy_ss, ...} = the (get_thyinfo tname); in the thy_ss end else (writeln ("Reading \"" ^ name ^ ".thy\""); + delete_thms (); read_thy tname thy_file; use (out_name tname); save_thy_ss (); if not (!delete_tmpfiles) then () - else delete_file (out_name tname) + else delete_file (out_name tname); + + if not (!make_html) then () + else thyfile2html abs_path tname ); set_info tname (Some (file_info thy_file)) None; @@ -375,21 +648,37 @@ (*Store axioms of theory (but only if it's not a copy of an older theory)*) - let val parents = get_parents tname; - val fst_thy = get_theory (hd parents); - val this_thy = get_theory tname; + let val parents = parents_of tname; + val this_thy = theory_of tname; val axioms = if length parents = 1 - andalso Sign.eq_sg (sign_of fst_thy, sign_of this_thy) then [] + andalso Sign.eq_sg (sign_of (theory_of (hd parents)), + sign_of this_thy) then [] else axioms_of this_thy; in map store_thm_db axioms end; + (*Add theory to list of all loaded theories (for 00-chart.html) + and add it to its parents' sub-charts*) + if !make_html then + let val path = path_of tname; + in if path = "" then mk_html () (*first time theory has been read*) + else () + end + else (); + (*Now set the correct info*) set_info tname (Some (file_info thy_file)) (Some (file_info ml_file)); set_path (); (*Mark theories that have to be reloaded*) - mark_children tname + mark_children tname; + + (*Close HTML file*) + case !cur_htmlfile of + Some out => (output (out, "
    \n"); + close_out out; + cur_htmlfile := None) + | None => () ) end; @@ -405,25 +694,19 @@ let (*List theories in the order they have to be loaded *) fun load_order [] result = result | load_order thys result = - let fun next_level (t :: ts) = - let val thy = get_thyinfo t - in if is_some thy then - let val ThyInfo {children, ...} = the thy - in children union (next_level ts) end - else next_level ts - end - | next_level [] = []; + let fun next_level [] = [] + | next_level (t :: ts) = + let val children = children_of t + in children union (next_level ts) end; - val children = next_level thys; - in load_order children ((result \\ children) @ children) end; + val descendants = next_level thys; + in load_order descendants ((result \\ descendants) @ descendants) + end; fun reload_changed (t :: ts) = - let val thy = get_thyinfo t; - - fun abspath () = - if is_some thy then - let val ThyInfo {path, ...} = the thy in path end - else ""; + let fun abspath () = case get_thyinfo t of + Some (ThyInfo {path, ...}) => path + | None => ""; val (thy_file, ml_file) = get_filenames (abspath ()) t; val (thy_uptodate, ml_uptodate) = @@ -453,7 +736,7 @@ (*Merge theories to build a base for a new theory. Base members are only loaded if they are missing.*) fun mk_base bases child mk_draft = - let (*Show the cycle that would be created by add_child *) + let (*Show the cycle that would be created by add_child*) fun show_cycle base = let fun find_it result curr = let val tinfo = get_thyinfo curr @@ -468,22 +751,23 @@ end in find_it "" child end; - (*Check if a cycle would be created by add_child *) + (*Check if a cycle would be created by add_child*) fun find_cycle base = if base mem (get_descendants [child]) then show_cycle base else (); - (*Add child to child list of base *) + (*Add child to child list of base*) fun add_child base = let val tinfo = case Symtab.lookup (!loaded_thys, base) of - Some (ThyInfo {path, children, thy_time, ml_time, + Some (ThyInfo {path, children, parents, thy_time, ml_time, theory, thms, thy_ss, simpset}) => - ThyInfo {path = path, children = child ins children, + ThyInfo {path = path, + children = child ins children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms, thy_ss = thy_ss, simpset = simpset} - | None => ThyInfo {path = "", children = [child], + | None => ThyInfo {path = "", children = [child], parents = [], thy_time = None, ml_time = None, theory = None, thms = Symtab.null, thy_ss = None, simpset = None}; @@ -516,7 +800,7 @@ (*Load all needed files and make a list of all real theories *) fun load_base (Thy b :: bs) = (load b; - b :: (load_base bs)) + b :: load_base bs) | load_base (File b :: bs) = (load b; load_base bs) (*don't add it to mergelist *) @@ -525,26 +809,34 @@ val dummy = unlink_thy child; val mergelist = load_base bases; + val dummy = + let val tinfo = case Symtab.lookup (!loaded_thys, child) of + Some (ThyInfo {path, children, thy_time, ml_time, theory, thms, + thy_ss, simpset, ...}) => + ThyInfo {path = path, + children = children, parents = mergelist, + thy_time = thy_time, ml_time = ml_time, + theory = theory, thms = thms, + thy_ss = thy_ss, simpset = simpset} + | None => error ("set_parents: theory " ^ child ^ " not found"); + in loaded_thys := Symtab.update ((child, tinfo), !loaded_thys) end; + val base_thy = (writeln ("Loading theory " ^ (quote child)); - merge_thy_list mk_draft (map get_theory mergelist)); + merge_thy_list mk_draft (map theory_of mergelist)); in simpset := foldr merge_ss (mapfilter get_simpset mergelist, empty_ss); base_thy end; -(*Change theory object for an existent item of loaded_thys - or create a new item*) +(*Change theory object for an existent item of loaded_thys*) fun store_theory (thy, tname) = let val tinfo = case Symtab.lookup (!loaded_thys, tname) of - Some (ThyInfo {path, children, thy_time, ml_time, thms, + Some (ThyInfo {path, children, parents, thy_time, ml_time, thms, thy_ss, simpset, ...}) => - ThyInfo {path = path, children = children, + ThyInfo {path = path, children = children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = Some thy, thms = thms, thy_ss = thy_ss, simpset = simpset} - | None => ThyInfo {path = "", children = [], - thy_time = None, ml_time = None, - theory = Some thy, thms = Symtab.null, - thy_ss = None, simpset = None}; + | None => error ("store_theory: theory " ^ tname ^ " not found"); in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) end; @@ -583,11 +875,12 @@ (* Store theorems *) -(*Store a theorem in the thy_info of its theory*) +(*Store a theorem in the thy_info of its theory, + and in the theory's HTML file*) fun store_thm (name, thm) = let - val (thy_name, ThyInfo {path, children, thy_time, ml_time, theory, thms, - thy_ss, simpset}) = + val (thy_name, ThyInfo {path, children, parents, thy_time, ml_time, + theory, thms, thy_ss, simpset}) = thyinfo_of_sign (#sign (rep_thm thm)); val (thms', duplicate) = (Symtab.update_new ((name, thm), thms), false) @@ -598,13 +891,28 @@ (thms, true)) else error ("Duplicate theorem name " ^ quote s ^ " used in theory database")); + + fun thm_to_html () = + let fun escape [] = "" + | escape ("<"::s) = "<" ^ escape s + | escape (">"::s) = ">" ^ escape s + | escape ("&"::s) = "&" ^ escape s + | escape (c::s) = c ^ escape s; + in case !cur_htmlfile of + Some out => + output (out, "" ^ name ^ "\n
    " ^
    +                            escape (explode (string_of_thm (freeze thm))) ^
    +                            "

    \n") + | None => () + end; in loaded_thys := Symtab.update - ((thy_name, ThyInfo {path = path, children = children, + ((thy_name, ThyInfo {path = path, children = children, parents = parents, thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms', thy_ss = thy_ss, simpset = simpset}), !loaded_thys); + thm_to_html (); if duplicate then thm else store_thm_db (name, thm) end; @@ -613,19 +921,24 @@ val qed_thm = ref flexpair_def(*dummy*); fun bind_thm (name, thm) = - (qed_thm := standard thm; - use_string ["val " ^name^ " = store_thm (" ^quote name^", !qed_thm);"]); + (qed_thm := standard thm; + store_thm (name, standard thm); + use_string ["val " ^ name ^ " = !qed_thm;"]); fun qed name = - use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^ ", result ());"]; + (qed_thm := result (); + store_thm (name, !qed_thm); + use_string ["val " ^ name ^ " = !qed_thm;"]); fun qed_goal name thy agoal tacsf = - (qed_thm := prove_goal thy agoal tacsf; - use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]); + (qed_thm := prove_goal thy agoal tacsf; + store_thm (name, !qed_thm); + use_string ["val " ^ name ^ " = !qed_thm;"]); fun qed_goalw name thy rths agoal tacsf = - (qed_thm := prove_goalw thy rths agoal tacsf; - use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]); + (qed_thm := prove_goalw thy rths agoal tacsf; + store_thm (name, !qed_thm); + use_string ["val " ^ name ^ " = !qed_thm;"]); (* Retrieve theorems *) @@ -648,7 +961,7 @@ | get (t::ts) ng searched = (case Symtab.lookup (thmtab_of_name t, name) of Some thm => thm - | None => get ts (ng union (get_parents t)) (t::searched)); + | None => get ts (ng union (parents_of t)) (t::searched)); val (tname, _) = thyinfo_of_sign (sign_of thy); in get [tname] [] [] end; @@ -677,4 +990,89 @@ fun print_theory thy = (Drule.print_theory thy; print_thms thy); + +(* Misc HTML functions *) + +(*Init HTML generator by setting paths and creating new files*) +fun init_html () = + let val pure_out = open_out "Pure_sub.html"; + val cpure_out = open_out "CPure_sub.html"; + val theory_list = close_out (open_out "theory_list.txt"); + + val rel_gif_path = relative_path (pwd ()) (!gif_path); + val package = hd (rev (space_explode "/" (pwd ()))); + in make_html := true; + chart00_path := pwd(); + writeln ("Setting path for 00-chart.html to " ^ quote (!chart00_path) ^ + "\nGIF path has been set to " ^ quote (!gif_path)); + + mk_charthead pure_out "Pure" "Children" false rel_gif_path "" package; + mk_charthead cpure_out "CPure" "Children" false rel_gif_path "" package; + output (pure_out, "Pure\n"); + output (cpure_out, "CPure\n"); + close_out pure_out; + close_out cpure_out + end; + +(*Generate 00-chart.html*) +fun make_chart () = if not (!make_html) then () else + let val theory_list = open_in (tack_on (!chart00_path) "theory_list.txt"); + val theories = space_explode "\n" (input (theory_list, 999999)); + val dummy = close_in theory_list; + + (*Path to Isabelle's main directory = $gif_path/.. *) + val base_path = "/" ^ + space_implode "/" (rev (tl (rev (space_explode "/" (!gif_path))))); + + val gif_path = relative_path (!chart00_path) (!gif_path); + + (*Make entry for main chart of all theories.*) + fun main_entries [] curdir = + implode (replicate (length curdir -1) "\n") + | main_entries (t::ts) curdir = + let + val (name, path) = take_prefix (not_equal " ") (explode t); + + val tname = implode name + val tpath = + tack_on (relative_path (!chart00_path) (implode (tl path))) + tname; + val subdir = space_explode "/" + (relative_path base_path (implode (tl path))); + val level_diff = length subdir - length curdir; + in "\n" ^ + (if subdir <> curdir then + (implode (if level_diff > 0 then + replicate level_diff "

    \n" + else []) ^ + "

    " ^ space_implode "/" subdir ^ "

    \n") + else "") ^ + "\\/" ^ + "/\\ " ^ tname ^ "
    \n" ^ + main_entries ts subdir + end; + + val out = open_out (tack_on (!chart00_path) "00-chart.html"); + val subdir = relative_path base_path (!chart00_path); + in output (out, + "Isabelle/" ^ subdir ^ "\n\ + \

    Isabelle/" ^ subdir ^ "

    \n\ + \The name of every theory is linked to its theory file
    \n\ + \\\/ stands for subtheories (child theories)
    \n\ + \/\\ stands for supertheories (parent theories)\n\ + \

    \ + \Back to the index of Isabelle logics.\n


    " ^ + main_entries theories (space_explode "/" base_path) ^ + "\n"); + close_out out + end; end; diff -r ee8f41456d28 -r e173be970d27 src/Pure/Thy/to_html.ML --- a/src/Pure/Thy/to_html.ML Tue Oct 24 13:41:06 1995 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,273 +0,0 @@ -(* ID: $Id$ - Author: Mateja Jamnik, University of Cambridge - Copyright 1995 University of Cambridge - - Convert the Isabelle theory files to .html format for hypertext browsing -*) - -val htmlpath = "/homes/lcp/html_isa/"; - -(* -------------------- - Exception declaration in case that there is a lexical - error occurs. - -------------------- *) - -exception lex_err; - -(* -------------------- - Get the list of all the theory files and the - path to access them in their directories - -------------------- *) - -print_depth 1000; -val theory_list = !loaded_thys; -val files = Symtab.alist_of (theory_list); - -(* -------------------- - The function move_eachf is going to move all the theory - files in isabelle to their html format. It takes - for arguments the name of the theory (tname) and - other theory information such as path (path), theorems (thms) - proved, ... It is the main driver of the program, and basically - contains all other functions. It contains the following - subfunctions: - - create_pure - - gettext - - move_onef - - transform - -------------------- *) - -fun move_eachf (tname, ThyInfo{path,thms,...}) = - let val intext = path^tname^".thy"; - val outtext = htmlpath^tname^".html"; - -(* -------------------- - The function gettext takes an instrem from the auxilliary - file .thy whose name and path are specified in the existent - Isabelle structure, treats the inputted string with all the - necessary modifications for html format and puts it into the - file with the same name but .html extension. The subfunctions - it contains are: - - after_first_c - - filter - - first_comment - - format_link - - getstring - - get_word - - he - - html - - html_escape - - insert_link - - leading_comment - - lc_exists - - modify_body - - remove_lc - - rest - - thy_name - -------------------- *) - - fun gettext is = - let - val head = "\n\n"^intext^ - "\n\n\n"^"\n"; - val title = "

    "^tname^".thy"^"

    \n\n"^ - "
    \nDependency Chart\n"^ - ": display of dependencies between the theories.\n"^ - "
    \n
    \n\n
    \n";
    -		val tail = "
    "^"\n"^""; - - - (* -------------------- - The function he (html escape) is going to take - every single characterof the input stream and check - for ">", "<" and "&" characters that have a special - meaning in html and convert them into their corresponding - escape sequences. - -------------------- *) - fun he [] r = r - | he ("<"::sl) r = he sl (r@["&","l","t"]) - | he (">"::sl) r = he sl (r@["&","g","t"]) - | he ("&"::sl) r = he sl (r@["&","a","m","p"]) - | he (c::sl) r = he sl (r@[c]); - - fun html_escape sl = he sl []; - - (* -------------------- - The function first_comment is a pattern checking for - nested comments. The argument d will keep track of how - deep we are in the nested comment. The function will - return the first comment extracted from the input stream, - so that we can copy it into the output stream. Lexical - error is raised if we open an empty file to read from. - -------------------- *) - fun first_comment ("*"::")"::cs) co 1 = co@["*",")"] - | first_comment ("*"::")"::cs) co d = - first_comment cs (co@["*",")"]) (d-1) - | first_comment ("("::"*"::cs) co d = - first_comment cs (co@["(","*"]) (d+1) - | first_comment (c::cs) co d = - if d>0 then first_comment cs (co@[c]) d - else first_comment cs co d - | first_comment [] _ _ = raise lex_err; - - (* -------------------- - The function lc_exists leading comment exists?) - checks whether in the input file at the very beginning - there is a comment, which needs to be extracted and put - into the output file. We also need to check whether there - might be a space, a new line or a tab, which do not - exclude the possibility that there is a leading comment. - The function returns a boolean value. - -------------------- *) - fun lc_exists ("("::"*"::_) = true - | lc_exists (" "::cs) = lc_exists cs - | lc_exists ("\n"::cs) = lc_exists cs - | lc_exists ("\t"::cs) = lc_exists cs - | lc_exists _ = false; - - (* -------------------- - In the case that there is a leading comment, this - function leading_comment extracts it> It also need - to check for any html escape sequences in the comment. - -------------------- *) - fun leading_comment sl = - if (lc_exists sl) then - (html_escape (first_comment sl [] 0)) - else - [""]; - - (* -------------------- - The function thy_name checks for the parent theory - names apearing after the leading comment. The function - returns a boolean value indicating if the word is a - theory name, so that a link can be inserted and can look - for another potential theory name. If the word is not a - theory name then continue to modify the rest of the body. - -------------------- *) - fun thy_name word = - is_some (Symtab.lookup (theory_list, word)); - - (* -------------------- - Creates the right html format when inserting the link. - -------------------- *) - fun format_link s = - let in - output(std_out,"\n"^s); - ""^s^"" - end; - - (* -------------------- - -------------------- *) - - fun insert_link w = (explode (format_link (implode w))) - (* -------------------- - -------------------- *) - - fun html ( " "::l) r = html l (r@[ " "]) - | html ( "+"::l) r = html l (r@[ "+"]) - | html ("\n"::l) r = html l (r@["\n"]) - | html ("\t"::l) r = html l (r@["\t"]) - | html l r = r@(get_word l []) - (* -------------------- - -------------------- *) - and get_word ( " "::l) w = - if (thy_name (implode w)) - then (insert_link w)@[ " "]@(html l []) - else w@[" "]@(html_escape l) - | get_word ( "+"::l) w = - if (thy_name (implode w)) - then (insert_link w)@[ "+"]@(html l []) - else w@["+"]@(html_escape l) - | get_word ("\n"::l) w = - if (thy_name (implode w)) - then (insert_link w)@[ "\n"]@(html l []) - else w@["\n"]@(html_escape l) - | get_word ("\t"::l) w = - if (thy_name (implode w)) - then (insert_link w)@[ "\t"]@(html l []) - else w@["\t"]@(html_escape l) - | get_word (c::l) w = (get_word l (w@[c])) - | get_word [] [] = [] - | get_word [] w = - if (thy_name (implode w)) - then (insert_link w) - else w; - - (* -------------------- - -------------------- *) - fun modify_body ("="::l) r = r@["="]@(html l []) - | modify_body (c::l) r = modify_body l (r@[c]) - | modify_body [] r = r; - - (* -------------------- - -------------------- *) - fun after_first_c ("*"::")"::cs) 1 = cs - | after_first_c ("*"::")"::cs) d = after_first_c cs (d-1) - | after_first_c ("("::"*"::cs) d = after_first_c cs (d+1) - | after_first_c (c::cs) d = after_first_c cs d - | after_first_c cs 0 = cs - | after_first_c [] _ = raise lex_err; - - (* -------------------- - -------------------- *) - fun remove_lc sl = - if (lc_exists sl) then (after_first_c sl 0) else sl; - - (* -------------------- - -------------------- *) - fun rest sl = modify_body (remove_lc sl) []; - - (* -------------------- - -------------------- *) - fun filter sl = (leading_comment sl) @ (rest sl); - - (* -------------------- - -------------------- *) - fun getstring s = - case input (is, 1) of - "" => head^title^(implode(filter(explode(s))))^tail - | "\n" => getstring (s^"\n") - | c => getstring (s^c) - in - getstring "" - end; - - (* -------------------- - -------------------- *) - fun transform t = - let - val infile = open_in intext; - val outfile = open_out outtext - in - output(std_out,"\nTheory: "^t); - output (outfile, gettext(infile)); - close_in (infile); - close_out (outfile) - end; - - (* -------------------- - -------------------- *) - fun create_pure p = - let - val outfile = open_out outtext - in - output(std_out, "\nCreating Pure.html ..."); - output (outfile, "\n\n"^intext^ - "\n\n\n"^"\n"^ - "

    "^tname^".thy"^"

    \n\n"^"
    \n"^
    -			"This is a theory file called Pure.\n"^
    -			"Its children are all other Isabelle theories."^
    -			"
    "^"\n"^""); - close_out (outfile) - end - - in - if (tname <> "Pure") then (transform tname) - else (create_pure tname) - end; - -(* -------------------- - -------------------- *) -map move_eachf (files); -