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:

1
2
3
4
val x: Z = 1
Deduce(|- (x == 1))
val y: Z = x + 1
Deduce(|- (y == x + 1))
  • 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:

1
2
3
4
var x: Z = 1
Deduce(|- (x == 1))
x = x + 1
Deduce(|- (x == At(x, 0) + 1))
  • 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 notation
    • At( v , i )
    • Where i refers to the “time” at which the prior assignment took place
1
2
3
S ; T:
var x: Z = 1; x = x + 1
Deduce(|- (x == At(x, 0) + 1))
  • We can write composed programs on one line separated by semicolons
  • Usually, we don’t do this to improve readability
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if ( C ) { S } else { T }:
val a: Z = randomInt()
var x: Z = 1
Deduce(|- (x == 1))
if (a == 0) {
Deduce(|- (a == 0))
x = x + a + 1
} else {
Deduce(|- (a != 0))
x = x + (a / a)
}
Deduce(|- (x == At(x, 0) + 1))
  • We can deduce the condition or it’s negation in either branch
  • A fact to be deduced is established by both branches
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
while ( C ) { S }:
var x = 10
while (x < 12) {
Invariant(
Modifies(x),
x <= 12
)
Deduce(|- (x < 12))
x = x + 1
}
Deduce(|- (x >= 12))
Deduce(|- (x == At(x, 0) + 2))
  • 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:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def square(x: Z): Z = {
  Contract(
    Requires(x >= 0),
    Ensures(Res == x * x)
  )
  var res = 0
  var k = 0
  while (k < x) {
    res = res + x
    k = k + 1
  }
  return res
}
  • Specifies pre- and post-condition
  • No modifies clause

Function Contracts II

  • Contract with side-effect (parameter):
1
2
3
4
5
6
7
8
def inc0(x: ZS) {
  Contract(
    Requires(x.size == 1),
    Modifies(x),
    Ensures(x(0) == In(x)(0) + 1 )
  )
  x(0) = x(0) + 1
}
  • 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):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var x: Z = 0
def square() {
  Contract(
    Requires(x >= 0),
    Modifies(x),
    Ensures(x == In(x) * In(x))
  )
  var res = 0
  var k = 0
  while (k < x) {
    res = res + x
    k = k + 1
  }
  x = res
}
  • 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:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def one(x: Z): Z = {
  Contract(           // Contract between caller (two) and callee (one)
    Requires(x > 0),  // Caller (two) is obliged to guarantee
    Ensures(Res == 1) // Callee (one) is obliged to guarantee
  )
  return x / x
}
def two(x: Z): Z = {
  Contract(
    Requires(x - 1 > 0),
    Ensures(Res == 2)
  )
  return one(x - 1) + one(x)
}
  • 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