/*
* Kodkod -- Copyright (c) 2005-present, Emina Torlak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package kodkod.engine.bool;
import java.util.Iterator;
import kodkod.util.ints.Ints;
/**
* A logic gate with two or more inputs; an AND or an OR gate.
*
* @specfield op: Operator.Binary
* @invariant #inputs > 1
* @invariant some components.this => label in [1..Integer.MAX_VALUE), label in [0..Integer.MAX_VALUE)
* @invariant no c1, c2: inputs | c1.label = -c2.label
* @invariant this.label > 0 => all c: inputs | |c.label| < this.label
* @author Emina Torlak
*/
public abstract class MultiGate extends BooleanFormula {
final Operator.Nary op;
private final int label, labelhash, hashcode;
/**
* Constructs a new MultiGate gate with the given operator and label.
* @requires op != null && label >= 0
* @ensures this.op' = op && this.label' = label
*/
MultiGate(Operator.Nary op, int label, int hashcode) {
super(null);
assert op != null;
assert label >= 0;
this.op = op;
this.label = label;
this.labelhash = Ints.superFastHash(label);
this.hashcode = hashcode;
}
/**
* Returns the label for this value.
* @return this.label
*/
@Override
public final int label() { return label; }
/**
* Returns the operator used to combine the input
* variables of this connective gate.
* @return this.op
*/
public final Operator.Nary op() { return op; }
/**
* Passes this value and the given
* argument value to the visitor, and returns the resulting value.
* @return the value produced by the visitor when visiting this node
* with the given argument.
*/
@Override
public <T, A> T accept(BooleanVisitor<T,A> visitor, A arg) {
return visitor.visit(this, arg);
}
/**
* Returns a string representation of this multigate.
* @return a string representation of this multigate.
*/
public String toString() {
final StringBuilder builder = new StringBuilder("(");
final Iterator<BooleanFormula> children = iterator();
builder.append(children.next());
while(children.hasNext()) {
builder.append(op);
builder.append(children.next());
}
builder.append(")");
return builder.toString();
}
/**
* Returns a hashcode for this gate. The hashcode obeys the Object contract.
* @return a hashcode for this gate.
*/
@Override
public final int hashCode() {
return hashcode;
}
/**
* Returns the digest of this formula that would be used
* to compute the digest of the composition of this and
* some other formula using the given operator. Specifically,
* if op = this.op, then the sum of this circuit's irreducible
* inputs' hashes (with respect to op) is returned. Otherwise,
* the superFastHash of this.label is returned.
* @return this.op = op => this.op.hash(this.inputs), Ints.superFastHash(this.label)
*/
@Override
final int hash(Operator op) {
return op==this.op ? hashcode : labelhash;
}
}