AutoProof Manual

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.

AutoProof panel

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:

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:

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

NameSupportExampleComment
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

NameSupportExampleComment
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

NameSupportExampleComment
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

NameExampleComment
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

NameExampleComment
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

NameExampleComment
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

NameExampleComment
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.