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 // We are Serializable, so we specify a version to allow changes to 017 // method signatures without breaking serialization. If you add or 018 // remove fields, you should change this number to the current date. 019 static final long serialVersionUID = 20020122L; 020 021 protected SingleScalar(PptSlice ppt) { 022 super(ppt); 023 } 024 025 protected @Prototype SingleScalar() { 026 super(); 027 } 028 029 public VarInfo var(@GuardSatisfied @UnknownInitialization(SingleScalar.class) SingleScalar this) { 030 return ppt.var_infos[0]; 031 } 032 033 /** 034 * Returns whether or not the specified types are valid for unary scalar. (Static version of 035 * method.) 036 */ 037 public static final boolean valid_types_static(VarInfo[] vis) { 038 return (vis.length == 1) && vis[0].file_rep_type.isScalar(); 039 } 040 041 /** Returns whether or not the specified types are valid for unary scalar. */ 042 @Override 043 public final boolean valid_types(VarInfo[] vis) { 044 return valid_types_static(vis); 045 } 046 047 // Should never be called with modified == ValueTuple.MISSING_NONSENSICAL. 048 // Subclasses need not override this except in special cases; 049 // just implement {@link #add_modified(Object,int)}. 050 @Override 051 public InvariantStatus add(@Interned Object val, int mod_index, int count) { 052 assert !falsified; 053 assert (mod_index >= 0) && (mod_index < 2); 054 long value = ((Long) val).longValue(); 055 if (mod_index == 0) { 056 return add_unmodified(value, count); 057 } else { 058 return add_modified(value, count); 059 } 060 } 061 062 @Override 063 public InvariantStatus check(@Interned Object val, int mod_index, int count) { 064 assert !falsified; 065 assert (mod_index >= 0) && (mod_index < 2); 066 long value = ((Long) val).longValue(); 067 if (mod_index == 0) { 068 return check_unmodified(value, count); 069 } else { 070 return check_modified(value, count); 071 } 072 } 073 074 /** 075 * Similar to {@link #check_modified} except that it can change the state of the invariant if 076 * necessary. If the invariant doesn't have any state, then the implementation should simply call 077 * {@link #check_modified}. This method need not check for falsification; that is done by the 078 * caller. 079 */ 080 public abstract InvariantStatus add_modified(long value, int count); 081 082 /** By default, do nothing if the value hasn't been seen yet. Subclasses can override this. */ 083 public InvariantStatus add_unmodified(long value, int count) { 084 // System.out.println("SingleScalar.add_unmodified " + ppt.name() + ": parent=" + ppt.parent); 085 return InvariantStatus.NO_CHANGE; 086 } 087 088 /** 089 * Presents a sample to the invariant. Returns whether the sample is consistent with the 090 * invariant. Does not change the state of the invariant. 091 * 092 * @param count how many identical samples were observed in a row. For example, three calls to 093 * check_modified with a count parameter of 1 is equivalent to one call to check_modified with 094 * a count parameter of 3. 095 * @return whether or not the sample is consistent with the invariant 096 */ 097 public abstract InvariantStatus check_modified(long value, int count); 098 099 public InvariantStatus check_unmodified(long value, int count) { 100 return InvariantStatus.NO_CHANGE; 101 } 102 103 // This has no additional suppression factories beyond those of Invariant. 104 105}