All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.io.ksmt.solver.yices.KYicesExprInternalizer.kt Maven / Gradle / Ivy

There is a newer version: 0.5.26
Show newest version
package io.ksmt.solver.yices

import com.sri.yices.Constructor
import com.sri.yices.Terms
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.KArrayStore
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.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.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.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.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.rewriteBvMulNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvMulNoUnderflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvNegNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvSubNoOverflowExpr
import io.ksmt.expr.rewrite.simplify.rewriteBvSubNoUnderflowExpr
import io.ksmt.solver.KSolverUnsupportedFeatureException
import io.ksmt.solver.util.KExprIntInternalizerBase
import io.ksmt.sort.KArithSort
import io.ksmt.sort.KArray2Sort
import io.ksmt.sort.KArray3Sort
import io.ksmt.sort.KArrayNSort
import io.ksmt.sort.KArraySort
import io.ksmt.sort.KArraySortBase
import io.ksmt.sort.KBoolSort
import io.ksmt.sort.KBv16Sort
import io.ksmt.sort.KBv1Sort
import io.ksmt.sort.KBv32Sort
import io.ksmt.sort.KBv64Sort
import io.ksmt.sort.KBv8Sort
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.KIntSort
import io.ksmt.sort.KRealSort
import io.ksmt.sort.KSort
import io.ksmt.sort.KUninterpretedSort
import java.math.BigInteger

@Suppress("LargeClass")
open class KYicesExprInternalizer(
    private val yicesCtx: KYicesContext,
) : KExprIntInternalizerBase() {

    private val sortInternalizer: KYicesSortInternalizer by lazy {
        KYicesSortInternalizer(yicesCtx)
    }

    private val declSortInternalizer: KYicesDeclSortInternalizer by lazy {
        KYicesDeclSortInternalizer(yicesCtx, sortInternalizer)
    }

    override fun findInternalizedExpr(expr: KExpr<*>) = yicesCtx.findInternalizedExpr(expr)

    override fun saveInternalizedExpr(expr: KExpr<*>, internalized: YicesTerm) {
        yicesCtx.saveInternalizedExpr(expr, internalized)
    }

    fun  KExpr.internalize(): YicesTerm = try {
        internalizeExpr()
    } finally {
        resetInternalizer()
    }

    fun > T.internalizeDecl(): YicesTerm = yicesCtx.internalizeDecl(this) {
        val sort = declSortInternalizer.internalizeYicesDeclSort(this)
        yicesCtx.newUninterpretedTerm(name, sort)
    }

    private fun > T.internalizeVariable(): YicesTerm = yicesCtx.internalizeVar(this) {
        val sort = declSortInternalizer.internalizeYicesDeclSort(this)
        yicesCtx.newVariable(name, sort)
    }

    private fun  T.internalizeSort(): YicesSort =
        sortInternalizer.internalizeYicesSort(this)

    override fun  transform(expr: KFunctionApp): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray ->
            if (args.isNotEmpty()) {
                yicesCtx.funApplication(decl.internalizeDecl(), args)
            } else {
                decl.internalizeDecl()
            }
        }
    }

    override fun  transform(expr: KConst): KExpr = with(expr) {
        transform { decl.internalizeDecl() }
    }

    override fun transform(expr: KAndExpr): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray ->
            yicesCtx.and(args)
        }
    }

    override fun transform(expr: KAndBinaryExpr): KExpr = with(expr) {
        transform(lhs, rhs) { l: YicesTerm, r: YicesTerm ->
            yicesCtx.and(intArrayOf(l, r))
        }
    }

    override fun transform(expr: KOrExpr): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray -> yicesCtx.or(args) }
    }

    override fun transform(expr: KOrBinaryExpr): KExpr = with(expr) {
        transform(lhs, rhs) { l: YicesTerm, r: YicesTerm ->
            yicesCtx.or(intArrayOf(l, r))
        }
    }

    override fun transform(expr: KNotExpr): KExpr = with(expr) {
        transform(arg, yicesCtx::not)
    }

    override fun transform(expr: KImpliesExpr): KExpr = with(expr) {
        transform(p, q, yicesCtx::implies)
    }

    override fun transform(expr: KXorExpr): KExpr = with(expr) {
        transform(a, b) { a: YicesTerm, b: YicesTerm -> yicesCtx.xor(a, b) }
    }

    override fun transform(expr: KTrue): KExpr = expr.transform(yicesCtx::mkTrue)

    override fun transform(expr: KFalse): KExpr = expr.transform(yicesCtx::mkFalse)

    override fun  transform(expr: KEqExpr): KExpr = with(expr) {
        transform(lhs, rhs) { l: YicesTerm, r: YicesTerm ->
            internalizeEqExpr(lhs.sort, l, r)
        }
    }

    override fun  transform(expr: KDistinctExpr): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray ->
            if (args.isEmpty()) {
                yicesCtx.mkTrue()
            } else {
                internalizeDistinctExpr(expr.args.first().sort, args)
            }
        }
    }

    override fun  transform(expr: KIteExpr): KExpr = with(expr) {
        transform(condition, trueBranch, falseBranch) { c: YicesTerm, t: YicesTerm, f: YicesTerm ->
            internalizeIteExpr(sort, c, t, f)
        }
    }

    private fun internalizeIteExpr(
        sort: KSort,
        condition: YicesTerm,
        trueBranch: YicesTerm,
        falseBranch: YicesTerm
    ): YicesTerm = if (sort is KArraySortBase<*>) {
        mkArrayIteTerm(sort, condition, trueBranch, falseBranch)
    } else {
        yicesCtx.ifThenElse(condition, trueBranch, falseBranch)
    }

    private fun internalizeEqExpr(
        sort: KSort,
        lhs: YicesTerm,
        rhs: YicesTerm
    ): YicesTerm = if (sort is KArraySortBase<*>) {
        mkArrayEqTerm(lhs, rhs)
    } else {
        yicesCtx.eq(lhs, rhs)
    }

    private fun internalizeDistinctExpr(
        sort: KSort,
        args: YicesTermArray
    ): YicesTerm = if (sort is KArraySortBase<*>) {
        mkArrayDistinctTerm(args)
    } else {
        yicesCtx.distinct(args)
    }

    override fun transform(expr: KBitVec1Value): KExpr = with(expr) {
        transform { yicesCtx.bvConst(sort.sizeBits, if (value) 1L else 0L) }
    }

    override fun transform(expr: KBitVec8Value): KExpr = with(expr) {
        transform { yicesCtx.bvConst(sort.sizeBits, byteValue.toLong()) }
    }

    override fun transform(expr: KBitVec16Value): KExpr = with(expr) {
        transform { yicesCtx.bvConst(sort.sizeBits, shortValue.toLong()) }
    }

    override fun transform(expr: KBitVec32Value): KExpr = with(expr) {
        transform { yicesCtx.bvConst(sort.sizeBits, intValue.toLong()) }
    }

    override fun transform(expr: KBitVec64Value): KExpr = with(expr) {
        transform { yicesCtx.bvConst(sort.sizeBits, longValue) }
    }

    override fun transform(expr: KBitVecCustomValue): KExpr = with(expr) {
        transform { yicesCtx.parseBvBin(stringValue) }
    }

    override fun  transform(expr: KBvNotExpr): KExpr = with(expr) {
        transform(value, yicesCtx::bvNot)
    }

    override fun  transform(expr: KBvReductionAndExpr): KExpr = with(expr) {
        transform(value, yicesCtx::bvRedAnd)
    }

    override fun  transform(expr: KBvReductionOrExpr): KExpr = with(expr) {
        transform(value, yicesCtx::bvRedOr)
    }

    override fun  transform(expr: KBvAndExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvAnd)
    }

    override fun  transform(expr: KBvOrExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvOr)
    }

    override fun  transform(expr: KBvXorExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvXor)
    }

    override fun  transform(expr: KBvNAndExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvNand)
    }

    override fun  transform(expr: KBvNorExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvNor)
    }

    override fun  transform(expr: KBvXNorExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvXNor)
    }

    override fun  transform(expr: KBvNegationExpr): KExpr = with(expr) {
        transform(value, yicesCtx::bvNeg)
    }

    override fun  transform(expr: KBvAddExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvAdd)
    }

    override fun  transform(expr: KBvSubExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSub)
    }

    override fun  transform(expr: KBvMulExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvMul)
    }

    override fun  transform(expr: KBvUnsignedDivExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvDiv)
    }

    override fun  transform(expr: KBvSignedDivExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSDiv)
    }

    override fun  transform(expr: KBvUnsignedRemExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvRem)
    }

    override fun  transform(expr: KBvSignedRemExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSRem)
    }

    override fun  transform(expr: KBvSignedModExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSMod)
    }

    override fun  transform(expr: KBvUnsignedLessExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvLt)
    }

    override fun  transform(expr: KBvSignedLessExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSLt)
    }

    override fun  transform(expr: KBvUnsignedLessOrEqualExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvLe)
    }

    override fun  transform(expr: KBvSignedLessOrEqualExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSLe)
    }

    override fun  transform(expr: KBvUnsignedGreaterOrEqualExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvGe)
    }

    override fun  transform(expr: KBvSignedGreaterOrEqualExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSGe)
    }

    override fun  transform(expr: KBvUnsignedGreaterExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvGt)
    }

    override fun  transform(expr: KBvSignedGreaterExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvSGt)
    }

    override fun transform(expr: KBvConcatExpr): KExpr = with(expr) {
        transform(arg0, arg1, yicesCtx::bvConcat)
    }

    override fun transform(expr: KBvExtractExpr): KExpr = with(expr) {
        transform(value) { value: YicesTerm -> yicesCtx.bvExtract(value, low, high) }
    }

    override fun transform(expr: KBvSignExtensionExpr): KExpr = with(expr) {
        transform(value) { value: YicesTerm -> yicesCtx.bvSignExtend(value, extensionSize) }
    }

    override fun transform(expr: KBvZeroExtensionExpr): KExpr = with(expr) {
        transform(value) { value: YicesTerm -> yicesCtx.bvZeroExtend(value, extensionSize) }
    }

    override fun transform(expr: KBvRepeatExpr): KExpr = with(expr) {
        transform(value) { value: YicesTerm -> yicesCtx.bvRepeat(value, repeatNumber) }
    }

    override fun  transform(expr: KBvShiftLeftExpr): KExpr = with(expr) {
        transform(arg, shift, yicesCtx::bvShl)
    }

    override fun  transform(expr: KBvLogicalShiftRightExpr): KExpr = with(expr) {
        transform(arg, shift, yicesCtx::bvLshr)
    }

    override fun  transform(expr: KBvArithShiftRightExpr): KExpr = with(expr) {
        transform(arg, shift, yicesCtx::bvAshr)
    }

    override fun  transform(expr: KBvRotateLeftExpr): KExpr = with(expr) {
        transform(arg, rotation) { arg0: YicesTerm, arg1: YicesTerm ->
            val size = expr.sort.sizeBits
            val bvSize = yicesCtx.bvConst(size, size.toLong())
            val rotationNumber = yicesCtx.bvRem(arg1, bvSize)

            val left = yicesCtx.bvShl(arg0, rotationNumber)
            val right = yicesCtx.bvLshr(arg0, yicesCtx.bvSub(bvSize, rotationNumber))

            yicesCtx.bvOr(left, right)
        }
    }

    override fun  transform(expr: KBvRotateLeftIndexedExpr): KExpr = with(expr) {
        transform(value) { value: YicesTerm -> yicesCtx.bvRotateLeft(value, rotationNumber) }
    }

    override fun  transform(expr: KBvRotateRightExpr): KExpr = with(expr) {
        transform(arg, rotation) { arg0: YicesTerm, arg1: YicesTerm ->
            val size = expr.sort.sizeBits
            val bvSize = yicesCtx.bvConst(size, size.toLong())
            val rotationNumber = yicesCtx.bvRem(arg1, bvSize)

            val left = yicesCtx.bvShl(arg0, yicesCtx.bvSub(bvSize, rotationNumber))
            val right = yicesCtx.bvLshr(arg0, rotationNumber)

            yicesCtx.bvOr(left, right)
        }
    }


    override fun  transform(expr: KBvRotateRightIndexedExpr): KExpr = with(expr) {
        transform(value) { value: YicesTerm -> yicesCtx.bvRotateRight(value, rotationNumber) }
    }

    override fun transform(expr: KBv2IntExpr): KExpr = with(expr) {
        transform(value) { value: YicesTerm ->
            val size = expr.value.sort.sizeBits.toInt()

            val args = (0 until size - 1).map {
                yicesCtx.ifThenElse(
                    yicesCtx.bvExtractBit(value, it),
                    yicesCtx.intConst(BigInteger.valueOf(2).pow(it)),
                    yicesCtx.zero
                )
            }

            var sign = yicesCtx.ifThenElse(
                yicesCtx.bvExtractBit(value, size - 1),
                yicesCtx.intConst(BigInteger.valueOf(2).pow(size - 1)),
                yicesCtx.zero
            )

            if (isSigned)
                sign = yicesCtx.neg(sign)

            yicesCtx.add((args + sign).toIntArray())
        }
    }

    override fun  transform(expr: KBvAddNoOverflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvAddNoOverflowExpr(arg0, arg1, isSigned).internalizeExpr()
        }
    }

    override fun  transform(expr: KBvAddNoUnderflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvAddNoUnderflowExpr(arg0, arg1).internalizeExpr()
        }
    }

    override fun  transform(expr: KBvSubNoOverflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvSubNoOverflowExpr(arg0, arg1).internalizeExpr()
        }
    }

    override fun  transform(expr: KBvSubNoUnderflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvSubNoUnderflowExpr(arg0, arg1, isSigned).internalizeExpr()
        }
    }

    override fun  transform(expr: KBvDivNoOverflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvDivNoOverflowExpr(arg0, arg1).internalizeExpr()
        }
    }

    override fun  transform(expr: KBvNegNoOverflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvNegNoOverflowExpr(value).internalizeExpr()
        }
    }

    override fun  transform(expr: KBvMulNoOverflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvMulNoOverflowExpr(arg0, arg1, isSigned).internalizeExpr()
        }
    }

    override fun  transform(expr: KBvMulNoUnderflowExpr): KExpr = with(expr) {
        transform {
            ctx.rewriteBvMulNoUnderflowExpr(arg0, arg1).internalizeExpr()
        }
    }

    override fun transform(expr: KFp16Value): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun transform(expr: KFp32Value): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun transform(expr: KFp64Value): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun transform(expr: KFp128Value): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun transform(expr: KFpCustomSizeValue): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun transform(expr: KFpRoundingModeExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpAbsExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpNegationExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpAddExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpSubExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpMulExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpDivExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpFusedMulAddExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpSqrtExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpRemExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpRoundToIntegralExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpMinExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpMaxExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpLessOrEqualExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpLessExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpGreaterOrEqualExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpGreaterExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpEqualExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpIsNormalExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpIsSubnormalExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpIsZeroExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpIsInfiniteExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpIsNaNExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpIsNegativeExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpIsPositiveExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpToBvExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpToRealExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpToIEEEBvExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpFromBvExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KFpToFpExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KRealToFpExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KBvToFpExpr): KExpr {
        throw KSolverUnsupportedFeatureException("Unsupported expr $expr")
    }

    override fun  transform(expr: KArrayStore): KExpr> = with(expr) {
        transform(array, index, value) { a: YicesTerm, index: YicesTerm, v: YicesTerm ->
            mkArrayStoreTerm(a, intArrayOf(index), v)
        }
    }

    override fun  transform(
        expr: KArray2Store
    ): KExpr> = with(expr) {
        transform(array, index0, index1, value) { a: YicesTerm, i0: YicesTerm, i1: YicesTerm, v: YicesTerm ->
            mkArrayStoreTerm(a, intArrayOf(i0, i1), v)
        }
    }

    override fun  transform(
        expr: KArray3Store
    ): KExpr> = with(expr) {
        transformList(listOf(array, value, index0, index1, index2)) { args: YicesTermArray ->
            mkArrayStoreTerm(
                array = args[0],
                indices = args.copyOfRange(fromIndex = 2, toIndex = args.size),
                value = args[1]
            )
        }
    }

    override fun  transform(
        expr: KArrayNStore
    ): KExpr> = with(expr) {
        transformList(listOf(array, value) + indices) { args: YicesTermArray ->
            mkArrayStoreTerm(
                array = args[0],
                indices = args.copyOfRange(fromIndex = 2, toIndex = args.size),
                value = args[1]
            )
        }
    }

    override fun  transform(expr: KArraySelect): KExpr = with(expr) {
        transform(array, index) { array: YicesTerm, index: YicesTerm ->
            yicesCtx.funApplication(array, index)
        }
    }

    override fun  transform(
        expr: KArray2Select
    ): KExpr = with(expr) {
        transform(array, index0, index1) { a: YicesTerm, i0: YicesTerm, i1: YicesTerm ->
            yicesCtx.funApplication(a, intArrayOf(i0, i1))
        }
    }

    override fun  transform(
        expr: KArray3Select
    ): KExpr = with(expr) {
        transform(array, index0, index1, index2) { a: YicesTerm, i0: YicesTerm, i1: YicesTerm, i2: YicesTerm ->
            yicesCtx.funApplication(a, intArrayOf(i0, i1, i2))
        }
    }

    override fun  transform(expr: KArrayNSelect): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray ->
            yicesCtx.funApplication(
                func = args[0],
                args = args.copyOfRange(fromIndex = 1, toIndex = args.size)
            )
        }
    }

    override fun , R : KSort> transform(
        expr: KArrayConst
    ): KExpr = with(expr) {
        transform(value) { value: YicesTerm ->
            val bounds = sort.domainSorts.let { domain ->
                IntArray(domain.size) { yicesCtx.newVariable(domain[it].internalizeSort()) }
            }
            yicesCtx.lambda(bounds, value)
        }
    }

    override fun , R : KSort> transform(expr: KFunctionAsArray): KExpr = with(expr) {
        transform { function.internalizeDecl() }
    }

    override fun  transform(expr: KArrayLambda): KExpr> =
        expr.transformArrayLambda()

    override fun  transform(
        expr: KArray2Lambda
    ): KExpr> =
        expr.transformArrayLambda()

    override fun  transform(
        expr: KArray3Lambda
    ): KExpr> =
        expr.transformArrayLambda()

    override fun  transform(expr: KArrayNLambda): KExpr> =
        expr.transformArrayLambda()

    private fun > L.transformArrayLambda(): L =
        internalizeQuantifiedBody(indexVarDeclarations, body) { vars, body ->
            yicesCtx.lambda(vars, body)
        }

    override fun  transform(expr: KAddArithExpr): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray -> yicesCtx.add(args) }
    }

    override fun  transform(expr: KMulArithExpr): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray -> yicesCtx.mul(args) }
    }

    override fun  transform(expr: KSubArithExpr): KExpr = with(expr) {
        transformList(args) { args: YicesTermArray ->
            if (args.size == 1) {
                args.first()
            } else {
                val argsToAdd = args.copyOfRange(fromIndex = 1, toIndex = args.size)
                yicesCtx.sub(args[0], yicesCtx.add(argsToAdd))
            }
        }
    }

    override fun  transform(expr: KUnaryMinusArithExpr): KExpr = with(expr) {
        transform(arg, yicesCtx::neg)
    }

    override fun  transform(expr: KDivArithExpr): KExpr = with(expr) {
        transform(lhs, rhs) { lhs: YicesTerm, rhs: YicesTerm ->
            when (sort) {
                is KIntSort -> yicesCtx.idiv(lhs, rhs)
                else -> yicesCtx.div(lhs, rhs)
            }
        }
    }

    override fun  transform(expr: KPowerArithExpr): KExpr = with(expr) {
        transform(lhs, rhs, yicesCtx::power)
    }

    override fun  transform(expr: KLtArithExpr): KExpr = with(expr) {
        transform(lhs, rhs, yicesCtx::arithLt)
    }

    override fun  transform(expr: KLeArithExpr): KExpr = with(expr) {
        transform(lhs, rhs, yicesCtx::arithLeq)
    }

    override fun  transform(expr: KGtArithExpr): KExpr = with(expr) {
        transform(lhs, rhs, yicesCtx::arithGt)
    }

    override fun  transform(expr: KGeArithExpr): KExpr = with(expr) {
        transform(lhs, rhs, yicesCtx::arithGeq)
    }

    override fun transform(expr: KModIntExpr): KExpr = with(expr) {
        transform(lhs, rhs, yicesCtx::imod)
    }

    override fun transform(expr: KRemIntExpr): KExpr = with(expr) {
        transform(lhs, rhs) { lhs: YicesTerm, rhs: YicesTerm ->
            val sign = yicesCtx.ifThenElse(yicesCtx.arithLeq0(rhs), yicesCtx.minusOne, yicesCtx.one)
            val mod = yicesCtx.imod(lhs, rhs)

            yicesCtx.mul(mod, sign)
        }
    }

    override fun transform(expr: KToRealIntExpr): KExpr = with(expr) {
        /**
         * Yices doesn't distinguish between IntSort and RealSort
         */
        transform(arg) { arg: YicesTerm ->
            arg
        }
    }

    override fun transform(expr: KInt32NumExpr): KExpr = with(expr) {
        transform { yicesCtx.intConst(value.toLong()) }
    }

    override fun transform(expr: KInt64NumExpr): KExpr = with(expr) {
        transform { yicesCtx.intConst(value) }
    }

    override fun transform(expr: KIntBigNumExpr): KExpr = with(expr) {
        transform { yicesCtx.intConst(value) }
    }

    override fun transform(expr: KToIntRealExpr): KExpr = with(expr) {
        transform(arg, yicesCtx::floor)
    }

    override fun transform(expr: KIsIntRealExpr): KExpr = with(expr) {
        transform(arg, yicesCtx::isInt)
    }

    override fun transform(expr: KRealNumExpr): KExpr = with(expr) {
        transform(numerator, denominator) { numerator: YicesTerm, denominator: YicesTerm ->
            yicesCtx.div(numerator, denominator)
        }
    }

    override fun transform(expr: KExistentialQuantifier): KExpr = with(expr) {
        internalizeQuantifiedBody(bounds, body) { vars, body ->
            yicesCtx.exists(vars, body)
        }
    }

    override fun transform(expr: KUniversalQuantifier): KExpr = with(expr) {
        internalizeQuantifiedBody(bounds, body) { vars, body ->
            yicesCtx.forall(vars, body)
        }
    }

    override fun transform(expr: KUninterpretedSortValue): KExpr = with(expr) {
        transform {
            yicesCtx.uninterpretedSortConst(
                sort.internalizeSort(),
                yicesCtx.uninterpretedSortValueIndex(valueIdx)
            )
        }
    }

    private inline fun > E.internalizeQuantifiedBody(
        quantifiedDecls: List>,
        quantifierBody: KExpr<*>,
        internalizer: (YicesTermArray, YicesTerm) -> YicesTerm
    ): E = transform(quantifierBody) { body: YicesTerm ->
        val consts = IntArray(quantifiedDecls.size)
        val vars = IntArray(quantifiedDecls.size)

        for (i in quantifiedDecls.indices) {
            val decl = quantifiedDecls[i]
            consts[i] = decl.internalizeDecl()
            vars[i] = decl.internalizeVariable()
        }

        val bodyWithVars = yicesCtx.substitute(
            term = body,
            substituteFrom = consts,
            substituteTo = vars
        )

        internalizer(vars, bodyWithVars)
    }

    private fun mkArrayStoreTerm(
        array: YicesTerm,
        indices: YicesTermArray,
        value: YicesTerm
    ): YicesTerm {
        if (!array.isLambda()) {
            return yicesCtx.functionUpdate(array, indices, value)
        }

        val indicesSorts = IntArray(indices.size) { Terms.typeOf(indices[it]) }
        return mkArrayIteLambdaTerm(
            indicesSorts = indicesSorts,
            mkCondition = { boundVars ->
                val indexEqualities = IntArray(indices.size) {
                    yicesCtx.eq(indices[it], boundVars[it])
                }
                yicesCtx.and(indexEqualities)
            },
            mkTrueBranch = { value },
            mkFalseBranch = { boundVars -> yicesCtx.funApplication(array, boundVars) }
        )
    }

    private fun mkArrayIteTerm(
        sort: KArraySortBase<*>,
        condition: YicesTerm,
        trueBranch: YicesTerm,
        falseBranch: YicesTerm
    ): YicesTerm {
        if (!trueBranch.isLambda() && !falseBranch.isLambda()) {
            return yicesCtx.ifThenElse(condition, trueBranch, falseBranch)
        }

        val indicesSorts = sort.domainSorts.let { domain ->
            IntArray(domain.size) { domain[it].internalizeSort() }
        }
        return mkArrayIteLambdaTerm(
            indicesSorts = indicesSorts,
            mkCondition = { condition },
            mkTrueBranch = { boundVars -> yicesCtx.funApplication(trueBranch, boundVars) },
            mkFalseBranch = { boundVars -> yicesCtx.funApplication(falseBranch, boundVars) }
        )
    }

    private fun mkArrayEqTerm(lhs: YicesTerm, rhs: YicesTerm): YicesTerm {
        if (!lhs.isLambda() && !rhs.isLambda()) {
            return yicesCtx.eq(lhs, rhs)
        }

        throw KSolverUnsupportedFeatureException("Yices doesn't support equalities with lambda expressions")
    }

    private fun mkArrayDistinctTerm(args: YicesTermArray): YicesTerm {
        if (args.all { !it.isLambda() }) {
            return yicesCtx.distinct(args)
        }

        // Blast array distinct
        val inequalities = mutableListOf()
        for (i in args.indices) {
            for (j in (i + 1) until args.size) {
                val equality = mkArrayEqTerm(args[i], args[j])
                inequalities += yicesCtx.not(equality)
            }
        }

        return yicesCtx.and(inequalities.toIntArray())
    }

    private fun YicesTerm.isLambda(): Boolean =
        Terms.constructor(this) == Constructor.LAMBDA_TERM

    private inline fun mkArrayIteLambdaTerm(
        indicesSorts: YicesSortArray,
        mkCondition: (YicesTermArray) -> YicesTerm,
        mkTrueBranch: (YicesTermArray) -> YicesTerm,
        mkFalseBranch: (YicesTermArray) -> YicesTerm
    ): YicesTerm {
        val lambdaBoundVars = IntArray(indicesSorts.size) {
            yicesCtx.newVariable(indicesSorts[it])
        }
        val condition = mkCondition(lambdaBoundVars)
        val trueBranch = mkTrueBranch(lambdaBoundVars)
        val falseBranch = mkFalseBranch(lambdaBoundVars)

        val lambdaBody = yicesCtx.ifThenElse(condition, trueBranch, falseBranch)
        return yicesCtx.lambda(lambdaBoundVars, lambdaBody)
    }

    private fun resetInternalizer() {
        exprStack.clear()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy