Skip to content

Commit aa2317a

Browse files
sgraf812volodeyka
andauthored
refactor: reorganize the Std.Internal.Do order metatheory and tidy its lemmas (#13999)
This PR reorganizes the order and assertion algebra of `Std.Internal.Do` into a dedicated `Order/` namespace (`Order.Basic`, `Order.Lemmas`, `Order.Frame`), reducing `Assertion` to re-exports, and tidies the resulting lemmas: the function-pointwise lemmas are spelled `_apply`, the precondition-introduction lemmas sit beside their `CompleteLattice` siblings, triples with explicit exception postconditions gain a delaborator so they round-trip in the pretty printer, and the loop-spec `Invariant` is a `def` with an implicit exception postcondition. It is internal-only preparation for the upcoming `mvcgen'` rewrite and does not change the public `mvcgen` surface. --------- Co-authored-by: volodeyka <vovaglad00@gmail.com>
1 parent 8ce8a63 commit aa2317a

8 files changed

Lines changed: 960 additions & 495 deletions

File tree

src/Std/Internal/Do/Assertion.lean

Lines changed: 3 additions & 334 deletions
Original file line numberDiff line numberDiff line change
@@ -7,267 +7,12 @@ module
77

88
prelude
99
public import Init.Internal.Order
10+
public import Std.Internal.Do.Order.Basic
11+
public import Std.Internal.Do.Order.Frame
12+
public import Std.Internal.Do.Order.Lemmas
1013
universe u v w
1114
@[expose] public section
1215

13-
set_option linter.missingDocs true
14-
15-
namespace Lean.Order
16-
17-
/-!
18-
# Additional Complete Lattice Operations
19-
20-
Extensions to `Lean.Order.CompleteLattice` providing additional operations
21-
needed for program verification.
22-
-/
23-
24-
section LatticeExtensions
25-
26-
attribute [refl] PartialOrder.rel_refl
27-
28-
variable {α : Type u} [CompleteLattice α]
29-
30-
/-- Top element of a complete lattice (supremum of all elements) -/
31-
noncomputable def top : α := CompleteLattice.sup (fun _ => True)
32-
33-
@[inherit_doc top]
34-
scoped notation "⊤" => top
35-
36-
theorem le_top (x : α) : x ⊑ ⊤ := by
37-
apply le_sup
38-
trivial
39-
40-
/-- A complete lattice is a chain-complete partial order. -/
41-
noncomputable scoped instance : CCPO α where
42-
has_csup {c} _ := CompleteLattice.has_sup c
43-
44-
/-- Binary meet (infimum) -/
45-
noncomputable def meet (x y : α) : α := inf (fun z => z = x ∨ z = y)
46-
47-
@[inherit_doc meet]
48-
scoped infixl:70 " ⊓ " => meet
49-
50-
theorem meet_le_left (x y : α) : x ⊓ y ⊑ x := by
51-
apply inf_le
52-
left; rfl
53-
54-
theorem meet_le_right (x y : α) : x ⊓ y ⊑ y := by
55-
apply inf_le
56-
right; rfl
57-
58-
theorem le_meet (x y z : α) : x ⊑ y → x ⊑ z → x ⊑ y ⊓ z := by
59-
intro hxy hxz
60-
apply le_inf
61-
intro w hw
62-
cases hw with
63-
| inl h => rw [h]; exact hxy
64-
| inr h => rw [h]; exact hxz
65-
66-
/-- Binary join (supremum) -/
67-
noncomputable def join (x y : α) : α := CompleteLattice.sup (fun z => z = x ∨ z = y)
68-
69-
@[inherit_doc join]
70-
scoped infixl:65 " ⊔ " => join
71-
72-
theorem left_le_join (x y : α) : x ⊑ x ⊔ y := by
73-
apply le_sup
74-
left; rfl
75-
76-
theorem right_le_join (x y : α) : y ⊑ x ⊔ y := by
77-
apply le_sup
78-
right; rfl
79-
80-
theorem join_le (x y z : α) : x ⊑ z → y ⊑ z → x ⊔ y ⊑ z := by
81-
intro hxz hyz
82-
apply sup_le
83-
intro w hw
84-
cases hw with
85-
| inl h => rw [h]; exact hxz
86-
| inr h => rw [h]; exact hyz
87-
88-
/-- Indexed infimum -/
89-
noncomputable def iInf {ι : Type v} (f : ι → α) : α := inf (fun x => ∃ i, f i = x)
90-
91-
theorem iInf_le {ι : Type v} (f : ι → α) (i : ι) : iInf f ⊑ f i := by
92-
apply inf_le
93-
exact ⟨i, rfl⟩
94-
95-
theorem le_iInf {ι : Type v} (f : ι → α) (x : α) : (∀ i, x ⊑ f i) → x ⊑ iInf f := by
96-
intro h
97-
apply le_inf
98-
intro y ⟨i, hi⟩
99-
rw [← hi]
100-
exact h i
101-
102-
/-- Pointwise characterization of indexed infimum on function lattices. -/
103-
@[simp] theorem iInf_fun_apply
104-
{ι : Type v} {σ : Type w} {β : Type u} [CompleteLattice β]
105-
(f : ι → σ → β) (s : σ) :
106-
(iInf f) s = iInf (fun i => f i s) := by
107-
apply PartialOrder.rel_antisymm
108-
·
109-
apply le_iInf
110-
intro i
111-
exact (iInf_le f i) s
112-
·
113-
let g : σ → β := fun t => iInf (fun i => f i t)
114-
have hg : g ⊑ iInf f := by
115-
apply le_iInf
116-
intro i t
117-
exact iInf_le (fun j => f j t) i
118-
simpa [g] using hg s
119-
120-
/-- Indexed supremum -/
121-
noncomputable def iSup {ι : Type v} (f : ι → α) : α := CompleteLattice.sup (fun x => ∃ i, f i = x)
122-
123-
theorem le_iSup {ι : Type v} (f : ι → α) (i : ι) : f i ⊑ iSup f := by
124-
apply le_sup
125-
exact ⟨i, rfl⟩
126-
127-
theorem iSup_le {ι : Type v} (f : ι → α) (x : α) : (∀ i, f i ⊑ x) → iSup f ⊑ x := by
128-
intro h
129-
apply sup_le
130-
intro y ⟨i, hi⟩
131-
rw [← hi]
132-
exact h i
133-
134-
/-- Pointwise characterization of `CompleteLattice.sup` on function lattices:
135-
`(sup c) s = sup (fun y => ∃ f, c f ∧ f s = y)`. -/
136-
theorem sup_fun_apply
137-
{σ : Type v} {β : Type w} [CompleteLattice β]
138-
(c : (σ → β) → Prop) (s : σ) :
139-
CompleteLattice.sup c s = CompleteLattice.sup (fun y => ∃ f, c f ∧ f s = y) := by
140-
apply PartialOrder.rel_antisymm
141-
· -- sup c s ⊑ sup {y | ∃ f ∈ c, f s = y}
142-
let g : σ → β := fun t => CompleteLattice.sup (fun y => ∃ f, c f ∧ f t = y)
143-
have hg : CompleteLattice.sup c ⊑ g := by
144-
apply sup_le
145-
intro f hf t
146-
apply le_sup
147-
exact ⟨f, hf, rfl⟩
148-
exact hg s
149-
· -- sup {y | ∃ f ∈ c, f s = y} ⊑ sup c s
150-
apply sup_le
151-
intro y ⟨f, hf, hfs⟩
152-
rw [← hfs]
153-
exact (le_sup (c := c) hf) s
154-
155-
/-- Pointwise characterization of binary meet on function lattices. -/
156-
@[simp] theorem meet_fun_apply
157-
{σ : Type v} {β : Type w} [CompleteLattice β]
158-
(a b : σ → β) (s : σ) :
159-
(a ⊓ b) s = a s ⊓ b s := by
160-
apply PartialOrder.rel_antisymm
161-
· apply le_meet
162-
· exact (meet_le_left a b) s
163-
· exact (meet_le_right a b) s
164-
· classical
165-
let f : σ → β := fun t => if t = s then a t ⊓ b t else
166-
have hf_left : f ⊑ a := by
167-
intro t
168-
simp only [f]
169-
split
170-
· next h => subst h; exact meet_le_left ..
171-
· exact bot_le _
172-
have hf_right : f ⊑ b := by
173-
intro t
174-
simp only [f]
175-
split
176-
· next h => subst h; exact meet_le_right ..
177-
· exact bot_le _
178-
have hf_meet : f ⊑ a ⊓ b := le_meet f a b hf_left hf_right
179-
have hs : f s = a s ⊓ b s := by simp [f]
180-
exact hs ▸ hf_meet s
181-
182-
/-- Pointwise characterization of binary join on function lattices. -/
183-
@[simp] theorem join_fun_apply
184-
{σ : Type v} {β : Type w} [CompleteLattice β]
185-
(a b : σ → β) (s : σ) :
186-
(a ⊔ b) s = a s ⊔ b s := by
187-
apply PartialOrder.rel_antisymm
188-
·
189-
have hfun : a ⊔ b ⊑ fun t => a t ⊔ b t :=
190-
join_le a b (fun t => a t ⊔ b t)
191-
(fun t => left_le_join (a t) (b t))
192-
(fun t => right_le_join (a t) (b t))
193-
exact hfun s
194-
·
195-
apply join_le
196-
· exact (left_le_join a b) s
197-
· exact (right_le_join a b) s
198-
199-
end LatticeExtensions
200-
201-
/-!
202-
# Prop Embedding into Partial Order
203-
204-
Embedding propositions into a partial order with top and bottom.
205-
-/
206-
207-
/-!
208-
# CompleteLattice instance for Prop
209-
210-
We define a CompleteLattice structure on Prop where:
211-
- rel is implication (→)
212-
- sup is existential quantification over the predicate
213-
-/
214-
215-
instance : PartialOrder Prop where
216-
rel p q := p → q
217-
rel_refl := id
218-
rel_trans := fun h1 h2 x => h2 (h1 x)
219-
rel_antisymm := fun h1 h2 => propext ⟨h1, h2⟩
220-
221-
/-- Supremum for Prop: true iff some element of the set is true -/
222-
def propSup (c : PropProp) : Prop := ∃ p, c p ∧ p
223-
224-
theorem propSup_is_sup (c : PropProp) : is_sup c (propSup c) := by
225-
intro y
226-
constructor
227-
· intro hsup z hcz hz
228-
apply hsup
229-
exact Exists.intro z (And.intro hcz hz)
230-
· intro h ⟨z, hcz, hz⟩
231-
exact h z hcz hz
232-
233-
instance : CompleteLattice Prop where
234-
has_sup c := ⟨propSup c, propSup_is_sup c⟩
235-
236-
theorem prop_pre_intro (x y : Prop) : (x → True ⊑ y) → x ⊑ y :=
237-
fun h hx => h hx trivial
238-
239-
theorem prop_pre_elim (x : Prop) : x → True ⊑ x :=
240-
fun hx _ => hx
241-
242-
@[simp] theorem iInf_prop_eq_forall {ι : Type u} (f : ι → Prop) :
243-
(iInf f : Prop) = (∀ i, f i) := by
244-
apply propext
245-
constructor
246-
· intro hf i
247-
exact (iInf_le f i) hf
248-
· intro hall
249-
exact (le_iInf f (x := ∀ i, f i) (fun i h => h i)) hall
250-
251-
@[simp] theorem meet_prop_eq_and (a b : Prop) : (a ⊓ b : Prop) = (a ∧ b) := by
252-
apply propext
253-
constructor
254-
· intro hab
255-
exact ⟨(meet_le_left a b) hab, (meet_le_right a b) hab⟩
256-
· intro hab
257-
exact (le_meet (a ∧ b) a b (fun h => h.left) (fun h => h.right)) hab
258-
259-
@[simp] theorem join_prop_eq_or (a b : Prop) : (a ⊔ b : Prop) = (a ∨ b) := by
260-
apply propext
261-
constructor
262-
· intro hab
263-
exact (join_le a b (a ∨ b) (fun ha => Or.inl ha) (fun hb => Or.inr hb)) hab
264-
· intro hab
265-
cases hab with
266-
| inl ha => exact (left_le_join a b) ha
267-
| inr hb => exact (right_le_join a b) hb
268-
269-
end Lean.Order
270-
27116
namespace Std.Internal.Do
27217

27318
open Lean.Order
@@ -282,82 +27,6 @@ The `Assertion` class and `Assertion.ofProp` embedding.
28227
used as the carrier for pre- and postconditions. -/
28328
class abbrev Assertion (α : Type w) := CompleteLattice α
28429

285-
/-- An assertion type is a chain-complete partial order. -/
286-
scoped instance [Assertion EPred] : CCPO EPred where
287-
has_csup {c} _ := CompleteLattice.has_sup c
288-
289-
open Classical
290-
291-
/-- Embedding of propositions into an assertion type. `⌜p⌝` embeds `p : Prop` as `⊤` if `p` holds
292-
and `⊥` otherwise. -/
293-
noncomputable def Assertion.ofProp [Assertion l] (p : Prop) : l :=
294-
if p thenelse
295-
296-
@[inherit_doc Assertion.ofProp]
297-
scoped notation "⌜" p "⌝" => Assertion.ofProp p
298-
299-
@[simp]
300-
theorem Assertion.ofProp_true (l : Type v) [Assertion l] : ⌜True⌝ = (⊤ : l) := by
301-
simp [Assertion.ofProp]
302-
303-
@[simp]
304-
theorem Assertion.ofProp_false (l : Type v) [Assertion l] : ⌜False⌝ = (⊥ : l) := by
305-
simp [Assertion.ofProp]
306-
307-
theorem Assertion.ofProp_imp [Assertion l]
308-
(p₁ p₂ : Prop) : (p₁ → p₂) → ⌜p₁⌝ ⊑ (⌜p₂⌝ : l) := by
309-
simp only [Assertion.ofProp]
310-
intro h
311-
split
312-
case isTrue hp1 =>
313-
split
314-
case isTrue => exact PartialOrder.rel_refl
315-
case isFalse hp2 => exact absurd (h hp1) hp2
316-
case isFalse =>
317-
exact bot_le _
318-
319-
@[simp]
320-
theorem Assertion.ofProp_intro [Assertion l]
321-
(p : Prop) (h : l) : (⌜p⌝ ⊑ h) = (p → ⊤ ⊑ h) := by
322-
simp only [Assertion.ofProp]
323-
apply propext
324-
constructor
325-
· intro hle hp
326-
simp only [hp, ↓reduceIte] at hle
327-
exact hle
328-
· intro himp
329-
split
330-
next hp => exact himp hp
331-
next => exact bot_le _
332-
333-
@[simp]
334-
theorem Assertion.ofProp_intro_l [Assertion l] (p : Prop) (x y : l) :
335-
(x ⊓ ⌜ p ⌝ ⊑ y) = (p → x ⊑ y) := by
336-
apply propext
337-
constructor
338-
· intro h hp
339-
have hxy : x ⊓ ⊤ ⊑ y := by simp only [Assertion.ofProp, hp, ↓reduceIte] at h; exact h
340-
have hx_le_meet : x ⊑ x ⊓ ⊤ := le_meet x x ⊤ PartialOrder.rel_refl (le_top x)
341-
exact PartialOrder.rel_trans hx_le_meet hxy
342-
· intro h
343-
simp only [Assertion.ofProp]
344-
split
345-
next hp => exact PartialOrder.rel_trans (meet_le_left x ⊤) (h hp)
346-
next => exact PartialOrder.rel_trans (meet_le_right x ⊥) (bot_le _)
34730

348-
@[simp]
349-
theorem Assertion.ofProp_intro_r [Assertion l] (p : Prop) (x y : l) :
350-
(⌜ p ⌝ ⊓ x ⊑ y) = (p → x ⊑ y) := by
351-
apply propext
352-
constructor
353-
· intro h hp
354-
have hxy : ⊤ ⊓ x ⊑ y := by simp only [Assertion.ofProp, hp, ↓reduceIte] at h; exact h
355-
have hx_le_meet : x ⊑ ⊤ ⊓ x := le_meet x ⊤ x (le_top x) PartialOrder.rel_refl
356-
exact PartialOrder.rel_trans hx_le_meet hxy
357-
· intro h
358-
simp only [Assertion.ofProp]
359-
split
360-
next hp => exact PartialOrder.rel_trans (meet_le_right ⊤ x) (h hp)
361-
next => exact PartialOrder.rel_trans (meet_le_left ⊥ x) (bot_le _)
36231

36332
end Std.Internal.Do

src/Std/Internal/Do/ExceptPost.lean

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,26 @@ theorem EPost.cons_rel [PartialOrder e] [PartialOrder e'] (eposth : e) (epostt :
106106
EPost.cons.mk eposth epostt ⊑ epost :=
107107
fun hh ht => ⟨hh, ht⟩
108108

109+
/-- An `EPost.cons` value is below another if both components are below. -/
110+
theorem EPost.cons_rel_tail [PartialOrder e] [PartialOrder e'] (epostt : e') (epost : EPost.cons e e') :
111+
epostt ⊑ epost.tail →
112+
EPost.cons.mk epost.head epostt ⊑ epost := by
113+
apply EPost.cons_rel; rfl
114+
109115
/-- The unique `EPost.nil` value is below any `EPost.nil` value. -/
110116
theorem EPost.nil_rel (epost : EPost.nil) :
111117
EPost.nil.mk ⊑ epost := by
112118
simp [PartialOrder.rel]
113119

120+
/-- The head component of the bottom `EPost.cons` is the bottom element. Propositional (not
121+
definitional), because `⊥` of a complete lattice is `csup ∅`, not a constructor application. -/
122+
theorem EPost.cons.head_bot {eh : Type u} {et : Type v}
123+
[CompleteLattice eh] [CompleteLattice et] :
124+
EPost.cons.head (⊥ : EPost.cons eh et) = (⊥ : eh) := by
125+
refine PartialOrder.rel_antisymm ?_ (bot_le _)
126+
have h : (⊥ : EPost.cons eh et) ⊑ EPost.cons.mk (⊥ : eh) (⊥ : et) := bot_le _
127+
exact EPost.cons.rel_head h
128+
114129
/-!
115130
## Notation
116131

0 commit comments

Comments
 (0)