main.io.ksmt.solver.cvc5.KCvc5ExprInternalizer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ksmt-cvc5-core Show documentation
Show all versions of ksmt-cvc5-core Show documentation
Kotlin API for various SMT solvers
The newest version!
package io.ksmt.solver.cvc5
import io.github.cvc5.Kind
import io.github.cvc5.RoundingMode
import io.github.cvc5.Solver
import io.github.cvc5.Sort
import io.github.cvc5.Term
import io.ksmt.decl.KDecl
import io.ksmt.expr.KAddArithExpr
import io.ksmt.expr.KAndBinaryExpr
import io.ksmt.expr.KAndExpr
import io.ksmt.expr.KArray2Lambda
import io.ksmt.expr.KArray2Select
import io.ksmt.expr.KArray2Store
import io.ksmt.expr.KArray3Lambda
import io.ksmt.expr.KArray3Select
import io.ksmt.expr.KArray3Store
import io.ksmt.expr.KArrayConst
import io.ksmt.expr.KArrayLambda
import io.ksmt.expr.KArrayLambdaBase
import io.ksmt.expr.KArrayNLambda
import io.ksmt.expr.KArrayNSelect
import io.ksmt.expr.KArrayNStore
import io.ksmt.expr.KArraySelect
import io.ksmt.expr.KArraySelectBase
import io.ksmt.expr.KArrayStore
import io.ksmt.expr.KArrayStoreBase
import io.ksmt.expr.KBitVec16Value
import io.ksmt.expr.KBitVec1Value
import io.ksmt.expr.KBitVec32Value
import io.ksmt.expr.KBitVec64Value
import io.ksmt.expr.KBitVec8Value
import io.ksmt.expr.KBitVecCustomValue
import io.ksmt.expr.KBitVecNumberValue
import io.ksmt.expr.KBitVecValue
import io.ksmt.expr.KBv2IntExpr
import io.ksmt.expr.KBvAddExpr
import io.ksmt.expr.KBvAddNoOverflowExpr
import io.ksmt.expr.KBvAddNoUnderflowExpr
import io.ksmt.expr.KBvAndExpr
import io.ksmt.expr.KBvArithShiftRightExpr
import io.ksmt.expr.KBvConcatExpr
import io.ksmt.expr.KBvDivNoOverflowExpr
import io.ksmt.expr.KBvExtractExpr
import io.ksmt.expr.KBvLogicalShiftRightExpr
import io.ksmt.expr.KBvMulExpr
import io.ksmt.expr.KBvMulNoOverflowExpr
import io.ksmt.expr.KBvMulNoUnderflowExpr
import io.ksmt.expr.KBvNAndExpr
import io.ksmt.expr.KBvNegNoOverflowExpr
import io.ksmt.expr.KBvNegationExpr
import io.ksmt.expr.KBvNorExpr
import io.ksmt.expr.KBvNotExpr
import io.ksmt.expr.KBvOrExpr
import io.ksmt.expr.KBvReductionAndExpr
import io.ksmt.expr.KBvReductionOrExpr
import io.ksmt.expr.KBvRepeatExpr
import io.ksmt.expr.KBvRotateLeftExpr
import io.ksmt.expr.KBvRotateLeftIndexedExpr
import io.ksmt.expr.KBvRotateRightExpr
import io.ksmt.expr.KBvRotateRightIndexedExpr
import io.ksmt.expr.KBvShiftLeftExpr
import io.ksmt.expr.KBvSignExtensionExpr
import io.ksmt.expr.KBvSignedDivExpr
import io.ksmt.expr.KBvSignedGreaterExpr
import io.ksmt.expr.KBvSignedGreaterOrEqualExpr
import io.ksmt.expr.KBvSignedLessExpr
import io.ksmt.expr.KBvSignedLessOrEqualExpr
import io.ksmt.expr.KBvSignedModExpr
import io.ksmt.expr.KBvSignedRemExpr
import io.ksmt.expr.KBvSubExpr
import io.ksmt.expr.KBvSubNoOverflowExpr
import io.ksmt.expr.KBvSubNoUnderflowExpr
import io.ksmt.expr.KBvToFpExpr
import io.ksmt.expr.KBvUnsignedDivExpr
import io.ksmt.expr.KBvUnsignedGreaterExpr
import io.ksmt.expr.KBvUnsignedGreaterOrEqualExpr
import io.ksmt.expr.KBvUnsignedLessExpr
import io.ksmt.expr.KBvUnsignedLessOrEqualExpr
import io.ksmt.expr.KBvUnsignedRemExpr
import io.ksmt.expr.KBvXNorExpr
import io.ksmt.expr.KBvXorExpr
import io.ksmt.expr.KBvZeroExtensionExpr
import io.ksmt.expr.KConst
import io.ksmt.expr.KDistinctExpr
import io.ksmt.expr.KDivArithExpr
import io.ksmt.expr.KEqExpr
import io.ksmt.expr.KExistentialQuantifier
import io.ksmt.expr.KExpr
import io.ksmt.expr.KFalse
import io.ksmt.expr.KFp128Value
import io.ksmt.expr.KFp16Value
import io.ksmt.expr.KFp32Value
import io.ksmt.expr.KFp64Value
import io.ksmt.expr.KFpAbsExpr
import io.ksmt.expr.KFpAddExpr
import io.ksmt.expr.KFpCustomSizeValue
import io.ksmt.expr.KFpDivExpr
import io.ksmt.expr.KFpEqualExpr
import io.ksmt.expr.KFpFromBvExpr
import io.ksmt.expr.KFpFusedMulAddExpr
import io.ksmt.expr.KFpGreaterExpr
import io.ksmt.expr.KFpGreaterOrEqualExpr
import io.ksmt.expr.KFpIsInfiniteExpr
import io.ksmt.expr.KFpIsNaNExpr
import io.ksmt.expr.KFpIsNegativeExpr
import io.ksmt.expr.KFpIsNormalExpr
import io.ksmt.expr.KFpIsPositiveExpr
import io.ksmt.expr.KFpIsSubnormalExpr
import io.ksmt.expr.KFpIsZeroExpr
import io.ksmt.expr.KFpLessExpr
import io.ksmt.expr.KFpLessOrEqualExpr
import io.ksmt.expr.KFpMaxExpr
import io.ksmt.expr.KFpMinExpr
import io.ksmt.expr.KFpMulExpr
import io.ksmt.expr.KFpNegationExpr
import io.ksmt.expr.KFpRemExpr
import io.ksmt.expr.KFpRoundToIntegralExpr
import io.ksmt.expr.KFpRoundingMode
import io.ksmt.expr.KFpRoundingModeExpr
import io.ksmt.expr.KFpSqrtExpr
import io.ksmt.expr.KFpSubExpr
import io.ksmt.expr.KFpToBvExpr
import io.ksmt.expr.KFpToFpExpr
import io.ksmt.expr.KFpToIEEEBvExpr
import io.ksmt.expr.KFpToRealExpr
import io.ksmt.expr.KFpValue
import io.ksmt.expr.KFunctionApp
import io.ksmt.expr.KFunctionAsArray
import io.ksmt.expr.KGeArithExpr
import io.ksmt.expr.KGtArithExpr
import io.ksmt.expr.KImpliesExpr
import io.ksmt.expr.KInt32NumExpr
import io.ksmt.expr.KInt64NumExpr
import io.ksmt.expr.KIntBigNumExpr
import io.ksmt.expr.KInterpretedValue
import io.ksmt.expr.KIsIntRealExpr
import io.ksmt.expr.KIteExpr
import io.ksmt.expr.KLeArithExpr
import io.ksmt.expr.KLtArithExpr
import io.ksmt.expr.KModIntExpr
import io.ksmt.expr.KMulArithExpr
import io.ksmt.expr.KNotExpr
import io.ksmt.expr.KOrBinaryExpr
import io.ksmt.expr.KOrExpr
import io.ksmt.expr.KPowerArithExpr
import io.ksmt.expr.KRealNumExpr
import io.ksmt.expr.KRealToFpExpr
import io.ksmt.expr.KRemIntExpr
import io.ksmt.expr.KSubArithExpr
import io.ksmt.expr.KToIntRealExpr
import io.ksmt.expr.KToRealIntExpr
import io.ksmt.expr.KTrue
import io.ksmt.expr.KUnaryMinusArithExpr
import io.ksmt.expr.KUninterpretedSortValue
import io.ksmt.expr.KUniversalQuantifier
import io.ksmt.expr.KXorExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoUnderflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvDivNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvNegNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvSubNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvSubNoUnderflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvMulNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvMulNoUnderflowExpr
import io.ksmt.expr.rewrite.simplify.simplifyBvRotateLeftExpr
import io.ksmt.expr.rewrite.simplify.simplifyBvRotateRightExpr
import io.ksmt.solver.KSolverUnsupportedFeatureException
import io.ksmt.solver.util.KExprInternalizerBase
import io.ksmt.sort.KArithSort
import io.ksmt.sort.KArray2Sort
import io.ksmt.sort.KArray3Sort
import io.ksmt.sort.KArrayNSort
import io.ksmt.sort.KArraySortBase
import io.ksmt.sort.KBoolSort
import io.ksmt.sort.KBvSort
import io.ksmt.sort.KFp128Sort
import io.ksmt.sort.KFp16Sort
import io.ksmt.sort.KFp32Sort
import io.ksmt.sort.KFp64Sort
import io.ksmt.sort.KFpRoundingModeSort
import io.ksmt.sort.KFpSort
import io.ksmt.sort.KRealSort
import io.ksmt.sort.KSort
import io.ksmt.sort.KUninterpretedSort
import io.ksmt.utils.powerOfTwo
import java.math.BigInteger
@Suppress("LargeClass")
class KCvc5ExprInternalizer(
private val cvc5Ctx: KCvc5Context,
private val solver: Solver
) : KExprInternalizerBase() {
private val sortInternalizer = KCvc5SortInternalizer(cvc5Ctx)
private val declInternalizer = KCvc5DeclInternalizer(cvc5Ctx, solver, sortInternalizer)
private val tm: KCvc5TermManager = cvc5Ctx.termManager
override fun findInternalizedExpr(expr: KExpr<*>): Term? = cvc5Ctx.findInternalizedExpr(expr)
override fun saveInternalizedExpr(expr: KExpr<*>, internalized: Term) {
cvc5Ctx.saveInternalizedExpr(expr, internalized)
}
private val zeroIntValueTerm: Term by lazy {
val ksmtZero = cvc5Ctx.ctx.mkIntNum(0)
findInternalizedExpr(ksmtZero)
?: tm.builder { mkInteger(0L) }.also { saveInternalizedExpr(ksmtZero, it) }
}
fun > T.internalizeDecl(): Term = accept(declInternalizer)
fun T.internalizeSort(): Sort = accept(sortInternalizer)
override fun transform(expr: KFunctionApp) = with(expr) {
transformArray(args) { args: Array ->
cvc5Ctx.addDeclaration(decl)
// args[0] is a function declaration
val decl = decl.internalizeDecl()
if (decl.hasOp()) {
val op = tm.termOp(decl) { op }
tm.mkTerm(op, args)
} else {
decl.mkFunctionApp(args.asList())
}
}
}
override fun transform(expr: KConst) = with(expr) {
transform {
cvc5Ctx.addDeclaration(decl)
decl.internalizeDecl()
}
}
override fun transform(expr: KAndExpr) = with(expr) {
transformArray(args) { args: Array -> mkAndTerm(args.asList()) }
}
override fun transform(expr: KAndBinaryExpr) = with(expr) {
transform(lhs, rhs) { l: Term, r: Term -> tm.mkTerm(Kind.AND, l, r) }
}
override fun transform(expr: KOrExpr) = with(expr) {
transformArray(args) { args: Array -> mkOrTerm(args.asList()) }
}
override fun transform(expr: KOrBinaryExpr) = with(expr) {
transform(lhs, rhs) { l: Term, r: Term -> tm.mkTerm(Kind.OR, l, r) }
}
override fun transform(expr: KNotExpr) =
with(expr) { transform(arg) { arg: Term -> tm.mkTerm(Kind.NOT, arg) } }
override fun transform(expr: KImpliesExpr) = with(expr) {
transform(p, q) { p: Term, q: Term ->
tm.mkTerm(Kind.IMPLIES, p, q)
}
}
override fun transform(expr: KXorExpr) = with(expr) {
transform(a, b) { a: Term, b: Term ->
tm.mkTerm(Kind.XOR, a, b)
}
}
override fun transform(expr: KTrue) = expr.transform { tm.builder { mkTrue() } }
override fun transform(expr: KFalse) = expr.transform { tm.builder { mkFalse() } }
override fun transform(expr: KEqExpr) = with(expr) {
transform(lhs, rhs) { lhs: Term, rhs: Term ->
mkArraySpecificTerm(
sort = expr.lhs.sort,
arrayTerm = { mkArrayEqTerm(it, lhs, rhs) },
default = { lhs.eqTerm(rhs) }
)
}
}
override fun transform(expr: KDistinctExpr) = with(expr) {
transformArray(args) { args: Array ->
mkArraySpecificTerm(
sort = expr.args.first().sort,
arrayTerm = { mkArrayDistinctTerm(it, args.asList()) },
default = { tm.mkTerm(Kind.DISTINCT, args) }
)
}
}
override fun transform(expr: KIteExpr) = with(expr) {
transform(
condition, trueBranch, falseBranch
) { condition: Term, trueBranch: Term, falseBranch: Term ->
mkArraySpecificTerm(
sort = expr.trueBranch.sort,
arrayTerm = { mkArrayIteTerm(it, condition, trueBranch, falseBranch) },
default = { condition.iteTerm(trueBranch, falseBranch) }
)
}
}
fun transformBitVecValue(expr: KBitVecValue) = expr.transform {
val size = expr.decl.sort.sizeBits.toInt()
when {
expr is KBitVec1Value -> tm.builder { mkBitVector(size, if (expr.value) 1L else 0L) }
// cvc5 can't create bitvector from negatives
expr is KBitVecNumberValue<*, *> && expr.numberValue.toLong() >= 0 -> {
tm.builder { mkBitVector(size, expr.numberValue.toLong()) }
}
else -> tm.builder { mkBitVector(size, expr.stringValue, 2) }
}
}
override fun transform(expr: KBitVec1Value) = transformBitVecValue(expr)
override fun transform(expr: KBitVec8Value) = transformBitVecValue(expr)
override fun transform(expr: KBitVec16Value) = transformBitVecValue(expr)
override fun transform(expr: KBitVec32Value) = transformBitVecValue(expr)
override fun transform(expr: KBitVec64Value) = transformBitVecValue(expr)
override fun transform(expr: KBitVecCustomValue) = transformBitVecValue(expr)
override fun transform(expr: KBvNotExpr) = with(expr) {
transform(value) { value: Term -> tm.mkTerm(Kind.BITVECTOR_NOT, value) }
}
override fun transform(expr: KBvReductionAndExpr) = with(expr) {
transform(value) { value: Term -> tm.mkTerm(Kind.BITVECTOR_REDAND, value) }
}
override fun transform(expr: KBvReductionOrExpr) = with(expr) {
transform(value) { value: Term -> tm.mkTerm(Kind.BITVECTOR_REDOR, value) }
}
override fun transform(expr: KBvAndExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_AND, arg0, arg1)
}
}
override fun transform(expr: KBvOrExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_OR, arg0, arg1)
}
}
override fun transform(expr: KBvXorExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_XOR, arg0, arg1)
}
}
override fun transform(expr: KBvNAndExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_NAND, arg0, arg1)
}
}
override fun transform(expr: KBvNorExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_NOR, arg0, arg1)
}
}
override fun transform(expr: KBvXNorExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_XNOR, arg0, arg1)
}
}
override fun transform(expr: KBvNegationExpr) = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.BITVECTOR_NEG, value)
}
}
override fun transform(expr: KBvAddExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_ADD, arg0, arg1)
}
}
override fun transform(expr: KBvSubExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SUB, arg0, arg1)
}
}
override fun transform(expr: KBvMulExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_MULT, arg0, arg1)
}
}
override fun transform(expr: KBvUnsignedDivExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_UDIV, arg0, arg1)
}
}
override fun transform(expr: KBvSignedDivExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SDIV, arg0, arg1)
}
}
override fun transform(expr: KBvUnsignedRemExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_UREM, arg0, arg1)
}
}
override fun transform(expr: KBvSignedRemExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SREM, arg0, arg1)
}
}
override fun transform(expr: KBvSignedModExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SMOD, arg0, arg1)
}
}
override fun transform(expr: KBvUnsignedLessExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_ULT, arg0, arg1)
}
}
override fun transform(expr: KBvSignedLessExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SLT, arg0, arg1)
}
}
override fun transform(expr: KBvUnsignedLessOrEqualExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_ULE, arg0, arg1)
}
}
override fun transform(expr: KBvSignedLessOrEqualExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SLE, arg0, arg1)
}
}
override fun transform(expr: KBvUnsignedGreaterOrEqualExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_UGE, arg0, arg1)
}
}
override fun transform(expr: KBvSignedGreaterOrEqualExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SGE, arg0, arg1)
}
}
override fun transform(expr: KBvUnsignedGreaterExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_UGT, arg0, arg1)
}
}
override fun transform(expr: KBvSignedGreaterExpr) = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_SGT, arg0, arg1)
}
}
override fun transform(expr: KBvConcatExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.BITVECTOR_CONCAT, arg0, arg1)
}
}
override fun transform(expr: KBvExtractExpr) = with(expr) {
transform(value) { value: Term ->
val extractOp = tm.mkOp(Kind.BITVECTOR_EXTRACT, high, low)
tm.mkTerm(extractOp, value)
}
}
override fun transform(expr: KBvSignExtensionExpr) = with(expr) {
transform(value) { value: Term ->
val extensionOp = tm.mkOp(Kind.BITVECTOR_SIGN_EXTEND, extensionSize)
tm.mkTerm(extensionOp, value)
}
}
override fun transform(expr: KBvZeroExtensionExpr) = with(expr) {
transform(value) { value: Term ->
val extensionOp = tm.mkOp(Kind.BITVECTOR_ZERO_EXTEND, extensionSize)
tm.mkTerm(extensionOp, value)
}
}
override fun transform(expr: KBvRepeatExpr) = with(expr) {
transform(value) { value: Term ->
val repeatOp = tm.mkOp(Kind.BITVECTOR_REPEAT, repeatNumber)
tm.mkTerm(repeatOp, value)
}
}
override fun transform(expr: KBvShiftLeftExpr) = with(expr) {
transform(arg, shift) { arg: Term, shift: Term ->
tm.mkTerm(Kind.BITVECTOR_SHL, arg, shift)
}
}
override fun transform(expr: KBvLogicalShiftRightExpr) = with(expr) {
transform(arg, shift) { arg: Term, shift: Term ->
tm.mkTerm(Kind.BITVECTOR_LSHR, arg, shift)
}
}
override fun transform(expr: KBvArithShiftRightExpr) = with(expr) {
transform(arg, shift) { arg: Term, shift: Term ->
tm.mkTerm(Kind.BITVECTOR_ASHR, arg, shift)
}
}
/*
* we can internalize rotate expr as concat expr due to simplification,
* otherwise we can't process rotate expr on expression
*/
override fun transform(expr: KBvRotateLeftExpr) = with(expr) {
transform {
val simplifiedExpr = ctx.simplifyBvRotateLeftExpr(arg, rotation)
if (simplifiedExpr is KBvRotateLeftExpr<*>) {
throw KSolverUnsupportedFeatureException(
"Rotate expr with expression argument is not supported by cvc5"
)
}
simplifiedExpr.internalizeExpr()
}
}
/*
* @see transform(expr: KBvRotateLeftExpr)
*/
override fun transform(expr: KBvRotateRightExpr) = with(expr) {
transform {
val simplifiedExpr = ctx.simplifyBvRotateRightExpr(arg, rotation)
if (simplifiedExpr is KBvRotateRightExpr<*>) {
throw KSolverUnsupportedFeatureException(
"Rotate expr with expression argument is not supported by cvc5"
)
}
simplifiedExpr.internalizeExpr()
}
}
override fun transform(expr: KBvRotateLeftIndexedExpr) = with(expr) {
transform(value) { value: Term ->
val rotationOp = tm.mkOp(Kind.BITVECTOR_ROTATE_LEFT, rotationNumber)
tm.mkTerm(rotationOp, value)
}
}
override fun transform(expr: KBvRotateRightIndexedExpr) = with(expr) {
transform(value) { value: Term ->
val rotationOp = tm.mkOp(Kind.BITVECTOR_ROTATE_RIGHT, rotationNumber)
tm.mkTerm(rotationOp, value)
}
}
// custom implementation
@Suppress("MagicNumber")
override fun transform(expr: KBv2IntExpr) = with(expr) {
transform(value) { value: Term ->
// by default, it is unsigned in cvc5
val intTerm = tm.mkTerm(Kind.BITVECTOR_TO_NAT, value)
if (isSigned) {
val size = this.value.sort.sizeBits.toInt()
val modulo = powerOfTwo(size.toUInt())
val maxInt = (powerOfTwo((size - 1).toUInt())) - BigInteger.ONE
val moduloTerm = tm.builder { mkInteger(modulo.toString(10)) }
val maxIntTerm = tm.builder { mkInteger(maxInt.toString(10)) }
val gtTerm = tm.mkTerm(Kind.GT, intTerm, maxIntTerm)
val subTerm = tm.mkTerm(Kind.SUB, intTerm, moduloTerm)
tm.mkTerm(Kind.ITE, gtTerm, subTerm, intTerm)
} else intTerm
}
}
override fun transform(expr: KBvAddNoOverflowExpr) = with(expr) {
transform {
ctx.rewriteBvAddNoOverflowExpr(arg0, arg1, isSigned).internalizeExpr()
}
}
override fun transform(expr: KBvAddNoUnderflowExpr) = with(expr) {
transform {
ctx.rewriteBvAddNoUnderflowExpr(arg0, arg1).internalizeExpr()
}
}
override fun transform(expr: KBvSubNoOverflowExpr) = with(expr) {
transform {
ctx.rewriteBvSubNoOverflowExpr(arg0, arg1).internalizeExpr()
}
}
override fun transform(expr: KBvSubNoUnderflowExpr) = with(expr) {
transform {
ctx.rewriteBvSubNoUnderflowExpr(arg0, arg1, isSigned).internalizeExpr()
}
}
override fun transform(expr: KBvDivNoOverflowExpr) = with(expr) {
transform {
ctx.rewriteBvDivNoOverflowExpr(arg0, arg1).internalizeExpr()
}
}
override fun transform(expr: KBvNegNoOverflowExpr) = with(expr) {
transform {
ctx.rewriteBvNegNoOverflowExpr(value).internalizeExpr()
}
}
override fun transform(expr: KBvMulNoOverflowExpr) = with(expr) {
transform {
ctx.rewriteBvMulNoOverflowExpr(arg0, arg1, isSigned).internalizeExpr()
}
}
override fun transform(expr: KBvMulNoUnderflowExpr) = with(expr) {
transform {
ctx.rewriteBvMulNoUnderflowExpr(arg0, arg1).internalizeExpr()
}
}
private fun fpToBvTerm(signBit: Boolean, biasedExp: KBitVecValue<*>, significand: KBitVecValue<*>): Term {
val signString = if (signBit) "1" else "0"
val expString = biasedExp.stringValue
val significandString = significand.stringValue
val bvString = signString + expString + significandString
return tm.builder { mkBitVector(bvString.length, bvString, 2) }
}
private fun KFpValue.toBitvectorTerm(): Term = fpToBvTerm(signBit, biasedExponent, significand)
private fun > transformFpValue(expr: T): T = with(expr) {
transform {
val bv = expr.toBitvectorTerm()
// created from IEEE-754 bit-vector representation of the floating-point value
tm.builder {
mkFloatingPoint(sort.exponentBits.toInt(), sort.significandBits.toInt(), bv)
}
}
}
override fun transform(expr: KFp16Value): KExpr = transformFpValue(expr)
override fun transform(expr: KFp32Value): KExpr = transformFpValue(expr)
override fun transform(expr: KFp64Value): KExpr = transformFpValue(expr)
override fun transform(expr: KFp128Value): KExpr = transformFpValue(expr)
override fun transform(expr: KFpCustomSizeValue): KExpr = transformFpValue(expr)
override fun transform(expr: KFpRoundingModeExpr): KExpr = with(expr) {
transform {
val rmMode = when (value) {
KFpRoundingMode.RoundNearestTiesToEven -> RoundingMode.ROUND_NEAREST_TIES_TO_EVEN
KFpRoundingMode.RoundNearestTiesToAway -> RoundingMode.ROUND_NEAREST_TIES_TO_AWAY
KFpRoundingMode.RoundTowardPositive -> RoundingMode.ROUND_TOWARD_POSITIVE
KFpRoundingMode.RoundTowardNegative -> RoundingMode.ROUND_TOWARD_NEGATIVE
KFpRoundingMode.RoundTowardZero -> RoundingMode.ROUND_TOWARD_ZERO
}
tm.builder { mkRoundingMode(rmMode) }
}
}
override fun transform(expr: KFpAbsExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_ABS, value)
}
}
override fun transform(expr: KFpNegationExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_NEG, value)
}
}
override fun transform(expr: KFpAddExpr): KExpr = with(expr) {
transform(roundingMode, arg0, arg1) { roundingMode: Term, arg0: Term, arg1: Term ->
tm.mkTerm(
Kind.FLOATINGPOINT_ADD,
roundingMode,
arg0,
arg1
)
}
}
override fun transform(expr: KFpSubExpr): KExpr = with(expr) {
transform(roundingMode, arg0, arg1) { roundingMode: Term, arg0: Term, arg1: Term ->
tm.mkTerm(
Kind.FLOATINGPOINT_SUB,
roundingMode,
arg0,
arg1
)
}
}
override fun transform(expr: KFpMulExpr): KExpr = with(expr) {
transform(roundingMode, arg0, arg1) { roundingMode: Term, arg0: Term, arg1: Term ->
tm.mkTerm(
Kind.FLOATINGPOINT_MULT,
roundingMode,
arg0,
arg1
)
}
}
override fun transform(expr: KFpDivExpr): KExpr = with(expr) {
transform(roundingMode, arg0, arg1) { roundingMode: Term, arg0: Term, arg1: Term ->
tm.mkTerm(
Kind.FLOATINGPOINT_DIV,
roundingMode,
arg0,
arg1
)
}
}
override fun transform(expr: KFpFusedMulAddExpr): KExpr = with(expr) {
transform(roundingMode, arg0, arg1, arg2) { rm: Term, arg0: Term, arg1: Term, arg2: Term ->
tm.mkTerm(
Kind.FLOATINGPOINT_FMA,
arrayOf(rm, arg0, arg1, arg2)
)
}
}
override fun transform(expr: KFpSqrtExpr): KExpr = with(expr) {
transform(roundingMode, value) { roundingMode: Term, value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_SQRT, roundingMode, value)
}
}
override fun transform(expr: KFpRemExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_REM, arg0, arg1)
}
}
override fun transform(expr: KFpRoundToIntegralExpr): KExpr =
with(expr) {
transform(roundingMode, value) { roundingMode: Term, value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_RTI, roundingMode, value)
}
}
override fun transform(expr: KFpMinExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_MIN, arg0, arg1)
}
}
override fun transform(expr: KFpMaxExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_MAX, arg0, arg1)
}
}
override fun transform(expr: KFpLessOrEqualExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_LEQ, arg0, arg1)
}
}
override fun transform(expr: KFpLessExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_LT, arg0, arg1)
}
}
override fun transform(expr: KFpGreaterOrEqualExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_GEQ, arg0, arg1)
}
}
override fun transform(expr: KFpGreaterExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_GT, arg0, arg1)
}
}
override fun transform(expr: KFpEqualExpr): KExpr = with(expr) {
transform(arg0, arg1) { arg0: Term, arg1: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_EQ, arg0, arg1)
}
}
override fun transform(expr: KFpIsNormalExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_IS_NORMAL, value)
}
}
override fun transform(expr: KFpIsSubnormalExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_IS_SUBNORMAL, value)
}
}
override fun transform(expr: KFpIsZeroExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_IS_ZERO, value)
}
}
override fun transform(expr: KFpIsInfiniteExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_IS_INF, value)
}
}
override fun transform(expr: KFpIsNaNExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_IS_NAN, value)
}
}
override fun transform(expr: KFpIsNegativeExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_IS_NEG, value)
}
}
override fun transform(expr: KFpIsPositiveExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_IS_POS, value)
}
}
override fun transform(expr: KFpToBvExpr): KExpr =
with(expr) {
transform(roundingMode, value) { rm: Term, value: Term ->
val opKind = if (isSigned) Kind.FLOATINGPOINT_TO_SBV else Kind.FLOATINGPOINT_TO_UBV
val op = tm.mkOp(opKind, bvSize)
tm.mkTerm(op, rm, value)
}
}
override fun transform(expr: KFpToRealExpr): KExpr = with(expr) {
transform(value) { value: Term ->
tm.mkTerm(Kind.FLOATINGPOINT_TO_REAL, value)
}
}
override fun transform(expr: KFpToIEEEBvExpr): KExpr =
throw KSolverUnsupportedFeatureException("no direct support for $expr")
override fun transform(expr: KFpFromBvExpr): KExpr = with(expr) {
transform(sign, biasedExponent, significand) { sign: Term, biasedExp: Term, significand: Term ->
val bvTerm = tm.mkTerm(
Kind.BITVECTOR_CONCAT,
tm.mkTerm(Kind.BITVECTOR_CONCAT, sign, biasedExp),
significand
)
val toFpOp = tm.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_IEEE_BV,
sort.exponentBits.toInt(),
sort.significandBits.toInt()
)
tm.mkTerm(toFpOp, bvTerm)
}
}
override fun transform(expr: KFpToFpExpr): KExpr = with(expr) {
transform(roundingMode, value) { rm: Term, value: Term ->
val op = tm.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_FP,
sort.exponentBits.toInt(),
sort.significandBits.toInt()
)
tm.mkTerm(op, rm, value)
}
}
override fun transform(expr: KRealToFpExpr): KExpr = with(expr) {
transform(roundingMode, value) { rm: Term, value: Term ->
val op = tm.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_REAL,
sort.exponentBits.toInt(),
sort.significandBits.toInt()
)
tm.mkTerm(op, rm, value)
}
}
override fun transform(expr: KBvToFpExpr): KExpr = with(expr) {
transform(roundingMode, value) { rm: Term, value: Term ->
val opKind = if (signed) Kind.FLOATINGPOINT_TO_FP_FROM_SBV else Kind.FLOATINGPOINT_TO_FP_FROM_UBV
val op = tm.mkOp(
opKind,
sort.exponentBits.toInt(),
sort.significandBits.toInt()
)
tm.mkTerm(op, rm, value)
}
}
override fun transform(expr: KArrayStore) =
expr.transformStore()
override fun transform(
expr: KArray2Store
): KExpr> = expr.transformStore()
override fun transform(
expr: KArray3Store
): KExpr> = expr.transformStore()
override fun transform(expr: KArrayNStore): KExpr> =
expr.transformStore()
private fun > E.transformStore(): E =
transformArray(listOf(array, value) + indices) { transformedArgs: Array ->
val (array, value) = transformedArgs.take(2)
val indices = transformedArgs.drop(2)
mkArrayStoreTerm(array, indices, value)
}
override fun transform(expr: KArraySelect) =
expr.transformSelect()
override fun transform(expr: KArray2Select) =
expr.transformSelect()
override fun transform(
expr: KArray3Select
): KExpr = expr.transformSelect()
override fun transform(expr: KArrayNSelect): KExpr =
expr.transformSelect()
private fun > E.transformSelect(): E =
transformArray(listOf(array) + indices) { transformedArgs: Array ->
val array = transformedArgs.first()
val indices = transformedArgs.drop(1)
mkArraySelectTerm(array, indices)
}
override fun , R : KSort> transform(expr: KArrayConst) = with(expr) {
transform(value) { valueTerm: Term ->
if (value is KInterpretedValue<*> || value is KArrayConst<*, *>) {
// const array base must be a value or a constant array
tm.builder { mkConstArray(sort.internalizeSort(), valueTerm) }
} else {
val bounds = sort.domainSorts.map { tm.builder { mkConst(it.internalizeSort()) } }
mkLambdaTerm(bounds, valueTerm)
}
}
}
override fun transform(expr: KArrayLambda) =
expr.transformLambda()
override fun transform(
expr: KArray2Lambda
): KExpr> =
expr.transformLambda()
override fun transform(
expr: KArray3Lambda
): KExpr> =
expr.transformLambda()
override fun transform(expr: KArrayNLambda): KExpr> =
expr.transformLambda()
private fun > E.transformLambda(): E = transform(body) { bodyTerm: Term ->
val bounds = indexVarDeclarations.map { it.internalizeDecl() }
mkLambdaTerm(bounds, bodyTerm)
}
override fun transform(expr: KAddArithExpr) = with(expr) {
transformArray(args) { args -> tm.mkTerm(Kind.ADD, args) }
}
override fun transform(expr: KSubArithExpr) = with(expr) {
transformArray(args) { args -> tm.mkTerm(Kind.SUB, args) }
}
override fun transform(expr: KMulArithExpr) = with(expr) {
transformArray(args) { args -> tm.mkTerm(Kind.MULT, args) }
}
override fun transform(expr: KUnaryMinusArithExpr) = with(expr) {
transform(arg) { arg: Term -> tm.mkTerm(Kind.NEG, arg) }
}
override fun