Lecture Summary: Summary
Programs and Facts
Programs
-
We have considered programs composed of the following constructs
val
var
S; T
if (C) {S} else {T}
while (C) {S}
-
For all of these constructs we’ve considered how facts can be traced though them
-
Facts describe relationships among variables that occur in a program (and constants)
-
val
:
|
|
-
We can deduce the value of the variable as an equation
-
Recall, that the value cannot be modified
-
Variables introduced with
val
are immutable -
var
:
|
|
- We can deduce the value of the variable as an equation
- When a variable
v
is modified the old values can be accessed using the notationAt( v , i )
- Where
i
refers to the “time” at which the prior assignment took place
|
|
- We can write composed programs on one line separated by semicolons
- Usually, we don’t do this to improve readability
|
|
- We can deduce the condition or it’s negation in either branch
- A fact to be deduced is established by both branches
|
|
- The invariant traces facts from the beginning throughout the execution of the loop
- In the beginning of the loop body, the loop condition holds
- On termination, the negated loop condition holds
Contracts
Function Contracts I
- Side-effect free contract:
|
|
- Specifies pre- and post-condition
- No modifies clause
Function Contracts II
- Contract with side-effect (parameter):
|
|
- Specifies pre- and post-condition, and modifies clause
- Initial values of variables are referred to using the
In
notation
Function Contracts III
- Contract with side-effect (variable):
|
|
- Specifies pre- and post-condition, and modifies clause
- Initial values of variables are referred to using the
In
notation
Function Contracts IV
- Contract between participating entities:
|
|
- A contract fixes obligations on both sides
Specification
- A specification describes the expected behaviour of a program in simple and clear terms
- Usually, this is done in terms of
@pure
functions - Specifications themselves rely on maths (consider, in particular,
@strictpure
) - Specifications in Slang are executable but not necessarily efficient
- It should be easy to reason about specifications (and prove properties)
- Clarity and efficiency can often not be had at the same time
Implementation
- An implementation describes the behaviour of a program in efficient terms
- Usually, efficiency comes at the cost of reduced clarity
- Implementations describe how the behaviour is computed
- Specifications describe what is to be computed
Proof
-
Commonly used
assert
statements are executable, aborting when their condition is false -
In Slang we have seen commands that support proving the stated facts correct
Deduce
Invariant
Contract
Requires
Ensures
-
A proof establishes these facts for all possible executions
- The facts stated in one of these commands are not evaluated at run-time
- They do not lead to program abortion
-
We have seen how facts are traced through programs and used to prove new facts
Testing
-
Test cases can be generated from specifications
-
We can use contracts and do this directly using
- equivalence partitioning and
- boundary value analysis
-
We can use specifications with their “mathematical” function bodies to generate test cases
-
These cases can be used to test implementations
-
Given, the contracts provided, test cases can also be generated from implementations
-
If test cases are generated on specification level, they are available when implementation starts
Proof and Testing
-
Many reasoning techniques for programs can be used for proof and test case generation
-
Considering programs as facts,
- we can ask for states satisfying the post-condition to create a test case
- we can ask whether the program implies the post-condition to prove it correct
-
Whereas proof verifies correctness for all possible input values, testing verifies correctness for specific inputs. It is fallible.
-
Testing is somewhat like scientific experimentation: We consider the correctness of a program confirmed until we encounter a failing test (experiment).
-
We can generate tests from specifications that are easier to reason about, and use them for implementations that are harder to reason about
-
The specifications themselves can be proved correct based on the maths by which means they are expressed