support for purge_theories;
authorwenzelm
Fri, 23 Mar 2018 22:26:50 +0100
changeset 67936 141a93b93aa6
parent 67935 61888dd27f73
child 67937 91eb307511bb
support for purge_theories;
src/Pure/Thy/thy_resources.scala
--- a/src/Pure/Thy/thy_resources.scala	Fri Mar 23 21:56:22 2018 +0100
+++ b/src/Pure/Thy/thy_resources.scala	Fri Mar 23 22:26:50 2018 +0100
@@ -86,6 +86,9 @@
       finally { Isabelle_System.rm_tree(tmp_dir) }
     }
 
+
+    /* theories */
+
     def use_theories(
       theories: List[(String, Position.T)],
       qualifier: String = Sessions.DRAFT,
@@ -134,6 +137,9 @@
 
       result.join
     }
+
+    def purge_theories(nodes: List[Document.Node.Name] = Nil, all: Boolean = false)
+      : List[Document.Node.Name] = resources.purge_theories(session, if (all) None else Some(nodes))
   }
 
 
@@ -159,6 +165,20 @@
             case _ => thys + (name -> thy)
           }
         }))
+
+    def remove_theories(remove: List[Document.Node.Name]): State =
+    {
+      require(remove.forall(name => !is_required(name)))
+      copy(theories = theories -- remove)
+    }
+
+    lazy val theories_graph: Graph[Document.Node.Name, Unit] =
+    {
+      val entries =
+        for ((name, theory) <- theories.toList)
+        yield ((name, ()), theory.node_header.imports.map(_._1).filter(theories.isDefinedAt(_)))
+      Graph.make(entries, symmetric = true)(Document.Node.Name.Ordering)
+    }
   }
 
   final class Theory private[Thy_Resources](
@@ -172,6 +192,11 @@
     def node_perspective: Document.Node.Perspective_Text =
       Document.Node.Perspective(node_required, Text.Perspective.empty, Document.Node.Overlays.empty)
 
+    def make_edits(text_edits: List[Text.Edit]): List[Document.Edit_Text] =
+      List(node_name -> Document.Node.Deps(node_header),
+        node_name -> Document.Node.Edits(text_edits),
+        node_name -> node_perspective)
+
     def node_edits(old: Option[Theory]): List[Document.Edit_Text] =
     {
       val (text_edits, old_required) =
@@ -179,12 +204,12 @@
         else (Text.Edit.replace(0, old.get.text, text), old.get.node_required)
 
       if (text_edits.isEmpty && node_required == old_required) Nil
-      else
-        List(node_name -> Document.Node.Deps(node_header),
-          node_name -> Document.Node.Edits(text_edits),
-          node_name -> node_perspective)
+      else make_edits(text_edits)
     }
 
+    def purge_edits: List[Document.Edit_Text] =
+      make_edits(Text.Edit.removes(0, text))
+
     def required(required: Boolean): Theory =
       if (required == node_required) this
       else new Theory(node_name, node_header, text, required)
@@ -262,4 +287,24 @@
         st1.update_theories(theory_edits.map(_._2))
       })
   }
+
+  def purge_theories(session: Session, nodes: Option[List[Document.Node.Name]])
+    : List[Document.Node.Name] =
+  {
+    state.change_result(st =>
+      {
+        val graph = st.theories_graph
+        val all_nodes = graph.topological_order
+
+        val purge =
+          (if (nodes.isEmpty) all_nodes else nodes.get.filter(graph.defined(_))).
+            filterNot(st.is_required(_)).toSet
+        val purged = all_nodes.filterNot(graph.all_preds(all_nodes.filterNot(purge)).toSet)
+
+        val purge_edits = purged.flatMap(name => st.theories(name).purge_edits)
+        session.update(Document.Blobs.empty, purge_edits)
+
+        (purged, st.remove_theories(purged))
+      })
+  }
 }