This chapter is an introduction to using the script management facilities of Proof General. We begin with a quick walkthrough example, then describe the concepts and functions in more detail.
Here's a short example in LEGO to see how script management is used. The file you are asked to type below is included in the distribution as `lego/example.l'. If you're not using LEGO, substitute some lines from a simple proof for your proof assistant, or consult the example file supplied with Proof General for your prover, called something like `foo/example.foo' for a proof assistant Foo.
This walkthrough is keyboard based, but you could easily use the toolbar and menu functions instead. The best way to learn Emacs key bindings is by using the menus. You'll find the keys named below listed on the menus.
The notation C-x C-f means control key with `x' followed by
control key with `f'. This is a standard notation for Emacs key
bindings, used throughout this manual. This function also
appears on the File
menu of Emacs. The remaining commands
used will be on the Proof-General
menu.
If you're not using LEGO, you must choose a different file extension, appropriately for your proof assistant. If you don't know what to use, see the previous chapter for the list of supported assistants and file extensions.
Module example Import lib_logic;This first command defines a file header and tells LEGO to use logic; these steps are usually not necessary in other proof assistants.
Electric terminator sends commands to the proof assistant as you type them. The exact key binding is based on the terminator used for your proof assistant, but you can always check the menu if you're not sure.
Electric terminator mode is popular, but not enabled by default because
of the principle of least surprise. You can customize Proof General to
enable it everytime if you want, See section 7. Customizing Proof General. In
XEmacs, this is particularly easy: just use the menu item Options
-> Save Options
to save some common options while using Proof General.
The Module
command should now be lit in pink (or inverse video if
you don't have a colour display). As LEGO imports each module, a line
will appear in the minibuffer showing the creation of context
marks. Eventually the command should turn blue, indicating that LEGO has
successfully processed it.
Goal bland_commutes: {A,B:Prop} (and A B) -> (and B A);
The goal should be displayed in the goals buffer.
Intros;
This will update the goals buffer.
But whoops! That was the wrong command.
Note: BS means the backspace key. This key press sends an undo
command to LEGO, and deletes the Intros;
command from the proof
script. If you just want to undo without deleting, you can type
C-c C-u instead, or use the toolbar navigation button.
intros; andI;We've used the conjunction-introduction rule. To finish off, use these commands:
Refine H; intros; Immed; Refine H; intros; Immed;
Now you should see LEGO display the QED message.
Save bland_commutes;
This last command closes the proof and saves the proved theorem.
Moving the mouse pointer over the locked region now reveals that the entire proof has been aggregated into a single segment. This reflects the fact that LEGO has thrown away the history of the proof, so if we want to undo now, the whole proof must be retracted.
You see that the locked segment for the whole proof is now unlocked (and uncoloured): it is transferred back into the editing region.
The command C-c C-RET moves the end of the locked region to the cursor position, sending undoing commands or proof commands as necessary.
Goal and_commutes: {A,B:Prop} (and A B) -> (and B A);Move the cursor to the end of the buffer, and type C-c C-RET again.
Proof General queues the commands for processing and executes them one by one. You should see the proof turn pink, then quickly command by command it is turned blue. The progress of pink to blue can be much slower with long and complicated proofs!
A proof script is a sequence of commands which constructs definitions, declarations, theories, and proofs in a proof assistant. Proof General is designed to work with text-based interactive proof assistants, where the mode of working is usually a dialogue between the human and the proof assistant.
Primitive interfaces for proof assistants simply present a shell (command interpreter) view of this dialogue: the human repeatedly types commands to the shell until the proof is completed. The system responds at each step, perhaps with a new list of subgoals to be solved, or perhaps with a failure report. Proof General manages the dialogue to show the human only the information which is relevant at each step.
Often we want to keep a record of the proof commands used to prove a theorem, to build up a library of proved results. An easy way to store a proof is to keep a text file which contains a proof script; proof assistants usually provide facilities to read a proof script from a file instead of the terminal. Using the file, we can replay the proof script to prove the theorem again.
Using only a primitive shell interface, it can be tedious to construct proof scripts with cut-and-paste. Proof General helps out by issuing commands directly from a proof script file, while it is being written and edited. Proof General can also be used conveniently to replay a proof step-by-step, to see the progress at each stage.
Scripting is the process of building up a proof script file or replaying a proof. When scripting, Proof General sends proof commands to the proof assistant one at a time, and prevents you from editing commands which have been successfully completed by the proof assistant, to keep synchronization. Regions of the proof script are analysed based on their syntax and the behaviour of the proof assistant after each proof command.
A script buffer is a buffer displaying a proof script. Its Emacs mode is particular to the proof assistant you are using (but it inherits from proof-mode).
A script buffer is divided into three regions: locked, queue and editing. The proof commands in the script buffer can include a number of Goal-save sequences.
The three regions that a script buffer is divided into are:
These three regions appear in the buffer in the order above; that is, the locked region is always at the start of the buffer, and the editing region always at the end. The queue region only exists if there is input waiting to be processed by the proof process.
Proof General has two fundamental operations which transfer commands between these regions: assertion (or processing) and retraction (or undoing).
Assertion causes commands from the editing region to be transferred to the queue region and sent one by one to the proof process. If the command is accepted, it is transferred to the locked region, but if an error occurs it is signalled to the user, and the offending command is transferred back to the editing region together with any remaining commands in the queue.
Assertion corresponds to processing proof commands, and makes the locked region grow.
Retraction causes commands to be transferred from the locked region to the editing region (again via the queue region) and the appropriate 'undo' commands to be sent to the proof process.
Retraction corresponds to undoing commands, and makes the locked region shrink. For details of the commands available for doing assertion and retraction, See section 2.6 Script processing commands.
A proof script contains a sequence of commands used to prove one or more theorems.
As commands in a proof script are transferred to the locked region, they are aggregated into segments which constitute the smallest units which can be undone. Typically a segment consists of a declaration or definition, or all the text from a goal command to the corresponding save command, or the individual commands in the proof of an unfinished goal. As the mouse moves over the the region, the segment containing the pointer will be highlighted.
Proof General therefore assumes that the proof script has a series of proofs which look something like this:
goal mythm is G ... save theorem mythm
interspersed with comments, definitions, and the like. Of course, the exact syntax and terminology will depend on the proof assistant you use.
The name mythm can appear in a menu for the proof script to help quickly find a proof (see section 5.3 Support for function menus).
You can edit as many script buffers as you want simultaneously, but only one buffer at a time can be used to process a proof script incrementally: this is the active scripting buffer.
The active scripting buffer has a special indicator: the word
Scripting
appears in its mode line.
When you use a scripting command, it will automatically turn a buffer into the active scripting mode. You can also do this by hand, via the menu command 'Toggle Scripting' or the key C-c C-s.
proof-toggle-active-scripting
When active scripting mode is turned on, several things may happen to
get ready for scripting (exactly what happens depends on which proof
assistant you are using and some user settings). First, the proof
assistant is started if it is not already running. Second, a command is
sent to the proof assistant to change directory to the directory of the
current buffer. If the current buffer corresponds to a file, this is
the directory the file lives in. This is in case any scripting commands
refer to files in the same directory as the script. The third thing
that may happen is that you are prompted to save some unsaved buffers.
This is in case any scripting commands may read in files which you are
editing. Finally, some proof assistants may automatically read in
files which the current file depends on implicitly. In Isabelle, for
example, there is an implicit dependency between a .ML
script
file and a .thy
theory file which defines its theory.
If you have a partly processed scripting buffer and use C-c C-s,
or you attempt to use script processing in a new buffer, Proof General
will ask you if you want to retract what has been proved so far,
Scripting incomplete in buffer myproof.l, retract?
or if you want to process the remainder of the active buffer,
Completely process buffer myproof.l instead?
before you can start scripting in a new buffer. If you refuse to do
either, Proof General will give an error message:
Cannot have more than one active scripting buffer!
.
To turn off active scripting, the buffer must be completely processed (all blue), or completely unprocessed. There are two reasons for this. First, it would certainly be confusing if it were possible to split parts of a proof arbitrarily between different buffers; the dependency between the commands would be lost and it would be tricky to replay the proof.(3) Second, we want to interface with file management in the proof assistant. Proof General assumes that a proof assistant may have a notion of which files have been processed, but that it will only record files that have been completely processed. For more explanation of the handling of multiple files, See section 4.2 Switching between proof scripts.
Proof General manages several kinds of buffers in Emacs. Here is a summary of the different kinds of buffers you will use when developing proofs.
Normally Proof General will automatically reveal and hide the goals and response buffers as necessary during scripting. However there are ways to customize the way the buffers are displayed (see section 7.3 Display customization).
The menu Proof General -> Buffers
provides a convenient way to
display or switch to a Proof General buffer: the active scripting
buffer; the goal or response buffer; the tracing buffer; or the shell
buffer. Another command on this menu, Clear Responses
, clears
the response and tracing buffer.
Proof General provides a few functions for editing proof scripts. The generic functions mainly consist of commands to navigate within the script. Specific proof assistant code may add more to these basics.
Indentation is controlled by the user option proof-script-indent
(see section 7.4 User options). When indentation is enabled, Proof General
will indent lines of proof script with the usual Emacs functions,
particularly TAB, indent-for-tab-command
.
Unfortunately, indentation in Proof General 3.4 is somewhat
slow. Therefore with large proof scripts, we recommend
proof-script-indent
is turned off.
Here are the commands for moving around in a proof script, with their default key-bindings:
proof-goto-command-start
proof-goto-command-end
proof-goto-end-of-locked
The variable proof-terminal-char
is a prover-specific character
to terminate proof commands. LEGO and Isabelle use a semicolon,
`;'. Coq employs a full-stop `.'.
During the course of a large proof, it may be useful to copy previous commands. As you move the mouse over previous portions of the script, you'll notice that each proof command is highlighted individually. (Once a goal...save sequence is "closed", the whole sequence is highlighted). There is a useful mouse binding for copying the highlighted command under the mouse:
proof-mouse-track-insert
mouse-track-insert
.
proof-mouse-track-insert
, if you don't already know what it
does.
Here are the commands for asserting and retracting portions of the proof
script, together with their default key-bindings. Sometimes assertion
and retraction commands can only be issued when the queue is empty. You
will get an error message Proof Process Busy!
if you try to
assert or retract when the queue is being processed.(4)
proof-assert-next-command-interactive
proof-undo-last-successful-command
proof-undo-and-delete-successful-command
proof-goto-point
proof-process-buffer
proof-retract-buffer
proof-electric-terminator-toggle
The last command, proof-electric-terminator-toggle
, is triggered
using the character which terminates proof commands for your proof
assistant's script language. For LEGO and Isabelle, use C-c ;,
for Coq, use C-c .. This not really a script processing
command. Instead, if enabled, it causes subsequent key presses of
; or . to automatically activate
proof-assert-next-command-interactive
for convenience.
Rather than use a file command inside the proof assistant to read a
proof script, a good reason to use C-c C-b
(proof-process-buffer
) is that with a faulty proof script (e.g.,
a script you are adapting to prove a different theorem), Proof General
will stop exactly where the proof script fails, showing you the error
message and the last processed command. So you can easily continue
development from exactly the right place in the script.
Here is the full set of script processing commands.
Notice that the deleted command is put into the Emacs kill ring, so you can use the usual `yank' and similar commands to retrieve the deleted text.
proof-assert-until-point
or proof-retract-until-point
as
appropriate.
proof-electric-terminator-enable
'. With arg, turn on iff ARG>0.customize-set-variable
to set the variable.
It was constructed with `proof-deftoggle-fn
'.
As experienced Emacs users will know, a prefix argument is a numeric
argument supplied by some key sequence typed before a command key
sequence. You can supply a specific number by typing Meta with
the digits, or a "universal" prefix of C-u. See
See Info file `(xemacs)', node `Arguments' for more details. Several Proof General
commands, like proof-retract-until-point-interactive
, may accept
a prefix argument to adjust their behaviour somehow.
There are several commands for interacting with the proof assistant and Proof General, which do not involve the proof script. Here are the key-bindings and functions.
proof-display-some-buffers
proof-prf
proof-ctxt
proof-help
proof-find-theorems
pg-response-clear-displays
proof-interrupt-process
proof-minibuffer-cmd
proof-showproof-command
.
proof-context-command
.
proof-info-command
.
proof-find-theorems-command
.
The user is prompted for an argument.
proof-tidy-response
'
is set to nil, so responses are not cleared automatically.
This command is risky because when an interrupt is trapped in the proof assistant, we don't know whether the last command succeeded or not. The assumption is that it didn't, which should be true most of the time, and all of the time if the proof assistant has a careful handling of interrupt signals.
If a prefix arg is given and there is a selected region, that is pasted into the command. This is handy for copying terms, etc from the script.
If `proof-strict-state-preserving
' is set, and `proof-state-preserving-p
'
is configured, then the latter is used as a check that the command
will be safe to execute, in other words, that it won't ruin
synchronization. If when applied to the command it returns false,
then an error message is given.
warning: this command risks spoiling synchronization if the test
`proof-state-preserving-p
' is not configured, if it is
only an approximate test, or if `proof-strict-state-preserving
'
is off (nil).
As if the last two commands weren't risky enough, there's also a command which explicitly adjusts the end of the locked region, to be used in extreme circumstances only. See section 4.7 Escaping script management.
There are a few commands for stopping, starting, and restarting the proof assistant process which have menu entries but no key-bindings. As with any Emacs command, you can invoke these with M-x.
Also generates goal and response buffers. Does nothing if proof assistant is already running.
proof-shell-restart-cmd
.
If the proof shell is busy, an interrupt is sent with
proof-interrupt-process
and we wait until the process is ready.
The restart command should re-synchronize Proof General with the proof assistant, without actually exiting and restarting the proof assistant process.
It is up to the proof assistant how much context is cleared: for example, theories already loaded may be "cached" in some way, so that loading them the next time round only performs a re-linking operation, not full re-processing. (One way of caching is via object files, used by Lego and Coq).
This simply kills the proof-shell-buffer
relying on the hook function
proof-shell-kill-function
to do the hard work.
The toolbar provides a selection of functions for asserting and retracting portions of the script, issuing non-scripting commands, and inserting "goal" and "save" type commands. The latter functions are not available on keys, but are available from the from the menu, or via M-x, as well as the toolbar.
proof-goal-command
.
The user is prompted for an argument.
proof-save-command
.
The user is prompted for an argument.
If your prover generates output which is recognized as tracing output in
Proof General, you may need to know about a special provision for
interrupting the prover process.
If the trace output is voluminous, perhaps looping, it may be difficult
to interrupt with the ordinary C-c C-c
(proof-interrupt-process
) or the corresponding button/menu. In
this case, you should try Emacs's quit key, C-g. This will
cause a quit in any current editing commands, as usual, but during
tracing output it will also send an interrupt signal to the prover.
Hopefully this will stop the tracing output, and Emacs should catch up
after a short delay.
Here's an explanation of the reason for this special provision. When
large volumes of output from the prover arrive quickly in Emacs, as
typically is the case during tracing (especially tracing looping
tactics!), Emacs may hog the CPU and spend all its time updating the
display with the trace output. This is especially the case when
features like output fontification and X-Symbol display are active. If
this happens, ordinary user input in Emacs is not processed, and it
becomes difficult to do normal editing. The root of the problem is that
Emacs runs in a single thread, and pending process output is dealt with
before pending user input. Whether or not you see this problem depends
partly on the processing power of your machine (or CPU available to
Emacs when the prover is running). One way to test is to start an Emacs
shell with M-x shell and type a command such as yes
which
produces output indefinitely. Now see if you can interrupt the process!
(Warning -- on slower machines especially, this can cause lockups, so
use a fresh Emacs.)
Go to the first, previous, next, last section, table of contents.