src/Pure/Thy/sessions.scala
changeset 73359 d8a0e996614b
parent 73357 31d4274f32de
child 73364 6bf6160a2c54
equal deleted inserted replaced
73358:78aa7846e91f 73359:d8a0e996614b
   154         }
   154         }
   155       }
   155       }
   156     }
   156     }
   157 
   157 
   158     val session_bases =
   158     val session_bases =
   159       (Map("" -> sessions_structure.bootstrap) /: sessions_structure.imports_topological_order)({
   159       sessions_structure.imports_topological_order.foldLeft(Map("" -> sessions_structure.bootstrap)) {
   160         case (session_bases, session_name) =>
   160         case (session_bases, session_name) =>
   161           progress.expose_interrupt()
   161           progress.expose_interrupt()
   162 
   162 
   163           val info = sessions_structure(session_name)
   163           val info = sessions_structure(session_name)
   164           try {
   164           try {
   228                   .transitive_closure
   228                   .transitive_closure
   229                   .restrict(required_sessions.toSet)
   229                   .restrict(required_sessions.toSet)
   230                   .transitive_reduction_acyclic
   230                   .transitive_reduction_acyclic
   231 
   231 
   232               val graph0 =
   232               val graph0 =
   233                 (Graph_Display.empty_graph /: required_subgraph.topological_order)(
   233                 required_subgraph.topological_order.foldLeft(Graph_Display.empty_graph) {
   234                   { case (g, session) =>
   234                   case (g, session) =>
   235                       val a = session_node(session)
   235                     val a = session_node(session)
   236                       val bs = required_subgraph.imm_preds(session).toList.map(session_node)
   236                     val bs = required_subgraph.imm_preds(session).toList.map(session_node)
   237                       ((g /: (a :: bs))(_.default_node(_, Nil)) /: bs)(_.add_edge(_, a)) })
   237                     bs.foldLeft((a :: bs).foldLeft(g)(_.default_node(_, Nil)))(_.add_edge(_, a))
   238 
   238                 }
   239               (graph0 /: dependencies.entries)(
   239 
   240                 { case (g, entry) =>
   240               dependencies.entries.foldLeft(graph0) {
   241                     val a = node(entry.name)
   241                 case (g, entry) =>
   242                     val bs = entry.header.imports.map(node).filterNot(_ == a)
   242                   val a = node(entry.name)
   243                     ((g /: (a :: bs))(_.default_node(_, Nil)) /: bs)(_.add_edge(_, a)) })
   243                   val bs = entry.header.imports.map(node).filterNot(_ == a)
       
   244                   bs.foldLeft((a :: bs).foldLeft(g)(_.default_node(_, Nil)))(_.add_edge(_, a))
       
   245               }
   244             }
   246             }
   245 
   247 
   246             val known_theories =
   248             val known_theories =
   247               (deps_base.known_theories /:
   249               dependencies.entries.iterator.map(entry => entry.name.theory -> entry).
   248                 dependencies.entries.iterator.map(entry => entry.name.theory -> entry))(_ + _)
   250                 foldLeft(deps_base.known_theories)(_ + _)
   249 
   251 
   250             val known_loaded_files = deps_base.known_loaded_files ++ loaded_files
   252             val known_loaded_files = deps_base.known_loaded_files ++ loaded_files
   251 
   253 
   252             val import_errors =
   254             val import_errors =
   253             {
   255             {
   355           catch {
   357           catch {
   356             case ERROR(msg) =>
   358             case ERROR(msg) =>
   357               cat_error(msg, "The error(s) above occurred in session " +
   359               cat_error(msg, "The error(s) above occurred in session " +
   358                 quote(info.name) + Position.here(info.pos))
   360                 quote(info.name) + Position.here(info.pos))
   359           }
   361           }
   360       })
   362       }
   361 
   363 
   362     Deps(sessions_structure, session_bases)
   364     Deps(sessions_structure, session_bases)
   363   }
   365   }
   364 
   366 
   365 
   367 
   487     {
   489     {
   488       val parent_base = session_bases(parent.getOrElse(""))
   490       val parent_base = session_bases(parent.getOrElse(""))
   489       val imports_bases = imports.map(session_bases)
   491       val imports_bases = imports.map(session_bases)
   490       parent_base.copy(
   492       parent_base.copy(
   491         known_theories =
   493         known_theories =
   492           (parent_base.known_theories /:
   494           (for {
   493             (for {
   495             base <- imports_bases.iterator
   494               base <- imports_bases.iterator
   496             (_, entry) <- base.known_theories.iterator
   495               (_, entry) <- base.known_theories.iterator
   497           } yield (entry.name.theory -> entry)).foldLeft(parent_base.known_theories)(_ + _),
   496             } yield (entry.name.theory -> entry)))(_ + _),
       
   497         known_loaded_files =
   498         known_loaded_files =
   498           (parent_base.known_loaded_files /:
   499           imports_bases.iterator.map(_.known_loaded_files).
   499             imports_bases.iterator.map(_.known_loaded_files))(_ ++ _))
   500             foldLeft(parent_base.known_loaded_files)(_ ++ _))
   500     }
   501     }
   501 
   502 
   502     def dirs: List[Path] = dir :: directories
   503     def dirs: List[Path] = dir :: directories
   503 
   504 
   504     def timeout: Time = Time.seconds(options.real("timeout") * options.real("timeout_scale"))
   505     def timeout: Time = Time.seconds(options.real("timeout") * options.real("timeout_scale"))
   659               error(cat_lines(exn.cycles.map(cycle =>
   660               error(cat_lines(exn.cycles.map(cycle =>
   660                 "Cyclic session dependency of " +
   661                 "Cyclic session dependency of " +
   661                   cycle.map(c => quote(c.toString)).mkString(" via "))) + Position.here(pos))
   662                   cycle.map(c => quote(c.toString)).mkString(" via "))) + Position.here(pos))
   662           }
   663           }
   663         }
   664         }
   664         (graph /: graph.iterator) {
   665         graph.iterator.foldLeft(graph) {
   665           case (g, (name, (info, _))) => (g /: edges(info))(add_edge(info.pos, name, _, _))
   666           case (g, (name, (info, _))) =>
       
   667             edges(info).foldLeft(g)(add_edge(info.pos, name, _, _))
   666         }
   668         }
   667       }
   669       }
   668 
   670 
   669       val info_graph =
   671       val info_graph =
   670         (Graph.string[Info] /: infos) {
   672         infos.foldLeft(Graph.string[Info]) {
   671           case (graph, info) =>
   673           case (graph, info) =>
   672             if (graph.defined(info.name))
   674             if (graph.defined(info.name))
   673               error("Duplicate session " + quote(info.name) + Position.here(info.pos) +
   675               error("Duplicate session " + quote(info.name) + Position.here(info.pos) +
   674                 Position.here(graph.get_node(info.name).pos))
   676                 Position.here(graph.get_node(info.name).pos))
   675             else graph.new_node(info.name, info)
   677             else graph.new_node(info.name, info)
   679 
   681 
   680       val session_positions: List[(String, Position.T)] =
   682       val session_positions: List[(String, Position.T)] =
   681         (for ((name, (info, _)) <- info_graph.iterator) yield (name, info.pos)).toList
   683         (for ((name, (info, _)) <- info_graph.iterator) yield (name, info.pos)).toList
   682 
   684 
   683       val session_directories: Map[JFile, String] =
   685       val session_directories: Map[JFile, String] =
   684         (Map.empty[JFile, String] /:
   686         (for {
   685           (for {
   687           session <- imports_graph.topological_order.iterator
   686             session <- imports_graph.topological_order.iterator
   688           info = info_graph.get_node(session)
   687             info = info_graph.get_node(session)
   689           dir <- info.dirs.iterator
   688             dir <- info.dirs.iterator
   690         } yield (info, dir)).foldLeft(Map.empty[JFile, String]) {
   689           } yield (info, dir)))({ case (dirs, (info, dir)) =>
   691             case (dirs, (info, dir)) =>
   690               val session = info.name
   692               val session = info.name
   691               val canonical_dir = dir.canonical_file
   693               val canonical_dir = dir.canonical_file
   692               dirs.get(canonical_dir) match {
   694               dirs.get(canonical_dir) match {
   693                 case Some(session1) =>
   695                 case Some(session1) =>
   694                   val info1 = info_graph.get_node(session1)
   696                   val info1 = info_graph.get_node(session1)
   695                   error("Duplicate use of directory " + dir +
   697                   error("Duplicate use of directory " + dir +
   696                     "\n  for session " + quote(session1) + Position.here(info1.pos) +
   698                     "\n  for session " + quote(session1) + Position.here(info1.pos) +
   697                     "\n  vs. session " + quote(session) + Position.here(info.pos))
   699                     "\n  vs. session " + quote(session) + Position.here(info.pos))
   698                 case None => dirs + (canonical_dir -> session)
   700                 case None => dirs + (canonical_dir -> session)
   699               }
   701               }
   700             })
   702           }
   701 
   703 
   702       val global_theories: Map[String, String] =
   704       val global_theories: Map[String, String] =
   703         (Thy_Header.bootstrap_global_theories.toMap /:
   705         (for {
   704           (for {
   706           session <- imports_graph.topological_order.iterator
   705             session <- imports_graph.topological_order.iterator
   707           info = info_graph.get_node(session)
   706             info = info_graph.get_node(session)
   708           thy <- info.global_theories.iterator }
   707             thy <- info.global_theories.iterator }
   709           yield (info, thy)).foldLeft(Thy_Header.bootstrap_global_theories.toMap) {
   708            yield (info, thy)))({ case (global, (info, thy)) =>
   710             case (global, (info, thy)) =>
   709               val qualifier = info.name
   711               val qualifier = info.name
   710               global.get(thy) match {
   712               global.get(thy) match {
   711                 case Some(qualifier1) if qualifier != qualifier1 =>
   713                 case Some(qualifier1) if qualifier != qualifier1 =>
   712                   error("Duplicate global theory " + quote(thy) + Position.here(info.pos))
   714                   error("Duplicate global theory " + quote(thy) + Position.here(info.pos))
   713                 case _ => global + (thy -> qualifier)
   715                 case _ => global + (thy -> qualifier)
   714               }
   716               }
   715             })
   717           }
   716 
   718 
   717       new Structure(
   719       new Structure(
   718         session_positions, session_directories, global_theories, build_graph, imports_graph)
   720         session_positions, session_directories, global_theories, build_graph, imports_graph)
   719     }
   721     }
   720   }
   722   }
   737     def dest_session_directories: List[(String, String)] =
   739     def dest_session_directories: List[(String, String)] =
   738       for ((file, session) <- session_directories.toList)
   740       for ((file, session) <- session_directories.toList)
   739         yield (File.standard_path(file), session)
   741         yield (File.standard_path(file), session)
   740 
   742 
   741     lazy val chapters: SortedMap[String, List[Info]] =
   743     lazy val chapters: SortedMap[String, List[Info]] =
   742       (SortedMap.empty[String, List[Info]] /: build_graph.iterator)(
   744       build_graph.iterator.foldLeft(SortedMap.empty[String, List[Info]]) {
   743         { case (chs, (_, (info, _))) =>
   745         case (chs, (_, (info, _))) =>
   744             chs + (info.chapter -> (info :: chs.getOrElse(info.chapter, Nil))) })
   746           chs + (info.chapter -> (info :: chs.getOrElse(info.chapter, Nil)))
       
   747       }
   745 
   748 
   746     def build_graph_display: Graph_Display.Graph = Graph_Display.make_graph(build_graph)
   749     def build_graph_display: Graph_Display.Graph = Graph_Display.make_graph(build_graph)
   747     def imports_graph_display: Graph_Display.Graph = Graph_Display.make_graph(imports_graph)
   750     def imports_graph_display: Graph_Display.Graph = Graph_Display.make_graph(imports_graph)
   748 
   751 
   749     def defined(name: String): Boolean = imports_graph.defined(name)
   752     def defined(name: String): Boolean = imports_graph.defined(name)
  1059         (select, dir) <- directories(dirs, select_dirs)
  1062         (select, dir) <- directories(dirs, select_dirs)
  1060         res <- load_dir(select, check_session_dir(dir))
  1063         res <- load_dir(select, check_session_dir(dir))
  1061       } yield res
  1064       } yield res
  1062 
  1065 
  1063     val unique_roots =
  1066     val unique_roots =
  1064       ((Map.empty[JFile, (Boolean, Path)] /: roots) { case (m, (select, path)) =>
  1067       roots.foldLeft(Map.empty[JFile, (Boolean, Path)]) {
  1065         val file = path.canonical_file
  1068         case (m, (select, path)) =>
  1066         m.get(file) match {
  1069           val file = path.canonical_file
  1067           case None => m + (file -> (select, path))
  1070           m.get(file) match {
  1068           case Some((select1, path1)) => m + (file -> (select1 || select, path1))
  1071             case None => m + (file -> (select, path))
  1069         }
  1072             case Some((select1, path1)) => m + (file -> (select1 || select, path1))
  1070       }).toList.map(_._2)
  1073           }
       
  1074       }.toList.map(_._2)
  1071 
  1075 
  1072     Structure.make(unique_roots.flatMap(p => read_root(options, p._1, p._2)) ::: infos)
  1076     Structure.make(unique_roots.flatMap(p => read_root(options, p._1, p._2)) ::: infos)
  1073   }
  1077   }
  1074 
  1078 
  1075 
  1079