src/Pure/Build/export_theory.scala
changeset 79502 c7a98469c0e7
parent 78604 9ccd5e8737cb
child 80313 a828e47c867c
equal deleted inserted replaced
79501:bce98b5dfec6 79502:c7a98469c0e7
       
     1 /*  Title:      Pure/Build/export_theory.scala
       
     2     Author:     Makarius
       
     3 
       
     4 Export foundational theory content.
       
     5 */
       
     6 
       
     7 package isabelle
       
     8 
       
     9 
       
    10 import scala.collection.immutable.SortedMap
       
    11 
       
    12 
       
    13 object Export_Theory {
       
    14   /** session content **/
       
    15 
       
    16   sealed case class Session(name: String, theory_graph: Graph[String, Option[Theory]]) {
       
    17     override def toString: String = name
       
    18 
       
    19     def theory(theory_name: String): Option[Theory] =
       
    20       if (theory_graph.defined(theory_name)) theory_graph.get_node(theory_name)
       
    21       else None
       
    22 
       
    23     def theories: List[Theory] =
       
    24       theory_graph.topological_order.flatMap(theory)
       
    25   }
       
    26 
       
    27   def read_session(
       
    28     session_context: Export.Session_Context,
       
    29     session_stack: Boolean = false,
       
    30     progress: Progress = new Progress
       
    31   ): Session = {
       
    32     val thys =
       
    33       for (theory <- theory_names(session_context, session_stack = session_stack)) yield {
       
    34         progress.echo("Reading theory " + theory)
       
    35         read_theory(session_context.theory(theory))
       
    36       }
       
    37 
       
    38     val graph0 =
       
    39       thys.foldLeft(Graph.string[Option[Theory]]) {
       
    40         case (g, thy) => g.default_node(thy.name, Some(thy))
       
    41       }
       
    42     val graph1 =
       
    43       thys.foldLeft(graph0) {
       
    44         case (g0, thy) =>
       
    45           thy.parents.foldLeft(g0) {
       
    46             case (g1, parent) => g1.default_node(parent, None).add_edge_acyclic(parent, thy.name)
       
    47           }
       
    48       }
       
    49 
       
    50     Session(session_context.session_name, graph1)
       
    51   }
       
    52 
       
    53 
       
    54 
       
    55   /** theory content **/
       
    56 
       
    57   sealed case class Theory(name: String, parents: List[String],
       
    58     types: List[Entity[Type]],
       
    59     consts: List[Entity[Const]],
       
    60     axioms: List[Entity[Axiom]],
       
    61     thms: List[Entity[Thm]],
       
    62     classes: List[Entity[Class]],
       
    63     locales: List[Entity[Locale]],
       
    64     locale_dependencies: List[Entity[Locale_Dependency]],
       
    65     classrel: List[Classrel],
       
    66     arities: List[Arity],
       
    67     constdefs: List[Constdef],
       
    68     typedefs: List[Typedef],
       
    69     datatypes: List[Datatype],
       
    70     spec_rules: List[Spec_Rule],
       
    71     others: Map[String, List[Entity[Other]]]
       
    72   ) {
       
    73     override def toString: String = name
       
    74 
       
    75     def entity_iterator: Iterator[Entity0] =
       
    76       types.iterator.map(_.no_content) ++
       
    77       consts.iterator.map(_.no_content) ++
       
    78       axioms.iterator.map(_.no_content) ++
       
    79       thms.iterator.map(_.no_content) ++
       
    80       classes.iterator.map(_.no_content) ++
       
    81       locales.iterator.map(_.no_content) ++
       
    82       locale_dependencies.iterator.map(_.no_content) ++
       
    83       (for { (_, xs) <- others; x <- xs.iterator } yield x.no_content)
       
    84 
       
    85     def cache(cache: Term.Cache): Theory =
       
    86       Theory(cache.string(name),
       
    87         parents.map(cache.string),
       
    88         types.map(_.cache(cache)),
       
    89         consts.map(_.cache(cache)),
       
    90         axioms.map(_.cache(cache)),
       
    91         thms.map(_.cache(cache)),
       
    92         classes.map(_.cache(cache)),
       
    93         locales.map(_.cache(cache)),
       
    94         locale_dependencies.map(_.cache(cache)),
       
    95         classrel.map(_.cache(cache)),
       
    96         arities.map(_.cache(cache)),
       
    97         constdefs.map(_.cache(cache)),
       
    98         typedefs.map(_.cache(cache)),
       
    99         datatypes.map(_.cache(cache)),
       
   100         spec_rules.map(_.cache(cache)),
       
   101         (for ((k, xs) <- others.iterator) yield cache.string(k) -> xs.map(_.cache(cache))).toMap)
       
   102   }
       
   103 
       
   104   def read_theory_parents(theory_context: Export.Theory_Context): Option[List[String]] =
       
   105     theory_context.get(Export.THEORY_PREFIX + "parents")
       
   106       .map(entry => Library.trim_split_lines(entry.text))
       
   107 
       
   108   def theory_names(
       
   109     session_context: Export.Session_Context,
       
   110     session_stack: Boolean = false
       
   111   ): List[String] = {
       
   112     val session = if (session_stack) "" else session_context.session_name
       
   113     for {
       
   114       theory <- session_context.theory_names(session = session)
       
   115       if read_theory_parents(session_context.theory(theory)).isDefined
       
   116     } yield theory
       
   117   }
       
   118 
       
   119   def no_theory: Theory =
       
   120     Theory("", Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Map.empty)
       
   121 
       
   122   def read_theory(
       
   123     theory_context: Export.Theory_Context,
       
   124     permissive: Boolean = false
       
   125   ): Theory = {
       
   126     val cache = theory_context.cache
       
   127     val session_name = theory_context.session_context.session_name
       
   128     val theory_name = theory_context.theory
       
   129     read_theory_parents(theory_context) match {
       
   130       case None if permissive => no_theory
       
   131       case None =>
       
   132         error("Missing theory export in session " + quote(session_name) + ": " + quote(theory_name))
       
   133       case Some(parents) =>
       
   134         val theory =
       
   135           Theory(theory_name, parents,
       
   136             read_types(theory_context),
       
   137             read_consts(theory_context),
       
   138             read_axioms(theory_context),
       
   139             read_thms(theory_context),
       
   140             read_classes(theory_context),
       
   141             read_locales(theory_context),
       
   142             read_locale_dependencies(theory_context),
       
   143             read_classrel(theory_context),
       
   144             read_arities(theory_context),
       
   145             read_constdefs(theory_context),
       
   146             read_typedefs(theory_context),
       
   147             read_datatypes(theory_context),
       
   148             read_spec_rules(theory_context),
       
   149             read_others(theory_context))
       
   150         if (cache.no_cache) theory else theory.cache(cache)
       
   151     }
       
   152   }
       
   153 
       
   154 
       
   155   /* entities */
       
   156 
       
   157   object Kind {
       
   158     val TYPE = "type"
       
   159     val CONST = "const"
       
   160     val THM = "thm"
       
   161     val PROOF = "proof"
       
   162     val LOCALE_DEPENDENCY = "locale_dependency"
       
   163     val DOCUMENT_HEADING = "document_heading"
       
   164     val DOCUMENT_TEXT = "document_text"
       
   165     val PROOF_TEXT = "proof_text"
       
   166   }
       
   167 
       
   168   def export_kind(kind: String): String =
       
   169     if (kind == Markup.TYPE_NAME) Kind.TYPE
       
   170     else if (kind == Markup.CONSTANT) Kind.CONST
       
   171     else kind
       
   172 
       
   173   def export_kind_name(kind: String, name: String): String =
       
   174     name + "|" + export_kind(kind)
       
   175 
       
   176   abstract class Content[T] {
       
   177     def cache(cache: Term.Cache): T
       
   178   }
       
   179   sealed case class No_Content() extends Content[No_Content] {
       
   180     def cache(cache: Term.Cache): No_Content = this
       
   181   }
       
   182   sealed case class Entity[A <: Content[A]](
       
   183     kind: String,
       
   184     name: String,
       
   185     xname: String,
       
   186     pos: Position.T,
       
   187     id: Option[Long],
       
   188     serial: Long,
       
   189     content: Option[A]
       
   190   ) {
       
   191     val kname: String = export_kind_name(kind, name)
       
   192     val range: Symbol.Range = Position.Range.unapply(pos).getOrElse(Text.Range.offside)
       
   193     val file: String = Position.File.unapply(pos).getOrElse("")
       
   194 
       
   195     def export_kind: String = Export_Theory.export_kind(kind)
       
   196     override def toString: String = export_kind + " " + quote(name)
       
   197 
       
   198     def the_content: A =
       
   199       if (content.isDefined) content.get else error("No content for " + toString)
       
   200 
       
   201     def no_content: Entity0 = copy(content = None)
       
   202 
       
   203     def cache(cache: Term.Cache): Entity[A] =
       
   204       Entity(
       
   205         cache.string(kind),
       
   206         cache.string(name),
       
   207         cache.string(xname),
       
   208         cache.position(pos),
       
   209         id,
       
   210         serial,
       
   211         content.map(_.cache(cache)))
       
   212   }
       
   213   type Entity0 = Entity[No_Content]
       
   214 
       
   215   def read_entities[A <: Content[A]](
       
   216     theory_context: Export.Theory_Context,
       
   217     export_name: String,
       
   218     kind: String,
       
   219     decode: XML.Decode.T[A]
       
   220   ): List[Entity[A]] = {
       
   221     def decode_entity(tree: XML.Tree): Entity[A] = {
       
   222       def err(): Nothing = throw new XML.XML_Body(List(tree))
       
   223 
       
   224       tree match {
       
   225         case XML.Elem(Markup(Markup.ENTITY, props), body) =>
       
   226           val name = Markup.Name.unapply(props) getOrElse err()
       
   227           val xname = Markup.XName.unapply(props) getOrElse err()
       
   228           val pos = props.filter(p => Markup.position_property(p) && p._1 != Markup.ID)
       
   229           val id = Position.Id.unapply(props)
       
   230           val serial = Markup.Serial.unapply(props) getOrElse err()
       
   231           val content = if (body.isEmpty) None else Some(decode(body))
       
   232           Entity(kind, name, xname, pos, id, serial, content)
       
   233         case _ => err()
       
   234       }
       
   235     }
       
   236     theory_context.yxml(export_name).map(decode_entity)
       
   237   }
       
   238 
       
   239 
       
   240   /* approximative syntax */
       
   241 
       
   242   enum Assoc { case NO_ASSOC, LEFT_ASSOC, RIGHT_ASSOC }
       
   243 
       
   244   sealed abstract class Syntax
       
   245   case object No_Syntax extends Syntax
       
   246   case class Prefix(delim: String) extends Syntax
       
   247   case class Infix(assoc: Assoc, delim: String, pri: Int) extends Syntax
       
   248 
       
   249   def decode_syntax: XML.Decode.T[Syntax] =
       
   250     XML.Decode.variant(List(
       
   251       { case (Nil, Nil) => No_Syntax },
       
   252       { case (List(delim), Nil) => Prefix(delim) },
       
   253       { case (Nil, body) =>
       
   254           import XML.Decode._
       
   255           val (ass, delim, pri) = triple(int, string, int)(body)
       
   256           Infix(Assoc.fromOrdinal(ass), delim, pri) }))
       
   257 
       
   258 
       
   259   /* types */
       
   260 
       
   261   sealed case class Type(syntax: Syntax, args: List[String], abbrev: Option[Term.Typ])
       
   262   extends Content[Type] {
       
   263     override def cache(cache: Term.Cache): Type =
       
   264       Type(
       
   265         syntax,
       
   266         args.map(cache.string),
       
   267         abbrev.map(cache.typ))
       
   268   }
       
   269 
       
   270   def read_types(theory_context: Export.Theory_Context): List[Entity[Type]] =
       
   271     read_entities(theory_context, Export.THEORY_PREFIX + "types", Markup.TYPE_NAME,
       
   272       { body =>
       
   273         import XML.Decode._
       
   274         val (syntax, args, abbrev) =
       
   275           triple(decode_syntax, list(string), option(Term_XML.Decode.typ))(body)
       
   276         Type(syntax, args, abbrev)
       
   277       })
       
   278 
       
   279 
       
   280   /* consts */
       
   281 
       
   282   sealed case class Const(
       
   283     syntax: Syntax,
       
   284     typargs: List[String],
       
   285     typ: Term.Typ,
       
   286     abbrev: Option[Term.Term],
       
   287     propositional: Boolean
       
   288   ) extends Content[Const] {
       
   289     override def cache(cache: Term.Cache): Const =
       
   290       Const(
       
   291         syntax,
       
   292         typargs.map(cache.string),
       
   293         cache.typ(typ),
       
   294         abbrev.map(cache.term),
       
   295         propositional)
       
   296   }
       
   297 
       
   298   def read_consts(theory_context: Export.Theory_Context): List[Entity[Const]] =
       
   299     read_entities(theory_context, Export.THEORY_PREFIX + "consts", Markup.CONSTANT,
       
   300       { body =>
       
   301         import XML.Decode._
       
   302         val (syntax, (typargs, (typ, (abbrev, propositional)))) =
       
   303           pair(decode_syntax,
       
   304             pair(list(string),
       
   305               pair(Term_XML.Decode.typ,
       
   306                 pair(option(Term_XML.Decode.term), bool))))(body)
       
   307         Const(syntax, typargs, typ, abbrev, propositional)
       
   308       })
       
   309 
       
   310 
       
   311   /* axioms */
       
   312 
       
   313   sealed case class Prop(
       
   314     typargs: List[(String, Term.Sort)],
       
   315     args: List[(String, Term.Typ)],
       
   316     term: Term.Term
       
   317   ) extends Content[Prop] {
       
   318     override def cache(cache: Term.Cache): Prop =
       
   319       Prop(
       
   320         typargs.map({ case (name, sort) => (cache.string(name), cache.sort(sort)) }),
       
   321         args.map({ case (name, typ) => (cache.string(name), cache.typ(typ)) }),
       
   322         cache.term(term))
       
   323   }
       
   324 
       
   325   def decode_prop(body: XML.Body): Prop = {
       
   326     val (typargs, args, t) = {
       
   327       import XML.Decode._
       
   328       import Term_XML.Decode._
       
   329       triple(list(pair(string, sort)), list(pair(string, typ)), term)(body)
       
   330     }
       
   331     Prop(typargs, args, t)
       
   332   }
       
   333 
       
   334   sealed case class Axiom(prop: Prop) extends Content[Axiom] {
       
   335     override def cache(cache: Term.Cache): Axiom = Axiom(prop.cache(cache))
       
   336   }
       
   337 
       
   338   def read_axioms(theory_context: Export.Theory_Context): List[Entity[Axiom]] =
       
   339     read_entities(theory_context, Export.THEORY_PREFIX + "axioms", Markup.AXIOM,
       
   340       body => Axiom(decode_prop(body)))
       
   341 
       
   342 
       
   343   /* theorems */
       
   344 
       
   345   sealed case class Thm_Id(serial: Long, theory_name: String)
       
   346 
       
   347   sealed case class Thm(
       
   348     prop: Prop,
       
   349     deps: List[String],
       
   350     proof: Term.Proof)
       
   351   extends Content[Thm] {
       
   352     override def cache(cache: Term.Cache): Thm =
       
   353       Thm(
       
   354         prop.cache(cache),
       
   355         deps.map(cache.string),
       
   356         cache.proof(proof))
       
   357   }
       
   358 
       
   359   def read_thms(theory_context: Export.Theory_Context): List[Entity[Thm]] =
       
   360     read_entities(theory_context, Export.THEORY_PREFIX + "thms", Kind.THM,
       
   361       { body =>
       
   362         import XML.Decode._
       
   363         import Term_XML.Decode._
       
   364         val (prop, deps, prf) = triple(decode_prop, list(string), proof)(body)
       
   365         Thm(prop, deps, prf)
       
   366       })
       
   367 
       
   368   sealed case class Proof(
       
   369     typargs: List[(String, Term.Sort)],
       
   370     args: List[(String, Term.Typ)],
       
   371     term: Term.Term,
       
   372     proof: Term.Proof
       
   373   ) {
       
   374     def prop: Prop = Prop(typargs, args, term)
       
   375 
       
   376     def cache(cache: Term.Cache): Proof =
       
   377       Proof(
       
   378         typargs.map({ case (name, sort) => (cache.string(name), cache.sort(sort)) }),
       
   379         args.map({ case (name, typ) => (cache.string(name), cache.typ(typ)) }),
       
   380         cache.term(term),
       
   381         cache.proof(proof))
       
   382   }
       
   383 
       
   384   def read_proof(
       
   385     session_context: Export.Session_Context,
       
   386     id: Thm_Id,
       
   387     other_cache: Option[Term.Cache] = None
       
   388   ): Option[Proof] = {
       
   389     val theory_context = session_context.theory(id.theory_name, other_cache = other_cache)
       
   390     val cache = theory_context.cache
       
   391 
       
   392     for { entry <- theory_context.get(Export.PROOFS_PREFIX + id.serial) }
       
   393     yield {
       
   394       val body = entry.yxml
       
   395       val (typargs, (args, (prop_body, proof_body))) = {
       
   396         import XML.Decode._
       
   397         import Term_XML.Decode._
       
   398         pair(list(pair(string, sort)), pair(list(pair(string, typ)), pair(x => x, x => x)))(body)
       
   399       }
       
   400       val env = args.toMap
       
   401       val prop = Term_XML.Decode.term_env(env)(prop_body)
       
   402       val proof = Term_XML.Decode.proof_env(env)(proof_body)
       
   403 
       
   404       val result = Proof(typargs, args, prop, proof)
       
   405       if (cache.no_cache) result else result.cache(cache)
       
   406     }
       
   407   }
       
   408 
       
   409   def read_proof_boxes(
       
   410     session_context: Export.Session_Context,
       
   411     proof: Term.Proof,
       
   412     suppress: Thm_Id => Boolean = _ => false,
       
   413     other_cache: Option[Term.Cache] = None
       
   414   ): List[(Thm_Id, Proof)] = {
       
   415     var seen = Set.empty[Long]
       
   416     var result = SortedMap.empty[Long, (Thm_Id, Proof)]
       
   417 
       
   418     def boxes(context: Option[(Long, Term.Proof)], prf: Term.Proof): Unit = {
       
   419       prf match {
       
   420         case Term.Abst(_, _, p) => boxes(context, p)
       
   421         case Term.AbsP(_, _, p) => boxes(context, p)
       
   422         case Term.Appt(p, _) => boxes(context, p)
       
   423         case Term.AppP(p, q) => boxes(context, p); boxes(context, q)
       
   424         case thm: Term.PThm if !seen(thm.serial) =>
       
   425           seen += thm.serial
       
   426           val id = Thm_Id(thm.serial, thm.theory_name)
       
   427           if (!suppress(id)) {
       
   428             Export_Theory.read_proof(session_context, id, other_cache = other_cache) match {
       
   429               case Some(p) =>
       
   430                 result += (thm.serial -> (id -> p))
       
   431                 boxes(Some((thm.serial, p.proof)), p.proof)
       
   432               case None =>
       
   433                 error("Missing proof " + thm.serial + " (theory " + quote (thm.theory_name) + ")" +
       
   434                   (context match {
       
   435                     case None => ""
       
   436                     case Some((i, p)) => " in proof " + i + ":\n" + p
       
   437                   }))
       
   438             }
       
   439           }
       
   440         case _ =>
       
   441       }
       
   442     }
       
   443 
       
   444     boxes(None, proof)
       
   445     result.iterator.map(_._2).toList
       
   446   }
       
   447 
       
   448 
       
   449   /* type classes */
       
   450 
       
   451   sealed case class Class(params: List[(String, Term.Typ)], axioms: List[Prop])
       
   452   extends Content[Class] {
       
   453     override def cache(cache: Term.Cache): Class =
       
   454       Class(
       
   455         params.map({ case (name, typ) => (cache.string(name), cache.typ(typ)) }),
       
   456         axioms.map(_.cache(cache)))
       
   457   }
       
   458 
       
   459   def read_classes(theory_context: Export.Theory_Context): List[Entity[Class]] =
       
   460     read_entities(theory_context, Export.THEORY_PREFIX + "classes", Markup.CLASS,
       
   461       { body =>
       
   462         import XML.Decode._
       
   463         import Term_XML.Decode._
       
   464         val (params, axioms) = pair(list(pair(string, typ)), list(decode_prop))(body)
       
   465         Class(params, axioms)
       
   466       })
       
   467 
       
   468 
       
   469   /* locales */
       
   470 
       
   471   sealed case class Locale(
       
   472     typargs: List[(String, Term.Sort)],
       
   473     args: List[((String, Term.Typ), Syntax)],
       
   474     axioms: List[Prop]
       
   475   ) extends Content[Locale] {
       
   476     override def cache(cache: Term.Cache): Locale =
       
   477       Locale(
       
   478         typargs.map({ case (name, sort) => (cache.string(name), cache.sort(sort)) }),
       
   479         args.map({ case ((name, typ), syntax) => ((cache.string(name), cache.typ(typ)), syntax) }),
       
   480         axioms.map(_.cache(cache)))
       
   481   }
       
   482 
       
   483   def read_locales(theory_context: Export.Theory_Context): List[Entity[Locale]] =
       
   484     read_entities(theory_context, Export.THEORY_PREFIX + "locales", Markup.LOCALE,
       
   485       { body =>
       
   486         import XML.Decode._
       
   487         import Term_XML.Decode._
       
   488         val (typargs, args, axioms) =
       
   489           triple(list(pair(string, sort)), list(pair(pair(string, typ), decode_syntax)),
       
   490             list(decode_prop))(body)
       
   491         Locale(typargs, args, axioms)
       
   492       })
       
   493 
       
   494 
       
   495   /* locale dependencies */
       
   496 
       
   497   sealed case class Locale_Dependency(
       
   498     source: String,
       
   499     target: String,
       
   500     prefix: List[(String, Boolean)],
       
   501     subst_types: List[((String, Term.Sort), Term.Typ)],
       
   502     subst_terms: List[((String, Term.Typ), Term.Term)]
       
   503   ) extends Content[Locale_Dependency] {
       
   504     override def cache(cache: Term.Cache): Locale_Dependency =
       
   505       Locale_Dependency(
       
   506         cache.string(source),
       
   507         cache.string(target),
       
   508         prefix.map({ case (name, mandatory) => (cache.string(name), mandatory) }),
       
   509         subst_types.map({ case ((a, s), ty) => ((cache.string(a), cache.sort(s)), cache.typ(ty)) }),
       
   510         subst_terms.map({ case ((x, ty), t) => ((cache.string(x), cache.typ(ty)), cache.term(t)) }))
       
   511 
       
   512     def is_inclusion: Boolean =
       
   513       subst_types.isEmpty && subst_terms.isEmpty
       
   514   }
       
   515 
       
   516   def read_locale_dependencies(
       
   517     theory_context: Export.Theory_Context
       
   518   ): List[Entity[Locale_Dependency]] = {
       
   519     read_entities(theory_context, Export.THEORY_PREFIX + "locale_dependencies",
       
   520       Kind.LOCALE_DEPENDENCY,
       
   521       { body =>
       
   522         import XML.Decode._
       
   523         import Term_XML.Decode._
       
   524         val (source, (target, (prefix, (subst_types, subst_terms)))) =
       
   525           pair(string, pair(string, pair(list(pair(string, bool)),
       
   526             pair(list(pair(pair(string, sort), typ)), list(pair(pair(string, typ), term))))))(body)
       
   527         Locale_Dependency(source, target, prefix, subst_types, subst_terms)
       
   528       })
       
   529   }
       
   530 
       
   531 
       
   532   /* sort algebra */
       
   533 
       
   534   sealed case class Classrel(class1: String, class2: String, prop: Prop) {
       
   535     def cache(cache: Term.Cache): Classrel =
       
   536       Classrel(cache.string(class1), cache.string(class2), prop.cache(cache))
       
   537   }
       
   538 
       
   539   def read_classrel(theory_context: Export.Theory_Context): List[Classrel] = {
       
   540     val body = theory_context.yxml(Export.THEORY_PREFIX + "classrel")
       
   541     val classrel = {
       
   542       import XML.Decode._
       
   543       list(pair(decode_prop, pair(string, string)))(body)
       
   544     }
       
   545     for ((prop, (c1, c2)) <- classrel) yield Classrel(c1, c2, prop)
       
   546   }
       
   547 
       
   548   sealed case class Arity(
       
   549     type_name: String,
       
   550     domain: List[Term.Sort],
       
   551     codomain: String,
       
   552     prop: Prop
       
   553   ) {
       
   554     def cache(cache: Term.Cache): Arity =
       
   555       Arity(cache.string(type_name), domain.map(cache.sort), cache.string(codomain),
       
   556         prop.cache(cache))
       
   557   }
       
   558 
       
   559   def read_arities(theory_context: Export.Theory_Context): List[Arity] = {
       
   560     val body = theory_context.yxml(Export.THEORY_PREFIX + "arities")
       
   561     val arities = {
       
   562       import XML.Decode._
       
   563       import Term_XML.Decode._
       
   564       list(pair(decode_prop, triple(string, list(sort), string)))(body)
       
   565     }
       
   566     for ((prop, (a, b, c)) <- arities) yield Arity(a, b, c, prop)
       
   567   }
       
   568 
       
   569 
       
   570   /* Pure constdefs */
       
   571 
       
   572   sealed case class Constdef(name: String, axiom_name: String) {
       
   573     def cache(cache: Term.Cache): Constdef =
       
   574       Constdef(cache.string(name), cache.string(axiom_name))
       
   575   }
       
   576 
       
   577   def read_constdefs(theory_context: Export.Theory_Context): List[Constdef] = {
       
   578     val body = theory_context.yxml(Export.THEORY_PREFIX + "constdefs")
       
   579     val constdefs = {
       
   580       import XML.Decode._
       
   581       list(pair(string, string))(body)
       
   582     }
       
   583     for ((name, axiom_name) <- constdefs) yield Constdef(name, axiom_name)
       
   584   }
       
   585 
       
   586 
       
   587   /* HOL typedefs */
       
   588 
       
   589   sealed case class Typedef(
       
   590     name: String,
       
   591     rep_type: Term.Typ,
       
   592     abs_type: Term.Typ,
       
   593     rep_name: String,
       
   594     abs_name: String,
       
   595     axiom_name: String
       
   596   ) {
       
   597     def cache(cache: Term.Cache): Typedef =
       
   598       Typedef(cache.string(name),
       
   599         cache.typ(rep_type),
       
   600         cache.typ(abs_type),
       
   601         cache.string(rep_name),
       
   602         cache.string(abs_name),
       
   603         cache.string(axiom_name))
       
   604   }
       
   605 
       
   606   def read_typedefs(theory_context: Export.Theory_Context): List[Typedef] = {
       
   607     val body = theory_context.yxml(Export.THEORY_PREFIX + "typedefs")
       
   608     val typedefs = {
       
   609       import XML.Decode._
       
   610       import Term_XML.Decode._
       
   611       list(pair(string, pair(typ, pair(typ, pair(string, pair(string, string))))))(body)
       
   612     }
       
   613     for { (name, (rep_type, (abs_type, (rep_name, (abs_name, axiom_name))))) <- typedefs }
       
   614     yield Typedef(name, rep_type, abs_type, rep_name, abs_name, axiom_name)
       
   615   }
       
   616 
       
   617 
       
   618   /* HOL datatypes */
       
   619 
       
   620   sealed case class Datatype(
       
   621     pos: Position.T,
       
   622     name: String,
       
   623     co: Boolean,
       
   624     typargs: List[(String, Term.Sort)],
       
   625     typ: Term.Typ,
       
   626     constructors: List[(Term.Term, Term.Typ)]
       
   627   ) {
       
   628     def id: Option[Long] = Position.Id.unapply(pos)
       
   629 
       
   630     def cache(cache: Term.Cache): Datatype =
       
   631       Datatype(
       
   632         cache.position(pos),
       
   633         cache.string(name),
       
   634         co,
       
   635         typargs.map({ case (name, sort) => (cache.string(name), cache.sort(sort)) }),
       
   636         cache.typ(typ),
       
   637         constructors.map({ case (term, typ) => (cache.term(term), cache.typ(typ)) }))
       
   638   }
       
   639 
       
   640   def read_datatypes(theory_context: Export.Theory_Context): List[Datatype] = {
       
   641     val body = theory_context.yxml(Export.THEORY_PREFIX + "datatypes")
       
   642     val datatypes = {
       
   643       import XML.Decode._
       
   644       import Term_XML.Decode._
       
   645       list(pair(properties, pair(string, pair(bool, pair(list(pair(string, sort)),
       
   646             pair(typ, list(pair(term, typ))))))))(body)
       
   647     }
       
   648     for ((pos, (name, (co, (typargs, (typ, constructors))))) <- datatypes)
       
   649       yield Datatype(pos, name, co, typargs, typ, constructors)
       
   650   }
       
   651 
       
   652 
       
   653   /* Pure spec rules */
       
   654 
       
   655   sealed abstract class Recursion {
       
   656     def cache(cache: Term.Cache): Recursion =
       
   657       this match {
       
   658         case Primrec(types) => Primrec(types.map(cache.string))
       
   659         case Primcorec(types) => Primcorec(types.map(cache.string))
       
   660         case _ => this
       
   661       }
       
   662   }
       
   663   case class Primrec(types: List[String]) extends Recursion
       
   664   case object Recdef extends Recursion
       
   665   case class Primcorec(types: List[String]) extends Recursion
       
   666   case object Corec extends Recursion
       
   667   case object Unknown_Recursion extends Recursion
       
   668 
       
   669   val decode_recursion: XML.Decode.T[Recursion] = {
       
   670     import XML.Decode._
       
   671     variant(List(
       
   672       { case (Nil, a) => Primrec(list(string)(a)) },
       
   673       { case (Nil, Nil) => Recdef },
       
   674       { case (Nil, a) => Primcorec(list(string)(a)) },
       
   675       { case (Nil, Nil) => Corec },
       
   676       { case (Nil, Nil) => Unknown_Recursion }))
       
   677   }
       
   678 
       
   679 
       
   680   sealed abstract class Rough_Classification {
       
   681     def is_equational: Boolean = this.isInstanceOf[Equational]
       
   682     def is_inductive: Boolean = this == Inductive
       
   683     def is_co_inductive: Boolean = this == Co_Inductive
       
   684     def is_relational: Boolean = is_inductive || is_co_inductive
       
   685     def is_unknown: Boolean = this == Unknown
       
   686 
       
   687     def cache(cache: Term.Cache): Rough_Classification =
       
   688       this match {
       
   689         case Equational(recursion) => Equational(recursion.cache(cache))
       
   690         case _ => this
       
   691       }
       
   692   }
       
   693   case class Equational(recursion: Recursion) extends Rough_Classification
       
   694   case object Inductive extends Rough_Classification
       
   695   case object Co_Inductive extends Rough_Classification
       
   696   case object Unknown extends Rough_Classification
       
   697 
       
   698   val decode_rough_classification: XML.Decode.T[Rough_Classification] = {
       
   699     import XML.Decode._
       
   700     variant(List(
       
   701       { case (Nil, a) => Equational(decode_recursion(a)) },
       
   702       { case (Nil, Nil) => Inductive },
       
   703       { case (Nil, Nil) => Co_Inductive },
       
   704       { case (Nil, Nil) => Unknown }))
       
   705   }
       
   706 
       
   707 
       
   708   sealed case class Spec_Rule(
       
   709     pos: Position.T,
       
   710     name: String,
       
   711     rough_classification: Rough_Classification,
       
   712     typargs: List[(String, Term.Sort)],
       
   713     args: List[(String, Term.Typ)],
       
   714     terms: List[(Term.Term, Term.Typ)],
       
   715     rules: List[Term.Term]
       
   716   ) {
       
   717     def id: Option[Long] = Position.Id.unapply(pos)
       
   718 
       
   719     def cache(cache: Term.Cache): Spec_Rule =
       
   720       Spec_Rule(
       
   721         cache.position(pos),
       
   722         cache.string(name),
       
   723         rough_classification.cache(cache),
       
   724         typargs.map({ case (name, sort) => (cache.string(name), cache.sort(sort)) }),
       
   725         args.map({ case (name, typ) => (cache.string(name), cache.typ(typ)) }),
       
   726         terms.map({ case (term, typ) => (cache.term(term), cache.typ(typ)) }),
       
   727         rules.map(cache.term))
       
   728   }
       
   729 
       
   730   def read_spec_rules(theory_context: Export.Theory_Context): List[Spec_Rule] = {
       
   731     val body = theory_context.yxml(Export.THEORY_PREFIX + "spec_rules")
       
   732     val spec_rules = {
       
   733       import XML.Decode._
       
   734       import Term_XML.Decode._
       
   735       list(
       
   736         pair(properties, pair(string, pair(decode_rough_classification,
       
   737           pair(list(pair(string, sort)), pair(list(pair(string, typ)),
       
   738             pair(list(pair(term, typ)), list(term))))))))(body)
       
   739     }
       
   740     for ((pos, (name, (rough_classification, (typargs, (args, (terms, rules)))))) <- spec_rules)
       
   741       yield Spec_Rule(pos, name, rough_classification, typargs, args, terms, rules)
       
   742   }
       
   743 
       
   744 
       
   745   /* other entities */
       
   746 
       
   747   sealed case class Other() extends Content[Other] {
       
   748     override def cache(cache: Term.Cache): Other = this
       
   749   }
       
   750 
       
   751   def read_others(theory_context: Export.Theory_Context): Map[String, List[Entity[Other]]] = {
       
   752     val kinds =
       
   753       theory_context.get(Export.THEORY_PREFIX + "other_kinds") match {
       
   754         case Some(entry) => split_lines(entry.text)
       
   755         case None => Nil
       
   756       }
       
   757     val other = Other()
       
   758     def read_other(kind: String): List[Entity[Other]] =
       
   759       read_entities(theory_context, Export.THEORY_PREFIX + "other/" + kind, kind, _ => other)
       
   760 
       
   761     kinds.map(kind => kind -> read_other(kind)).toMap
       
   762   }
       
   763 }