001package daikon.inv;
002
003import daikon.inv.filter.DerivedParameterFilter;
004import daikon.inv.filter.InvariantFilter;
005import daikon.inv.filter.ObviousFilter;
006import daikon.inv.filter.OnlyConstantVariablesFilter;
007import daikon.inv.filter.SimplifyFilter;
008import daikon.inv.filter.UnjustifiedFilter;
009import daikon.inv.filter.UnmodifiedVariableEqualityFilter;
010import daikon.inv.filter.VariableFilter;
011import java.io.ObjectStreamException;
012import java.io.Serializable;
013import org.checkerframework.checker.lock.qual.GuardSatisfied;
014import org.checkerframework.dataflow.qual.Pure;
015import org.checkerframework.dataflow.qual.SideEffectFree;
016
017/**
018 * DiscardCode is an enumeration type. It represents reasons why an invariant is falsified or
019 * disregarded. Methods that decide whether an Invariant should be printed later (such as
020 * isObviousImplied()), side effect Invariants to contain DiscardCode instances in their discardCode
021 * field slot.
022 *
023 * <p>The different elements of the enumeration are:
024 *
025 * <p>obvious // is implied by other already known invariants
026 *
027 * <p>bad_sample // is falsified by a seen example
028 *
029 * <p>bad_confidence // has an unjustified confidence
030 *
031 * <p>(unused) // was few_modified_samples
032 *
033 * <p>not_enough_samples // not enough samples seen for the Invariant
034 *
035 * <p>non_canonical_var // expression involves a non-canonical variable
036 *
037 * <p>implied_post_condition // implied by some prestate conditions
038 *
039 * <p>only_constant_vars // expression for invariant only contains constant variables
040 *
041 * <p>derived_param // has a VarInfo that has derived and uninteresting param
042 *
043 * <p>unmodified_var // invariant discarded because it says some var hasn't been modified
044 *
045 * <p>control_check // if discarded due to the ControlledInvariantFilter
046 *
047 * <p>exact // isExact() fails
048 *
049 * <p>var_filtered // Doesn't contain a desirable variable
050 *
051 * <p>filtered // filtered by some other means not in the above list
052 *
053 * <p>There is no representation for an invariant that is *not* discarded; don't use a DiscardCode
054 * in that situation.
055 */
056public class DiscardCode implements Comparable<DiscardCode>, Serializable {
057
058  static final long serialVersionUID = 20031016L;
059
060  /** used when an invariant is implied by other known invariants. */
061  public static final DiscardCode obvious = new DiscardCode(0);
062
063  /** used when an invariant is falsified by a seen example. */
064  public static final DiscardCode bad_sample = new DiscardCode(1);
065
066  /** used when an invariant has an unjustified confidence. */
067  public static final DiscardCode bad_confidence = new DiscardCode(2);
068
069  /** used when an invariant has not had enough samples. */
070  public static final DiscardCode not_enough_samples = new DiscardCode(4);
071
072  /** used when an invariant contains a non-canonical variable. */
073  public static final DiscardCode non_canonical_var = new DiscardCode(5);
074
075  /** used when an invariant is implied by some prestate conditions. */
076  public static final DiscardCode implied_post_condition = new DiscardCode(6);
077
078  /** used when an invariant's expression contains only constant variables. */
079  public static final DiscardCode only_constant_vars = new DiscardCode(7);
080
081  /** used when an invariant's VarInfo returns true for isDerivedParamAndUninteresting() */
082  public static final DiscardCode derived_param = new DiscardCode(8);
083
084  /** used for invariants that describe unmodified variables. */
085  public static final DiscardCode unmodified_var = new DiscardCode(9);
086
087  /** used for invariants discarded because of the ControlledInvariantsFilter. */
088  public static final DiscardCode control_check = new DiscardCode(10);
089
090  /** used for invariants discarded when isExact() fails. */
091  public static final DiscardCode exact = new DiscardCode(11);
092
093  /** used for invariants that don't contain desired variables. */
094  public static final DiscardCode var_filtered = new DiscardCode(12);
095
096  /** used for invariants that are filtered by some means not in the above list. */
097  public static final DiscardCode filtered = new DiscardCode(13);
098
099  /** Each member of the enumeration is associated with a distinct int for comparability. */
100  public final int enumValue;
101
102  // Prevents the user from using DiscardCode types not in the enumeration
103  // by making the default constructor private.  This constructor should never be
104  // used to make new elements of the enumeration.
105  private DiscardCode() {
106    this.enumValue = -1;
107  }
108
109  // Makes it easier to add a new DiscardCode type by simply constructing it as a field with the
110  // next non-used integer value.
111  private DiscardCode(int enumValue) {
112    this.enumValue = enumValue;
113  }
114
115  /**
116   * The enumeration members in sorted order: <br>
117   * obvious, bad_sample, bad_confidence, [unused], not_enough_samples, non_canonical_var,<br>
118   * implied_post_condition, only_constant_vars, derived_param, unmodified_var, control_check,
119   * exact, var filter
120   *
121   * @return this.enumValue.compareTo(o.enumValue) where the enumValue are treated as Integers
122   * @throws ClassCastException iff !(o instanceof DiscardCode)
123   */
124  @Pure
125  @Override
126  public int compareTo(@GuardSatisfied DiscardCode this, DiscardCode o) {
127    if (this.enumValue < o.enumValue) {
128      return -1;
129    } else if (this.enumValue == o.enumValue) {
130      return 0;
131    } else {
132      return 1;
133    }
134  }
135
136  /** Returns the DiscardCode most associated with the given filter. */
137  public static DiscardCode findCode(InvariantFilter filter) {
138    if ((filter instanceof ObviousFilter) || (filter instanceof SimplifyFilter)) {
139      return obvious;
140    } else if (filter instanceof DerivedParameterFilter) {
141      return derived_param;
142    } else if (filter instanceof OnlyConstantVariablesFilter) {
143      return only_constant_vars;
144    } else if (filter instanceof UnjustifiedFilter) {
145      return bad_confidence;
146    } else if (filter instanceof UnmodifiedVariableEqualityFilter) {
147      return unmodified_var;
148    } else if (filter instanceof VariableFilter) {
149      return var_filtered;
150    } else {
151      return filtered;
152    }
153  }
154
155  /**
156   * Prints out a string describing the reason for discard.
157   *
158   * @return one of {"Not discarded", "Obvious, "Bad sample seen", "Unjustified confidence", "Few
159   *     modified samples", "Not enough samples", "Non-canonical variable", "Implied post state",
160   *     "Only constant variables in this expression", "Derived Param", "Control Check", "Exact",
161   *     "Variable Filter", "Filtered"}
162   */
163  @SideEffectFree
164  @Override
165  public String toString(@GuardSatisfied DiscardCode this) {
166    if (this.enumValue == -1) {
167      return "Not discarded";
168    } else if (this.enumValue == 0) {
169      return "Obvious";
170    } else if (this.enumValue == 1) {
171      return "Bad sample seen";
172    } else if (this.enumValue == 2) {
173      return "Unjustified confidence";
174    } else if (this.enumValue == 3) {
175      return "Few modified samples";
176    } else if (this.enumValue == 4) {
177      return "Not enough samples";
178    } else if (this.enumValue == 5) {
179      return "Non-canonical variable";
180    } else if (this.enumValue == 6) {
181      return "Implied post state";
182    } else if (this.enumValue == 7) {
183      return "Only constant variables in this expression";
184    } else if (this.enumValue == 8) {
185      return "Derived Param";
186    } else if (this.enumValue == 9) {
187      return "Unmodified var";
188    } else if (this.enumValue == 10) {
189      return "Control Check";
190    } else if (this.enumValue == 11) {
191      return "Exact";
192    } else if (this.enumValue == 12) {
193      return "Variable Filter";
194    } else if (this.enumValue == 13) {
195      return "Filtered";
196    } else { // this should never happen since the constructor is private
197      return "Unknown instance of DiscardCode used";
198    }
199  }
200
201  /**
202   * To prevent deserialization causing more DiscardCodes to be instantiated.
203   *
204   * @return one of the static DiscardCode instances
205   */
206  public Object readResolve() throws ObjectStreamException {
207    if (enumValue == 0) {
208      return obvious;
209    } else if (enumValue == 1) {
210      return bad_sample;
211    } else if (enumValue == 2) {
212      return bad_confidence;
213    } else if (enumValue == 3) throw new Error("few_modified_samples no longer exists");
214    else if (enumValue == 4) {
215      return not_enough_samples;
216    } else if (enumValue == 5) {
217      return non_canonical_var;
218    } else if (enumValue == 6) {
219      return implied_post_condition;
220    } else if (enumValue == 7) {
221      return only_constant_vars;
222    } else if (enumValue == 8) {
223      return derived_param;
224    } else if (enumValue == 9) {
225      return unmodified_var;
226    } else if (enumValue == 10) {
227      return control_check;
228    } else if (enumValue == 11) {
229      return exact;
230    } else if (enumValue == 12) {
231      return var_filtered;
232    } else if (enumValue == 13) {
233      return filtered;
234    } else { // this should never happen
235      // return null;
236      throw new Error("impossible");
237    }
238  }
239}