| author | wenzelm | 
| Mon, 30 Sep 2019 11:36:21 +0200 | |
| changeset 70768 | 670bb96096a7 | 
| parent 70767 | b196f7d724b3 | 
| child 70769 | 9514fdbb8abe | 
| permissions | -rw-r--r-- | 
| 69012 | 1  | 
/* Title: Pure/PIDE/headless.scala  | 
| 67054 | 2  | 
Author: Makarius  | 
3  | 
||
| 69012 | 4  | 
Headless PIDE session and resources from file-system.  | 
| 67054 | 5  | 
*/  | 
6  | 
||
7  | 
package isabelle  | 
|
8  | 
||
9  | 
||
| 67925 | 10  | 
import java.io.{File => JFile}
 | 
11  | 
||
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
12  | 
import scala.annotation.tailrec  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
13  | 
import scala.collection.mutable  | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
14  | 
|
| 67925 | 15  | 
|
| 69012 | 16  | 
object Headless  | 
| 67054 | 17  | 
{
 | 
| 69012 | 18  | 
/** session **/  | 
| 
67061
 
2efa25302f34
synchronous session start (similar to isabelle.vscode.Server);
 
wenzelm 
parents: 
67059 
diff
changeset
 | 
19  | 
|
| 68916 | 20  | 
private def stable_snapshot(  | 
21  | 
state: Document.State, version: Document.Version, name: Document.Node.Name): Document.Snapshot =  | 
|
22  | 
  {
 | 
|
23  | 
val snapshot = state.snapshot(name)  | 
|
24  | 
assert(version.id == snapshot.version.id)  | 
|
25  | 
snapshot  | 
|
26  | 
}  | 
|
27  | 
||
| 69013 | 28  | 
class Use_Theories_Result private[Headless](  | 
| 67883 | 29  | 
val state: Document.State,  | 
| 67889 | 30  | 
val version: Document.Version,  | 
| 68925 | 31  | 
val nodes: List[(Document.Node.Name, Document_Status.Node_Status)],  | 
32  | 
val nodes_committed: List[(Document.Node.Name, Document_Status.Node_Status)])  | 
|
| 67879 | 33  | 
  {
 | 
| 
69032
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
34  | 
def nodes_pending: List[(Document.Node.Name, Document_Status.Node_Status)] =  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
35  | 
    {
 | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
36  | 
val committed = nodes_committed.iterator.map(_._1).toSet  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
37  | 
nodes.filter(p => !committed(p._1))  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
38  | 
}  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
39  | 
|
| 68925 | 40  | 
def snapshot(name: Document.Node.Name): Document.Snapshot =  | 
41  | 
stable_snapshot(state, version, name)  | 
|
42  | 
||
43  | 
def ok: Boolean =  | 
|
44  | 
      (nodes.iterator ++ nodes_committed.iterator).forall({ case (_, st) => st.ok })
 | 
|
| 67879 | 45  | 
}  | 
46  | 
||
| 70765 | 47  | 
private sealed abstract class Load_State  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
48  | 
  {
 | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
49  | 
def next(  | 
| 
70674
 
29bb1ebb188f
clarified signature: proper Document.Node.Ordering conforming to equality (e.g. required in situations where theory names are ambiguous due to overlapping session directories);
 
wenzelm 
parents: 
70657 
diff
changeset
 | 
50  | 
dep_graph: Document.Node.Name.Graph[Unit],  | 
| 70765 | 51  | 
finished: Document.Node.Name => Boolean): (List[Document.Node.Name], Load_State) =  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
52  | 
    {
 | 
| 70765 | 53  | 
val (load_theories, st1) =  | 
54  | 
        this match {
 | 
|
55  | 
case Load_Init(Nil) =>  | 
|
56  | 
(dep_graph.topological_order, Load_Finished)  | 
|
| 70767 | 57  | 
case Load_Init(target :: checkpoints) =>  | 
58  | 
(dep_graph.all_preds(List(target)).reverse, Load_Target(target, checkpoints))  | 
|
| 70768 | 59  | 
case Load_Target(pending, checkpoints) if finished(pending) =>  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
60  | 
val dep_graph1 =  | 
| 70767 | 61  | 
if (checkpoints.isEmpty) dep_graph  | 
62  | 
else dep_graph.exclude(dep_graph.all_succs(checkpoints).toSet)  | 
|
| 70768 | 63  | 
val descendants = dep_graph1.all_succs(List(pending))  | 
64  | 
(descendants, Load_Bulk(descendants, checkpoints))  | 
|
65  | 
case Load_Bulk(pending, checkpoints) if pending.forall(finished) =>  | 
|
| 70767 | 66  | 
Load_Init(checkpoints).next(dep_graph, finished)  | 
| 70765 | 67  | 
case st => (Nil, st)  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
68  | 
}  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
69  | 
(load_theories.filterNot(finished), st1)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
70  | 
}  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
71  | 
}  | 
| 70765 | 72  | 
private case class Load_Init(checkpoints: List[Document.Node.Name]) extends Load_State  | 
73  | 
private case class Load_Target(  | 
|
| 70768 | 74  | 
pending: Document.Node.Name, checkpoints: List[Document.Node.Name]) extends Load_State  | 
75  | 
private case class Load_Bulk(  | 
|
76  | 
pending: List[Document.Node.Name], checkpoints: List[Document.Node.Name]) extends Load_State  | 
|
| 70765 | 77  | 
private case object Load_Finished extends Load_State  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
78  | 
|
| 69520 | 79  | 
class Session private[Headless](  | 
80  | 
session_name: String,  | 
|
81  | 
_session_options: => Options,  | 
|
82  | 
override val resources: Resources) extends isabelle.Session(_session_options, resources)  | 
|
83  | 
  {
 | 
|
84  | 
session =>  | 
|
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
85  | 
|
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
86  | 
|
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
87  | 
private def loaded_theory(name: Document.Node.Name): Boolean =  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
88  | 
resources.session_base.loaded_theory(name.theory)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
89  | 
|
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
90  | 
|
| 69520 | 91  | 
/* options */  | 
92  | 
||
93  | 
    def default_check_delay: Time = session_options.seconds("headless_check_delay")
 | 
|
94  | 
    def default_check_limit: Int = session_options.int("headless_check_limit")
 | 
|
95  | 
    def default_nodes_status_delay: Time = session_options.seconds("headless_nodes_status_delay")
 | 
|
96  | 
    def default_watchdog_timeout: Time = session_options.seconds("headless_watchdog_timeout")
 | 
|
97  | 
    def default_commit_cleanup_delay: Time = session_options.seconds("headless_commit_cleanup_delay")
 | 
|
| 67063 | 98  | 
|
| 68922 | 99  | 
|
100  | 
/* temporary directory */  | 
|
101  | 
||
| 67925 | 102  | 
    val tmp_dir: JFile = Isabelle_System.tmp_dir("server_session")
 | 
| 67946 | 103  | 
val tmp_dir_name: String = File.path(tmp_dir).implode  | 
| 67925 | 104  | 
|
| 68923 | 105  | 
def master_directory(master_dir: String): String =  | 
106  | 
proper_string(master_dir) getOrElse tmp_dir_name  | 
|
107  | 
||
| 67945 | 108  | 
override def toString: String = session_name  | 
109  | 
||
| 67925 | 110  | 
override def stop(): Process_Result =  | 
111  | 
    {
 | 
|
112  | 
      try { super.stop() }
 | 
|
113  | 
      finally { Isabelle_System.rm_tree(tmp_dir) }
 | 
|
114  | 
}  | 
|
115  | 
||
| 67936 | 116  | 
|
117  | 
/* theories */  | 
|
118  | 
||
| 68914 | 119  | 
private sealed case class Use_Theories_State(  | 
| 70697 | 120  | 
dep_graph: Document.Node.Name.Graph[Unit],  | 
| 70765 | 121  | 
load_state: Load_State,  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
122  | 
watchdog_timeout: Time,  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
123  | 
commit: Option[(Document.Snapshot, Document_Status.Node_Status) => Unit],  | 
| 68914 | 124  | 
last_update: Time = Time.now(),  | 
125  | 
nodes_status: Document_Status.Nodes_Status = Document_Status.Nodes_Status.empty,  | 
|
| 68925 | 126  | 
already_committed: Map[Document.Node.Name, Document_Status.Node_Status] = Map.empty,  | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
127  | 
result: Option[Exn.Result[Use_Theories_Result]] = None)  | 
| 68914 | 128  | 
    {
 | 
129  | 
def update(new_nodes_status: Document_Status.Nodes_Status): Use_Theories_State =  | 
|
130  | 
copy(last_update = Time.now(), nodes_status = new_nodes_status)  | 
|
131  | 
||
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
132  | 
def watchdog: Boolean =  | 
| 68914 | 133  | 
watchdog_timeout > Time.zero && Time.now() - last_update > watchdog_timeout  | 
134  | 
||
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
135  | 
def finished_result: Boolean = result.isDefined  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
136  | 
|
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
137  | 
def join_result: Option[(Exn.Result[Use_Theories_Result], Use_Theories_State)] =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
138  | 
if (finished_result) Some((result.get, this)) else None  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
139  | 
|
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
140  | 
def cancel_result: Use_Theories_State =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
141  | 
if (finished_result) this else copy(result = Some(Exn.Exn(Exn.Interrupt())))  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
142  | 
|
| 
70763
 
5fae55752c70
tuned messages (again) -- avoid confusion wrt. total remaining size;
 
wenzelm 
parents: 
70710 
diff
changeset
 | 
143  | 
def clean_theories: (List[Document.Node.Name], Use_Theories_State) =  | 
| 70698 | 144  | 
      {
 | 
145  | 
@tailrec def frontier(base: List[Document.Node.Name], front: Set[Document.Node.Name])  | 
|
146  | 
: Set[Document.Node.Name] =  | 
|
147  | 
        {
 | 
|
148  | 
val add = base.filter(name => dep_graph.imm_succs(name).forall(front))  | 
|
149  | 
if (add.isEmpty) front  | 
|
150  | 
          else {
 | 
|
151  | 
val preds = add.map(dep_graph.imm_preds)  | 
|
152  | 
val base1 = (preds.head /: preds.tail)(_ ++ _).toList.filter(already_committed.keySet)  | 
|
153  | 
frontier(base1, front ++ add)  | 
|
154  | 
}  | 
|
155  | 
}  | 
|
156  | 
||
| 
70763
 
5fae55752c70
tuned messages (again) -- avoid confusion wrt. total remaining size;
 
wenzelm 
parents: 
70710 
diff
changeset
 | 
157  | 
if (already_committed.isEmpty) (Nil, this)  | 
| 70698 | 158  | 
        else {
 | 
| 70705 | 159  | 
val base =  | 
160  | 
            (for {
 | 
|
161  | 
(name, (_, (_, succs))) <- dep_graph.iterator  | 
|
162  | 
if succs.isEmpty && already_committed.isDefinedAt(name)  | 
|
163  | 
} yield name).toList  | 
|
164  | 
val clean = frontier(base, Set.empty)  | 
|
| 
70763
 
5fae55752c70
tuned messages (again) -- avoid confusion wrt. total remaining size;
 
wenzelm 
parents: 
70710 
diff
changeset
 | 
165  | 
if (clean.isEmpty) (Nil, this)  | 
| 70698 | 166  | 
          else {
 | 
| 
70763
 
5fae55752c70
tuned messages (again) -- avoid confusion wrt. total remaining size;
 
wenzelm 
parents: 
70710 
diff
changeset
 | 
167  | 
(dep_graph.topological_order.filter(clean),  | 
| 70699 | 168  | 
copy(dep_graph = dep_graph.exclude(clean)))  | 
| 70698 | 169  | 
}  | 
170  | 
}  | 
|
171  | 
}  | 
|
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
172  | 
|
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
173  | 
def check(state: Document.State, version: Document.Version, beyond_limit: Boolean)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
174  | 
: (List[Document.Node.Name], Use_Theories_State) =  | 
| 68916 | 175  | 
      {
 | 
| 69035 | 176  | 
val already_committed1 =  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
177  | 
          commit match {
 | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
178  | 
case None => already_committed  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
179  | 
case Some(commit_fn) =>  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
180  | 
(already_committed /: dep_graph.topological_order)(  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
181  | 
                { case (committed, name) =>
 | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
182  | 
def parents_committed: Boolean =  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
183  | 
version.nodes(name).header.imports.forall(parent =>  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
184  | 
loaded_theory(parent) || committed.isDefinedAt(parent))  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
185  | 
if (!committed.isDefinedAt(name) && parents_committed &&  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
186  | 
state.node_consolidated(version, name))  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
187  | 
                    {
 | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
188  | 
val snapshot = stable_snapshot(state, version, name)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
189  | 
val status = Document_Status.Node_Status.make(state, version, name)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
190  | 
commit_fn(snapshot, status)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
191  | 
committed + (name -> status)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
192  | 
}  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
193  | 
else committed  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
194  | 
})  | 
| 68916 | 195  | 
}  | 
196  | 
||
| 70657 | 197  | 
def finished_theory(name: Document.Node.Name): Boolean =  | 
198  | 
loaded_theory(name) ||  | 
|
| 70704 | 199  | 
(if (commit.isDefined) already_committed1.isDefinedAt(name)  | 
200  | 
else state.node_consolidated(version, name))  | 
|
| 70657 | 201  | 
|
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
202  | 
val result1 =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
203  | 
if (!finished_result &&  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
204  | 
(beyond_limit || watchdog ||  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
205  | 
dep_graph.keys_iterator.forall(name =>  | 
| 70657 | 206  | 
finished_theory(name) || nodes_status.quasi_consolidated(name))))  | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
207  | 
          {
 | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
208  | 
val nodes =  | 
| 70657 | 209  | 
              (for {
 | 
210  | 
name <- dep_graph.keys_iterator  | 
|
211  | 
if !loaded_theory(name)  | 
|
212  | 
              } yield { (name -> Document_Status.Node_Status.make(state, version, name)) }).toList
 | 
|
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
213  | 
val nodes_committed =  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
214  | 
              (for {
 | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
215  | 
name <- dep_graph.keys_iterator  | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
216  | 
status <- already_committed1.get(name)  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
217  | 
} yield (name -> status)).toList  | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
218  | 
Some(Exn.Res(new Use_Theories_Result(state, version, nodes, nodes_committed)))  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
219  | 
}  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
220  | 
else result  | 
| 68925 | 221  | 
|
| 70765 | 222  | 
val (load_theories, load_state1) = load_state.next(dep_graph, finished_theory(_))  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
223  | 
|
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
224  | 
(load_theories,  | 
| 70765 | 225  | 
copy(already_committed = already_committed1, result = result1, load_state = load_state1))  | 
| 68916 | 226  | 
}  | 
| 68914 | 227  | 
}  | 
228  | 
||
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
229  | 
def use_theories(  | 
| 
67940
 
b4e80f062fbf
clarified signature -- eliminated somewhat pointless positions;
 
wenzelm 
parents: 
67939 
diff
changeset
 | 
230  | 
theories: List[String],  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
231  | 
qualifier: String = Sessions.DRAFT,  | 
| 67881 | 232  | 
master_dir: String = "",  | 
| 69920 | 233  | 
unicode_symbols: Boolean = false,  | 
| 68943 | 234  | 
check_delay: Time = default_check_delay,  | 
| 69520 | 235  | 
check_limit: Int = default_check_limit,  | 
| 68947 | 236  | 
watchdog_timeout: Time = default_watchdog_timeout,  | 
| 68943 | 237  | 
nodes_status_delay: Time = default_nodes_status_delay,  | 
| 69458 | 238  | 
id: UUID.T = UUID.random(),  | 
| 
70625
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
239  | 
share_common_data: Boolean = false,  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
240  | 
checkpoints: Set[Document.Node.Name] = Set.empty,  | 
| 68916 | 241  | 
// commit: must not block, must not fail  | 
242  | 
commit: Option[(Document.Snapshot, Document_Status.Node_Status) => Unit] = None,  | 
|
| 68981 | 243  | 
commit_cleanup_delay: Time = default_commit_cleanup_delay,  | 
| 69013 | 244  | 
progress: Progress = No_Progress): Use_Theories_Result =  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
245  | 
    {
 | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
246  | 
val dependencies =  | 
| 
68894
 
1dbdad1b57a5
more robust: load_theories after consumer is installed;
 
wenzelm 
parents: 
68888 
diff
changeset
 | 
247  | 
      {
 | 
| 
 
1dbdad1b57a5
more robust: load_theories after consumer is installed;
 
wenzelm 
parents: 
68888 
diff
changeset
 | 
248  | 
val import_names =  | 
| 68923 | 249  | 
theories.map(thy =>  | 
250  | 
resources.import_name(qualifier, master_directory(master_dir), thy) -> Position.none)  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
251  | 
resources.dependencies(import_names, progress = progress).check_errors  | 
| 
68894
 
1dbdad1b57a5
more robust: load_theories after consumer is installed;
 
wenzelm 
parents: 
68888 
diff
changeset
 | 
252  | 
}  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
253  | 
val dep_theories = dependencies.theories  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
254  | 
val dep_theories_set = dep_theories.toSet  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
255  | 
val dep_files =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
256  | 
dependencies.loaded_files(false).flatMap(_._2).  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
257  | 
          map(path => Document.Node.Name(resources.append("", path)))
 | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
258  | 
|
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
259  | 
val use_theories_state =  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
260  | 
      {
 | 
| 70765 | 261  | 
val load_state =  | 
262  | 
Load_Init(  | 
|
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
263  | 
if (checkpoints.isEmpty) Nil  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
264  | 
else dependencies.theory_graph.topological_order.filter(checkpoints(_)))  | 
| 70697 | 265  | 
Synchronized(  | 
| 70765 | 266  | 
Use_Theories_State(dependencies.theory_graph, load_state, watchdog_timeout, commit))  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
267  | 
}  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
268  | 
|
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
269  | 
def check_state(beyond_limit: Boolean = false)  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
270  | 
      {
 | 
| 
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
271  | 
val state = session.current_state()  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
272  | 
        for (version <- state.stable_tip_version) {
 | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
273  | 
val load_theories = use_theories_state.change_result(_.check(state, version, beyond_limit))  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
274  | 
          if (load_theories.nonEmpty) {
 | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
275  | 
resources.load_theories(  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
276  | 
session, id, load_theories, dep_files, unicode_symbols, share_common_data, progress)  | 
| 
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
277  | 
}  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
278  | 
}  | 
| 
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
279  | 
}  | 
| 
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
280  | 
|
| 
67894
 
fee080c4045f
more robust check_state loop, even without session activity (e.g. idempotent use_theories);
 
wenzelm 
parents: 
67893 
diff
changeset
 | 
281  | 
val check_progress =  | 
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
282  | 
      {
 | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
283  | 
var check_count = 0  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
284  | 
Event_Timer.request(Time.now(), repeat = Some(check_delay))  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
285  | 
          {
 | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
286  | 
if (progress.stopped) use_theories_state.change(_.cancel_result)  | 
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
287  | 
            else {
 | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
288  | 
check_count += 1  | 
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
289  | 
check_state(check_limit > 0 && check_count > check_limit)  | 
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
290  | 
}  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
291  | 
}  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
292  | 
}  | 
| 
67894
 
fee080c4045f
more robust check_state loop, even without session activity (e.g. idempotent use_theories);
 
wenzelm 
parents: 
67893 
diff
changeset
 | 
293  | 
|
| 68906 | 294  | 
val consumer =  | 
295  | 
      {
 | 
|
296  | 
val delay_nodes_status =  | 
|
297  | 
          Standard_Thread.delay_first(nodes_status_delay max Time.zero) {
 | 
|
| 
69818
 
60d0ee8f2ddb
more robust: avoid potentially unrelated snapshot for the sake of is_suppressed;
 
wenzelm 
parents: 
69817 
diff
changeset
 | 
298  | 
progress.nodes_status(use_theories_state.value.nodes_status)  | 
| 68906 | 299  | 
}  | 
| 
68770
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
300  | 
|
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
301  | 
val delay_commit_clean =  | 
| 68981 | 302  | 
          Standard_Thread.delay_first(commit_cleanup_delay max Time.zero) {
 | 
| 
70763
 
5fae55752c70
tuned messages (again) -- avoid confusion wrt. total remaining size;
 
wenzelm 
parents: 
70710 
diff
changeset
 | 
303  | 
val clean_theories = use_theories_state.change_result(_.clean_theories)  | 
| 70702 | 304  | 
            if (clean_theories.nonEmpty) {
 | 
| 70766 | 305  | 
              progress.echo("Removing " + clean_theories.length + " theories")
 | 
| 70702 | 306  | 
resources.clean_theories(session, id, clean_theories)  | 
307  | 
}  | 
|
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
308  | 
}  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
309  | 
|
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
310  | 
        Session.Consumer[Session.Commands_Changed](getClass.getName) {
 | 
| 68330 | 311  | 
case changed =>  | 
| 
68770
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
312  | 
            if (changed.nodes.exists(dep_theories_set)) {
 | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
313  | 
val snapshot = session.snapshot()  | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
314  | 
val state = snapshot.state  | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
315  | 
val version = snapshot.version  | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
316  | 
|
| 68957 | 317  | 
val theory_progress =  | 
| 68914 | 318  | 
use_theories_state.change_result(st =>  | 
| 68903 | 319  | 
                  {
 | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
320  | 
val domain =  | 
| 68914 | 321  | 
if (st.nodes_status.is_empty) dep_theories_set  | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
322  | 
else changed.nodes.iterator.filter(dep_theories_set).toSet  | 
| 68899 | 323  | 
|
| 68903 | 324  | 
val (nodes_status_changed, nodes_status1) =  | 
| 
69255
 
800b1ce96fce
more general support for Isabelle/PIDE file formats -- less hardwired Bibtex operations;
 
wenzelm 
parents: 
69035 
diff
changeset
 | 
325  | 
st.nodes_status.update(resources, state, version,  | 
| 68903 | 326  | 
domain = Some(domain), trim = changed.assignment)  | 
| 68899 | 327  | 
|
| 68903 | 328  | 
                    if (nodes_status_delay >= Time.zero && nodes_status_changed) {
 | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
329  | 
delay_nodes_status.invoke  | 
| 68899 | 330  | 
}  | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
331  | 
|
| 68957 | 332  | 
val theory_progress =  | 
| 68905 | 333  | 
                      (for {
 | 
| 
69818
 
60d0ee8f2ddb
more robust: avoid potentially unrelated snapshot for the sake of is_suppressed;
 
wenzelm 
parents: 
69817 
diff
changeset
 | 
334  | 
(name, node_status) <- nodes_status1.present.iterator  | 
| 68959 | 335  | 
if changed.nodes.contains(name) && !st.already_committed.isDefinedAt(name)  | 
| 68962 | 336  | 
p1 = node_status.percentage  | 
337  | 
if p1 > 0 && Some(p1) != st.nodes_status.get(name).map(_.percentage)  | 
|
338  | 
} yield Progress.Theory(name.theory, percentage = Some(p1))).toList  | 
|
| 68903 | 339  | 
|
| 68957 | 340  | 
(theory_progress, st.update(nodes_status1))  | 
| 68903 | 341  | 
})  | 
| 68330 | 342  | 
|
| 68957 | 343  | 
theory_progress.foreach(progress.theory(_))  | 
| 68903 | 344  | 
|
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
345  | 
check_state()  | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
346  | 
|
| 68981 | 347  | 
              if (commit.isDefined && commit_cleanup_delay > Time.zero) {
 | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
348  | 
if (use_theories_state.value.finished_result)  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
349  | 
delay_commit_clean.revoke  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
350  | 
else delay_commit_clean.invoke  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
351  | 
}  | 
| 68330 | 352  | 
}  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
353  | 
}  | 
| 68906 | 354  | 
}  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
355  | 
|
| 67892 | 356  | 
      try {
 | 
357  | 
session.commands_changed += consumer  | 
|
| 
70653
 
f7c5b30fc432
load theories in stages, to reduce ML heap requirements;
 
wenzelm 
parents: 
70649 
diff
changeset
 | 
358  | 
check_state()  | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
359  | 
use_theories_state.guarded_access(_.join_result)  | 
| 
67894
 
fee080c4045f
more robust check_state loop, even without session activity (e.g. idempotent use_theories);
 
wenzelm 
parents: 
67893 
diff
changeset
 | 
360  | 
check_progress.cancel  | 
| 67892 | 361  | 
}  | 
362  | 
      finally {
 | 
|
| 68907 | 363  | 
session.commands_changed -= consumer  | 
| 67892 | 364  | 
resources.unload_theories(session, id, dep_theories)  | 
365  | 
}  | 
|
| 
67884
 
43af581d7d8e
unload_theories after consolidation -- reset node_required;
 
wenzelm 
parents: 
67883 
diff
changeset
 | 
366  | 
|
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
367  | 
Exn.release(use_theories_state.guarded_access(_.join_result))  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
368  | 
}  | 
| 67936 | 369  | 
|
| 67939 | 370  | 
def purge_theories(  | 
| 68915 | 371  | 
theories: List[String],  | 
372  | 
qualifier: String = Sessions.DRAFT,  | 
|
373  | 
master_dir: String = "",  | 
|
374  | 
all: Boolean = false): (List[Document.Node.Name], List[Document.Node.Name]) =  | 
|
375  | 
    {
 | 
|
| 68923 | 376  | 
val nodes =  | 
377  | 
if (all) None  | 
|
378  | 
else Some(theories.map(resources.import_name(qualifier, master_directory(master_dir), _)))  | 
|
| 68915 | 379  | 
resources.purge_theories(session, nodes)  | 
380  | 
}  | 
|
| 67063 | 381  | 
}  | 
382  | 
||
| 
67061
 
2efa25302f34
synchronous session start (similar to isabelle.vscode.Server);
 
wenzelm 
parents: 
67059 
diff
changeset
 | 
383  | 
|
| 67054 | 384  | 
|
| 69012 | 385  | 
/** resources **/  | 
| 68922 | 386  | 
|
| 69012 | 387  | 
object Resources  | 
388  | 
  {
 | 
|
| 69536 | 389  | 
def apply(base_info: Sessions.Base_Info, log: Logger = No_Logger): Resources =  | 
390  | 
new Resources(base_info, log = log)  | 
|
391  | 
||
392  | 
def make(  | 
|
393  | 
options: Options,  | 
|
394  | 
session_name: String,  | 
|
395  | 
session_dirs: List[Path] = Nil,  | 
|
396  | 
include_sessions: List[String] = Nil,  | 
|
397  | 
progress: Progress = No_Progress,  | 
|
398  | 
log: Logger = No_Logger): Resources =  | 
|
399  | 
    {
 | 
|
400  | 
val base_info =  | 
|
401  | 
Sessions.base_info(options, session_name, dirs = session_dirs,  | 
|
402  | 
include_sessions = include_sessions, progress = progress)  | 
|
403  | 
apply(base_info, log = log)  | 
|
404  | 
}  | 
|
405  | 
||
| 69012 | 406  | 
final class Theory private[Headless](  | 
407  | 
val node_name: Document.Node.Name,  | 
|
408  | 
val node_header: Document.Node.Header,  | 
|
409  | 
val text: String,  | 
|
410  | 
val node_required: Boolean)  | 
|
| 68922 | 411  | 
    {
 | 
| 69012 | 412  | 
override def toString: String = node_name.toString  | 
| 68922 | 413  | 
|
| 69012 | 414  | 
def node_perspective: Document.Node.Perspective_Text =  | 
415  | 
Document.Node.Perspective(node_required, Text.Perspective.empty, Document.Node.Overlays.empty)  | 
|
| 68922 | 416  | 
|
| 69012 | 417  | 
def make_edits(text_edits: List[Text.Edit]): List[Document.Edit_Text] =  | 
418  | 
List(node_name -> Document.Node.Deps(node_header),  | 
|
419  | 
node_name -> Document.Node.Edits(text_edits),  | 
|
420  | 
node_name -> node_perspective)  | 
|
| 68922 | 421  | 
|
| 69012 | 422  | 
def node_edits(old: Option[Theory]): List[Document.Edit_Text] =  | 
423  | 
      {
 | 
|
424  | 
val (text_edits, old_required) =  | 
|
425  | 
if (old.isEmpty) (Text.Edit.inserts(0, text), false)  | 
|
426  | 
else (Text.Edit.replace(0, old.get.text, text), old.get.node_required)  | 
|
| 
67887
 
a4d5342898b1
unload_theories: actually observe required state;
 
wenzelm 
parents: 
67885 
diff
changeset
 | 
427  | 
|
| 69012 | 428  | 
if (text_edits.isEmpty && node_required == old_required) Nil  | 
429  | 
else make_edits(text_edits)  | 
|
430  | 
}  | 
|
| 
67887
 
a4d5342898b1
unload_theories: actually observe required state;
 
wenzelm 
parents: 
67885 
diff
changeset
 | 
431  | 
|
| 69012 | 432  | 
def purge_edits: List[Document.Edit_Text] =  | 
433  | 
make_edits(Text.Edit.removes(0, text))  | 
|
| 67936 | 434  | 
|
| 69012 | 435  | 
def required(required: Boolean): Theory =  | 
436  | 
if (required == node_required) this  | 
|
437  | 
else new Theory(node_name, node_header, text, required)  | 
|
| 67936 | 438  | 
}  | 
439  | 
||
| 69012 | 440  | 
sealed case class State(  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
441  | 
blobs: Map[Document.Node.Name, Document.Blob] = Map.empty,  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
442  | 
theories: Map[Document.Node.Name, Theory] = Map.empty,  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
443  | 
required: Multi_Map[Document.Node.Name, UUID.T] = Multi_Map.empty)  | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
444  | 
    {
 | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
445  | 
/* blobs */  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
446  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
447  | 
def doc_blobs: Document.Blobs = Document.Blobs(blobs)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
448  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
449  | 
def update_blobs(names: List[Document.Node.Name]): (Document.Blobs, State) =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
450  | 
      {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
451  | 
val new_blobs =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
452  | 
names.flatMap(name =>  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
453  | 
          {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
454  | 
val bytes = Bytes.read(name.path)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
455  | 
def new_blob: Document.Blob =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
456  | 
            {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
457  | 
val text = bytes.text  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
458  | 
Document.Blob(bytes, text, Symbol.Text_Chunk(text), changed = true)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
459  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
460  | 
            blobs.get(name) match {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
461  | 
case Some(blob) => if (blob.bytes == bytes) None else Some(name -> new_blob)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
462  | 
case None => Some(name -> new_blob)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
463  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
464  | 
})  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
465  | 
val blobs1 = (blobs /: new_blobs)(_ + _)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
466  | 
        val blobs2 = (blobs /: new_blobs)({ case (map, (a, b)) => map + (a -> b.unchanged) })
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
467  | 
(Document.Blobs(blobs1), copy(blobs = blobs2))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
468  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
469  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
470  | 
def blob_edits(name: Document.Node.Name, old_blob: Option[Document.Blob])  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
471  | 
: List[Document.Edit_Text] =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
472  | 
      {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
473  | 
        val blob = blobs.getOrElse(name, error("Missing blob " + quote(name.toString)))
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
474  | 
val text_edits =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
475  | 
          old_blob match {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
476  | 
case None => List(Text.Edit.insert(0, blob.source))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
477  | 
case Some(blob0) => Text.Edit.replace(0, blob0.source, blob.source)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
478  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
479  | 
if (text_edits.isEmpty) Nil  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
480  | 
else List(name -> Document.Node.Blob(blob), name -> Document.Node.Edits(text_edits))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
481  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
482  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
483  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
484  | 
/* theories */  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
485  | 
|
| 
70674
 
29bb1ebb188f
clarified signature: proper Document.Node.Ordering conforming to equality (e.g. required in situations where theory names are ambiguous due to overlapping session directories);
 
wenzelm 
parents: 
70657 
diff
changeset
 | 
486  | 
lazy val theory_graph: Document.Node.Name.Graph[Unit] =  | 
| 
 
29bb1ebb188f
clarified signature: proper Document.Node.Ordering conforming to equality (e.g. required in situations where theory names are ambiguous due to overlapping session directories);
 
wenzelm 
parents: 
70657 
diff
changeset
 | 
487  | 
Document.Node.Name.make_graph(  | 
| 69012 | 488  | 
for ((name, theory) <- theories.toList)  | 
| 70647 | 489  | 
yield ((name, ()), theory.node_header.imports.filter(theories.isDefinedAt(_))))  | 
| 67056 | 490  | 
|
| 69012 | 491  | 
def is_required(name: Document.Node.Name): Boolean = required.isDefinedAt(name)  | 
492  | 
||
| 69458 | 493  | 
def insert_required(id: UUID.T, names: List[Document.Node.Name]): State =  | 
| 69012 | 494  | 
copy(required = (required /: names)(_.insert(_, id)))  | 
495  | 
||
| 69458 | 496  | 
def remove_required(id: UUID.T, names: List[Document.Node.Name]): State =  | 
| 69012 | 497  | 
copy(required = (required /: names)(_.remove(_, id)))  | 
| 68958 | 498  | 
|
| 69012 | 499  | 
def update_theories(update: List[(Document.Node.Name, Theory)]): State =  | 
500  | 
copy(theories =  | 
|
501  | 
          (theories /: update)({ case (thys, (name, thy)) =>
 | 
|
502  | 
            thys.get(name) match {
 | 
|
503  | 
case Some(thy1) if thy1 == thy => thys  | 
|
504  | 
case _ => thys + (name -> thy)  | 
|
505  | 
}  | 
|
506  | 
}))  | 
|
507  | 
||
508  | 
def remove_theories(remove: List[Document.Node.Name]): State =  | 
|
| 67893 | 509  | 
      {
 | 
| 69012 | 510  | 
require(remove.forall(name => !is_required(name)))  | 
511  | 
copy(theories = theories -- remove)  | 
|
512  | 
}  | 
|
513  | 
||
| 70649 | 514  | 
def unload_theories(session: Session, id: UUID.T, theories: List[Document.Node.Name])  | 
| 69458 | 515  | 
: State =  | 
| 69012 | 516  | 
      {
 | 
| 70649 | 517  | 
val st1 = remove_required(id, theories)  | 
| 67893 | 518  | 
val theory_edits =  | 
| 69012 | 519  | 
          for {
 | 
| 70649 | 520  | 
node_name <- theories  | 
| 69012 | 521  | 
theory <- st1.theories.get(node_name)  | 
522  | 
}  | 
|
| 67893 | 523  | 
          yield {
 | 
524  | 
val theory1 = theory.required(st1.is_required(node_name))  | 
|
| 69012 | 525  | 
val edits = theory1.node_edits(Some(theory))  | 
| 67893 | 526  | 
(edits, (node_name, theory1))  | 
527  | 
}  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
528  | 
session.update(doc_blobs, theory_edits.flatMap(_._1))  | 
| 67893 | 529  | 
st1.update_theories(theory_edits.map(_._2))  | 
| 69012 | 530  | 
}  | 
531  | 
||
532  | 
def purge_theories(session: Session, nodes: List[Document.Node.Name])  | 
|
533  | 
: ((List[Document.Node.Name], List[Document.Node.Name]), State) =  | 
|
534  | 
      {
 | 
|
535  | 
val all_nodes = theory_graph.topological_order  | 
|
536  | 
val purge = nodes.filterNot(is_required(_)).toSet  | 
|
537  | 
||
538  | 
val retain = theory_graph.all_preds(all_nodes.filterNot(purge)).toSet  | 
|
539  | 
val (retained, purged) = all_nodes.partition(retain)  | 
|
540  | 
||
541  | 
val purge_edits = purged.flatMap(name => theories(name).purge_edits)  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
542  | 
session.update(doc_blobs, purge_edits)  | 
| 69012 | 543  | 
|
544  | 
((purged, retained), remove_theories(purged))  | 
|
545  | 
}  | 
|
546  | 
}  | 
|
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
547  | 
}  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
548  | 
|
| 69536 | 549  | 
class Resources private[Headless](  | 
550  | 
val session_base_info: Sessions.Base_Info,  | 
|
551  | 
log: Logger = No_Logger)  | 
|
| 
70683
 
8c7706b053c7
find theory files via session structure: much faster Prover IDE startup;
 
wenzelm 
parents: 
70674 
diff
changeset
 | 
552  | 
extends isabelle.Resources(  | 
| 
 
8c7706b053c7
find theory files via session structure: much faster Prover IDE startup;
 
wenzelm 
parents: 
70674 
diff
changeset
 | 
553  | 
session_base_info.sessions_structure, session_base_info.check_base, log = log)  | 
| 
67884
 
43af581d7d8e
unload_theories after consolidation -- reset node_required;
 
wenzelm 
parents: 
67883 
diff
changeset
 | 
554  | 
  {
 | 
| 69012 | 555  | 
resources =>  | 
556  | 
||
| 
69538
 
faf547d2834c
clarified signature, notably cascade of dump_options, deps, resources, session;
 
wenzelm 
parents: 
69536 
diff
changeset
 | 
557  | 
def options: Options = session_base_info.options  | 
| 
 
faf547d2834c
clarified signature, notably cascade of dump_options, deps, resources, session;
 
wenzelm 
parents: 
69536 
diff
changeset
 | 
558  | 
|
| 69536 | 559  | 
|
560  | 
/* session */  | 
|
561  | 
||
562  | 
def start_session(print_mode: List[String] = Nil, progress: Progress = No_Progress): Session =  | 
|
563  | 
    {
 | 
|
564  | 
val session = new Session(session_base_info.session, options, resources)  | 
|
565  | 
||
566  | 
val session_error = Future.promise[String]  | 
|
567  | 
var session_phase: Session.Consumer[Session.Phase] = null  | 
|
568  | 
session_phase =  | 
|
569  | 
        Session.Consumer(getClass.getName) {
 | 
|
570  | 
case Session.Ready =>  | 
|
571  | 
session.phase_changed -= session_phase  | 
|
572  | 
            session_error.fulfill("")
 | 
|
573  | 
case Session.Terminated(result) if !result.ok =>  | 
|
574  | 
session.phase_changed -= session_phase  | 
|
575  | 
            session_error.fulfill("Session start failed: return code " + result.rc)
 | 
|
576  | 
case _ =>  | 
|
577  | 
}  | 
|
578  | 
session.phase_changed += session_phase  | 
|
579  | 
||
580  | 
      progress.echo("Starting session " + session_base_info.session + " ...")
 | 
|
581  | 
Isabelle_Process.start(session, options,  | 
|
582  | 
logic = session_base_info.session, dirs = session_base_info.dirs, modes = print_mode)  | 
|
583  | 
||
584  | 
      session_error.join match {
 | 
|
585  | 
case "" => session  | 
|
586  | 
case msg => session.stop(); error(msg)  | 
|
587  | 
}  | 
|
588  | 
}  | 
|
589  | 
||
590  | 
||
591  | 
/* theories */  | 
|
592  | 
||
| 69012 | 593  | 
private val state = Synchronized(Resources.State())  | 
594  | 
||
595  | 
def load_theories(  | 
|
596  | 
session: Session,  | 
|
| 69458 | 597  | 
id: UUID.T,  | 
| 70649 | 598  | 
theories: List[Document.Node.Name],  | 
599  | 
files: List[Document.Node.Name],  | 
|
| 69920 | 600  | 
unicode_symbols: Boolean,  | 
| 
70625
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
601  | 
share_common_data: Boolean,  | 
| 69012 | 602  | 
progress: Progress)  | 
603  | 
    {
 | 
|
604  | 
val loaded_theories =  | 
|
| 70649 | 605  | 
for (node_name <- theories)  | 
| 69012 | 606  | 
        yield {
 | 
607  | 
val path = node_name.path  | 
|
608  | 
          if (!node_name.is_theory) error("Not a theory file: " + path)
 | 
|
609  | 
||
610  | 
progress.expose_interrupt()  | 
|
| 69920 | 611  | 
val text0 = File.read(path)  | 
612  | 
val text = if (unicode_symbols) Symbol.decode(text0) else text0  | 
|
| 69012 | 613  | 
val node_header = resources.check_thy_reader(node_name, Scan.char_reader(text))  | 
614  | 
new Resources.Theory(node_name, node_header, text, true)  | 
|
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
615  | 
}  | 
| 69012 | 616  | 
|
617  | 
val loaded = loaded_theories.length  | 
|
618  | 
      if (loaded > 1) progress.echo("Loading " + loaded + " theories ...")
 | 
|
619  | 
||
620  | 
state.change(st =>  | 
|
621  | 
        {
 | 
|
| 70649 | 622  | 
val (doc_blobs1, st1) = st.insert_required(id, theories).update_blobs(files)  | 
| 69012 | 623  | 
val theory_edits =  | 
624  | 
for (theory <- loaded_theories)  | 
|
625  | 
            yield {
 | 
|
626  | 
val node_name = theory.node_name  | 
|
627  | 
val theory1 = theory.required(st1.is_required(node_name))  | 
|
628  | 
val edits = theory1.node_edits(st1.theories.get(node_name))  | 
|
629  | 
(edits, (node_name, theory1))  | 
|
630  | 
}  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
631  | 
val file_edits =  | 
| 70649 | 632  | 
            for { node_name <- files if doc_blobs1.changed(node_name) }
 | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
633  | 
yield st1.blob_edits(node_name, st.blobs.get(node_name))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
634  | 
|
| 
70625
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
635  | 
session.update(doc_blobs1, theory_edits.flatMap(_._1) ::: file_edits.flatten,  | 
| 
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
636  | 
share_common_data = share_common_data)  | 
| 69012 | 637  | 
st1.update_theories(theory_edits.map(_._2))  | 
638  | 
})  | 
|
639  | 
}  | 
|
| 67936 | 640  | 
|
| 70649 | 641  | 
def unload_theories(session: Session, id: UUID.T, theories: List[Document.Node.Name])  | 
| 69012 | 642  | 
    {
 | 
| 70649 | 643  | 
state.change(_.unload_theories(session, id, theories))  | 
| 69012 | 644  | 
}  | 
645  | 
||
| 70698 | 646  | 
def clean_theories(session: Session, id: UUID.T, theories: List[Document.Node.Name])  | 
| 69012 | 647  | 
    {
 | 
648  | 
state.change(st =>  | 
|
| 70698 | 649  | 
st.unload_theories(session, id, theories).purge_theories(session, theories)._2  | 
650  | 
)  | 
|
| 69012 | 651  | 
}  | 
652  | 
||
653  | 
def purge_theories(session: Session, nodes: Option[List[Document.Node.Name]])  | 
|
654  | 
: (List[Document.Node.Name], List[Document.Node.Name]) =  | 
|
655  | 
    {
 | 
|
656  | 
state.change_result(st => st.purge_theories(session, nodes getOrElse st.theory_graph.keys))  | 
|
657  | 
}  | 
|
| 67936 | 658  | 
}  | 
| 67054 | 659  | 
}  |