src/Pure/Thy/sessions.scala
changeset 70671 cb1776c8e216
parent 70668 9cac4dec0da9
child 70672 e4bba654d085
equal deleted inserted replaced
70670:a1dfd603260e 70671:cb1776c8e216
   251         case errs => error(cat_lines(errs))
   251         case errs => error(cat_lines(errs))
   252       }
   252       }
   253   }
   253   }
   254 
   254 
   255   def deps(sessions_structure: Structure,
   255   def deps(sessions_structure: Structure,
   256       global_theories: Map[String, String],
       
   257       progress: Progress = No_Progress,
   256       progress: Progress = No_Progress,
   258       inlined_files: Boolean = false,
   257       inlined_files: Boolean = false,
   259       verbose: Boolean = false,
   258       verbose: Boolean = false,
   260       list_files: Boolean = false,
   259       list_files: Boolean = false,
   261       check_keywords: Set[String] = Set.empty): Deps =
   260       check_keywords: Set[String] = Set.empty): Deps =
   288 
   287 
   289           val info = sessions_structure(session_name)
   288           val info = sessions_structure(session_name)
   290           try {
   289           try {
   291             val parent_base: Sessions.Base =
   290             val parent_base: Sessions.Base =
   292               info.parent match {
   291               info.parent match {
   293                 case None => Base.bootstrap(global_theories)
   292                 case None => Base.bootstrap(sessions_structure.global_theories)
   294                 case Some(parent) => session_bases(parent)
   293                 case Some(parent) => session_bases(parent)
   295               }
   294               }
   296             val imports_base: Sessions.Base =
   295             val imports_base: Sessions.Base =
   297               parent_base.copy(known =
   296               parent_base.copy(known =
   298                 Known.make(info.dir, parent_base :: info.imports.map(session_bases(_))))
   297                 Known.make(info.dir, parent_base :: info.imports.map(session_bases(_))))
   385 
   384 
   386             val base =
   385             val base =
   387               Base(
   386               Base(
   388                 pos = info.pos,
   387                 pos = info.pos,
   389                 doc_names = doc_names,
   388                 doc_names = doc_names,
   390                 global_theories = global_theories,
   389                 global_theories = sessions_structure.global_theories,
   391                 loaded_theories = dependencies.loaded_theories,
   390                 loaded_theories = dependencies.loaded_theories,
   392                 used_theories = used_theories,
   391                 used_theories = used_theories,
   393                 dump_checkpoints = dump_checkpoints,
   392                 dump_checkpoints = dump_checkpoints,
   394                 known = known,
   393                 known = known,
   395                 overall_syntax = overall_syntax,
   394                 overall_syntax = overall_syntax,
   438     session_requirements: Boolean = false,
   437     session_requirements: Boolean = false,
   439     session_focus: Boolean = false,
   438     session_focus: Boolean = false,
   440     all_known: Boolean = false): Base_Info =
   439     all_known: Boolean = false): Base_Info =
   441   {
   440   {
   442     val full_sessions = load_structure(options, dirs = dirs)
   441     val full_sessions = load_structure(options, dirs = dirs)
   443     val global_theories = full_sessions.global_theories
       
   444 
   442 
   445     val selected_sessions =
   443     val selected_sessions =
   446       full_sessions.selection(Selection(sessions = session :: session_ancestor.toList))
   444       full_sessions.selection(Selection(sessions = session :: session_ancestor.toList))
   447     val info = selected_sessions(session)
   445     val info = selected_sessions(session)
   448     val ancestor = session_ancestor orElse info.parent
   446     val ancestor = session_ancestor orElse info.parent
   449 
   447 
   450     val (session1, infos1) =
   448     val (session1, infos1) =
   451       if (session_requirements && ancestor.isDefined) {
   449       if (session_requirements && ancestor.isDefined) {
   452         val deps = Sessions.deps(selected_sessions, global_theories, progress = progress)
   450         val deps = Sessions.deps(selected_sessions, progress = progress)
   453         val base = deps(session)
   451         val base = deps(session)
   454 
   452 
   455         val ancestor_loaded =
   453         val ancestor_loaded =
   456           deps.get(ancestor.get) match {
   454           deps.get(ancestor.get) match {
   457             case Some(ancestor_base)
   455             case Some(ancestor_base)
   509         else sel_sessions1
   507         else sel_sessions1
   510       full_sessions1.selection(Selection(sessions = select_sessions1))
   508       full_sessions1.selection(Selection(sessions = select_sessions1))
   511     }
   509     }
   512 
   510 
   513     val sessions1 = if (all_known) full_sessions1 else selected_sessions1
   511     val sessions1 = if (all_known) full_sessions1 else selected_sessions1
   514     val deps1 = Sessions.deps(sessions1, global_theories, progress = progress)
   512     val deps1 = Sessions.deps(sessions1, progress = progress)
   515     val base1 = deps1(session1).copy(known = deps1.all_known)
   513     val base1 = deps1(session1).copy(known = deps1.all_known)
   516 
   514 
   517     Base_Info(options, dirs, session1, deps1.sessions_structure, deps1.errors, base1, infos1)
   515     Base_Info(options, dirs, session1, deps1.sessions_structure, deps1.errors, base1, infos1)
   518   }
   516   }
   519 
   517 
   660       (graph /: graph.iterator) {
   658       (graph /: graph.iterator) {
   661         case (g, (name, (info, _))) => (g /: edges(info))(add_edge(info.pos, name, _, _))
   659         case (g, (name, (info, _))) => (g /: edges(info))(add_edge(info.pos, name, _, _))
   662       }
   660       }
   663     }
   661     }
   664 
   662 
   665     val graph0 =
   663     val info_graph =
   666       (Graph.string[Info] /: infos) {
   664       (Graph.string[Info] /: infos) {
   667         case (graph, info) =>
   665         case (graph, info) =>
   668           if (graph.defined(info.name))
   666           if (graph.defined(info.name))
   669             error("Duplicate session " + quote(info.name) + Position.here(info.pos) +
   667             error("Duplicate session " + quote(info.name) + Position.here(info.pos) +
   670               Position.here(graph.get_node(info.name).pos))
   668               Position.here(graph.get_node(info.name).pos))
   671           else graph.new_node(info.name, info)
   669           else graph.new_node(info.name, info)
   672       }
   670       }
   673     val graph1 = add_edges(graph0, "parent", _.parent)
   671     val build_graph = add_edges(info_graph, "parent", _.parent)
   674     val graph2 = add_edges(graph1, "imports", _.imports)
   672     val imports_graph = add_edges(build_graph, "imports", _.imports)
   675 
   673 
   676     new Structure(graph1, graph2)
   674     val strict_directories: Map[JFile, String] =
   677   }
       
   678 
       
   679   final class Structure private[Sessions](
       
   680       val build_graph: Graph[String, Info],
       
   681       val imports_graph: Graph[String, Info])
       
   682   {
       
   683     sessions_structure =>
       
   684 
       
   685     lazy val chapters: SortedMap[String, List[Info]] =
       
   686       (SortedMap.empty[String, List[Info]] /: build_graph.iterator)(
       
   687         { case (chs, (_, (info, _))) =>
       
   688             chs + (info.chapter -> (info :: chs.getOrElse(info.chapter, Nil))) })
       
   689 
       
   690     def build_graph_display: Graph_Display.Graph = Graph_Display.make_graph(build_graph)
       
   691     def imports_graph_display: Graph_Display.Graph = Graph_Display.make_graph(imports_graph)
       
   692 
       
   693     def defined(name: String): Boolean = imports_graph.defined(name)
       
   694     def apply(name: String): Info = imports_graph.get_node(name)
       
   695     def get(name: String): Option[Info] = if (defined(name)) Some(apply(name)) else None
       
   696 
       
   697     def strict_directories: Map[JFile, String] =
       
   698       (Map.empty[JFile, String] /:
   675       (Map.empty[JFile, String] /:
   699         (for {
   676         (for {
   700           session <- imports_topological_order.iterator
   677           session <- imports_graph.topological_order.iterator
   701           info = apply(session)
   678           info = info_graph.get_node(session)
   702           dir <- info.dirs_strict.iterator
   679           dir <- info.dirs_strict.iterator
   703         } yield (info, dir)))({ case (dirs, (info, dir)) =>
   680         } yield (info, dir)))({ case (dirs, (info, dir)) =>
   704             val session = info.name
   681             val session = info.name
   705             val canonical_dir = dir.canonical_file
   682             val canonical_dir = dir.canonical_file
   706             dirs.get(canonical_dir) match {
   683             dirs.get(canonical_dir) match {
   707               case Some(session1) if session != session1 =>
   684               case Some(session1) if session != session1 =>
   708                 val info1 = apply(session1)
   685                 val info1 = info_graph.get_node(session1)
   709                 error("Duplicate use of directory " + dir +
   686                 error("Duplicate use of directory " + dir +
   710                   "\n  for session " + quote(session1) + Position.here(info1.pos) +
   687                   "\n  for session " + quote(session1) + Position.here(info1.pos) +
   711                   "\n  vs. session " + quote(session) + Position.here(info.pos))
   688                   "\n  vs. session " + quote(session) + Position.here(info.pos))
   712               case _ => dirs + (canonical_dir -> session)
   689               case _ => dirs + (canonical_dir -> session)
   713             }
   690             }
   714           })
   691           })
   715 
   692 
   716     def global_theories: Map[String, String] =
   693     val global_theories: Map[String, String] =
   717       (Thy_Header.bootstrap_global_theories.toMap /:
   694       (Thy_Header.bootstrap_global_theories.toMap /:
   718         (for {
   695         (for {
   719           (_, (info, _)) <- imports_graph.iterator
   696           session <- imports_graph.topological_order.iterator
       
   697           info = info_graph.get_node(session)
   720           thy <- info.global_theories.iterator }
   698           thy <- info.global_theories.iterator }
   721          yield (thy, info)))({ case (global, (thy, info)) =>
   699          yield (info, thy)))({ case (global, (info, thy)) =>
   722             val qualifier = info.name
   700             val qualifier = info.name
   723             global.get(thy) match {
   701             global.get(thy) match {
   724               case Some(qualifier1) if qualifier != qualifier1 =>
   702               case Some(qualifier1) if qualifier != qualifier1 =>
   725                 error("Duplicate global theory " + quote(thy) + Position.here(info.pos))
   703                 error("Duplicate global theory " + quote(thy) + Position.here(info.pos))
   726               case _ => global + (thy -> qualifier)
   704               case _ => global + (thy -> qualifier)
   727             }
   705             }
   728           })
   706           })
       
   707 
       
   708     new Structure(strict_directories, global_theories, build_graph, imports_graph)
       
   709   }
       
   710 
       
   711   final class Structure private[Sessions](
       
   712       val strict_directories: Map[JFile, String],
       
   713       val global_theories: Map[String, String],
       
   714       val build_graph: Graph[String, Info],
       
   715       val imports_graph: Graph[String, Info])
       
   716   {
       
   717     sessions_structure =>
       
   718 
       
   719     lazy val chapters: SortedMap[String, List[Info]] =
       
   720       (SortedMap.empty[String, List[Info]] /: build_graph.iterator)(
       
   721         { case (chs, (_, (info, _))) =>
       
   722             chs + (info.chapter -> (info :: chs.getOrElse(info.chapter, Nil))) })
       
   723 
       
   724     def build_graph_display: Graph_Display.Graph = Graph_Display.make_graph(build_graph)
       
   725     def imports_graph_display: Graph_Display.Graph = Graph_Display.make_graph(imports_graph)
       
   726 
       
   727     def defined(name: String): Boolean = imports_graph.defined(name)
       
   728     def apply(name: String): Info = imports_graph.get_node(name)
       
   729     def get(name: String): Option[Info] = if (defined(name)) Some(apply(name)) else None
   729 
   730 
   730     def check_sessions(names: List[String])
   731     def check_sessions(names: List[String])
   731     {
   732     {
   732       val bad_sessions = SortedSet(names.filterNot(defined(_)): _*).toList
   733       val bad_sessions = SortedSet(names.filterNot(defined(_)): _*).toList
   733       if (bad_sessions.nonEmpty)
   734       if (bad_sessions.nonEmpty)
   777       {
   778       {
   778         val sessions = graph.all_preds(selected(graph, sel)).filterNot(excluded)
   779         val sessions = graph.all_preds(selected(graph, sel)).filterNot(excluded)
   779         graph.restrict(graph.all_preds(sessions).toSet)
   780         graph.restrict(graph.all_preds(sessions).toSet)
   780       }
   781       }
   781 
   782 
   782       new Structure(restrict(build_graph), restrict(imports_graph))
   783       new Structure(
       
   784         strict_directories, global_theories, restrict(build_graph), restrict(imports_graph))
   783     }
   785     }
   784 
   786 
   785     def selection_deps(
   787     def selection_deps(
   786       options: Options,
   788       options: Options,
   787       selection: Selection,
   789       selection: Selection,
   813           selection.copy(exclude_sessions = excluded ::: selection.exclude_sessions)
   815           selection.copy(exclude_sessions = excluded ::: selection.exclude_sessions)
   814         }
   816         }
   815         else selection
   817         else selection
   816 
   818 
   817       val deps =
   819       val deps =
   818         Sessions.deps(sessions_structure.selection(selection1), global_theories,
   820         Sessions.deps(sessions_structure.selection(selection1),
   819           progress = progress, inlined_files = inlined_files, verbose = verbose)
   821           progress = progress, inlined_files = inlined_files, verbose = verbose)
   820 
   822 
   821       if (loading_sessions) {
   823       if (loading_sessions) {
   822         val selection_size = deps.sessions_structure.build_graph.size
   824         val selection_size = deps.sessions_structure.build_graph.size
   823         if (selection_size > 1) progress.echo("Loading " + selection_size + " sessions ...")
   825         if (selection_size > 1) progress.echo("Loading " + selection_size + " sessions ...")