@@ -53,15 +53,52 @@ namespace AbstractEncoder
5353
5454variable {τ σ : Type } {m : Type → Type } [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+
5693private 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