Skip to content

Commit cf7923c

Browse files
committed
Merge
2 parents 65a2e00 + 1599880 commit cf7923c

11 files changed

Lines changed: 52 additions & 52 deletions

‎src/SUMMARY.md‎

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,51 @@
33
- [Introduction](./introduction.md)
44
- [Structure](./structure.md)
55
- [Language Overview](./language.md)
6-
- [Top-level declarations](./language-top.md)
7-
- [Built-in types](./language-types.md)
8-
- [Imports](./language-imports.md)
9-
- [Annotations](./language-annotations.md)
6+
- [Top-level declarations](./language-top.md)
7+
- [Built-in types](./language-types.md)
8+
- [Imports](./language-imports.md)
9+
- [Annotations](./language-annotations.md)
1010
- [Permissions](./permissions.md)
11-
- [Viper's program state](./permissions-state.md)
12-
- [Inhaling and exhaling](./permissions-inhale-exhale.md)
13-
- [Self-framing assertions](./permissions-self-framing.md)
14-
- [Exclusive permissions](./permissions-exclusive.md)
15-
- [Fractional permissions](./permissions-fractional.md)
11+
- [Viper's program state](./permissions-state.md)
12+
- [Inhaling and exhaling](./permissions-inhale-exhale.md)
13+
- [Self-framing assertions](./permissions-self-framing.md)
14+
- [Exclusive permissions](./permissions-exclusive.md)
15+
- [Fractional permissions](./permissions-fractional.md)
1616
- [Predicates](./predicates.md)
1717
- [Functions](./functions.md)
1818
- [Quantifiers](./quantifiers.md)
1919
- [Quantified Permissions](./quantified-permissions.md)
20-
- [Receiver expressions and injectivity](./quantified-permissions-injectivity.md)
20+
- [Receiver expressions and injectivity](./quantified-permissions-injectivity.md)
2121
- [Magic Wands](./magic-wands.md)
22-
- [Package operations](./magic-wands-package.md)
23-
- [Heap-dependent expressions](./magic-wands-heap-dependent.md)
22+
- [Package operations](./magic-wands-package.md)
23+
- [Heap-dependent expressions](./magic-wands-heap-dependent.md)
2424
- [Statements](./statements.md)
25-
- [Assignments](./statements-assignments.md)
26-
- [Control structures](./statements-control.md)
27-
- [Assertion checking](./statements-assertions.md)
28-
- [Verifier directives](./statements-verifier.md)
25+
- [Assignments](./statements-assignments.md)
26+
- [Control structures](./statements-control.md)
27+
- [Assertion checking](./statements-assertions.md)
28+
- [Verifier directives](./statements-verifier.md)
2929
- [Expressions](./expressions.md)
30-
- [Integer expressions](./expressions-integer.md)
31-
- [Boolean expressions](./expressions-boolean.md)
32-
- [Reference expressions](./expressions-reference.md)
33-
- [Perm expressions](./expressions-perm.md)
34-
- [Sequence expressions](./expressions-sequence.md)
35-
- [Set and multiset expressions](./expressions-set-multiset.md)
36-
- [Map expressions](./expressions-map.md)
37-
- [Expressions of multiple types](./expressions-multi.md)
30+
- [Integer expressions](./expressions-integer.md)
31+
- [Boolean expressions](./expressions-boolean.md)
32+
- [Reference expressions](./expressions-reference.md)
33+
- [Perm expressions](./expressions-perm.md)
34+
- [Sequence expressions](./expressions-sequence.md)
35+
- [Set and multiset expressions](./expressions-set-multiset.md)
36+
- [Map expressions](./expressions-map.md)
37+
- [Expressions of multiple types](./expressions-multi.md)
3838
- [Assertions](./assertions.md)
3939
- [Domains](./domains.md)
40-
- [Declaring new types](./domains-new-types.md)
41-
- [Axiomatising custom theories](./domains-axiomatising.md)
42-
- [Encoding an array datatype](./domains-array.md)
43-
- [ADT plugin](./domains-adt.md)
40+
- [Declaring new types](./domains-new-types.md)
41+
- [Axiomatising custom theories](./domains-axiomatising.md)
42+
- [Encoding an array datatype](./domains-array.md)
43+
- [ADT plugin](./domains-adt.md)
4444
- [Termination](./termination.md)
45-
- [Termination measures and `decreases` clauses](./termination-measures.md)
46-
- [General syntax of `decreases` tuples](./termination-syntax.md)
47-
- [Special `decreases` tuples](./termination-special-tuples.md)
48-
- [Custom well-founded orders](./termination-custom-orders.md)
49-
- [Mutual recursion](./termination-mutual-recursion.md)
50-
- [Conditional termination](./termination-conditional.md)
51-
- [Abstract functions](./termination-abstract.md)
52-
- [Statement termination (experimental)](./termination-statement.md)
45+
- [Termination measures and `decreases` clauses](./termination-measures.md)
46+
- [General syntax of `decreases` tuples](./termination-syntax.md)
47+
- [Special `decreases` tuples](./termination-special-tuples.md)
48+
- [Custom well-founded orders](./termination-custom-orders.md)
49+
- [Mutual recursion](./termination-mutual-recursion.md)
50+
- [Conditional termination](./termination-conditional.md)
51+
- [Abstract functions](./termination-abstract.md)
52+
- [Statement termination (experimental)](./termination-statement.md)
5353
- [Further Information](./further-info.md)

‎src/domains.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ domain MyDomain {
1515

1616
The functions declared in a domain are global: one can apply them in any other scope of the Viper program. Functions declared inside a domain are called *domain functions*; these are more restricted than the standard Viper functions described previously. In particular, domain functions cannot have preconditions; they can be applied in *any* state. They are also always abstract, i.e., cannot have a defined body. The typical way to attach any meaning to these otherwise-uninterpreted functions, is via domain axioms.
1717

18-
Domain axioms are also global: they define properties of the program which are assumed to hold *in all states*. Since there is no restriction on the states to which an axiom applies, it must be well-defined in all states; for this reason, domain axioms cannot refer to the values of heap locations, nor to permission amounts (e.g., via [perm expressions](./expressions-perm.md)). In practice, domain axioms are standard (often quantified) first-order logic assertions. Axiom names are used only for readability of the code, but are currently not optional.
18+
Domain axioms are also global: they define properties of the program which are assumed to hold *in all states*. Since there is no restriction on the states to which an axiom applies, it must be well-defined in all states; for this reason, domain axioms cannot refer to the values of heap locations, nor to permission amounts (e.g., via [perm expressions](./expressions-perm.md)). In practice, domain axioms are standard (often quantified) first-order logic assertions. Axiom names are optional and are used only for readability of the code; for example, `axiom { bar(true) }` declares a valid, anonymous axiom.
1919

2020
```viper,editable,playground
2121
domain Neg {

‎src/expressions-perm.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
Expressions of type `Perm` are real numbers and are usually used to represent permission amounts (though they can be used for other purposes).
44

5-
* Fractional permission expressions `e1/e2`, where both `e1` and `e2` are integers, evaluate to a Perm value whose numerator is `e1` and whose denominator is `e2`. A well-definedness condition is that `e2` must not equal 0. `e1/e2` can also denote a permission amount divided by an integer if `e1` is an expression of type `Perm` and `e2` is an expression of type `Int`.
5+
* Fractional permission expressions `e1/e2`, where both `e1` and `e2` are integers, evaluate to a Perm value whose numerator is `e1` and whose denominator is `e2`. A well-definedness condition is that `e2` must not equal 0. `e1/e2` can also denote a permission amount divided by an integer if `e1` is an expression of type `Perm` and `e2` is an expression of type `Int`, or the quotient of two permission amounts if both `e1` and `e2` are of type `Perm`. Note that for ambiguous cases like `1/2`, the division operator `/` defaults to `Perm`-typed division; `Int`-typed (truncating) division can be forced with the alternative syntax `e1 \ e2` (see the [section on integer expressions](./expressions-integer.md)).
66

77
* The `Perm`-typed literals `none` and `write` denote no permission and a full permission, corresponding to `0/1` and `1/1`, respectively.
88

99
* The special literal `wildcard` denotes an unspecified positive amount. The specific value represented by `wildcard` is not fixed but is chosen anew every time a `wildcard` expression is encountered. In particular, if a `wildcard` amount of permission to a field or predicate is to be exhaled, a value less than the currently held amount is chosen, so that it is always possible to exhale (or assert having) a `wildcard` amount of any permission, unless no permission at all is currently held. However, exhaling and subsequently inhaling a `wildcard` permission to a location will not restore the initial permission amount, since it will not be known that the inhaled `wildcard` amount is equal to the exhaled one. The `wildcard` permission amount provides a convenient way to implement duplicable read-only resources, which, for example, can be used to model immutable data.
1010

1111
* `perm(e.f)`: Evaluates to the amount of permission the current method has to the specified location. Similarly, `perm(P(e1, ..., en))` returns the amount of permission held for the specified predicate instance. Similarly to `forperm`, the values of `perm` expressions take into account the side-effects of e.g. ongoing `exhale` operations. For example `exhale acc(x.f) && perm(x.f) > none` should always fail, while `exhale perm(x.f) > none && acc(x.f)` will succeed (if the full permission to `x.f` was held before the `exhale`).
1212

13-
* Permissions can be added (`e1 + e2`), subtracted (`e1 - e2`), multiplied (`e1 * e2`) or divided (`e1 / e2`). In the first two cases, `e1` and `e2` must both be `Perm`-typed. In the case of multiplication, either two `Perm`-typed expressions or one `Perm`-typed and one `Int`-typed are possible. For divisions, the first expression must be `Perm`-typed and the second of type `Int` (though of course ordinary fractions, where both expressions are `Int`-typed, also exist). The results in all cases will be `Perm`-typed expressions.
13+
* Permissions can be added (`e1 + e2`), subtracted (`e1 - e2`), multiplied (`e1 * e2`) or divided (`e1 / e2`). In the first two cases, `e1` and `e2` must both be `Perm`-typed. In the case of multiplication, either two `Perm`-typed expressions or one `Perm`-typed and one `Int`-typed are possible. For divisions, either both expressions are `Perm`-typed, or the first is `Perm`-typed and the second of type `Int` (and of course ordinary fractions, where both expressions are `Int`-typed, also exist). The results in all cases will be `Perm`-typed expressions.

‎src/functions.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ function capacity(l:Ref): Int
5050

5151
Note that functions declared in [Viper domains (i.e. *domain functions*)](./domains.md) are considered by Viper to be abstract state-independent total functions. As such, they can neither have a body nor be equipped with any pre-/postconditions; see the [domains section](./domains.md) for more details. In contrast, top-level functions can be state-dependent; the ability for function preconditions to include permissions allows them to depend on not only the values of their parameters, but also on heap locations to which their preconditions require permissions.
5252

53+
Permission *amounts* in function preconditions are interpreted differently from those in method preconditions: since functions cannot modify the heap, all that matters is whether a function may *read* a location, i.e., whether it has a positive permission amount. Concrete permission amounts in function preconditions are therefore ignored (and Viper reports a warning if one is written): `acc(x.f, 1/2)`, `acc(x.f, wildcard)` and `acc(x.f)` all simply require *some* positive permission to `x.f`. Two consequences are worth pointing out. First, non-aliasing cannot be concluded from permission amounts in a function precondition; e.g., unlike in a method precondition, `acc(x.f) && acc(y.f)` does *not* imply `x != y` inside the function. Second, inside a function, a predicate instance may be unfolded (via an [`unfolding` expression](./expressions-multi.md)) even if the precondition only provides a fraction of it. The previous behaviour, in which concrete permission amounts in function preconditions were taken into account, can be restored with the command-line option `--respectFunctionPrePermAmounts`.
54+
5355
Viper checks that the function body and any postconditions are framed by the preconditions; that is, the preconditions must require all permissions that are needed to evaluate the function body and the postconditions. Moreover, Viper verifies that the postconditions can be proven to hold for the result of the function.
5456
In order to enable function termination checks, which are *not* performed by default, users can specify termination measures, as discussed in [the chapter on termination](./termination.md).
5557
As the checking of a recursive function definition is essentially a proof by induction on the unrolling of the definition, not checking termination can lead to unsound behaviour. The following example yields such an inconsistency by means of a non-terminating function:

‎src/introduction.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<img src="https://www.ethz.ch/content/dam/ethz/special-interest/infk/chair-program-method/pm/images/Research/viper_architecture.png" alt="The Viper verification infrastructure" style="width: 100%;"/>
66

7-
The Viper infrastructure, shown above, provides an intermediate language as well as two verification back-ends, one based on symbolic execution and one based on verification condition generation. Both back-ends ultimately use the SMT solver
7+
The Viper infrastructure, shown above, provides an intermediate language as well as two verification back-ends: Viper's Symbolic Execution (SE) backend and its Verification Condition Generation (VCG) backend. Both back-ends ultimately use the SMT solver
88
[Z3](https://github.com/Z3Prover/z3) to discharge proof obligations. Front-end tools translate different source languages and verification
99
approaches into the Viper language and thereby benefit from its tool support and automation.
1010

‎src/language-types.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* `Ref` for references (to objects, except for the built-in `Ref` constant `null`)
44
* `Bool` for Boolean values
55
* `Int` for mathematical (unbounded) integers
6-
* `Rational` for mathematical (unbounded) rationals (this type is expected to be deprecated in the summer 2023 release)
6+
* `Rational` for mathematical (unbounded) rationals (this type is deprecated and will be removed in a future release; use `Perm` instead)
77
* `Perm` for permission amounts (see the [section on permissions](./permissions.md) for details)
88
* `Seq[T]` for immutable sequences with element type `T`
99
* `Set[T]` for immutable sets with element type `T`

‎src/permissions-exclusive.md‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ method exclusivity(x: Ref, y: Ref) {
1717
> * Add the third inhale statement `inhale x == y` anywhere before the exhale statement and change the latter to `exhale false`. Can false be asserted? Why does this demonstrate that it is not possible to hold more than one exclusive permission to `x.f`?
1818
1919
In Viper, accessibility predicates can be conjoined via `&&`; the resulting assertion requires the _sum_ of the permissions required by its two conjuncts. Therefore, the two statements `inhale acc(x.f); inhale acc(y.f)` (semicolons are required in Viper only if statements are on the same line) are equivalent to the single statement `inhale acc(x.f) && acc(y.f)`. In both cases, the obtained permissions imply that `x` and `y` cannot be aliases.
20-
Intuitively, the statement `inhale acc(x.f) && acc(y.f)` can be understood as inhaling permission to `acc(x.f)`, and in *addition* to that, inhaling the permission to `acc(y.f)`. Technically, this conjunction between resource assertions is strongly related to the *separating conjunction* from [separation logic](https://link.springer.com/chapter/10.1007/3-540-44802-0_1); formal details of the connection (and how to encode standard separation logic into Viper) can be found in [this paper](https://lmcs.episciences.org/802).
21-
22-
<!--**TODO: maybe consider also a link to wikipedia (for separation logic and separating conjunction), as suggested in one of the feedback e-mails **.-->
23-
24-
<!--**TODO: We could add a note here that briefly states that a conjunction between non-resource assertions, or a resource and a non-resource assertion, is the usual boolean conjunction. However, my feeling is that such a note will be more confusing then helpful.** -->
20+
Intuitively, the statement `inhale acc(x.f) && acc(y.f)` can be understood as inhaling permission to `acc(x.f)`, and in *addition* to that, inhaling the permission to `acc(y.f)`. Technically, this conjunction between resource assertions is strongly related to the *separating conjunction* from [separation logic](https://link.springer.com/chapter/10.1007/3-540-44802-0_1) (see also the [Wikipedia article](https://en.wikipedia.org/wiki/Separation_logic)); formal details of the connection (and how to encode standard separation logic into Viper) can be found in [this paper](https://lmcs.episciences.org/802).
2521

2622
We can now see how exclusive permissions enable framing and modular verification, as illustrated by the next example below. Here, method `client` is able to frame the property `b.f == 3` across the call to `inc(a, 3)` because holding permission to both `a.f` and `b.f` implies that `a` and `b` cannot be aliases, and because method `inc`'s specification states that `inc` only requires the permission to `a.f`. Since permission to `b.f` is _retained_, the value of `b.f` can be framed across the method call. Informally, and thinking more operationally, the method would not be able to modify this field location, since it lacks the necessary permission to do so.
2723

‎src/permissions-fractional.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,5 @@ method client(a: Ref, b: Ref) {
7373
> * Can you fix the new code by changing the specifications of method `copyAndInc`?
7474
> * Revert to the original example. Afterwards, modify method `client` as follows: change the invocation of method `copyAndInc` to `copyAndInc(a, a)`, and change the `assert` statement to `assert b.f == 3 && a.f == 2`. To verify the resulting code, you'll have to change the specifications of method `copyAndInc`.
7575
> * Can you find specifications for method `copyAndInc` that allow verifying both versions of method `client`: the original implementation (`copyAndInc(a, b); assert b.f == 3 && a.f == 4`) and the new one (`copyAndInc(a, a); assert b.f == 3 && a.f == 2`). That is, can you find specifications that work, regardless of whether or not the passed references are aliases?
76+
77+
Note that permission amounts are interpreted differently in the preconditions of Viper *functions* (introduced [later in this tutorial](./functions.md)): since functions cannot modify the heap, only the distinction between zero and positive permission amounts matters there, and concrete permission amounts are ignored; see the [section on functions](./functions.md) for details.

0 commit comments

Comments
 (0)