Skip to content

Commit 9b14ad9

Browse files
committed
Move termTypeToSort out of AbstractSolver; build it in encoder from sort primitives
1 parent 9ddb634 commit 9b14ad9

3 files changed

Lines changed: 54 additions & 23 deletions

File tree

Strata/DL/SMT/AbstractSolver.lean

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,6 @@ structure AbstractSolver (τ : Type) (σ : Type) (m : Type → Type) where
7474
with the given type arguments. -/
7575
constrSort : String → List σ → m σ
7676

77-
/-- Convert a `TermType` to the solver's sort `σ`. Backends implement this
78-
directly (e.g. identity for SMT-LIB, actual conversion for FFI).
79-
Built from the sort primitives above. -/
80-
termTypeToSort : TermType → m σ
81-
8277
-- Literal / leaf constructors
8378
mkBool : Bool → m τ
8479
mkInt : Int → m τ

Strata/DL/SMT/IncrementalSolver.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ def mkIncrementalSolver : AbstractSolver Term TermType IncrementalSolverM where
170170
bitvecSort n := return .bitvec n
171171
arraySort k v := return .ok (.constr "Array" [k, v])
172172
constrSort name args := return .constr name args
173-
termTypeToSort ty := return ty
174173

175174
mkBool b := return Term.bool b
176175
mkInt i := return Term.int i

Strata/Languages/Core/Verifier.lean

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,52 @@ namespace AbstractEncoder
5353

5454
variable {τ σ : Type} {m : TypeType} [Monad m] [MonadExceptOf IO.Error m]
5555

56+
/-- Convert a `TermType` to the solver's sort type `σ` by dispatching on
57+
the sort primitives provided by the solver. This is the sort-level
58+
counterpart of `encodeTerm`: both convert a Strata representation to a
59+
solver-native handle by pattern-matching on constructors. Keeping this
60+
logic in the encoder (rather than in `AbstractSolver`) means backends
61+
only need to implement the one-liner sort primitives, not a full
62+
dispatching method. -/
63+
def termTypeToSort (solver : AbstractSolver τ σ m) (ty : TermType) : m σ := do
64+
match ty with
65+
| .prim .bool => solver.boolSort
66+
| .prim .int => solver.intSort
67+
| .prim .real => solver.realSort
68+
| .prim .string => solver.stringSort
69+
| .prim .regex => solver.regexSort
70+
| .prim (.bitvec n) => solver.bitvecSort n
71+
| .prim .trigger => solver.boolSort
72+
| .option inner => do
73+
let s ← termTypeToSort solver inner
74+
solver.constrSort "Option" [s]
75+
| .constr name args => do
76+
if name == "Array" then
77+
match args with
78+
| [k, v] => do
79+
let ks ← termTypeToSort solver k
80+
let vs ← termTypeToSort solver v
81+
match ← solver.arraySort ks vs with
82+
| .ok s => return s
83+
| .error _ => solver.constrSort name []
84+
| _ => solver.constrSort name []
85+
else
86+
let argSorts ← args.attach.mapM fun ⟨t, _⟩ => termTypeToSort solver t
87+
solver.constrSort name argSorts
88+
termination_by sizeOf ty
89+
decreasing_by
90+
all_goals simp_wf
91+
all_goals (try omega) <;> (have := List.sizeOf_lt_of_mem ‹_›; omega)
92+
5693
private def encodeUF (solver : AbstractSolver τ σ m) (uf : UF) : AbstractEncoderM τ m String := do
5794
if let .some enc := (← get).base.ufs.get? uf then return enc
5895
let baseName := sanitizeSmtName uf.id
5996
let existingNames := (← get).base.ufs.toList.map (·.2)
6097
let usedNames := Std.HashSet.ofList (existingNames ++ smtReservedKeywords)
6198
let id := Strata.Name.findUnique baseName 1 usedNames
6299
liftM (solver.comment uf.id)
63-
let argSorts ← uf.args.mapM (fun vt => liftM (solver.termTypeToSort vt.ty))
64-
let outSort ← liftM (solver.termTypeToSort uf.out)
100+
let argSorts ← uf.args.mapM (fun vt => liftM (termTypeToSort solver vt.ty))
101+
let outSort ← liftM (termTypeToSort solver uf.out)
65102
match ← liftM (solver.declareFun id argSorts outSort) with
66103
| .ok handle =>
67104
modify fun st => { st with varHandles := st.varHandles.insert id handle }
@@ -104,7 +141,7 @@ private def defineApp (solver : AbstractSolver τ σ m) (retSort : σ) (op : Op)
104141
| .uf f, _ =>
105142
let ufName ← encodeUF solver f
106143
let ufRef : UF := { id := ufName, args := f.args, out := f.out }
107-
let outSort ← liftM (solver.termTypeToSort ufRef.out)
144+
let outSort ← liftM (termTypeToSort solver ufRef.out)
108145
let handle ← liftExcept "mkAppOp(uf)" (← liftM (solver.mkAppOp (.uf ufRef) [] outSort))
109146
liftExcept "mkApp" (← liftM (solver.mkApp handle tEncs))
110147
-- Datatype operations: build handle and apply
@@ -120,7 +157,7 @@ private def defineQuantifierHelper (solver : AbstractSolver τ σ m) (qk : Quant
120157
(encodeTriggers : AbstractEncoderM τ m (List (List τ)))
121158
: AbstractEncoderM τ m τ := do
122159
let bindings ← args.mapM fun v => do
123-
let s ← liftM (solver.termTypeToSort v.ty)
160+
let s ← liftM (termTypeToSort solver v.ty)
124161
return (v.id, s)
125162
let mkQuant := match qk with
126163
| .all => solver.mkForall
@@ -147,40 +184,40 @@ def encodeTerm (solver : AbstractSolver τ σ m) (t : Term) : AbstractEncoderM
147184
| .some handle => return handle
148185
| .none =>
149186
-- Variable not yet declared — declare it now via declareNew
150-
let s ← liftM (solver.termTypeToSort v.ty)
187+
let s ← liftM (termTypeToSort solver v.ty)
151188
let handle ← liftM (solver.declareNew v.id s)
152189
modify fun st => { st with varHandles := st.varHandles.insert v.id handle }
153190
return handle
154191
| .prim p => liftM (solver.mkPrim p)
155192
| .none ty =>
156193
-- Option none: use the datatype constructor via mkAppOp
157-
let retSort ← liftM (solver.termTypeToSort (.option ty))
194+
let retSort ← liftM (termTypeToSort solver (.option ty))
158195
liftExcept "mkAppOp(none)" (← liftM (solver.mkAppOp (.datatype_op .constructor "none") [] retSort))
159196
| .some t₁ =>
160197
-- Option some: encode the inner term and apply the constructor via mkAppOp
161198
let t₁Enc ← encodeTerm solver t₁
162-
let retSort ← liftM (solver.termTypeToSort (.option t₁.typeOf))
199+
let retSort ← liftM (termTypeToSort solver (.option t₁.typeOf))
163200
let handle ← liftExcept "mkAppOp(some)" (← liftM (solver.mkAppOp (.datatype_op .constructor "some") [] retSort))
164201
liftExcept "mkApp(some)" (← liftM (solver.mkApp handle [t₁Enc]))
165202
| .app .re_allchar [] .regex =>
166-
let s ← liftM (solver.termTypeToSort .regex)
203+
let s ← liftM (termTypeToSort solver .regex)
167204
liftExcept "mkAppOp(re)" (← liftM (solver.mkAppOp .re_allchar [] s))
168205
| .app .re_all [] .regex =>
169-
let s ← liftM (solver.termTypeToSort .regex)
206+
let s ← liftM (termTypeToSort solver .regex)
170207
liftExcept "mkAppOp(re)" (← liftM (solver.mkAppOp .re_all [] s))
171208
| .app .re_none [] .regex =>
172-
let s ← liftM (solver.termTypeToSort .regex)
209+
let s ← liftM (termTypeToSort solver .regex)
173210
liftExcept "mkAppOp(re)" (← liftM (solver.mkAppOp .re_none [] s))
174211
| .app .bvnego [inner] .bool =>
175212
match inner.typeOf with
176213
| .bitvec n =>
177214
let innerEnc ← encodeTerm solver inner
178215
let minVal ← liftM (solver.mkPrim (.bitvec (BitVec.intMin n)))
179-
let retSort ← liftM (solver.termTypeToSort .bool)
216+
let retSort ← liftM (termTypeToSort solver .bool)
180217
defineApp solver retSort .eq [innerEnc, minVal]
181218
| _ => liftM (solver.mkBool false)
182219
| .app op ts _ =>
183-
let retSort ← liftM (solver.termTypeToSort t.typeOf)
220+
let retSort ← liftM (termTypeToSort solver t.typeOf)
184221
defineApp solver retSort op (← mapM₁ ts (fun ⟨tᵢ, _⟩ => encodeTerm solver tᵢ))
185222
| .quant qk qargs tr body =>
186223
let trExprs := if Factory.isSimpleTrigger tr then [] else extractTriggers tr
@@ -203,9 +240,9 @@ private def encodeFunction (solver : AbstractSolver τ σ m) (uf : UF) (body : T
203240
let id := ufId (← get).base.ufs.size
204241
liftM (solver.comment uf.id)
205242
let argPairs ← uf.args.mapM fun vt => do
206-
let s ← liftM (solver.termTypeToSort vt.ty)
243+
let s ← liftM (termTypeToSort solver vt.ty)
207244
return (vt.id, s)
208-
let outSort ← liftM (solver.termTypeToSort uf.out)
245+
let outSort ← liftM (termTypeToSort solver uf.out)
209246
let bodyEnc ← encodeTerm solver body
210247
match ← liftM (solver.defineFun id argPairs outSort bodyEnc) with
211248
| .ok _ => pure ()
@@ -233,7 +270,7 @@ private def datatypeConstrsM [Monad m] (solver : AbstractSolver τ σ m)
233270
for c in d.constrs.reverse do
234271
let mut fields := []
235272
for (name, fieldTy) in c.args.reverse do
236-
let s ← solver.termTypeToSort (Core.lMonoTyToTermType fieldTy)
273+
let s ← AbstractEncoder.termTypeToSort solver (Core.lMonoTyToTermType fieldTy)
237274
fields := (d.name ++ ".." ++ name.name, s) :: fields
238275
result := (c.name.name, fields) :: result
239276
return result
@@ -307,12 +344,12 @@ def encodeDeclarationsAbstract [Monad m] [MonadExceptOf IO.Error m]
307344
unwrap "assert" (← solver.assert id)
308345
-- Emit variable declarations as declareFun
309346
for decl in varDeclarations do
310-
let sort ← solver.termTypeToSort decl.ty
347+
let sort ← AbstractEncoder.termTypeToSort solver decl.ty
311348
let _ ← unwrap "declareFun" (← solver.declareFun decl.name [] sort)
312349
-- Emit variable definitions as defineFun
313350
let estate ← varDefinitions.foldlM (init := estate) fun estate def_ => do
314351
let (bodyEnc, estate) ← (AbstractEncoder.encodeTerm solver def_.body) |>.run estate
315-
let sort ← solver.termTypeToSort def_.ty
352+
let sort ← AbstractEncoder.termTypeToSort solver def_.ty
316353
unwrap "defineFun" (← solver.defineFun def_.name [] sort bodyEnc)
317354
pure estate
318355
let (assumptionIds, estate) ← assumptionTerms.mapM (AbstractEncoder.encodeTerm solver) |>.run estate

0 commit comments

Comments
 (0)