/****************************************************************************** * Copyright (c) 2009 - 2015 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ package com.ibm.wala.memsat.util; import java.util.LinkedHashSet; import java.util.Set; import kodkod.ast.Expression; import kodkod.ast.Formula; import kodkod.ast.IntConstant; import kodkod.ast.NotFormula; import kodkod.util.ints.SparseSequence; /** * Propagates conditions that are true in the top-level conjunction to if-then-else * conditions. PartialCannonicalizer should be applied before the propagator. * @author etorlak */ final class Propagator extends Simplifier { private final Set<Formula> conjuncts; private final Set<Formula> negs; /** * Constructs a new propagator. */ private Propagator(Set<Formula> conjuncts, SparseSequence<Expression> empties, SparseSequence<IntConstant> constants) { super(empties, constants); this.conjuncts = conjuncts; this.negs = new LinkedHashSet<Formula>(); for(Formula f: conjuncts) { if (f instanceof NotFormula) negs.add(((NotFormula)f).formula()); } } /** * Applies condition propagation to the given formula, using the information from the given simplifier. * @return a simplification of the given formula */ static Formula apply(Formula formula, Simplifier simplifier) { final Propagator p = new Propagator(kodkod.util.nodes.Nodes.roots(formula), simplifier.empties, simplifier.constants); final Set<Formula> out = new LinkedHashSet<Formula>(); for(Formula f : p.conjuncts) { final Formula visited = f.accept(p); if (visited==Formula.FALSE) { return Formula.FALSE; } else if (visited!=Formula.TRUE) { out.add(visited); } } return Formula.and(out); } final boolean isTrue(Formula formula) { return formula==Formula.TRUE || conjuncts.contains(formula); } final boolean isFalse(Formula formula) { if (formula==Formula.FALSE) return true; else if (!conjuncts.contains(formula)) { if (formula.getClass()==NotFormula.class) { return conjuncts.contains(((NotFormula)formula).formula()); } else { return negs.contains(formula); } } return false; } }