org.sosy_lab.cpachecker.cpa.sign.SignState.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.cpa.sign.SignState.java

Source

/*
 *  CPAchecker is a tool for configurable software verification.
 *  This file is part of CPAchecker.
 *
 *  Copyright (C) 2007-2014  Dirk Beyer
 *  All rights reserved.
 *
 *  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.
 *
 *
 *  CPAchecker web page:
 *    http://cpachecker.sosy-lab.org
 */
package org.sosy_lab.cpachecker.cpa.sign;

import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.List;

import org.sosy_lab.common.collect.PathCopyingPersistentTreeMap;
import org.sosy_lab.common.collect.PersistentMap;
import org.sosy_lab.cpachecker.core.defaults.LatticeAbstractState;
import org.sosy_lab.cpachecker.core.interfaces.AbstractQueryableState;
import org.sosy_lab.cpachecker.core.interfaces.Graphable;
import org.sosy_lab.cpachecker.exceptions.InvalidQueryException;
import org.sosy_lab.cpachecker.util.CheckTypesOfStringsUtil;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;

public class SignState implements Serializable, LatticeAbstractState<SignState>, AbstractQueryableState, Graphable {

    private static final long serialVersionUID = -2507059869178203119L;

    private static final boolean DEBUG = false;

    private static final Splitter propertySplitter = Splitter.on("<=").trimResults();

    private PersistentMap<String, SIGN> signMap;

    public final static SignState TOP = new SignState();
    private final static SerialProxySign proxy = new SerialProxySign();

    private SignState(PersistentMap<String, SIGN> pSignMap) {
        signMap = pSignMap;
    }

    private SignState() {
        signMap = PathCopyingPersistentTreeMap.of();
    }

    @Override
    public SignState join(SignState pToJoin) {
        if (pToJoin.equals(this)) {
            return pToJoin;
        }
        if (this.equals(TOP) || pToJoin.equals(TOP)) {
            return TOP;
        }

        // assure termination of loops do not merge if  pToJoin covers this but return pToJoin
        if (isLessOrEqual(pToJoin)) {
            return pToJoin;
        }

        SignState result = SignState.TOP;
        PersistentMap<String, SIGN> newMap = PathCopyingPersistentTreeMap.of();
        SIGN combined;
        for (String varIdent : pToJoin.signMap.keySet()) {
            // only add those variables that are contained in both states (otherwise one has value ALL (not saved))
            if (signMap.containsKey(varIdent)) {
                combined = getSignForVariable(varIdent).combineWith(pToJoin.getSignForVariable(varIdent));
                if (!combined.isAll()) {
                    newMap = newMap.putAndCopy(varIdent, combined);
                }
            }
        }

        return newMap.size() > 0 ? new SignState(newMap) : result;
    }

    @Override
    public boolean isLessOrEqual(SignState pSuperset) {
        if (pSuperset.equals(this) || pSuperset.equals(TOP)) {
            return true;
        }
        if (signMap.size() < pSuperset.signMap.size()) {
            return false;
        }
        // is subset if for every variable all sign assumptions are considered in pSuperset
        // check that all variables in superset with SIGN != ALL have no bigger assumptions in subset
        for (String varIdent : pSuperset.signMap.keySet()) {
            if (!getSignForVariable(varIdent).isSubsetOf(pSuperset.getSignForVariable(varIdent))) {
                return false;
            }
        }
        return true;
    }

    public SignState enterFunction(ImmutableMap<String, SIGN> pArguments) {
        PersistentMap<String, SIGN> newMap = signMap;

        for (String var : pArguments.keySet()) {
            if (!pArguments.get(var).equals(SIGN.ALL)) {
                newMap = newMap.putAndCopy(var, pArguments.get(var));
            }
        }

        return signMap == newMap ? this : new SignState(newMap);
    }

    public SignState leaveFunction(String pFunctionName) {
        PersistentMap<String, SIGN> newMap = signMap;

        for (String var : signMap.keySet()) {
            if (var.startsWith(pFunctionName + "::")) {
                newMap = newMap.removeAndCopy(var);
            }
        }

        return newMap == signMap ? this : new SignState(newMap);
    }

    public SignState assignSignToVariable(String pVarIdent, SIGN sign) {
        if (sign.isAll()) {
            return signMap.containsKey(pVarIdent) ? new SignState(signMap.removeAndCopy(pVarIdent)) : this;
        }
        return signMap.containsKey(pVarIdent) && getSignForVariable(pVarIdent).equals(sign) ? this
                : new SignState(signMap.putAndCopy(pVarIdent, sign));
    }

    public SignState removeSignAssumptionOfVariable(String pVarIdent) {
        return assignSignToVariable(pVarIdent, SIGN.ALL);
    }

    public SIGN getSignForVariable(String pVarIdent) {
        return signMap.containsKey(pVarIdent) ? signMap.get(pVarIdent) : SIGN.ALL;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        String delim = ", ";
        builder.append("[");
        String loopDelim = "";
        for (String key : signMap.keySet()) {
            if (!DEBUG && (key.matches("\\w*::__CPAchecker_TMP_\\w*")
                    || key.endsWith(SignTransferRelation.FUNC_RET_VAR))) {
                continue;
            }
            builder.append(loopDelim);
            builder.append(key + "->" + getSignForVariable(key));
            loopDelim = delim;
        }
        builder.append("]");
        return builder.toString();
    }

    @Override
    public boolean equals(Object pObj) {
        if (!(pObj instanceof SignState)) {
            return false;
        }
        return ((SignState) pObj).signMap.equals(this.signMap);
    }

    @Override
    public int hashCode() {
        return signMap.hashCode();
    }

    private Object writeReplace() throws ObjectStreamException {
        if (this == TOP) {
            return proxy;
        } else {
            return this;
        }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
    }

    private static class SerialProxySign implements Serializable {

        private static final long serialVersionUID = 2843708585446089623L;

        public SerialProxySign() {
        }

        private Object readResolve() throws ObjectStreamException {
            return TOP;
        }
    }

    @Override
    public String getCPAName() {
        return "SignAnalysis";
    }

    @Override
    public Object evaluateProperty(String pProperty) throws InvalidQueryException {
        return Boolean.valueOf(checkProperty(pProperty));
    }

    @Override
    public boolean checkProperty(String pProperty) throws InvalidQueryException {
        // TODO Auto-generated method stub
        List<String> parts = propertySplitter.splitToList(pProperty);

        if (parts.size() == 2) {

            // pProperty = value <= varName
            if (CheckTypesOfStringsUtil.isSIGN(parts.get(0))) {
                SIGN value = SIGN.valueOf(parts.get(0));
                SIGN varName = getSignForVariable(parts.get(1));
                return (varName.covers(value));
            }

            // pProperty = varName <= value
            else if (CheckTypesOfStringsUtil.isSIGN(parts.get(1))) {
                SIGN varName = getSignForVariable(parts.get(0));
                SIGN value = SIGN.valueOf(parts.get(1));
                return (value.covers(varName));
            }

            // pProperty = varName1 <= varName2
            else {
                SIGN varName1 = getSignForVariable(parts.get(0));
                SIGN varName2 = getSignForVariable(parts.get(1));
                return (varName2.covers(varName1));
            }
        }

        return false;
    }

    @Override
    public void modifyProperty(String pModification) throws InvalidQueryException {
        throw new InvalidQueryException(
                "The modifying query " + pModification + " is an unsupported operation in " + getCPAName() + "!");
    }

    @Override
    public String toDOTLabel() {
        StringBuilder sb = new StringBuilder();

        sb.append("{");
        Joiner.on(", ").withKeyValueSeparator("=").appendTo(sb, signMap);
        sb.append("}");

        return sb.toString();
    }

    @Override
    public boolean shouldBeHighlighted() {
        return false;
    }

}