Skip to content

Commit 3f985f8

Browse files
committed
Small touchups
1 parent 65bdc82 commit 3f985f8

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

.vale/styles/config/ignore/terms.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ monad's
119119
monoid
120120
monomorphic
121121
monomorphism
122+
morphism
122123
multipattern
123124
multipatterns
124125
multiset

Manual/VCGen.lean

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ open Std.Do
5555

5656
## Preconditions and Postconditions
5757

58-
One style in which program specifications can be written is to provide a {deftech}_precondition_, which the program's caller is expected to ensure, and a {deftech}_postcondition_, which the program itself is expected to ensure.
59-
The program is correct if running it when the precondition holds always results in the postcondition holding.
58+
One style in which program specifications can be written is to provide a {deftech}_precondition_ $`P`, which the caller of a program `prog` is expected to ensure, and a {deftech}_postcondition_ $`Q`, which the `prog` is expected to ensure.
59+
The program `prog` satisfies the specification if running it when the precondition $`P` holds always results in the postcondition $`Q` holding.
6060

6161
In general, many different preconditions might suffice for a program to ensure the postcondition.
62-
After all, new preconditions can be generated by replacing a precondition $`P` with $`P \wedge Q`.
63-
The {deftech}_weakest precondition_ is a precondition that is implied by all other preconditions.
62+
After all, new preconditions can be generated by replacing a precondition $`P` with $`P \wedge P₂`.
63+
The {deftech}_weakest precondition_ $`\textbf{wp}⟦\texttt{prog}⟧(Q)` of a program `prog` and postcondition $`Q` is a precondition for which `prog` ensures the postcondition `Q` and is implied by all other such preconditions.
6464

6565
One way to prove something about the result of a program is to find the weakest precondition that guarantees the desired result, and then to show that this weakest precondition is simply true.
6666
This means that the postcondition holds no matter what.
@@ -83,7 +83,7 @@ def mySum (l : Array Nat) : Nat := Id.run do
8383
If {name}`mySum` is correct, then it is equal to {name}`Array.sum`.
8484
In {name}`mySum`, the use of {keywordOf Lean.Parser.Term.do}`do` is an internal implementation detail—the function's signature makes no mention of any monad.
8585
Thus, the proof first manipulates the goal into a form that is amenable to the use of {tactic}`mvcgen`, using the lemma {name}`Id.of_wp_run_eq`.
86-
This lemma states that facts about the result of running a computation in the {name}`Id` monad that terminates normally (that is, does not use {ref "early-return"}[early return]) can be proved by showing that the {tech}[weakest precondition] that ensures the desired result is true.
86+
This lemma states that facts about the result of running a computation in the {name}`Id` monad that terminates normally (`Id` computations never throw exceptions) can be proved by showing that the {tech}[weakest precondition] that ensures the desired result is true.
8787
Next, the proof uses {tactic}`mvcgen` to replace the formulation in terms of weakest preconditions with a set of {tech}[verification conditions].
8888

8989
While {tactic}`mvcgen` is mostly automatic, it does require an invariant for the loop.
@@ -130,7 +130,7 @@ For example:
130130

131131
* `vc1.step` conveys that this {tech}[VC] proves the inductive step for the loop
132132
* `vc2.a.pre` is meant to prove that the hypotheses of a goal imply the precondition of a specification (of {name}`forIn`).
133-
* `vc3.a.post` is meant to prove that the postcondition of a specification (of {name}`forIn`) implies the desired property.
133+
* `vc3.a.post.success` is meant to prove that the postcondition of a specification (of {name}`forIn`) implies the desired property.
134134
:::
135135

136136
:::paragraph
@@ -257,13 +257,21 @@ end
257257
```
258258
:::
259259

260-
:::TODO
261-
Note that the form `mvcgen invariants?` would hint that {name}`Invariant.withEarlyReturn` is a useful way to construct the invariant:
262-
```
260+
:::paragraph
261+
Note that the form `mvcgen invariants?` will suggest an initial invariant using {name}`Invariant.withEarlyReturn`, so there is no need to memorize the exact syntax for specifying invariants:
262+
```lean
263+
/--
264+
info: Try this:
265+
[apply] invariants
266+
·
267+
Invariant.withEarlyReturn (onReturn := fun r letMuts => ⌜l.Nodup ∧ (r = true ↔ l.Nodup)⌝) (onContinue :=
268+
fun xs letMuts => ⌜xs.prefix = [] ∧ letMuts = ∅ ∨ xs.suffix = [] ∧ l.Nodup⌝)
269+
-/
270+
#guard_msgs (info) in
263271
example (l : List Int) : nodup l ↔ l.Nodup := by
264272
generalize h : nodup l = r
265273
apply Id.of_wp_run_eq h
266-
mvcgen invariants?
274+
mvcgen invariants? <;> sorry
267275
```
268276
:::
269277

@@ -417,7 +425,7 @@ mkFresh
417425
⦃⇓ r state => ⌜r = c ∧ c < state.counter⌝⦄
418426
```
419427
When working in a state monad, preconditions may be parameterized over the value of the state prior to running the code.
420-
Here, the universally quantified {name}`Nat` is used to _relate_ the initial state to the final state; the precondition is used to connect it the initial state.
428+
Here, the universally quantified {name}`Nat` is used to _relate_ the initial state to the final state; the precondition is used to connect it to the initial state.
421429
Similarly, the postcondition may also accept the final state as a parameter.
422430
This Hoare triple states:
423431

0 commit comments

Comments
 (0)