Overview
This manual describes how to use AutoProof. AutoProof is an auto-active verifier for the Eiffel programming language that can prove functional correctness of Eiffel programs annotated with contracts. AutoProof is available as part of the Eiffel Verification Environment (EVE) or via an online version.
AutoProof in EVE
AutoProof is integrated in EVE, a research branch of EiffelStudio.
Installation
Follow the installation instructions of EVE.
Open Project
Open and compile an EiffelStudio project using the EVE base library. For this you can download the example project provided. Launch EVE using the run_eve script in the EVE delivery and add the example's ecf file using the add project button. When you have added the project you can open and compile it.
Open AutoProof tool panel
Click the menu entry View > Tools > AutoProof. This will show the AutoProof panel, which can be docked like the other tools in EVE.
Run AutoProof
The Eiffel compilation of the project has to be finished and successful in order to run AutoProof. It is not necessary to do the C compilation when working with AutoProof. When the project is compiled successfully there are three ways to launch AutoProof:
- You can run AutoProof using the Verify button. By default, AutoProof will verify the class or cluster that is shown in the editor pane. You can change this behaviour by clicking the down-arrow on the Verify button and select either to verify the parent cluster of the item currently shown in the editor, or to verify the whole system (excluding libraries).
- You can pick-and-drop a feature, class, or cluster onto the Verify button.
- You can right-click a feature or class and select Verify with AutoProof in the context menu.
Only one execution of AutoProof can run at a time, so when the verification has started the Verify button will become inactive.
Stop AutoProof
When AutoProof is running you can stop it using the red stop button next to the Verify button. This can be helpful if you want to cancel a long-running verification.
Filtering Results
There are two ways of filtering the results displayed by AutoProof:
- The three toggle-buttons can be used to show or hide all successful results, failed verifications, or semantic errors.
- The filter box can be used to enter text. Only results will be shown where this text is contained in either the class name, feature name, or text message. To clear the filter box you can click the red x button next to it.
Options
On the top-right of the AutoProof tool is the options button. Clicking it will display the available options and if the option is enabled or disabled. Clicking any of the options will toggle its value. For an explanation of the options see the AutoProof Options section.
AutoProof on the Command-line
The command-line version of AutoProof is available as part of EVE.
Run AutoProof
To run AutoProof via the command-line you have to run the EVE command-line compiler with a valid Eiffel project and add the -autoproof option:
ec.exe -config ecf-file -target ecf-target -autoproof
By default all user classes in the system are verified by AutoProof. To select which classes or routines are verified you can add the class names and routine names as additional command-line arguments. The routine name is composed of the class name together with the routine in the format CLASS.routine
.
Options
AutoProof has the same options on the command-line as for the graphical version. The available command-line options are listed in the AutoProof Options section.
AutoProof on the Web
The online version of AutoProof is integrated in ComCom, an online interface to run command-line tools.
Examples
Across the top of the AutoProof interface on Comcom are different examples that can be selected. The examples can be adapted in the browser. To reload the original version, click the reload button on the top-right.
Custom code
The last tab More AutoProof can be used to write your own code from scratch. In addition to writing your own code you can use command-line options on this tab. For a list of command-line options see the AutoProof Options section.
Run AutoProof
To run AutoProof click the Run button below the code area. The results will be shown in the box below the button. Note that changing the example will clear the results box. The verification time is limited to 2 minutes, you will get a result or a time-out message after that time.
Limitations
The ComCom version of AutoProof is limited to examples that consist only of one user-defined class. You can use the classes of the EVE version of EiffelBase in your code, in particular the ones defined in the AutoProof base library. It is not possible to add further libraries.
AutoProof Options
There are different options which influence the behaviour of the AutoProof translation and execution as a whole, as opposed to annotations which only affect individual classes or features (see the Annotations section for details). The following table lists these options. The command-line switches usually come in pairs: one switch turns the option on and the other turns it off.
Option name | Default | Command-line switch | Description |
---|---|---|---|
Two-step | Disabled | -twostep -notwostep |
Use two-step verification when enabled. |
Automatic inlining | Disabled | -autoinline -noautoinline |
Inline routines without postcondition automatically when enabled. |
Automatic unrolling | Disabled | -autounroll -noautounroll |
Unroll loops without loop invariants automatically when enabled. |
Postcondition predicates | Disabled | -postpredicate -nopostpredicate |
Generate postcondition predicates when enabled. |
Overflow | Disabled | -overflow -nooverflow |
Check for integer overflows when enabled. |
Generate triggers | Disabled | -trigger -notrigger |
Generates triggers for across expressions when enabled. |
Arithmetic triggers | Disabled | -arithtrigger -noarithtrigger |
Uses arithmetic functions for triggers when enabled. |
SC defaults | Enabled | -scdefaults -noscdefaults |
Use semantic collaboration defaults when enabled. |
Bulk verification | Bulk | -bulk -fork |
Bulk: all routines are verified at the same time and the results are displayed at the end. \newline Forked: routines are verified in parallel and results are displayed when available. |
Timeout | no timeout | -timeout X | Command-line only - Set the timeout of Boogie in seconds. |
HTML output | -html | Command-line only - Produce HTML output. |
Verification Process
Modularity
AutoProof does routine-level modular verification. Each routine is verified in isolation and only the interface of suppliers are considered during the verification of a routine. A program can only be considered fully verified if all routines are verified individually. By default AutoProof only verifies user-written classes when a program is verified, referenced libraries should be verified separately.
Creation routines
Creation routines in Eiffel double as regular routines and can be called on existing objects. Since routines behave differently depending on whether they are called as a creation routine (the class invariant is not checked on entry and all attributes are set to their default value for creation routines) these routines are verified twice with AutoProof. The feedback of AutoProof will list these routines twice specifying the context of the verification.
Assumptions
It can be useful to temporarily assume a fact that the verifier should use. This helps in debugging failed verifications, e.g. by directing the verifier in a specific branch. You can write an assumption using a check instruction with the special tag assume.
check assume: False end
Skipping classes or routines
You can skip the verification of single routines or classes by adding a note clause.
note status: skip
Language Support
The programming language that AutoProof supports is not exactly the standard Eiffel language. Some features of the Eiffel language are not supported, on the other hand custom annotations have been added to increase the expressiveness of the specification language. All custom annotations are valid syntax in standard Eiffel.
Standard Eiffel Support
AutoProof supports a large portion of the Eiffel language. When AutoProof encounters code constructs it does not support, it will try to degrade in a correct but incomplete way in order to verify the surrounding program. In any case, a special message will be displayed. Here is a comprehensive list of supported and unsupported instructions, expressions, and language concepts.
Instructions
Name | Support | Example | Comment |
---|---|---|---|
Assignment | full |
a := b |
|
Call | full |
a.f (x) |
The verification will check if a is not Void and if the precondition of f holds. Adding tag names to the preconditions of f improves the error reporting. |
Check | full |
check tag: c end |
The verification will check if the condition c holds. Adding a tag name improves the error reporting. |
Conditional | full |
if c then ... else ... end |
|
Creation | full |
create a.f (x) |
The verification will check if the precondition of f holds. Adding tag names to the preconditions of f improves the error reporting. |
Debug | full |
debug ... end |
|
Inspect | full |
inspect a when x then ... when y..z then ... else ... end |
|
From loop | full |
from ... invariant tag1: i1 tag2: i2 until c loop ... variant v end |
The verification will check if the invariants i1 and i2 hold after the (possibly empty) from block is executed and after every loop iteration. If a loop variant v or decreases annotation is provided then it is checked that the variant is non-negative and is reduced in every loop iteration. Adding tag names to the loop invariants improves the error reporting. |
Across loop | none |
across a as c loop ... end |
Across loops can be expressed with from loops. |
Retry | none |
retry |
The retry statement is only used in exception handling, which is not supported. |
Expressions
Name | Support | Example | Comment |
---|---|---|---|
Access | full |
a |
|
Across expression | partial |
across set as c all ... end across 1 |..| 5 as c some ... end |
Only specific container types are supported: MML types, INTEGER_INTERVAL, SIMPLE_ARRAY, and SIMPLE_LIST. |
Address operator | none |
$ |
The address operator is used to interoperate with external C code, which is not supported. |
Agent call | partial |
a.call([x]) |
|
Call | full |
a.f (x) |
The verification will check if a is not Void and if the precondition of f holds. Adding tag names to the preconditions of f improves the error reporting. |
Conditional expression | full |
if c then x else y end |
|
Creation expression (in body) | full |
create {T}.f (x) |
The verification will check if the precondition of f holds. Adding tag names to the preconditions of f improves the error reporting. |
Creation expression (in contract) | none |
create {T}.f (x) |
The contracts have to be side-effect free, creating objects in the contract is not supported. |
Manifest array (in body) | full |
<< a, b >> |
This syntax can be used to initialize MML_SEQUENCE entities. |
Manifest array (in contract) | partial |
<< a, b >> |
This syntax can be used to initialize MML_SEQUENCE entities. Otherwise the syntax is not supported in contracts, as they have to be side-effect free. |
Manifest string | partial |
"abc" |
AutoProof provdes a special string class V_STRING which can be initialized with manifest strings. |
Manifest tuple (in body) | full |
[a, b] |
This syntax can be used to initialize MML_SET entities in addition to initialize TUPLEs. |
Manifest tuple (in contract) | partial |
[a, b] |
This syntax can be used to initialize MML_SET entities. Otherwise the syntax is not supported in contracts, as they have to be side-effect free. |
Object test | full |
attached {T} a as x |
|
Old | full |
old a |
The old keyword can only be used in postconditions. For accessing the prestate in the routine body AutoProof provides a special query old_ . |
Library support and built-in types
Name | Support | Example | Comment |
---|---|---|---|
Boolean values | full |
True False |
|
Boolean arithmetic | full |
a and b or c a implies b xor c |
|
Integer values | full |
1 -2 |
|
Integer arithmetic | full |
a + b - c a * b // c |
The handling of integers is based on the built-in capabilities of Boogie. AutoProof also checks arithmetic overflows (if enabled). |
Floating point values | partial |
1.2 |
Floating point values are mapped to Boogie's real type. This is only an approximation of floating-point numbers. |
Floating point arithmetic | partial |
a + b - c a * b / c |
Floating point values are mapped to Boogie's real type. This is only an approximation of floating-point numbers. |
Character values | full |
'c' |
Characters are mapped to the integer code of the character. |
Character operations | partial |
a + b c.to_upper |
Only basic arithmetic on characters is supported. |
String values | partial |
"abc" |
AutoProof provdes a special string class V_STRING which can be initialized with manifest strings. |
Basic library | partial |
a: SIMPLE_ARRAY [INTEGER] create a.make (1, 5) a.put (v, 3) |
An array and a list class are provided specifically for the use in specification: SIMPLE_ARRAY and SIMPLE_LIST. |
Annotations
The following tables give a summary of the custom annotations supported by AutoProof. If you use the same tag name for multiple values, you can use either multiple note entries or a comma-separated list for the values. For example the following two declarations are equivalent:
note status: skip, functional |
note status: skip status: functional |
Class Annotations
Name | Example | Comment |
---|---|---|
Explicit |
note explicit: "all" |
Turn off all semantic collaboration defaults in the class. |
Explicit Contracts |
note explicit: contracts |
Turn off all semantic collaboration default contracts in the class. |
Explicit Sets |
note explicit: observers explicit: subjects explicit: owns |
Turn off semantic collaboration default invariants for the mentioned sets. |
Explicit Wrapping |
note explicit: wrapping |
Turn off all semantic collaboration default unwrapping and wrapping instructions in the class. |
Manual inv() |
note manual_inv: True |
If set to true then you need to insert manual inv , inv_only , and inv_without assertions in the code. |
Model |
note model: f, g |
List of model queries. |
Status: Skip |
note status: skip |
Skip verification of whole class. |
Theory |
note theory: "file.bpl" |
Include the specified theory file in the generated Boogie code. |
Type Mapping |
note maps_to: "BoogieType" |
Map this class to the specified custom Boogie type. |
Type Properties |
note type_properties: "BoogieFunction" |
Comma-separated list of Boogie functions that define the type properties for reference-type generic parameters. | Type Invariant |
note where: "BoogieFunction" |
Boogie function that defines the type invariant for this type. |
Feature Annotations
Name | Example | Comment |
---|---|---|
Explicit |
note explicit: "all" |
Turn off all semantic collaboration defaults in the feature. |
Explicit Contracts |
note explicit: contracts |
Turn off semantic collaboration default contracts in the feature. |
Explicit Wrapping |
note explicit: wrapping |
Turn off semantic collaboration default unwrapping and wrapping instructions in the feature. |
Function Mapping |
note maps_to: "BoogieFunction" |
Map this feature to the specified Boogie function. |
Guard |
note guard: True guard: False guard: "SomeFeature" |
Set the update guard of this attribute to the specified value. The update guard feature has to be functional. |
Inlining |
note inline: True inline: 4 |
Inline calls in this routine. If a number is given, then the calls will be inlined up to the specified depth. |
Manual inv() |
note manual_inv: True |
If set to true then you need to insert manual inv , inv_only , and inv_without assertions in the code. |
Status: Creator |
note status: creator |
Verify this routine only in the context of a creation routine. |
Status: Dynamic |
note status: dynamic |
Verify this routine assuming the Current type might be a subtype. This removes the need to reverify this routine in subclasses. |
Status: Functional |
note status: functional |
Mark this routine as functional. Functional features can only contain a single instruction that assigns a value to the Result |
Status: Ghost |
note status: ghost |
Mark the feature as a ghost feature. |
Status: Impure |
note status: impure |
Functions are supposed to have an empty modifies clause and are therefore pure. By marking a function as impure, you can add a modifies clause. |
Status: Inline in caller |
note status: inline_in_caller |
Mark this feature to be always inlined in the caller. |
Status: Lemma |
note status: lemma |
Mark this feature as a lemma. Lemma features have no automatic unwrapping and wrapping of the Current object and are implicitly ghost. |
Status: Skip |
note status: skip |
Skip verification of this feature. |
Precondition and Loop Invariant Functions
Name | Example | Comment |
---|---|---|
Decreases Clause |
require decreases (x) decreases ([x, y]) decreases ([]) |
Specify the variant of a recursive function or a loop. An empty decreases clause (last line) removes the termination check entirely. |
Modifies Clause (object) |
require modify (Current) modify (set) |
Allow this routine or loop to modify all attributes of the given objects. |
Modifies Clause (field) |
require modify_field ("x", Current) modify_field ("x", set) modify_field (["x", "y"], Current, set) |
Allow this routine or loop to modify the specified attributes of the given objects. |
Modifies Clause (model) |
require modify_model ("x", Current) modify_model ("x", set) modify_model (["x", "y"], Current, set) |
Allow this routine or loop to modify the specified models of the given objects. |
Reads Clause |
require reads (o) reads_field ("attr", o) reads_model ("attr", o) |
Allow this functional routine to read the specified objects, attributes or models. |
Commands and Queries
Name | Example | Comment |
---|---|---|
Invariant |
inv other.inv |
Check whether the class invariant of an object holds. |
Partial invariant |
inv_only ("tag1") other.inv_without ("tag2", "tag3") |
Check whether part of the class invariant holds. The check takes a list of tag names given by string constants and either just checks these tags (inv_only) or the whole invariant except for the specified tags (inv_without). |
Is Free |
is_free other.is_free |
Check whether an object is free. Free objects have no owner. |
Is Fresh |
is_fresh other.is_fresh |
Check whether an object is fresh. Fresh objects were not allocated in the pre-state. |
Is Open |
is_open other.is_open |
Check whether an object is open. Open objects might not satisfy their class invariant. |
Is Wrapped |
is_wrapped other.is_wrapped |
Check whether an object is wrapped. Wrapped objects are closed and free. |
Unwrapping |
unwrap other.unwrap unwrap_all (Current, set) |
Unwrap an object or a set of objects. |
Wrapping |
wrap other.wrap wrap_all (Current, set) |
Wrap an object or a set of objects. |