src/Pure/PIDE/protocol.scala
changeset 75393 87ebf5a50283
parent 73838 0e6a5a6cc767
child 75394 42267c650205
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
     5 */
     5 */
     6 
     6 
     7 package isabelle
     7 package isabelle
     8 
     8 
     9 
     9 
    10 object Protocol
    10 object Protocol {
    11 {
       
    12   /* markers for inlined messages */
    11   /* markers for inlined messages */
    13 
    12 
    14   val Loading_Theory_Marker = Protocol_Message.Marker("loading_theory")
    13   val Loading_Theory_Marker = Protocol_Message.Marker("loading_theory")
    15   val Meta_Info_Marker = Protocol_Message.Marker("meta_info")
    14   val Meta_Info_Marker = Protocol_Message.Marker("meta_info")
    16   val Command_Timing_Marker = Protocol_Message.Marker("command_timing")
    15   val Command_Timing_Marker = Protocol_Message.Marker("command_timing")
    21   val Error_Message_Marker = Protocol_Message.Marker("error_message")
    20   val Error_Message_Marker = Protocol_Message.Marker("error_message")
    22 
    21 
    23 
    22 
    24   /* batch build */
    23   /* batch build */
    25 
    24 
    26   object Loading_Theory
    25   object Loading_Theory {
    27   {
       
    28     def unapply(props: Properties.T): Option[(Document.Node.Name, Document_ID.Exec)] =
    26     def unapply(props: Properties.T): Option[(Document.Node.Name, Document_ID.Exec)] =
    29       (props, props, props) match {
    27       (props, props, props) match {
    30         case (Markup.Name(name), Position.File(file), Position.Id(id))
    28         case (Markup.Name(name), Position.File(file), Position.Id(id))
    31         if Path.is_wellformed(file) =>
    29         if Path.is_wellformed(file) =>
    32           val master_dir = Path.explode(file).dir.implode
    30           val master_dir = Path.explode(file).dir.implode
    36   }
    34   }
    37 
    35 
    38 
    36 
    39   /* document editing */
    37   /* document editing */
    40 
    38 
    41   object Commands_Accepted
    39   object Commands_Accepted {
    42   {
       
    43     def unapply(text: String): Option[List[Document_ID.Command]] =
    40     def unapply(text: String): Option[List[Document_ID.Command]] =
    44       try { Some(space_explode(',', text).map(Value.Long.parse)) }
    41       try { Some(space_explode(',', text).map(Value.Long.parse)) }
    45       catch { case ERROR(_) => None }
    42       catch { case ERROR(_) => None }
    46 
    43 
    47     val message: XML.Elem = XML.elem(Markup.STATUS, List(XML.elem(Markup.ACCEPTED)))
    44     val message: XML.Elem = XML.elem(Markup.STATUS, List(XML.elem(Markup.ACCEPTED)))
    48   }
    45   }
    49 
    46 
    50   object Assign_Update
    47   object Assign_Update {
    51   {
    48     def unapply(
    52     def unapply(text: String)
    49       text: String
    53       : Option[(Document_ID.Version, List[String], Document.Assign_Update)] =
    50     ) : Option[(Document_ID.Version, List[String], Document.Assign_Update)] = {
    54     {
       
    55       try {
    51       try {
    56         import XML.Decode._
    52         import XML.Decode._
    57         def decode_upd(body: XML.Body): (Long, List[Long]) =
    53         def decode_upd(body: XML.Body): (Long, List[Long]) =
    58           space_explode(',', string(body)).map(Value.Long.parse) match {
    54           space_explode(',', string(body)).map(Value.Long.parse) match {
    59             case a :: bs => (a, bs)
    55             case a :: bs => (a, bs)
    66         case _: XML.Error => None
    62         case _: XML.Error => None
    67       }
    63       }
    68     }
    64     }
    69   }
    65   }
    70 
    66 
    71   object Removed
    67   object Removed {
    72   {
       
    73     def unapply(text: String): Option[List[Document_ID.Version]] =
    68     def unapply(text: String): Option[List[Document_ID.Version]] =
    74       try {
    69       try {
    75         import XML.Decode._
    70         import XML.Decode._
    76         Some(list(long)(Symbol.decode_yxml(text)))
    71         Some(list(long)(Symbol.decode_yxml(text)))
    77       }
    72       }
    82   }
    77   }
    83 
    78 
    84 
    79 
    85   /* command timing */
    80   /* command timing */
    86 
    81 
    87   object Command_Timing
    82   object Command_Timing {
    88   {
       
    89     def unapply(props: Properties.T): Option[(Properties.T, Document_ID.Generic, isabelle.Timing)] =
    83     def unapply(props: Properties.T): Option[(Properties.T, Document_ID.Generic, isabelle.Timing)] =
    90       props match {
    84       props match {
    91         case Markup.Command_Timing(args) =>
    85         case Markup.Command_Timing(args) =>
    92           (args, args) match {
    86           (args, args) match {
    93             case (Position.Id(id), Markup.Timing_Properties(timing)) => Some((args, id, timing))
    87             case (Position.Id(id), Markup.Timing_Properties(timing)) => Some((args, id, timing))
    98   }
    92   }
    99 
    93 
   100 
    94 
   101   /* theory timing */
    95   /* theory timing */
   102 
    96 
   103   object Theory_Timing
    97   object Theory_Timing {
   104   {
       
   105     def unapply(props: Properties.T): Option[(String, isabelle.Timing)] =
    98     def unapply(props: Properties.T): Option[(String, isabelle.Timing)] =
   106       props match {
    99       props match {
   107         case Markup.Theory_Timing(args) =>
   100         case Markup.Theory_Timing(args) =>
   108           (args, args) match {
   101           (args, args) match {
   109             case (Markup.Name(name), Markup.Timing_Properties(timing)) => Some((name, timing))
   102             case (Markup.Name(name), Markup.Timing_Properties(timing)) => Some((name, timing))
   180   def message_text(elem: XML.Elem,
   173   def message_text(elem: XML.Elem,
   181     heading: Boolean = false,
   174     heading: Boolean = false,
   182     pos: Position.T = Position.none,
   175     pos: Position.T = Position.none,
   183     margin: Double = Pretty.default_margin,
   176     margin: Double = Pretty.default_margin,
   184     breakgain: Double = Pretty.default_breakgain,
   177     breakgain: Double = Pretty.default_breakgain,
   185     metric: Pretty.Metric = Pretty.Default_Metric): String =
   178     metric: Pretty.Metric = Pretty.Default_Metric
   186   {
   179   ): String = {
   187     val text1 =
   180     val text1 =
   188       if (heading) {
   181       if (heading) {
   189         val h =
   182         val h =
   190           if (is_warning(elem) || is_legacy(elem)) "Warning"
   183           if (is_warning(elem) || is_legacy(elem)) "Warning"
   191           else if (is_error(elem)) "Error"
   184           else if (is_error(elem)) "Error"
   210   }
   203   }
   211 
   204 
   212 
   205 
   213   /* ML profiling */
   206   /* ML profiling */
   214 
   207 
   215   object ML_Profiling
   208   object ML_Profiling {
   216   {
       
   217     def unapply(msg: XML.Tree): Option[isabelle.ML_Profiling.Report] =
   209     def unapply(msg: XML.Tree): Option[isabelle.ML_Profiling.Report] =
   218       msg match {
   210       msg match {
   219         case XML.Elem(_, List(tree)) if is_tracing(msg) =>
   211         case XML.Elem(_, List(tree)) if is_tracing(msg) =>
   220           Markup.ML_Profiling.unapply_report(tree)
   212           Markup.ML_Profiling.unapply_report(tree)
   221         case _ => None
   213         case _ => None
   223   }
   215   }
   224 
   216 
   225 
   217 
   226   /* export */
   218   /* export */
   227 
   219 
   228   object Export
   220   object Export {
   229   {
       
   230     sealed case class Args(
   221     sealed case class Args(
   231       id: Option[String] = None,
   222       id: Option[String] = None,
   232       serial: Long = 0L,
   223       serial: Long = 0L,
   233       theory_name: String,
   224       theory_name: String,
   234       name: String,
   225       name: String,
   235       executable: Boolean = false,
   226       executable: Boolean = false,
   236       compress: Boolean = true,
   227       compress: Boolean = true,
   237       strict: Boolean = true)
   228       strict: Boolean = true
   238     {
   229     ) {
   239       def compound_name: String = isabelle.Export.compound_name(theory_name, name)
   230       def compound_name: String = isabelle.Export.compound_name(theory_name, name)
   240     }
   231     }
   241 
   232 
   242     def unapply(props: Properties.T): Option[Args] =
   233     def unapply(props: Properties.T): Option[Args] =
   243       props match {
   234       props match {
   257   }
   248   }
   258 
   249 
   259 
   250 
   260   /* breakpoints */
   251   /* breakpoints */
   261 
   252 
   262   object ML_Breakpoint
   253   object ML_Breakpoint {
   263   {
       
   264     def unapply(tree: XML.Tree): Option[Long] =
   254     def unapply(tree: XML.Tree): Option[Long] =
   265     tree match {
   255     tree match {
   266       case XML.Elem(Markup(Markup.ML_BREAKPOINT, Markup.Serial(breakpoint)), _) => Some(breakpoint)
   256       case XML.Elem(Markup(Markup.ML_BREAKPOINT, Markup.Serial(breakpoint)), _) => Some(breakpoint)
   267       case _ => None
   257       case _ => None
   268     }
   258     }
   269   }
   259   }
   270 
   260 
   271 
   261 
   272   /* dialogs */
   262   /* dialogs */
   273 
   263 
   274   object Dialog_Args
   264   object Dialog_Args {
   275   {
       
   276     def unapply(props: Properties.T): Option[(Document_ID.Generic, Long, String)] =
   265     def unapply(props: Properties.T): Option[(Document_ID.Generic, Long, String)] =
   277       (props, props, props) match {
   266       (props, props, props) match {
   278         case (Position.Id(id), Markup.Serial(serial), Markup.Result(result)) =>
   267         case (Position.Id(id), Markup.Serial(serial), Markup.Result(result)) =>
   279           Some((id, serial, result))
   268           Some((id, serial, result))
   280         case _ => None
   269         case _ => None
   281       }
   270       }
   282   }
   271   }
   283 
   272 
   284   object Dialog
   273   object Dialog {
   285   {
       
   286     def unapply(tree: XML.Tree): Option[(Document_ID.Generic, Long, String)] =
   274     def unapply(tree: XML.Tree): Option[(Document_ID.Generic, Long, String)] =
   287       tree match {
   275       tree match {
   288         case XML.Elem(Markup(Markup.DIALOG, Dialog_Args(id, serial, result)), _) =>
   276         case XML.Elem(Markup(Markup.DIALOG, Dialog_Args(id, serial, result)), _) =>
   289           Some((id, serial, result))
   277           Some((id, serial, result))
   290         case _ => None
   278         case _ => None
   291       }
   279       }
   292   }
   280   }
   293 
   281 
   294   object Dialog_Result
   282   object Dialog_Result {
   295   {
   283     def apply(id: Document_ID.Generic, serial: Long, result: String): XML.Elem = {
   296     def apply(id: Document_ID.Generic, serial: Long, result: String): XML.Elem =
       
   297     {
       
   298       val props = Position.Id(id) ::: Markup.Serial(serial)
   284       val props = Position.Id(id) ::: Markup.Serial(serial)
   299       XML.Elem(Markup(Markup.RESULT, props), List(XML.Text(result)))
   285       XML.Elem(Markup(Markup.RESULT, props), List(XML.Text(result)))
   300     }
   286     }
   301 
   287 
   302     def unapply(tree: XML.Tree): Option[String] =
   288     def unapply(tree: XML.Tree): Option[String] =
   306       }
   292       }
   307   }
   293   }
   308 }
   294 }
   309 
   295 
   310 
   296 
   311 trait Protocol
   297 trait Protocol {
   312 {
       
   313   /* protocol commands */
   298   /* protocol commands */
   314 
   299 
   315   def protocol_command_raw(name: String, args: List[Bytes]): Unit
   300   def protocol_command_raw(name: String, args: List[Bytes]): Unit
   316   def protocol_command_args(name: String, args: List[String]): Unit
   301   def protocol_command_args(name: String, args: List[String]): Unit
   317   def protocol_command(name: String, args: String*): Unit
   302   def protocol_command(name: String, args: String*): Unit
   332   /* interned items */
   317   /* interned items */
   333 
   318 
   334   def define_blob(digest: SHA1.Digest, bytes: Bytes): Unit =
   319   def define_blob(digest: SHA1.Digest, bytes: Bytes): Unit =
   335     protocol_command_raw("Document.define_blob", List(Bytes(digest.toString), bytes))
   320     protocol_command_raw("Document.define_blob", List(Bytes(digest.toString), bytes))
   336 
   321 
   337   private def encode_command(resources: Resources, command: Command)
   322   private def encode_command(
   338     : (String, String, String, String, String, List[String]) =
   323     resources: Resources,
   339   {
   324     command: Command
       
   325   ) : (String, String, String, String, String, List[String]) = {
   340     import XML.Encode._
   326     import XML.Encode._
   341 
   327 
   342     val parents = command.theory_parents(resources).map(name => File.standard_url(name.node))
   328     val parents = command.theory_parents(resources).map(name => File.standard_url(name.node))
   343     val parents_yxml = Symbol.encode_yxml(list(string)(parents))
   329     val parents_yxml = Symbol.encode_yxml(list(string)(parents))
   344 
   330 
   345     val blobs_yxml =
   331     val blobs_yxml = {
   346     {
       
   347       val encode_blob: T[Exn.Result[Command.Blob]] =
   332       val encode_blob: T[Exn.Result[Command.Blob]] =
   348         variant(List(
   333         variant(List(
   349           { case Exn.Res(Command.Blob(a, b, c)) =>
   334           { case Exn.Res(Command.Blob(a, b, c)) =>
   350               (Nil, triple(string, string, option(string))(
   335               (Nil, triple(string, string, option(string))(
   351                 (a.node, b.implode, c.map(p => p._1.toString)))) },
   336                 (a.node, b.implode, c.map(p => p._1.toString)))) },
   352           { case Exn.Exn(e) => (Nil, string(Exn.message(e))) }))
   337           { case Exn.Exn(e) => (Nil, string(Exn.message(e))) }))
   353 
   338 
   354       Symbol.encode_yxml(pair(list(encode_blob), int)(command.blobs, command.blobs_index))
   339       Symbol.encode_yxml(pair(list(encode_blob), int)(command.blobs, command.blobs_index))
   355     }
   340     }
   356 
   341 
   357     val toks_yxml =
   342     val toks_yxml = {
   358     {
       
   359       val encode_tok: T[Token] = (tok => pair(int, int)((tok.kind.id, Symbol.length(tok.source))))
   343       val encode_tok: T[Token] = (tok => pair(int, int)((tok.kind.id, Symbol.length(tok.source))))
   360       Symbol.encode_yxml(list(encode_tok)(command.span.content))
   344       Symbol.encode_yxml(list(encode_tok)(command.span.content))
   361     }
   345     }
   362     val toks_sources = command.span.content.map(tok => Symbol.encode(tok.source))
   346     val toks_sources = command.span.content.map(tok => Symbol.encode(tok.source))
   363 
   347 
   364     (Document_ID(command.id), Symbol.encode(command.span.name), parents_yxml,
   348     (Document_ID(command.id), Symbol.encode(command.span.name), parents_yxml,
   365       blobs_yxml, toks_yxml, toks_sources)
   349       blobs_yxml, toks_yxml, toks_sources)
   366   }
   350   }
   367 
   351 
   368   def define_command(resources: Resources, command: Command): Unit =
   352   def define_command(resources: Resources, command: Command): Unit = {
   369   {
       
   370     val (command_id, name, parents_yxml, blobs_yxml, toks_yxml, toks_sources) =
   353     val (command_id, name, parents_yxml, blobs_yxml, toks_yxml, toks_sources) =
   371       encode_command(resources, command)
   354       encode_command(resources, command)
   372     protocol_command_args(
   355     protocol_command_args(
   373       "Document.define_command", command_id :: name :: parents_yxml :: blobs_yxml ::
   356       "Document.define_command", command_id :: name :: parents_yxml :: blobs_yxml ::
   374         toks_yxml :: toks_sources)
   357         toks_yxml :: toks_sources)
   375   }
   358   }
   376 
   359 
   377   def define_commands(resources: Resources, commands: List[Command]): Unit =
   360   def define_commands(resources: Resources, commands: List[Command]): Unit = {
   378   {
       
   379     protocol_command_args("Document.define_commands",
   361     protocol_command_args("Document.define_commands",
   380       commands.map(command =>
   362       commands.map(command => {
   381       {
       
   382         import XML.Encode._
   363         import XML.Encode._
   383         val (command_id, name, parents_yxml, blobs_yxml, toks_yxml, toks_sources) =
   364         val (command_id, name, parents_yxml, blobs_yxml, toks_yxml, toks_sources) =
   384           encode_command(resources, command)
   365           encode_command(resources, command)
   385         val body =
   366         val body =
   386           pair(string, pair(string, pair(string, pair(string, pair(string, list(string))))))(
   367           pair(string, pair(string, pair(string, pair(string, pair(string, list(string))))))(
   387             command_id, (name, (parents_yxml, (blobs_yxml, (toks_yxml, toks_sources)))))
   368             command_id, (name, (parents_yxml, (blobs_yxml, (toks_yxml, toks_sources)))))
   388         YXML.string_of_body(body)
   369         YXML.string_of_body(body)
   389       }))
   370       }))
   390   }
   371   }
   391 
   372 
   392   def define_commands_bulk(resources: Resources, commands: List[Command]): Unit =
   373   def define_commands_bulk(resources: Resources, commands: List[Command]): Unit = {
   393   {
       
   394     val (irregular, regular) = commands.partition(command => YXML.detect(command.source))
   374     val (irregular, regular) = commands.partition(command => YXML.detect(command.source))
   395     irregular.foreach(define_command(resources, _))
   375     irregular.foreach(define_command(resources, _))
   396     regular match {
   376     regular match {
   397       case Nil =>
   377       case Nil =>
   398       case List(command) => define_command(resources, command)
   378       case List(command) => define_command(resources, command)
   410     protocol_command("Document.cancel_exec", Document_ID(id))
   390     protocol_command("Document.cancel_exec", Document_ID(id))
   411 
   391 
   412 
   392 
   413   /* document versions */
   393   /* document versions */
   414 
   394 
   415   def update(old_id: Document_ID.Version, new_id: Document_ID.Version,
   395   def update(
   416     edits: List[Document.Edit_Command], consolidate: List[Document.Node.Name]): Unit =
   396     old_id: Document_ID.Version,
   417   {
   397     new_id: Document_ID.Version,
   418     val consolidate_yxml =
   398     edits: List[Document.Edit_Command],
   419     {
   399     consolidate: List[Document.Node.Name]
       
   400   ): Unit = {
       
   401     val consolidate_yxml = {
   420       import XML.Encode._
   402       import XML.Encode._
   421       Symbol.encode_yxml(list(string)(consolidate.map(_.node)))
   403       Symbol.encode_yxml(list(string)(consolidate.map(_.node)))
   422     }
   404     }
   423     val edits_yxml =
   405     val edits_yxml = {
   424     {
       
   425       import XML.Encode._
   406       import XML.Encode._
   426       def id: T[Command] = (cmd => long(cmd.id))
   407       def id: T[Command] = (cmd => long(cmd.id))
   427       def encode_edit(name: Document.Node.Name)
   408       def encode_edit(name: Document.Node.Name)
   428           : T[Document.Node.Edit[Command.Edit, Command.Perspective]] =
   409           : T[Document.Node.Edit[Command.Edit, Command.Perspective]] =
   429         variant(List(
   410         variant(List(
   444     }
   425     }
   445     protocol_command_args("Document.update",
   426     protocol_command_args("Document.update",
   446       Document_ID(old_id) :: Document_ID(new_id) :: consolidate_yxml :: edits_yxml)
   427       Document_ID(old_id) :: Document_ID(new_id) :: consolidate_yxml :: edits_yxml)
   447   }
   428   }
   448 
   429 
   449   def remove_versions(versions: List[Document.Version]): Unit =
   430   def remove_versions(versions: List[Document.Version]): Unit = {
   450   {
       
   451     val versions_yxml =
   431     val versions_yxml =
   452     { import XML.Encode._
   432     { import XML.Encode._
   453       Symbol.encode_yxml(list(long)(versions.map(_.id))) }
   433       Symbol.encode_yxml(list(long)(versions.map(_.id))) }
   454     protocol_command("Document.remove_versions", versions_yxml)
   434     protocol_command("Document.remove_versions", versions_yxml)
   455   }
   435   }