| author | wenzelm | 
| Fri, 08 Dec 2023 20:08:52 +0100 | |
| changeset 79216 | 58f9b0d53d97 | 
| parent 78839 | 7799ec03b8bd | 
| child 79777 | db9c6be8e236 | 
| permissions | -rw-r--r-- | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 1 | /* Title: Pure/Tools/dump.scala | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 3 | |
| 68348 | 4 | Dump cumulative PIDE session database. | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 6 | |
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 8 | |
| 71534 | 9 | import java.io.{BufferedWriter, FileOutputStream, OutputStreamWriter}
 | 
| 10 | ||
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 11 | |
| 75393 | 12 | object Dump {
 | 
| 68316 | 13 | /* aspects */ | 
| 14 | ||
| 15 | sealed case class Aspect_Args( | |
| 68355 | 16 | options: Options, | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 17 | deps: Sessions.Deps, | 
| 68355 | 18 | progress: Progress, | 
| 69896 | 19 | output_dir: Path, | 
| 68929 | 20 | snapshot: Document.Snapshot, | 
| 75393 | 21 | status: Document_Status.Node_Status | 
| 22 |   ) {
 | |
| 23 |     def write_path(file_name: Path): Path = {
 | |
| 68929 | 24 | val path = output_dir + Path.basic(snapshot.node_name.theory) + file_name | 
| 72375 | 25 | Isabelle_System.make_directory(path.dir) | 
| 71534 | 26 | path | 
| 68319 | 27 | } | 
| 28 | ||
| 71534 | 29 | def write(file_name: Path, bytes: Bytes): Unit = | 
| 30 | Bytes.write(write_path(file_name), bytes) | |
| 31 | ||
| 68365 | 32 | def write(file_name: Path, text: String): Unit = | 
| 33 | write(file_name, Bytes(text)) | |
| 68332 | 34 | |
| 68365 | 35 | def write(file_name: Path, body: XML.Body): Unit = | 
| 71534 | 36 | using(File.writer(write_path(file_name).file))( | 
| 37 | writer => YXML.traversal(s => writer.write(Symbol.encode(s)), body)) | |
| 68319 | 38 | } | 
| 68316 | 39 | |
| 75393 | 40 | sealed case class Aspect( | 
| 41 | name: String, | |
| 42 | description: String, | |
| 43 | operation: Aspect_Args => Unit, | |
| 44 | options: List[String] = Nil | |
| 45 |   ) {
 | |
| 68345 | 46 | override def toString: String = name | 
| 47 | } | |
| 68316 | 48 | |
| 69521 | 49 | val known_aspects: List[Aspect] = | 
| 68316 | 50 | List( | 
| 68365 | 51 |       Aspect("markup", "PIDE markup (YXML format)",
 | 
| 72724 | 52 | args => args.write(Path.explode(Export.MARKUP), args.snapshot.xml_markup())), | 
| 68319 | 53 |       Aspect("messages", "output messages (YXML format)",
 | 
| 72724 | 54 | args => args.write(Path.explode(Export.MESSAGES), args.snapshot.messages.map(_._1))), | 
| 68347 | 55 |       Aspect("latex", "generated LaTeX source",
 | 
| 72724 | 56 | args => | 
| 57 |           for {
 | |
| 58 | entry <- args.snapshot.exports | |
| 59 | if entry.name_has_prefix(Export.DOCUMENT_PREFIX) | |
| 76852 | 60 | } args.write(Path.explode(entry.name), entry.bytes)), | 
| 68347 | 61 |       Aspect("theory", "foundational theory content",
 | 
| 72724 | 62 | args => | 
| 63 |           for {
 | |
| 64 | entry <- args.snapshot.exports | |
| 65 | if entry.name_has_prefix(Export.THEORY_PREFIX) | |
| 76852 | 66 | } args.write(Path.explode(entry.name), entry.bytes), | 
| 72724 | 67 |         options = List("export_theory"))
 | 
| 68345 | 68 | ).sortBy(_.name) | 
| 68316 | 69 | |
| 70 | def show_aspects: String = | |
| 68345 | 71 | cat_lines(known_aspects.map(aspect => aspect.name + " - " + aspect.description)) | 
| 68316 | 72 | |
| 73 | def the_aspect(name: String): Aspect = | |
| 74 | known_aspects.find(aspect => aspect.name == name) getOrElse | |
| 75 |       error("Unknown aspect " + quote(name))
 | |
| 76 | ||
| 77 | ||
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 78 | /* context and session */ | 
| 69538 
faf547d2834c
clarified signature, notably cascade of dump_options, deps, resources, session;
 wenzelm parents: 
69537diff
changeset | 79 | |
| 69896 | 80 | sealed case class Args( | 
| 69897 | 81 | session: Headless.Session, | 
| 82 | snapshot: Document.Snapshot, | |
| 75393 | 83 | status: Document_Status.Node_Status | 
| 84 |   ) {
 | |
| 69896 | 85 | def print_node: String = snapshot.node_name.toString | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 86 | } | 
| 69896 | 87 | |
| 75393 | 88 |   object Context {
 | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 89 | def apply( | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 90 | options: Options, | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 91 | aspects: List[Aspect] = Nil, | 
| 71726 
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
 wenzelm parents: 
71678diff
changeset | 92 | progress: Progress = new Progress, | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 93 | dirs: List[Path] = Nil, | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 94 | select_dirs: List[Path] = Nil, | 
| 71161 
ffccc1f346ae
avoid vacuous session Pure -- dump does not read_pure_theory;
 wenzelm parents: 
71159diff
changeset | 95 | selection: Sessions.Selection = Sessions.Selection.empty, | 
| 71573 
c67076c07fb8
avoid accidental update of base session sources (following documentation in "system" manual);
 wenzelm parents: 
71534diff
changeset | 96 | pure_base: Boolean = false, | 
| 75393 | 97 | skip_base: Boolean = false | 
| 98 |     ): Context = {
 | |
| 99 |       val session_options: Options = {
 | |
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 100 | val options1 = | 
| 78839 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78617diff
changeset | 101 | Host.numa_options(options, Host.numa_node0()) + | 
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 102 | "parallel_proofs=0" + | 
| 71678 | 103 | "completion_limit=0" + | 
| 76426 | 104 | "editor_tracing_messages=0" | 
| 73359 | 105 |         aspects.foldLeft(options1) { case (opts, aspect) => aspect.options.foldLeft(opts)(_ + _) }
 | 
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 106 | } | 
| 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 107 | |
| 70869 | 108 | val sessions_structure: Sessions.Structure = | 
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 109 | Sessions.load_structure(session_options, dirs = dirs, select_dirs = select_dirs). | 
| 70869 | 110 | selection(selection) | 
| 111 | ||
| 112 |       {
 | |
| 113 | val selection_size = sessions_structure.build_graph.size | |
| 114 |         if (selection_size > 1) progress.echo("Loading " + selection_size + " sessions ...")
 | |
| 115 | } | |
| 116 | ||
| 117 | val deps: Sessions.Deps = | |
| 118 | Sessions.deps(sessions_structure, progress = progress).check_errors | |
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 119 | |
| 71573 
c67076c07fb8
avoid accidental update of base session sources (following documentation in "system" manual);
 wenzelm parents: 
71534diff
changeset | 120 | new Context(options, progress, dirs, select_dirs, pure_base, skip_base, session_options, deps) | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 121 | } | 
| 69896 | 122 | } | 
| 123 | ||
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 124 | class Context private( | 
| 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 125 | val options: Options, | 
| 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 126 | val progress: Progress, | 
| 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 127 | val dirs: List[Path], | 
| 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 128 | val select_dirs: List[Path], | 
| 71161 
ffccc1f346ae
avoid vacuous session Pure -- dump does not read_pure_theory;
 wenzelm parents: 
71159diff
changeset | 129 | val pure_base: Boolean, | 
| 71573 
c67076c07fb8
avoid accidental update of base session sources (following documentation in "system" manual);
 wenzelm parents: 
71534diff
changeset | 130 | val skip_base: Boolean, | 
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 131 | val session_options: Options, | 
| 75393 | 132 | val deps: Sessions.Deps | 
| 133 |   ) {
 | |
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 134 | context => | 
| 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 135 | |
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 136 | def session_dirs: List[Path] = dirs ::: select_dirs | 
| 68926 | 137 | |
| 75393 | 138 |     def build_logic(logic: String): Unit = {
 | 
| 70857 | 139 | Build.build_logic(options, logic, build_heap = true, progress = progress, | 
| 140 | dirs = session_dirs, strict = true) | |
| 141 | } | |
| 142 | ||
| 70864 | 143 | def sessions( | 
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 144 | logic: String = default_logic, | 
| 75393 | 145 | log: Logger = No_Logger | 
| 146 |     ): List[Session] = {
 | |
| 70869 | 147 | /* partitions */ | 
| 148 | ||
| 149 | def session_info(session_name: String): Sessions.Info = | |
| 150 | deps.sessions_structure(session_name) | |
| 151 | ||
| 70870 
877fe56af178
proper build_graph to make session selection work as in "isabelle build";
 wenzelm parents: 
70869diff
changeset | 152 | val session_graph = deps.sessions_structure.build_graph | 
| 70869 | 153 | val all_sessions = session_graph.topological_order | 
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 154 | |
| 70862 | 155 | val base_sessions = | 
| 72065 
11dc8929832d
clarified order --- proper sorting of requirements;
 wenzelm parents: 
71894diff
changeset | 156 | session_graph.all_preds_rev(List(logic).filter(session_graph.defined)) | 
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 157 | |
| 70869 | 158 | val proof_sessions = | 
| 159 | session_graph.all_succs( | |
| 160 | for (name <- all_sessions if session_info(name).record_proofs) yield name) | |
| 161 | ||
| 162 | ||
| 163 | /* resulting sessions */ | |
| 164 | ||
| 165 | def make_session( | |
| 166 | selected_sessions: List[String], | |
| 71158 | 167 | session_logic: String = logic, | 
| 71159 | 168 | strict: Boolean = false, | 
| 75393 | 169 | record_proofs: Boolean = false | 
| 170 |       ): List[Session] = {
 | |
| 71159 | 171 | if (selected_sessions.isEmpty && !strict) Nil | 
| 71158 | 172 | else List(new Session(context, session_logic, log, selected_sessions, record_proofs)) | 
| 70869 | 173 | } | 
| 174 | ||
| 71161 
ffccc1f346ae
avoid vacuous session Pure -- dump does not read_pure_theory;
 wenzelm parents: 
71159diff
changeset | 175 | val PURE = isabelle.Thy_Header.PURE | 
| 
ffccc1f346ae
avoid vacuous session Pure -- dump does not read_pure_theory;
 wenzelm parents: 
71159diff
changeset | 176 | |
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 177 | val base = | 
| 71573 
c67076c07fb8
avoid accidental update of base session sources (following documentation in "system" manual);
 wenzelm parents: 
71534diff
changeset | 178 | if ((logic == PURE && !pure_base) || skip_base) Nil | 
| 71161 
ffccc1f346ae
avoid vacuous session Pure -- dump does not read_pure_theory;
 wenzelm parents: 
71159diff
changeset | 179 | else make_session(base_sessions, session_logic = PURE, strict = logic == PURE) | 
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 180 | |
| 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 181 | val main = | 
| 70869 | 182 | make_session( | 
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 183 | session_graph.topological_order.filterNot(name => | 
| 70869 | 184 | base_sessions.contains(name) || | 
| 185 | proof_sessions.contains(name))) | |
| 186 | ||
| 71161 
ffccc1f346ae
avoid vacuous session Pure -- dump does not read_pure_theory;
 wenzelm parents: 
71159diff
changeset | 187 | val proofs = make_session(proof_sessions, session_logic = PURE, record_proofs = true) | 
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 188 | |
| 78617 
2c3a05b297f4
discontinue special treatment of AFP: "isabelle dump" has been superseded by regular "isabelle build" databases;
 wenzelm parents: 
78435diff
changeset | 189 | proofs ::: base ::: main | 
| 70857 | 190 | } | 
| 70875 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 191 | |
| 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 192 | |
| 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 193 | /* processed theories */ | 
| 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 194 | |
| 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 195 | private val processed_theories = Synchronized(Set.empty[String]) | 
| 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 196 | |
| 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 197 | def process_theory(theory: String): Boolean = | 
| 
a62c34770df9
proper guard for process_theory: ensure uniform precedence of results;
 wenzelm parents: 
70874diff
changeset | 198 | processed_theories.change_result(processed => (!processed(theory), processed + theory)) | 
| 70876 | 199 | |
| 200 | ||
| 201 | /* errors */ | |
| 202 | ||
| 203 | private val errors = Synchronized(List.empty[String]) | |
| 204 | ||
| 75393 | 205 |     def add_errors(more_errs: List[String]): Unit = {
 | 
| 70876 | 206 | errors.change(errs => errs ::: more_errs) | 
| 207 | } | |
| 208 | ||
| 75393 | 209 |     def check_errors: Unit = {
 | 
| 70876 | 210 | val errs = errors.value | 
| 211 |       if (errs.nonEmpty) error(errs.mkString("\n\n"))
 | |
| 212 | } | |
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 213 | } | 
| 68926 | 214 | |
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 215 | class Session private[Dump]( | 
| 70867 | 216 | val context: Context, | 
| 217 | val logic: String, | |
| 218 | log: Logger, | |
| 70869 | 219 | selected_sessions: List[String], | 
| 75393 | 220 | record_proofs: Boolean | 
| 221 |   ) {
 | |
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 222 | /* resources */ | 
| 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 223 | |
| 70869 | 224 | val options: Options = | 
| 225 | if (record_proofs) context.session_options + "record_proofs=2" | |
| 226 | else context.session_options | |
| 70866 | 227 | |
| 70867 | 228 | private def deps = context.deps | 
| 229 | private def progress = context.progress | |
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 230 | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 231 | val resources: Headless.Resources = | 
| 70865 | 232 | Headless.Resources.make(options, logic, progress = progress, log = log, | 
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 233 | session_dirs = context.session_dirs, | 
| 70867 | 234 | include_sessions = deps.sessions_structure.imports_topological_order) | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 235 | |
| 75393 | 236 |     val used_theories: List[Document.Node.Name] = {
 | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 237 |       for {
 | 
| 70867 | 238 | session_name <- | 
| 70871 
2beac4adc565
more complete coverage of sessions: process_theory operation needs to handle duplicate theories;
 wenzelm parents: 
70870diff
changeset | 239 | deps.sessions_structure.build_graph.restrict(selected_sessions.toSet).topological_order | 
| 70867 | 240 | (name, theory_options) <- deps(session_name).used_theories | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 241 | if !resources.session_base.loaded_theory(name.theory) | 
| 70867 | 242 |         if {
 | 
| 243 | def warn(msg: String): Unit = | |
| 244 |             progress.echo_warning("Skipping theory " + name + "  (" + msg + ")")
 | |
| 245 | ||
| 246 | val conditions = | |
| 247 |             space_explode(',', theory_options.string("condition")).
 | |
| 248 | filter(cond => Isabelle_System.getenv(cond) == "") | |
| 249 |           if (conditions.nonEmpty) {
 | |
| 250 |             warn("undefined " + conditions.mkString(", "))
 | |
| 251 | false | |
| 252 | } | |
| 253 |           else if (options.bool("skip_proofs") && !theory_options.bool("skip_proofs")) {
 | |
| 254 |             warn("option skip_proofs")
 | |
| 255 | false | |
| 256 | } | |
| 257 | else true | |
| 258 | } | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 259 | } yield name | 
| 68926 | 260 | } | 
| 261 | ||
| 262 | ||
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 263 | /* process */ | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 264 | |
| 75393 | 265 |     def process(process_theory: Args => Unit, unicode_symbols: Boolean = false): Unit = {
 | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 266 | val session = resources.start_session(progress = progress) | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 267 | |
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 268 | |
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 269 | // asynchronous consumer | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 270 | |
| 75393 | 271 |       object Consumer {
 | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 272 | sealed case class Bad_Theory( | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 273 | name: Document.Node.Name, | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 274 | status: Document_Status.Node_Status, | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 275 | errors: List[String]) | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 276 | |
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 277 | private val consumer_bad_theories = Synchronized(List.empty[Bad_Theory]) | 
| 68318 | 278 | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 279 | private val consumer = | 
| 75394 | 280 | Consumer_Thread.fork(name = "dump")(consume = | 
| 281 |             { (args: (Document.Snapshot, Document_Status.Node_Status)) =>
 | |
| 282 | val (snapshot, status) = args | |
| 283 | val name = snapshot.node_name | |
| 284 |               if (status.ok) {
 | |
| 285 |                 try {
 | |
| 286 |                   if (context.process_theory(name.theory)) {
 | |
| 287 | process_theory(Args(session, snapshot, status)) | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 288 | } | 
| 70871 
2beac4adc565
more complete coverage of sessions: process_theory operation needs to handle duplicate theories;
 wenzelm parents: 
70870diff
changeset | 289 | } | 
| 75394 | 290 |                 catch {
 | 
| 291 | case exn: Throwable if !Exn.is_interrupt(exn) => | |
| 292 | val msg = Exn.message(exn) | |
| 293 |                     progress.echo("FAILED to process theory " + name)
 | |
| 294 | progress.echo_error_message(msg) | |
| 295 | consumer_bad_theories.change(Bad_Theory(name, status, List(msg)) :: _) | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 296 | } | 
| 75394 | 297 | } | 
| 298 |               else {
 | |
| 299 | val msgs = | |
| 300 | for ((elem, pos) <- snapshot.messages if Protocol.is_error(elem)) | |
| 301 |                   yield {
 | |
| 302 | "Error" + Position.here(pos) + ":\n" + | |
| 303 | XML.content(Pretty.formatted(List(elem))) | |
| 304 | } | |
| 305 |                 progress.echo("FAILED to process theory " + name)
 | |
| 77509 
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
 wenzelm parents: 
77477diff
changeset | 306 | msgs.foreach(progress.echo_error_message(_)) | 
| 75394 | 307 | consumer_bad_theories.change(Bad_Theory(name, status, msgs) :: _) | 
| 308 | } | |
| 309 | true | |
| 310 | }) | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 311 | |
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 312 | def apply(snapshot: Document.Snapshot, status: Document_Status.Node_Status): Unit = | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 313 | consumer.send((snapshot, status)) | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 314 | |
| 75393 | 315 |         def shutdown(): List[Bad_Theory] = {
 | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 316 | consumer.shutdown() | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 317 | consumer_bad_theories.value.reverse | 
| 70634 
0f8742b5a9e8
more scalable isabelle dump (and derivatives): mark individual theories to share common data in ML;
 wenzelm parents: 
70626diff
changeset | 318 | } | 
| 
0f8742b5a9e8
more scalable isabelle dump (and derivatives): mark individual theories to share common data in ML;
 wenzelm parents: 
70626diff
changeset | 319 | } | 
| 
0f8742b5a9e8
more scalable isabelle dump (and derivatives): mark individual theories to share common data in ML;
 wenzelm parents: 
70626diff
changeset | 320 | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 321 | |
| 70653 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 wenzelm parents: 
70645diff
changeset | 322 | // synchronous body | 
| 68320 
1d33697199c1
shutdown ML process before output: Theories_Result is timeless/stateless;
 wenzelm parents: 
68319diff
changeset | 323 | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 324 |       try {
 | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 325 | val use_theories_result = | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 326 | session.use_theories(used_theories.map(_.theory), | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 327 | unicode_symbols = unicode_symbols, | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 328 | progress = progress, | 
| 71601 | 329 | commit = Some(Consumer.apply)) | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 330 | |
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 331 | val bad_theories = Consumer.shutdown() | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 332 | val bad_msgs = | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 333 | bad_theories.map(bad => | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 334 | Output.clean_yxml( | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 335 | "FAILED theory " + bad.name + | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 336 | (if (bad.status.consolidated) "" else ": " + bad.status.percentage + "% finished") + | 
| 77368 | 337 |                 if_proper(bad.errors, bad.errors.mkString("\n", "\n", ""))))
 | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 338 | |
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 339 | val pending_msgs = | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 340 |           use_theories_result.nodes_pending match {
 | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 341 | case Nil => Nil | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 342 |             case pending => List("Pending theories: " + commas(pending.map(p => p._1.toString)))
 | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 343 | } | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 344 | |
| 70876 | 345 | context.add_errors(bad_msgs ::: pending_msgs) | 
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 346 | } | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 347 |       finally { session.stop() }
 | 
| 69032 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 wenzelm parents: 
69026diff
changeset | 348 | } | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 349 | } | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 350 | |
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 351 | |
| 69523 | 352 | /* dump */ | 
| 353 | ||
| 354 |   val default_output_dir: Path = Path.explode("dump")
 | |
| 70858 | 355 | val default_logic: String = Thy_Header.PURE | 
| 69523 | 356 | |
| 70640 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 357 | def dump( | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 358 | options: Options, | 
| 
5f4b8a505090
more explicit type Dump.Session, with context information;
 wenzelm parents: 
70634diff
changeset | 359 | logic: String, | 
| 69523 | 360 | aspects: List[Aspect] = Nil, | 
| 71726 
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
 wenzelm parents: 
71678diff
changeset | 361 | progress: Progress = new Progress, | 
| 69523 | 362 | log: Logger = No_Logger, | 
| 363 | dirs: List[Path] = Nil, | |
| 364 | select_dirs: List[Path] = Nil, | |
| 365 | output_dir: Path = default_output_dir, | |
| 75393 | 366 | selection: Sessions.Selection = Sessions.Selection.empty | 
| 367 |   ): Unit = {
 | |
| 70856 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 368 | val context = | 
| 
545229df2f82
clarified signature: static Dump.Context vs. dynamic Dump.Session;
 wenzelm parents: 
70796diff
changeset | 369 | Context(options, aspects = aspects, progress = progress, dirs = dirs, | 
| 70796 
2739631ac368
discontinued pointless dump_checkpoint and share_common_data -- superseded by base logic image in Isabelle/MMT;
 wenzelm parents: 
70779diff
changeset | 370 | select_dirs = select_dirs, selection = selection) | 
| 69523 | 371 | |
| 70864 | 372 | context.build_logic(logic) | 
| 373 | ||
| 70865 | 374 |     for (session <- context.sessions(logic = logic, log = log)) {
 | 
| 75394 | 375 |       session.process({ (args: Args) =>
 | 
| 376 |         progress.echo("Processing theory " + args.print_node + " ...")
 | |
| 377 | val aspect_args = | |
| 378 | Aspect_Args(session.options, context.deps, progress, output_dir, | |
| 379 | args.snapshot, args.status) | |
| 380 | aspects.foreach(_.operation(aspect_args)) | |
| 381 | }) | |
| 70865 | 382 | } | 
| 70876 | 383 | |
| 384 | context.check_errors | |
| 69523 | 385 | } | 
| 386 | ||
| 387 | ||
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 388 | /* Isabelle tool wrapper */ | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 389 | |
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 390 | val isabelle_tool = | 
| 75393 | 391 |     Isabelle_Tool("dump", "dump cumulative PIDE session database", Scala_Project.here,
 | 
| 75394 | 392 |       { args =>
 | 
| 393 | var aspects: List[Aspect] = known_aspects | |
| 394 | var base_sessions: List[String] = Nil | |
| 395 | var select_dirs: List[Path] = Nil | |
| 396 | var output_dir = default_output_dir | |
| 397 | var requirements = false | |
| 398 | var exclude_session_groups: List[String] = Nil | |
| 399 | var all_sessions = false | |
| 400 | var logic = default_logic | |
| 401 | var dirs: List[Path] = Nil | |
| 402 | var session_groups: List[String] = Nil | |
| 403 | var options = Options.init() | |
| 404 | var verbose = false | |
| 405 | var exclude_sessions: List[String] = Nil | |
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 406 | |
| 75394 | 407 |         val getopts = Getopts("""
 | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 408 | Usage: isabelle dump [OPTIONS] [SESSIONS ...] | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 409 | |
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 410 | Options are: | 
| 68345 | 411 |     -A NAMES     dump named aspects (default: """ + known_aspects.mkString("\"", ",", "\"") + """)
 | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 412 | -B NAME include session NAME and all descendants | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 413 | -D DIR include session directory and select its sessions | 
| 68316 | 414 | -O DIR output directory for dumped files (default: """ + default_output_dir + """) | 
| 71807 | 415 | -R refer to requirements of selected sessions | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 416 | -X NAME exclude sessions from group NAME and all descendants | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 417 | -a select all sessions | 
| 70859 
6e6254bbce1f
split into standard partitions, for improved scalability;
 wenzelm parents: 
70858diff
changeset | 418 | -b NAME base logic image (default """ + isabelle.quote(default_logic) + """) | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 419 | -d DIR include session directory | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 420 | -g NAME select session group NAME | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 421 | -o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 422 | -v verbose | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 423 | -x NAME exclude session NAME and all descendants | 
| 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 424 | |
| 68348 | 425 | Dump cumulative PIDE session database, with the following aspects: | 
| 68316 | 426 | |
| 73736 | 427 | """ + Library.indent_lines(4, show_aspects) + "\n", | 
| 75394 | 428 |         "A:" -> (arg => aspects = Library.distinct(space_explode(',', arg)).map(the_aspect)),
 | 
| 429 | "B:" -> (arg => base_sessions = base_sessions ::: List(arg)), | |
| 430 | "D:" -> (arg => select_dirs = select_dirs ::: List(Path.explode(arg))), | |
| 431 | "O:" -> (arg => output_dir = Path.explode(arg)), | |
| 432 | "R" -> (_ => requirements = true), | |
| 433 | "X:" -> (arg => exclude_session_groups = exclude_session_groups ::: List(arg)), | |
| 434 | "a" -> (_ => all_sessions = true), | |
| 435 | "b:" -> (arg => logic = arg), | |
| 436 | "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))), | |
| 437 | "g:" -> (arg => session_groups = session_groups ::: List(arg)), | |
| 438 | "o:" -> (arg => options = options + arg), | |
| 439 | "v" -> (_ => verbose = true), | |
| 440 | "x:" -> (arg => exclude_sessions = exclude_sessions ::: List(arg))) | |
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 441 | |
| 75394 | 442 | val sessions = getopts(args) | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 443 | |
| 75394 | 444 | val progress = new Console_Progress(verbose = verbose) | 
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 445 | |
| 75394 | 446 | val start_date = Date.now() | 
| 71661 
6db526adccac
clarified messages: indicate termination explicitly;
 wenzelm parents: 
71573diff
changeset | 447 | |
| 77510 
f5d6cd98b16a
clarified signature: manage "verbose" flag via "progress";
 wenzelm parents: 
77509diff
changeset | 448 |         progress.echo("Started at " + Build_Log.print_date(start_date), verbose = true)
 | 
| 71661 
6db526adccac
clarified messages: indicate termination explicitly;
 wenzelm parents: 
71573diff
changeset | 449 | |
| 75394 | 450 |         progress.interrupt_handler {
 | 
| 451 | dump(options, logic, | |
| 452 | aspects = aspects, | |
| 453 | progress = progress, | |
| 454 | dirs = dirs, | |
| 455 | select_dirs = select_dirs, | |
| 456 | output_dir = output_dir, | |
| 457 | selection = Sessions.Selection( | |
| 458 | requirements = requirements, | |
| 459 | all_sessions = all_sessions, | |
| 460 | base_sessions = base_sessions, | |
| 461 | exclude_session_groups = exclude_session_groups, | |
| 462 | exclude_sessions = exclude_sessions, | |
| 463 | session_groups = session_groups, | |
| 464 | sessions = sessions)) | |
| 465 | } | |
| 71661 
6db526adccac
clarified messages: indicate termination explicitly;
 wenzelm parents: 
71573diff
changeset | 466 | |
| 75394 | 467 | val end_date = Date.now() | 
| 468 | val timing = end_date.time - start_date.time | |
| 71661 
6db526adccac
clarified messages: indicate termination explicitly;
 wenzelm parents: 
71573diff
changeset | 469 | |
| 77510 
f5d6cd98b16a
clarified signature: manage "verbose" flag via "progress";
 wenzelm parents: 
77509diff
changeset | 470 |         progress.echo("\nFinished at " + Build_Log.print_date(end_date), verbose = true)
 | 
| 75394 | 471 | progress.echo(timing.message_hms + " elapsed time") | 
| 472 | }) | |
| 68308 
119fc05f6b00
support to dump build database produced by PIDE session;
 wenzelm parents: diff
changeset | 473 | } |