11package org.ksmt.solver.bitwuzla
22
33import org.ksmt.KContext
4- import org.ksmt.decl.KConstDecl
54import org.ksmt.decl.KDecl
65import org.ksmt.expr.KExpr
76import org.ksmt.expr.KUninterpretedSortValue
7+ import org.ksmt.solver.model.KFuncInterp
8+ import org.ksmt.solver.model.KFuncInterpEntryVarsFree
9+ import org.ksmt.solver.model.KFuncInterpEntryVarsFreeOneAry
10+ import org.ksmt.solver.model.KFuncInterpVarsFree
811import org.ksmt.solver.KModel
912import org.ksmt.solver.KSolverUnsupportedFeatureException
1013import org.ksmt.solver.bitwuzla.bindings.BitwuzlaNativeException
1114import org.ksmt.solver.bitwuzla.bindings.BitwuzlaTerm
1215import org.ksmt.solver.bitwuzla.bindings.FunValue
1316import org.ksmt.solver.bitwuzla.bindings.Native
17+ import org.ksmt.solver.model.KFuncInterpWithVars
1418import org.ksmt.solver.model.KModelEvaluator
1519import org.ksmt.solver.model.KModelImpl
1620import org.ksmt.sort.KArraySort
@@ -36,8 +40,18 @@ open class KBitwuzlaModel(
3640 private val evaluatorWithModelCompletion by lazy { KModelEvaluator (ctx, this , isComplete = true ) }
3741 private val evaluatorWithoutModelCompletion by lazy { KModelEvaluator (ctx, this , isComplete = false ) }
3842
39- override fun <T : KSort > eval (expr : KExpr <T >, isComplete : Boolean ): KExpr <T > {
43+ private var isValid: Boolean = true
44+
45+ fun markInvalid () {
46+ isValid = false
47+ }
48+
49+ private fun ensureModelValid () {
4050 bitwuzlaCtx.ensureActive()
51+ check(isValid) { " The model is no longer valid" }
52+ }
53+
54+ override fun <T : KSort > eval (expr : KExpr <T >, isComplete : Boolean ): KExpr <T > {
4155 ctx.ensureContextMatch(expr)
4256
4357 val evaluator = if (isComplete) evaluatorWithModelCompletion else evaluatorWithoutModelCompletion
@@ -68,11 +82,11 @@ open class KBitwuzlaModel(
6882 uninterpretedSortValueContext.currentSortUniverse(sort)
6983 }
7084
71- private val interpretations: MutableMap <KDecl <* >, KModel . KFuncInterp <* >> = hashMapOf()
85+ private val interpretations: MutableMap <KDecl <* >, KFuncInterp <* >> = hashMapOf()
7286
73- override fun <T : KSort > interpretation (decl : KDecl <T >): KModel .KFuncInterp <T >? {
87+ override fun <T : KSort > interpretation (decl : KDecl <T >): KFuncInterp <T >? {
88+ ensureModelValid()
7489 ctx.ensureContextMatch(decl)
75- bitwuzlaCtx.ensureActive()
7690
7791 if (decl !in modelDeclarations) return null
7892
@@ -90,7 +104,7 @@ open class KBitwuzlaModel(
90104 private fun <T : KSort > getInterpretationSafe (
91105 decl : KDecl <T >,
92106 term : BitwuzlaTerm
93- ): KModel . KFuncInterp <T > = bitwuzlaCtx.bitwuzlaTry {
107+ ): KFuncInterp <T > = bitwuzlaCtx.bitwuzlaTry {
94108 handleModelIsUnsupportedWithQuantifiers {
95109 getInterpretation(decl, term)
96110 }
@@ -99,16 +113,15 @@ open class KBitwuzlaModel(
99113 private fun <T : KSort > getInterpretation (
100114 decl : KDecl <T >,
101115 term : BitwuzlaTerm
102- ): KModel . KFuncInterp <T > = converter.withUninterpretedSortValueContext(uninterpretedSortValueContext) {
116+ ): KFuncInterp <T > = converter.withUninterpretedSortValueContext(uninterpretedSortValueContext) {
103117 when {
104118 Native .bitwuzlaTermIsArray(term) -> arrayInterpretation(decl, term)
105119 Native .bitwuzlaTermIsFun(term) -> functionInterpretation(decl, term)
106120 else -> {
107121 val value = Native .bitwuzlaGetValue(bitwuzlaCtx.bitwuzla, term)
108122 val convertedValue = with (converter) { value.convertExpr(decl.sort) }
109- KModel . KFuncInterp (
123+ KFuncInterpVarsFree (
110124 decl = decl,
111- vars = emptyList(),
112125 entries = emptyList(),
113126 default = convertedValue
114127 )
@@ -119,11 +132,11 @@ open class KBitwuzlaModel(
119132 private fun <T : KSort > functionInterpretation (
120133 decl : KDecl <T >,
121134 term : BitwuzlaTerm
122- ): KModel . KFuncInterp <T > {
135+ ): KFuncInterp <T > {
123136 val interp = Native .bitwuzlaGetFunValue(bitwuzlaCtx.bitwuzla, term)
124137 return if (interp.size != 0 ) {
125- handleArrayFunctionDecl(decl) { functionDecl, vars ->
126- functionValueInterpretation(functionDecl, vars, interp)
138+ handleArrayFunctionDecl(decl) { functionDecl ->
139+ functionValueInterpretation(functionDecl, interp)
127140 }
128141 } else {
129142 /* *
@@ -136,21 +149,19 @@ open class KBitwuzlaModel(
136149
137150 private fun <T : KSort > KBitwuzlaExprConverter.functionValueInterpretation (
138151 decl : KDecl <T >,
139- vars : List <KConstDecl <* >>,
140152 interp : FunValue
141- ): KModel . KFuncInterp <T > {
142- val entries = mutableListOf<KModel . KFuncInterpEntry <T >>()
153+ ): KFuncInterpVarsFree <T > {
154+ val entries = mutableListOf<KFuncInterpEntryVarsFree <T >>()
143155
144156 for (i in 0 until interp.size) {
145157 // Don't substitute vars since arguments in Bitwuzla model are always constants
146158 val args = interp.args!! [i].zip(decl.argSorts) { arg, sort -> arg.convertExpr(sort) }
147159 val value = interp.values!! [i].convertExpr(decl.sort)
148- entries + = KModel . KFuncInterpEntry (args, value)
160+ entries + = KFuncInterpEntryVarsFree .create (args, value)
149161 }
150162
151- return KModel . KFuncInterp (
163+ return KFuncInterpVarsFree (
152164 decl = decl,
153- vars = vars,
154165 entries = entries,
155166 default = null
156167 )
@@ -159,7 +170,7 @@ open class KBitwuzlaModel(
159170 private fun <T : KSort > KBitwuzlaExprConverter.retrieveFunctionValue (
160171 decl : KDecl <T >,
161172 functionTerm : BitwuzlaTerm
162- ): KModel . KFuncInterp <T > = handleArrayFunctionInterpretation(decl) { arraySort ->
173+ ): KFuncInterp <T > = handleArrayFunctionInterpretation(decl) { arraySort ->
163174 // We expect lambda expression here. Therefore, we convert function interpretation as array.
164175 val functionValue = Native .bitwuzlaGetValue(bitwuzlaCtx.bitwuzla, functionTerm)
165176 functionValue.convertExpr(arraySort)
@@ -168,51 +179,45 @@ open class KBitwuzlaModel(
168179 private fun <T : KSort > arrayInterpretation (
169180 decl : KDecl <T >,
170181 term : BitwuzlaTerm
171- ): KModel . KFuncInterp <T > = handleArrayFunctionDecl(decl) { arrayFunctionDecl, vars ->
182+ ): KFuncInterp <T > = handleArrayFunctionDecl(decl) { arrayFunctionDecl ->
172183 val sort: KArraySort <KSort , KSort > = decl.sort.uncheckedCast()
173- val entries = mutableListOf<KModel . KFuncInterpEntry <KSort >>()
184+ val entries = mutableListOf<KFuncInterpEntryVarsFree <KSort >>()
174185 val interp = Native .bitwuzlaGetArrayValue(bitwuzlaCtx.bitwuzla, term)
175186
176187 for (i in 0 until interp.size) {
177188 val index = interp.indices!! [i].convertExpr(sort.domain)
178189 val value = interp.values!! [i].convertExpr(sort.range)
179- entries + = KModel . KFuncInterpEntry ( listOf ( index) , value)
190+ entries + = KFuncInterpEntryVarsFreeOneAry ( index, value)
180191 }
181192
182193 val default = interp.defaultValue.takeIf { it != 0L }?.convertExpr(sort.range)
183194
184- KModel . KFuncInterp (
195+ KFuncInterpVarsFree (
185196 decl = arrayFunctionDecl,
186- vars = vars,
187197 entries = entries,
188198 default = default
189199 )
190200 }
191201
192202 private inline fun <T : KSort > handleArrayFunctionDecl (
193203 decl : KDecl <T >,
194- body : KBitwuzlaExprConverter .(KDecl <KSort >, List < KConstDecl < * >> ) -> KModel . KFuncInterp <* >
195- ): KModel . KFuncInterp <T > = with (ctx) {
204+ body : KBitwuzlaExprConverter .(KDecl <KSort >) -> KFuncInterp <* >
205+ ): KFuncInterp <T > = with (ctx) {
196206 val sort = decl.sort
197207
198208 if (sort !is KArraySortBase <* >) {
199- val vars = decl.argSorts.mapIndexed { i, s -> s.mkFreshConstDecl(" x!$i " ) }
200- return converter.body(decl.uncheckedCast(), vars).uncheckedCast()
209+ return converter.body(decl.uncheckedCast()).uncheckedCast()
201210 }
202211
203212 check(decl.argSorts.isEmpty()) { " Unexpected function with array range" }
204213
205214 val arrayInterpDecl = mkFreshFuncDecl(" array" , sort.range, sort.domainSorts)
206- val arrayInterpIndicesDecls = sort.domainSorts.mapIndexed { i, s ->
207- s.mkFreshConstDecl(" idx!$i " )
208- }
209215
210216 modelDeclarations + = arrayInterpDecl
211- interpretations[arrayInterpDecl] = converter.body(arrayInterpDecl, arrayInterpIndicesDecls )
217+ interpretations[arrayInterpDecl] = converter.body(arrayInterpDecl)
212218
213- KModel . KFuncInterp (
219+ KFuncInterpVarsFree (
214220 decl = decl,
215- vars = emptyList(),
216221 entries = emptyList(),
217222 default = mkFunctionAsArray(sort.uncheckedCast(), arrayInterpDecl).uncheckedCast()
218223 )
@@ -221,14 +226,13 @@ open class KBitwuzlaModel(
221226 private inline fun <T : KSort > KBitwuzlaExprConverter.handleArrayFunctionInterpretation (
222227 decl : KDecl <T >,
223228 convertInterpretation : (KArraySortBase <* >) -> KExpr <KArraySortBase <* >>
224- ): KModel . KFuncInterp <T > {
229+ ): KFuncInterp <T > {
225230 val sort = decl.sort
226231
227232 if (sort is KArraySortBase <* > && decl.argSorts.isEmpty()) {
228233 val arrayInterpretation = convertInterpretation(sort)
229- return KModel . KFuncInterp (
234+ return KFuncInterpVarsFree (
230235 decl = decl,
231- vars = emptyList(),
232236 entries = emptyList(),
233237 default = arrayInterpretation.uncheckedCast()
234238 )
@@ -242,7 +246,7 @@ open class KBitwuzlaModel(
242246 val functionVars = decl.argSorts.mapIndexed { i, s -> s.mkFreshConstDecl(" x!$i " ) }
243247 val functionValue = ctx.mkAnyArraySelect(arrayInterpretation, functionVars.map { it.apply () })
244248
245- return KModel . KFuncInterp (
249+ return KFuncInterpWithVars (
246250 decl = decl,
247251 vars = functionVars,
248252 entries = emptyList(),
0 commit comments