src/Doc/System/Scala.thy
changeset 71907 64c9628b39fc
parent 71897 2cf0b0293f0d
child 72103 7b318273a4aa
equal deleted inserted replaced
71906:a63072d875d1 71907:64c9628b39fc
     2 
     2 
     3 theory Scala
     3 theory Scala
     4 imports Base
     4 imports Base
     5 begin
     5 begin
     6 
     6 
     7 chapter \<open>Isabelle/Scala development tools\<close>
     7 chapter \<open>Isabelle/Scala systems programming\<close>
     8 
     8 
     9 text \<open>
     9 text \<open>
    10   Isabelle/ML and Isabelle/Scala are the two main language environments for
    10   Isabelle/ML and Isabelle/Scala are the two main implementation languages of
    11   Isabelle tool implementations. There are some basic command-line tools to
    11   the Isabelle environment:
    12   work with the underlying Java Virtual Machine, the Scala toplevel and
    12 
    13   compiler. Note that Isabelle/jEdit @{cite "isabelle-jedit"} provides a Scala
    13     \<^item> Isabelle/ML is for \<^emph>\<open>mathematics\<close>, to develop tools within the context
    14   Console for interactive experimentation within the running application.
    14     of symbolic logic, e.g.\ for constructing proofs or defining
    15 \<close>
    15     domain-specific formal languages. See the \<^emph>\<open>Isabelle/Isar implementation
    16 
    16     manual\<close> @{cite "isabelle-implementation"} for more details.
    17 
    17 
    18 section \<open>Java Runtime Environment within Isabelle \label{sec:tool-java}\<close>
    18     \<^item> Isabelle/Scala is for \<^emph>\<open>physics\<close>, to connect with the world of systems
       
    19     and services, including editors and IDE frameworks.
       
    20 
       
    21   There are various ways to access Isabelle/Scala modules and operations:
       
    22 
       
    23     \<^item> Isabelle command-line tools (\secref{sec:scala-tools}) run in a separate
       
    24     Java process.
       
    25 
       
    26     \<^item> Isabelle/ML antiquotations access Isabelle/Scala functions
       
    27     (\secref{sec:scala-functions}) via the PIDE protocol: execution happens
       
    28     within the running Java process underlying Isabelle/Scala.
       
    29 
       
    30     \<^item> The \<^verbatim>\<open>Console/Scala\<close> plugin of Isabelle/jEdit @{cite "isabelle-jedit"}
       
    31     operates on the running Java application, using the Scala
       
    32     read-eval-print-loop (REPL).
       
    33 
       
    34   The main Isabelle/Scala functionality is provided by \<^verbatim>\<open>Pure.jar\<close>, but
       
    35   further add-ons are bundled with Isabelle, e.g.\ to access SQLite or
       
    36   PostgreSQL using JDBC (Java Database Connectivity).
       
    37 
       
    38   Other components may augment the system environment by providing a suitable
       
    39   \<^path>\<open>etc/settings\<close> shell script in the component directory. Some shell
       
    40   functions are available to help with that:
       
    41 
       
    42     \<^item> Function \<^bash_function>\<open>classpath\<close> adds \<^verbatim>\<open>jar\<close> files in Isabelle path
       
    43     notation (POSIX). On Windows, this is converted to native path names
       
    44     before invoking @{tool java} or @{tool scala} (\secref{sec:scala-tools}).
       
    45 
       
    46     \<^item> Function \<^bash_function>\<open>isabelle_scala_service\<close> registers global
       
    47     service providers as subclasses of
       
    48     \<^scala_type>\<open>isabelle.Isabelle_System.Service\<close>, using the raw Java name
       
    49     according to @{scala_method (in java.lang.Object) getClass} (it should be
       
    50     enclosed in single quotes to avoid special characters like \<^verbatim>\<open>$\<close> to be
       
    51     interpreted by the shell).
       
    52 
       
    53     Particular Isabelle/Scala services require particular subclasses:
       
    54     instances are filtered according to their dynamic type. For example, class
       
    55     \<^scala_type>\<open>isabelle.Isabelle_Scala_Tools\<close> collects Scala command-line
       
    56     tools, and class \<^scala_type>\<open>isabelle.Isabelle_Scala_Functions\<close>
       
    57     collects Scala functions (\secref{sec:scala-functions}).
       
    58 \<close>
       
    59 
       
    60 
       
    61 section \<open>Command-line tools \label{sec:scala-tools}\<close>
       
    62 
       
    63 subsection \<open>Java Runtime Environment \label{sec:tool-java}\<close>
    19 
    64 
    20 text \<open>
    65 text \<open>
    21   The @{tool_def java} tool is a direct wrapper for the Java Runtime
    66   The @{tool_def java} tool is a direct wrapper for the Java Runtime
    22   Environment, within the regular Isabelle settings environment
    67   Environment, within the regular Isabelle settings environment
    23   (\secref{sec:settings}). The command line arguments are that of the
    68   (\secref{sec:settings}) and Isabelle classpath. The command line arguments
    24   underlying Java version. It is run in \<^verbatim>\<open>-server\<close> mode if possible, to
    69   are that of the bundled Java distribution: see option \<^verbatim>\<open>-help\<close> in
    25   improve performance (at the cost of extra startup time).
    70   particular.
    26 
    71 
    27   The \<^verbatim>\<open>java\<close> executable is the one within @{setting ISABELLE_JDK_HOME},
    72   The \<^verbatim>\<open>java\<close> executable is taken from @{setting ISABELLE_JDK_HOME}, according
    28   according to the standard directory layout for official JDK distributions.
    73   to the standard directory layout for regular distributions of OpenJDK.
    29   The class loader is augmented such that the name space of
    74 
    30   \<^verbatim>\<open>Isabelle/Pure.jar\<close> is available, which is the main Isabelle/Scala module.
    75   The shell function \<^bash_function>\<open>isabelle_jdk\<close> allows shell scripts to
    31 \<close>
    76   invoke other Java tools robustly (e.g.\ \<^verbatim>\<open>isabelle_jdk jar\<close>), without
    32 
    77   depending on accidental operating system installations.
    33 
    78 \<close>
    34 section \<open>Scala toplevel \label{sec:tool-scala}\<close>
    79 
    35 
    80 
    36 text \<open>
    81 subsection \<open>Scala toplevel \label{sec:tool-scala}\<close>
    37   The @{tool_def scala} tool is a direct wrapper for the Scala toplevel; see
    82 
    38   also @{tool java} above. The command line arguments are that of the
    83 text \<open>
    39   underlying Scala version. This allows to interact with Isabelle/Scala in TTY
    84   The @{tool_def scala} tool is a direct wrapper for the Scala toplevel,
    40   mode. An alternative is to use the \<^verbatim>\<open>Console/Scala\<close> plugin of Isabelle/jEdit
    85   similar to @{tool java} above. The command line arguments are that of the
    41   @{cite "isabelle-jedit"}.
    86   bundled Scala distribution: see option \<^verbatim>\<open>-help\<close> in particular. This allows
       
    87   to interact with Isabelle/Scala interactively.
    42 \<close>
    88 \<close>
    43 
    89 
    44 subsubsection \<open>Example\<close>
    90 subsubsection \<open>Example\<close>
    45 
    91 
    46 text \<open>
    92 text \<open>
    47   Explore the Isabelle system environment in Scala:
    93   Explore the Isabelle system environment in Scala:
    48   @{scala [display]
    94   @{verbatim [display, indent = 2] \<open>$ isabelle scala\<close>}
       
    95   @{scala [display, indent = 2]
    49 \<open>import isabelle._
    96 \<open>import isabelle._
    50 
    97 
    51 val isabelle_home = Isabelle_System.getenv("ISABELLE_HOME")
    98 val isabelle_home = Isabelle_System.getenv("ISABELLE_HOME")
    52 
    99 
    53 val options = Options.init()
   100 val options = Options.init()
    54 options.bool("browser_info")
   101 options.bool("browser_info")
    55 options.string("document")\<close>}
   102 options.string("document")\<close>}
    56 \<close>
   103 \<close>
    57 
   104 
    58 
   105 
    59 section \<open>Scala compiler \label{sec:tool-scalac}\<close>
   106 subsection \<open>Scala compiler \label{sec:tool-scalac}\<close>
    60 
   107 
    61 text \<open>
   108 text \<open>
    62   The @{tool_def scalac} tool is a direct wrapper for the Scala compiler; see
   109   The @{tool_def scalac} tool is a direct wrapper for the Scala compiler; see
    63   also @{tool scala} above. The command line arguments are that of the
   110   also @{tool scala} above. The command line arguments are that of the
    64   underlying Scala version.
   111   bundled Scala distribution.
    65 
   112 
    66   This allows to compile further Scala modules, depending on existing
   113   This allows to compile further Scala modules, depending on existing
    67   Isabelle/Scala functionality. The resulting class or jar files can be added
   114   Isabelle/Scala functionality. The resulting \<^verbatim>\<open>class\<close> or \<^verbatim>\<open>jar\<close> files can be
    68   to the Java classpath using the \<^verbatim>\<open>classpath\<close> Bash function that is provided
   115   added to the Java classpath using the shell function
    69   by the Isabelle process environment. Thus add-on components can register
   116   \<^bash_function>\<open>classpath\<close>. Thus add-on components can register themselves
    70   themselves in a modular manner, see also \secref{sec:components}.
   117   in a modular manner, see also \secref{sec:components}.
    71 
   118 
    72   Note that jEdit @{cite "isabelle-jedit"} has its own mechanisms for adding
   119   Note that Isabelle/jEdit @{cite "isabelle-jedit"} has its own mechanisms for
    73   plugin components, which needs special attention since it overrides the
   120   adding plugin components. This needs special attention, since it overrides
    74   standard Java class loader.
   121   the standard Java class loader.
    75 \<close>
   122 \<close>
    76 
   123 
    77 
   124 
    78 section \<open>Scala script wrapper\<close>
   125 subsection \<open>Scala script wrapper\<close>
    79 
   126 
    80 text \<open>
   127 text \<open>
    81   The executable @{executable "$ISABELLE_HOME/bin/isabelle_scala_script"}
   128   The executable @{executable "$ISABELLE_HOME/bin/isabelle_scala_script"}
    82   allows to run Isabelle/Scala source files stand-alone programs, by using a
   129   allows to run Isabelle/Scala source files stand-alone programs, by using a
    83   suitable ``hash-bang'' line and executable file permissions. For example:
   130   suitable ``hash-bang'' line and executable file permissions. For example:
    84   @{verbatim [display]
   131   @{verbatim [display, indent = 2] \<open>#!/usr/bin/env isabelle_scala_script\<close>}
    85 \<open>#!/usr/bin/env isabelle_scala_script
   132   @{scala [display, indent = 2]
    86 
   133 \<open>val options = isabelle.Options.init()
    87 val options = isabelle.Options.init()
       
    88 Console.println("browser_info = " + options.bool("browser_info"))
   134 Console.println("browser_info = " + options.bool("browser_info"))
    89 Console.println("document = " + options.string("document"))\<close>}
   135 Console.println("document = " + options.string("document"))\<close>}
    90 
   136 
    91   This assumes that the executable may be found via the @{setting PATH} from
   137   This assumes that the executable may be found via the @{setting PATH} from
    92   the process environment: this is the case when Isabelle settings are active,
   138   the process environment: this is the case when Isabelle settings are active,
    95   \<^file>\<open>$ISABELLE_HOME/bin/isabelle_scala_script\<close> may be specified in expanded
   141   \<^file>\<open>$ISABELLE_HOME/bin/isabelle_scala_script\<close> may be specified in expanded
    96   form.
   142   form.
    97 \<close>
   143 \<close>
    98 
   144 
    99 
   145 
   100 section \<open>Project setup for common Scala IDEs\<close>
   146 subsection \<open>Project setup for common Scala IDEs\<close>
   101 
   147 
   102 text \<open>
   148 text \<open>
   103   The @{tool_def scala_project} tool creates a project configuration for
   149   The @{tool_def scala_project} tool creates a project configuration for
   104   Isabelle/Scala/jEdit:
   150   Isabelle/Scala/jEdit:
   105   @{verbatim [display]
   151   @{verbatim [display]
   114   The generated configuration is for Gradle\<^footnote>\<open>\<^url>\<open>https://gradle.org\<close>\<close>, but the
   160   The generated configuration is for Gradle\<^footnote>\<open>\<^url>\<open>https://gradle.org\<close>\<close>, but the
   115   main purpose is to import it into common Scala IDEs, such as IntelliJ
   161   main purpose is to import it into common Scala IDEs, such as IntelliJ
   116   IDEA\<^footnote>\<open>\<^url>\<open>https://www.jetbrains.com/idea\<close>\<close>. This allows to explore the
   162   IDEA\<^footnote>\<open>\<^url>\<open>https://www.jetbrains.com/idea\<close>\<close>. This allows to explore the
   117   sources with static analysis and other hints in real-time.
   163   sources with static analysis and other hints in real-time.
   118 
   164 
   119   The specified project directory must not exist yet. The generated files
   165   The specified project directory needs to be fresh. The generated files refer
   120   refer to physical file-system locations, using the path notation of the
   166   to physical file-system locations, using the path notation of the underlying
   121   underlying OS platform. Thus the project needs to be recreated whenever the
   167   OS platform. Thus the project needs to be recreated whenever the Isabelle
   122   Isabelle installation is changed or moved.
   168   installation is changed or moved.
   123 
   169 
   124   \<^medskip> By default, Scala sources are \<^emph>\<open>copied\<close> from the Isabelle distribution and
   170   \<^medskip>
       
   171   By default, Scala sources are \<^emph>\<open>copied\<close> from the Isabelle distribution and
   125   editing them within the IDE has no permanent effect.
   172   editing them within the IDE has no permanent effect.
   126 
   173 
   127   Option \<^verbatim>\<open>-L\<close> produces \<^emph>\<open>symlinks\<close> to the original files: this allows to
   174   Option \<^verbatim>\<open>-L\<close> produces \<^emph>\<open>symlinks\<close> to the original files: this allows to
   128   develop Isabelle/Scala/jEdit within an external Scala IDE. Note that
   175   develop Isabelle/Scala/jEdit within an external Scala IDE. Note that
   129   building the result always requires \<^verbatim>\<open>isabelle jedit -b\<close> on the
   176   building the result always requires \<^verbatim>\<open>isabelle jedit -b\<close> on the
   130   command-line.
   177   command-line.
   131 \<close>
   178 \<close>
   132 
   179 
       
   180 
       
   181 section \<open>Registered Isabelle/Scala functions \label{sec:scala-functions}\<close>
       
   182 
       
   183 subsection \<open>Defining functions in Isabelle/Scala\<close>
       
   184 
       
   185 text \<open>
       
   186   A Scala functions of type \<^scala_type>\<open>String => String\<close> may be wrapped as
       
   187   \<^scala_type>\<open>isabelle.Scala.Fun\<close> and collected via an instance of the
       
   188   class \<^scala_type>\<open>isabelle.Isabelle_Scala_Functions\<close>. A system component
       
   189   can then register that class via \<^bash_function>\<open>isabelle_scala_service\<close>
       
   190   in \<^path>\<open>etc/settings\<close> (\secref{sec:components}). An example is the
       
   191   predefined collection of \<^scala_type>\<open>isabelle.Functions\<close> in
       
   192   Isabelle/\<^verbatim>\<open>Pure.jar\<close> with the following line in
       
   193   \<^file>\<open>$ISABELLE_HOME/etc/settings\<close>:
       
   194   @{verbatim [display, indent = 2] \<open>isabelle_scala_service 'isabelle.Functions'\<close>}
       
   195 
       
   196   The overall list of registered functions is accessible in Isabelle/Scala as
       
   197   \<^scala_object>\<open>isabelle.Scala.functions\<close>.
       
   198 \<close>
       
   199 
       
   200 
       
   201 subsection \<open>Invoking functions in Isabelle/ML\<close>
       
   202 
       
   203 text \<open>
       
   204   Isabelle/PIDE provides a protocol to invoke registered Scala functions in
       
   205   ML: this requires a proper PIDE session context, e.g.\ within the Prover IDE
       
   206   or in batch builds via option @{system_option pide_session}.
       
   207 
       
   208   The subsequent ML antiquotations refer to Scala functions in a
       
   209   formally-checked manner.
       
   210 
       
   211   \begin{matharray}{rcl}
       
   212   @{ML_antiquotation_def "scala_function"} & : & \<open>ML_antiquotation\<close> \\
       
   213   @{ML_antiquotation_def "scala"} & : & \<open>ML_antiquotation\<close> \\
       
   214   \end{matharray}
       
   215 
       
   216   \<^rail>\<open>
       
   217     (@{ML_antiquotation scala_function} | @{ML_antiquotation scala})
       
   218       @{syntax embedded}
       
   219   \<close>
       
   220 
       
   221   \<^descr> \<open>@{scala_function name}\<close> inlines the checked function name as ML string
       
   222     literal.
       
   223 
       
   224   \<^descr> \<open>@{scala name}\<close> invokes the checked function via the PIDE protocol. In
       
   225   Isabelle/ML this appears as a function of type
       
   226   \<^ML_type>\<open>string -> string\<close>, which is subject to interrupts within the ML
       
   227   runtime environment as usual. A \<^scala>\<open>null\<close> result in Scala raises an
       
   228   exception \<^ML>\<open>Scala.Null\<close> in ML.
       
   229 
       
   230   The standard approach of representing datatypes via strings works via XML in
       
   231   YXML transfer syntax. See Isabelle/ML operations and modules @{ML
       
   232   YXML.string_of_body}, @{ML YXML.parse_body}, @{ML_structure XML.Encode},
       
   233   @{ML_structure XML.Decode}; similarly for Isabelle/Scala. Isabelle symbols
       
   234   may have to be recoded via Scala operations
       
   235   \<^scala_method>\<open>isabelle.Symbol.decode\<close> and
       
   236   \<^scala_method>\<open>isabelle.Symbol.encode\<close>.
       
   237 \<close>
       
   238 
       
   239 
       
   240 subsubsection \<open>Examples\<close>
       
   241 
       
   242 text \<open>
       
   243   Invoke a predefined Scala function that is the identity on type
       
   244   \<^ML_type>\<open>string\<close>:
       
   245 \<close>
       
   246 
       
   247 ML \<open>
       
   248   val s = "test";
       
   249   val s' = \<^scala>\<open>echo\<close> s;
       
   250   \<^assert> (s = s')
       
   251 \<close>
       
   252 
       
   253 text \<open>
       
   254   Let the Scala compiler process some toplevel declarations, producing a list
       
   255   of errors:
       
   256 \<close>
       
   257 
       
   258 ML \<open>
       
   259   val source = "class A(a: Int, b: Boolean)"
       
   260   val errors =
       
   261     \<^scala>\<open>scala_toplevel\<close> source
       
   262     |> YXML.parse_body
       
   263     |> let open XML.Decode in list string end;
       
   264 
       
   265   \<^assert> (null errors)\<close>
       
   266 
       
   267 text \<open>
       
   268   The above is merely for demonstration. See \<^ML>\<open>Scala_Compiler.toplevel\<close>
       
   269   for a more convenient version with builtin decoding and treatment of errors.
       
   270 \<close>
       
   271 
       
   272 
       
   273 section \<open>Documenting Isabelle/Scala entities\<close>
       
   274 
       
   275 text \<open>
       
   276   The subsequent document antiquotations help to document Isabelle/Scala
       
   277   entities, with formal checking of names against the Isabelle classpath.
       
   278 
       
   279   \begin{matharray}{rcl}
       
   280   @{antiquotation_def "scala"} & : & \<open>antiquotation\<close> \\
       
   281   @{antiquotation_def "scala_object"} & : & \<open>antiquotation\<close> \\
       
   282   @{antiquotation_def "scala_type"} & : & \<open>antiquotation\<close> \\
       
   283   @{antiquotation_def "scala_method"} & : & \<open>antiquotation\<close> \\
       
   284   \end{matharray}
       
   285 
       
   286   \<^rail>\<open>
       
   287     (@@{antiquotation scala} | @@{antiquotation scala_object})
       
   288       @{syntax embedded}
       
   289     ;
       
   290     @@{antiquotation scala_type} @{syntax embedded} types
       
   291     ;
       
   292     @@{antiquotation scala_method} class @{syntax embedded} types args
       
   293     ;
       
   294     class: ('(' @'in' @{syntax name} types ')')?
       
   295     ;
       
   296     types: ('[' (@{syntax name} ',' +) ']')?
       
   297     ;
       
   298     args: ('(' (nat | (('_' | @{syntax name}) + ',')) ')')?
       
   299   \<close>
       
   300 
       
   301   \<^descr> \<open>@{scala s}\<close> is similar to \<open>@{verbatim s}\<close>, but the given source text is
       
   302   checked by the Scala compiler as toplevel declaration (without evaluation).
       
   303   This allows to write Isabelle/Scala examples that are statically checked.
       
   304 
       
   305   \<^descr> \<open>@{scala_object x}\<close> checks the given Scala object name (simple value or
       
   306   ground module) and prints the result verbatim.
       
   307 
       
   308   \<^descr> \<open>@{scala_type T[A]}\<close> checks the given Scala type name (with optional type
       
   309   parameters) and prints the result verbatim.
       
   310 
       
   311   \<^descr> \<open>@{scala_method (in c[A]) m[B](n)}\<close> checks the given Scala method \<open>m\<close> in
       
   312   the context of class \<open>c\<close>. The method argument slots are either specified by
       
   313   a number \<open>n\<close> or by a list of (optional) argument types; this may refer to
       
   314   type variables specified for the class or method: \<open>A\<close> or \<open>B\<close> above.
       
   315 
       
   316   Everything except for the method name \<open>m\<close> is optional. The absence of the
       
   317   class context means that this is a static method. The absence of arguments
       
   318   with types means that the method can be determined uniquely as \<^verbatim>\<open>(\<close>\<open>m\<close>\<^verbatim>\<open> _)\<close>
       
   319   in Scala (no overloading).
       
   320 \<close>
       
   321 
       
   322 
       
   323 subsubsection \<open>Examples\<close>
       
   324 
       
   325 text \<open>
       
   326   Miscellaneous Isabelle/Scala entities:
       
   327 
       
   328     \<^item> object: \<^scala_object>\<open>isabelle.Isabelle_Process\<close>
       
   329     \<^item> type without parameter: @{scala_type isabelle.Console_Progress}
       
   330     \<^item> type with parameter: @{scala_type List[A]}
       
   331     \<^item> static method: \<^scala_method>\<open>isabelle.Isabelle_System.bash\<close>
       
   332     \<^item> class and method with type parameters:
       
   333       @{scala_method (in List[A]) map[B]("A => B")}
       
   334     \<^item> overloaded method with argument type: @{scala_method (in Int) "+" (Int)}
       
   335 \<close>
       
   336 
   133 end
   337 end