Skip to content

Commit 8b6598d

Browse files
committed
Start implementing the lifting of pres and posts
1 parent a82cbe9 commit 8b6598d

File tree

2 files changed

+145
-6
lines changed

2 files changed

+145
-6
lines changed
Lines changed: 136 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,167 @@
11
import Aeneas.Inv.Loop
22

3-
namespace Aeneas.Inv
3+
namespace Aeneas.Inv.Formula
44

55
open Lean Elab Meta
66
open Extensions
77

8+
-- TODO: decompose formulae, then analyze them
9+
810
inductive IneqKind where
9-
| Lt | Le | Gt | Ge | Eq
11+
| lt | le | gt | ge | eq
12+
deriving BEq, Hashable, Ord
1013

1114
inductive VarOrConst where
1215
| var (v : Var)
1316
| const (e : Expr) -- TODO: also support constants in the footprint
17+
deriving BEq, Hashable
1418

1519
structure MulGroup where
1620
elems : Array VarOrConst
1721
const : Int
22+
deriving BEq, Hashable
1823

1924
structure AddGroup where
2025
elems : Array MulGroup
26+
deriving BEq, Hashable
27+
28+
abbrev ArithExpr := AddGroup
2129

2230
inductive Clause where
2331
| unknown
2432
| and (c0 c1 : Clause)
2533
| or (c0 c1 : Clause)
2634
| arith (kind : IneqKind) (lhs rhs : AddGroup)
35+
deriving BEq, Hashable
2736

28-
inductive Formula where
37+
inductive Fml where
2938
| forall (v : Var)
3039
| exists (v : Var)
31-
| imp (c : Clause) (f : Formula)
40+
| imp (c : Clause) (f : Fml)
3241
| clause (c : Clause)
42+
deriving BEq, Hashable
43+
44+
structure State where
45+
/-- Var id counter -/
46+
varId : VarId := 0
47+
fvars : Std.HashMap FVarId Var := {}
48+
arrayGetters : Std.HashSet (VarProj × Array ArithExpr) := {}
49+
50+
abbrev M := StateRefT State MetaM
51+
52+
def pushFVar (fvar : FVarId) : M VarId := do
53+
let s ← get
54+
let varId := s.varId
55+
let name ← do
56+
if let some decl ← fvar.findDecl? then pure (some (decl.userName.toString))
57+
else pure none
58+
let var : Var := { id := varId, name }
59+
set ({s with varId := varId + 1, fvars := s.fvars.insert fvar var })
60+
pure varId
61+
62+
def pushFVars (fvars : Array FVarId) : M (Array VarId) := do
63+
fvars.mapM pushFVar
64+
65+
def pushArrayGetter (a : VarProj) (indices : Array ArithExpr) : M Unit := do
66+
let s ← get
67+
set { s with arrayGetters := s.arrayGetters.insert (a, indices) }
68+
69+
def propBinops : Std.HashMap Name IneqKind := Std.HashMap.ofList [
70+
(``LT.lt, .lt),
71+
(``LT.lt, .lt),
72+
(``HSub.hSub, .sub),
73+
(``HMul.hMul, .mul),
74+
(``HMod.hMod, .mod),
75+
(``HDiv.hDiv, .div),
76+
(``HPow.hPow, .pow),
77+
]
78+
79+
mutual
80+
81+
partial def formula.formula (e : Expr) : M (Array (Expr × Fml)) := do
82+
match e with
83+
| .bvar _ | .fvar _ | .mvar _ | .sort _ | .const _ _ | .lit _
84+
| .lam _ _ _ _ | .letE _ _ _ _ _ | .proj _ _ _ =>
85+
/- Explore the expression to accumulate information about the array
86+
accesses, but return an unknown clause -/
87+
formula.unknown e
88+
pure #[(e, .clause .unknown)]
89+
| .app _ _ =>
90+
trace[Inv] ".app"
91+
formula.clause e
92+
| .mdata _ e => formula.formula e
93+
| .forallE _ _ _ _ =>
94+
trace[Inv] ".forallE"
95+
forallTelescope e fun fvars body => do
96+
/- Explore the introduced fvars. Depending on their type we want to introduce:
97+
- new variables
98+
- new clauses -/
99+
formula.forall fvars body
33100

34-
def analyzeFormula (fp : Footprint) (isPre : Bool) (e : Expr) : MetaM (Array (Expr × Formula)) := do
101+
partial def formula.clause (e : Expr) : M (Array (Expr × Fml)) := do
102+
/- TODO: check if this is a clause:
103+
- and, or
104+
- eq, ineq
105+
- or unknown clause
106+
-/
107+
let f := e.getAppFn
108+
let args := e.getAppArgs
109+
110+
if f.isConstOf ``And ∧ args.size = 2 then sorry
111+
if f.isConstOf ``Or ∧ args.size = 2 then sorry
112+
if f.isConstOf ``Eq ∧ args.size = 3 then sorry
113+
114+
-- TODO: ineqs
115+
if f.isConstOf ``LT.lt ∧ args.size = 4 then sorry
116+
117+
sorry
118+
119+
partial def formula.forall (fvars : Array Expr) (body : Expr) : M (Array (Expr × Fml)) := do
35120
sorry
36121

37-
end Aeneas.Inv
122+
/-- Simply explore the expression to accumulate information about the found
123+
arrays, etc. -/
124+
partial def formula.unknown (e : Expr) : M Unit := do
125+
match e with
126+
| .bvar _ | .fvar _ | .mvar _ | .sort _ | .const _ _ | .lit _
127+
| .lam _ _ _ _ =>
128+
Meta.lambdaTelescope e fun fvars body => do
129+
formula.unknown body
130+
| .letE _ _ _ _ _ =>
131+
Meta.lambdaLetTelescope e fun fvars body => do
132+
for fvar in fvars do
133+
if let some decl ← fvar.fvarId!.findDecl? then
134+
if let some value := decl.value? then -- Should always be some?
135+
formula.unknown value
136+
| .app _ _ =>
137+
-- Check if this is a getter (note that we don't care about setters)
138+
if let some (array, indices) ← asGetter? e then
139+
try
140+
let array ← formula.array array
141+
let indices ← indices.mapM formula.arith
142+
pushArrayGetter array indices
143+
catch _ => pure ()
144+
-- Otherwise: simply explore the arguments
145+
let f := e.getAppFn
146+
formula.unknown f
147+
let args := e.getAppArgs
148+
args.forM formula.unknown
149+
| .mdata _ e => formula.unknown e
150+
| .proj _ _ struct =>
151+
formula.unknown struct
152+
| .forallE _ _ _ _ =>
153+
forallTelescope e fun fvars body => do
154+
-- Explore the type of the fvars
155+
fvars.forM fun fvar => do
156+
let ty ← inferType fvar
157+
formula.unknown ty
158+
-- Explore the body
159+
formula.unknown body
160+
161+
partial def formula.array (e : Expr) : M VarProj := do sorry
162+
163+
partial def formula.arith (e : Expr) : M ArithExpr := do sorry
164+
165+
end
166+
167+
end Aeneas.Inv.Formula

backends/lean/Aeneas/Inv/Test.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ example (src dst : Array Nat)
367367
analyze_loop
368368
simp [post]
369369

370+
-- TODO: call a loop on an array which is not a variable (ex.: `List.replicate ...`)
371+
370372
set_option grind.warning false
371373

372374
example (P : Nat → Prop) (_ : ∀ i < 8, ∀ j < 8, P (8 * i + j)) :
@@ -391,4 +393,11 @@ example (P : Nat → Prop) (h : ∀ i < 8, P (2 * i) ∧ P (2 * i + 1)) :
391393

392394
example (P : Nat → Prop) (h : ∀ i < 2, P i) : P 0 ∧ P 1 := by grind
393395

396+
example (P : Nat → Prop) (_ : ∀ i < 8, ∀ j < 8, P (8 * i + j))
397+
-- This should be given by a theorem
398+
(h : (∀ k < 64, P k) ↔ (∀ i < 8, ∀ j < 8, P (8 * i + j))) :
399+
∀ k < 64, P k := by
400+
grind
401+
402+
394403
end Aeneas.Inv.Test

0 commit comments

Comments
 (0)