001package daikon.inv.unary.scalar;
002
003import daikon.PptSlice;
004import daikon.VarInfo;
005import daikon.inv.InvariantStatus;
006import daikon.inv.unary.UnaryInvariant;
007import org.checkerframework.checker.initialization.qual.UnknownInitialization;
008import org.checkerframework.checker.interning.qual.Interned;
009import org.checkerframework.checker.lock.qual.GuardSatisfied;
010import typequals.prototype.qual.Prototype;
011
012/**
013 * Abstract base class for invariants over one numeric (scalar) variable, such as {@code x != 0}.
014 */
015public abstract class SingleScalar extends UnaryInvariant {
016  static final long serialVersionUID = 20020122L;
017
018  protected SingleScalar(PptSlice ppt) {
019    super(ppt);
020  }
021
022  protected @Prototype SingleScalar() {
023    super();
024  }
025
026  public VarInfo var(@GuardSatisfied @UnknownInitialization(SingleScalar.class) SingleScalar this) {
027    return ppt.var_infos[0];
028  }
029
030  /**
031   * Returns whether or not the specified types are valid for unary scalar. (Static version of
032   * method.)
033   */
034  public static final boolean valid_types_static(VarInfo[] vis) {
035    return (vis.length == 1) && vis[0].file_rep_type.isScalar();
036  }
037
038  @Override
039  public final boolean valid_types(VarInfo[] vis) {
040    return valid_types_static(vis);
041  }
042
043  // Should never be called with modified == ValueTuple.MISSING_NONSENSICAL.
044  // Subclasses need not override this except in special cases;
045  // just implement {@link #add_modified(Object,int)}.
046  @Override
047  public InvariantStatus add(@Interned Object val, int mod_index, int count) {
048    assert !falsified;
049    assert (mod_index >= 0) && (mod_index < 2);
050    long value = ((Long) val).longValue();
051    if (mod_index == 0) {
052      return add_unmodified(value, count);
053    } else {
054      return add_modified(value, count);
055    }
056  }
057
058  @Override
059  public InvariantStatus check(@Interned Object val, int mod_index, int count) {
060    assert !falsified;
061    assert (mod_index >= 0) && (mod_index < 2);
062    long value = ((Long) val).longValue();
063    if (mod_index == 0) {
064      return check_unmodified(value, count);
065    } else {
066      return check_modified(value, count);
067    }
068  }
069
070  /**
071   * Similar to {@link #check_modified} except that it can change the state of the invariant if
072   * necessary. If the invariant doesn't have any state, then the implementation should simply call
073   * {@link #check_modified}. This method need not check for falsification; that is done by the
074   * caller.
075   */
076  public abstract InvariantStatus add_modified(long value, int count);
077
078  /** By default, do nothing if the value hasn't been seen yet. Subclasses can override this. */
079  public InvariantStatus add_unmodified(long value, int count) {
080    // System.out.println("SingleScalar.add_unmodified " + ppt.name() + ": parent=" + ppt.parent);
081    return InvariantStatus.NO_CHANGE;
082  }
083
084  /**
085   * Presents a sample to the invariant. Returns whether the sample is consistent with the
086   * invariant. Does not change the state of the invariant.
087   *
088   * @param count how many identical samples were observed in a row. For example, three calls to
089   *     check_modified with a count parameter of 1 is equivalent to one call to check_modified with
090   *     a count parameter of 3.
091   * @return whether or not the sample is consistent with the invariant
092   */
093  public abstract InvariantStatus check_modified(long value, int count);
094
095  public InvariantStatus check_unmodified(long value, int count) {
096    return InvariantStatus.NO_CHANGE;
097  }
098
099  // This has no additional suppression factories beyond those of Invariant.
100
101}