summaryrefslogtreecommitdiff
path: root/AvlVerification/Specifications.lean
blob: 0694df39c073da059d5ca85690afa5469078f22c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import «AvlVerification»

namespace Primitives

namespace Result

def map {A B: Type} (x: Result A) (f: A -> B): Result B := match x with
| .ok y => .ok (f y)
| .fail e => .fail e
| .div => .div

@[inline]
def isok {A: Type} : Result A -> Bool
| .ok _ => true
| .fail _ => false
| .div => false

@[inline]
def get? {A: Type}: (r: Result A) -> isok r -> A
| .ok x, _ => x

end Result

end Primitives

namespace avl_verification

def Ordering.toLeanOrdering (o: avl_verification.Ordering): _root_.Ordering := match o with 
| .Less => .lt
| .Equal => .eq
| .Greater => .gt

def Ordering.ofLeanOrdering (o: _root_.Ordering): avl_verification.Ordering := match o with
| .lt => .Less
| .eq => .Equal
| .gt => .Greater

end avl_verification

namespace Specifications

open Primitives
open Result

variable {T: Type} (H: outParam (avl_verification.Ord T))

-- TODO: reason about raw bundling vs. refined bundling.
-- raw bundling: hypothesis with Rust extracted objects.
-- refined bundling: lifted hypothesis with Lean native objects.
class OrdSpecInfaillible where
  infallible:  a b,  (o: avl_verification.Ordering), H.cmp a b = .ok o

class OrdSpecDuality extends OrdSpecInfaillible H where
  duality:  a b, H.cmp a b = .ok .Greater -> H.cmp b a = .ok .Less

-- TODO: OrdSpecEq := OrdSpecRel (R := Eq).
class OrdSpecEq extends OrdSpecInfaillible H where
  equality:  a b, H.cmp a b = .ok .Equal -> a = b

class OrdSpecRel (R: outParam (T -> T -> Prop)) extends OrdSpecInfaillible H where
  equivalence:  a b, H.cmp a b = .ok .Equal -> R a b

class OrdSpecDualityEq extends OrdSpecDuality H, OrdSpecEq H

instance: Coe (avl_verification.Ordering) (_root_.Ordering) where
  coe a := a.toLeanOrdering

def ordOfOrdSpec (H: avl_verification.Ord T) (spec: OrdSpecInfaillible H): Ord T where
  compare x y := (H.cmp x y).get? (by
    cases' (spec.infallible x y) with o Hcmp
    rewrite [isok, Hcmp]
    simp only
  )

instance [spec: OrdSpecInfaillible H]: Ord T := ordOfOrdSpec H spec
instance [OrdSpecInfaillible H]: LT T := ltOfOrd

theorem ltOfRustOrder {Spec: OrdSpecInfaillible H}: 
  haveI O := ordOfOrdSpec H Spec
  haveI := @ltOfOrd _ O
   a b, H.cmp a b = .ok .Less -> a < b := by
  intros a b
  intro Hcmp
  rw [LT.lt]
  simp [ltOfOrd]
  rw [compare]
  simp [ordOfOrdSpec]
  -- https://proofassistants.stackexchange.com/questions/1062/what-does-the-motive-is-not-type-correct-error-mean-in-lean
  simp_rw [Hcmp, get?, avl_verification.Ordering.toLeanOrdering]
  rfl

theorem gtOfRustOrder {Spec: OrdSpecDuality H}: 
  haveI O := ordOfOrdSpec H Spec.toOrdSpecInfaillible
  haveI := @ltOfOrd _ O
   a b, H.cmp a b = .ok .Greater -> b < a := by
  intros a b
  intro Hcmp
  apply ltOfRustOrder
  exact (Spec.duality _ _ Hcmp)


end Specifications