Code Generation Utilities
This section will outline the core functionality of this toolbox generator, namely the utilities used for generating the calculus tools.
build.py
This is the main build script, which ties in all the utilities into a single script for easy calculus generation. The script takes the following set of parameters:
Flag | Arguments | Description | |
---|---|---|---|
--path |
-p |
Specify an output path for the calculus. | |
--template |
-t |
Specify a templates folder to be used. | |
--verbose |
-v |
Verbose mode. | |
--build |
-b |
all , scala , isabelle |
Compile the specified files only. Defaults to all |
--stage |
-s |
core_calc_gen , rule_calc_gen , calc_compile , add_gui |
Call a specific stage of the build. |
Build Stages
The calculus toolbox is compiled from the calculus description file in several stages, which include compiling the core calculus Isabelle theory files, generating the ASCII parser and print classes in Scala, parsing and translating the encoded rules into Isabelle, generating the rule theory files and finally adding the UI Scala classes. Bellow is a short overview of these stages (you can manually call any stage of the build via the --stage
flag) .
-
core_calc_gen
Isabelle
The core calculus theory file is generated from
template/Calc_Core.thy
, compiled in Isabelle and exported into Scala (using Isabelle’s code generation facilities).Scala
The parsers for the terms of the calculus are generated using
template/Parser.scala
The print class for terms of the calculus is generated usingtemplate/Print.scala
-
calc_compile
Scala
This stage simply compiles all the Scala classes in
<calculus_output_path>/src/scala
-
rule_calc_gen
Isabelle
The rules of the calculus encoded in the JSON file are parsed and encoded in the main Isabelle theory file (
template/Calc_Rules.thy
).Scala
The parser class is rebuilt, now including parsers for proof trees and rule datatype definitions
The print class is rebuilt, adding printing for proof trees and rule datatype definitions -
add_gui
Scala
Generates the Scala UI from
template/gui/
adding a separate compile script and a make file for the built calculus.
Any libraries inside thelibs
folder will be copied to the calculus folder.
gui.py
this utility requires the npyscreen python module (install using pip) |
This utility provides some debugging tools when extending the calculus functionality. To use, simply run ./gui.py
. The debugging tools currently include the following functionality:
-
Test build on single file…
Allows the user to specify a template file and a JSON calculus description file to generate a specific Isabelle theory or Scala class. To get a better understanding of how code generation works have a look at how code generation works. If changes are made to the IsabelleBuilder or ScalaBuilder python classes,
Reload Builder
can be used to reload these into the utility. -
Test unbuild on single file…
Takes an already generated Isabelle theory file or Scala class and removes any code, generated by the calculus toolbox tools.
The utility replaces any block of code enclosed in(*<identifier>-BEGIN*) .. (*<identifier>-END*)
by(*<identifier>*)
in.thy
files and/*<identifier>-BEGIN*/ .. /*<identifier>-END*/
by/*<identifier>*/
in.scala
files This functionality has been mostly superseded by thewatcher.py
utility.
watcher.py
this utility requires the watchdog python module (install using pip) |
The watcher utility is useful when rewriting code within the generated calculus and wanting to propagate the changes back to the template files automatically. As mentioned, the gui.py
utility provides a way to strip down generated classes back into templates. However, the watcher utility does this automatically whenever a file is changed. The following table lists the arguments that can be passed to the utility:
Flag | Description | |
---|---|---|
--source |
-s |
Specify the folder to be watched |
--dest |
-d |
Specify the output folder |
--ext |
-e |
Specify file extensions to be monitored. The default are ‘*.scala ’ and *.thy |
--rules |
-r |
Specify path rewrite rules (currently just a dictionary of hard coded strings, there is no regular expression matching). The command uses bash-like redirect syntax "<old1> > <new1>, <old2> > <new2>, ..." |
--ignore |
-i |
Specify paths (or substrings of a path) from the source folder to be ignored (currently no regular expressions matching) |
To run, use the following command:
./watcher.py -s <path_to_built_calculus>/src -d <path_to_template_folder> -i "scala/<calculus_name>.scala, .thy#, .thy~" -r "scala/ > , isabelle/ > , <calculus_name>_Core.thy > Calc_Core.thy, <calculus_name>.thy > Calc_Rules.thy"
This configuration will strip all the generated code from Isabelle and Scala files in <path_to_built_calculus>/src
and save them back into the specified template folder. The -i
flag will ignore any temporary Isabelle theory files .thy#
and .thy~
as well as the scala/<calculus_name>.scala
file which is automatically generated from the Isabelle theory files and therefore doe not have a template file (this file should not be modified manually at all).
The -r
flag introduces some path rewrite rules, specific to the structure of the source and/or destination folders (these should work for the default setup). Note that <calculus_name>
should be replaced with the name of the calculus one is working in (as specified in the JSON file under calc_name
)
IsabelleBuilder / ScalaBuilder
IsabelleBuilder
and ScalaBuilder
form the core of the code generation facilities for Isabelle theories and Scala classes respectively. The way code generation is set up is the following:
-
The template files include comments of the form
(*<function_name>*)
in Isabelle and/*<function_name>*/
and the corresponding identifier is used as a function name in Isabelle/Scala builder classes.
This is a snippet fromtemplate/Calc_Core.thy
where the calculus name is plugged in for(*calc_name_core*)
when it is generated by the toolbox:
The corresponding python function is defined in `IsabelleBuilder` and shown below:
<div markdown="1">
When run with the [default calculus description file](https://github.com/goodlyrottenapple/calculus-toolbox/blob/master/default.json), the code snippet above will be turned into:
<div markdown="1">
- - -
The code generation leaves delimiters `(*<identifier>-BEGIN*)` and `(*<identifier>-END*)` for Isabelle theories or `/*<identifier>-BEGIN*/` and `/*<identifier>-END*/` for Scala around generated code. While this may look cluttered, it allows for the conversion of the generated files back into templates, as described in the documentation of the [gui.py](#guipyhttpsgithubcomgoodlyrottenapplecalculus-toolboxblobmasterguipy) and [watcher.py](#watcherpyhttpsgithubcomgoodlyrottenapplecalculus-toolboxblobmasterwatcherpy) utilities. However, these comment delimiters can be removed entirely if need be (_this functionality is present in [`utils.py`](https://github.com/goodlyrottenapple/calculus-toolbox/blob/master/tools/utils.py) (function `clean`), but is currently not implemented as a stand-alone runnable script_).
- - -
-
Arguments can be passed to the defined python functions by appending them to the identifier in the comments with a question mark:
(*<identifier>?<arg1>?<arg2>?<arg3>?...*)
. The corresponding python function must take an extra list parameter, where the arguments are stored in the order they were written (i.e.[arg1, arg2, arg3, ...]
):
-
The data from the calculus JSON file is accessible through
self.calc
dictionary in both IsabelleBuilder and ScalaBuilder classes. For example, the calculus name can be accessed throughself.calc["calc_name"]
.Care should be taken not to override any data in self.calc
. Even though the code generator tools do not write any changes to the JSON file, data may be reused by different functions at different times and any modification of theself.calc
dictionary can lead to unexpected behavior. - To create an internal/hidden function which cannot be called directly through its identifier, prepend two underscores to the function name:
def __<fun>(self): ...
- To create a static function use the
@staticmethod
flag before function declaration