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

hu.bme.mit.theta.xsts.analysis.XstsToRelations.kt Maven / Gradle / Ivy

There is a newer version: 6.5.2
Show newest version
/*
 *  Copyright 2024 Budapest University of Technology and Economics
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package hu.bme.mit.theta.xsts.analysis

import hu.bme.mit.theta.core.Relation
import hu.bme.mit.theta.core.decl.Decls.Param
import hu.bme.mit.theta.core.decl.Decls.Var
import hu.bme.mit.theta.core.decl.VarDecl
import hu.bme.mit.theta.core.plus
import hu.bme.mit.theta.core.type.Expr
import hu.bme.mit.theta.core.type.anytype.PrimeExpr
import hu.bme.mit.theta.core.type.anytype.RefExpr
import hu.bme.mit.theta.core.type.booltype.BoolType
import hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.And
import hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.Not
import hu.bme.mit.theta.core.type.enumtype.EnumEqExpr
import hu.bme.mit.theta.core.type.enumtype.EnumLitExpr
import hu.bme.mit.theta.core.type.enumtype.EnumNeqExpr
import hu.bme.mit.theta.core.type.enumtype.EnumType
import hu.bme.mit.theta.core.type.inttype.IntEqExpr
import hu.bme.mit.theta.core.type.inttype.IntExprs.Int
import hu.bme.mit.theta.core.type.inttype.IntLitExpr
import hu.bme.mit.theta.core.type.inttype.IntNeqExpr
import hu.bme.mit.theta.core.type.inttype.IntType
import hu.bme.mit.theta.core.utils.ExprUtils
import hu.bme.mit.theta.core.utils.PathUtils
import hu.bme.mit.theta.core.utils.StmtUtils
import hu.bme.mit.theta.core.utils.indexings.VarIndexing
import hu.bme.mit.theta.core.utils.indexings.VarIndexingFactory
import hu.bme.mit.theta.xsts.XSTS
import java.math.BigInteger


fun XSTS.toRelations(): List {
    val enumValueLut = LinkedHashMap>()
    val varChangeMap = LinkedHashMap, VarDecl<*>>()
    var cnt = 0
    fun Expr<*>.replaceEnums(): Expr<*> {
        if (type is EnumType) {
            when (this) {
                is EnumLitExpr -> {
                    val value =
                        enumValueLut.computeIfAbsent(this.type) { LinkedHashMap() }.computeIfAbsent(
                            this.value) { cnt++ }
                    return IntLitExpr.of(BigInteger.valueOf(value.toLong()))
                }

                is RefExpr -> {
                    return varChangeMap.computeIfAbsent(decl as VarDecl) { Var(this.decl.name, Int()) }.ref
                }

                is PrimeExpr -> {
                    return PrimeExpr.of(op.replaceEnums())
                }

                else -> error("I expect that only EnumLiterals and RefExprs may have EnumType")
            }
        } else if (this is EnumEqExpr) {
            return IntEqExpr.of(leftOp.replaceEnums() as Expr, rightOp.replaceEnums() as Expr);
        } else if (this is EnumNeqExpr) {
            return IntNeqExpr.of(leftOp.replaceEnums() as Expr, rightOp.replaceEnums() as Expr);
        } else {
            return this.map(Expr<*>::replaceEnums)
        }
    }

    fun VarIndexing.replaceEnums() = transform().copyVars(varChangeMap).build()


    val initUnfoldResult = StmtUtils.toExpr(this.init, VarIndexingFactory.indexing(0))
    val initExpr = And(And(initUnfoldResult.exprs), this.initFormula).replaceEnums() as Expr
    val initOffsetIndex = initUnfoldResult.indexing.replaceEnums()

    val envUnfoldResult = StmtUtils.toExpr(env, VarIndexingFactory.indexing(0));
    val envExpr = And(envUnfoldResult.exprs).replaceEnums() as Expr
    val envOffsetIndex = envUnfoldResult.indexing.replaceEnums()

    val tranUnfoldResult = StmtUtils.toExpr(tran, VarIndexingFactory.indexing(0));
    val tranExpr = And(tranUnfoldResult.exprs).replaceEnums() as Expr
    val tranOffsetIndex = tranUnfoldResult.indexing.replaceEnums()

    val propExpr = this.prop.replaceEnums() as Expr

    val vars = vars.map { varChangeMap[it] ?: it }

    val types = vars.map { it.type }.toTypedArray()
    val oldParams = vars.associateWith { Param("|" + it.name + "|", it.type) }
    val oldParamList = vars.map { oldParams[it]!!.ref }.toTypedArray()
    val newParams = vars.associateWith { Param("|" + it.name + "_new|", it.type) }

    fun toRelation(
        rel: Relation,
        prevRels: List,
        notUnfoldedExpr: Expr,
        indexing: VarIndexing,
        vars: List>
    ): Relation {

        val expr = PathUtils.unfold(notUnfoldedExpr, VarIndexingFactory.indexing(0))

        // var[0] is oldParam, var[-1]is newParam, everything else is a fresh param
        var cnt = 0
        val consts = ExprUtils.getIndexedConstants(expr).associateWith {
            if (it.index == 0 && oldParams.containsKey(it.varDecl)) oldParams[it.varDecl]!!
            else if (it.index == indexing[it.varDecl] && newParams.containsKey(it.varDecl)) newParams[it.varDecl]!!
            else Param("__tmp_${cnt++}", it.type)
        }
        val newParamList = vars.map { if (indexing[it] == 0) oldParams[it]!!.ref else newParams[it]!!.ref }
            .toTypedArray()
        val paramdExpr = ExprUtils.changeDecls(expr, consts)
        if (prevRels.isEmpty()) {
            rel(*newParamList) += paramdExpr
        } else {
            for (prevRel in prevRels) {
                rel(*newParamList) += prevRel(*oldParamList).expr + paramdExpr
            }
        }
        return rel
    }

    val init = Relation("init", *types)
    val env = Relation("env", *types)
    val tran = Relation("tran", *types)

    toRelation(init, listOf(), initExpr, initOffsetIndex, vars.toList())
    toRelation(env, listOf(init, tran), envExpr, envOffsetIndex, vars.toList())
    toRelation(tran, listOf(env), tranExpr, tranOffsetIndex, vars.toList())
    !(tran(*oldParamList) with ExprUtils.changeDecls(Not(propExpr), oldParams))

    return listOf(init, tran, env)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy