# HG changeset patch # User wenzelm # Date 1621794883 -7200 # Node ID 6b4c47666267e90f3123b019122da41f02890f2c # Parent 58bd53caf8006dbd221a4dd7cef7aa8be8f30794# Parent d07ab5b144538696166d6ae493619b08d3ee31d1 merged diff -r 58bd53caf800 -r 6b4c47666267 NEWS --- a/NEWS Wed May 19 14:17:40 2021 +0100 +++ b/NEWS Sun May 23 20:34:43 2021 +0200 @@ -34,6 +34,60 @@ *** Document preparation *** +* Document antiquotations for ML text have been refined: "def" and "ref" +variants support index entries, e.g. @{ML} (no entry) vs. @{ML_def} +(bold entry) vs. @{ML_ref} (regular entry); @{ML_type} supports explicit +type arguments for constructors (only relevant for index), e.g. +@{ML_type \'a list\} vs. @{ML_type 'a \list\}; @{ML_op} has been renamed +to @{ML_infix}. Minor INCOMPATIBILITY concerning name and syntax. + +* Option "document_logo" determines if an instance of the Isabelle logo +should be created in the document output directory. The given string +specifies the name of the logo variant, while "_" (underscore) refers to +the unnamed variant. The output file name is always "isabelle_logo.pdf". + +* Option "document_preprocessor" specifies the name of an executable +that is run within the document output directory, after preparing the +document sources and before the actual build process. This allows to +apply adhoc patches, without requiring a separate "build" script. + +* Option "document_build" determines the document build engine, as +defined in Isabelle/Scala (as system service). The subsequent engines +are provided by the Isabelle distribution: + + - "lualatex" (default): use ISABELLE_LUALATEX for a standard LaTeX + build with optional ISABELLE_BIBTEX and ISABELLE_MAKEINDEX + + - "pdflatex": as above, but use ISABELLE_PDFLATEX (legacy mode for + special LaTeX styles) + + - "build": delegate to the executable "./build pdf" + +The presence of a "build" command within the document output directory +explicitly requires document_build=build. Minor INCOMPATIBILITY, need to +adjust session ROOT options. + +* The command-line tool "isabelle latex" has been discontinued, +INCOMPATIBILITY for old document build scripts. + + - Former "isabelle latex -o sty" has become obsolete: Isabelle .sty + files are automatically generated within the document output + directory. + + - Former "isabelle latex -o pdf" should be replaced by + "$ISABELLE_LUALATEX root" or "$ISABELLE_PDFLATEX root" (without + quotes), according to the intended LaTeX engine. + + - Former "isabelle latex -o bbl" should be replaced by + "$ISABELLE_BIBTEX root" (without quotes). + + - Former "isabelle latex -o idx" should be replaced by + "$ISABELLE_MAKEINDEX root" (without quotes). + +* Option "document_bibliography" explicitly enables the use of bibtex; +the default is to check the presence of root.bib, but it could have a +different name. + * Improved LaTeX typesetting of \...\ using \guilsinglleft ... \guilsinglright. INCOMPATIBILITY, need to use \usepackage[T1]{fontenc} (which is now also the default in "isabelle mkroot"). diff -r 58bd53caf800 -r 6b4c47666267 etc/options --- a/etc/options Wed May 19 14:17:40 2021 +0100 +++ b/etc/options Sun May 23 20:34:43 2021 +0200 @@ -13,6 +13,14 @@ -- "alternative document variants (separated by colons)" option document_tags : string = "" -- "default command tags (separated by commas)" +option document_bibliography : bool = false + -- "explicitly enable use of bibtex (default: according to presence of root.bib)" +option document_preprocessor : string = "" + -- "document preprocessor: executable relative to document output directory" +option document_build : string = "lualatex" + -- "document build engine (e.g. lualatex, pdflatex, build)" +option document_logo : string = "" + -- "generate named instance of Isabelle logo (underscore means unnamed variant)" option thy_output_display : bool = false -- "indicate output as multi-line display-style material" diff -r 58bd53caf800 -r 6b4c47666267 etc/settings --- a/etc/settings Wed May 19 14:17:40 2021 +0100 +++ b/etc/settings Sun May 23 20:34:43 2021 +0200 @@ -16,7 +16,7 @@ ISABELLE_TOOL_JAVA_OPTIONS="-Djava.awt.headless=true -Xms512m -Xmx4g -Xss16m" -ISABELLE_SCALAC_OPTIONS="-encoding UTF-8 -Wconf:cat=other-match-analysis:silent -feature -deprecation -target:11 -J-Xms512m -J-Xmx4g -J-Xss16m" +ISABELLE_SCALAC_OPTIONS="-encoding UTF-8 -Wconf:cat=other-match-analysis:silent -feature -deprecation -target:11 -Xsource:3 -J-Xms512m -J-Xmx4g -J-Xss16m" classpath "$ISABELLE_HOME/lib/classes/Pure.jar" @@ -34,6 +34,10 @@ isabelle_scala_service 'isabelle.Simplifier_Trace$Handler' isabelle_scala_service 'isabelle.Server_Commands' +isabelle_scala_service 'isabelle.Document_Build$LuaLaTeX_Engine' +isabelle_scala_service 'isabelle.Document_Build$PDFLaTeX_Engine' +isabelle_scala_service 'isabelle.Document_Build$Build_Engine' + #paranoia settings -- avoid intrusion of alien options unset "_JAVA_OPTIONS" unset "JAVA_TOOL_OPTIONS" @@ -57,12 +61,18 @@ ### -### Document preparation (cf. isabelle latex/document) +### Document preparation (cf. isabelle latex) ### -ISABELLE_PDFLATEX="lualatex --file-line-error" +if [ "$ISABELLE_PLATFORM_FAMILY" = "windows" ]; then + ISABELLE_PDFLATEX="pdflatex -interaction=nonstopmode -c-style-errors" +else + ISABELLE_PDFLATEX="pdflatex -interaction=nonstopmode -file-line-error" +fi + +ISABELLE_LUALATEX="lualatex --interaction=nonstopmode --file-line-error" ISABELLE_BIBTEX="bibtex" -ISABELLE_MAKEINDEX="makeindex" +ISABELLE_MAKEINDEX="makeindex -c -q" ISABELLE_EPSTOPDF="epstopdf" diff -r 58bd53caf800 -r 6b4c47666267 lib/Tools/latex --- a/lib/Tools/latex Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -#!/usr/bin/env bash -# -# Author: Markus Wenzel, TU Muenchen -# -# DESCRIPTION: run LaTeX (and related tools) - - -PRG="$(basename "$0")" - -function usage() -{ - echo - echo "Usage: isabelle $PRG [OPTIONS] [FILE]" - echo - echo " Options are:" - echo " -o FORMAT specify output format: pdf (default), bbl, idx, sty" - echo - echo " Run LaTeX (and related tools) on FILE (default root.tex)," - echo " producing the specified output format." - echo - exit 1 -} - -function fail() -{ - echo "$1" >&2 - exit 2 -} - - -## process command line - -# options - -OUTFORMAT=pdf - -while getopts "o:" OPT -do - case "$OPT" in - o) - OUTFORMAT="$OPTARG" - ;; - \?) - usage - ;; - esac -done - -shift $(($OPTIND - 1)) - - -# args - -FILE="root.tex" -[ "$#" -ge 1 ] && { FILE="$1"; shift; } - -[ "$#" -ne 0 ] && usage - - -## main - -# root file - -DIR="$(dirname "$FILE")" -FILEBASE="$(basename "$FILE" .tex)" -[ "$DIR" = . ] || FILEBASE="$DIR/$FILEBASE" - -function check_root () { [ -f "$FILEBASE.tex" ] || fail "Bad file '$FILE'"; } - - -# operations - -function run_pdflatex () { $ISABELLE_PDFLATEX "\\nonstopmode\\input{$FILEBASE.tex}"; } -function run_bibtex () { - $ISABELLE_BIBTEX &2 - fi - return "$RC" -} -function run_makeindex () { $ISABELLE_MAKEINDEX "$TARGET" - done -} - -case "$OUTFORMAT" in - pdf) - check_root && \ - run_pdflatex - RC="$?" - ;; - bbl) - check_root && \ - run_bibtex - RC="$?" - ;; - idx) - check_root && \ - run_makeindex - RC="$?" - ;; - sty) - copy_styles - RC="$?" - ;; - *) - fail "Bad output format '$OUTFORMAT'" - ;; -esac - -exit "$RC" diff -r 58bd53caf800 -r 6b4c47666267 lib/texinputs/isabelle.sty --- a/lib/texinputs/isabelle.sty Wed May 19 14:17:40 2021 +0100 +++ b/lib/texinputs/isabelle.sty Sun May 23 20:34:43 2021 +0200 @@ -173,6 +173,12 @@ \newcommand{\isamarkupcmt}[1]{{\isastylecmt--- #1}} +% index entries + +\newcommand{\isaindexdef}[1]{\textbf{#1}} +\newcommand{\isaindexref}[1]{#1} + + % styles \def\isabellestyle#1{\csname isabellestyle#1\endcsname} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Classes/document/build --- a/src/Doc/Classes/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo Isar -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Classes/document/root.tex --- a/src/Doc/Classes/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Classes/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -10,7 +10,7 @@ \hyphenation{Isar} \isadroptag{theory} -\title{\includegraphics[scale=0.5]{isabelle_isar} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Haskell-style type classes with Isabelle/Isar} \author{\emph{Florian Haftmann}} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Codegen/document/build --- a/src/Doc/Codegen/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -# ad-hoc patching of temporary path from sources -perl -i -pe 's/\{\\isachardollar\}ISABELLE\{\\isacharunderscore\}TMP\{\\isacharslash\}examples/examples/g' *.tex - -isabelle logo Isar -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - -# clean up afterwards -rm -rf "${ISABELLE_TMP}/examples" diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Codegen/document/root.tex --- a/src/Doc/Codegen/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Codegen/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -13,7 +13,7 @@ \hyphenation{Isar} \isadroptag{theory} -\title{\includegraphics[scale=0.5]{isabelle_isar} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Code generation from Isabelle/HOL theories} \author{\emph{Florian Haftmann with contributions from Lukas Bulwahn}} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Corec/document/build --- a/src/Doc/Corec/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Corec/document/root.tex --- a/src/Doc/Corec/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Corec/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -48,7 +48,7 @@ \isadroptag{theory} -\title{%\includegraphics[scale=0.5]{isabelle_hol} \\[4ex] +\title{%\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Defining Nonprimitively (Co)recursive Functions in Isabelle/HOL} \author{Jasmin Christian Blanchette, Aymeric Bouzy, \\ Andreas Lochbihler, Andrei Popescu, and \\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Datatypes/document/build --- a/src/Doc/Datatypes/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Datatypes/document/root.tex --- a/src/Doc/Datatypes/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Datatypes/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -48,7 +48,7 @@ \isadroptag{theory} -\title{%\includegraphics[scale=0.5]{isabelle_hol} \\[4ex] +\title{%\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Defining (Co)datatypes and Primitively (Co)recursive Functions in Isabelle/HOL} \author{Julian Biendarra, Jasmin Blanchette, \\ Martin Desharnais, Lorenz Panny, \\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Eisbach/document/build --- a/src/Doc/Eisbach/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo Eisbach -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Eisbach/document/root.tex --- a/src/Doc/Eisbach/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Eisbach/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -16,7 +16,7 @@ \hyphenation{Eisbach} \isadroptag{theory} -\title{\includegraphics[scale=0.5]{isabelle_eisbach} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] The Eisbach User Manual} \author{Daniel Matichuk \\ Makarius Wenzel \\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Functions/document/build --- a/src/Doc/Functions/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/How_to_Prove_it/document/root.tex --- a/src/Doc/How_to_Prove_it/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/How_to_Prove_it/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -5,7 +5,7 @@ \begin{document} \title{How to Prove it in Isabelle/HOL} -%\subtitle{\includegraphics[scale=.7]{isabelle_hol}} +%\subtitle{\includegraphics[scale=.7]{isabelle_logo}} \author{Tobias Nipkow} \maketitle diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Eq.thy --- a/src/Doc/Implementation/Eq.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Eq.thy Sun May 23 20:34:43 2021 +0200 @@ -55,13 +55,13 @@ text %mlref \ \begin{mldecls} - @{index_ML Thm.reflexive: "cterm -> thm"} \\ - @{index_ML Thm.symmetric: "thm -> thm"} \\ - @{index_ML Thm.transitive: "thm -> thm -> thm"} \\ - @{index_ML Thm.abstract_rule: "string -> cterm -> thm -> thm"} \\ - @{index_ML Thm.combination: "thm -> thm -> thm"} \\[0.5ex] - @{index_ML Thm.equal_intr: "thm -> thm -> thm"} \\ - @{index_ML Thm.equal_elim: "thm -> thm -> thm"} \\ + @{define_ML Thm.reflexive: "cterm -> thm"} \\ + @{define_ML Thm.symmetric: "thm -> thm"} \\ + @{define_ML Thm.transitive: "thm -> thm -> thm"} \\ + @{define_ML Thm.abstract_rule: "string -> cterm -> thm -> thm"} \\ + @{define_ML Thm.combination: "thm -> thm -> thm"} \\[0.5ex] + @{define_ML Thm.equal_intr: "thm -> thm -> thm"} \\ + @{define_ML Thm.equal_elim: "thm -> thm -> thm"} \\ \end{mldecls} See also \<^file>\~~/src/Pure/thm.ML\ for further description of these inference @@ -82,9 +82,9 @@ text %mlref \ \begin{mldecls} - @{index_ML_structure Conv} \\ - @{index_ML_type conv} \\ - @{index_ML Simplifier.asm_full_rewrite : "Proof.context -> conv"} \\ + @{define_ML_structure Conv} \\ + @{define_ML_type conv} \\ + @{define_ML Simplifier.asm_full_rewrite : "Proof.context -> conv"} \\ \end{mldecls} \<^descr> \<^ML_structure>\Conv\ is a library of combinators to build conversions, @@ -109,11 +109,11 @@ text %mlref \ \begin{mldecls} - @{index_ML rewrite_rule: "Proof.context -> thm list -> thm -> thm"} \\ - @{index_ML rewrite_goals_rule: "Proof.context -> thm list -> thm -> thm"} \\ - @{index_ML rewrite_goal_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML rewrite_goals_tac: "Proof.context -> thm list -> tactic"} \\ - @{index_ML fold_goals_tac: "Proof.context -> thm list -> tactic"} \\ + @{define_ML rewrite_rule: "Proof.context -> thm list -> thm -> thm"} \\ + @{define_ML rewrite_goals_rule: "Proof.context -> thm list -> thm -> thm"} \\ + @{define_ML rewrite_goal_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML rewrite_goals_tac: "Proof.context -> thm list -> tactic"} \\ + @{define_ML fold_goals_tac: "Proof.context -> thm list -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\rewrite_rule\~\ctxt rules thm\ rewrites the whole theorem by the diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Integration.thy --- a/src/Doc/Implementation/Integration.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Integration.thy Sun May 23 20:34:43 2021 +0200 @@ -37,11 +37,11 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Toplevel.state} \\ - @{index_ML_exception Toplevel.UNDEF} \\ - @{index_ML Toplevel.is_toplevel: "Toplevel.state -> bool"} \\ - @{index_ML Toplevel.theory_of: "Toplevel.state -> theory"} \\ - @{index_ML Toplevel.proof_of: "Toplevel.state -> Proof.state"} \\ + @{define_ML_type Toplevel.state} \\ + @{define_ML_exception Toplevel.UNDEF} \\ + @{define_ML Toplevel.is_toplevel: "Toplevel.state -> bool"} \\ + @{define_ML Toplevel.theory_of: "Toplevel.state -> theory"} \\ + @{define_ML Toplevel.proof_of: "Toplevel.state -> Proof.state"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\Toplevel.state\ represents Isar toplevel states, which are @@ -95,17 +95,17 @@ text %mlref \ \begin{mldecls} - @{index_ML Toplevel.keep: "(Toplevel.state -> unit) -> + @{define_ML Toplevel.keep: "(Toplevel.state -> unit) -> Toplevel.transition -> Toplevel.transition"} \\ - @{index_ML Toplevel.theory: "(theory -> theory) -> + @{define_ML Toplevel.theory: "(theory -> theory) -> Toplevel.transition -> Toplevel.transition"} \\ - @{index_ML Toplevel.theory_to_proof: "(theory -> Proof.state) -> + @{define_ML Toplevel.theory_to_proof: "(theory -> Proof.state) -> Toplevel.transition -> Toplevel.transition"} \\ - @{index_ML Toplevel.proof: "(Proof.state -> Proof.state) -> + @{define_ML Toplevel.proof: "(Proof.state -> Proof.state) -> Toplevel.transition -> Toplevel.transition"} \\ - @{index_ML Toplevel.proofs: "(Proof.state -> Proof.state Seq.result Seq.seq) -> + @{define_ML Toplevel.proofs: "(Proof.state -> Proof.state Seq.result Seq.seq) -> Toplevel.transition -> Toplevel.transition"} \\ - @{index_ML Toplevel.end_proof: "(bool -> Proof.state -> Proof.context) -> + @{define_ML Toplevel.end_proof: "(bool -> Proof.state -> Proof.context) -> Toplevel.transition -> Toplevel.transition"} \\ \end{mldecls} @@ -150,10 +150,10 @@ text %mlref \ \begin{mldecls} - @{index_ML use_thy: "string -> unit"} \\ - @{index_ML Thy_Info.get_theory: "string -> theory"} \\ - @{index_ML Thy_Info.remove_thy: "string -> unit"} \\ - @{index_ML Thy_Info.register_thy: "theory -> unit"} \\ + @{define_ML use_thy: "string -> unit"} \\ + @{define_ML Thy_Info.get_theory: "string -> theory"} \\ + @{define_ML Thy_Info.remove_thy: "string -> unit"} \\ + @{define_ML Thy_Info.register_thy: "theory -> unit"} \\ \end{mldecls} \<^descr> \<^ML>\use_thy\~\A\ ensures that theory \A\ is fully up-to-date wrt.\ the diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Isar.thy --- a/src/Doc/Implementation/Isar.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Isar.thy Sun May 23 20:34:43 2021 +0200 @@ -60,16 +60,16 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Proof.state} \\ - @{index_ML Proof.assert_forward: "Proof.state -> Proof.state"} \\ - @{index_ML Proof.assert_chain: "Proof.state -> Proof.state"} \\ - @{index_ML Proof.assert_backward: "Proof.state -> Proof.state"} \\ - @{index_ML Proof.simple_goal: "Proof.state -> {context: Proof.context, goal: thm}"} \\ - @{index_ML Proof.goal: "Proof.state -> + @{define_ML_type Proof.state} \\ + @{define_ML Proof.assert_forward: "Proof.state -> Proof.state"} \\ + @{define_ML Proof.assert_chain: "Proof.state -> Proof.state"} \\ + @{define_ML Proof.assert_backward: "Proof.state -> Proof.state"} \\ + @{define_ML Proof.simple_goal: "Proof.state -> {context: Proof.context, goal: thm}"} \\ + @{define_ML Proof.goal: "Proof.state -> {context: Proof.context, facts: thm list, goal: thm}"} \\ - @{index_ML Proof.raw_goal: "Proof.state -> + @{define_ML Proof.raw_goal: "Proof.state -> {context: Proof.context, facts: thm list, goal: thm}"} \\ - @{index_ML Proof.theorem: "Method.text option -> + @{define_ML Proof.theorem: "Method.text option -> (thm list list -> Proof.context -> Proof.context) -> (term * term list) list list -> Proof.context -> Proof.state"} \\ \end{mldecls} @@ -272,13 +272,13 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Proof.method} \\ - @{index_ML CONTEXT_METHOD: "(thm list -> context_tactic) -> Proof.method"} \\ - @{index_ML METHOD: "(thm list -> tactic) -> Proof.method"} \\ - @{index_ML SIMPLE_METHOD: "tactic -> Proof.method"} \\ - @{index_ML SIMPLE_METHOD': "(int -> tactic) -> Proof.method"} \\ - @{index_ML Method.insert_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML Method.setup: "binding -> (Proof.context -> Proof.method) context_parser -> + @{define_ML_type Proof.method} \\ + @{define_ML CONTEXT_METHOD: "(thm list -> context_tactic) -> Proof.method"} \\ + @{define_ML METHOD: "(thm list -> tactic) -> Proof.method"} \\ + @{define_ML SIMPLE_METHOD: "tactic -> Proof.method"} \\ + @{define_ML SIMPLE_METHOD': "(int -> tactic) -> Proof.method"} \\ + @{define_ML Method.insert_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML Method.setup: "binding -> (Proof.context -> Proof.method) context_parser -> string -> theory -> theory"} \\ \end{mldecls} @@ -286,7 +286,7 @@ \<^descr> \<^ML>\CONTEXT_METHOD\~\(fn facts => context_tactic)\ wraps \context_tactic\ depending on goal facts as a general proof method that may change the proof - context dynamically. A typical operation is \<^ML>\Proof_Context.update_cases\, which is wrapped up as combinator @{index_ML + context dynamically. A typical operation is \<^ML>\Proof_Context.update_cases\, which is wrapped up as combinator @{define_ML CONTEXT_CASES} for convenience. \<^descr> \<^ML>\METHOD\~\(fn facts => tactic)\ wraps \tactic\ depending on goal facts @@ -495,12 +495,12 @@ text %mlref \ \begin{mldecls} - @{index_ML_type attribute} \\ - @{index_ML Thm.rule_attribute: "thm list -> + @{define_ML_type attribute} \\ + @{define_ML Thm.rule_attribute: "thm list -> (Context.generic -> thm -> thm) -> attribute"} \\ - @{index_ML Thm.declaration_attribute: " + @{define_ML Thm.declaration_attribute: " (thm -> Context.generic -> Context.generic) -> attribute"} \\ - @{index_ML Attrib.setup: "binding -> attribute context_parser -> + @{define_ML Attrib.setup: "binding -> attribute context_parser -> string -> theory -> theory"} \\ \end{mldecls} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Local_Theory.thy --- a/src/Doc/Implementation/Local_Theory.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Local_Theory.thy Sun May 23 20:34:43 2021 +0200 @@ -90,11 +90,11 @@ text %mlref \ \begin{mldecls} - @{index_ML_type local_theory: Proof.context} \\ - @{index_ML Named_Target.init: "string list -> string -> theory -> local_theory"} \\[1ex] - @{index_ML Local_Theory.define: "(binding * mixfix) * (Attrib.binding * term) -> + @{define_ML_type local_theory = Proof.context} \\ + @{define_ML Named_Target.init: "string list -> string -> theory -> local_theory"} \\[1ex] + @{define_ML Local_Theory.define: "(binding * mixfix) * (Attrib.binding * term) -> local_theory -> (term * (string * thm)) * local_theory"} \\ - @{index_ML Local_Theory.note: "Attrib.binding * thm list -> + @{define_ML Local_Theory.note: "Attrib.binding * thm list -> local_theory -> (string * thm list) * local_theory"} \\ \end{mldecls} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Logic.thy --- a/src/Doc/Implementation/Logic.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Logic.thy Sun May 23 20:34:43 2021 +0200 @@ -102,22 +102,22 @@ text %mlref \ \begin{mldecls} - @{index_ML_type class: string} \\ - @{index_ML_type sort: "class list"} \\ - @{index_ML_type arity: "string * sort list * sort"} \\ - @{index_ML_type typ} \\ - @{index_ML Term.map_atyps: "(typ -> typ) -> typ -> typ"} \\ - @{index_ML Term.fold_atyps: "(typ -> 'a -> 'a) -> typ -> 'a -> 'a"} \\ + @{define_ML_type class = string} \\ + @{define_ML_type sort = "class list"} \\ + @{define_ML_type arity = "string * sort list * sort"} \\ + @{define_ML_type typ} \\ + @{define_ML Term.map_atyps: "(typ -> typ) -> typ -> typ"} \\ + @{define_ML Term.fold_atyps: "(typ -> 'a -> 'a) -> typ -> 'a -> 'a"} \\ \end{mldecls} \begin{mldecls} - @{index_ML Sign.subsort: "theory -> sort * sort -> bool"} \\ - @{index_ML Sign.of_sort: "theory -> typ * sort -> bool"} \\ - @{index_ML Sign.add_type: "Proof.context -> binding * int * mixfix -> theory -> theory"} \\ - @{index_ML Sign.add_type_abbrev: "Proof.context -> + @{define_ML Sign.subsort: "theory -> sort * sort -> bool"} \\ + @{define_ML Sign.of_sort: "theory -> typ * sort -> bool"} \\ + @{define_ML Sign.add_type: "Proof.context -> binding * int * mixfix -> theory -> theory"} \\ + @{define_ML Sign.add_type_abbrev: "Proof.context -> binding * string list * typ -> theory -> theory"} \\ - @{index_ML Sign.primitive_class: "binding * class list -> theory -> theory"} \\ - @{index_ML Sign.primitive_classrel: "class * class -> theory -> theory"} \\ - @{index_ML Sign.primitive_arity: "arity -> theory -> theory"} \\ + @{define_ML Sign.primitive_class: "binding * class list -> theory -> theory"} \\ + @{define_ML Sign.primitive_classrel: "class * class -> theory -> theory"} \\ + @{define_ML Sign.primitive_arity: "arity -> theory -> theory"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\class\ represents type classes. @@ -313,30 +313,30 @@ text %mlref \ \begin{mldecls} - @{index_ML_type term} \\ - @{index_ML_op "aconv": "term * term -> bool"} \\ - @{index_ML Term.map_types: "(typ -> typ) -> term -> term"} \\ - @{index_ML Term.fold_types: "(typ -> 'a -> 'a) -> term -> 'a -> 'a"} \\ - @{index_ML Term.map_aterms: "(term -> term) -> term -> term"} \\ - @{index_ML Term.fold_aterms: "(term -> 'a -> 'a) -> term -> 'a -> 'a"} \\ + @{define_ML_type term} \\ + @{define_ML_infix "aconv": "term * term -> bool"} \\ + @{define_ML Term.map_types: "(typ -> typ) -> term -> term"} \\ + @{define_ML Term.fold_types: "(typ -> 'a -> 'a) -> term -> 'a -> 'a"} \\ + @{define_ML Term.map_aterms: "(term -> term) -> term -> term"} \\ + @{define_ML Term.fold_aterms: "(term -> 'a -> 'a) -> term -> 'a -> 'a"} \\ \end{mldecls} \begin{mldecls} - @{index_ML fastype_of: "term -> typ"} \\ - @{index_ML lambda: "term -> term -> term"} \\ - @{index_ML betapply: "term * term -> term"} \\ - @{index_ML incr_boundvars: "int -> term -> term"} \\ - @{index_ML Sign.declare_const: "Proof.context -> + @{define_ML fastype_of: "term -> typ"} \\ + @{define_ML lambda: "term -> term -> term"} \\ + @{define_ML betapply: "term * term -> term"} \\ + @{define_ML incr_boundvars: "int -> term -> term"} \\ + @{define_ML Sign.declare_const: "Proof.context -> (binding * typ) * mixfix -> theory -> term * theory"} \\ - @{index_ML Sign.add_abbrev: "string -> binding * term -> + @{define_ML Sign.add_abbrev: "string -> binding * term -> theory -> (term * term) * theory"} \\ - @{index_ML Sign.const_typargs: "theory -> string * typ -> typ list"} \\ - @{index_ML Sign.const_instance: "theory -> string * typ list -> typ"} \\ + @{define_ML Sign.const_typargs: "theory -> string * typ -> typ list"} \\ + @{define_ML Sign.const_instance: "theory -> string * typ list -> typ"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\term\ represents de-Bruijn terms, with comments in abstractions, and explicitly named free variables and constants; this is a - datatype with constructors @{index_ML Bound}, @{index_ML Free}, @{index_ML - Var}, @{index_ML Const}, @{index_ML Abs}, @{index_ML_op "$"}. + datatype with constructors @{define_ML Bound}, @{define_ML Free}, @{define_ML + Var}, @{define_ML Const}, @{define_ML Abs}, @{define_ML_infix "$"}. \<^descr> \t\~\<^ML_text>\aconv\~\u\ checks \\\-equivalence of two terms. This is the basic equality relation on type \<^ML_type>\term\; raw datatype equality @@ -564,41 +564,41 @@ text %mlref \ \begin{mldecls} - @{index_ML Logic.all: "term -> term -> term"} \\ - @{index_ML Logic.mk_implies: "term * term -> term"} \\ + @{define_ML Logic.all: "term -> term -> term"} \\ + @{define_ML Logic.mk_implies: "term * term -> term"} \\ \end{mldecls} \begin{mldecls} - @{index_ML_type ctyp} \\ - @{index_ML_type cterm} \\ - @{index_ML Thm.ctyp_of: "Proof.context -> typ -> ctyp"} \\ - @{index_ML Thm.cterm_of: "Proof.context -> term -> cterm"} \\ - @{index_ML Thm.apply: "cterm -> cterm -> cterm"} \\ - @{index_ML Thm.lambda: "cterm -> cterm -> cterm"} \\ - @{index_ML Thm.all: "Proof.context -> cterm -> cterm -> cterm"} \\ - @{index_ML Drule.mk_implies: "cterm * cterm -> cterm"} \\ + @{define_ML_type ctyp} \\ + @{define_ML_type cterm} \\ + @{define_ML Thm.ctyp_of: "Proof.context -> typ -> ctyp"} \\ + @{define_ML Thm.cterm_of: "Proof.context -> term -> cterm"} \\ + @{define_ML Thm.apply: "cterm -> cterm -> cterm"} \\ + @{define_ML Thm.lambda: "cterm -> cterm -> cterm"} \\ + @{define_ML Thm.all: "Proof.context -> cterm -> cterm -> cterm"} \\ + @{define_ML Drule.mk_implies: "cterm * cterm -> cterm"} \\ \end{mldecls} \begin{mldecls} - @{index_ML_type thm} \\ - @{index_ML Thm.transfer: "theory -> thm -> thm"} \\ - @{index_ML Thm.assume: "cterm -> thm"} \\ - @{index_ML Thm.forall_intr: "cterm -> thm -> thm"} \\ - @{index_ML Thm.forall_elim: "cterm -> thm -> thm"} \\ - @{index_ML Thm.implies_intr: "cterm -> thm -> thm"} \\ - @{index_ML Thm.implies_elim: "thm -> thm -> thm"} \\ - @{index_ML Thm.generalize: "string list * string list -> int -> thm -> thm"} \\ - @{index_ML Thm.instantiate: "((indexname * sort) * ctyp) list * ((indexname * typ) * cterm) list + @{define_ML_type thm} \\ + @{define_ML Thm.transfer: "theory -> thm -> thm"} \\ + @{define_ML Thm.assume: "cterm -> thm"} \\ + @{define_ML Thm.forall_intr: "cterm -> thm -> thm"} \\ + @{define_ML Thm.forall_elim: "cterm -> thm -> thm"} \\ + @{define_ML Thm.implies_intr: "cterm -> thm -> thm"} \\ + @{define_ML Thm.implies_elim: "thm -> thm -> thm"} \\ + @{define_ML Thm.generalize: "string list * string list -> int -> thm -> thm"} \\ + @{define_ML Thm.instantiate: "((indexname * sort) * ctyp) list * ((indexname * typ) * cterm) list -> thm -> thm"} \\ - @{index_ML Thm.add_axiom: "Proof.context -> + @{define_ML Thm.add_axiom: "Proof.context -> binding * term -> theory -> (string * thm) * theory"} \\ - @{index_ML Thm.add_oracle: "binding * ('a -> cterm) -> theory -> + @{define_ML Thm.add_oracle: "binding * ('a -> cterm) -> theory -> (string * ('a -> thm)) * theory"} \\ - @{index_ML Thm.add_def: "Defs.context -> bool -> bool -> + @{define_ML Thm.add_def: "Defs.context -> bool -> bool -> binding * term -> theory -> (string * thm) * theory"} \\ \end{mldecls} \begin{mldecls} - @{index_ML Theory.add_deps: "Defs.context -> string -> + @{define_ML Theory.add_deps: "Defs.context -> string -> Defs.entry -> Defs.entry list -> theory -> theory"} \\ - @{index_ML Thm_Deps.all_oracles: "thm list -> Proofterm.oracle list"} \\ + @{define_ML Thm_Deps.all_oracles: "thm list -> Proofterm.oracle list"} \\ \end{mldecls} \<^descr> \<^ML>\Logic.all\~\a B\ produces a Pure quantification \\a. B\, where @@ -624,7 +624,7 @@ \<^descr> \<^ML>\Thm.apply\, \<^ML>\Thm.lambda\, \<^ML>\Thm.all\, \<^ML>\Drule.mk_implies\ etc.\ compose certified terms (or propositions) incrementally. This is - equivalent to \<^ML>\Thm.cterm_of\ after unchecked \<^ML_op>\$\, \<^ML>\lambda\, + equivalent to \<^ML>\Thm.cterm_of\ after unchecked \<^ML_infix>\$\, \<^ML>\lambda\, \<^ML>\Logic.all\, \<^ML>\Logic.mk_implies\ etc., but there can be a big difference in performance when large existing entities are composed by a few extra constructions on top. There are separate operations to decompose @@ -796,12 +796,12 @@ text %mlref \ \begin{mldecls} - @{index_ML Conjunction.intr: "thm -> thm -> thm"} \\ - @{index_ML Conjunction.elim: "thm -> thm * thm"} \\ - @{index_ML Drule.mk_term: "cterm -> thm"} \\ - @{index_ML Drule.dest_term: "thm -> cterm"} \\ - @{index_ML Logic.mk_type: "typ -> term"} \\ - @{index_ML Logic.dest_type: "term -> typ"} \\ + @{define_ML Conjunction.intr: "thm -> thm -> thm"} \\ + @{define_ML Conjunction.elim: "thm -> thm * thm"} \\ + @{define_ML Drule.mk_term: "cterm -> thm"} \\ + @{define_ML Drule.dest_term: "thm -> cterm"} \\ + @{define_ML Logic.mk_type: "typ -> term"} \\ + @{define_ML Logic.dest_type: "term -> typ"} \\ \end{mldecls} \<^descr> \<^ML>\Conjunction.intr\ derives \A &&& B\ from \A\ and \B\. @@ -846,8 +846,8 @@ text %mlref \ \begin{mldecls} - @{index_ML Thm.extra_shyps: "thm -> sort list"} \\ - @{index_ML Thm.strip_shyps: "thm -> thm"} \\ + @{define_ML Thm.extra_shyps: "thm -> sort list"} \\ + @{define_ML Thm.strip_shyps: "thm -> thm"} \\ \end{mldecls} \<^descr> \<^ML>\Thm.extra_shyps\~\thm\ determines the extraneous sort hypotheses of @@ -951,7 +951,7 @@ text %mlref \ \begin{mldecls} - @{index_ML Simplifier.norm_hhf: "Proof.context -> thm -> thm"} \\ + @{define_ML Simplifier.norm_hhf: "Proof.context -> thm -> thm"} \\ \end{mldecls} \<^descr> \<^ML>\Simplifier.norm_hhf\~\ctxt thm\ normalizes the given theorem @@ -1022,14 +1022,14 @@ text %mlref \ \begin{mldecls} - @{index_ML_op "RSN": "thm * (int * thm) -> thm"} \\ - @{index_ML_op "RS": "thm * thm -> thm"} \\ + @{define_ML_infix "RSN": "thm * (int * thm) -> thm"} \\ + @{define_ML_infix "RS": "thm * thm -> thm"} \\ - @{index_ML_op "RLN": "thm list * (int * thm list) -> thm list"} \\ - @{index_ML_op "RL": "thm list * thm list -> thm list"} \\ + @{define_ML_infix "RLN": "thm list * (int * thm list) -> thm list"} \\ + @{define_ML_infix "RL": "thm list * thm list -> thm list"} \\ - @{index_ML_op "MRS": "thm list * thm -> thm"} \\ - @{index_ML_op "OF": "thm * thm list -> thm"} \\ + @{define_ML_infix "MRS": "thm list * thm -> thm"} \\ + @{define_ML_infix "OF": "thm * thm list -> thm"} \\ \end{mldecls} \<^descr> \rule\<^sub>1 RSN (i, rule\<^sub>2)\ resolves the conclusion of \rule\<^sub>1\ with the @@ -1184,22 +1184,22 @@ text %mlref \ \begin{mldecls} - @{index_ML_type proof} \\ - @{index_ML_type proof_body} \\ - @{index_ML Proofterm.proofs: "int Unsynchronized.ref"} \\ - @{index_ML Proofterm.reconstruct_proof: + @{define_ML_type proof} \\ + @{define_ML_type proof_body} \\ + @{define_ML Proofterm.proofs: "int Unsynchronized.ref"} \\ + @{define_ML Proofterm.reconstruct_proof: "theory -> term -> proof -> proof"} \\ - @{index_ML Proofterm.expand_proof: "theory -> + @{define_ML Proofterm.expand_proof: "theory -> (Proofterm.thm_header -> string option) -> proof -> proof"} \\ - @{index_ML Proof_Checker.thm_of_proof: "theory -> proof -> thm"} \\ - @{index_ML Proof_Syntax.read_proof: "theory -> bool -> bool -> string -> proof"} \\ - @{index_ML Proof_Syntax.pretty_proof: "Proof.context -> proof -> Pretty.T"} \\ + @{define_ML Proof_Checker.thm_of_proof: "theory -> proof -> thm"} \\ + @{define_ML Proof_Syntax.read_proof: "theory -> bool -> bool -> string -> proof"} \\ + @{define_ML Proof_Syntax.pretty_proof: "Proof.context -> proof -> Pretty.T"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\proof\ represents proof terms; this is a datatype with - constructors @{index_ML Abst}, @{index_ML AbsP}, @{index_ML_op "%"}, - @{index_ML_op "%%"}, @{index_ML PBound}, @{index_ML MinProof}, @{index_ML - Hyp}, @{index_ML PAxm}, @{index_ML Oracle}, @{index_ML PThm} as explained + constructors @{define_ML Abst}, @{define_ML AbsP}, @{define_ML_infix "%"}, + @{define_ML_infix "%%"}, @{define_ML PBound}, @{define_ML MinProof}, @{define_ML + Hyp}, @{define_ML PAxm}, @{define_ML Oracle}, @{define_ML PThm} as explained above. %FIXME PClass (!?) \<^descr> Type \<^ML_type>\proof_body\ represents the nested proof information of a diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/ML.thy --- a/src/Doc/Implementation/ML.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/ML.thy Sun May 23 20:34:43 2021 +0200 @@ -611,10 +611,10 @@ text %mlref \ \begin{mldecls} - @{index_ML Context.the_generic_context: "unit -> Context.generic"} \\ - @{index_ML "Context.>>": "(Context.generic -> Context.generic) -> unit"} \\ - @{index_ML ML_Thms.bind_thms: "string * thm list -> unit"} \\ - @{index_ML ML_Thms.bind_thm: "string * thm -> unit"} \\ + @{define_ML Context.the_generic_context: "unit -> Context.generic"} \\ + @{define_ML "Context.>>": "(Context.generic -> Context.generic) -> unit"} \\ + @{define_ML ML_Thms.bind_thms: "string * thm list -> unit"} \\ + @{define_ML ML_Thms.bind_thm: "string * thm -> unit"} \\ \end{mldecls} \<^descr> \<^ML>\Context.the_generic_context ()\ refers to the theory context of @@ -818,10 +818,10 @@ text %mlref \ \begin{mldecls} - @{index_ML_op "|> ": "'a * ('a -> 'b) -> 'b"} \\ - @{index_ML_op "|-> ": "('c * 'a) * ('c -> 'a -> 'b) -> 'b"} \\ - @{index_ML_op "#> ": "('a -> 'b) * ('b -> 'c) -> 'a -> 'c"} \\ - @{index_ML_op "#-> ": "('a -> 'c * 'b) * ('c -> 'b -> 'd) -> 'a -> 'd"} \\ + @{define_ML_infix "|>" : "'a * ('a -> 'b) -> 'b"} \\ + @{define_ML_infix "|->" : "('c * 'a) * ('c -> 'a -> 'b) -> 'b"} \\ + @{define_ML_infix "#>" : "('a -> 'b) * ('b -> 'c) -> 'a -> 'c"} \\ + @{define_ML_infix "#->" : "('a -> 'c * 'b) * ('c -> 'b -> 'd) -> 'a -> 'd"} \\ \end{mldecls} \ @@ -853,9 +853,9 @@ text %mlref \ \begin{mldecls} - @{index_ML fold: "('a -> 'b -> 'b) -> 'a list -> 'b -> 'b"} \\ - @{index_ML fold_rev: "('a -> 'b -> 'b) -> 'a list -> 'b -> 'b"} \\ - @{index_ML fold_map: "('a -> 'b -> 'c * 'b) -> 'a list -> 'b -> 'c list * 'b"} \\ + @{define_ML fold: "('a -> 'b -> 'b) -> 'a list -> 'b -> 'b"} \\ + @{define_ML fold_rev: "('a -> 'b -> 'b) -> 'a list -> 'b -> 'b"} \\ + @{define_ML fold_map: "('a -> 'b -> 'c * 'b) -> 'a list -> 'b -> 'c list * 'b"} \\ \end{mldecls} \<^descr> \<^ML>\fold\~\f\ lifts the parametrized update function \f\ to a list of @@ -969,10 +969,10 @@ text %mlref \ \begin{mldecls} - @{index_ML writeln: "string -> unit"} \\ - @{index_ML tracing: "string -> unit"} \\ - @{index_ML warning: "string -> unit"} \\ - @{index_ML error: "string -> 'a"} % FIXME Output.error_message (!?) \\ + @{define_ML writeln: "string -> unit"} \\ + @{define_ML tracing: "string -> unit"} \\ + @{define_ML warning: "string -> unit"} \\ + @{define_ML error: "string -> 'a"} % FIXME Output.error_message (!?) \\ \end{mldecls} \<^descr> \<^ML>\writeln\~\text\ outputs \text\ as regular message. This is the @@ -1140,13 +1140,13 @@ text %mlref \ \begin{mldecls} - @{index_ML try: "('a -> 'b) -> 'a -> 'b option"} \\ - @{index_ML can: "('a -> 'b) -> 'a -> bool"} \\ - @{index_ML_exception ERROR: string} \\ - @{index_ML_exception Fail: string} \\ - @{index_ML Exn.is_interrupt: "exn -> bool"} \\ - @{index_ML Exn.reraise: "exn -> 'a"} \\ - @{index_ML Runtime.exn_trace: "(unit -> 'a) -> 'a"} \\ + @{define_ML try: "('a -> 'b) -> 'a -> 'b option"} \\ + @{define_ML can: "('a -> 'b) -> 'a -> bool"} \\ + @{define_ML_exception ERROR of string} \\ + @{define_ML_exception Fail of string} \\ + @{define_ML Exn.is_interrupt: "exn -> bool"} \\ + @{define_ML Exn.reraise: "exn -> 'a"} \\ + @{define_ML Runtime.exn_trace: "(unit -> 'a) -> 'a"} \\ \end{mldecls} \<^rail>\ @@ -1284,16 +1284,16 @@ text %mlref \ \begin{mldecls} - @{index_ML_type "Symbol.symbol": string} \\ - @{index_ML Symbol.explode: "string -> Symbol.symbol list"} \\ - @{index_ML Symbol.is_letter: "Symbol.symbol -> bool"} \\ - @{index_ML Symbol.is_digit: "Symbol.symbol -> bool"} \\ - @{index_ML Symbol.is_quasi: "Symbol.symbol -> bool"} \\ - @{index_ML Symbol.is_blank: "Symbol.symbol -> bool"} \\ + @{define_ML_type Symbol.symbol = string} \\ + @{define_ML Symbol.explode: "string -> Symbol.symbol list"} \\ + @{define_ML Symbol.is_letter: "Symbol.symbol -> bool"} \\ + @{define_ML Symbol.is_digit: "Symbol.symbol -> bool"} \\ + @{define_ML Symbol.is_quasi: "Symbol.symbol -> bool"} \\ + @{define_ML Symbol.is_blank: "Symbol.symbol -> bool"} \\ \end{mldecls} \begin{mldecls} - @{index_ML_type "Symbol.sym"} \\ - @{index_ML Symbol.decode: "Symbol.symbol -> Symbol.sym"} \\ + @{define_ML_type "Symbol.sym"} \\ + @{define_ML Symbol.decode: "Symbol.symbol -> Symbol.sym"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\Symbol.symbol\ represents individual Isabelle symbols. @@ -1347,7 +1347,7 @@ text %mlref \ \begin{mldecls} - @{index_ML_type char} \\ + @{define_ML_type char} \\ \end{mldecls} \<^descr> Type \<^ML_type>\char\ is \<^emph>\not\ used. The smallest textual unit in Isabelle @@ -1359,7 +1359,7 @@ text %mlref \ \begin{mldecls} - @{index_ML_type string} \\ + @{define_ML_type string} \\ \end{mldecls} \<^descr> Type \<^ML_type>\string\ represents immutable vectors of 8-bit characters. @@ -1407,7 +1407,7 @@ text %mlref \ \begin{mldecls} - @{index_ML_type int} \\ + @{define_ML_type int} \\ \end{mldecls} \<^descr> Type \<^ML_type>\int\ represents regular mathematical integers, which are @@ -1425,7 +1425,7 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Rat.rat} \\ + @{define_ML_type Rat.rat} \\ \end{mldecls} \<^descr> Type \<^ML_type>\Rat.rat\ represents rational numbers, based on the @@ -1444,8 +1444,8 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Time.time} \\ - @{index_ML seconds: "real -> Time.time"} \\ + @{define_ML_type Time.time} \\ + @{define_ML seconds: "real -> Time.time"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\Time.time\ represents time abstractly according to the @@ -1463,13 +1463,13 @@ text %mlref \ \begin{mldecls} - @{index_ML Option.map: "('a -> 'b) -> 'a option -> 'b option"} \\ - @{index_ML is_some: "'a option -> bool"} \\ - @{index_ML is_none: "'a option -> bool"} \\ - @{index_ML the: "'a option -> 'a"} \\ - @{index_ML these: "'a list option -> 'a list"} \\ - @{index_ML the_list: "'a option -> 'a list"} \\ - @{index_ML the_default: "'a -> 'a option -> 'a"} \\ + @{define_ML Option.map: "('a -> 'b) -> 'a option -> 'b option"} \\ + @{define_ML is_some: "'a option -> bool"} \\ + @{define_ML is_none: "'a option -> bool"} \\ + @{define_ML the: "'a option -> 'a"} \\ + @{define_ML these: "'a list option -> 'a list"} \\ + @{define_ML the_list: "'a option -> 'a list"} \\ + @{define_ML the_default: "'a -> 'a option -> 'a"} \\ \end{mldecls} \ @@ -1490,11 +1490,11 @@ text %mlref \ \begin{mldecls} - @{index_ML cons: "'a -> 'a list -> 'a list"} \\ - @{index_ML member: "('b * 'a -> bool) -> 'a list -> 'b -> bool"} \\ - @{index_ML insert: "('a * 'a -> bool) -> 'a -> 'a list -> 'a list"} \\ - @{index_ML remove: "('b * 'a -> bool) -> 'b -> 'a list -> 'a list"} \\ - @{index_ML update: "('a * 'a -> bool) -> 'a -> 'a list -> 'a list"} \\ + @{define_ML cons: "'a -> 'a list -> 'a list"} \\ + @{define_ML member: "('b * 'a -> bool) -> 'a list -> 'b -> bool"} \\ + @{define_ML insert: "('a * 'a -> bool) -> 'a -> 'a list -> 'a list"} \\ + @{define_ML remove: "('b * 'a -> bool) -> 'b -> 'a list -> 'a list"} \\ + @{define_ML update: "('a * 'a -> bool) -> 'a -> 'a list -> 'a list"} \\ \end{mldecls} \<^descr> \<^ML>\cons\~\x xs\ evaluates to \x :: xs\. @@ -1563,9 +1563,9 @@ text \ \begin{mldecls} - @{index_ML AList.lookup: "('a * 'b -> bool) -> ('b * 'c) list -> 'a -> 'c option"} \\ - @{index_ML AList.defined: "('a * 'b -> bool) -> ('b * 'c) list -> 'a -> bool"} \\ - @{index_ML AList.update: "('a * 'a -> bool) -> 'a * 'b -> ('a * 'b) list -> ('a * 'b) list"} \\ + @{define_ML AList.lookup: "('a * 'b -> bool) -> ('b * 'c) list -> 'a -> 'c option"} \\ + @{define_ML AList.defined: "('a * 'b -> bool) -> ('b * 'c) list -> 'a -> bool"} \\ + @{define_ML AList.update: "('a * 'a -> bool) -> 'a * 'b -> ('a * 'b) list -> ('a * 'b) list"} \\ \end{mldecls} \<^descr> \<^ML>\AList.lookup\, \<^ML>\AList.defined\, \<^ML>\AList.update\ implement the @@ -1593,10 +1593,10 @@ text %mlref \ \begin{mldecls} - @{index_ML_type "'a Unsynchronized.ref"} \\ - @{index_ML Unsynchronized.ref: "'a -> 'a Unsynchronized.ref"} \\ - @{index_ML "!": "'a Unsynchronized.ref -> 'a"} \\ - @{index_ML_op ":=": "'a Unsynchronized.ref * 'a -> unit"} \\ + @{define_ML_type 'a "Unsynchronized.ref"} \\ + @{define_ML Unsynchronized.ref: "'a -> 'a Unsynchronized.ref"} \\ + @{define_ML "!": "'a Unsynchronized.ref -> 'a"} \\ + @{define_ML_infix ":=" : "'a Unsynchronized.ref * 'a -> unit"} \\ \end{mldecls} \ @@ -1608,7 +1608,7 @@ The unwieldy name of \<^ML>\Unsynchronized.ref\ for the constructor for references in Isabelle/ML emphasizes the inconveniences caused by - mutability. Existing operations \<^ML>\!\ and \<^ML_op>\:=\ are unchanged, + mutability. Existing operations \<^ML>\!\ and \<^ML_infix>\:=\ are unchanged, but should be used with special precautions, say in a strictly local situation that is guaranteed to be restricted to sequential evaluation --- now and in the future. @@ -1748,8 +1748,8 @@ text %mlref \ \begin{mldecls} - @{index_ML File.tmp_path: "Path.T -> Path.T"} \\ - @{index_ML serial_string: "unit -> string"} \\ + @{define_ML File.tmp_path: "Path.T -> Path.T"} \\ + @{define_ML serial_string: "unit -> string"} \\ \end{mldecls} \<^descr> \<^ML>\File.tmp_path\~\path\ relocates the base component of \path\ into the @@ -1790,9 +1790,9 @@ text %mlref \ \begin{mldecls} - @{index_ML_type "'a Synchronized.var"} \\ - @{index_ML Synchronized.var: "string -> 'a -> 'a Synchronized.var"} \\ - @{index_ML Synchronized.guarded_access: "'a Synchronized.var -> + @{define_ML_type 'a "Synchronized.var"} \\ + @{define_ML Synchronized.var: "string -> 'a -> 'a Synchronized.var"} \\ + @{define_ML Synchronized.guarded_access: "'a Synchronized.var -> ('a -> ('b * 'a) option) -> 'b"} \\ \end{mldecls} @@ -1890,12 +1890,12 @@ text %mlref \ \begin{mldecls} - @{index_ML_type "'a Exn.result"} \\ - @{index_ML Exn.capture: "('a -> 'b) -> 'a -> 'b Exn.result"} \\ - @{index_ML Exn.interruptible_capture: "('a -> 'b) -> 'a -> 'b Exn.result"} \\ - @{index_ML Exn.release: "'a Exn.result -> 'a"} \\ - @{index_ML Par_Exn.release_all: "'a Exn.result list -> 'a list"} \\ - @{index_ML Par_Exn.release_first: "'a Exn.result list -> 'a list"} \\ + @{define_ML_type 'a "Exn.result"} \\ + @{define_ML Exn.capture: "('a -> 'b) -> 'a -> 'b Exn.result"} \\ + @{define_ML Exn.interruptible_capture: "('a -> 'b) -> 'a -> 'b Exn.result"} \\ + @{define_ML Exn.release: "'a Exn.result -> 'a"} \\ + @{define_ML Par_Exn.release_all: "'a Exn.result list -> 'a list"} \\ + @{define_ML Par_Exn.release_first: "'a Exn.result list -> 'a list"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\'a Exn.result\ represents the disjoint sum of ML results @@ -1945,8 +1945,8 @@ text %mlref \ \begin{mldecls} - @{index_ML Par_List.map: "('a -> 'b) -> 'a list -> 'b list"} \\ - @{index_ML Par_List.get_some: "('a -> 'b option) -> 'a list -> 'b option"} \\ + @{define_ML Par_List.map: "('a -> 'b) -> 'a list -> 'b list"} \\ + @{define_ML Par_List.get_some: "('a -> 'b option) -> 'a list -> 'b option"} \\ \end{mldecls} \<^descr> \<^ML>\Par_List.map\~\f [x\<^sub>1, \, x\<^sub>n]\ is like \<^ML>\map\~\f [x\<^sub>1, \, @@ -2009,10 +2009,10 @@ text %mlref \ \begin{mldecls} - @{index_ML_type "'a lazy"} \\ - @{index_ML Lazy.lazy: "(unit -> 'a) -> 'a lazy"} \\ - @{index_ML Lazy.value: "'a -> 'a lazy"} \\ - @{index_ML Lazy.force: "'a lazy -> 'a"} \\ + @{define_ML_type 'a "lazy"} \\ + @{define_ML Lazy.lazy: "(unit -> 'a) -> 'a lazy"} \\ + @{define_ML Lazy.value: "'a -> 'a lazy"} \\ + @{define_ML Lazy.force: "'a lazy -> 'a"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\'a lazy\ represents lazy values over type \<^verbatim>\'a\. @@ -2090,17 +2090,17 @@ text %mlref \ \begin{mldecls} - @{index_ML_type "'a future"} \\ - @{index_ML Future.fork: "(unit -> 'a) -> 'a future"} \\ - @{index_ML Future.forks: "Future.params -> (unit -> 'a) list -> 'a future list"} \\ - @{index_ML Future.join: "'a future -> 'a"} \\ - @{index_ML Future.joins: "'a future list -> 'a list"} \\ - @{index_ML Future.value: "'a -> 'a future"} \\ - @{index_ML Future.map: "('a -> 'b) -> 'a future -> 'b future"} \\ - @{index_ML Future.cancel: "'a future -> unit"} \\ - @{index_ML Future.cancel_group: "Future.group -> unit"} \\[0.5ex] - @{index_ML Future.promise: "(unit -> unit) -> 'a future"} \\ - @{index_ML Future.fulfill: "'a future -> 'a -> unit"} \\ + @{define_ML_type 'a "future"} \\ + @{define_ML Future.fork: "(unit -> 'a) -> 'a future"} \\ + @{define_ML Future.forks: "Future.params -> (unit -> 'a) list -> 'a future list"} \\ + @{define_ML Future.join: "'a future -> 'a"} \\ + @{define_ML Future.joins: "'a future list -> 'a list"} \\ + @{define_ML Future.value: "'a -> 'a future"} \\ + @{define_ML Future.map: "('a -> 'b) -> 'a future -> 'b future"} \\ + @{define_ML Future.cancel: "'a future -> unit"} \\ + @{define_ML Future.cancel_group: "Future.group -> unit"} \\[0.5ex] + @{define_ML Future.promise: "(unit -> unit) -> 'a future"} \\ + @{define_ML Future.fulfill: "'a future -> 'a -> unit"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\'a future\ represents future values over type \<^verbatim>\'a\. diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Prelim.thy --- a/src/Doc/Implementation/Prelim.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Prelim.thy Sun May 23 20:34:43 2021 +0200 @@ -108,12 +108,12 @@ text %mlref \ \begin{mldecls} - @{index_ML_type theory} \\ - @{index_ML Context.eq_thy: "theory * theory -> bool"} \\ - @{index_ML Context.subthy: "theory * theory -> bool"} \\ - @{index_ML Theory.begin_theory: "string * Position.T -> theory list -> theory"} \\ - @{index_ML Theory.parents_of: "theory -> theory list"} \\ - @{index_ML Theory.ancestors_of: "theory -> theory list"} \\ + @{define_ML_type theory} \\ + @{define_ML Context.eq_thy: "theory * theory -> bool"} \\ + @{define_ML Context.subthy: "theory * theory -> bool"} \\ + @{define_ML Theory.begin_theory: "string * Position.T -> theory list -> theory"} \\ + @{define_ML Theory.parents_of: "theory -> theory list"} \\ + @{define_ML Theory.ancestors_of: "theory -> theory list"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\theory\ represents theory contexts. @@ -187,10 +187,10 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Proof.context} \\ - @{index_ML Proof_Context.init_global: "theory -> Proof.context"} \\ - @{index_ML Proof_Context.theory_of: "Proof.context -> theory"} \\ - @{index_ML Proof_Context.transfer: "theory -> Proof.context -> Proof.context"} \\ + @{define_ML_type Proof.context} \\ + @{define_ML Proof_Context.init_global: "theory -> Proof.context"} \\ + @{define_ML Proof_Context.theory_of: "Proof.context -> theory"} \\ + @{define_ML Proof_Context.transfer: "theory -> Proof.context -> Proof.context"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\Proof.context\ represents proof contexts. @@ -236,9 +236,9 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Context.generic} \\ - @{index_ML Context.theory_of: "Context.generic -> theory"} \\ - @{index_ML Context.proof_of: "Context.generic -> Proof.context"} \\ + @{define_ML_type Context.generic} \\ + @{define_ML Context.theory_of: "Context.generic -> theory"} \\ + @{define_ML Context.proof_of: "Context.generic -> Proof.context"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\Context.generic\ is the direct sum of \<^ML_type>\theory\ @@ -339,9 +339,9 @@ text %mlref \ \begin{mldecls} - @{index_ML_functor Theory_Data} \\ - @{index_ML_functor Proof_Data} \\ - @{index_ML_functor Generic_Data} \\ + @{define_ML_functor Theory_Data} \\ + @{define_ML_functor Proof_Data} \\ + @{define_ML_functor Generic_Data} \\ \end{mldecls} \<^descr> \<^ML_functor>\Theory_Data\\(spec)\ declares data for type \<^ML_type>\theory\ @@ -482,15 +482,15 @@ text %mlref \ \begin{mldecls} - @{index_ML Config.get: "Proof.context -> 'a Config.T -> 'a"} \\ - @{index_ML Config.map: "'a Config.T -> ('a -> 'a) -> Proof.context -> Proof.context"} \\ - @{index_ML Attrib.setup_config_bool: "binding -> (Context.generic -> bool) -> + @{define_ML Config.get: "Proof.context -> 'a Config.T -> 'a"} \\ + @{define_ML Config.map: "'a Config.T -> ('a -> 'a) -> Proof.context -> Proof.context"} \\ + @{define_ML Attrib.setup_config_bool: "binding -> (Context.generic -> bool) -> bool Config.T"} \\ - @{index_ML Attrib.setup_config_int: "binding -> (Context.generic -> int) -> + @{define_ML Attrib.setup_config_int: "binding -> (Context.generic -> int) -> int Config.T"} \\ - @{index_ML Attrib.setup_config_real: "binding -> (Context.generic -> real) -> + @{define_ML Attrib.setup_config_real: "binding -> (Context.generic -> real) -> real Config.T"} \\ - @{index_ML Attrib.setup_config_string: "binding -> (Context.generic -> string) -> + @{define_ML Attrib.setup_config_string: "binding -> (Context.generic -> string) -> string Config.T"} \\ \end{mldecls} @@ -613,18 +613,18 @@ text %mlref \ \begin{mldecls} - @{index_ML Name.internal: "string -> string"} \\ - @{index_ML Name.skolem: "string -> string"} \\ + @{define_ML Name.internal: "string -> string"} \\ + @{define_ML Name.skolem: "string -> string"} \\ \end{mldecls} \begin{mldecls} - @{index_ML_type Name.context} \\ - @{index_ML Name.context: Name.context} \\ - @{index_ML Name.declare: "string -> Name.context -> Name.context"} \\ - @{index_ML Name.invent: "Name.context -> string -> int -> string list"} \\ - @{index_ML Name.variant: "string -> Name.context -> string * Name.context"} \\ + @{define_ML_type Name.context} \\ + @{define_ML Name.context: Name.context} \\ + @{define_ML Name.declare: "string -> Name.context -> Name.context"} \\ + @{define_ML Name.invent: "Name.context -> string -> int -> string list"} \\ + @{define_ML Name.variant: "string -> Name.context -> string * Name.context"} \\ \end{mldecls} \begin{mldecls} - @{index_ML Variable.names_of: "Proof.context -> Name.context"} \\ + @{define_ML Variable.names_of: "Proof.context -> Name.context"} \\ \end{mldecls} \<^descr> \<^ML>\Name.internal\~\name\ produces an internal name by adding one @@ -720,7 +720,7 @@ text %mlref \ \begin{mldecls} - @{index_ML_type indexname: "string * int"} \\ + @{define_ML_type indexname = "string * int"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\indexname\ represents indexed names. This is an @@ -755,11 +755,11 @@ text %mlref \ \begin{mldecls} - @{index_ML Long_Name.base_name: "string -> string"} \\ - @{index_ML Long_Name.qualifier: "string -> string"} \\ - @{index_ML Long_Name.append: "string -> string -> string"} \\ - @{index_ML Long_Name.implode: "string list -> string"} \\ - @{index_ML Long_Name.explode: "string -> string list"} \\ + @{define_ML Long_Name.base_name: "string -> string"} \\ + @{define_ML Long_Name.qualifier: "string -> string"} \\ + @{define_ML Long_Name.append: "string -> string -> string"} \\ + @{define_ML Long_Name.implode: "string list -> string"} \\ + @{define_ML Long_Name.explode: "string -> string list"} \\ \end{mldecls} \<^descr> \<^ML>\Long_Name.base_name\~\name\ returns the base name of a long name. @@ -832,29 +832,29 @@ text %mlref \ \begin{mldecls} - @{index_ML_type binding} \\ - @{index_ML Binding.empty: binding} \\ - @{index_ML Binding.name: "string -> binding"} \\ - @{index_ML Binding.qualify: "bool -> string -> binding -> binding"} \\ - @{index_ML Binding.prefix: "bool -> string -> binding -> binding"} \\ - @{index_ML Binding.concealed: "binding -> binding"} \\ - @{index_ML Binding.print: "binding -> string"} \\ + @{define_ML_type binding} \\ + @{define_ML Binding.empty: binding} \\ + @{define_ML Binding.name: "string -> binding"} \\ + @{define_ML Binding.qualify: "bool -> string -> binding -> binding"} \\ + @{define_ML Binding.prefix: "bool -> string -> binding -> binding"} \\ + @{define_ML Binding.concealed: "binding -> binding"} \\ + @{define_ML Binding.print: "binding -> string"} \\ \end{mldecls} \begin{mldecls} - @{index_ML_type Name_Space.naming} \\ - @{index_ML Name_Space.global_naming: Name_Space.naming} \\ - @{index_ML Name_Space.add_path: "string -> Name_Space.naming -> Name_Space.naming"} \\ - @{index_ML Name_Space.full_name: "Name_Space.naming -> binding -> string"} \\ + @{define_ML_type Name_Space.naming} \\ + @{define_ML Name_Space.global_naming: Name_Space.naming} \\ + @{define_ML Name_Space.add_path: "string -> Name_Space.naming -> Name_Space.naming"} \\ + @{define_ML Name_Space.full_name: "Name_Space.naming -> binding -> string"} \\ \end{mldecls} \begin{mldecls} - @{index_ML_type Name_Space.T} \\ - @{index_ML Name_Space.empty: "string -> Name_Space.T"} \\ - @{index_ML Name_Space.merge: "Name_Space.T * Name_Space.T -> Name_Space.T"} \\ - @{index_ML Name_Space.declare: "Context.generic -> bool -> + @{define_ML_type Name_Space.T} \\ + @{define_ML Name_Space.empty: "string -> Name_Space.T"} \\ + @{define_ML Name_Space.merge: "Name_Space.T * Name_Space.T -> Name_Space.T"} \\ + @{define_ML Name_Space.declare: "Context.generic -> bool -> binding -> Name_Space.T -> string * Name_Space.T"} \\ - @{index_ML Name_Space.intern: "Name_Space.T -> string -> string"} \\ - @{index_ML Name_Space.extern: "Proof.context -> Name_Space.T -> string -> string"} \\ - @{index_ML Name_Space.is_concealed: "Name_Space.T -> string -> bool"} + @{define_ML Name_Space.intern: "Name_Space.T -> string -> string"} \\ + @{define_ML Name_Space.extern: "Proof.context -> Name_Space.T -> string -> string"} \\ + @{define_ML Name_Space.is_concealed: "Name_Space.T -> string -> bool"} \end{mldecls} \<^descr> Type \<^ML_type>\binding\ represents the abstract concept of name bindings. diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Proof.thy --- a/src/Doc/Implementation/Proof.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Proof.thy Sun May 23 20:34:43 2021 +0200 @@ -92,18 +92,18 @@ text %mlref \ \begin{mldecls} - @{index_ML Variable.add_fixes: " + @{define_ML Variable.add_fixes: " string list -> Proof.context -> string list * Proof.context"} \\ - @{index_ML Variable.variant_fixes: " + @{define_ML Variable.variant_fixes: " string list -> Proof.context -> string list * Proof.context"} \\ - @{index_ML Variable.declare_term: "term -> Proof.context -> Proof.context"} \\ - @{index_ML Variable.declare_constraints: "term -> Proof.context -> Proof.context"} \\ - @{index_ML Variable.export: "Proof.context -> Proof.context -> thm list -> thm list"} \\ - @{index_ML Variable.polymorphic: "Proof.context -> term list -> term list"} \\ - @{index_ML Variable.import: "bool -> thm list -> Proof.context -> + @{define_ML Variable.declare_term: "term -> Proof.context -> Proof.context"} \\ + @{define_ML Variable.declare_constraints: "term -> Proof.context -> Proof.context"} \\ + @{define_ML Variable.export: "Proof.context -> Proof.context -> thm list -> thm list"} \\ + @{define_ML Variable.polymorphic: "Proof.context -> term list -> term list"} \\ + @{define_ML Variable.import: "bool -> thm list -> Proof.context -> ((((indexname * sort) * ctyp) list * ((indexname * typ) * cterm) list) * thm list) * Proof.context"} \\ - @{index_ML Variable.focus: "binding list option -> term -> Proof.context -> + @{define_ML Variable.focus: "binding list option -> term -> Proof.context -> ((string * (string * typ)) list * term) * Proof.context"} \\ \end{mldecls} @@ -263,14 +263,14 @@ text %mlref \ \begin{mldecls} - @{index_ML_type Assumption.export} \\ - @{index_ML Assumption.assume: "Proof.context -> cterm -> thm"} \\ - @{index_ML Assumption.add_assms: + @{define_ML_type Assumption.export} \\ + @{define_ML Assumption.assume: "Proof.context -> cterm -> thm"} \\ + @{define_ML Assumption.add_assms: "Assumption.export -> cterm list -> Proof.context -> thm list * Proof.context"} \\ - @{index_ML Assumption.add_assumes: " + @{define_ML Assumption.add_assumes: " cterm list -> Proof.context -> thm list * Proof.context"} \\ - @{index_ML Assumption.export: "bool -> Proof.context -> Proof.context -> thm -> thm"} \\ + @{define_ML Assumption.export: "bool -> Proof.context -> Proof.context -> thm -> thm"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\Assumption.export\ represents arbitrary export rules, which @@ -359,31 +359,31 @@ text %mlref \ \begin{mldecls} - @{index_ML SUBPROOF: "(Subgoal.focus -> tactic) -> + @{define_ML SUBPROOF: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\ - @{index_ML Subgoal.FOCUS: "(Subgoal.focus -> tactic) -> + @{define_ML Subgoal.FOCUS: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\ - @{index_ML Subgoal.FOCUS_PREMS: "(Subgoal.focus -> tactic) -> + @{define_ML Subgoal.FOCUS_PREMS: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\ - @{index_ML Subgoal.FOCUS_PARAMS: "(Subgoal.focus -> tactic) -> + @{define_ML Subgoal.FOCUS_PARAMS: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\ - @{index_ML Subgoal.focus: "Proof.context -> int -> binding list option -> + @{define_ML Subgoal.focus: "Proof.context -> int -> binding list option -> thm -> Subgoal.focus * thm"} \\ - @{index_ML Subgoal.focus_prems: "Proof.context -> int -> binding list option -> + @{define_ML Subgoal.focus_prems: "Proof.context -> int -> binding list option -> thm -> Subgoal.focus * thm"} \\ - @{index_ML Subgoal.focus_params: "Proof.context -> int -> binding list option -> + @{define_ML Subgoal.focus_params: "Proof.context -> int -> binding list option -> thm -> Subgoal.focus * thm"} \\ \end{mldecls} \begin{mldecls} - @{index_ML Goal.prove: "Proof.context -> string list -> term list -> term -> + @{define_ML Goal.prove: "Proof.context -> string list -> term list -> term -> ({prems: thm list, context: Proof.context} -> tactic) -> thm"} \\ - @{index_ML Goal.prove_common: "Proof.context -> int option -> + @{define_ML Goal.prove_common: "Proof.context -> int option -> string list -> term list -> term list -> ({prems: thm list, context: Proof.context} -> tactic) -> thm list"} \\ \end{mldecls} \begin{mldecls} - @{index_ML Obtain.result: "(Proof.context -> tactic) -> thm list -> + @{define_ML Obtain.result: "(Proof.context -> tactic) -> thm list -> Proof.context -> ((string * cterm) list * thm list) * Proof.context"} \\ \end{mldecls} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Syntax.thy --- a/src/Doc/Implementation/Syntax.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Syntax.thy Sun May 23 20:34:43 2021 +0200 @@ -69,16 +69,16 @@ text %mlref \ \begin{mldecls} - @{index_ML Syntax.read_typs: "Proof.context -> string list -> typ list"} \\ - @{index_ML Syntax.read_terms: "Proof.context -> string list -> term list"} \\ - @{index_ML Syntax.read_props: "Proof.context -> string list -> term list"} \\[0.5ex] - @{index_ML Syntax.read_typ: "Proof.context -> string -> typ"} \\ - @{index_ML Syntax.read_term: "Proof.context -> string -> term"} \\ - @{index_ML Syntax.read_prop: "Proof.context -> string -> term"} \\[0.5ex] - @{index_ML Syntax.pretty_typ: "Proof.context -> typ -> Pretty.T"} \\ - @{index_ML Syntax.pretty_term: "Proof.context -> term -> Pretty.T"} \\ - @{index_ML Syntax.string_of_typ: "Proof.context -> typ -> string"} \\ - @{index_ML Syntax.string_of_term: "Proof.context -> term -> string"} \\ + @{define_ML Syntax.read_typs: "Proof.context -> string list -> typ list"} \\ + @{define_ML Syntax.read_terms: "Proof.context -> string list -> term list"} \\ + @{define_ML Syntax.read_props: "Proof.context -> string list -> term list"} \\[0.5ex] + @{define_ML Syntax.read_typ: "Proof.context -> string -> typ"} \\ + @{define_ML Syntax.read_term: "Proof.context -> string -> term"} \\ + @{define_ML Syntax.read_prop: "Proof.context -> string -> term"} \\[0.5ex] + @{define_ML Syntax.pretty_typ: "Proof.context -> typ -> Pretty.T"} \\ + @{define_ML Syntax.pretty_term: "Proof.context -> term -> Pretty.T"} \\ + @{define_ML Syntax.string_of_typ: "Proof.context -> typ -> string"} \\ + @{define_ML Syntax.string_of_term: "Proof.context -> term -> string"} \\ \end{mldecls} \<^descr> \<^ML>\Syntax.read_typs\~\ctxt strs\ parses and checks a simultaneous list @@ -158,11 +158,11 @@ text %mlref \ \begin{mldecls} - @{index_ML Syntax.parse_typ: "Proof.context -> string -> typ"} \\ - @{index_ML Syntax.parse_term: "Proof.context -> string -> term"} \\ - @{index_ML Syntax.parse_prop: "Proof.context -> string -> term"} \\[0.5ex] - @{index_ML Syntax.unparse_typ: "Proof.context -> typ -> Pretty.T"} \\ - @{index_ML Syntax.unparse_term: "Proof.context -> term -> Pretty.T"} \\ + @{define_ML Syntax.parse_typ: "Proof.context -> string -> typ"} \\ + @{define_ML Syntax.parse_term: "Proof.context -> string -> term"} \\ + @{define_ML Syntax.parse_prop: "Proof.context -> string -> term"} \\[0.5ex] + @{define_ML Syntax.unparse_typ: "Proof.context -> typ -> Pretty.T"} \\ + @{define_ML Syntax.unparse_term: "Proof.context -> term -> Pretty.T"} \\ \end{mldecls} \<^descr> \<^ML>\Syntax.parse_typ\~\ctxt str\ parses a source string as pre-type that @@ -219,11 +219,11 @@ text %mlref \ \begin{mldecls} - @{index_ML Syntax.check_typs: "Proof.context -> typ list -> typ list"} \\ - @{index_ML Syntax.check_terms: "Proof.context -> term list -> term list"} \\ - @{index_ML Syntax.check_props: "Proof.context -> term list -> term list"} \\[0.5ex] - @{index_ML Syntax.uncheck_typs: "Proof.context -> typ list -> typ list"} \\ - @{index_ML Syntax.uncheck_terms: "Proof.context -> term list -> term list"} \\ + @{define_ML Syntax.check_typs: "Proof.context -> typ list -> typ list"} \\ + @{define_ML Syntax.check_terms: "Proof.context -> term list -> term list"} \\ + @{define_ML Syntax.check_props: "Proof.context -> term list -> term list"} \\[0.5ex] + @{define_ML Syntax.uncheck_typs: "Proof.context -> typ list -> typ list"} \\ + @{define_ML Syntax.uncheck_terms: "Proof.context -> term list -> term list"} \\ \end{mldecls} \<^descr> \<^ML>\Syntax.check_typs\~\ctxt Ts\ checks a simultaneous list of pre-types diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/Tactic.thy --- a/src/Doc/Implementation/Tactic.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/Tactic.thy Sun May 23 20:34:43 2021 +0200 @@ -61,10 +61,10 @@ text %mlref \ \begin{mldecls} - @{index_ML Goal.init: "cterm -> thm"} \\ - @{index_ML Goal.finish: "Proof.context -> thm -> thm"} \\ - @{index_ML Goal.protect: "int -> thm -> thm"} \\ - @{index_ML Goal.conclude: "thm -> thm"} \\ + @{define_ML Goal.init: "cterm -> thm"} \\ + @{define_ML Goal.finish: "Proof.context -> thm -> thm"} \\ + @{define_ML Goal.protect: "int -> thm -> thm"} \\ + @{define_ML Goal.conclude: "thm -> thm"} \\ \end{mldecls} \<^descr> \<^ML>\Goal.init\~\C\ initializes a tactical goal from the well-formed @@ -156,15 +156,15 @@ text %mlref \ \begin{mldecls} - @{index_ML_type tactic: "thm -> thm Seq.seq"} \\ - @{index_ML no_tac: tactic} \\ - @{index_ML all_tac: tactic} \\ - @{index_ML print_tac: "Proof.context -> string -> tactic"} \\[1ex] - @{index_ML PRIMITIVE: "(thm -> thm) -> tactic"} \\[1ex] - @{index_ML SUBGOAL: "(term * int -> tactic) -> int -> tactic"} \\ - @{index_ML CSUBGOAL: "(cterm * int -> tactic) -> int -> tactic"} \\ - @{index_ML SELECT_GOAL: "tactic -> int -> tactic"} \\ - @{index_ML PREFER_GOAL: "tactic -> int -> tactic"} \\ + @{define_ML_type tactic = "thm -> thm Seq.seq"} \\ + @{define_ML no_tac: tactic} \\ + @{define_ML all_tac: tactic} \\ + @{define_ML print_tac: "Proof.context -> string -> tactic"} \\[1ex] + @{define_ML PRIMITIVE: "(thm -> thm) -> tactic"} \\[1ex] + @{define_ML SUBGOAL: "(term * int -> tactic) -> int -> tactic"} \\ + @{define_ML CSUBGOAL: "(cterm * int -> tactic) -> int -> tactic"} \\ + @{define_ML SELECT_GOAL: "tactic -> int -> tactic"} \\ + @{define_ML PREFER_GOAL: "tactic -> int -> tactic"} \\ \end{mldecls} \<^descr> Type \<^ML_type>\tactic\ represents tactics. The well-formedness conditions @@ -243,17 +243,17 @@ text %mlref \ \begin{mldecls} - @{index_ML resolve_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML eresolve_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML dresolve_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML forward_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML biresolve_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\[1ex] - @{index_ML assume_tac: "Proof.context -> int -> tactic"} \\ - @{index_ML eq_assume_tac: "int -> tactic"} \\[1ex] - @{index_ML match_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML ematch_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML dmatch_tac: "Proof.context -> thm list -> int -> tactic"} \\ - @{index_ML bimatch_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\ + @{define_ML resolve_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML eresolve_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML dresolve_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML forward_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML biresolve_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\[1ex] + @{define_ML assume_tac: "Proof.context -> int -> tactic"} \\ + @{define_ML eq_assume_tac: "int -> tactic"} \\[1ex] + @{define_ML match_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML ematch_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML dmatch_tac: "Proof.context -> thm list -> int -> tactic"} \\ + @{define_ML bimatch_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\resolve_tac\~\ctxt thms i\ refines the goal state using the given @@ -351,23 +351,23 @@ text %mlref \ \begin{mldecls} - @{index_ML Rule_Insts.res_inst_tac: "Proof.context -> + @{define_ML Rule_Insts.res_inst_tac: "Proof.context -> ((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> thm -> int -> tactic"} \\ - @{index_ML Rule_Insts.eres_inst_tac: "Proof.context -> + @{define_ML Rule_Insts.eres_inst_tac: "Proof.context -> ((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> thm -> int -> tactic"} \\ - @{index_ML Rule_Insts.dres_inst_tac: "Proof.context -> + @{define_ML Rule_Insts.dres_inst_tac: "Proof.context -> ((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> thm -> int -> tactic"} \\ - @{index_ML Rule_Insts.forw_inst_tac: "Proof.context -> + @{define_ML Rule_Insts.forw_inst_tac: "Proof.context -> ((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> thm -> int -> tactic"} \\ - @{index_ML Rule_Insts.subgoal_tac: "Proof.context -> string -> + @{define_ML Rule_Insts.subgoal_tac: "Proof.context -> string -> (binding * string option * mixfix) list -> int -> tactic"} \\ - @{index_ML Rule_Insts.thin_tac: "Proof.context -> string -> + @{define_ML Rule_Insts.thin_tac: "Proof.context -> string -> (binding * string option * mixfix) list -> int -> tactic"} \\ - @{index_ML rename_tac: "string list -> int -> tactic"} \\ + @{define_ML rename_tac: "string list -> int -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\Rule_Insts.res_inst_tac\~\ctxt insts thm i\ instantiates the rule @@ -415,9 +415,9 @@ text %mlref \ \begin{mldecls} - @{index_ML rotate_tac: "int -> int -> tactic"} \\ - @{index_ML distinct_subgoals_tac: tactic} \\ - @{index_ML flexflex_tac: "Proof.context -> tactic"} \\ + @{define_ML rotate_tac: "int -> int -> tactic"} \\ + @{define_ML distinct_subgoals_tac: tactic} \\ + @{define_ML flexflex_tac: "Proof.context -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\rotate_tac\~\n i\ rotates the premises of subgoal \i\ by \n\ @@ -450,9 +450,9 @@ text %mlref \ \begin{mldecls} - @{index_ML compose_tac: "Proof.context -> (bool * thm * int) -> int -> tactic"} \\ - @{index_ML Drule.compose: "thm * int * thm -> thm"} \\ - @{index_ML_op COMP: "thm * thm -> thm"} \\ + @{define_ML compose_tac: "Proof.context -> (bool * thm * int) -> int -> tactic"} \\ + @{define_ML Drule.compose: "thm * int * thm -> thm"} \\ + @{define_ML_infix COMP: "thm * thm -> thm"} \\ \end{mldecls} \<^descr> \<^ML>\compose_tac\~\ctxt (flag, rule, m) i\ refines subgoal \i\ using @@ -494,53 +494,53 @@ text \ Sequential composition and alternative choices are the most basic ways to combine tactics, similarly to ``\<^verbatim>\,\'' and ``\<^verbatim>\|\'' in Isar method notation. - This corresponds to \<^ML_op>\THEN\ and \<^ML_op>\ORELSE\ in ML, but there + This corresponds to \<^ML_infix>\THEN\ and \<^ML_infix>\ORELSE\ in ML, but there are further possibilities for fine-tuning alternation of tactics such as - \<^ML_op>\APPEND\. Further details become visible in ML due to explicit + \<^ML_infix>\APPEND\. Further details become visible in ML due to explicit subgoal addressing. \ text %mlref \ \begin{mldecls} - @{index_ML_op "THEN": "tactic * tactic -> tactic"} \\ - @{index_ML_op "ORELSE": "tactic * tactic -> tactic"} \\ - @{index_ML_op "APPEND": "tactic * tactic -> tactic"} \\ - @{index_ML "EVERY": "tactic list -> tactic"} \\ - @{index_ML "FIRST": "tactic list -> tactic"} \\[0.5ex] + @{define_ML_infix "THEN": "tactic * tactic -> tactic"} \\ + @{define_ML_infix "ORELSE": "tactic * tactic -> tactic"} \\ + @{define_ML_infix "APPEND": "tactic * tactic -> tactic"} \\ + @{define_ML "EVERY": "tactic list -> tactic"} \\ + @{define_ML "FIRST": "tactic list -> tactic"} \\[0.5ex] - @{index_ML_op "THEN'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ - @{index_ML_op "ORELSE'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ - @{index_ML_op "APPEND'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ - @{index_ML "EVERY'": "('a -> tactic) list -> 'a -> tactic"} \\ - @{index_ML "FIRST'": "('a -> tactic) list -> 'a -> tactic"} \\ + @{define_ML_infix "THEN'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ + @{define_ML_infix "ORELSE'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ + @{define_ML_infix "APPEND'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ + @{define_ML "EVERY'": "('a -> tactic) list -> 'a -> tactic"} \\ + @{define_ML "FIRST'": "('a -> tactic) list -> 'a -> tactic"} \\ \end{mldecls} - \<^descr> \tac\<^sub>1\~\<^ML_op>\THEN\~\tac\<^sub>2\ is the sequential composition of \tac\<^sub>1\ and + \<^descr> \tac\<^sub>1\~\<^ML_infix>\THEN\~\tac\<^sub>2\ is the sequential composition of \tac\<^sub>1\ and \tac\<^sub>2\. Applied to a goal state, it returns all states reachable in two steps by applying \tac\<^sub>1\ followed by \tac\<^sub>2\. First, it applies \tac\<^sub>1\ to the goal state, getting a sequence of possible next states; then, it applies \tac\<^sub>2\ to each of these and concatenates the results to produce again one flat sequence of states. - \<^descr> \tac\<^sub>1\~\<^ML_op>\ORELSE\~\tac\<^sub>2\ makes a choice between \tac\<^sub>1\ and + \<^descr> \tac\<^sub>1\~\<^ML_infix>\ORELSE\~\tac\<^sub>2\ makes a choice between \tac\<^sub>1\ and \tac\<^sub>2\. Applied to a state, it tries \tac\<^sub>1\ and returns the result if non-empty; if \tac\<^sub>1\ fails then it uses \tac\<^sub>2\. This is a deterministic choice: if \tac\<^sub>1\ succeeds then \tac\<^sub>2\ is excluded from the result. - \<^descr> \tac\<^sub>1\~\<^ML_op>\APPEND\~\tac\<^sub>2\ concatenates the possible results of - \tac\<^sub>1\ and \tac\<^sub>2\. Unlike \<^ML_op>\ORELSE\ there is \<^emph>\no commitment\ to - either tactic, so \<^ML_op>\APPEND\ helps to avoid incompleteness during + \<^descr> \tac\<^sub>1\~\<^ML_infix>\APPEND\~\tac\<^sub>2\ concatenates the possible results of + \tac\<^sub>1\ and \tac\<^sub>2\. Unlike \<^ML_infix>\ORELSE\ there is \<^emph>\no commitment\ to + either tactic, so \<^ML_infix>\APPEND\ helps to avoid incompleteness during search, at the cost of potential inefficiencies. - \<^descr> \<^ML>\EVERY\~\[tac\<^sub>1, \, tac\<^sub>n]\ abbreviates \tac\<^sub>1\~\<^ML_op>\THEN\~\\\~\<^ML_op>\THEN\~\tac\<^sub>n\. Note that \<^ML>\EVERY []\ is the same as + \<^descr> \<^ML>\EVERY\~\[tac\<^sub>1, \, tac\<^sub>n]\ abbreviates \tac\<^sub>1\~\<^ML_infix>\THEN\~\\\~\<^ML_infix>\THEN\~\tac\<^sub>n\. Note that \<^ML>\EVERY []\ is the same as \<^ML>\all_tac\: it always succeeds. - \<^descr> \<^ML>\FIRST\~\[tac\<^sub>1, \, tac\<^sub>n]\ abbreviates \tac\<^sub>1\~\<^ML_op>\ORELSE\~\\\~\<^ML_op>\ORELSE\~\tac\<^sub>n\. Note that \<^ML>\FIRST []\ is the + \<^descr> \<^ML>\FIRST\~\[tac\<^sub>1, \, tac\<^sub>n]\ abbreviates \tac\<^sub>1\~\<^ML_infix>\ORELSE\~\\\~\<^ML_infix>\ORELSE\~\tac\<^sub>n\. Note that \<^ML>\FIRST []\ is the same as \<^ML>\no_tac\: it always fails. - \<^descr> \<^ML_op>\THEN'\ is the lifted version of \<^ML_op>\THEN\, for tactics - with explicit subgoal addressing. So \(tac\<^sub>1\~\<^ML_op>\THEN'\~\tac\<^sub>2) i\ is - the same as \(tac\<^sub>1 i\~\<^ML_op>\THEN\~\tac\<^sub>2 i)\. + \<^descr> \<^ML_infix>\THEN'\ is the lifted version of \<^ML_infix>\THEN\, for tactics + with explicit subgoal addressing. So \(tac\<^sub>1\~\<^ML_infix>\THEN'\~\tac\<^sub>2) i\ is + the same as \(tac\<^sub>1 i\~\<^ML_infix>\THEN\~\tac\<^sub>2 i)\. The other primed tacticals work analogously. \ @@ -555,11 +555,11 @@ text %mlref \ \begin{mldecls} - @{index_ML "TRY": "tactic -> tactic"} \\ - @{index_ML "REPEAT": "tactic -> tactic"} \\ - @{index_ML "REPEAT1": "tactic -> tactic"} \\ - @{index_ML "REPEAT_DETERM": "tactic -> tactic"} \\ - @{index_ML "REPEAT_DETERM_N": "int -> tactic -> tactic"} \\ + @{define_ML "TRY": "tactic -> tactic"} \\ + @{define_ML "REPEAT": "tactic -> tactic"} \\ + @{define_ML "REPEAT1": "tactic -> tactic"} \\ + @{define_ML "REPEAT_DETERM": "tactic -> tactic"} \\ + @{define_ML "REPEAT_DETERM_N": "int -> tactic -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\TRY\~\tac\ applies \tac\ to the goal state and returns the resulting @@ -567,7 +567,7 @@ applies \tac\ at most once. Note that for tactics with subgoal addressing, the combinator can be applied - via functional composition: \<^ML>\TRY\~\<^ML_op>\o\~\tac\. There is no need + via functional composition: \<^ML>\TRY\~\<^ML_infix>\o\~\tac\. There is no need for \<^verbatim>\TRY'\. \<^descr> \<^ML>\REPEAT\~\tac\ applies \tac\ to the goal state and, recursively, to @@ -592,10 +592,10 @@ text %mlex \ The basic tactics and tacticals considered above follow some algebraic laws: - \<^item> \<^ML>\all_tac\ is the identity element of the tactical \<^ML_op>\THEN\. + \<^item> \<^ML>\all_tac\ is the identity element of the tactical \<^ML_infix>\THEN\. - \<^item> \<^ML>\no_tac\ is the identity element of \<^ML_op>\ORELSE\ and \<^ML_op>\APPEND\. Also, it is a zero element for \<^ML_op>\THEN\, which means that - \tac\~\<^ML_op>\THEN\~\<^ML>\no_tac\ is equivalent to \<^ML>\no_tac\. + \<^item> \<^ML>\no_tac\ is the identity element of \<^ML_infix>\ORELSE\ and \<^ML_infix>\APPEND\. Also, it is a zero element for \<^ML_infix>\THEN\, which means that + \tac\~\<^ML_infix>\THEN\~\<^ML>\no_tac\ is equivalent to \<^ML>\no_tac\. \<^item> \<^ML>\TRY\ and \<^ML>\REPEAT\ can be expressed as (recursive) functions over more basic combinators (ignoring some internal implementation tricks): @@ -607,7 +607,7 @@ \ text \ - If \tac\ can return multiple outcomes then so can \<^ML>\REPEAT\~\tac\. \<^ML>\REPEAT\ uses \<^ML_op>\ORELSE\ and not \<^ML_op>\APPEND\, it applies \tac\ + If \tac\ can return multiple outcomes then so can \<^ML>\REPEAT\~\tac\. \<^ML>\REPEAT\ uses \<^ML_infix>\ORELSE\ and not \<^ML_infix>\APPEND\, it applies \tac\ as many times as possible in each outcome. \begin{warn} @@ -641,20 +641,20 @@ text %mlref \ \begin{mldecls} - @{index_ML ALLGOALS: "(int -> tactic) -> tactic"} \\ - @{index_ML SOMEGOAL: "(int -> tactic) -> tactic"} \\ - @{index_ML FIRSTGOAL: "(int -> tactic) -> tactic"} \\ - @{index_ML HEADGOAL: "(int -> tactic) -> tactic"} \\ - @{index_ML REPEAT_SOME: "(int -> tactic) -> tactic"} \\ - @{index_ML REPEAT_FIRST: "(int -> tactic) -> tactic"} \\ - @{index_ML RANGE: "(int -> tactic) list -> int -> tactic"} \\ + @{define_ML ALLGOALS: "(int -> tactic) -> tactic"} \\ + @{define_ML SOMEGOAL: "(int -> tactic) -> tactic"} \\ + @{define_ML FIRSTGOAL: "(int -> tactic) -> tactic"} \\ + @{define_ML HEADGOAL: "(int -> tactic) -> tactic"} \\ + @{define_ML REPEAT_SOME: "(int -> tactic) -> tactic"} \\ + @{define_ML REPEAT_FIRST: "(int -> tactic) -> tactic"} \\ + @{define_ML RANGE: "(int -> tactic) list -> int -> tactic"} \\ \end{mldecls} - \<^descr> \<^ML>\ALLGOALS\~\tac\ is equivalent to \tac n\~\<^ML_op>\THEN\~\\\~\<^ML_op>\THEN\~\tac 1\. It applies the \tac\ to all the subgoals, counting downwards. + \<^descr> \<^ML>\ALLGOALS\~\tac\ is equivalent to \tac n\~\<^ML_infix>\THEN\~\\\~\<^ML_infix>\THEN\~\tac 1\. It applies the \tac\ to all the subgoals, counting downwards. - \<^descr> \<^ML>\SOMEGOAL\~\tac\ is equivalent to \tac n\~\<^ML_op>\ORELSE\~\\\~\<^ML_op>\ORELSE\~\tac 1\. It applies \tac\ to one subgoal, counting downwards. + \<^descr> \<^ML>\SOMEGOAL\~\tac\ is equivalent to \tac n\~\<^ML_infix>\ORELSE\~\\\~\<^ML_infix>\ORELSE\~\tac 1\. It applies \tac\ to one subgoal, counting downwards. - \<^descr> \<^ML>\FIRSTGOAL\~\tac\ is equivalent to \tac 1\~\<^ML_op>\ORELSE\~\\\~\<^ML_op>\ORELSE\~\tac n\. It applies \tac\ to one subgoal, counting upwards. + \<^descr> \<^ML>\FIRSTGOAL\~\tac\ is equivalent to \tac 1\~\<^ML_infix>\ORELSE\~\\\~\<^ML_infix>\ORELSE\~\tac n\. It applies \tac\ to one subgoal, counting upwards. \<^descr> \<^ML>\HEADGOAL\~\tac\ is equivalent to \tac 1\. It applies \tac\ unconditionally to the first subgoal. @@ -666,7 +666,7 @@ upwards. \<^descr> \<^ML>\RANGE\~\[tac\<^sub>1, \, tac\<^sub>k] i\ is equivalent to \tac\<^sub>k (i + k - - 1)\~\<^ML_op>\THEN\~\\\~\<^ML_op>\THEN\~\tac\<^sub>1 i\. It applies the given list of + 1)\~\<^ML_infix>\THEN\~\\\~\<^ML_infix>\THEN\~\tac\<^sub>1 i\. It applies the given list of tactics to the corresponding range of subgoals, counting downwards. \ @@ -689,8 +689,8 @@ text \ \begin{mldecls} - @{index_ML FILTER: "(thm -> bool) -> tactic -> tactic"} \\ - @{index_ML CHANGED: "tactic -> tactic"} \\ + @{define_ML FILTER: "(thm -> bool) -> tactic -> tactic"} \\ + @{define_ML CHANGED: "tactic -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\FILTER\~\sat tac\ applies \tac\ to the goal state and returns a @@ -706,15 +706,15 @@ text \ \begin{mldecls} - @{index_ML DEPTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\ - @{index_ML DEPTH_SOLVE: "tactic -> tactic"} \\ - @{index_ML DEPTH_SOLVE_1: "tactic -> tactic"} \\ + @{define_ML DEPTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\ + @{define_ML DEPTH_SOLVE: "tactic -> tactic"} \\ + @{define_ML DEPTH_SOLVE_1: "tactic -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\DEPTH_FIRST\~\sat tac\ returns the goal state if \sat\ returns true. Otherwise it applies \tac\, then recursively searches from each element of the resulting sequence. The code uses a stack for efficiency, in effect - applying \tac\~\<^ML_op>\THEN\~\<^ML>\DEPTH_FIRST\~\sat tac\ to the state. + applying \tac\~\<^ML_infix>\THEN\~\<^ML>\DEPTH_FIRST\~\sat tac\ to the state. \<^descr> \<^ML>\DEPTH_SOLVE\\tac\ uses \<^ML>\DEPTH_FIRST\ to search for states having no subgoals. @@ -729,9 +729,9 @@ text \ \begin{mldecls} - @{index_ML BREADTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\ - @{index_ML BEST_FIRST: "(thm -> bool) * (thm -> int) -> tactic -> tactic"} \\ - @{index_ML THEN_BEST_FIRST: "tactic -> (thm -> bool) * (thm -> int) -> tactic -> tactic"} \\ + @{define_ML BREADTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\ + @{define_ML BEST_FIRST: "(thm -> bool) * (thm -> int) -> tactic -> tactic"} \\ + @{define_ML THEN_BEST_FIRST: "tactic -> (thm -> bool) * (thm -> int) -> tactic -> tactic"} \\ \end{mldecls} These search strategies will find a solution if one exists. However, they do @@ -763,10 +763,10 @@ text \ \begin{mldecls} - @{index_ML COND: "(thm -> bool) -> tactic -> tactic -> tactic"} \\ - @{index_ML IF_UNSOLVED: "tactic -> tactic"} \\ - @{index_ML SOLVE: "tactic -> tactic"} \\ - @{index_ML DETERM: "tactic -> tactic"} \\ + @{define_ML COND: "(thm -> bool) -> tactic -> tactic -> tactic"} \\ + @{define_ML IF_UNSOLVED: "tactic -> tactic"} \\ + @{define_ML SOLVE: "tactic -> tactic"} \\ + @{define_ML DETERM: "tactic -> tactic"} \\ \end{mldecls} \<^descr> \<^ML>\COND\~\sat tac\<^sub>1 tac\<^sub>2\ applies \tac\<^sub>1\ to the goal state if it @@ -792,10 +792,10 @@ text \ \begin{mldecls} - @{index_ML has_fewer_prems: "int -> thm -> bool"} \\ - @{index_ML Thm.eq_thm: "thm * thm -> bool"} \\ - @{index_ML Thm.eq_thm_prop: "thm * thm -> bool"} \\ - @{index_ML size_of_thm: "thm -> int"} \\ + @{define_ML has_fewer_prems: "int -> thm -> bool"} \\ + @{define_ML Thm.eq_thm: "thm * thm -> bool"} \\ + @{define_ML Thm.eq_thm_prop: "thm * thm -> bool"} \\ + @{define_ML size_of_thm: "thm -> int"} \\ \end{mldecls} \<^descr> \<^ML>\has_fewer_prems\~\n thm\ reports whether \thm\ has fewer than \n\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/document/build --- a/src/Doc/Implementation/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo Isar -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Implementation/document/root.tex --- a/src/Doc/Implementation/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Implementation/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -16,7 +16,7 @@ \hyphenation{Isar} \isadroptag{theory} -\title{\includegraphics[scale=0.5]{isabelle_isar} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] The Isabelle/Isar Implementation} \author{\emph{Makarius Wenzel} \\[3ex] With Contributions by diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Intro/document/build --- a/src/Doc/Intro/document/build Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Intro/document/build Sun May 23 20:34:43 2021 +0200 @@ -2,9 +2,18 @@ set -e -FORMAT="$1" -VARIANT="$2" +$ISABELLE_LUALATEX root + +if [ -f manual.bib -o -f root.bib ] +then + $ISABELLE_BIBTEX root + $ISABELLE_LUALATEX root +fi -isabelle logo -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" +$ISABELLE_LUALATEX root +if [ -f root.idx ] +then + "$ISABELLE_HOME/src/Doc/sedindex" root + $ISABELLE_LUALATEX root +fi diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Intro/document/root.tex --- a/src/Doc/Intro/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Intro/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -6,7 +6,7 @@ %prth *(\(.*\)); \1; %{\\out \(.*\)} {\\out val it = "\1" : thm} -\title{\includegraphics[scale=0.5]{isabelle} \\[4ex] Old Introduction to Isabelle} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Old Introduction to Isabelle} \author{{\em Lawrence C. Paulson}\\ Computer Laboratory \\ University of Cambridge \\ \texttt{lcp@cl.cam.ac.uk}\\[3ex] diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/Document_Preparation.thy --- a/src/Doc/Isar_Ref/Document_Preparation.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/Document_Preparation.thy Sun May 23 20:34:43 2021 +0200 @@ -100,11 +100,22 @@ @{antiquotation_def subgoals} & : & \antiquotation\ \\ @{antiquotation_def prf} & : & \antiquotation\ \\ @{antiquotation_def full_prf} & : & \antiquotation\ \\ + @{antiquotation_def ML_text} & : & \antiquotation\ \\ @{antiquotation_def ML} & : & \antiquotation\ \\ - @{antiquotation_def ML_op} & : & \antiquotation\ \\ + @{antiquotation_def ML_def} & : & \antiquotation\ \\ + @{antiquotation_def ML_ref} & : & \antiquotation\ \\ + @{antiquotation_def ML_infix} & : & \antiquotation\ \\ + @{antiquotation_def ML_infix_def} & : & \antiquotation\ \\ + @{antiquotation_def ML_infix_ref} & : & \antiquotation\ \\ @{antiquotation_def ML_type} & : & \antiquotation\ \\ + @{antiquotation_def ML_type_def} & : & \antiquotation\ \\ + @{antiquotation_def ML_type_ref} & : & \antiquotation\ \\ @{antiquotation_def ML_structure} & : & \antiquotation\ \\ + @{antiquotation_def ML_structure_def} & : & \antiquotation\ \\ + @{antiquotation_def ML_structure_ref} & : & \antiquotation\ \\ @{antiquotation_def ML_functor} & : & \antiquotation\ \\ + @{antiquotation_def ML_functor_def} & : & \antiquotation\ \\ + @{antiquotation_def ML_functor_ref} & : & \antiquotation\ \\ @{antiquotation_def emph} & : & \antiquotation\ \\ @{antiquotation_def bold} & : & \antiquotation\ \\ @{antiquotation_def verbatim} & : & \antiquotation\ \\ @@ -192,9 +203,10 @@ @@{antiquotation subgoals} options | @@{antiquotation prf} options @{syntax thms} | @@{antiquotation full_prf} options @{syntax thms} | + @@{antiquotation ML_text} options @{syntax text} | @@{antiquotation ML} options @{syntax text} | - @@{antiquotation ML_op} options @{syntax text} | - @@{antiquotation ML_type} options @{syntax text} | + @@{antiquotation ML_infix} options @{syntax text} | + @@{antiquotation ML_type} options @{syntax typeargs} @{syntax text} | @@{antiquotation ML_structure} options @{syntax text} | @@{antiquotation ML_functor} options @{syntax text} | @@{antiquotation emph} options @{syntax text} | @@ -280,10 +292,22 @@ \<^descr> \@{full_prf a\<^sub>1 \ a\<^sub>n}\ is like \@{prf a\<^sub>1 \ a\<^sub>n}\, but prints the full proof terms, i.e.\ also displays information omitted in the compact proof term, which is denoted by ``\_\'' placeholders there. - - \<^descr> \@{ML s}\, \@{ML_op s}\, \@{ML_type s}\, \@{ML_structure s}\, and + + \<^descr> \@{ML_text s}\ prints ML text verbatim: only the token language is + checked. + + \<^descr> \@{ML s}\, \@{ML_infix s}\, \@{ML_type s}\, \@{ML_structure s}\, and \@{ML_functor s}\ check text \s\ as ML value, infix operator, type, - structure, and functor respectively. The source is printed verbatim. + exception, structure, and functor respectively. The source is printed + verbatim. The variants \@{ML_def s}\ and \@{ML_ref s}\ etc. maintain the + document index: ``def'' means to make a bold entry, ``ref'' means to make a + regular entry. + + There are two forms for type constructors, with or without separate type + arguments: this impacts only the index entry. For example, \@{ML_type_ref + \'a list\}\ makes an entry literally for ``\'a list\'' (sorted under the + letter ``a''), but \@{ML_type_ref 'a \list\}\ makes an entry for the + constructor name ``\list\''. \<^descr> \@{emph s}\ prints document source recursively, with {\LaTeX} markup \<^verbatim>\\emph{\\\\\<^verbatim>\}\. diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/Generic.thy --- a/src/Doc/Isar_Ref/Generic.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/Generic.thy Sun May 23 20:34:43 2021 +0200 @@ -153,7 +153,7 @@ \<^descr> @{attribute THEN}~\a\ composes rules by resolution; it resolves with the first premise of \a\ (an alternative position may be also specified). See - also \<^ML_op>\RS\ in @{cite "isabelle-implementation"}. + also \<^ML_infix>\RS\ in @{cite "isabelle-implementation"}. \<^descr> @{attribute unfolded}~\a\<^sub>1 \ a\<^sub>n\ and @{attribute folded}~\a\<^sub>1 \ a\<^sub>n\ expand and fold back again the given definitions throughout a rule. @@ -638,7 +638,7 @@ of the term ordering. The default is lexicographic ordering of term structure, but this could be - also changed locally for special applications via @{index_ML + also changed locally for special applications via @{define_ML Simplifier.set_term_ord} in Isabelle/ML. \<^medskip> @@ -866,9 +866,9 @@ text \ \begin{mldecls} - @{index_ML Simplifier.set_subgoaler: "(Proof.context -> int -> tactic) -> + @{define_ML Simplifier.set_subgoaler: "(Proof.context -> int -> tactic) -> Proof.context -> Proof.context"} \\ - @{index_ML Simplifier.prems_of: "Proof.context -> thm list"} \\ + @{define_ML Simplifier.prems_of: "Proof.context -> thm list"} \\ \end{mldecls} The subgoaler is the tactic used to solve subgoals arising out of @@ -906,13 +906,13 @@ text \ \begin{mldecls} - @{index_ML_type solver} \\ - @{index_ML Simplifier.mk_solver: "string -> + @{define_ML_type solver} \\ + @{define_ML Simplifier.mk_solver: "string -> (Proof.context -> int -> tactic) -> solver"} \\ - @{index_ML_op setSolver: "Proof.context * solver -> Proof.context"} \\ - @{index_ML_op addSolver: "Proof.context * solver -> Proof.context"} \\ - @{index_ML_op setSSolver: "Proof.context * solver -> Proof.context"} \\ - @{index_ML_op addSSolver: "Proof.context * solver -> Proof.context"} \\ + @{define_ML_infix setSolver: "Proof.context * solver -> Proof.context"} \\ + @{define_ML_infix addSolver: "Proof.context * solver -> Proof.context"} \\ + @{define_ML_infix setSSolver: "Proof.context * solver -> Proof.context"} \\ + @{define_ML_infix addSSolver: "Proof.context * solver -> Proof.context"} \\ \end{mldecls} A solver is a tactic that attempts to solve a subgoal after simplification. @@ -992,17 +992,17 @@ text \ \begin{mldecls} - @{index_ML_op setloop: "Proof.context * + @{define_ML_infix setloop: "Proof.context * (Proof.context -> int -> tactic) -> Proof.context"} \\ - @{index_ML_op addloop: "Proof.context * + @{define_ML_infix addloop: "Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context"} \\ - @{index_ML_op delloop: "Proof.context * string -> Proof.context"} \\ - @{index_ML Splitter.add_split: "thm -> Proof.context -> Proof.context"} \\ - @{index_ML Splitter.add_split: "thm -> Proof.context -> Proof.context"} \\ - @{index_ML Splitter.add_split_bang: " + @{define_ML_infix delloop: "Proof.context * string -> Proof.context"} \\ + @{define_ML Splitter.add_split: "thm -> Proof.context -> Proof.context"} \\ + @{define_ML Splitter.add_split: "thm -> Proof.context -> Proof.context"} \\ + @{define_ML Splitter.add_split_bang: " thm -> Proof.context -> Proof.context"} \\ - @{index_ML Splitter.del_split: "thm -> Proof.context -> Proof.context"} \\ + @{define_ML Splitter.del_split: "thm -> Proof.context -> Proof.context"} \\ \end{mldecls} The looper is a list of tactics that are applied after simplification, in @@ -1624,23 +1624,23 @@ text \ \begin{mldecls} - @{index_ML_type wrapper: "(int -> tactic) -> (int -> tactic)"} \\[0.5ex] - @{index_ML_op addSWrapper: "Proof.context * + @{define_ML_type wrapper = "(int -> tactic) -> (int -> tactic)"} \\[0.5ex] + @{define_ML_infix addSWrapper: "Proof.context * (string * (Proof.context -> wrapper)) -> Proof.context"} \\ - @{index_ML_op addSbefore: "Proof.context * + @{define_ML_infix addSbefore: "Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context"} \\ - @{index_ML_op addSafter: "Proof.context * + @{define_ML_infix addSafter: "Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context"} \\ - @{index_ML_op delSWrapper: "Proof.context * string -> Proof.context"} \\[0.5ex] - @{index_ML_op addWrapper: "Proof.context * + @{define_ML_infix delSWrapper: "Proof.context * string -> Proof.context"} \\[0.5ex] + @{define_ML_infix addWrapper: "Proof.context * (string * (Proof.context -> wrapper)) -> Proof.context"} \\ - @{index_ML_op addbefore: "Proof.context * + @{define_ML_infix addbefore: "Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context"} \\ - @{index_ML_op addafter: "Proof.context * + @{define_ML_infix addafter: "Proof.context * (string * (Proof.context -> int -> tactic)) -> Proof.context"} \\ - @{index_ML_op delWrapper: "Proof.context * string -> Proof.context"} \\[0.5ex] - @{index_ML addSss: "Proof.context -> Proof.context"} \\ - @{index_ML addss: "Proof.context -> Proof.context"} \\ + @{define_ML_infix delWrapper: "Proof.context * string -> Proof.context"} \\[0.5ex] + @{define_ML addSss: "Proof.context -> Proof.context"} \\ + @{define_ML addss: "Proof.context -> Proof.context"} \\ \end{mldecls} The proof strategy of the Classical Reasoner is simple. Perform as diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/Inner_Syntax.thy --- a/src/Doc/Isar_Ref/Inner_Syntax.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/Inner_Syntax.thy Sun May 23 20:34:43 2021 +0200 @@ -220,8 +220,8 @@ text \ \begin{mldecls} - @{index_ML print_mode_value: "unit -> string list"} \\ - @{index_ML Print_Mode.with_modes: "string list -> ('a -> 'b) -> 'a -> 'b"} \\ + @{define_ML print_mode_value: "unit -> string list"} \\ + @{define_ML Print_Mode.with_modes: "string list -> ('a -> 'b) -> 'a -> 'b"} \\ \end{mldecls} The \<^emph>\print mode\ facility allows to modify various operations for printing. diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/Outer_Syntax.thy --- a/src/Doc/Isar_Ref/Outer_Syntax.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/Outer_Syntax.thy Sun May 23 20:34:43 2021 +0200 @@ -343,12 +343,16 @@ no infixes. \<^rail>\ - @{syntax_def typespec}: - (() | @{syntax type_ident} | '(' ( @{syntax type_ident} + ',' ) ')') @{syntax name} + @{syntax_def typeargs}: + (() | @{syntax type_ident} | '(' ( @{syntax type_ident} + ',' ) ')') ; - @{syntax_def typespec_sorts}: + @{syntax_def typeargs_sorts}: (() | (@{syntax type_ident} ('::' @{syntax sort})?) | - '(' ( (@{syntax type_ident} ('::' @{syntax sort})?) + ',' ) ')') @{syntax name} + '(' ( (@{syntax type_ident} ('::' @{syntax sort})?) + ',' ) ')') + ; + @{syntax_def typespec}: @{syntax typeargs} @{syntax name} + ; + @{syntax_def typespec_sorts}: @{syntax typeargs_sorts} @{syntax name} \ \ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/Proof.thy --- a/src/Doc/Isar_Ref/Proof.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/Proof.thy Sun May 23 20:34:43 2021 +0200 @@ -626,7 +626,7 @@ Structural composition ``\m\<^sub>1\\<^verbatim>\;\~\m\<^sub>2\'' means that method \m\<^sub>1\ is applied with restriction to the first subgoal, then \m\<^sub>2\ is applied consecutively with restriction to each subgoal that has newly emerged due to - \m\<^sub>1\. This is analogous to the tactic combinator \<^ML_op>\THEN_ALL_NEW\ in + \m\<^sub>1\. This is analogous to the tactic combinator \<^ML_infix>\THEN_ALL_NEW\ in Isabelle/ML, see also @{cite "isabelle-implementation"}. For example, \(rule r; blast)\ applies rule \r\ and then solves all new subgoals by \blast\. diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/Spec.thy --- a/src/Doc/Isar_Ref/Spec.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/Spec.thy Sun May 23 20:34:43 2021 +0200 @@ -520,8 +520,11 @@ @{command_def "locale_deps"}\\<^sup>*\ & : & \context \\ \\ \end{tabular} - \indexisarelem{fixes}\indexisarelem{constrains}\indexisarelem{assumes} - \indexisarelem{defines}\indexisarelem{notes} + @{index_ref \\<^theory_text>\fixes\ (element)\} + @{index_ref \\<^theory_text>\constrains\ (element)\} + @{index_ref \\<^theory_text>\assumes\ (element)\} + @{index_ref \\<^theory_text>\defines\ (element)\} + @{index_ref \\<^theory_text>\notes\ (element)\} \<^rail>\ @@{command locale} @{syntax name} ('=' @{syntax locale})? @'begin'? ; diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/Symbols.thy --- a/src/Doc/Isar_Ref/Symbols.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/Symbols.thy Sun May 23 20:34:43 2021 +0200 @@ -32,7 +32,7 @@ \begin{center} \begin{isabellebody} - \input{syms} + @{show_symbols} \end{isabellebody} \end{center} \ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/document/build --- a/src/Doc/Isar_Ref/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo Isar -./showsymbols "$ISABELLE_HOME/lib/texinputs/isabellesym.sty" > syms.tex -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/document/root.tex --- a/src/Doc/Isar_Ref/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Isar_Ref/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -23,7 +23,7 @@ \hyphenation{Isar} \isadroptag{theory} -\title{\includegraphics[scale=0.5]{isabelle_isar} \\[4ex] The Isabelle/Isar Reference Manual} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] The Isabelle/Isar Reference Manual} \author{\emph{Makarius Wenzel} \\[3ex] With Contributions by Clemens Ballarin, diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Isar_Ref/document/showsymbols --- a/src/Doc/Isar_Ref/document/showsymbols Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -#!/usr/bin/env perl - -print "\\begin{supertabular}{ll\@{\\qquad}ll}\n"; - -$eol = "&"; - -while () { - if (m/^\\newcommand\{\\isasym([A-Za-z]+)\}/) { - print "\\verb,\\<$1>, & {\\isasym$1} $eol\n"; - if ("$eol" eq "&") { - $eol = "\\\\"; - } else { - $eol = "&"; - } - } -} - -if ("$eol" eq "\\\\") { - print "$eol\n"; -} - -print "\\end{supertabular}\n"; - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/JEdit/JEdit.thy --- a/src/Doc/JEdit/JEdit.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/JEdit/JEdit.thy Sun May 23 20:34:43 2021 +0200 @@ -1911,7 +1911,7 @@ text \ Citations are managed by {\LaTeX} and Bib{\TeX} in \<^verbatim>\.bib\ files. The - Isabelle session build process and the @{tool latex} tool @{cite + Isabelle session build process and the @{tool document} tool @{cite "isabelle-system"} are smart enough to assemble the result, based on the session directory layout. diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/JEdit/document/build --- a/src/Doc/JEdit/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo jEdit -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/JEdit/document/root.tex --- a/src/Doc/JEdit/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/JEdit/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -20,7 +20,7 @@ \isabellestyle{literal} \def\isastylett{\footnotesize\tt} -\title{\includegraphics[scale=0.5]{isabelle_jedit} \\[4ex] Isabelle/jEdit} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Isabelle/jEdit} \author{\emph{Makarius Wenzel}} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Locales/document/build --- a/src/Doc/Locales/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Logics/document/build --- a/src/Doc/Logics/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Logics/document/root.tex --- a/src/Doc/Logics/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Logics/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -8,7 +8,7 @@ %%% to index constants: \\tt \([a-zA-Z0-9][a-zA-Z0-9_]*\) \\cdx{\1} %%% to deverbify: \\verb|\([^|]*\)| \\ttindex{\1} %% run ../sedindex logics to prepare index file -\title{\includegraphics[scale=0.5]{isabelle} \\[4ex] Isabelle's Logics} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Isabelle's Logics} \author{{\em Lawrence C. Paulson}\\ Computer Laboratory \\ University of Cambridge \\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Logics_ZF/document/build --- a/src/Doc/Logics_ZF/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo ZF -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Logics_ZF/document/logics.sty --- a/src/Doc/Logics_ZF/document/logics.sty Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Logics_ZF/document/logics.sty Sun May 23 20:34:43 2021 +0200 @@ -1,1 +1,179 @@ -% logics.sty : Logics Manuals Page Layout % \typeout{Document Style logics. Released 18 August 2003} \hyphenation{Isa-belle man-u-script man-u-scripts ap-pen-dix mut-u-al-ly} \hyphenation{data-type data-types co-data-type co-data-types } %usage: \iflabelundefined{LABEL}{if not defined}{if defined} \newcommand{\iflabelundefined}[1]{\@ifundefined{r@#1}} %%%INDEXING use isa-index to process the index \newcommand\seealso[2]{\emph{see also} #1} \usepackage{makeidx} %index, putting page numbers of definitions in boldface \def\bold#1{\textbf{#1}} \newcommand\fnote[1]{#1n} \newcommand\indexbold[1]{\index{#1|bold}} % The alternative to \protect\isa in the indexing macros is % \noexpand\noexpand \noexpand\isa % need TWO levels of \noexpand to delay the expansion of \isa: % the \noexpand\noexpand will leave one \noexpand, to be given to the % (still unexpanded) \isa token. See TeX by Topic, page 122. %%%% for indexing constants, symbols, theorems, ... \newcommand\cdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (constant)}} \newcommand\sdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (symbol)}} \newcommand\tdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (theorem)}} \newcommand\tdxbold[1]{\isa{#1}\index{#1@\protect\isa{#1} (theorem)|bold}} \newcommand\cldx[1]{\isa{#1}\index{#1@\protect\isa{#1} (class)}} \newcommand\tydx[1]{\isa{#1}\index{#1@\protect\isa{#1} (type)}} \newcommand\thydx[1]{\isa{#1}\index{#1@\protect\isa{#1} (theory)}} \newcommand\attrdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (attribute)}} \newcommand\cmmdx[1]{\index{#1@\protect\isacommand{#1} (command)}} \newcommand\commdx[1]{\isacommand{#1}\index{#1@\protect\isacommand{#1} (command)}} \newcommand\methdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (method)}} \newcommand\tooldx[1]{\isa{#1}\index{#1@\protect\isa{#1} (tool)}} \newcommand\settdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (setting)}} %set argument in \bf font and index in ROMAN font (for definitions in text!) \newcommand\bfindex[1]{{\bf#1}\index{#1|bold}\@} \newcommand\rmindex[1]{{#1}\index{#1}\@} \newcommand\ttindex[1]{\texttt{#1}\index{#1@\texttt{#1}}\@} \newcommand\ttindexbold[1]{\texttt{#1}\index{#1@\texttt{#1}|bold}\@} \newcommand{\indexboldpos}[2]{#1\@} \newcommand{\ttindexboldpos}[2]{\isa{#1}\@} %\newtheorem{theorem}{Theorem}[section] \newtheorem{Exercise}{Exercise}[section] \newenvironment{exercise}{\begin{Exercise}\rm}{\end{Exercise}} \newcommand{\ttlbr}{\texttt{[|}} \newcommand{\ttrbr}{\texttt{|]}} \newcommand{\ttor}{\texttt{|}} \newcommand{\ttall}{\texttt{!}} \newcommand{\ttuniquex}{\texttt{?!}} \newcommand{\ttEXU}{\texttt{EX!}} \newcommand{\ttAnd}{\texttt{!!}} \newcommand{\isasymignore}{} \newcommand{\isasymimp}{\isasymlongrightarrow} \newcommand{\isasymImp}{\isasymLongrightarrow} \newcommand{\isasymFun}{\isasymRightarrow} \newcommand{\isasymuniqex}{\isamath{\exists!\,}} \renewcommand{\S}{Sect.\ts} \renewenvironment{isamarkuptxt}{\begin{isamarkuptext}}{\end{isamarkuptext}} \newif\ifremarks \newcommand{\REMARK}[1]{\ifremarks\marginpar{\raggedright\footnotesize#1}\fi} %names of Isabelle rules \newcommand{\rulename}[1]{\hfill(#1)} \newcommand{\rulenamedx}[1]{\hfill(#1\index{#1@\protect\isa{#1} (theorem)|bold})} %%%% meta-logical connectives \let\Forall=\bigwedge \let\Imp=\Longrightarrow \let\To=\Rightarrow \newcommand{\Var}[1]{{?\!#1}} %%% underscores as ordinary characters, not for subscripting %% use @ or \sb for subscripting; use \at for @ %% only works in \tt font %% must not make _ an active char; would make \ttindex fail! \gdef\underscoreoff{\catcode`\@=8\catcode`\_=\other} \gdef\underscoreon{\catcode`\_=8\makeatother} \chardef\other=12 \chardef\at=`\@ % alternative underscore \def\_{\leavevmode\kern.06em\vbox{\hrule height.2ex width.3em}\hskip0.1em} %%%% ``WARNING'' environment \def\dbend{\vtop to 0pt{\vss\hbox{\Huge\bf!}\vss}} \newenvironment{warn}{\medskip\medbreak\begingroup \clubpenalty=10000 \small %%WAS\baselineskip=0.9\baselineskip \noindent \hangindent\parindent \hangafter=-2 \hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces}% {\par\endgroup\medbreak} %%%% Standard logical symbols \let\turn=\vdash \let\conj=\wedge \let\disj=\vee \let\imp=\rightarrow \let\bimp=\leftrightarrow \newcommand\all[1]{\forall#1.} %quantification \newcommand\ex[1]{\exists#1.} \newcommand{\pair}[1]{\langle#1\rangle} \newcommand{\lparr}{\mathopen{(\!|}} \newcommand{\rparr}{\mathclose{|\!)}} \newcommand{\fs}{\mathpunct{,\,}} \newcommand{\ty}{\mathrel{::}} \newcommand{\asn}{\mathrel{:=}} \newcommand{\more}{\ldots} \newcommand{\record}[1]{\lparr #1 \rparr} \newcommand{\dtt}{\mathord.} \newcommand\lbrakk{\mathopen{[\![}} \newcommand\rbrakk{\mathclose{]\!]}} \newcommand\List[1]{\lbrakk#1\rbrakk} %was \obj \newcommand\vpile[1]{\begin{array}{c}#1\end{array}} \newenvironment{matharray}[1]{\[\begin{array}{#1}}{\end{array}\]} \newcommand{\Text}[1]{\mbox{#1}} \DeclareMathSymbol{\dshsym}{\mathalpha}{letters}{"2D} \newcommand{\dsh}{\mathit{\dshsym}} \let\int=\cap \let\un=\cup \let\inter=\bigcap \let\union=\bigcup \def\ML{{\sc ml}} \def\AST{{\sc ast}} %macros to change the treatment of symbols \def\relsemicolon{\mathcode`\;="303B} %treat ; like a relation \def\binperiod{\mathcode`\.="213A} %treat . like a binary operator \def\binvert{\mathcode`\|="226A} %treat | like a binary operator %redefinition of \sloppy and \fussy to use \emergencystretch \def\sloppy{\tolerance2000 \hfuzz.5pt \vfuzz.5pt \emergencystretch=15pt} \def\fussy{\tolerance200 \hfuzz.1pt \vfuzz.1pt \emergencystretch=0pt} %non-bf version of description \def\descrlabel#1{\hspace\labelsep #1} \def\descr{\list{}{\labelwidth\z@ \itemindent-\leftmargin\let\makelabel\descrlabel}} \let\enddescr\endlist % The mathcodes for the letters A, ..., Z, a, ..., z are changed to % generate text italic rather than math italic by default. This makes % multi-letter identifiers look better. The mathcode for character c % is set to |"7000| (variable family) + |"400| (text italic) + |c|. % \DeclareSymbolFont{italics}{\encodingdefault}{\rmdefault}{m}{it}% \def\@setmcodes#1#2#3{{\count0=#1 \count1=#3 \loop \global\mathcode\count0=\count1 \ifnum \count0<#2 \advance\count0 by1 \advance\count1 by1 \repeat}} \@setmcodes{`A}{`Z}{"7\hexnumber@\symitalics41} \@setmcodes{`a}{`z}{"7\hexnumber@\symitalics61} %%% \dquotes permits usage of "..." for \hbox{...} %%% also taken from under.sty {\catcode`\"=\active \gdef\dquotes{\catcode`\"=\active \let"=\@mathText}% \gdef\@mathText#1"{\hbox{\mathTextFont #1\/}}} \def\mathTextFont{\frenchspacing\tt} \def\dquotesoff{\catcode`\"=\other} \ No newline at end of file +% logics.sty : Logics Manuals Page Layout +% +\typeout{Document Style logics. Released 18 August 2003} + +\hyphenation{Isa-belle man-u-script man-u-scripts ap-pen-dix mut-u-al-ly} +\hyphenation{data-type data-types co-data-type co-data-types } + +%usage: \iflabelundefined{LABEL}{if not defined}{if defined} +\newcommand{\iflabelundefined}[1]{\@ifundefined{r@#1}} + + +%%%INDEXING use isa-index to process the index + +\newcommand\seealso[2]{\emph{see also} #1} +\usepackage{makeidx} + +%index, putting page numbers of definitions in boldface +\def\bold#1{\textbf{#1}} +\newcommand\fnote[1]{#1n} +\newcommand\indexbold[1]{\index{#1|bold}} + +% The alternative to \protect\isa in the indexing macros is +% \noexpand\noexpand \noexpand\isa +% need TWO levels of \noexpand to delay the expansion of \isa: +% the \noexpand\noexpand will leave one \noexpand, to be given to the +% (still unexpanded) \isa token. See TeX by Topic, page 122. + +%%%% for indexing constants, symbols, theorems, ... +\newcommand\cdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (constant)}} +\newcommand\sdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (symbol)}} + +\newcommand\tdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (theorem)}} +\newcommand\tdxbold[1]{\isa{#1}\index{#1@\protect\isa{#1} (theorem)|bold}} + +\newcommand\cldx[1]{\isa{#1}\index{#1@\protect\isa{#1} (class)}} +\newcommand\tydx[1]{\isa{#1}\index{#1@\protect\isa{#1} (type)}} +\newcommand\thydx[1]{\isa{#1}\index{#1@\protect\isa{#1} (theory)}} + +\newcommand\attrdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (attribute)}} +\newcommand\cmmdx[1]{\index{#1@\protect\isacommand{#1} (command)}} +\newcommand\commdx[1]{\isacommand{#1}\index{#1@\protect\isacommand{#1} (command)}} +\newcommand\methdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (method)}} + +%set argument in \bf font and index in ROMAN font (for definitions in text!) +\newcommand\bfindex[1]{{\bf#1}\index{#1|bold}\@} + +\newcommand\rmindex[1]{{#1}\index{#1}\@} +\newcommand\ttindex[1]{\texttt{#1}\index{#1@\texttt{#1}}\@} +\newcommand\ttindexbold[1]{\texttt{#1}\index{#1@\texttt{#1}|bold}\@} + +\newcommand{\indexboldpos}[2]{#1\@} +\newcommand{\ttindexboldpos}[2]{\isa{#1}\@} + +%\newtheorem{theorem}{Theorem}[section] +\newtheorem{Exercise}{Exercise}[section] +\newenvironment{exercise}{\begin{Exercise}\rm}{\end{Exercise}} +\newcommand{\ttlbr}{\texttt{[|}} +\newcommand{\ttrbr}{\texttt{|]}} +\newcommand{\ttor}{\texttt{|}} +\newcommand{\ttall}{\texttt{!}} +\newcommand{\ttuniquex}{\texttt{?!}} +\newcommand{\ttEXU}{\texttt{EX!}} +\newcommand{\ttAnd}{\texttt{!!}} + +\newcommand{\isasymignore}{} +\newcommand{\isasymimp}{\isasymlongrightarrow} +\newcommand{\isasymImp}{\isasymLongrightarrow} +\newcommand{\isasymFun}{\isasymRightarrow} +\newcommand{\isasymuniqex}{\isamath{\exists!\,}} +\renewcommand{\S}{Sect.\ts} + +\renewenvironment{isamarkuptxt}{\begin{isamarkuptext}}{\end{isamarkuptext}} + +\newif\ifremarks +\newcommand{\REMARK}[1]{\ifremarks\marginpar{\raggedright\footnotesize#1}\fi} + +%names of Isabelle rules +\newcommand{\rulename}[1]{\hfill(#1)} +\newcommand{\rulenamedx}[1]{\hfill(#1\index{#1@\protect\isa{#1} (theorem)|bold})} + +%%%% meta-logical connectives + +\let\Forall=\bigwedge +\let\Imp=\Longrightarrow +\let\To=\Rightarrow +\newcommand{\Var}[1]{{?\!#1}} + +%%% underscores as ordinary characters, not for subscripting +%% use @ or \sb for subscripting; use \at for @ +%% only works in \tt font +%% must not make _ an active char; would make \ttindex fail! +\gdef\underscoreoff{\catcode`\@=8\catcode`\_=\other} +\gdef\underscoreon{\catcode`\_=8\makeatother} +\chardef\other=12 +\chardef\at=`\@ + +% alternative underscore +\def\_{\leavevmode\kern.06em\vbox{\hrule height.2ex width.3em}\hskip0.1em} + + +%%%% ``WARNING'' environment +\def\dbend{\vtop to 0pt{\vss\hbox{\Huge\bf!}\vss}} +\newenvironment{warn}{\medskip\medbreak\begingroup \clubpenalty=10000 + \small %%WAS\baselineskip=0.9\baselineskip + \noindent \hangindent\parindent \hangafter=-2 + \hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces}% + {\par\endgroup\medbreak} + + +%%%% Standard logical symbols +\let\turn=\vdash +\let\conj=\wedge +\let\disj=\vee +\let\imp=\rightarrow +\let\bimp=\leftrightarrow +\newcommand\all[1]{\forall#1.} %quantification +\newcommand\ex[1]{\exists#1.} +\newcommand{\pair}[1]{\langle#1\rangle} + +\newcommand{\lparr}{\mathopen{(\!|}} +\newcommand{\rparr}{\mathclose{|\!)}} +\newcommand{\fs}{\mathpunct{,\,}} +\newcommand{\ty}{\mathrel{::}} +\newcommand{\asn}{\mathrel{:=}} +\newcommand{\more}{\ldots} +\newcommand{\record}[1]{\lparr #1 \rparr} +\newcommand{\dtt}{\mathord.} + +\newcommand\lbrakk{\mathopen{[\![}} +\newcommand\rbrakk{\mathclose{]\!]}} +\newcommand\List[1]{\lbrakk#1\rbrakk} %was \obj +\newcommand\vpile[1]{\begin{array}{c}#1\end{array}} +\newenvironment{matharray}[1]{\[\begin{array}{#1}}{\end{array}\]} +\newcommand{\Text}[1]{\mbox{#1}} + +\DeclareMathSymbol{\dshsym}{\mathalpha}{letters}{"2D} +\newcommand{\dsh}{\mathit{\dshsym}} + +\let\int=\cap +\let\un=\cup +\let\inter=\bigcap +\let\union=\bigcup + +\def\ML{{\sc ml}} +\def\AST{{\sc ast}} + +%macros to change the treatment of symbols +\def\relsemicolon{\mathcode`\;="303B} %treat ; like a relation +\def\binperiod{\mathcode`\.="213A} %treat . like a binary operator +\def\binvert{\mathcode`\|="226A} %treat | like a binary operator + +%redefinition of \sloppy and \fussy to use \emergencystretch +\def\sloppy{\tolerance2000 \hfuzz.5pt \vfuzz.5pt \emergencystretch=15pt} +\def\fussy{\tolerance200 \hfuzz.1pt \vfuzz.1pt \emergencystretch=0pt} + +%non-bf version of description +\def\descrlabel#1{\hspace\labelsep #1} +\def\descr{\list{}{\labelwidth\z@ \itemindent-\leftmargin\let\makelabel\descrlabel}} +\let\enddescr\endlist + +% The mathcodes for the letters A, ..., Z, a, ..., z are changed to +% generate text italic rather than math italic by default. This makes +% multi-letter identifiers look better. The mathcode for character c +% is set to |"7000| (variable family) + |"400| (text italic) + |c|. +% +\DeclareSymbolFont{italics}{\encodingdefault}{\rmdefault}{m}{it}% +\def\@setmcodes#1#2#3{{\count0=#1 \count1=#3 + \loop \global\mathcode\count0=\count1 \ifnum \count0<#2 + \advance\count0 by1 \advance\count1 by1 \repeat}} +\@setmcodes{`A}{`Z}{"7\hexnumber@\symitalics41} +\@setmcodes{`a}{`z}{"7\hexnumber@\symitalics61} + +%%% \dquotes permits usage of "..." for \hbox{...} +%%% also taken from under.sty +{\catcode`\"=\active +\gdef\dquotes{\catcode`\"=\active \let"=\@mathText}% +\gdef\@mathText#1"{\hbox{\mathTextFont #1\/}}} +\def\mathTextFont{\frenchspacing\tt} +\def\dquotesoff{\catcode`\"=\other} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Logics_ZF/document/root.tex --- a/src/Doc/Logics_ZF/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Logics_ZF/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -13,7 +13,7 @@ %%% to index constants: \\tt \([a-zA-Z0-9][a-zA-Z0-9_]*\) \\cdx{\1} %%% to deverbify: \\verb|\([^|]*\)| \\ttindex{\1} -\title{\includegraphics[scale=0.5]{isabelle_zf} \\[4ex] +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Isabelle's Logics: FOL and ZF} \author{{\em Lawrence C. Paulson}\\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Main/Main_Doc.thy --- a/src/Doc/Main/Main_Doc.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Main/Main_Doc.thy Sun May 23 20:34:43 2021 +0200 @@ -4,14 +4,14 @@ begin setup \ - Thy_Output.antiquotation_pretty_source \<^binding>\term_type_only\ (Args.term -- Args.typ_abbrev) + Document_Output.antiquotation_pretty_source \<^binding>\term_type_only\ (Args.term -- Args.typ_abbrev) (fn ctxt => fn (t, T) => (if fastype_of t = Sign.certify_typ (Proof_Context.theory_of ctxt) T then () else error "term_type_only: type mismatch"; Syntax.pretty_typ ctxt T)) \ setup \ - Thy_Output.antiquotation_pretty_source \<^binding>\expanded_typ\ Args.typ + Document_Output.antiquotation_pretty_source \<^binding>\expanded_typ\ Args.typ Syntax.pretty_typ \ (*>*) diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Main/document/build --- a/src/Doc/Main/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle latex -o "$FORMAT" -isabelle latex -o "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Nitpick/document/build --- a/src/Doc/Nitpick/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo Nitpick -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Nitpick/document/root.tex --- a/src/Doc/Nitpick/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Nitpick/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -48,7 +48,7 @@ %\renewcommand\labelitemi{$\bullet$} \renewcommand\labelitemi{\raise.065ex\hbox{\small\textbullet}} -\title{\includegraphics[scale=0.5]{isabelle_nitpick} \\[4ex] +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Picking Nits \\[\smallskipamount] \Large A User's Guide to Nitpick for Isabelle/HOL} \author{\hbox{} \\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Prog_Prove/LaTeXsugar.thy --- a/src/Doc/Prog_Prove/LaTeXsugar.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Prog_Prove/LaTeXsugar.thy Sun May 23 20:34:43 2021 +0200 @@ -44,10 +44,11 @@ "_asm" :: "prop \ asms" ("_") setup \ - Thy_Output.antiquotation_pretty_source \<^binding>\const_typ\ (Scan.lift Args.embedded_inner_syntax) + Document_Output.antiquotation_pretty_source \<^binding>\const_typ\ + (Scan.lift Args.embedded_inner_syntax) (fn ctxt => fn c => let val tc = Proof_Context.read_const {proper = false, strict = false} ctxt c in - Pretty.block [Thy_Output.pretty_term ctxt tc, Pretty.str " ::", + Pretty.block [Document_Output.pretty_term ctxt tc, Pretty.str " ::", Pretty.brk 1, Syntax.pretty_typ ctxt (fastype_of tc)] end) \ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Prog_Prove/document/build --- a/src/Doc/Prog_Prove/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo HOL -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Prog_Prove/document/root.tex --- a/src/Doc/Prog_Prove/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Prog_Prove/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -7,7 +7,7 @@ \begin{document} \title{Programming and Proving in Isabelle/HOL} -\subtitle{\includegraphics[scale=.7]{isabelle_hol}} +\subtitle{\includegraphics[scale=.7]{isabelle_logo}} \author{Tobias Nipkow} \maketitle diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/ROOT --- a/src/Doc/ROOT Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/ROOT Sun May 23 20:34:43 2021 +0200 @@ -1,23 +1,23 @@ chapter Doc session Classes (doc) in "Classes" = HOL + - options [document_variants = "classes", quick_and_dirty] + options [document_logo = "Isar", document_bibliography, + document_variants = "classes", quick_and_dirty] theories [document = false] Setup theories Classes document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" "isar.sty" "manual.bib" document_files - "build" "root.tex" "style.sty" session Codegen (doc) in "Codegen" = HOL + - options [document_variants = "codegen", print_mode = "no_brackets,iff"] + options [document_logo = "Isar", document_bibliography, document_variants = "codegen", + print_mode = "no_brackets,iff"] sessions "HOL-Library" theories [document = false] @@ -32,35 +32,31 @@ Adaptation Further document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" "isar.sty" "manual.bib" document_files - "build" "root.tex" "style.sty" session Corec (doc) in "Corec" = Datatypes + - options [document_variants = "corec"] + options [document_bibliography, document_variants = "corec"] theories Corec document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" "isar.sty" "manual.bib" document_files - "build" "root.tex" "style.sty" session Datatypes (doc) in "Datatypes" = HOL + - options [document_variants = "datatypes"] + options [document_bibliography, document_variants = "datatypes"] sessions "HOL-Library" theories [document = false] @@ -68,20 +64,18 @@ theories Datatypes document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" "isar.sty" "manual.bib" document_files - "build" "root.tex" "style.sty" session Eisbach (doc) in "Eisbach" = HOL + - options [document_variants = "eisbach", quick_and_dirty, - print_mode = "no_brackets,iff", show_question_marks = false] + options [document_logo = "Eisbach", document_bibliography, document_variants = "eisbach", + quick_and_dirty, print_mode = "no_brackets,iff", show_question_marks = false] sessions "HOL-Eisbach" theories [document = false] @@ -90,7 +84,6 @@ Preface Manual document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" @@ -99,22 +92,20 @@ "underscore.sty" "manual.bib" document_files - "build" "root.tex" "style.sty" session Functions (doc) in "Functions" = HOL + - options [document_variants = "functions", skip_proofs = false, quick_and_dirty] + options [document_bibliography, document_variants = "functions", + skip_proofs = false, quick_and_dirty] theories Functions document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" "isar.sty" "manual.bib" document_files - "build" "conclusion.tex" "intro.tex" "root.tex" @@ -130,9 +121,9 @@ "prelude.tex" session Intro (doc) in "Intro" = Pure + - options [document_variants = "intro"] + options [document_logo = "_", document_bibliography, document_build = "build", + document_variants = "intro"] document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" @@ -146,7 +137,8 @@ "root.tex" session Implementation (doc) in "Implementation" = HOL + - options [document_variants = "implementation", quick_and_dirty] + options [document_logo = "Isar", document_bibliography, + document_variants = "implementation", quick_and_dirty] theories Eq Integration @@ -160,7 +152,6 @@ theories [parallel_proofs = 0] Logic document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" @@ -169,12 +160,12 @@ "underscore.sty" "manual.bib" document_files - "build" "root.tex" "style.sty" session Isar_Ref (doc) in "Isar_Ref" = HOL + - options [document_variants = "isar-ref", quick_and_dirty, thy_output_source] + options [document_logo = "Isar", document_bibliography, document_variants = "isar-ref", + quick_and_dirty, thy_output_source] sessions "HOL-Library" theories @@ -193,7 +184,6 @@ Quick_Reference Symbols document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" @@ -202,15 +192,14 @@ "underscore.sty" "manual.bib" document_files - "build" "isar-vm.pdf" "isar-vm.svg" "root.tex" - "showsymbols" "style.sty" session JEdit (doc) in "JEdit" = HOL + - options [document_variants = "jedit", thy_output_source] + options [document_logo = "jEdit", document_bibliography, document_variants = "jedit", + thy_output_source] theories JEdit document_files (in "..") @@ -219,7 +208,6 @@ "isar.sty" "manual.bib" "pdfsetup.sty" - "prepare_document" "ttbox.sty" "underscore.sty" document_files (in "../Isar_Ref/document") @@ -227,7 +215,6 @@ document_files "auto-tools.png" "bibtex-mode.png" - "build" "cite-completion.png" "isabelle-jedit.png" "markdown-document.png" @@ -247,54 +234,52 @@ "theories.png" session Sugar (doc) in "Sugar" = HOL + - options [document_variants = "sugar"] + options [document_bibliography, document_variants = "sugar"] sessions "HOL-Library" theories Sugar document_files (in "..") - "prepare_document" "pdfsetup.sty" document_files - "build" "root.bib" "root.tex" session Locales (doc) in "Locales" = HOL + - options [document_variants = "locales", thy_output_margin = 65, skip_proofs = false] + options [document_bibliography, document_variants = "locales", + thy_output_margin = 65, skip_proofs = false] theories Examples1 Examples2 Examples3 document_files (in "..") - "prepare_document" "pdfsetup.sty" document_files - "build" "root.bib" "root.tex" session Logics (doc) in "Logics" = Pure + - options [document_variants = "logics"] + options [document_logo = "_", document_bibliography, document_build = "build", + document_variants = "logics"] document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" "ttbox.sty" "manual.bib" + document_files (in "../Intro/document") + "build" document_files "CTT.tex" "HOL.tex" "LK.tex" "Sequents.tex" - "build" "preface.tex" "root.tex" "syntax.tex" session Logics_ZF (doc) in "Logics_ZF" = ZF + - options [document_variants = "logics-ZF", print_mode = "brackets", - thy_output_source] + options [document_logo = "ZF", document_bibliography, document_build = "build", + document_variants = "logics-ZF", print_mode = "brackets", thy_output_source] sessions FOL theories @@ -304,17 +289,17 @@ If ZF_Isar document_files (in "..") - "prepare_document" "pdfsetup.sty" "isar.sty" "ttbox.sty" "manual.bib" + document_files (in "../Intro/document") + "build" document_files (in "../Logics/document") "syntax.tex" document_files "FOL.tex" "ZF.tex" - "build" "logics.sty" "root.tex" @@ -322,25 +307,22 @@ options [document_variants = "main"] theories Main_Doc document_files (in "..") - "prepare_document" "pdfsetup.sty" document_files - "build" "root.tex" session Nitpick (doc) in "Nitpick" = Pure + - options [document_variants = "nitpick"] + options [document_logo = "Nitpick", document_bibliography, document_variants = "nitpick"] document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "manual.bib" document_files - "build" "root.tex" session Prog_Prove (doc) in "Prog_Prove" = HOL + - options [document_variants = "prog-prove", show_question_marks = false] + options [document_logo = "HOL", document_bibliography, document_variants = "prog-prove", + show_question_marks = false] theories Basics Bool_nat_list @@ -351,11 +333,9 @@ document_files (in ".") "MyList.thy" document_files (in "..") - "prepare_document" "pdfsetup.sty" document_files "bang.pdf" - "build" "intro-isabelle.tex" "prelude.tex" "root.bib" @@ -363,18 +343,17 @@ "svmono.cls" session Sledgehammer (doc) in "Sledgehammer" = Pure + - options [document_variants = "sledgehammer"] + options [document_logo = "S/H", document_bibliography, document_variants = "sledgehammer"] document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "manual.bib" document_files - "build" "root.tex" session System (doc) in "System" = Pure + - options [document_variants = "system", thy_output_source] + options [document_logo = "_", document_bibliography, document_variants = "system", + thy_output_source] sessions "HOL-Library" theories @@ -386,7 +365,6 @@ Phabricator Misc document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" @@ -397,11 +375,11 @@ document_files (in "../Isar_Ref/document") "style.sty" document_files - "build" "root.tex" session Tutorial (doc) in "Tutorial" = HOL + - options [document_variants = "tutorial", print_mode = "brackets", skip_proofs = false] + options [document_logo = "HOL", document_bibliography, document_build = "build", + document_variants = "tutorial", print_mode = "brackets", skip_proofs = false] directories "Advanced" "CTL" "CodeGen" "Datatype" "Documents" "Fun" "Ifexpr" "Inductive" "Misc" "Protocol" "Rules" "Sets" "ToyList" "Trie" "Types" theories [document = false] @@ -494,7 +472,7 @@ "types0.tex" session Typeclass_Hierarchy (doc) in "Typeclass_Hierarchy" = HOL + - options [document_variants = "typeclass_hierarchy"] + options [document_logo = "Isar", document_bibliography, document_variants = "typeclass_hierarchy"] sessions "HOL-Library" theories [document = false] @@ -502,13 +480,11 @@ theories Typeclass_Hierarchy document_files (in "..") - "prepare_document" "pdfsetup.sty" "iman.sty" "extra.sty" "isar.sty" "manual.bib" document_files - "build" "root.tex" "style.sty" diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Sledgehammer/document/build --- a/src/Doc/Sledgehammer/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo -o isabelle_sledgehammer.pdf "S/H" -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Sledgehammer/document/root.tex --- a/src/Doc/Sledgehammer/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Sledgehammer/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -54,7 +54,7 @@ %\renewcommand\labelitemi{$\bullet$} \renewcommand\labelitemi{\raise.065ex\hbox{\small\textbullet}} -\title{\includegraphics[scale=0.5]{isabelle_sledgehammer} \\[4ex] +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] Hammering Away \\[\smallskipamount] \Large A User's Guide to Sledgehammer for Isabelle/HOL} \author{\hbox{} \\ diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Sugar/document/build --- a/src/Doc/Sugar/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/System/Environment.thy --- a/src/Doc/System/Environment.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/System/Environment.thy Sun May 23 20:34:43 2021 +0200 @@ -181,9 +181,10 @@ \<^descr>[@{setting_def ISABELLE_LINE_EDITOR}] specifies the line editor for the @{tool_ref console} interface. - \<^descr>[@{setting_def ISABELLE_PDFLATEX}, @{setting_def ISABELLE_BIBTEX}] refer to - {\LaTeX} related tools for Isabelle document preparation (see also - \secref{sec:tool-latex}). + \<^descr>[@{setting_def ISABELLE_PDFLATEX}, @{setting_def ISABELLE_LUALATEX}, + @{setting_def ISABELLE_BIBTEX}, @{setting_def ISABELLE_MAKEINDEX}] refer to + {\LaTeX}-related tools for Isabelle document preparation (see also + \secref{sec:tool-document}). \<^descr>[@{setting_def ISABELLE_TOOLS}] is a colon separated list of directories that are scanned by @{executable isabelle} for external utility programs diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/System/Presentation.thy --- a/src/Doc/System/Presentation.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/System/Presentation.thy Sun May 23 20:34:43 2021 +0200 @@ -22,8 +22,7 @@ with the PDF into the given directory (relative to the session directory). Alternatively, @{tool_ref document} may be used to turn the generated - {\LaTeX} sources of a session (exports from its build database) into PDF, - using suitable invocations of @{tool_ref latex}. + {\LaTeX} sources of a session (exports from its build database) into PDF. \ @@ -161,12 +160,20 @@ \<^medskip> Isabelle is usually smart enough to create the PDF from the given \<^verbatim>\root.tex\ and optional \<^verbatim>\root.bib\ (bibliography) and \<^verbatim>\root.idx\ (index) - using standard {\LaTeX} tools. Alternatively, \isakeyword{document\_files} - in the session \<^verbatim>\ROOT\ may include an executable \<^verbatim>\build\ script to take - care of that. It is invoked with command-line arguments for the document - format (\<^verbatim>\pdf\) and the document variant name. The script needs to produce - corresponding output files, e.g.\ \<^verbatim>\root.pdf\ for default document variants - (the main work can be delegated to @{tool latex}). \ + using standard {\LaTeX} tools. Actual command-lines are given by settings + @{setting_ref ISABELLE_PDFLATEX}, @{setting_ref ISABELLE_LUALATEX}, + @{setting_ref ISABELLE_BIBTEX}, @{setting_ref ISABELLE_MAKEINDEX}: these + variables are used without quoting in shell scripts, and thus may contain + additional options. + + Alternatively, the session \<^verbatim>\ROOT\ may include an option + \<^verbatim>\document_build=build\ together with an executable \<^verbatim>\build\ script in + \isakeyword{document\_files}: it is invoked with command-line arguments for + the document format (\<^verbatim>\pdf\) and the document variant name. The script needs + to produce corresponding output files, e.g.\ \<^verbatim>\root.pdf\ for default + document variants. +\ + subsubsection \Examples\ @@ -177,47 +184,4 @@ @{verbatim [display] \isabelle document -v -V -O. FOL\} \ - -section \Running {\LaTeX} within the Isabelle environment - \label{sec:tool-latex}\ - -text \ - The @{tool_def latex} tool provides the basic interface for Isabelle - document preparation. Its usage is: - @{verbatim [display] -\Usage: isabelle latex [OPTIONS] [FILE] - - Options are: - -o FORMAT specify output format: pdf (default), bbl, idx, sty - - Run LaTeX (and related tools) on FILE (default root.tex), - producing the specified output format.\} - - Appropriate {\LaTeX}-related programs are run on the input file, according - to the given output format: @{executable pdflatex}, @{executable bibtex} - (for \<^verbatim>\bbl\), and @{executable makeindex} (for \<^verbatim>\idx\). The actual commands - are determined from the settings environment (@{setting ISABELLE_PDFLATEX} - etc.). - - The \<^verbatim>\sty\ output format causes the Isabelle style files to be updated from - the distribution. This is useful in special situations where the document - sources are to be processed another time by separate tools. -\ - - -subsubsection \Examples\ - -text \ - Invoking @{tool latex} by hand may be occasionally useful when debugging - failed attempts of the automatic document preparation stage of batch-mode - Isabelle. The abortive process leaves the sources at a certain place within - @{setting ISABELLE_BROWSER_INFO}, see the runtime error message for details. - This enables users to inspect {\LaTeX} runs in further detail, e.g.\ like - this: - - @{verbatim [display] -\cd "$(isabelle getenv -b ISABELLE_BROWSER_INFO)/Unsorted/Test/document" -isabelle latex -o pdf\} -\ - end diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/System/Sessions.thy --- a/src/Doc/System/Sessions.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/System/Sessions.thy Sun May 23 20:34:43 2021 +0200 @@ -238,6 +238,16 @@ is occasionally useful to control the global visibility of commands via session options (e.g.\ in \<^verbatim>\ROOT\). + \<^item> @{system_option_def "document_bibliography"} explicitly enables the use + of \<^verbatim>\bibtex\; the default is to check the presence of \<^verbatim>\root.bib\, but it + could have a different name. + + \<^item> @{system_option_def "document_preprocessor"} specifies the name of an + executable that is run within the document output directory, after + preparing the document sources and before the actual build process. This + allows to apply adhoc patches, without requiring a separate \<^verbatim>\build\ + script. + \<^item> @{system_option_def "threads"} determines the number of worker threads for parallel checking of theories and proofs. The default \0\ means that a sensible maximum value is determined by the underlying hardware. For diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/System/document/build --- a/src/Doc/System/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -isabelle logo -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/System/document/root.tex --- a/src/Doc/System/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/System/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -17,7 +17,7 @@ \isabellestyle{literal} \def\isastylett{\footnotesize\tt} -\title{\includegraphics[scale=0.5]{isabelle} \\[4ex] The Isabelle System Manual} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] The Isabelle System Manual} \author{\emph{Makarius Wenzel}} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Tutorial/document/build --- a/src/Doc/Tutorial/document/build Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Tutorial/document/build Sun May 23 20:34:43 2021 +0200 @@ -2,13 +2,9 @@ set -e -FORMAT="$1" -VARIANT="$2" - -isabelle logo HOL -isabelle latex -o "$FORMAT" -isabelle latex -o bbl +$ISABELLE_LUALATEX root +$ISABELLE_BIBTEX root +$ISABELLE_LUALATEX root +$ISABELLE_LUALATEX root ./isa-index root -isabelle latex -o "$FORMAT" -[ -f root.out ] && "$ISABELLE_HOME/src/Doc/fixbookmarks" root.out -isabelle latex -o "$FORMAT" +$ISABELLE_LUALATEX root diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Tutorial/document/isa-index --- a/src/Doc/Tutorial/document/isa-index Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Tutorial/document/isa-index Sun May 23 20:34:43 2021 +0200 @@ -20,4 +20,4 @@ s~\*\(\".\".\".\)~\1@\\\\isa {\1}~g s~\*\(\".\".\)~\1@\\\\isa {\1}~g s~\*\(\".\)~\1@\\\\isa {\1}~g -s~\*\([^ |!@{}][^ |!@{}]*\)~\1@\\\\isa {\1}~g" $1.idx | makeindex -c -q -o $1.ind +s~\*\([^ |!@{}][^ |!@{}]*\)~\1@\\\\isa {\1}~g" $1.idx | $ISABELLE_MAKEINDEX -o $1.ind diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Tutorial/document/root.tex --- a/src/Doc/Tutorial/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Tutorial/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -29,7 +29,7 @@ \begin{document} \title{ \begin{center} -\includegraphics[scale=.8]{isabelle_hol} +\includegraphics[scale=.8]{isabelle_logo} \\ \vspace{0.5cm} A Proof Assistant for Higher-Order Logic \end{center}} \author{Tobias Nipkow \quad Lawrence C. Paulson \quad Markus Wenzel%\\[1ex] diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Tutorial/document/tutorial.sty --- a/src/Doc/Tutorial/document/tutorial.sty Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Tutorial/document/tutorial.sty Sun May 23 20:34:43 2021 +0200 @@ -42,8 +42,6 @@ \newcommand\cmmdx[1]{\index{#1@\protect\isacommand{#1} (command)}} \newcommand\commdx[1]{\isacommand{#1}\index{#1@\protect\isacommand{#1} (command)}} \newcommand\methdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (method)}} -\newcommand\tooldx[1]{\isa{#1}\index{#1@\protect\isa{#1} (tool)}} -\newcommand\settdx[1]{\isa{#1}\index{#1@\protect\isa{#1} (setting)}} \newcommand\pgdx[1]{\pgmenu{#1}\index{#1@\protect\pgmenu{#1} (Proof General)}} %set argument in \bf font and index in ROMAN font (for definitions in text!) diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Typeclass_Hierarchy/document/build --- a/src/Doc/Typeclass_Hierarchy/document/build Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" -VARIANT="$2" - -"$ISABELLE_TOOL" logo Isar -"$ISABELLE_HOME/src/Doc/prepare_document" "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/Typeclass_Hierarchy/document/root.tex --- a/src/Doc/Typeclass_Hierarchy/document/root.tex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/Typeclass_Hierarchy/document/root.tex Sun May 23 20:34:43 2021 +0200 @@ -9,7 +9,7 @@ \hyphenation{Isar} \isadroptag{theory} -\title{\includegraphics[scale=0.5]{isabelle_isar} +\title{\includegraphics[scale=0.5]{isabelle_logo} \\[4ex] The {Isabelle/HOL} type-class hierarchy} \author{\emph{Florian Haftmann}} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/antiquote_setup.ML --- a/src/Doc/antiquote_setup.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/antiquote_setup.ML Sun May 23 20:34:43 2021 +0200 @@ -33,104 +33,20 @@ | clean_name s = s |> translate (fn "_" => "-" | "\" => "-" | c => c); -(* ML text *) - -local - -fun ml_val (toks1, []) = ML_Lex.read "fn _ => (" @ toks1 @ ML_Lex.read ");" - | ml_val (toks1, toks2) = - ML_Lex.read "fn _ => (" @ toks1 @ ML_Lex.read " : " @ toks2 @ ML_Lex.read ");"; - -fun ml_op (toks1, []) = ML_Lex.read "fn _ => (op " @ toks1 @ ML_Lex.read ");" - | ml_op (toks1, toks2) = - ML_Lex.read "fn _ => (op " @ toks1 @ ML_Lex.read " : " @ toks2 @ ML_Lex.read ");"; - -fun ml_type (toks1, []) = ML_Lex.read "val _ = NONE : (" @ toks1 @ ML_Lex.read ") option;" - | ml_type (toks1, toks2) = - ML_Lex.read "val _ = [NONE : (" @ toks1 @ ML_Lex.read ") option, NONE : (" @ - toks2 @ ML_Lex.read ") option];"; - -fun ml_exception (toks1, []) = ML_Lex.read "fn _ => (" @ toks1 @ ML_Lex.read " : exn);" - | ml_exception (toks1, toks2) = - ML_Lex.read "fn _ => (" @ toks1 @ ML_Lex.read " : " @ toks2 @ ML_Lex.read " -> exn);"; - -fun ml_structure (toks, _) = - ML_Lex.read "functor XXX() = struct structure XX = " @ toks @ ML_Lex.read " end;"; - -fun ml_functor (Antiquote.Text tok :: _, _) = - ML_Lex.read "ML_Env.check_functor " @ - ML_Lex.read (ML_Syntax.print_string (ML_Lex.content_of tok)) - | ml_functor _ = raise Fail "Bad ML functor specification"; - -val is_name = - ML_Lex.kind_of #> (fn kind => kind = ML_Lex.Ident orelse kind = ML_Lex.Long_Ident); - -fun ml_name txt = - (case filter is_name (ML_Lex.tokenize txt) of - toks as [_] => ML_Lex.flatten toks - | _ => error ("Single ML name expected in input: " ^ quote txt)); - -fun prep_ml source = - (#1 (Input.source_content source), ML_Lex.read_source source); - -fun index_ml name kind ml = Thy_Output.antiquotation_raw name - (Scan.lift (Args.text_input -- Scan.option (Args.colon |-- Args.text_input))) - (fn ctxt => fn (source1, opt_source2) => - let - val (txt1, toks1) = prep_ml source1; - val (txt2, toks2) = - (case opt_source2 of - SOME source => prep_ml source - | NONE => ("", [])); - - val txt = - if txt2 = "" then txt1 - else if kind = "type" then txt1 ^ " = " ^ txt2 - else if kind = "exception" then txt1 ^ " of " ^ txt2 - else if Symbol_Pos.is_identifier (Long_Name.base_name (ml_name txt1)) - then txt1 ^ ": " ^ txt2 - else txt1 ^ " : " ^ txt2; - val txt' = if kind = "" then txt else kind ^ " " ^ txt; - - val pos = Input.pos_of source1; - val _ = - ML_Context.eval_in (SOME ctxt) ML_Compiler.flags pos (ml (toks1, toks2)) - handle ERROR msg => error (msg ^ Position.here pos); - val kind' = if kind = "" then "ML" else "ML " ^ kind; - in - Latex.block - [Latex.string ("\\indexdef{}{" ^ kind' ^ "}{" ^ clean_string (ml_name txt1) ^ "}"), - Thy_Output.verbatim ctxt txt'] - end); - -in - -val _ = - Theory.setup - (index_ml \<^binding>\index_ML\ "" ml_val #> - index_ml \<^binding>\index_ML_op\ "infix" ml_op #> - index_ml \<^binding>\index_ML_type\ "type" ml_type #> - index_ml \<^binding>\index_ML_exception\ "exception" ml_exception #> - index_ml \<^binding>\index_ML_structure\ "structure" ml_structure #> - index_ml \<^binding>\index_ML_functor\ "functor" ml_functor); - -end; - - (* named theorems *) val _ = - Theory.setup (Thy_Output.antiquotation_raw \<^binding>\named_thms\ + Theory.setup (Document_Output.antiquotation_raw \<^binding>\named_thms\ (Scan.repeat (Attrib.thm -- Scan.lift (Args.parens Args.name))) (fn ctxt => map (fn (thm, name) => Output.output (Document_Antiquotation.format ctxt - (Document_Antiquotation.delimit ctxt (Thy_Output.pretty_thm ctxt thm))) ^ + (Document_Antiquotation.delimit ctxt (Document_Output.pretty_thm ctxt thm))) ^ enclose "\\rulename{" "}" (Output.output name)) #> space_implode "\\par\\smallskip%\n" #> Latex.string #> single - #> Thy_Output.isabelle ctxt)); + #> Document_Output.isabelle ctxt)); (* Isabelle/Isar entities (with index) *) @@ -150,7 +66,7 @@ val arg = enclose "{" "}" o clean_string; fun entity check markup binding index = - Thy_Output.antiquotation_raw + Document_Output.antiquotation_raw (binding |> Binding.map_name (fn name => name ^ (case index of NONE => "" | SOME true => "_def" | SOME false => "_ref"))) (Scan.lift (Scan.optional (Args.parens Args.name) "" -- Args.name_position)) @@ -207,4 +123,36 @@ end; + +(* show symbols *) + +val _ = + Theory.setup (Document_Output.antiquotation_raw \<^binding>\show_symbols\ (Scan.succeed ()) + (fn _ => fn _ => + let + val symbol_name = + unprefix "\\newcommand{\\isasym" + #> raw_explode + #> take_prefix Symbol.is_ascii_letter + #> implode; + + val symbols = + File.read \<^file>\~~/lib/texinputs/isabellesym.sty\ + |> split_lines + |> map_filter (fn line => + (case try symbol_name line of + NONE => NONE + | SOME "" => NONE + | SOME name => SOME ("\\verb,\\" ^ "<" ^ name ^ ">, & {\\isasym" ^ name ^ "}"))); + + val eol = "\\\\\n"; + fun table (a :: b :: rest) = a ^ " & " ^ b ^ eol :: table rest + | table [a] = [a ^ eol] + | table [] = []; + in + Latex.string + ("\\begin{supertabular}{ll@{\\qquad}ll}\n" ^ implode (table symbols) ^ + "\\end{supertabular}\n") + end)) + end; diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/fixbookmarks --- a/src/Doc/fixbookmarks Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -perl -pi -e 's/\\([a-zA-Z]+)\s*/$1/g; s/\$//g; s/^BOOKMARK/\\BOOKMARK/g;' "$@" diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/iman.sty --- a/src/Doc/iman.sty Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/iman.sty Sun May 23 20:34:43 2021 +0200 @@ -31,16 +31,10 @@ \newcommand\mltydx[1]{{\tt#1}\index{#1@{\tt#1} ML type}} \newcommand\xdx[1]{{\tt#1}\index{#1@{\tt#1} exception}} -\newcommand\ndx[1]{{\tt#1}\index{#1@{\tt#1} nonterminal}} -\newcommand\ndxbold[1]{{\tt#1}\index{#1@{\tt#1} nonterminal|bold}} - \newcommand\cldx[1]{{\tt#1}\index{#1@{\tt#1} class}} \newcommand\tydx[1]{\textit{#1}\index{#1@{\textit{#1}} type}} \newcommand\thydx[1]{{\tt#1}\index{#1@{\tt#1} theory}} -\newcommand\tooldx[1]{{\tt#1}\index{#1@{\tt#1} tool}} -\newcommand\settdx[1]{{\tt#1}\index{#1@{\tt#1} setting}} - %set argument in \tt font; at the same time, index using * prefix \newcommand\rmindex[1]{{#1}\index{#1}\@} \newcommand\ttindex[1]{{\tt#1}\index{*#1}\@} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/isar.sty --- a/src/Doc/isar.sty Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/isar.sty Sun May 23 20:34:43 2021 +0200 @@ -9,10 +9,6 @@ \newcommand{\isasystem}[1]{{\def\isacharminus{-}\def\isacharunderscore{\_}\isadigitreset\tt #1}} \newcommand{\isatool}[1]{{\def\isacharminus{-}\def\isacharunderscore{\_}\isadigitreset\tt isabelle #1}} -\newcommand{\indexoutertoken}[1]{\indexdef{}{syntax}{#1}} -\newcommand{\indexouternonterm}[1]{\indexdef{}{syntax}{#1}} -\newcommand{\indexisarelem}[1]{\indexdef{}{element}{#1}} - \newcommand{\isasymIF}{\isakeyword{if}} \newcommand{\isasymFOR}{\isakeyword{for}} \newcommand{\isasymAND}{\isakeyword{and}} diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/more_antiquote.ML --- a/src/Doc/more_antiquote.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/more_antiquote.ML Sun May 23 20:34:43 2021 +0200 @@ -10,7 +10,7 @@ (* class specifications *) val _ = - Theory.setup (Thy_Output.antiquotation_pretty \<^binding>\class_spec\ (Scan.lift Args.name) + Theory.setup (Document_Output.antiquotation_pretty \<^binding>\class_spec\ (Scan.lift Args.name) (fn ctxt => fn s => let val thy = Proof_Context.theory_of ctxt; @@ -21,7 +21,7 @@ (* code theorem antiquotation *) val _ = - Theory.setup (Thy_Output.antiquotation_pretty \<^binding>\code_thms\ Args.term + Theory.setup (Document_Output.antiquotation_pretty \<^binding>\code_thms\ Args.term (fn ctxt => fn raw_const => let val thy = Proof_Context.theory_of ctxt; @@ -33,6 +33,6 @@ |> these |> map_filter (fn (_, (some_thm, proper)) => if proper then some_thm else NONE) |> map (HOLogic.mk_obj_eq o Variable.import_vars ctxt o Axclass.overload ctxt); - in Pretty.chunks (map (Thy_Output.pretty_thm ctxt) thms) end)); + in Pretty.chunks (map (Document_Output.pretty_thm ctxt) thms) end)); end; diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/prepare_document --- a/src/Doc/prepare_document Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -e - -FORMAT="$1" - -isabelle latex -o sty -cp "$ISABELLE_HOME/src/Doc/pdfsetup.sty" . - -isabelle latex -o "$FORMAT" -isabelle latex -o bbl -[ -f root.idx ] && "$ISABELLE_HOME/src/Doc/sedindex" root -isabelle latex -o "$FORMAT" -[ -f root.out ] && "$ISABELLE_HOME/src/Doc/fixbookmarks" root.out -isabelle latex -o "$FORMAT" - diff -r 58bd53caf800 -r 6b4c47666267 src/Doc/sedindex --- a/src/Doc/sedindex Wed May 19 14:17:40 2021 +0100 +++ b/src/Doc/sedindex Sun May 23 20:34:43 2021 +0200 @@ -18,4 +18,4 @@ s~\*\(\".\".\".\)~\1@{\\\\tt \1}~g s~\*\(\".\".\)~\1@{\\\\tt \1}~g s~\*\(\".\)~\1@{\\\\tt \1}~g -s~\*\([^ |!@{}][^ |!@{}]*\)~\1@{\\\\tt \1}~g" $1.idx | makeindex -c -q -o $1.ind +s~\*\([^ |!@{}][^ |!@{}]*\)~\1@{\\\\tt \1}~g" $1.idx | $ISABELLE_MAKEINDEX -o $1.ind diff -r 58bd53caf800 -r 6b4c47666267 src/HOL/Library/Code_Lazy.thy --- a/src/HOL/Library/Code_Lazy.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/HOL/Library/Code_Lazy.thy Sun May 23 20:34:43 2021 +0200 @@ -182,7 +182,7 @@ \object Lazy { final class Lazy[A] (f: Unit => A) { var evaluated = false; - lazy val x: A = f () + lazy val x: A = f(()) def get() : A = { evaluated = true; @@ -210,7 +210,7 @@ x: Lazy[A], dummy: Term) : Term = { if (x.evaluated) - app(const("Code_Lazy.delay")(funT(funT(unitT)(ty))(lazyT(ty))))(abs("_")(unitT)(term_of(x.get))) + app(const("Code_Lazy.delay")(funT(funT(unitT)(ty))(lazyT(ty))))(abs("_")(unitT)(term_of(x.get()))) else app(const("Code_Lazy.delay")(funT(funT(unitT)(ty))(lazyT(ty))))(const("Pure.dummy_pattern")(funT(unitT)(ty))) } diff -r 58bd53caf800 -r 6b4c47666267 src/HOL/Library/LaTeXsugar.thy --- a/src/HOL/Library/LaTeXsugar.thy Wed May 19 14:17:40 2021 +0100 +++ b/src/HOL/Library/LaTeXsugar.thy Sun May 23 20:34:43 2021 +0200 @@ -97,11 +97,11 @@ "_asm" :: "prop \ asms" ("_") setup \ - Thy_Output.antiquotation_pretty_source_embedded \<^binding>\const_typ\ + Document_Output.antiquotation_pretty_source_embedded \<^binding>\const_typ\ (Scan.lift Args.embedded_inner_syntax) (fn ctxt => fn c => let val tc = Proof_Context.read_const {proper = false, strict = false} ctxt c in - Pretty.block [Thy_Output.pretty_term ctxt tc, Pretty.str " ::", + Pretty.block [Document_Output.pretty_term ctxt tc, Pretty.str " ::", Pretty.brk 1, Syntax.pretty_typ ctxt (fastype_of tc)] end) \ diff -r 58bd53caf800 -r 6b4c47666267 src/HOL/Tools/Ctr_Sugar/ctr_sugar.ML --- a/src/HOL/Tools/Ctr_Sugar/ctr_sugar.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/HOL/Tools/Ctr_Sugar/ctr_sugar.ML Sun May 23 20:34:43 2021 +0200 @@ -1200,7 +1200,7 @@ local fun antiquote_setup binding co = - Thy_Output.antiquotation_pretty_source_embedded binding + Document_Output.antiquotation_pretty_source_embedded binding ((Scan.ahead (Scan.lift Parse.not_eof) >> Token.pos_of) -- Args.type_name {proper = true, strict = true}) (fn ctxt => fn (pos, type_name) => diff -r 58bd53caf800 -r 6b4c47666267 src/HOL/Tools/value_command.ML --- a/src/HOL/Tools/value_command.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/HOL/Tools/value_command.ML Sun May 23 20:34:43 2021 +0200 @@ -73,10 +73,10 @@ >> (fn ((name, modes), t) => Toplevel.keep (value_cmd name modes t))); val _ = Theory.setup - (Thy_Output.antiquotation_pretty_source_embedded \<^binding>\value\ + (Document_Output.antiquotation_pretty_source_embedded \<^binding>\value\ (Scan.lift opt_evaluator -- Term_Style.parse -- Args.term) (fn ctxt => fn ((name, style), t) => - Thy_Output.pretty_term ctxt (style (value_select name ctxt t))) + Document_Output.pretty_term ctxt (style (value_select name ctxt t))) #> add_evaluator (\<^binding>\simp\, Code_Simp.dynamic_value) #> snd #> add_evaluator (\<^binding>\nbe\, Nbe.dynamic_value) #> snd #> add_evaluator (\<^binding>\code\, Code_Evaluation.dynamic_value_strict) #> snd); diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Admin/build_csdp.scala --- a/src/Pure/Admin/build_csdp.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Admin/build_csdp.scala Sun May 23 20:34:43 2021 +0200 @@ -23,13 +23,13 @@ def print: Option[String] = if (changed.isEmpty) None else - Some(" * " + platform + ":\n" + changed.map(p => " " + p._1 + "=" + p._2) + Some(" * " + platform + ":\n" + changed.map(p => " " + Properties.Eq(p)) .mkString("\n")) def change(path: Path): Unit = { - def change_line(line: String, entry: (String, String)): String = - line.replaceAll(entry._1 + "=.*", entry._1 + "=" + entry._2) + def change_line(line: String, p: (String, String)): String = + line.replaceAll(p._1 + "=.*", Properties.Eq(p)) File.change(path, s => split_lines(s).map(line => changed.foldLeft(line)(change_line)).mkString("\n")) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Admin/build_doc.scala --- a/src/Pure/Admin/build_doc.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Admin/build_doc.scala Sun May 23 20:34:43 2021 +0200 @@ -55,7 +55,7 @@ progress.echo("Documentation " + quote(doc) + " ...") using(store.open_database_context())(db_context => - Presentation.build_documents(session, deps, db_context, + Document_Build.build_documents(Document_Build.context(session, deps, db_context), output_pdf = Some(Path.explode("~~/doc")))) None } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Admin/build_log.scala --- a/src/Pure/Admin/build_log.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Admin/build_log.scala Sun May 23 20:34:43 2021 +0200 @@ -60,15 +60,10 @@ object Entry { def unapply(s: String): Option[Entry] = - s.indexOf('=') match { - case -1 => None - case i => - val a = s.substring(0, i) - val b = Library.perhaps_unquote(s.substring(i + 1)) - Some((a, b)) - } - def apply(a: String, b: String): String = a + "=" + quote(b) - def getenv(a: String): String = apply(a, Isabelle_System.getenv(a)) + for { (a, b) <- Properties.Eq.unapply(s) } + yield (a, Library.perhaps_unquote(b)) + def getenv(a: String): String = + Properties.Eq(a, quote(Isabelle_System.getenv(a))) } def show(): String = @@ -231,11 +226,8 @@ /* settings */ - def get_setting(a: String): Option[Settings.Entry] = - lines.find(_.startsWith(a + "=")) match { - case Some(line) => Settings.Entry.unapply(line) - case None => None - } + def get_setting(name: String): Option[Settings.Entry] = + lines.collectFirst({ case Settings.Entry(a, b) if a == name => a -> b }) def get_all_settings: Settings.T = for { c <- Settings.all_settings; entry <- get_setting(c.name) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Admin/components.scala --- a/src/Pure/Admin/components.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Admin/components.scala Sun May 23 20:34:43 2021 +0200 @@ -339,7 +339,7 @@ Build and publish Isabelle components as .tar.gz archives on SSH server, depending on system options: -""" + Library.prefix_lines(" ", show_options) + "\n", +""" + Library.indent_lines(2, show_options) + "\n", "P" -> (_ => publish = true), "f" -> (_ => force = true), "o:" -> (arg => options = options + arg), diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/General/exn.scala --- a/src/Pure/General/exn.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/General/exn.scala Sun May 23 20:34:43 2021 +0200 @@ -119,8 +119,7 @@ /* message */ def user_message(exn: Throwable): Option[String] = - if (exn.getClass == classOf[RuntimeException] || - exn.getClass == classOf[User_Error]) + if (exn.isInstanceOf[User_Error] || exn.getClass == classOf[RuntimeException]) { Some(proper_string(exn.getMessage) getOrElse "Error") } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/General/http.scala --- a/src/Pure/General/http.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/General/http.scala Sun May 23 20:34:43 2021 +0200 @@ -200,10 +200,10 @@ sealed case class Arg(method: String, uri: URI, request: Bytes) { def decode_properties: Properties.T = - space_explode('&', request.text).map(s => - space_explode('=', s) match { - case List(a, b) => Url.decode(a) -> Url.decode(b) - case _ => error("Malformed key-value pair in HTTP/POST: " + quote(s)) + space_explode('&', request.text).map( + { + case Properties.Eq(a, b) => Url.decode(a) -> Url.decode(b) + case s => error("Malformed key-value pair in HTTP/POST: " + quote(s)) }) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/General/path.scala --- a/src/Pure/General/path.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/General/path.scala Sun May 23 20:34:43 2021 +0200 @@ -263,7 +263,7 @@ case Path.Variable(s) => val path = Path.explode(Isabelle_System.getenv_strict(s, env)) if (path.elems.exists(_.isInstanceOf[Path.Variable])) - error("Illegal path variable nesting: " + s + "=" + path.toString) + error("Illegal path variable nesting: " + Properties.Eq(s, path.toString)) else path.elems case x => List(x) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/General/properties.scala --- a/src/Pure/General/properties.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/General/properties.scala Sun May 23 20:34:43 2021 +0200 @@ -14,6 +14,18 @@ type Entry = (java.lang.String, java.lang.String) type T = List[Entry] + object Eq + { + def apply(a: java.lang.String, b: java.lang.String): java.lang.String = a + "=" + b + def apply(entry: Entry): java.lang.String = apply(entry._1, entry._2) + + def unapply(str: java.lang.String): Option[Entry] = + { + val i = str.indexOf('=') + if (i <= 0) None else Some((str.substring(0, i), str.substring(i + 1))) + } + } + def defined(props: T, name: java.lang.String): java.lang.Boolean = props.exists({ case (x, _) => x == name }) diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/ML/ml_file.ML --- a/src/Pure/ML/ml_file.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/ML/ml_file.ML Sun May 23 20:34:43 2021 +0200 @@ -21,7 +21,7 @@ val provide = Resources.provide_file file; val source = Token.file_source file; - val _ = Thy_Output.check_comments (Context.proof_of gthy) (Input.source_explode source); + val _ = Document_Output.check_comments (Context.proof_of gthy) (Input.source_explode source); val flags: ML_Compiler.flags = {environment = environment, redirect = true, verbose = true, diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/ML/ml_statistics.scala --- a/src/Pure/ML/ml_statistics.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/ML/ml_statistics.scala Sun May 23 20:34:43 2021 +0200 @@ -58,12 +58,7 @@ { def progress_stdout(line: String): Unit = { - val props = - Library.space_explode(',', line).flatMap((entry: String) => - Library.space_explode('=', entry) match { - case List(a, b) => Some((a, b)) - case _ => None - }) + val props = Library.space_explode(',', line).flatMap(Properties.Eq.unapply) if (props.nonEmpty) consume(props) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/PIDE/command.ML --- a/src/Pure/PIDE/command.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/PIDE/command.ML Sun May 23 20:34:43 2021 +0200 @@ -226,7 +226,7 @@ else Toplevel.command_errors int tr st; fun check_token_comments ctxt tok = - (Thy_Output.check_comments ctxt (Input.source_explode (Token.input_of tok)); []) + (Document_Output.check_comments ctxt (Input.source_explode (Token.input_of tok)); []) handle exn => if Exn.is_interrupt exn then Exn.reraise exn else Runtime.exn_messages exn; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/PIDE/prover.scala --- a/src/Pure/PIDE/prover.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/PIDE/prover.scala Sun May 23 20:34:43 2021 +0200 @@ -50,7 +50,7 @@ kind + " [[" + res + "]]" else kind + " " + - (for ((x, y) <- properties) yield x + "=" + y).mkString("{", ",", "}") + " [[" + res + "]]" + (properties.map(Properties.Eq.apply)).mkString("{", ",", "}") + " [[" + res + "]]" } } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/PIDE/resources.ML --- a/src/Pure/PIDE/resources.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/PIDE/resources.ML Sun May 23 20:34:43 2021 +0200 @@ -198,7 +198,7 @@ in (name, multi) end; val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\scala_function\ + (Document_Output.antiquotation_verbatim_embedded \<^binding>\scala_function\ (Scan.lift Parse.embedded_position) (#1 oo check_scala_function) #> ML_Antiquotation.inline_embedded \<^binding>\scala_function\ (Args.context -- Scan.lift Parse.embedded_position @@ -424,11 +424,11 @@ in val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\session\ + (Document_Output.antiquotation_verbatim_embedded \<^binding>\session\ (Scan.lift Parse.embedded_position) check_session #> - Thy_Output.antiquotation_raw_embedded \<^binding>\path\ (document_antiq check_path) (K I) #> - Thy_Output.antiquotation_raw_embedded \<^binding>\file\ (document_antiq check_file) (K I) #> - Thy_Output.antiquotation_raw_embedded \<^binding>\dir\ (document_antiq check_dir) (K I) #> + Document_Output.antiquotation_raw_embedded \<^binding>\path\ (document_antiq check_path) (K I) #> + Document_Output.antiquotation_raw_embedded \<^binding>\file\ (document_antiq check_file) (K I) #> + Document_Output.antiquotation_raw_embedded \<^binding>\dir\ (document_antiq check_dir) (K I) #> ML_Antiquotation.value_embedded \<^binding>\path\ (ML_antiq check_path) #> ML_Antiquotation.value_embedded \<^binding>\file\ (ML_antiq check_file) #> ML_Antiquotation.value_embedded \<^binding>\dir\ (ML_antiq check_dir) #> diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/PIDE/yxml.scala --- a/src/Pure/PIDE/yxml.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/PIDE/yxml.scala Sun May 23 20:34:43 2021 +0200 @@ -71,12 +71,7 @@ else err("unbalanced element " + quote(name)) private def parse_attrib(source: CharSequence): (String, String) = - { - val s = source.toString - val i = s.indexOf('=') - if (i <= 0) err_attribute() - (s.substring(0, i), s.substring(i + 1)) - } + Properties.Eq.unapply(source.toString) getOrElse err_attribute() def parse_body(source: CharSequence, cache: XML.Cache = XML.Cache.none): XML.Body = diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/ROOT.ML --- a/src/Pure/ROOT.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/ROOT.ML Sun May 23 20:34:43 2021 +0200 @@ -304,7 +304,7 @@ ML_file "ML/ml_antiquotations2.ML"; ML_file "ML/ml_pid.ML"; ML_file "Thy/document_antiquotation.ML"; -ML_file "Thy/thy_output.ML"; +ML_file "Thy/document_output.ML"; ML_file "Thy/document_antiquotations.ML"; ML_file "General/graph_display.ML"; ML_file "pure_syn.ML"; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/ROOT.scala --- a/src/Pure/ROOT.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/ROOT.scala Sun May 23 20:34:43 2021 +0200 @@ -21,4 +21,3 @@ val proper_string = Library.proper_string _ def proper_list[A](list: List[A]): Option[List[A]] = Library.proper_list(list) } - diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/System/isabelle_platform.scala --- a/src/Pure/System/isabelle_platform.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/System/isabelle_platform.scala Sun May 23 20:34:43 2021 +0200 @@ -29,10 +29,7 @@ val result = ssh.execute("bash -c " + Bash.string(script)).check new Isabelle_Platform( result.out_lines.map(line => - space_explode('=', line) match { - case List(a, b) => (a, b) - case _ => error("Bad output: " + quote(result.out)) - })) + Properties.Eq.unapply(line) getOrElse error("Bad output: " + quote(result.out)))) } } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/System/isabelle_system.scala --- a/src/Pure/System/isabelle_system.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/System/isabelle_system.scala Sun May 23 20:34:43 2021 +0200 @@ -128,11 +128,11 @@ if (rc != 0) error(output) val entries = - (for (entry <- space_explode('\u0000', File.read(dump)) if entry != "") yield { - val i = entry.indexOf('=') - if (i <= 0) entry -> "" - else entry.substring(0, i) -> entry.substring(i + 1) - }).toMap + space_explode('\u0000', File.read(dump)).flatMap( + { + case Properties.Eq(a, b) => Some(a -> b) + case s => if (s.isEmpty || s.startsWith("=")) None else Some(s -> "") + }).toMap entries + ("PATH" -> entries("PATH_JVM")) - "PATH_JVM" } finally { dump.delete } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/System/isabelle_tool.ML --- a/src/Pure/System/isabelle_tool.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/System/isabelle_tool.ML Sun May 23 20:34:43 2021 +0200 @@ -38,7 +38,7 @@ val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\tool\ + (Document_Output.antiquotation_verbatim_embedded \<^binding>\tool\ (Scan.lift Parse.embedded_position) check); end; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/System/isabelle_tool.scala --- a/src/Pure/System/isabelle_tool.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/System/isabelle_tool.scala Sun May 23 20:34:43 2021 +0200 @@ -187,6 +187,7 @@ Build_Docker.isabelle_tool, Build_Job.isabelle_tool, Doc.isabelle_tool, + Document_Build.isabelle_tool, Dump.isabelle_tool, Export.isabelle_tool, ML_Process.isabelle_tool, @@ -198,7 +199,6 @@ Phabricator.isabelle_tool2, Phabricator.isabelle_tool3, Phabricator.isabelle_tool4, - Presentation.isabelle_tool, Profiling_Report.isabelle_tool, Server.isabelle_tool, Sessions.isabelle_tool, diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/System/options.scala --- a/src/Pure/System/options.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/System/options.scala Sun May 23 20:34:43 2021 +0200 @@ -355,12 +355,10 @@ } def + (str: String): Options = - { - str.indexOf('=') match { - case -1 => this + (str, None) - case i => this + (str.substring(0, i), str.substring(i + 1)) + str match { + case Properties.Eq(a, b) => this + (a, b) + case _ => this + (str, None) } - } def ++ (specs: List[Options.Spec]): Options = specs.foldLeft(this) { case (x, (y, z)) => x + (y, z) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/System/scala_compiler.ML --- a/src/Pure/System/scala_compiler.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/System/scala_compiler.ML Sun May 23 20:34:43 2021 +0200 @@ -65,21 +65,21 @@ val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\scala\ + (Document_Output.antiquotation_verbatim_embedded \<^binding>\scala\ (Scan.lift Args.embedded_position) (fn _ => fn (s, pos) => (static_check (s, pos); s)) #> - Thy_Output.antiquotation_raw_embedded \<^binding>\scala_type\ + Document_Output.antiquotation_raw_embedded \<^binding>\scala_type\ (Scan.lift (Args.embedded_position -- (types >> print_types))) (fn _ => fn ((t, pos), type_args) => (static_check ("type _Test_" ^ type_args ^ " = " ^ t ^ type_args, pos); scala_name (t ^ type_args))) #> - Thy_Output.antiquotation_raw_embedded \<^binding>\scala_object\ + Document_Output.antiquotation_raw_embedded \<^binding>\scala_object\ (Scan.lift Args.embedded_position) (fn _ => fn (x, pos) => (static_check ("val _test_ = " ^ x, pos); scala_name x)) #> - Thy_Output.antiquotation_raw_embedded \<^binding>\scala_method\ + Document_Output.antiquotation_raw_embedded \<^binding>\scala_method\ (Scan.lift (class -- Args.embedded_position -- types -- args)) (fn _ => fn (((class_context, (method, pos)), method_types), method_args) => let diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/bibtex.ML --- a/src/Pure/Thy/bibtex.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/bibtex.ML Sun May 23 20:34:43 2021 +0200 @@ -41,7 +41,7 @@ val _ = Theory.setup (Document_Antiquotation.setup_option \<^binding>\cite_macro\ (Config.put cite_macro) #> - Thy_Output.antiquotation_raw \<^binding>\cite\ + Document_Output.antiquotation_raw \<^binding>\cite\ (Scan.lift (Scan.option (Parse.verbatim || Parse.cartouche) -- Parse.and_list1 Args.name_position)) (fn ctxt => fn (opt, citations) => diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/bibtex.scala --- a/src/Pure/Thy/bibtex.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/bibtex.scala Sun May 23 20:34:43 2021 +0200 @@ -55,11 +55,13 @@ val log_path = dir + Path.explode(root_name).ext("blg") if (log_path.is_file) { val Error1 = """^(I couldn't open database file .+)$""".r - val Error2 = """^(.+)---line (\d+) of file (.+)""".r + val Error2 = """^(I found no .+)$""".r + val Error3 = """^(.+)---line (\d+) of file (.+)""".r Line.logical_lines(File.read(log_path)).flatMap(line => line match { case Error1(msg) => Some("Bibtex error: " + msg) - case Error2(msg, Value.Int(l), file) => + case Error2(msg) => Some("Bibtex error: " + msg) + case Error3(msg, Value.Int(l), file) => val path = File.standard_path(file) if (Path.is_wellformed(path)) { val pos = Position.Line_File(l, (dir + Path.explode(path)).canonical.implode) diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/document_antiquotation.ML --- a/src/Pure/Thy/document_antiquotation.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/document_antiquotation.ML Sun May 23 20:34:43 2021 +0200 @@ -35,6 +35,7 @@ val integer: string -> int val evaluate: (Symbol_Pos.T list -> Latex.text list) -> Proof.context -> Antiquote.text_antiquote -> Latex.text list + val approx_content: Proof.context -> string -> string end; structure Document_Antiquotation: DOCUMENT_ANTIQUOTATION = @@ -187,15 +188,52 @@ in +fun read_antiq ctxt ({range = (pos, _), body, ...}: Antiquote.antiq) = + let val keywords = Thy_Header.get_keywords' ctxt; + in Token.read_antiq keywords parse_antiq (body, pos) end; + fun evaluate eval_text ctxt antiq = (case antiq of Antiquote.Text ss => eval_text ss | Antiquote.Control {name, body, ...} => eval ctxt Position.none ([], Token.make_src name (if null body then [] else [Token.read_cartouche body])) - | Antiquote.Antiq {range = (pos, _), body, ...} => - let val keywords = Thy_Header.get_keywords' ctxt; - in eval ctxt pos (Token.read_antiq keywords parse_antiq (body, pos)) end); + | Antiquote.Antiq antiq => eval ctxt (#1 (#range antiq)) (read_antiq ctxt antiq)); + +end; + + +(* approximative content, e.g. for index entries *) + +local + +val strip_symbols = [Symbol.open_, Symbol.close, "'", "\"", "`"]; + +fun strip_symbol sym = + if member (op =) strip_symbols sym then "" + else + (case Symbol.decode sym of + Symbol.Char s => s + | Symbol.UTF8 s => s + | Symbol.Sym s => s + | Symbol.Control s => s + | _ => ""); + +fun strip_antiq _ (Antiquote.Text body) = map Symbol_Pos.symbol body + | strip_antiq _ (Antiquote.Control {body, ...}) = map Symbol_Pos.symbol body + | strip_antiq ctxt (Antiquote.Antiq antiq) = + read_antiq ctxt antiq |> #2 |> tl + |> maps (Symbol.explode o Token.content_of); + +in + +fun approx_content ctxt = + Symbol_Pos.explode0 + #> trim (Symbol.is_blank o Symbol_Pos.symbol) + #> Antiquote.parse_comments Position.none + #> maps (strip_antiq ctxt) + #> map strip_symbol + #> implode; end; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/document_antiquotations.ML --- a/src/Pure/Thy/document_antiquotations.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/document_antiquotations.ML Sun May 23 20:34:43 2021 +0200 @@ -14,14 +14,14 @@ type style = term -> term; fun pretty_term_style ctxt (style: style, t) = - Thy_Output.pretty_term ctxt (style t); + Document_Output.pretty_term ctxt (style t); fun pretty_thms_style ctxt (style: style, ths) = - map (fn th => Thy_Output.pretty_term ctxt (style (Thm.full_prop_of th))) ths; + map (fn th => Document_Output.pretty_term ctxt (style (Thm.full_prop_of th))) ths; fun pretty_term_typ ctxt (style: style, t) = let val t' = style t - in Thy_Output.pretty_term ctxt (Type.constraint (Term.fastype_of t') t') end; + in Document_Output.pretty_term ctxt (Type.constraint (Term.fastype_of t') t') end; fun pretty_term_typeof ctxt (style: style, t) = Syntax.pretty_typ ctxt (Term.fastype_of (style t)); @@ -31,7 +31,7 @@ val t = Const (c, Consts.type_scheme (Proof_Context.consts_of ctxt) c) handle TYPE (msg, _, _) => error msg; val (t', _) = yield_singleton (Variable.import_terms true) t ctxt; - in Thy_Output.pretty_term ctxt t' end; + in Document_Output.pretty_term ctxt t' end; fun pretty_abbrev ctxt s = let @@ -62,14 +62,12 @@ fun pretty_theory ctxt (name, pos) = (Theory.check {long = true} ctxt (name, pos); Pretty.str name); -val basic_entity = Thy_Output.antiquotation_pretty_source_embedded; +val basic_entity = Document_Output.antiquotation_pretty_source_embedded; fun basic_entities name scan pretty = Document_Antiquotation.setup name scan (fn {context = ctxt, source = src, argument = xs} => - Thy_Output.pretty_items_source ctxt {embedded = false} src (map (pretty ctxt) xs)); - -in + Document_Output.pretty_items_source ctxt {embedded = false} src (map (pretty ctxt) xs)); val _ = Theory.setup (basic_entity \<^binding>\prop\ (Term_Style.parse -- Args.prop) pretty_term_style #> @@ -87,9 +85,9 @@ basic_entities \<^binding>\full_prf\ Attrib.thms (pretty_prf true) #> Document_Antiquotation.setup \<^binding>\thm\ (Term_Style.parse -- Attrib.thms) (fn {context = ctxt, source = src, argument = arg} => - Thy_Output.pretty_items_source ctxt {embedded = false} src (pretty_thms_style ctxt arg))); + Document_Output.pretty_items_source ctxt {embedded = false} src (pretty_thms_style ctxt arg))); -end; +in end; (* Markdown errors *) @@ -102,48 +100,80 @@ error ("Bad Markdown structure: illegal " ^ quote (Binding.name_of binding) ^ Position.here (Position.no_range_position (#1 (Token.range_of src))))) -in - val _ = Theory.setup (markdown_error \<^binding>\item\ #> markdown_error \<^binding>\enum\ #> markdown_error \<^binding>\descr\); -end; +in end; (* control spacing *) val _ = Theory.setup - (Thy_Output.antiquotation_raw \<^binding>\noindent\ (Scan.succeed ()) + (Document_Output.antiquotation_raw \<^binding>\noindent\ (Scan.succeed ()) (fn _ => fn () => Latex.string "\\noindent") #> - Thy_Output.antiquotation_raw \<^binding>\smallskip\ (Scan.succeed ()) + Document_Output.antiquotation_raw \<^binding>\smallskip\ (Scan.succeed ()) (fn _ => fn () => Latex.string "\\smallskip") #> - Thy_Output.antiquotation_raw \<^binding>\medskip\ (Scan.succeed ()) + Document_Output.antiquotation_raw \<^binding>\medskip\ (Scan.succeed ()) (fn _ => fn () => Latex.string "\\medskip") #> - Thy_Output.antiquotation_raw \<^binding>\bigskip\ (Scan.succeed ()) + Document_Output.antiquotation_raw \<^binding>\bigskip\ (Scan.succeed ()) (fn _ => fn () => Latex.string "\\bigskip")); -(* control style *) +(* nested document text *) local -fun control_antiquotation name s1 s2 = - Thy_Output.antiquotation_raw_embedded name (Scan.lift Args.cartouche_input) - (fn ctxt => Latex.enclose_block s1 s2 o Thy_Output.output_document ctxt {markdown = false}); - -in +fun nested_antiquotation name s1 s2 = + Document_Output.antiquotation_raw_embedded name (Scan.lift Args.cartouche_input) + (fn ctxt => fn txt => + (Context_Position.reports ctxt (Document_Output.document_reports txt); + Latex.enclose_block s1 s2 (Document_Output.output_document ctxt {markdown = false} txt))); val _ = Theory.setup - (control_antiquotation \<^binding>\footnote\ "\\footnote{" "}" #> - control_antiquotation \<^binding>\emph\ "\\emph{" "}" #> - control_antiquotation \<^binding>\bold\ "\\textbf{" "}"); + (nested_antiquotation \<^binding>\footnote\ "\\footnote{" "}" #> + nested_antiquotation \<^binding>\emph\ "\\emph{" "}" #> + nested_antiquotation \<^binding>\bold\ "\\textbf{" "}"); + +in end; + + +(* index entries *) + +local + +val index_like = Parse.$$$ "(" |-- Parse.!!! (Parse.$$$ "is" |-- Args.name --| Parse.$$$ ")"); +val index_args = Parse.enum1 "!" (Args.embedded_input -- Scan.option index_like); + +fun output_text ctxt = Latex.block o Document_Output.output_document ctxt {markdown = false}; -end; +fun index binding def = + Document_Output.antiquotation_raw binding (Scan.lift index_args) + (fn ctxt => fn args => + let + val _ = Context_Position.reports ctxt (maps (Document_Output.document_reports o #1) args); + fun make_item (txt, opt_like) = + let + val text = output_text ctxt txt; + val like = + (case opt_like of + SOME s => s + | NONE => Document_Antiquotation.approx_content ctxt (Input.string_of txt)); + val _ = + if is_none opt_like andalso Context_Position.is_visible ctxt then + writeln ("(" ^ Markup.markup Markup.keyword2 "is" ^ " " ^ quote like ^ ")" ^ + Position.here (Input.pos_of txt)) + else (); + in {text = text, like = like} end; + in Latex.index_entry {items = map make_item args, def = def} end); + +val _ = Theory.setup (index \<^binding>\index_ref\ false #> index \<^binding>\index_def\ true); + +in end; (* quasi-formal text (unchecked) *) @@ -161,18 +191,18 @@ Input.source_content #> #1 #> Document_Antiquotation.prepare_lines ctxt; fun text_antiquotation name = - Thy_Output.antiquotation_raw_embedded name (Scan.lift Args.text_input) + Document_Output.antiquotation_raw_embedded name (Scan.lift Args.text_input) (fn ctxt => fn text => let val _ = report_text ctxt text; in prepare_text ctxt text - |> Thy_Output.output_source ctxt - |> Thy_Output.isabelle ctxt + |> Document_Output.output_source ctxt + |> Document_Output.isabelle ctxt end); val theory_text_antiquotation = - Thy_Output.antiquotation_raw_embedded \<^binding>\theory_text\ (Scan.lift Args.text_input) + Document_Output.antiquotation_raw_embedded \<^binding>\theory_text\ (Scan.lift Args.text_input) (fn ctxt => fn text => let val keywords = Thy_Header.get_keywords' ctxt; @@ -186,21 +216,17 @@ in prepare_text ctxt text |> Token.explode0 keywords - |> maps (Thy_Output.output_token ctxt) - |> Thy_Output.isabelle ctxt + |> maps (Document_Output.output_token ctxt) + |> Document_Output.isabelle ctxt end); -in - val _ = Theory.setup (text_antiquotation \<^binding>\text\ #> text_antiquotation \<^binding>\cartouche\ #> theory_text_antiquotation); -end; - - +in end; (* goal state *) @@ -208,19 +234,17 @@ local fun goal_state name main = - Thy_Output.antiquotation_pretty name (Scan.succeed ()) + Document_Output.antiquotation_pretty name (Scan.succeed ()) (fn ctxt => fn () => Goal_Display.pretty_goal (Config.put Goal_Display.show_main_goal main ctxt) (#goal (Proof.goal (Toplevel.proof_of (Toplevel.presentation_state ctxt))))); -in - val _ = Theory.setup (goal_state \<^binding>\goals\ true #> goal_state \<^binding>\subgoals\ false); -end; +in end; (* embedded lemma *) @@ -241,15 +265,15 @@ |> Proof.theorem NONE (K I) [[(prop, [])]] |> Proof.global_terminal_proof (m1, m2); in - Thy_Output.pretty_source ctxt {embedded = false} - [hd src, prop_tok] (Thy_Output.pretty_term ctxt prop) + Document_Output.pretty_source ctxt {embedded = false} + [hd src, prop_tok] (Document_Output.pretty_term ctxt prop) end)); (* verbatim text *) val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\verbatim\ (Scan.lift Args.text_input) + (Document_Output.antiquotation_verbatim_embedded \<^binding>\verbatim\ (Scan.lift Args.text_input) (fn ctxt => fn text => let val pos = Input.pos_of text; @@ -263,14 +287,14 @@ (* bash functions *) val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\bash_function\ + (Document_Output.antiquotation_verbatim_embedded \<^binding>\bash_function\ (Scan.lift Args.embedded_position) Isabelle_System.check_bash_function); (* system options *) val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\system_option\ + (Document_Output.antiquotation_verbatim_embedded \<^binding>\system_option\ (Scan.lift Args.embedded_position) (fn ctxt => fn (name, pos) => let val _ = Completion.check_option (Options.default ()) ctxt (name, pos); @@ -281,30 +305,104 @@ local -fun ml_text name ml = - Thy_Output.antiquotation_verbatim_embedded name (Scan.lift Args.text_input) - (fn ctxt => fn text => - let val _ = ML_Context.eval_in (SOME ctxt) ML_Compiler.flags (Input.pos_of text) (ml text) - in #1 (Input.source_content text) end); +fun test_val (ml1, []) = ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read ");" + | test_val (ml1, ml2) = ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read " : " @ ml2 @ ML_Lex.read ");"; + +fun test_op (ml1, ml2) = test_val (ML_Lex.read "op " @ ml1, ml2); + +fun test_type (ml1, []) = ML_Lex.read "val _ = NONE : (" @ ml1 @ ML_Lex.read ") option;" + | test_type (ml1, ml2) = + ML_Lex.read "val _ = [NONE : (" @ ml1 @ ML_Lex.read ") option, NONE : (" @ + ml2 @ ML_Lex.read ") option];"; + +fun test_exn (ml1, []) = ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read " : exn);" + | test_exn (ml1, ml2) = + ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read " : " @ ml2 @ ML_Lex.read " -> exn);"; + +fun test_struct (ml, _) = + ML_Lex.read "functor XXX() = struct structure XX = " @ ml @ ML_Lex.read " end;"; + +fun test_functor (Antiquote.Text tok :: _, _) = + ML_Lex.read "ML_Env.check_functor " @ + ML_Lex.read (ML_Syntax.print_string (ML_Lex.content_of tok)) + | test_functor _ = raise Fail "Bad ML functor specification"; + +val parse_ml0 = Args.text_input >> (fn source => ("", (source, Input.empty))); + +val parse_ml = + Args.text_input -- Scan.optional (Args.colon |-- Args.text_input) Input.empty >> pair ""; + +val parse_exn = + Args.text_input -- Scan.optional (Args.$$$ "of" |-- Args.text_input) Input.empty >> pair ""; + +val parse_type = + (Parse.type_args >> (fn [] => "" | [a] => a ^ " " | bs => enclose "(" ") " (commas bs))) -- + (Args.text_input -- Scan.optional (Args.$$$ "=" |-- Args.text_input) Input.empty); + +fun eval ctxt pos ml = + ML_Context.eval_in (SOME ctxt) ML_Compiler.flags pos ml + handle ERROR msg => error (msg ^ Position.here pos); -fun ml_enclose bg en source = - ML_Lex.read bg @ ML_Lex.read_source source @ ML_Lex.read en; +fun make_text sep sources = + let + val (txt1, txt2) = apply2 (#1 o Input.source_content) sources; + val is_ident = + (case try List.last (Symbol.explode txt1) of + NONE => false + | SOME s => Symbol.is_ascii_letdig s); + val txt = + if txt2 = "" then txt1 + else if sep = ":" andalso is_ident then txt1 ^ ": " ^ txt2 + else txt1 ^ " " ^ sep ^ " " ^ txt2 + in (txt, txt1) end; + +fun antiquotation_ml parse test kind show_kind binding index = + Document_Output.antiquotation_raw binding (Scan.lift parse) + (fn ctxt => fn (txt0, sources) => + let + val (ml1, ml2) = apply2 ML_Lex.read_source sources; + val ml0 = ML_Lex.read_source (Input.string txt0); + val _ = test (ml0 @ ml1, ml2) |> eval ctxt (Input.pos_of (#1 sources)); + + val sep = if kind = "type" then "=" else if kind = "exception" then "of" else ":"; + val (txt, idx) = make_text sep sources; + + val main_text = + Document_Output.verbatim ctxt + ((if kind = "" orelse not show_kind then "" else kind ^ " ") ^ txt0 ^ txt); + + val index_text = + index |> Option.map (fn def => + let + val ctxt' = Config.put Document_Antiquotation.thy_output_display false ctxt; + val kind' = if kind = "" then " (ML)" else " (ML " ^ kind ^ ")"; + val txt' = Latex.block [Document_Output.verbatim ctxt' idx, Latex.string kind']; + val like = Document_Antiquotation.approx_content ctxt' idx; + in Latex.index_entry {items = [{text = txt', like = like}], def = def} end); + in Latex.block (the_list index_text @ [main_text]) end); + +fun antiquotation_ml0 test kind = + antiquotation_ml parse_ml0 test kind false; + +fun antiquotation_ml1 parse test kind binding = + antiquotation_ml parse test kind true binding (SOME true); in -val _ = Theory.setup - (ml_text \<^binding>\ML\ (ml_enclose "fn _ => (" ");") #> - ml_text \<^binding>\ML_op\ (ml_enclose "fn _ => (op " ");") #> - ml_text \<^binding>\ML_type\ (ml_enclose "val _ = NONE : (" ") option;") #> - ml_text \<^binding>\ML_structure\ - (ml_enclose "functor XXX() = struct structure XX = " " end;") #> - - ml_text \<^binding>\ML_functor\ (* FIXME formal treatment of functor name (!?) *) - (fn source => - ML_Lex.read ("ML_Env.check_functor " ^ - ML_Syntax.print_string (#1 (Input.source_content source)))) #> - - ml_text \<^binding>\ML_text\ (K [])); +val _ = + Theory.setup + (Latex.index_variants (antiquotation_ml0 test_val "") \<^binding>\ML\ #> + Latex.index_variants (antiquotation_ml0 test_op "infix") \<^binding>\ML_infix\ #> + Latex.index_variants (antiquotation_ml0 test_type "type") \<^binding>\ML_type\ #> + Latex.index_variants (antiquotation_ml0 test_struct "structure") \<^binding>\ML_structure\ #> + Latex.index_variants (antiquotation_ml0 test_functor "functor") \<^binding>\ML_functor\ #> + antiquotation_ml0 (K []) "text" \<^binding>\ML_text\ NONE #> + antiquotation_ml1 parse_ml test_val "" \<^binding>\define_ML\ #> + antiquotation_ml1 parse_ml test_op "infix" \<^binding>\define_ML_infix\ #> + antiquotation_ml1 parse_type test_type "type" \<^binding>\define_ML_type\ #> + antiquotation_ml1 parse_exn test_exn "exception" \<^binding>\define_ML_exception\ #> + antiquotation_ml1 parse_ml0 test_struct "structure" \<^binding>\define_ML_structure\ #> + antiquotation_ml1 parse_ml0 test_functor "functor" \<^binding>\define_ML_functor\); end; @@ -315,7 +413,7 @@ translate_string (fn c => if c = "%" orelse c = "#" orelse c = "^" then "\\" ^ c else c); val _ = Theory.setup - (Thy_Output.antiquotation_raw_embedded \<^binding>\url\ (Scan.lift Args.embedded_input) + (Document_Output.antiquotation_raw_embedded \<^binding>\url\ (Scan.lift Args.embedded_input) (fn ctxt => fn source => let val url = Input.string_of source; @@ -332,19 +430,17 @@ local fun entity_antiquotation name check bg en = - Thy_Output.antiquotation_raw name (Scan.lift Args.name_position) + Document_Output.antiquotation_raw name (Scan.lift Args.name_position) (fn ctxt => fn (name, pos) => let val _ = check ctxt (name, pos) in Latex.enclose_block bg en [Latex.string (Output.output name)] end); -in - val _ = Theory.setup (entity_antiquotation \<^binding>\command\ Outer_Syntax.check_command "\\isacommand{" "}" #> entity_antiquotation \<^binding>\method\ Method.check_name "\\isa{" "}" #> entity_antiquotation \<^binding>\attribute\ Attrib.check_name "\\isa{" "}"); -end; +in end; end; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/document_build.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Pure/Thy/document_build.scala Sun May 23 20:34:43 2021 +0200 @@ -0,0 +1,535 @@ +/* Title: Pure/Thy/document_build.scala + Author: Makarius + +Build theory document (PDF) from session database. +*/ + +package isabelle + + +object Document_Build +{ + /* document variants */ + + sealed case class Content(path: Path, bytes: Bytes) + { + def write(dir: Path): Unit = Bytes.write(dir + path, bytes) + } + + abstract class Document_Name + { + def name: String + def path: Path = Path.basic(name) + + override def toString: String = name + } + + object Document_Variant + { + def parse(name: String, tags: String): Document_Variant = + Document_Variant(name, Library.space_explode(',', tags)) + + def parse(opt: String): Document_Variant = + Library.space_explode('=', opt) match { + case List(name) => Document_Variant(name, Nil) + case List(name, tags) => parse(name, tags) + case _ => error("Malformed document variant: " + quote(opt)) + } + } + + sealed case class Document_Variant(name: String, tags: List[String]) extends Document_Name + { + def print_tags: String = tags.mkString(",") + def print: String = if (tags.isEmpty) name else name + "=" + print_tags + + def isabelletags: Content = + { + val path = Path.explode("isabelletags.sty") + val text = + Library.terminate_lines( + tags.map(tag => + tag.toList match { + case '/' :: cs => "\\isafoldtag{" + cs.mkString + "}" + case '-' :: cs => "\\isadroptag{" + cs.mkString + "}" + case '+' :: cs => "\\isakeeptag{" + cs.mkString + "}" + case cs => "\\isakeeptag{" + cs.mkString + "}" + })) + Content(path, Bytes(text)) + } + } + + sealed case class Document_Input(name: String, sources: SHA1.Digest) + extends Document_Name + + sealed case class Document_Output(name: String, sources: SHA1.Digest, log_xz: Bytes, pdf: Bytes) + extends Document_Name + { + def log: String = log_xz.uncompress().text + def log_lines: List[String] = split_lines(log) + + def write(db: SQL.Database, session_name: String): Unit = + write_document(db, session_name, this) + + def write(dir: Path): Path = + { + val path = dir + Path.basic(name).pdf + Isabelle_System.make_directory(path.expand.dir) + Bytes.write(path, pdf) + path + } + } + + + /* SQL data model */ + + object Data + { + val session_name = SQL.Column.string("session_name").make_primary_key + val name = SQL.Column.string("name").make_primary_key + val sources = SQL.Column.string("sources") + val log_xz = SQL.Column.bytes("log_xz") + val pdf = SQL.Column.bytes("pdf") + + val table = SQL.Table("isabelle_documents", List(session_name, name, sources, log_xz, pdf)) + + def where_equal(session_name: String, name: String = ""): SQL.Source = + "WHERE " + Data.session_name.equal(session_name) + + (if (name == "") "" else " AND " + Data.name.equal(name)) + } + + def read_documents(db: SQL.Database, session_name: String): List[Document_Input] = + { + val select = Data.table.select(List(Data.name, Data.sources), Data.where_equal(session_name)) + db.using_statement(select)(stmt => + stmt.execute_query().iterator(res => + { + val name = res.string(Data.name) + val sources = res.string(Data.sources) + Document_Input(name, SHA1.fake(sources)) + }).toList) + } + + def read_document(db: SQL.Database, session_name: String, name: String): Option[Document_Output] = + { + val select = Data.table.select(sql = Data.where_equal(session_name, name)) + db.using_statement(select)(stmt => + { + val res = stmt.execute_query() + if (res.next()) { + val name = res.string(Data.name) + val sources = res.string(Data.sources) + val log_xz = res.bytes(Data.log_xz) + val pdf = res.bytes(Data.pdf) + Some(Document_Output(name, SHA1.fake(sources), log_xz, pdf)) + } + else None + }) + } + + def write_document(db: SQL.Database, session_name: String, doc: Document_Output): Unit = + { + db.using_statement(Data.table.insert())(stmt => + { + stmt.string(1) = session_name + stmt.string(2) = doc.name + stmt.string(3) = doc.sources.toString + stmt.bytes(4) = doc.log_xz + stmt.bytes(5) = doc.pdf + stmt.execute() + }) + } + + + /* context */ + + val isabelle_styles: List[Path] = + List("comment.sty", "isabelle.sty", "isabellesym.sty", "pdfsetup.sty", "railsetup.sty"). + map(name => Path.explode("~~/lib/texinputs") + Path.basic(name)) + + def context( + session: String, + deps: Sessions.Deps, + db_context: Sessions.Database_Context, + progress: Progress = new Progress): Context = + { + val info = deps.sessions_structure(session) + val base = deps(session) + val hierarchy = deps.sessions_structure.hierarchy(session) + new Context(info, base, hierarchy, db_context, progress) + } + + final class Context private[Document_Build]( + info: Sessions.Info, + base: Sessions.Base, + hierarchy: List[String], + db_context: Sessions.Database_Context, + val progress: Progress = new Progress) + { + /* session info */ + + def session: String = info.name + def options: Options = info.options + + def document_bibliography: Boolean = options.bool("document_bibliography") + + def document_preprocessor: Option[String] = + proper_string(options.string("document_preprocessor")) + + def document_logo: Option[String] = + options.string("document_logo") match { + case "" => None + case "_" => Some("") + case name => Some(name) + } + + def document_build: String = options.string("document_build") + + def get_engine(): Engine = + { + val name = document_build + engines.find(_.name == name).getOrElse(error("Bad document_build engine " + quote(name))) + } + + def get_export(theory: String, name: String): Export.Entry = + db_context.get_export(hierarchy, theory, name) + + + /* document content */ + + def documents: List[Document_Variant] = info.documents + + def session_theories: List[Document.Node.Name] = base.session_theories + def document_theories: List[Document.Node.Name] = session_theories ::: base.document_theories + + lazy val tex_files: List[Content] = + for (name <- document_theories) + yield { + val path = Path.basic(tex_name(name)) + val bytes = get_export(name.theory, document_tex_name(name)).uncompressed + Content(path, bytes) + } + + lazy val session_graph: Content = + { + val path = Presentation.session_graph_path + val bytes = graphview.Graph_File.make_pdf(options, base.session_graph_display) + Content(path, bytes) + } + + lazy val session_tex: Content = + { + val path = Path.basic("session.tex") + val text = + Library.terminate_lines( + base.session_theories.map(name => "\\input{" + tex_name(name) + "}")) + Content(path, Bytes(text)) + } + + lazy val isabelle_logo: Option[Content] = + { + document_logo.map(logo_name => + Isabelle_System.with_tmp_file("logo", ext = "pdf")(tmp_path => + { + Logo.create_logo(logo_name, output_file = tmp_path, quiet = true) + val path = Path.basic("isabelle_logo.pdf") + val bytes = Bytes.read(tmp_path) + Content(path, bytes) + })) + } + + + /* document directory */ + + def prepare_directory(dir: Path, doc: Document_Variant): Directory = + { + val doc_dir = dir + Path.basic(doc.name) + Isabelle_System.make_directory(doc_dir) + + + /* sources */ + + isabelle_styles.foreach(Isabelle_System.copy_file(_, doc_dir)) + doc.isabelletags.write(doc_dir) + + for ((base_dir, src) <- info.document_files) { + Isabelle_System.copy_file_base(info.dir + base_dir, src, doc_dir) + } + + session_tex.write(doc_dir) + tex_files.foreach(_.write(doc_dir)) + + val root_name1 = "root_" + doc.name + val root_name = if ((doc_dir + Path.explode(root_name1).tex).is_file) root_name1 else "root" + + for (name <- document_preprocessor) { + def message(s: String): String = s + " for document_preprocessor=" + quote(name) + val path = doc_dir + Path.explode(name) + if (path.is_file) { + try { Isabelle_System.bash(File.bash_path(path), cwd = doc_dir.file).check } + catch { case ERROR(msg) => cat_error(msg, message("The error(s) above occurred")) } + } + else error(message("Missing executable")) + } + + val digests1 = List(doc.print, document_logo.toString, document_build).map(SHA1.digest) + val digests2 = File.find_files(doc_dir.file, follow_links = true).map(SHA1.digest) + val sources = SHA1.digest_set(digests1 ::: digests2) + + + /* derived material (without SHA1 digest) */ + + isabelle_logo.foreach(_.write(doc_dir)) + + session_graph.write(doc_dir) + + Directory(doc_dir, doc, root_name, sources) + } + + def old_document(directory: Directory): Option[Document_Output] = + for { + old_doc <- db_context.input_database(session)(read_document(_, _, directory.doc.name)) + if old_doc.sources == directory.sources + } + yield old_doc + } + + sealed case class Directory( + doc_dir: Path, + doc: Document_Variant, + root_name: String, + sources: SHA1.Digest) + { + def root_name_script(ext: String = ""): String = + Bash.string(if (ext.isEmpty) root_name else root_name + "." + ext) + + def conditional_script(ext: String, exe: String, after: String = ""): String = + "if [ -f " + root_name_script(ext) + " ]\n" + + "then\n" + + " " + exe + " " + root_name_script() + "\n" + + (if (after.isEmpty) "" else " " + after) + + "fi\n" + + def log_errors(): List[String] = + Latex.latex_errors(doc_dir, root_name) ::: + Bibtex.bibtex_errors(doc_dir, root_name) + + def make_document(log: List[String], errors: List[String]): Document_Output = + { + val root_pdf = Path.basic(root_name).pdf + val result_pdf = doc_dir + root_pdf + + if (errors.nonEmpty) { + val errors1 = errors ::: List("Failed to build document " + quote(doc.name)) + throw new Build_Error(log, Exn.cat_message(errors1: _*)) + } + else if (!result_pdf.is_file) { + val message = "Bad document result: expected to find " + root_pdf + throw new Build_Error(log, message) + } + else { + val log_xz = Bytes(cat_lines(log)).compress() + val pdf = Bytes.read(result_pdf) + Document_Output(doc.name, sources, log_xz, pdf) + } + } + } + + + /* build engines */ + + lazy val engines: List[Engine] = Isabelle_System.make_services(classOf[Engine]) + + abstract class Engine(val name: String) extends Isabelle_System.Service + { + override def toString: String = name + + def prepare_directory(context: Context, dir: Path, doc: Document_Variant): Directory + def build_document(context: Context, directory: Directory, verbose: Boolean): Document_Output + } + + abstract class Bash_Engine(name: String) extends Engine(name) + { + def prepare_directory(context: Context, dir: Path, doc: Document_Variant): Directory = + context.prepare_directory(dir, doc) + + def use_pdflatex: Boolean = false + def latex_script(context: Context, directory: Directory): String = + (if (use_pdflatex) "$ISABELLE_PDFLATEX" else "$ISABELLE_LUALATEX") + + " " + directory.root_name_script() + "\n" + + def bibtex_script(context: Context, directory: Directory, latex: Boolean = false): String = + { + val ext = if (context.document_bibliography) "aux" else "bib" + directory.conditional_script(ext, "$ISABELLE_BIBTEX", + after = if (latex) latex_script(context, directory) else "") + } + + def makeindex_script(context: Context, directory: Directory, latex: Boolean = false): String = + directory.conditional_script("idx", "$ISABELLE_MAKEINDEX", + after = if (latex) latex_script(context, directory) else "") + + def use_build_script: Boolean = false + def build_script(context: Context, directory: Directory): String = + { + val has_build_script = (directory.doc_dir + Path.explode("build")).is_file + + if (!use_build_script && has_build_script) { + error("Unexpected document build script for option document_build=" + + quote(context.document_build)) + } + else if (use_build_script && !has_build_script) error("Missing document build script") + else if (has_build_script) "./build pdf " + Bash.string(directory.doc.name) + else { + "set -e\n" + + latex_script(context, directory) + + bibtex_script(context, directory, latex = true) + + makeindex_script(context, directory) + + latex_script(context, directory) + + makeindex_script(context, directory, latex = true) + } + } + + def build_document(context: Context, directory: Directory, verbose: Boolean): Document_Output = + { + val result = + context.progress.bash( + build_script(context, directory), + cwd = directory.doc_dir.file, + echo = verbose, + watchdog = Time.seconds(0.5)) + + val log = result.out_lines ::: result.err_lines + val errors = (if (result.ok) Nil else List(result.err)) ::: directory.log_errors() + directory.make_document(log, errors) + } + } + + class LuaLaTeX_Engine extends Bash_Engine("lualatex") + class PDFLaTeX_Engine extends Bash_Engine("pdflatex") { override def use_pdflatex: Boolean = true } + class Build_Engine extends Bash_Engine("build") { override def use_build_script: Boolean = true } + + + /* build documents */ + + def tex_name(name: Document.Node.Name): String = name.theory_base_name + ".tex" + def document_tex_name(name: Document.Node.Name): String = "document/" + tex_name(name) + + class Build_Error(val log_lines: List[String], val message: String) + extends Exn.User_Error(message) + + def build_documents( + context: Context, + output_sources: Option[Path] = None, + output_pdf: Option[Path] = None, + verbose: Boolean = false): List[Document_Output] = + { + val progress = context.progress + val engine = context.get_engine() + + val documents = + for (doc <- context.documents) + yield { + Isabelle_System.with_tmp_dir("document")(tmp_dir => + { + progress.echo("Preparing " + context.session + "/" + doc.name + " ...") + val start = Time.now() + + output_sources.foreach(engine.prepare_directory(context, _, doc)) + val directory = engine.prepare_directory(context, tmp_dir, doc) + + val document = + context.old_document(directory) getOrElse + engine.build_document(context, directory, verbose) + + val stop = Time.now() + val timing = stop - start + + progress.echo("Finished " + context.session + "/" + doc.name + + " (" + timing.message_hms + " elapsed time)") + + document + }) + } + + for (dir <- output_pdf; doc <- documents) { + val path = doc.write(dir) + progress.echo("Document at " + path.absolute) + } + + documents + } + + + /* Isabelle tool wrapper */ + + val isabelle_tool = + Isabelle_Tool("document", "prepare session theory document", Scala_Project.here, args => + { + var output_sources: Option[Path] = None + var output_pdf: Option[Path] = None + var verbose_latex = false + var dirs: List[Path] = Nil + var options = Options.init() + var verbose_build = false + + val getopts = Getopts( + """ +Usage: isabelle document [OPTIONS] SESSION + + Options are: + -O DIR output directory for LaTeX sources and resulting PDF + -P DIR output directory for resulting PDF + -S DIR output directory for LaTeX sources + -V verbose latex + -d DIR include session directory + -o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) + -v verbose build + + Prepare the theory document of a session. +""", + "O:" -> (arg => + { + val dir = Path.explode(arg) + output_sources = Some(dir) + output_pdf = Some(dir) + }), + "P:" -> (arg => { output_pdf = Some(Path.explode(arg)) }), + "S:" -> (arg => { output_sources = Some(Path.explode(arg)) }), + "V" -> (_ => verbose_latex = true), + "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))), + "o:" -> (arg => options = options + arg), + "v" -> (_ => verbose_build = true)) + + val more_args = getopts(args) + val session = + more_args match { + case List(a) => a + case _ => getopts.usage() + } + + val progress = new Console_Progress(verbose = verbose_build) + val store = Sessions.store(options) + + progress.interrupt_handler { + val res = + Build.build(options, selection = Sessions.Selection.session(session), + dirs = dirs, progress = progress, verbose = verbose_build) + if (!res.ok) error("Failed to build session " + quote(session)) + + val deps = + Sessions.load_structure(options + "document=pdf", dirs = dirs). + selection_deps(Sessions.Selection.session(session)) + + if (output_sources.isEmpty && output_pdf.isEmpty) { + progress.echo_warning("No output directory") + } + + using(store.open_database_context())(db_context => + { + build_documents(context(session, deps, db_context, progress = progress), + output_sources = output_sources, output_pdf = output_pdf, + verbose = verbose_latex) + }) + } + }) +} diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/document_output.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Pure/Thy/document_output.ML Sun May 23 20:34:43 2021 +0200 @@ -0,0 +1,577 @@ +(* Title: Pure/Thy/document_output.ML + Author: Makarius + +Theory document output. +*) + +signature DOCUMENT_OUTPUT = +sig + val document_reports: Input.source -> Position.report list + val output_document: Proof.context -> {markdown: bool} -> Input.source -> Latex.text list + val check_comments: Proof.context -> Symbol_Pos.T list -> unit + val output_token: Proof.context -> Token.T -> Latex.text list + val output_source: Proof.context -> string -> Latex.text list + type segment = + {span: Command_Span.span, command: Toplevel.transition, + prev_state: Toplevel.state, state: Toplevel.state} + val present_thy: Options.T -> theory -> segment list -> Latex.text list + val pretty_term: Proof.context -> term -> Pretty.T + val pretty_thm: Proof.context -> thm -> Pretty.T + val lines: Latex.text list -> Latex.text list + val items: Latex.text list -> Latex.text list + val isabelle: Proof.context -> Latex.text list -> Latex.text + val isabelle_typewriter: Proof.context -> Latex.text list -> Latex.text + val typewriter: Proof.context -> string -> Latex.text + val verbatim: Proof.context -> string -> Latex.text + val source: Proof.context -> {embedded: bool} -> Token.src -> Latex.text + val pretty: Proof.context -> Pretty.T -> Latex.text + val pretty_source: Proof.context -> {embedded: bool} -> Token.src -> Pretty.T -> Latex.text + val pretty_items: Proof.context -> Pretty.T list -> Latex.text + val pretty_items_source: Proof.context -> {embedded: bool} -> Token.src -> + Pretty.T list -> Latex.text + val antiquotation_pretty: + binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory + val antiquotation_pretty_embedded: + binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory + val antiquotation_pretty_source: + binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory + val antiquotation_pretty_source_embedded: + binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory + val antiquotation_raw: + binding -> 'a context_parser -> (Proof.context -> 'a -> Latex.text) -> theory -> theory + val antiquotation_raw_embedded: + binding -> 'a context_parser -> (Proof.context -> 'a -> Latex.text) -> theory -> theory + val antiquotation_verbatim: + binding -> 'a context_parser -> (Proof.context -> 'a -> string) -> theory -> theory + val antiquotation_verbatim_embedded: + binding -> 'a context_parser -> (Proof.context -> 'a -> string) -> theory -> theory +end; + +structure Document_Output: DOCUMENT_OUTPUT = +struct + +(* output document source *) + +fun document_reports txt = + let val pos = Input.pos_of txt in + [(pos, Markup.language_document (Input.is_delimited txt)), + (pos, Markup.plain_text)] + end; + +val output_symbols = single o Latex.symbols_output; + +fun output_comment ctxt (kind, syms) = + (case kind of + Comment.Comment => + Input.cartouche_content syms + |> output_document (ctxt |> Config.put Document_Antiquotation.thy_output_display false) + {markdown = false} + |> Latex.enclose_body "%\n\\isamarkupcmt{" "%\n}" + | Comment.Cancel => + Symbol_Pos.cartouche_content syms + |> output_symbols + |> Latex.enclose_body "%\n\\isamarkupcancel{" "}" + | Comment.Latex => [Latex.symbols (Symbol_Pos.cartouche_content syms)] + | Comment.Marker => []) +and output_comment_document ctxt (comment, syms) = + (case comment of + SOME kind => output_comment ctxt (kind, syms) + | NONE => [Latex.symbols syms]) +and output_document_text ctxt syms = + Comment.read_body syms |> maps (output_comment_document ctxt) +and output_document ctxt {markdown} source = + let + val pos = Input.pos_of source; + val syms = Input.source_explode source; + + val output_antiquotes = + maps (Document_Antiquotation.evaluate (output_document_text ctxt) ctxt); + + fun output_line line = + (if Markdown.line_is_item line then [Latex.string "\\item "] else []) @ + output_antiquotes (Markdown.line_content line); + + fun output_block (Markdown.Par lines) = + Latex.block (separate (Latex.string "\n") (map (Latex.block o output_line) lines)) + | output_block (Markdown.List {kind, body, ...}) = + Latex.environment_block (Markdown.print_kind kind) (output_blocks body) + and output_blocks blocks = separate (Latex.string "\n\n") (map output_block blocks); + in + if Toplevel.is_skipped_proof (Toplevel.presentation_state ctxt) then [] + else if markdown andalso exists (Markdown.is_control o Symbol_Pos.symbol) syms + then + let + val ants = Antiquote.parse_comments pos syms; + val reports = Antiquote.antiq_reports ants; + val blocks = Markdown.read_antiquotes ants; + val _ = Context_Position.reports ctxt (reports @ Markdown.reports blocks); + in output_blocks blocks end + else + let + val ants = Antiquote.parse_comments pos (trim (Symbol.is_blank o Symbol_Pos.symbol) syms); + val reports = Antiquote.antiq_reports ants; + val _ = Context_Position.reports ctxt (reports @ Markdown.text_reports ants); + in output_antiquotes ants end + end; + + +(* output tokens with formal comments *) + +local + +val output_symbols_antiq = + (fn Antiquote.Text syms => output_symbols syms + | Antiquote.Control {name = (name, _), body, ...} => + Latex.string (Latex.output_symbols [Symbol.encode (Symbol.Control name)]) :: + output_symbols body + | Antiquote.Antiq {body, ...} => + Latex.enclose_body "%\n\\isaantiq\n" "{}%\n\\endisaantiq\n" (output_symbols body)); + +fun output_comment_symbols ctxt {antiq} (comment, syms) = + (case (comment, antiq) of + (NONE, false) => output_symbols syms + | (NONE, true) => + Antiquote.parse_comments (#1 (Symbol_Pos.range syms)) syms + |> maps output_symbols_antiq + | (SOME comment, _) => output_comment ctxt (comment, syms)); + +fun output_body ctxt antiq bg en syms = + Comment.read_body syms + |> maps (output_comment_symbols ctxt {antiq = antiq}) + |> Latex.enclose_body bg en; + +in + +fun output_token ctxt tok = + let + fun output antiq bg en = + output_body ctxt antiq bg en (Input.source_explode (Token.input_of tok)); + in + (case Token.kind_of tok of + Token.Comment NONE => [] + | Token.Comment (SOME Comment.Marker) => [] + | Token.Command => output false "\\isacommand{" "}" + | Token.Keyword => + if Symbol.is_ascii_identifier (Token.content_of tok) + then output false "\\isakeyword{" "}" + else output false "" "" + | Token.String => output false "{\\isachardoublequoteopen}" "{\\isachardoublequoteclose}" + | Token.Alt_String => output false "{\\isacharbackquoteopen}" "{\\isacharbackquoteclose}" + | Token.Verbatim => output true "{\\isacharverbatimopen}" "{\\isacharverbatimclose}" + | Token.Cartouche => output false "{\\isacartoucheopen}" "{\\isacartoucheclose}" + | _ => output false "" "") + end handle ERROR msg => error (msg ^ Position.here (Token.pos_of tok)); + +fun output_source ctxt s = + output_body ctxt false "" "" (Symbol_Pos.explode (s, Position.none)); + +fun check_comments ctxt = + Comment.read_body #> List.app (fn (comment, syms) => + let + val pos = #1 (Symbol_Pos.range syms); + val _ = + comment |> Option.app (fn kind => + Context_Position.reports ctxt (map (pair pos) (Comment.kind_markups kind))); + val _ = output_comment_symbols ctxt {antiq = false} (comment, syms); + in if comment = SOME Comment.Comment then check_comments ctxt syms else () end); + +end; + + + +(** present theory source **) + +(* presentation tokens *) + +datatype token = + Ignore + | Token of Token.T + | Heading of string * Input.source + | Body of string * Input.source + | Raw of Input.source; + +fun token_with pred (Token tok) = pred tok + | token_with _ _ = false; + +val white_token = token_with Document_Source.is_white; +val white_comment_token = token_with Document_Source.is_white_comment; +val blank_token = token_with Token.is_blank; +val newline_token = token_with Token.is_newline; + +fun present_token ctxt tok = + (case tok of + Ignore => [] + | Token tok => output_token ctxt tok + | Heading (cmd, source) => + Latex.enclose_body ("%\n\\isamarkup" ^ cmd ^ "{") "%\n}\n" + (output_document ctxt {markdown = false} source) + | Body (cmd, source) => + [Latex.environment_block ("isamarkup" ^ cmd) (output_document ctxt {markdown = true} source)] + | Raw source => + Latex.string "%\n" :: output_document ctxt {markdown = true} source @ [Latex.string "\n"]); + + +(* command spans *) + +type command = string * Position.T; (*name, position*) +type source = (token * (string * int)) list; (*token, markup flag, meta-comment depth*) + +datatype span = Span of command * (source * source * source * source) * bool; + +fun make_span cmd src = + let + fun chop_newline (tok :: toks) = + if newline_token (fst tok) then ([tok], toks, true) + else ([], tok :: toks, false) + | chop_newline [] = ([], [], false); + val (((src_prefix, src_main), src_suffix1), (src_suffix2, src_appendix, newline)) = + src + |> chop_prefix (white_token o fst) + ||>> chop_suffix (white_token o fst) + ||>> chop_prefix (white_comment_token o fst) + ||> chop_newline; + in Span (cmd, (src_prefix, src_main, src_suffix1 @ src_suffix2, src_appendix), newline) end; + + +(* present spans *) + +local + +fun err_bad_nesting here = + error ("Bad nesting of commands in presentation" ^ here); + +fun edge which f (x: string option, y) = + if x = y then I + else (case which (x, y) of NONE => I | SOME txt => cons (Latex.string (f txt))); + +val begin_tag = edge #2 Latex.begin_tag; +val end_tag = edge #1 Latex.end_tag; +fun open_delim delim e = edge #2 Latex.begin_delim e #> delim #> edge #2 Latex.end_delim e; +fun close_delim delim e = edge #1 Latex.begin_delim e #> delim #> edge #1 Latex.end_delim e; + +fun document_tag cmd_pos state state' tagging_stack = + let + val ctxt' = Toplevel.presentation_context state'; + val nesting = Toplevel.level state' - Toplevel.level state; + + val (tagging, taggings) = tagging_stack; + val (tag', tagging') = Document_Source.update_tagging ctxt' tagging; + + val tagging_stack' = + if nesting = 0 andalso not (Toplevel.is_proof state) then tagging_stack + else if nesting >= 0 then (tagging', replicate nesting tagging @ taggings) + else + (case drop (~ nesting - 1) taggings of + tg :: tgs => (tg, tgs) + | [] => err_bad_nesting (Position.here cmd_pos)); + in (tag', tagging_stack') end; + +fun read_tag s = + (case space_explode "%" s of + ["", b] => (SOME b, NONE) + | [a, b] => (NONE, SOME (a, b)) + | _ => error ("Bad document_tags specification: " ^ quote s)); + +in + +fun make_command_tag options keywords = + let + val document_tags = + map read_tag (space_explode "," (Options.string options \<^system_option>\document_tags\)); + val document_tags_default = map_filter #1 document_tags; + val document_tags_command = map_filter #2 document_tags; + in + fn cmd_name => fn state => fn state' => fn active_tag => + let + val keyword_tags = + if cmd_name = "end" andalso Toplevel.is_end_theory state' then ["theory"] + else Keyword.command_tags keywords cmd_name; + val command_tags = + the_list (AList.lookup (op =) document_tags_command cmd_name) @ + keyword_tags @ document_tags_default; + val active_tag' = + (case command_tags of + default_tag :: _ => SOME default_tag + | [] => + if Keyword.is_vacuous keywords cmd_name andalso Toplevel.is_proof state + then active_tag + else NONE); + in active_tag' end + end; + +fun present_span command_tag span state state' + (tagging_stack, active_tag, newline, latex, present_cont) = + let + val ctxt' = Toplevel.presentation_context state'; + val present = fold (fn (tok, (flag, 0)) => + fold cons (present_token ctxt' tok) + #> cons (Latex.string flag) + | _ => I); + + val Span ((cmd_name, cmd_pos), srcs, span_newline) = span; + + val (tag', tagging_stack') = document_tag cmd_pos state state' tagging_stack; + val active_tag' = + if is_some tag' then Option.map #1 tag' + else command_tag cmd_name state state' active_tag; + val edge = (active_tag, active_tag'); + + val newline' = + if is_none active_tag' then span_newline else newline; + + val latex' = + latex + |> end_tag edge + |> close_delim (fst present_cont) edge + |> snd present_cont + |> open_delim (present (#1 srcs)) edge + |> begin_tag edge + |> present (#2 srcs); + val present_cont' = + if newline then (present (#3 srcs), present (#4 srcs)) + else (I, present (#3 srcs) #> present (#4 srcs)); + in (tagging_stack', active_tag', newline', latex', present_cont') end; + +fun present_trailer ((_, tags), active_tag, _, latex, present_cont) = + if not (null tags) then err_bad_nesting " at end of theory" + else + latex + |> end_tag (active_tag, NONE) + |> close_delim (fst present_cont) (active_tag, NONE) + |> snd present_cont; + +end; + + +(* present_thy *) + +local + +val markup_true = "\\isamarkuptrue%\n"; +val markup_false = "\\isamarkupfalse%\n"; + +val opt_newline = Scan.option (Scan.one Token.is_newline); + +val ignore = + Scan.depend (fn d => opt_newline |-- Scan.one Token.is_begin_ignore + >> pair (d + 1)) || + Scan.depend (fn d => Scan.one Token.is_end_ignore --| + (if d = 0 then Scan.fail_with (K (fn () => "Bad nesting of meta-comments")) else opt_newline) + >> pair (d - 1)); + +val locale = + Scan.option ((Parse.$$$ "(" -- Document_Source.improper -- Parse.$$$ "in") |-- + Parse.!!! + (Document_Source.improper |-- Parse.name --| (Document_Source.improper -- Parse.$$$ ")"))); + +in + +type segment = + {span: Command_Span.span, command: Toplevel.transition, + prev_state: Toplevel.state, state: Toplevel.state}; + +fun present_thy options thy (segments: segment list) = + let + val keywords = Thy_Header.get_keywords thy; + + + (* tokens *) + + val ignored = Scan.state --| ignore + >> (fn d => (NONE, (Ignore, ("", d)))); + + fun markup pred mk flag = Scan.peek (fn d => + Document_Source.improper |-- + Parse.position (Scan.one (fn tok => + Token.is_command tok andalso pred keywords (Token.content_of tok))) -- + (Document_Source.annotation |-- + Parse.!!!! ((Document_Source.improper -- locale -- Document_Source.improper) |-- + Parse.document_source --| Document_Source.improper_end)) + >> (fn ((tok, pos'), source) => + let val name = Token.content_of tok + in (SOME (name, pos'), (mk (name, source), (flag, d))) end)); + + val command = Scan.peek (fn d => + Scan.optional (Scan.one Token.is_command_modifier ::: Document_Source.improper) [] -- + Scan.one Token.is_command --| Document_Source.annotation + >> (fn (cmd_mod, cmd) => + map (fn tok => (NONE, (Token tok, ("", d)))) cmd_mod @ + [(SOME (Token.content_of cmd, Token.pos_of cmd), + (Token cmd, (markup_false, d)))])); + + val cmt = Scan.peek (fn d => + Scan.one Document_Source.is_black_comment >> (fn tok => (NONE, (Token tok, ("", d))))); + + val other = Scan.peek (fn d => + Parse.not_eof >> (fn tok => (NONE, (Token tok, ("", d))))); + + val tokens = + (ignored || + markup Keyword.is_document_heading Heading markup_true || + markup Keyword.is_document_body Body markup_true || + markup Keyword.is_document_raw (Raw o #2) "") >> single || + command || + (cmt || other) >> single; + + + (* spans *) + + val is_eof = fn (_, (Token x, _)) => Token.is_eof x | _ => false; + val stopper = Scan.stopper (K (NONE, (Token Token.eof, ("", 0)))) is_eof; + + val cmd = Scan.one (is_some o fst); + val non_cmd = Scan.one (is_none o fst andf not o is_eof) >> #2; + + val white_comments = Scan.many (white_comment_token o fst o snd); + val blank = Scan.one (blank_token o fst o snd); + val newline = Scan.one (newline_token o fst o snd); + val before_cmd = + Scan.option (newline -- white_comments) -- + Scan.option (newline -- white_comments) -- + Scan.option (blank -- white_comments) -- cmd; + + val span = + Scan.repeat non_cmd -- cmd -- + Scan.repeat (Scan.unless before_cmd non_cmd) -- + Scan.option (newline >> (single o snd)) + >> (fn (((toks1, (cmd, tok2)), toks3), tok4) => + make_span (the cmd) (toks1 @ (tok2 :: (toks3 @ the_default [] tok4)))); + + val spans = segments + |> maps (Command_Span.content o #span) + |> drop_suffix Token.is_space + |> Source.of_list + |> Source.source' 0 Token.stopper (Scan.error (Scan.bulk tokens >> flat)) + |> Source.source stopper (Scan.error (Scan.bulk span)) + |> Source.exhaust; + + val command_results = + segments |> map_filter (fn {command, state, ...} => + if Toplevel.is_ignored command then NONE else SOME (command, state)); + + + (* present commands *) + + val command_tag = make_command_tag options keywords; + + fun present_command tr span st st' = + Toplevel.setmp_thread_position tr (present_span command_tag span st st'); + + fun present _ [] = I + | present st ((span, (tr, st')) :: rest) = present_command tr span st st' #> present st' rest; + in + if length command_results = length spans then + (([], []), NONE, true, [], (I, I)) + |> present (Toplevel.init_toplevel ()) (spans ~~ command_results) + |> present_trailer + |> rev + else error "Messed-up outer syntax for presentation" + end; + +end; + + + +(** standard output operations **) + +(* pretty printing *) + +fun pretty_term ctxt t = + Syntax.pretty_term (Proof_Context.augment t ctxt) t; + +fun pretty_thm ctxt = pretty_term ctxt o Thm.full_prop_of; + + +(* default output *) + +val lines = separate (Latex.string "\\isanewline%\n"); +val items = separate (Latex.string "\\isasep\\isanewline%\n"); + +fun isabelle ctxt body = + if Config.get ctxt Document_Antiquotation.thy_output_display + then Latex.environment_block "isabelle" body + else Latex.block (Latex.enclose_body "\\isa{" "}" body); + +fun isabelle_typewriter ctxt body = + if Config.get ctxt Document_Antiquotation.thy_output_display + then Latex.environment_block "isabellett" body + else Latex.block (Latex.enclose_body "\\isatt{" "}" body); + +fun typewriter ctxt s = + isabelle_typewriter ctxt [Latex.string (Latex.output_ascii s)]; + +fun verbatim ctxt = + if Config.get ctxt Document_Antiquotation.thy_output_display + then Document_Antiquotation.indent_lines ctxt #> typewriter ctxt + else split_lines #> map (typewriter ctxt) #> lines #> Latex.block; + +fun token_source ctxt {embedded} tok = + if Token.is_kind Token.Cartouche tok andalso embedded andalso + not (Config.get ctxt Document_Antiquotation.thy_output_source_cartouche) + then Token.content_of tok + else Token.unparse tok; + +fun is_source ctxt = + Config.get ctxt Document_Antiquotation.thy_output_source orelse + Config.get ctxt Document_Antiquotation.thy_output_source_cartouche; + +fun source ctxt embedded = + Token.args_of_src + #> map (token_source ctxt embedded #> Document_Antiquotation.prepare_lines ctxt) + #> space_implode " " + #> output_source ctxt + #> isabelle ctxt; + +fun pretty ctxt = + Document_Antiquotation.output ctxt #> Latex.string #> single #> isabelle ctxt; + +fun pretty_source ctxt embedded src prt = + if is_source ctxt then source ctxt embedded src else pretty ctxt prt; + +fun pretty_items ctxt = + map (Document_Antiquotation.output ctxt #> Latex.string) #> items #> isabelle ctxt; + +fun pretty_items_source ctxt embedded src prts = + if is_source ctxt then source ctxt embedded src else pretty_items ctxt prts; + + +(* antiquotation variants *) + +local + +fun gen_setup name embedded = + if embedded + then Document_Antiquotation.setup_embedded name + else Document_Antiquotation.setup name; + +fun gen_antiquotation_pretty name embedded scan f = + gen_setup name embedded scan (fn {context = ctxt, argument = x, ...} => pretty ctxt (f ctxt x)); + +fun gen_antiquotation_pretty_source name embedded scan f = + gen_setup name embedded scan + (fn {context = ctxt, source = src, argument = x} => + pretty_source ctxt {embedded = embedded} src (f ctxt x)); + +fun gen_antiquotation_raw name embedded scan f = + gen_setup name embedded scan (fn {context = ctxt, argument = x, ...} => f ctxt x); + +fun gen_antiquotation_verbatim name embedded scan f = + gen_antiquotation_raw name embedded scan (fn ctxt => verbatim ctxt o f ctxt); + +in + +fun antiquotation_pretty name = gen_antiquotation_pretty name false; +fun antiquotation_pretty_embedded name = gen_antiquotation_pretty name true; + +fun antiquotation_pretty_source name = gen_antiquotation_pretty_source name false; +fun antiquotation_pretty_source_embedded name = gen_antiquotation_pretty_source name true; + +fun antiquotation_raw name = gen_antiquotation_raw name false; +fun antiquotation_raw_embedded name = gen_antiquotation_raw name true; + +fun antiquotation_verbatim name = gen_antiquotation_verbatim name false; +fun antiquotation_verbatim_embedded name = gen_antiquotation_verbatim name true; + +end; + +end; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/latex.ML --- a/src/Pure/Thy/latex.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/latex.ML Sun May 23 20:34:43 2021 +0200 @@ -1,7 +1,7 @@ (* Title: Pure/Thy/latex.ML - Author: Markus Wenzel, TU Muenchen + Author: Makarius -LaTeX presentation elements -- based on outer lexical syntax. +LaTeX output of theory sources. *) signature LATEX = @@ -29,6 +29,12 @@ val environment: string -> string -> string val isabelle_body: string -> text list -> text list val theory_entry: string -> string + val index_escape: string -> string + type index_item = {text: text, like: string} + val index_item: index_item -> text + type index_entry = {items: index_item list, def: bool} + val index_entry: index_entry -> text + val index_variants: (binding -> bool option -> 'a -> 'a) -> binding -> 'a -> 'a val latexN: string val latex_output: string -> string * int val latex_markup: string * Properties.T -> Markup.output @@ -47,6 +53,9 @@ val text = Text; val block = Block; +fun map_text f (Text (s, pos)) = Text (f s, pos) + | map_text f (Block texts) = Block ((map o map_text) f texts); + fun output_text texts = let fun output (Text (s, _)) = Buffer.add s @@ -243,6 +252,36 @@ fun theory_entry name = "\\input{" ^ name ^ ".tex}\n\n"; +(* index entries *) + +type index_item = {text: text, like: string}; +type index_entry = {items: index_item list, def: bool}; + +val index_escape = + translate_string (fn s => + if member_string "!\"@|" s then "\\char" ^ string_of_int (ord s) + else if member_string "\\{}#" s then "\"" ^ s else s); + +fun index_item (item: index_item) = + let + val like_text = + if #like item = "" then [] + else [string (index_escape (#like item) ^ "@")]; + in block (like_text @ [map_text index_escape (#text item)]) end; + +fun index_entry (entry: index_entry) = + (separate (string "!") (map index_item (#items entry)) @ + [string ("|" ^ index_escape (if #def entry then "isaindexdef" else "isaindexref"))]) + |> enclose_block "\\index{" "}"; + + +fun index_binding NONE = I + | index_binding (SOME def) = Binding.map_name (suffix (if def then "_def" else "_ref")); + +fun index_variants setup binding = + fold (fn index => setup (index_binding index binding) index) [NONE, SOME true, SOME false]; + + (* print mode *) val latexN = "latex"; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/latex.scala --- a/src/Pure/Thy/latex.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/latex.scala Sun May 23 20:34:43 2021 +0200 @@ -22,7 +22,7 @@ val root_log_path = dir + Path.explode(root_name).ext("log") if (root_log_path.is_file) { for { (msg, pos) <- filter_errors(dir, File.read(root_log_path)) } - yield "Latex error" + Position.here(pos) + ":\n" + Library.prefix_lines(" ", msg) + yield "Latex error" + Position.here(pos) + ":\n" + Library.indent_lines(2, msg) } else Nil } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/presentation.scala --- a/src/Pure/Thy/presentation.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/presentation.scala Sun May 23 20:34:43 2021 +0200 @@ -1,7 +1,7 @@ -/* Title: Pure/Thy/present.scala +/* Title: Pure/Thy/presentation.scala Author: Makarius -HTML/PDF presentation of theory documents. +HTML presentation of PIDE document content. */ package isabelle @@ -14,6 +14,8 @@ { /** HTML documents **/ + /* HTML context */ + val fonts_path = Path.explode("fonts") sealed case class HTML_Document(title: String, content: String) @@ -74,7 +76,7 @@ language = Markup.Elements(Markup.Language.DOCUMENT)) - /* HTML */ + /* HTML output */ private val div_elements = Set(HTML.div.name, HTML.pre.name, HTML.par.name, HTML.list.name, HTML.enum.name, @@ -169,120 +171,7 @@ - /** PDF LaTeX documents **/ - - /* document info */ - - abstract class Document_Name - { - def name: String - def path: Path = Path.basic(name) - - override def toString: String = name - } - - object Document_Variant - { - def parse(name: String, tags: String): Document_Variant = - Document_Variant(name, Library.space_explode(',', tags)) - - def parse(opt: String): Document_Variant = - Library.space_explode('=', opt) match { - case List(name) => Document_Variant(name, Nil) - case List(name, tags) => parse(name, tags) - case _ => error("Malformed document variant: " + quote(opt)) - } - } - - sealed case class Document_Variant(name: String, tags: List[String]) extends Document_Name - { - def print_tags: String = tags.mkString(",") - def print: String = if (tags.isEmpty) name else name + "=" + print_tags - - def latex_sty: String = - Library.terminate_lines( - tags.map(tag => - tag.toList match { - case '/' :: cs => "\\isafoldtag{" + cs.mkString + "}" - case '-' :: cs => "\\isadroptag{" + cs.mkString + "}" - case '+' :: cs => "\\isakeeptag{" + cs.mkString + "}" - case cs => "\\isakeeptag{" + cs.mkString + "}" - })) - } - - sealed case class Document_Input(name: String, sources: SHA1.Digest) - extends Document_Name - - sealed case class Document_Output(name: String, sources: SHA1.Digest, log_xz: Bytes, pdf: Bytes) - extends Document_Name - { - def log: String = log_xz.uncompress().text - def log_lines: List[String] = split_lines(log) - - def write(db: SQL.Database, session_name: String): Unit = - write_document(db, session_name, this) - } - - - /* SQL data model */ - - object Data - { - val session_name = SQL.Column.string("session_name").make_primary_key - val name = SQL.Column.string("name").make_primary_key - val sources = SQL.Column.string("sources") - val log_xz = SQL.Column.bytes("log_xz") - val pdf = SQL.Column.bytes("pdf") - - val table = SQL.Table("isabelle_documents", List(session_name, name, sources, log_xz, pdf)) - - def where_equal(session_name: String, name: String = ""): SQL.Source = - "WHERE " + Data.session_name.equal(session_name) + - (if (name == "") "" else " AND " + Data.name.equal(name)) - } - - def read_documents(db: SQL.Database, session_name: String): List[Document_Input] = - { - val select = Data.table.select(List(Data.name, Data.sources), Data.where_equal(session_name)) - db.using_statement(select)(stmt => - stmt.execute_query().iterator(res => - { - val name = res.string(Data.name) - val sources = res.string(Data.sources) - Document_Input(name, SHA1.fake(sources)) - }).toList) - } - - def read_document(db: SQL.Database, session_name: String, name: String): Option[Document_Output] = - { - val select = Data.table.select(sql = Data.where_equal(session_name, name)) - db.using_statement(select)(stmt => - { - val res = stmt.execute_query() - if (res.next()) { - val name = res.string(Data.name) - val sources = res.string(Data.sources) - val log_xz = res.bytes(Data.log_xz) - val pdf = res.bytes(Data.pdf) - Some(Document_Output(name, SHA1.fake(sources), log_xz, pdf)) - } - else None - }) - } - - def write_document(db: SQL.Database, session_name: String, doc: Document_Output): Unit = - { - db.using_statement(Data.table.insert())(stmt => - { - stmt.string(1) = session_name - stmt.string(2) = doc.name - stmt.string(3) = doc.sources.toString - stmt.bytes(4) = doc.log_xz - stmt.bytes(5) = doc.pdf - stmt.execute() - }) - } - + /** HTML presentation **/ /* presentation context */ @@ -311,9 +200,6 @@ } - - /** HTML presentation **/ - /* maintain chapter index */ private val sessions_path = Path.basic(".sessions") @@ -498,7 +384,7 @@ val documents = for { doc <- info.document_variants - document <- db_context.input_database(session)(read_document(_, _, doc.name)) + document <- db_context.input_database(session)(Document_Build.read_document(_, _, doc.name)) } yield { if (verbose) progress.echo("Presenting document " + session + "/" + doc.name) Bytes.write(session_dir + doc.path.pdf, document.pdf) @@ -613,259 +499,4 @@ html_context.head(title, List(HTML.par(view_links))) :: html_context.contents("Theories", theories)) } - - - - /** build documents **/ - - val session_tex_path = Path.explode("session.tex") - - def tex_name(name: Document.Node.Name): String = name.theory_base_name + ".tex" - def document_tex_name(name: Document.Node.Name): String = "document/" + tex_name(name) - - class Build_Error(val log_lines: List[String], val message: String) - extends Exn.User_Error(message) - - def build_documents( - session: String, - deps: Sessions.Deps, - db_context: Sessions.Database_Context, - progress: Progress = new Progress, - output_sources: Option[Path] = None, - output_pdf: Option[Path] = None, - verbose: Boolean = false, - verbose_latex: Boolean = false): List[Document_Output] = - { - /* session info */ - - val info = deps.sessions_structure(session) - val hierarchy = deps.sessions_structure.hierarchy(session) - val options = info.options - val base = deps(session) - val graph_pdf = graphview.Graph_File.make_pdf(options, base.session_graph_display) - - - /* prepare document directory */ - - lazy val tex_files = - for (name <- base.session_theories ::: base.document_theories) - yield { - val entry = db_context.get_export(hierarchy, name.theory, document_tex_name(name)) - Path.basic(tex_name(name)) -> entry.uncompressed - } - - def prepare_dir1(dir: Path, doc: Document_Variant): (Path, String) = - { - val doc_dir = dir + Path.basic(doc.name) - Isabelle_System.make_directory(doc_dir) - - Isabelle_System.bash("isabelle latex -o sty", cwd = doc_dir.file).check - File.write(doc_dir + Path.explode("isabelletags.sty"), doc.latex_sty) - for ((base_dir, src) <- info.document_files) { - Isabelle_System.copy_file_base(info.dir + base_dir, src, doc_dir) - } - - File.write(doc_dir + session_tex_path, - Library.terminate_lines( - base.session_theories.map(name => "\\input{" + tex_name(name) + "}"))) - - for ((path, tex) <- tex_files) Bytes.write(doc_dir + path, tex) - - val root1 = "root_" + doc.name - val root = if ((doc_dir + Path.explode(root1).tex).is_file) root1 else "root" - - (doc_dir, root) - } - - def prepare_dir2(dir: Path, doc: Document_Variant): Unit = - { - val doc_dir = dir + Path.basic(doc.name) - - // non-deterministic, but irrelevant - Bytes.write(doc_dir + session_graph_path, graph_pdf) - } - - - /* produce documents */ - - val documents = - for (doc <- info.documents) - yield { - Isabelle_System.with_tmp_dir("document")(tmp_dir => - { - progress.echo("Preparing " + session + "/" + doc.name + " ...") - val start = Time.now() - - - // prepare sources - - val (doc_dir, root) = prepare_dir1(tmp_dir, doc) - val digests = File.find_files(doc_dir.file, follow_links = true).map(SHA1.digest) - val sources = SHA1.digest_set(digests) - prepare_dir2(tmp_dir, doc) - - for (dir <- output_sources) { - prepare_dir1(dir, doc) - prepare_dir2(dir, doc) - } - - - // old document from database - - val old_document = - for { - old_doc <- db_context.input_database(session)(read_document(_, _, doc.name)) - if old_doc.sources == sources - } - yield { - Bytes.write(doc_dir + doc.path.pdf, old_doc.pdf) - old_doc - } - - old_document getOrElse { - // bash scripts - - def root_bash(ext: String): String = Bash.string(root + "." + ext) - - def latex_bash(fmt: String = "pdf", ext: String = "tex"): String = - "isabelle latex -o " + Bash.string(fmt) + " " + Bash.string(root + "." + ext) - - def bash(items: String*): Process_Result = - progress.bash(items.mkString(" && "), cwd = doc_dir.file, - echo = verbose_latex, watchdog = Time.seconds(0.5)) - - - // prepare document - - val result = - if ((doc_dir + Path.explode("build")).is_file) { - bash("./build pdf " + Bash.string(doc.name)) - } - else { - bash( - latex_bash(), - "{ [ ! -f " + root_bash("bib") + " ] || " + latex_bash("bbl") + "; }", - "{ [ ! -f " + root_bash("idx") + " ] || " + latex_bash("idx") + "; }", - latex_bash(), - latex_bash()) - } - - - // result - - val root_pdf = Path.basic(root).pdf - val result_path = doc_dir + root_pdf - - val log_lines = result.out_lines ::: result.err_lines - - val errors = - (if (result.ok) Nil else List(result.err)) ::: - Latex.latex_errors(doc_dir, root) ::: - Bibtex.bibtex_errors(doc_dir, root) - - if (errors.nonEmpty) { - val message = - Exn.cat_message( - (errors ::: List("Failed to build document " + quote(doc.name))):_*) - throw new Build_Error(log_lines, message) - } - else if (!result_path.is_file) { - val message = "Bad document result: expected to find " + root_pdf - throw new Build_Error(log_lines, message) - } - else { - val stop = Time.now() - val timing = stop - start - progress.echo("Finished " + session + "/" + doc.name + - " (" + timing.message_hms + " elapsed time)") - - val log_xz = Bytes(cat_lines(log_lines)).compress() - val pdf = Bytes.read(result_path) - Document_Output(doc.name, sources, log_xz, pdf) - } - } - }) - } - - for (dir <- output_pdf; doc <- documents) { - Isabelle_System.make_directory(dir) - val path = dir + doc.path.pdf - Bytes.write(path, doc.pdf) - progress.echo("Document at " + path.absolute) - } - - documents - } - - - /* Isabelle tool wrapper */ - - val isabelle_tool = - Isabelle_Tool("document", "prepare session theory document", Scala_Project.here, args => - { - var output_sources: Option[Path] = None - var output_pdf: Option[Path] = None - var verbose_latex = false - var dirs: List[Path] = Nil - var options = Options.init() - var verbose_build = false - - val getopts = Getopts( - """ -Usage: isabelle document [OPTIONS] SESSION - - Options are: - -O DIR output directory for LaTeX sources and resulting PDF - -P DIR output directory for resulting PDF - -S DIR output directory for LaTeX sources - -V verbose latex - -d DIR include session directory - -o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) - -v verbose build - - Prepare the theory document of a session. -""", - "O:" -> (arg => - { - val dir = Path.explode(arg) - output_sources = Some(dir) - output_pdf = Some(dir) - }), - "P:" -> (arg => { output_pdf = Some(Path.explode(arg)) }), - "S:" -> (arg => { output_sources = Some(Path.explode(arg)) }), - "V" -> (_ => verbose_latex = true), - "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))), - "o:" -> (arg => options = options + arg), - "v" -> (_ => verbose_build = true)) - - val more_args = getopts(args) - val session = - more_args match { - case List(a) => a - case _ => getopts.usage() - } - - val progress = new Console_Progress(verbose = verbose_build) - val store = Sessions.store(options) - - progress.interrupt_handler { - val res = - Build.build(options, selection = Sessions.Selection.session(session), - dirs = dirs, progress = progress, verbose = verbose_build) - if (!res.ok) error("Failed to build session " + quote(session)) - - val deps = - Sessions.load_structure(options + "document=pdf", dirs = dirs). - selection_deps(Sessions.Selection.session(session)) - - if (output_sources.isEmpty && output_pdf.isEmpty) { - progress.echo_warning("No output directory") - } - - using(store.open_database_context())(db_context => - build_documents(session, deps, db_context, progress = progress, - output_sources = output_sources, output_pdf = output_pdf, - verbose = true, verbose_latex = verbose_latex)) - } - }) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/sessions.scala --- a/src/Pure/Thy/sessions.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/sessions.scala Sun May 23 20:34:43 2021 +0200 @@ -514,11 +514,11 @@ case doc => error("Bad document specification " + quote(doc)) } - def document_variants: List[Presentation.Document_Variant] = + def document_variants: List[Document_Build.Document_Variant] = { val variants = Library.space_explode(':', options.string("document_variants")). - map(Presentation.Document_Variant.parse) + map(Document_Build.Document_Variant.parse) val dups = Library.duplicates(variants.map(_.name)) if (dups.nonEmpty) error("Duplicate document variants: " + commas_quote(dups)) @@ -526,7 +526,7 @@ variants } - def documents: List[Presentation.Document_Variant] = + def documents: List[Document_Build.Document_Variant] = { val variants = document_variants if (!document_enabled || document_files.isEmpty) Nil else variants @@ -1429,10 +1429,10 @@ db.using_statement( Export.Data.table.delete(Export.Data.session_name.where_equal(name)))(_.execute()) - db.create_table(Presentation.Data.table) + db.create_table(Document_Build.Data.table) db.using_statement( - Presentation.Data.table.delete( - Presentation.Data.session_name.where_equal(name)))(_.execute()) + Document_Build.Data.table.delete( + Document_Build.Data.session_name.where_equal(name)))(_.execute()) } } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/thy_info.ML --- a/src/Pure/Thy/thy_info.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Thy/thy_info.ML Sun May 23 20:34:43 2021 +0200 @@ -9,7 +9,7 @@ sig type presentation_context = {options: Options.T, file_pos: Position.T, adjust_pos: Position.T -> Position.T, - segments: Thy_Output.segment list} + segments: Document_Output.segment list} val adjust_pos_properties: presentation_context -> Position.T -> Properties.T val apply_presentation: presentation_context -> theory -> unit val add_presentation: (presentation_context -> theory -> unit) -> theory -> theory @@ -42,7 +42,7 @@ type presentation_context = {options: Options.T, file_pos: Position.T, adjust_pos: Position.T -> Position.T, - segments: Thy_Output.segment list}; + segments: Document_Output.segment list}; fun adjust_pos_properties (context: presentation_context) pos = Position.offset_properties_of (#adjust_pos context pos) @ Position.id_properties_of pos; @@ -71,7 +71,7 @@ if exists (Toplevel.is_skipped_proof o #state) segments then () else let - val body = Thy_Output.present_thy options thy segments; + val body = Document_Output.present_thy options thy segments; in if Options.string options "document" = "false" then () else diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Thy/thy_output.ML --- a/src/Pure/Thy/thy_output.ML Wed May 19 14:17:40 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,570 +0,0 @@ -(* Title: Pure/Thy/thy_output.ML - Author: Makarius - -Theory document output. -*) - -signature THY_OUTPUT = -sig - val output_document: Proof.context -> {markdown: bool} -> Input.source -> Latex.text list - val check_comments: Proof.context -> Symbol_Pos.T list -> unit - val output_token: Proof.context -> Token.T -> Latex.text list - val output_source: Proof.context -> string -> Latex.text list - type segment = - {span: Command_Span.span, command: Toplevel.transition, - prev_state: Toplevel.state, state: Toplevel.state} - val present_thy: Options.T -> theory -> segment list -> Latex.text list - val pretty_term: Proof.context -> term -> Pretty.T - val pretty_thm: Proof.context -> thm -> Pretty.T - val lines: Latex.text list -> Latex.text list - val items: Latex.text list -> Latex.text list - val isabelle: Proof.context -> Latex.text list -> Latex.text - val isabelle_typewriter: Proof.context -> Latex.text list -> Latex.text - val typewriter: Proof.context -> string -> Latex.text - val verbatim: Proof.context -> string -> Latex.text - val source: Proof.context -> {embedded: bool} -> Token.src -> Latex.text - val pretty: Proof.context -> Pretty.T -> Latex.text - val pretty_source: Proof.context -> {embedded: bool} -> Token.src -> Pretty.T -> Latex.text - val pretty_items: Proof.context -> Pretty.T list -> Latex.text - val pretty_items_source: Proof.context -> {embedded: bool} -> Token.src -> - Pretty.T list -> Latex.text - val antiquotation_pretty: - binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory - val antiquotation_pretty_embedded: - binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory - val antiquotation_pretty_source: - binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory - val antiquotation_pretty_source_embedded: - binding -> 'a context_parser -> (Proof.context -> 'a -> Pretty.T) -> theory -> theory - val antiquotation_raw: - binding -> 'a context_parser -> (Proof.context -> 'a -> Latex.text) -> theory -> theory - val antiquotation_raw_embedded: - binding -> 'a context_parser -> (Proof.context -> 'a -> Latex.text) -> theory -> theory - val antiquotation_verbatim: - binding -> 'a context_parser -> (Proof.context -> 'a -> string) -> theory -> theory - val antiquotation_verbatim_embedded: - binding -> 'a context_parser -> (Proof.context -> 'a -> string) -> theory -> theory -end; - -structure Thy_Output: THY_OUTPUT = -struct - -(* output document source *) - -val output_symbols = single o Latex.symbols_output; - -fun output_comment ctxt (kind, syms) = - (case kind of - Comment.Comment => - Input.cartouche_content syms - |> output_document (ctxt |> Config.put Document_Antiquotation.thy_output_display false) - {markdown = false} - |> Latex.enclose_body "%\n\\isamarkupcmt{" "%\n}" - | Comment.Cancel => - Symbol_Pos.cartouche_content syms - |> output_symbols - |> Latex.enclose_body "%\n\\isamarkupcancel{" "}" - | Comment.Latex => [Latex.symbols (Symbol_Pos.cartouche_content syms)] - | Comment.Marker => []) -and output_comment_document ctxt (comment, syms) = - (case comment of - SOME kind => output_comment ctxt (kind, syms) - | NONE => [Latex.symbols syms]) -and output_document_text ctxt syms = - Comment.read_body syms |> maps (output_comment_document ctxt) -and output_document ctxt {markdown} source = - let - val pos = Input.pos_of source; - val syms = Input.source_explode source; - - val output_antiquotes = - maps (Document_Antiquotation.evaluate (output_document_text ctxt) ctxt); - - fun output_line line = - (if Markdown.line_is_item line then [Latex.string "\\item "] else []) @ - output_antiquotes (Markdown.line_content line); - - fun output_block (Markdown.Par lines) = - Latex.block (separate (Latex.string "\n") (map (Latex.block o output_line) lines)) - | output_block (Markdown.List {kind, body, ...}) = - Latex.environment_block (Markdown.print_kind kind) (output_blocks body) - and output_blocks blocks = separate (Latex.string "\n\n") (map output_block blocks); - in - if Toplevel.is_skipped_proof (Toplevel.presentation_state ctxt) then [] - else if markdown andalso exists (Markdown.is_control o Symbol_Pos.symbol) syms - then - let - val ants = Antiquote.parse_comments pos syms; - val reports = Antiquote.antiq_reports ants; - val blocks = Markdown.read_antiquotes ants; - val _ = Context_Position.reports ctxt (reports @ Markdown.reports blocks); - in output_blocks blocks end - else - let - val ants = Antiquote.parse_comments pos (trim (Symbol.is_blank o Symbol_Pos.symbol) syms); - val reports = Antiquote.antiq_reports ants; - val _ = Context_Position.reports ctxt (reports @ Markdown.text_reports ants); - in output_antiquotes ants end - end; - - -(* output tokens with formal comments *) - -local - -val output_symbols_antiq = - (fn Antiquote.Text syms => output_symbols syms - | Antiquote.Control {name = (name, _), body, ...} => - Latex.string (Latex.output_symbols [Symbol.encode (Symbol.Control name)]) :: - output_symbols body - | Antiquote.Antiq {body, ...} => - Latex.enclose_body "%\n\\isaantiq\n" "{}%\n\\endisaantiq\n" (output_symbols body)); - -fun output_comment_symbols ctxt {antiq} (comment, syms) = - (case (comment, antiq) of - (NONE, false) => output_symbols syms - | (NONE, true) => - Antiquote.parse_comments (#1 (Symbol_Pos.range syms)) syms - |> maps output_symbols_antiq - | (SOME comment, _) => output_comment ctxt (comment, syms)); - -fun output_body ctxt antiq bg en syms = - Comment.read_body syms - |> maps (output_comment_symbols ctxt {antiq = antiq}) - |> Latex.enclose_body bg en; - -in - -fun output_token ctxt tok = - let - fun output antiq bg en = - output_body ctxt antiq bg en (Input.source_explode (Token.input_of tok)); - in - (case Token.kind_of tok of - Token.Comment NONE => [] - | Token.Comment (SOME Comment.Marker) => [] - | Token.Command => output false "\\isacommand{" "}" - | Token.Keyword => - if Symbol.is_ascii_identifier (Token.content_of tok) - then output false "\\isakeyword{" "}" - else output false "" "" - | Token.String => output false "{\\isachardoublequoteopen}" "{\\isachardoublequoteclose}" - | Token.Alt_String => output false "{\\isacharbackquoteopen}" "{\\isacharbackquoteclose}" - | Token.Verbatim => output true "{\\isacharverbatimopen}" "{\\isacharverbatimclose}" - | Token.Cartouche => output false "{\\isacartoucheopen}" "{\\isacartoucheclose}" - | _ => output false "" "") - end handle ERROR msg => error (msg ^ Position.here (Token.pos_of tok)); - -fun output_source ctxt s = - output_body ctxt false "" "" (Symbol_Pos.explode (s, Position.none)); - -fun check_comments ctxt = - Comment.read_body #> List.app (fn (comment, syms) => - let - val pos = #1 (Symbol_Pos.range syms); - val _ = - comment |> Option.app (fn kind => - Context_Position.reports ctxt (map (pair pos) (Comment.kind_markups kind))); - val _ = output_comment_symbols ctxt {antiq = false} (comment, syms); - in if comment = SOME Comment.Comment then check_comments ctxt syms else () end); - -end; - - - -(** present theory source **) - -(* presentation tokens *) - -datatype token = - Ignore - | Token of Token.T - | Heading of string * Input.source - | Body of string * Input.source - | Raw of Input.source; - -fun token_with pred (Token tok) = pred tok - | token_with _ _ = false; - -val white_token = token_with Document_Source.is_white; -val white_comment_token = token_with Document_Source.is_white_comment; -val blank_token = token_with Token.is_blank; -val newline_token = token_with Token.is_newline; - -fun present_token ctxt tok = - (case tok of - Ignore => [] - | Token tok => output_token ctxt tok - | Heading (cmd, source) => - Latex.enclose_body ("%\n\\isamarkup" ^ cmd ^ "{") "%\n}\n" - (output_document ctxt {markdown = false} source) - | Body (cmd, source) => - [Latex.environment_block ("isamarkup" ^ cmd) (output_document ctxt {markdown = true} source)] - | Raw source => - Latex.string "%\n" :: output_document ctxt {markdown = true} source @ [Latex.string "\n"]); - - -(* command spans *) - -type command = string * Position.T; (*name, position*) -type source = (token * (string * int)) list; (*token, markup flag, meta-comment depth*) - -datatype span = Span of command * (source * source * source * source) * bool; - -fun make_span cmd src = - let - fun chop_newline (tok :: toks) = - if newline_token (fst tok) then ([tok], toks, true) - else ([], tok :: toks, false) - | chop_newline [] = ([], [], false); - val (((src_prefix, src_main), src_suffix1), (src_suffix2, src_appendix, newline)) = - src - |> chop_prefix (white_token o fst) - ||>> chop_suffix (white_token o fst) - ||>> chop_prefix (white_comment_token o fst) - ||> chop_newline; - in Span (cmd, (src_prefix, src_main, src_suffix1 @ src_suffix2, src_appendix), newline) end; - - -(* present spans *) - -local - -fun err_bad_nesting here = - error ("Bad nesting of commands in presentation" ^ here); - -fun edge which f (x: string option, y) = - if x = y then I - else (case which (x, y) of NONE => I | SOME txt => cons (Latex.string (f txt))); - -val begin_tag = edge #2 Latex.begin_tag; -val end_tag = edge #1 Latex.end_tag; -fun open_delim delim e = edge #2 Latex.begin_delim e #> delim #> edge #2 Latex.end_delim e; -fun close_delim delim e = edge #1 Latex.begin_delim e #> delim #> edge #1 Latex.end_delim e; - -fun document_tag cmd_pos state state' tagging_stack = - let - val ctxt' = Toplevel.presentation_context state'; - val nesting = Toplevel.level state' - Toplevel.level state; - - val (tagging, taggings) = tagging_stack; - val (tag', tagging') = Document_Source.update_tagging ctxt' tagging; - - val tagging_stack' = - if nesting = 0 andalso not (Toplevel.is_proof state) then tagging_stack - else if nesting >= 0 then (tagging', replicate nesting tagging @ taggings) - else - (case drop (~ nesting - 1) taggings of - tg :: tgs => (tg, tgs) - | [] => err_bad_nesting (Position.here cmd_pos)); - in (tag', tagging_stack') end; - -fun read_tag s = - (case space_explode "%" s of - ["", b] => (SOME b, NONE) - | [a, b] => (NONE, SOME (a, b)) - | _ => error ("Bad document_tags specification: " ^ quote s)); - -in - -fun make_command_tag options keywords = - let - val document_tags = - map read_tag (space_explode "," (Options.string options \<^system_option>\document_tags\)); - val document_tags_default = map_filter #1 document_tags; - val document_tags_command = map_filter #2 document_tags; - in - fn cmd_name => fn state => fn state' => fn active_tag => - let - val keyword_tags = - if cmd_name = "end" andalso Toplevel.is_end_theory state' then ["theory"] - else Keyword.command_tags keywords cmd_name; - val command_tags = - the_list (AList.lookup (op =) document_tags_command cmd_name) @ - keyword_tags @ document_tags_default; - val active_tag' = - (case command_tags of - default_tag :: _ => SOME default_tag - | [] => - if Keyword.is_vacuous keywords cmd_name andalso Toplevel.is_proof state - then active_tag - else NONE); - in active_tag' end - end; - -fun present_span command_tag span state state' - (tagging_stack, active_tag, newline, latex, present_cont) = - let - val ctxt' = Toplevel.presentation_context state'; - val present = fold (fn (tok, (flag, 0)) => - fold cons (present_token ctxt' tok) - #> cons (Latex.string flag) - | _ => I); - - val Span ((cmd_name, cmd_pos), srcs, span_newline) = span; - - val (tag', tagging_stack') = document_tag cmd_pos state state' tagging_stack; - val active_tag' = - if is_some tag' then Option.map #1 tag' - else command_tag cmd_name state state' active_tag; - val edge = (active_tag, active_tag'); - - val newline' = - if is_none active_tag' then span_newline else newline; - - val latex' = - latex - |> end_tag edge - |> close_delim (fst present_cont) edge - |> snd present_cont - |> open_delim (present (#1 srcs)) edge - |> begin_tag edge - |> present (#2 srcs); - val present_cont' = - if newline then (present (#3 srcs), present (#4 srcs)) - else (I, present (#3 srcs) #> present (#4 srcs)); - in (tagging_stack', active_tag', newline', latex', present_cont') end; - -fun present_trailer ((_, tags), active_tag, _, latex, present_cont) = - if not (null tags) then err_bad_nesting " at end of theory" - else - latex - |> end_tag (active_tag, NONE) - |> close_delim (fst present_cont) (active_tag, NONE) - |> snd present_cont; - -end; - - -(* present_thy *) - -local - -val markup_true = "\\isamarkuptrue%\n"; -val markup_false = "\\isamarkupfalse%\n"; - -val opt_newline = Scan.option (Scan.one Token.is_newline); - -val ignore = - Scan.depend (fn d => opt_newline |-- Scan.one Token.is_begin_ignore - >> pair (d + 1)) || - Scan.depend (fn d => Scan.one Token.is_end_ignore --| - (if d = 0 then Scan.fail_with (K (fn () => "Bad nesting of meta-comments")) else opt_newline) - >> pair (d - 1)); - -val locale = - Scan.option ((Parse.$$$ "(" -- Document_Source.improper -- Parse.$$$ "in") |-- - Parse.!!! - (Document_Source.improper |-- Parse.name --| (Document_Source.improper -- Parse.$$$ ")"))); - -in - -type segment = - {span: Command_Span.span, command: Toplevel.transition, - prev_state: Toplevel.state, state: Toplevel.state}; - -fun present_thy options thy (segments: segment list) = - let - val keywords = Thy_Header.get_keywords thy; - - - (* tokens *) - - val ignored = Scan.state --| ignore - >> (fn d => (NONE, (Ignore, ("", d)))); - - fun markup pred mk flag = Scan.peek (fn d => - Document_Source.improper |-- - Parse.position (Scan.one (fn tok => - Token.is_command tok andalso pred keywords (Token.content_of tok))) -- - (Document_Source.annotation |-- - Parse.!!!! ((Document_Source.improper -- locale -- Document_Source.improper) |-- - Parse.document_source --| Document_Source.improper_end)) - >> (fn ((tok, pos'), source) => - let val name = Token.content_of tok - in (SOME (name, pos'), (mk (name, source), (flag, d))) end)); - - val command = Scan.peek (fn d => - Scan.optional (Scan.one Token.is_command_modifier ::: Document_Source.improper) [] -- - Scan.one Token.is_command --| Document_Source.annotation - >> (fn (cmd_mod, cmd) => - map (fn tok => (NONE, (Token tok, ("", d)))) cmd_mod @ - [(SOME (Token.content_of cmd, Token.pos_of cmd), - (Token cmd, (markup_false, d)))])); - - val cmt = Scan.peek (fn d => - Scan.one Document_Source.is_black_comment >> (fn tok => (NONE, (Token tok, ("", d))))); - - val other = Scan.peek (fn d => - Parse.not_eof >> (fn tok => (NONE, (Token tok, ("", d))))); - - val tokens = - (ignored || - markup Keyword.is_document_heading Heading markup_true || - markup Keyword.is_document_body Body markup_true || - markup Keyword.is_document_raw (Raw o #2) "") >> single || - command || - (cmt || other) >> single; - - - (* spans *) - - val is_eof = fn (_, (Token x, _)) => Token.is_eof x | _ => false; - val stopper = Scan.stopper (K (NONE, (Token Token.eof, ("", 0)))) is_eof; - - val cmd = Scan.one (is_some o fst); - val non_cmd = Scan.one (is_none o fst andf not o is_eof) >> #2; - - val white_comments = Scan.many (white_comment_token o fst o snd); - val blank = Scan.one (blank_token o fst o snd); - val newline = Scan.one (newline_token o fst o snd); - val before_cmd = - Scan.option (newline -- white_comments) -- - Scan.option (newline -- white_comments) -- - Scan.option (blank -- white_comments) -- cmd; - - val span = - Scan.repeat non_cmd -- cmd -- - Scan.repeat (Scan.unless before_cmd non_cmd) -- - Scan.option (newline >> (single o snd)) - >> (fn (((toks1, (cmd, tok2)), toks3), tok4) => - make_span (the cmd) (toks1 @ (tok2 :: (toks3 @ the_default [] tok4)))); - - val spans = segments - |> maps (Command_Span.content o #span) - |> drop_suffix Token.is_space - |> Source.of_list - |> Source.source' 0 Token.stopper (Scan.error (Scan.bulk tokens >> flat)) - |> Source.source stopper (Scan.error (Scan.bulk span)) - |> Source.exhaust; - - val command_results = - segments |> map_filter (fn {command, state, ...} => - if Toplevel.is_ignored command then NONE else SOME (command, state)); - - - (* present commands *) - - val command_tag = make_command_tag options keywords; - - fun present_command tr span st st' = - Toplevel.setmp_thread_position tr (present_span command_tag span st st'); - - fun present _ [] = I - | present st ((span, (tr, st')) :: rest) = present_command tr span st st' #> present st' rest; - in - if length command_results = length spans then - (([], []), NONE, true, [], (I, I)) - |> present (Toplevel.init_toplevel ()) (spans ~~ command_results) - |> present_trailer - |> rev - else error "Messed-up outer syntax for presentation" - end; - -end; - - - -(** standard output operations **) - -(* pretty printing *) - -fun pretty_term ctxt t = - Syntax.pretty_term (Proof_Context.augment t ctxt) t; - -fun pretty_thm ctxt = pretty_term ctxt o Thm.full_prop_of; - - -(* default output *) - -val lines = separate (Latex.string "\\isanewline%\n"); -val items = separate (Latex.string "\\isasep\\isanewline%\n"); - -fun isabelle ctxt body = - if Config.get ctxt Document_Antiquotation.thy_output_display - then Latex.environment_block "isabelle" body - else Latex.block (Latex.enclose_body "\\isa{" "}" body); - -fun isabelle_typewriter ctxt body = - if Config.get ctxt Document_Antiquotation.thy_output_display - then Latex.environment_block "isabellett" body - else Latex.block (Latex.enclose_body "\\isatt{" "}" body); - -fun typewriter ctxt s = - isabelle_typewriter ctxt [Latex.string (Latex.output_ascii s)]; - -fun verbatim ctxt = - if Config.get ctxt Document_Antiquotation.thy_output_display - then Document_Antiquotation.indent_lines ctxt #> typewriter ctxt - else split_lines #> map (typewriter ctxt) #> lines #> Latex.block; - -fun token_source ctxt {embedded} tok = - if Token.is_kind Token.Cartouche tok andalso embedded andalso - not (Config.get ctxt Document_Antiquotation.thy_output_source_cartouche) - then Token.content_of tok - else Token.unparse tok; - -fun is_source ctxt = - Config.get ctxt Document_Antiquotation.thy_output_source orelse - Config.get ctxt Document_Antiquotation.thy_output_source_cartouche; - -fun source ctxt embedded = - Token.args_of_src - #> map (token_source ctxt embedded #> Document_Antiquotation.prepare_lines ctxt) - #> space_implode " " - #> output_source ctxt - #> isabelle ctxt; - -fun pretty ctxt = - Document_Antiquotation.output ctxt #> Latex.string #> single #> isabelle ctxt; - -fun pretty_source ctxt embedded src prt = - if is_source ctxt then source ctxt embedded src else pretty ctxt prt; - -fun pretty_items ctxt = - map (Document_Antiquotation.output ctxt #> Latex.string) #> items #> isabelle ctxt; - -fun pretty_items_source ctxt embedded src prts = - if is_source ctxt then source ctxt embedded src else pretty_items ctxt prts; - - -(* antiquotation variants *) - -local - -fun gen_setup name embedded = - if embedded - then Document_Antiquotation.setup_embedded name - else Document_Antiquotation.setup name; - -fun gen_antiquotation_pretty name embedded scan f = - gen_setup name embedded scan (fn {context = ctxt, argument = x, ...} => pretty ctxt (f ctxt x)); - -fun gen_antiquotation_pretty_source name embedded scan f = - gen_setup name embedded scan - (fn {context = ctxt, source = src, argument = x} => - pretty_source ctxt {embedded = embedded} src (f ctxt x)); - -fun gen_antiquotation_raw name embedded scan f = - gen_setup name embedded scan (fn {context = ctxt, argument = x, ...} => f ctxt x); - -fun gen_antiquotation_verbatim name embedded scan f = - gen_antiquotation_raw name embedded scan (fn ctxt => verbatim ctxt o f ctxt); - -in - -fun antiquotation_pretty name = gen_antiquotation_pretty name false; -fun antiquotation_pretty_embedded name = gen_antiquotation_pretty name true; - -fun antiquotation_pretty_source name = gen_antiquotation_pretty_source name false; -fun antiquotation_pretty_source_embedded name = gen_antiquotation_pretty_source name true; - -fun antiquotation_raw name = gen_antiquotation_raw name false; -fun antiquotation_raw_embedded name = gen_antiquotation_raw name true; - -fun antiquotation_verbatim name = gen_antiquotation_verbatim name false; -fun antiquotation_verbatim_embedded name = gen_antiquotation_verbatim name true; - -end; - -end; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/build.scala --- a/src/Pure/Tools/build.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/build.scala Sun May 23 20:34:43 2021 +0200 @@ -576,7 +576,7 @@ Build and manage Isabelle sessions, depending on implicit settings: -""" + Library.prefix_lines(" ", Build_Log.Settings.show()) + "\n", +""" + Library.indent_lines(2, Build_Log.Settings.show()) + "\n", "B:" -> (arg => base_sessions = base_sessions ::: List(arg)), "D:" -> (arg => select_dirs = select_dirs ::: List(Path.explode(arg))), "N" -> (_ => numa_shuffling = true), diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/build_job.scala --- a/src/Pure/Tools/build_job.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/build_job.scala Sun May 23 20:34:43 2021 +0200 @@ -447,10 +447,10 @@ using(store.open_database_context())(db_context => { val documents = - Presentation.build_documents(session_name, deps, db_context, + Document_Build.build_documents( + Document_Build.context(session_name, deps, db_context, progress = progress), output_sources = info.document_output, output_pdf = info.document_output, - progress = progress, verbose = verbose) db_context.output_database(session_name)(db => documents.foreach(_.write(db, session_name))) @@ -460,7 +460,7 @@ else (Nil, Nil) } catch { - case exn: Presentation.Build_Error => (exn.log_lines, List(exn.message)) + case exn: Document_Build.Build_Error => (exn.log_lines, List(exn.message)) case Exn.Interrupt.ERROR(msg) => (Nil, List(msg)) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/doc.ML --- a/src/Pure/Tools/doc.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/doc.ML Sun May 23 20:34:43 2021 +0200 @@ -18,7 +18,7 @@ val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\doc\ + (Document_Output.antiquotation_verbatim_embedded \<^binding>\doc\ (Scan.lift Parse.embedded_position) check); end; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/dump.scala --- a/src/Pure/Tools/dump.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/dump.scala Sun May 23 20:34:43 2021 +0200 @@ -456,7 +456,7 @@ Dump cumulative PIDE session database, with the following aspects: -""" + Library.prefix_lines(" ", show_aspects) + "\n", +""" + Library.indent_lines(4, show_aspects) + "\n", "A:" -> (arg => aspects = Library.distinct(space_explode(',', arg)).map(the_aspect)), "B:" -> (arg => base_sessions = base_sessions ::: List(arg)), "D:" -> (arg => select_dirs = select_dirs ::: List(Path.explode(arg))), diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/jedit.ML --- a/src/Pure/Tools/jedit.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/jedit.ML Sun May 23 20:34:43 2021 +0200 @@ -78,7 +78,7 @@ val _ = Theory.setup - (Thy_Output.antiquotation_verbatim_embedded \<^binding>\action\ (Scan.lift Args.embedded_position) + (Document_Output.antiquotation_verbatim_embedded \<^binding>\action\ (Scan.lift Args.embedded_position) (fn ctxt => fn (name, pos) => let val _ = diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/logo.scala --- a/src/Pure/Tools/logo.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/logo.scala Sun May 23 20:34:43 2021 +0200 @@ -11,12 +11,19 @@ { /* create logo */ + def make_output_file(logo_name: String): Path = + { + val name = if (logo_name.isEmpty) "isabelle" else "isabelle_" + Word.lowercase(logo_name) + Path.explode(name).pdf + } + def create_logo(logo_name: String, output_file: Path, quiet: Boolean = false): Unit = { Isabelle_System.with_tmp_file("logo", ext = "eps")(tmp_file => { val template = File.read(Path.explode("$ISABELLE_HOME/lib/logo/isabelle_any.eps")) File.write(tmp_file, template.replace("", logo_name)) + Isabelle_System.bash( "\"$ISABELLE_EPSTOPDF\" --filter < " + File.bash_path(tmp_file) + " > " + File.bash_path(output_file)).check @@ -46,13 +53,12 @@ "q" -> (_ => quiet = true)) val more_args = getopts(args) - val (logo_name, output_file) = + val logo_name = more_args match { - case Nil => ("", Path.explode("isabelle").pdf) - case List(a) => (a, output.getOrElse(Path.explode("isabelle_" + Word.lowercase(a)).pdf)) + case Nil => "" + case List(name) => name case _ => getopts.usage() } - - create_logo(logo_name, output_file, quiet = quiet) + create_logo(logo_name, output getOrElse make_output_file(logo_name), quiet = quiet) }) } diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/phabricator.scala --- a/src/Pure/Tools/phabricator.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/phabricator.scala Sun May 23 20:34:43 2021 +0200 @@ -91,7 +91,7 @@ NAME="$(echo "$REPLY" | cut -d: -f1)" ROOT="$(echo "$REPLY" | cut -d: -f2)" { -""" + Library.prefix_lines(" ", body) + """ +""" + Library.indent_lines(6, body) + """ } < /dev/null done } < """ + File.bash_path(global_config) + "\n" + diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/Tools/rail.ML --- a/src/Pure/Tools/rail.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/Tools/rail.ML Sun May 23 20:34:43 2021 +0200 @@ -384,7 +384,7 @@ in Latex.string (Latex.environment "railoutput" (implode (map output_rule rules))) end; val _ = Theory.setup - (Thy_Output.antiquotation_raw_embedded \<^binding>\rail\ (Scan.lift Args.text_input) + (Document_Output.antiquotation_raw_embedded \<^binding>\rail\ (Scan.lift Args.text_input) (fn ctxt => output_rules ctxt o read ctxt)); end; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/build-jars --- a/src/Pure/build-jars Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/build-jars Sun May 23 20:34:43 2021 +0200 @@ -154,6 +154,7 @@ src/Pure/System/system_channel.scala src/Pure/System/tty_loop.scala src/Pure/Thy/bibtex.scala + src/Pure/Thy/document_build.scala src/Pure/Thy/export.scala src/Pure/Thy/export_theory.scala src/Pure/Thy/file_format.scala diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/library.ML --- a/src/Pure/library.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/library.ML Sun May 23 20:34:43 2021 +0200 @@ -132,6 +132,7 @@ val fold_string: (string -> 'a -> 'a) -> string -> 'a -> 'a val exists_string: (string -> bool) -> string -> bool val forall_string: (string -> bool) -> string -> bool + val member_string: string -> string -> bool val first_field: string -> string -> (string * string) option val enclose: string -> string -> string -> string val unenclose: string -> string @@ -703,6 +704,8 @@ fun forall_string pred = not o exists_string (not o pred); +fun member_string str s = exists_string (fn s' => s = s') str; + fun first_field sep str = let val n = size sep; diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/library.scala --- a/src/Pure/library.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/library.scala Sun May 23 20:34:43 2021 +0200 @@ -107,6 +107,9 @@ def prefix_lines(prfx: String, str: String): String = if (str == "") str else cat_lines(split_lines(str).map(prfx + _)) + def indent_lines(n: Int, str: String): String = + prefix_lines(Symbol.spaces(n), str) + def first_line(source: CharSequence): String = { val lines = separated_chunks(_ == '\n', source) diff -r 58bd53caf800 -r 6b4c47666267 src/Pure/pure_syn.ML --- a/src/Pure/pure_syn.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Pure/pure_syn.ML Sun May 23 20:34:43 2021 +0200 @@ -20,12 +20,8 @@ fun output_document state markdown txt = let val ctxt = Toplevel.presentation_context state; - val pos = Input.pos_of txt; - val _ = - Context_Position.reports ctxt - [(pos, Markup.language_document (Input.is_delimited txt)), - (pos, Markup.plain_text)]; - in Thy_Output.output_document ctxt markdown txt end; + val _ = Context_Position.reports ctxt (Document_Output.document_reports txt); + in Document_Output.output_document ctxt markdown txt end; fun document_command markdown (loc, txt) = Toplevel.keep (fn state => diff -r 58bd53caf800 -r 6b4c47666267 src/Tools/Code/code_target.ML --- a/src/Tools/Code/code_target.ML Wed May 19 14:17:40 2021 +0100 +++ b/src/Tools/Code/code_target.ML Sun May 23 20:34:43 2021 +0200 @@ -782,7 +782,7 @@ in val _ = Theory.setup - (Thy_Output.antiquotation_raw \<^binding>\code_stmts\ + (Document_Output.antiquotation_raw \<^binding>\code_stmts\ (parse_const_terms -- Scan.repeats (parse_consts || parse_types || parse_classes || parse_instances) -- Scan.lift (Args.parens (Args.name -- Scan.option Parse.int))) @@ -790,7 +790,7 @@ present_code ctxt consts symbols target_name "Example" some_width [] |> trim_line - |> Thy_Output.verbatim (Config.put Document_Antiquotation.thy_output_display true ctxt))); + |> Document_Output.verbatim (Config.put Document_Antiquotation.thy_output_display true ctxt))); end; diff -r 58bd53caf800 -r 6b4c47666267 src/Tools/jEdit/src/keymap_merge.scala --- a/src/Tools/jEdit/src/keymap_merge.scala Wed May 19 14:17:40 2021 +0100 +++ b/src/Tools/jEdit/src/keymap_merge.scala Sun May 23 20:34:43 2021 +0200 @@ -30,7 +30,7 @@ class Shortcut(val property: String, val binding: String) { - override def toString: String = property + "=" + binding + override def toString: String = Properties.Eq(property, binding) def primary: Boolean = property.endsWith(".shortcut")