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) |
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) |