Extensibella is an interactive proof assistant based on Abella. Much of the language will look familiar to those familiar with Abella.
The syntax of formulas in Extensibella includes the following constructs:
forall A B C, ... |
universal quantification |
exists A B C, ... |
existential quantification |
F1 /\ F2 |
and |
F1 \/ F2 |
or |
F1 -> F2 |
implies |
true |
true |
false |
false |
t1 = t2 |
equality |
t1, t2, t3 |{ty}- t ~~> t' |
projection |
rel t1 t2 t3 |
relation |
<rel {ES}> t1 t2 t3 |
extension size of a derivation |
<rel {T}> t1 t2 t3 |
projection version of a relation |
t1 + t2 = t3
):
Integers: | + , - , * ,
/ , mod , < ,
> , <= ,
>= |
Booleans: | && , || |
Lists and Strings: | ++ |
- t1 = t2
) and
unary Boolean negation (!t1 = t2
).
The syntax of terms in Extensibella includes the following constructs:
<var> |
variable |
c t1 t2 t3 |
constructor application |
t1::t2 |
cons list |
nil |
empty list |
[] |
empty list |
[t1, t2, t3] |
list literal |
(t1, t2, t3) |
tuple literal |
"string" |
string literal |
<integer> |
integer literal |
true |
Boolean true |
false |
Boolean false |
Identifiers (variables, theorem names, relations, etc.) may begin
with a letter or one of -^=`'?
followed by any
letters, digits, symbols from the previous list,
or _*@+#!~/
. Note that this also means spaces in
operations can be important. For example, a + b = c
is an integer addition formula, but a+b=c
is a single
identifier.
Anywhere the short name of a construct can be used, the qualified
name can also be used. For example, if
module mo:du:le
contains a relation rel
,
both rel x y z
and mo:du:le:rel x y z
may be used interchangeably, as long as there is not another
relation named rel
available in the current module.
Single-line comments start with %
and may begin
anywhere in a line. Multi-line comments are demarcated
by /*
and */
.
Each Extensibella interaction begins with a module declaration:
Module mo:du:le.This tells Extensibella which language specification to use, namely the one for the module named
mo:du:le
. This
is the language module about which the session will reason.
Top-level commands are commands that may be used outside of a proof.
Theorem <name> : <formula>. |
Declares a (non-extensible) theorem, causing Extensibella to enter its proof mode for the user to prove it |
Define <pred> : <type>,
<pred> : <type>, ... by
<clause>; ... <clause>. |
Inductively defines a set of non-extensible fixed-point relations at the proof level |
Split <name> as
<name>, ... <name>. |
Splits a theorem with top-level conjunctions into separate theorems. For example, |
Kind <name> <kind>. |
Declares a new proof-level type |
Type <name> <type>. |
Declares a new proof-level constructor with the given type. The type must be a proof-level type, not a type in the language or a built-in type. |
Extensibella has top-level commands for declaring extensible proof objects:
Extensible_Theorem <name> :
forall <bindings>,
<hyp name> : <formula> ->
<hyp name> : <formula> ->
...
<conclusion> on <hyp name>. |
Declares an extensible theorem to be proven, using
induction and case analysis on the premise given in
the |
Multiple extensible theorems can be declared
together and proven using mutual induction by repeating the
theorem declaration part (everything
after |
Non-extensible theorems may be added, for purposes of mutual induction, after all extensible theorems in a group with the |
The induction hypothesis may be given a descriptive name by adding |
Multiple inductions may be declared by repeating the |
Projection_Constraint <name> :
forall <bindings>,
<hyp name> : <args> |{<ty>}-
<original> ~~> <projection> ->
<hyp name> : <formula> ->
<conclusion>. |
Declares a projection constraints to be proven using case analysis on the projection |
Ext_Size <rel> <args>. |
Declares the extension size version
of |
Multiple relations can have their extension size
versions declared together by repeating
the |
This also introduces three lemmas the user does not need to prove but can use. For a relation |
Proj_Rel <rel> <args>. |
Declares the projection version
of |
Multiple relations can have their projection
versions declared together by repeating
the |
This also introduces a lemma the user does not need to prove but can use. For a relation |
Ext_Ind forall <bindings>,
<rel> <rel args> with
<hyp name> : <formula>, ...,
<hyp name> : <formula>
as <IH name>, <IH name>. |
Declares a requirement for modules to show the
projection version of the relation follows from the
relation itself; this allows
extension to build arguments for new properties using the
extensible relation |
Multiple relations can be proven together by
repeating the bindings, relation, and extra premises
(everything after |
Uses the extension size version of |
The |
The |
Arbitrary theorems can be proven mutually by adding |
This also introduces a lemma based on what the user has proven. For a relation |
Prove
version, used for adding to its proof in
modules that build on the module introducing it. They
are Prove_Theorem
, Prove_Constraint
,
Add_Ext_Size
, Add_Proj_Rel
,
and Prove_Ext_Ind
, respectively. Each of these takes a
list of qualified names (not short names) for the
theorems or relations to which
it is adding, and presents the user with the new cases to prove in
the current module, if any exist.
Some of these allow new additions in their Prove
versions:
Prove <existing thm names> with <new thm
statements> also <new also thm statements>.
Adds new mutually-inductive theorems to the set to prove
Add_Ext_Size <existing rels> with <new
rels>.
Adds new relations, which must be introduced by the current module, to the set of relations defined together for the extension size
Add_Proj_Rel <existing rels> with <new
rels>.
Adds new relations, which must be introduced by the current module, to the set of relations defined together for the projection versions of all
Prove_Ext_Ind <existing rels>
and_thms <existing mutual theorem names>
with <new rels and premises>.
Adds new relations to the set for which we are proving the
projection version follows from the basic relations; can add
new theorems by adding and
and also
as with Ext_Ind
Tactics are the commands used within a proof to advance the proof state. We borrow our tactics from Abella.
induction on <num>. | |
For a goal of the form |
|
intros <names>. | |
For a goal of the form |
|
apply <thm> to <hyps> with <var> =
<tm>, .... | |
Applies a formula, referenced by name, to the given hypotheses, giving specific instantiations of the variables listed at the end, adding the conclusion to the context as a hypothesis. The hypotheses to which it is applied may also include underscores, in which case Extensibella searches for a formula to fill them. Any not found are added as subgoals for the user to prove. Variable instantiations are usually not needed and may be left off; they are helpful in conjunction with underscores to fill in terms that are otherwise not known. |
|
backchain <thm> with <var> = <tm>, .... | |
Unifies the conclusion of the formula with the current goal
and searches for solutions to the premises. If premises are
not found, they are added as subgoals for the user to prove.
As with applications, variable instantiations are optional,
but are helpful if some of the bound variables in the
formula do not appear in its conclusion. This is similar
to |
|
assert <formula>. | |
Extensibella searches for a proof of the formula; if one is not found, the formula is added as a subgoal for the user to prove. Once the formula is proven, it is added to the context as a hypothesis. |
|
exists <tm>. | |
For a goal of the form |
|
search <depth>. | |
Searches for a way to prove the current goal, using rules to the given depth. If no depth is given, this uses the default depth. |
|
split. | |
For a goal of the form |
|
left. | |
For a goal of the form |
|
right. | |
For a goal of the form |
case <hyp>. | |
Analyze the ways in which the formula in the hypothesis named |
|
If |
|
unfold. | |
For a goal of the form |
skip. | |
Skips the current subgoal, moving to the next one. This treats the subgoal as if it were truly solved. |
|
admit. | |
Skip all remaining subgoals, completing the current theorem. This treats the theorem as if it were truly solved. |
|
abort. | |
Aborts the current theorem without adding it to the set of known theorems. |
|
undo | |
Undoes the effect of the last tactic. |
|
clear <hyp>. | |
Removes the given hypothesis from the context. |
|
rename <name> to <name>. | |
Changes the name of one hypothesis or variable to another. |
Common commands do not affect the state of the prover and can be used in either the proof mode or the top mode.
Set <option> <value>. |
|
Set the value of various runtime options: |
|
Show <name>. | |
Display a previously-proven theorem. The name may either be a qualified name or a short name, with short names only working if there is only one known theorem with that name. |
|
Quit. | |
Exits Extensibella |
integer
string
bool
list
(kind type -> type
,
written list A
)
pair
(kind type -> type -> type
,
written pair A B
)
Definitions and non-extensible theorems may be defined as polymorphic. For definitions, any capitalized names in the definition will be treated as variables. For example,
Define rel : A -> list (pair A B) -> prop by ...will define a relation with two variables,
A
and B
. Non-extensible theorems must declare their
type variables. For example,
Theorem thm[A, B] : forall (L : pair A B) X Y, ...Some bound variables need to be annotated with types so Extensibella can determine the correct types.
Extensibella differentiates between language-level types and
proof-level types in defining new constructors with
the Type
top-level command, but does not
differentiate between them in typing.
As in Abella, the application of inductive hypotheses in
Extensibella is guarded by inductive restrictions. These
are *
for smaller and @
for equal.
The induction
tactic adds the @
restriction to the induction measure premise and creates the
inductive hypothesis with the *
restriction. For
example, induction on 1
with
============================ forall A B C, rel A B -> rel B C -> rel A Cas the proof state creates
IH : forall A B C, rel A B * -> rel B C -> rel A C ============================ forall A B C, rel A B @ -> rel B C -> rel A CThe inductive hypothesis having the
*
restriction
means it can only be used with an argument that also has
the *
restriction. Such a hypothesis can be obtained
by case analysis on a premise with the @
restriction,
meaning it is equal to the current derivation size we are
attempting to prove.
Extensibella can be run interactively to build proofs. The best way to do this is using Proof General, where one writes commands into a file in Emacs and runs them as they are written. Alternatively, proofs may be written directly into Extensibella by running it as
extensibellaNote this will not save the proofs written. Writing proofs directly into the Extensibella command line also requires saving the commands elsewhere. When running interactively, Extensibella waits for a command, processes it, and displays the proof state after the command has run.
To check an Extensibella file thms.xthm
that has
already been written, run
extensibella --check thms.xthmThis will check all the proofs are correct, and that all proof obligations have been fulfilled.
Because the Extensibella file for a module may be anywhere, a file
must be compiled before proofs can be written for modules building
on it. This takes the relevant information modules building on it
must know and places it in Extensibella's generated
directory. To compile a file thms.xthm
, run
extensibella --compile thms.xthmThe best practice is to combine this with the
--check
flag, as the proofs being compiled are not checked by default, to
ensure the properties being compiled are true.
Note --compile
by itself can be quite a bit faster
than combining it with --check
, however, which is why
the combination is not the default.
In addition to its use in writing modular proofs, Extensibella
also provides a facility for combining them into a single Abella
proof. The existence of modular proofs acceptable to Extensibella
is sufficient evidence a single Abella proof of the properties for
the language exists, but this allows skeptics, or the curious, to
check the proof for themselves. To compose a set of modular
proofs for the language of a module mo:du:le
into an
Abella proof out.thm
, run
extensibella --compose out.thm mo:du:le file_1.xthm file_2.xthm ... file_n.xthmwhere the listed files are the proof files for all modules included in the composition. A few notes:
mo:du:le
in our example command, must be
compiled for an Extensibella full language; this has slightly
different requirements than the modular compiled format, so
both will be needed.
Extensibella has a mode written for Proof General, found in the Extensibella GitHub repository. The mode has only been tested with the Abella fork of Proof General and is not guaranteed to work with other versions.
To install the Extensibella Proof General instance, copy the
Extensibella
Proof General files to a directory
named Extensibella
in the Proof General directory.
You also need to add the following line to
the generic/proof-site.el
file in the Proof General
directory, in the proof-assistant-table-default
:
(extensibella "Extensibella" "xthm")This makes Proof General and Emacs know to open Extensibella
.xthm
files using this mode
automatically.