| | 1 | == contract clauses == |
| | 2 | |
| | 3 | * `requires e;`: precondition, `e` should hold at the entry of the function |
| | 4 | * `terminates e;`: |
| | 5 | * `decreases e ;` or `decreases e for r`;: decreases clause, where `e` is an expression of type `T` and `r` is an relation over `T` |
| | 6 | * simple clauses: |
| | 7 | * `ensures e;` |
| | 8 | * `assumes e;` |
| | 9 | * `assigns e0, e1, ...;` |
| | 10 | * `allocates e0, e1, ...;` |
| | 11 | * `frees e0, e1, ...;` |
| | 12 | * `guards e;` |
| | 13 | * `reads e0, e1, ...;` |
| | 14 | * `depends e0, e1, ...;` |
| | 15 | |
| | 16 | * action expressions: |
| | 17 | * `read(e)`: `e` has type `Mem`. The function reads the memory units specified by `e`. |
| | 18 | * `write(e)`: `e` has type `Mem`. The function writes the memory units specified by `e`. |
| | 19 | * `call(f, <e1, ...>)`: `f` has type `Function`. The function calls `f` with parameters `e1, ...`. |
| | 20 | * `noaction`: no action |
| | 21 | * `anyaction`: all actions |
| | 22 | * `act_union(ma0, ma1)`: the union of the two memory set actions `ma0` and `ma1`. |
| | 23 | * `act_comp(ma0, ma1)`: action complement (everything not in `ma1`) |
| | 24 | * `act_isect(ma0, ma1)`: action intersection |
| | 25 | |
| | 26 | * depends clause: `depends action0, action1, action2, ... ` |
| | 27 | * Example: `depends act_union(act_comp(read(n), call(inc, <x>))), call(dec, <y>))` |
| | 28 | * absence of depends clause: there is no information about the dependency of the function, which means that the analysis needs to figure it out by itself. |
| | 29 | * some facts about assigns-or-reads clause |
| | 30 | * absence of `reads`/`assigns` clause: there is no assumption about the read/assign access of the function, i.e., the function could read/assign anything |
| | 31 | * absence of `assigns` clause: similar to the absence of `reads` clause |
| | 32 | * `reads/assigns nothing` doesn’t necessarily means that the function never reads or assigns any variable. The function could still reads/assigns its “local” variables, including function parameters and any variable declared inside the function body. **check it** |
| | 33 | |
| | 34 | * For an independent function which has `depends coaction`, usually we also need to specify `reads nothing`, for the purpose of reachability analysis. |
| | 35 | e.g., |
| | 36 | {{{ |
| | 37 | /* Returns the size of the given bundle b. */ |
| | 38 | bundle_size(Bundle b): Integer |
| | 39 | depends nothing |
| | 40 | reads b |
| | 41 | ; |
| | 42 | }}} |
| | 43 | |
| | 44 | * Example of a function declaration with contracts: |
| | 45 | {{{ |
| | 46 | fun[atomic] sendRecv(Int cmd, Pointer buf): Integer |
| | 47 | reads deref(buf); |
| | 48 | behavior send: |
| | 49 | depends writes(buf); |
| | 50 | assigns nothing; |
| | 51 | behavior receive: |
| | 52 | depends access(deref(buf)); |
| | 53 | assigns deref(buf); |
| | 54 | { |
| | 55 | begin choose |
| | 56 | when eq(cmd, 0) |
| | 57 | do CALL send, <buf, ...>; goto L1; |
| | 58 | when eq(cmd, 1) |
| | 59 | do CALL recv, <buf, ...>; goto L1; |
| | 60 | when and(neq(cmd, 0), neq(cmd, 1)) |
| | 61 | do NOOP; goto L1; |
| | 62 | end choose |
| | 63 | L1: |
| | 64 | } |
| | 65 | }}} |