|
1 | 1 | import Aeneas.Inv.Loop |
2 | 2 |
|
3 | | -namespace Aeneas.Inv |
| 3 | +namespace Aeneas.Inv.Formula |
4 | 4 |
|
5 | 5 | open Lean Elab Meta |
6 | 6 | open Extensions |
7 | 7 |
|
| 8 | +-- TODO: decompose formulae, then analyze them |
| 9 | + |
8 | 10 | inductive IneqKind where |
9 | | -| Lt | Le | Gt | Ge | Eq |
| 11 | +| lt | le | gt | ge | eq |
| 12 | +deriving BEq, Hashable, Ord |
10 | 13 |
|
11 | 14 | inductive VarOrConst where |
12 | 15 | | var (v : Var) |
13 | 16 | | const (e : Expr) -- TODO: also support constants in the footprint |
| 17 | +deriving BEq, Hashable |
14 | 18 |
|
15 | 19 | structure MulGroup where |
16 | 20 | elems : Array VarOrConst |
17 | 21 | const : Int |
| 22 | +deriving BEq, Hashable |
18 | 23 |
|
19 | 24 | structure AddGroup where |
20 | 25 | elems : Array MulGroup |
| 26 | +deriving BEq, Hashable |
| 27 | + |
| 28 | +abbrev ArithExpr := AddGroup |
21 | 29 |
|
22 | 30 | inductive Clause where |
23 | 31 | | unknown |
24 | 32 | | and (c0 c1 : Clause) |
25 | 33 | | or (c0 c1 : Clause) |
26 | 34 | | arith (kind : IneqKind) (lhs rhs : AddGroup) |
| 35 | +deriving BEq, Hashable |
27 | 36 |
|
28 | | -inductive Formula where |
| 37 | +inductive Fml where |
29 | 38 | | forall (v : Var) |
30 | 39 | | exists (v : Var) |
31 | | -| imp (c : Clause) (f : Formula) |
| 40 | +| imp (c : Clause) (f : Fml) |
32 | 41 | | 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 |
33 | 100 |
|
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 |
35 | 120 | sorry |
36 | 121 |
|
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 |
0 commit comments