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}