001// ***** This file is automatically generated from SequenceScalar.java.jpp 002 003package daikon.inv.binary.sequenceScalar; 004 005import daikon.*; 006import daikon.inv.*; 007import daikon.inv.binary.BinaryInvariant; 008import org.checkerframework.checker.interning.qual.Interned; 009import org.checkerframework.checker.lock.qual.GuardSatisfied; 010import org.checkerframework.dataflow.qual.Pure; 011import org.plumelib.util.ArraysPlume; 012import org.plumelib.util.Intern; 013import typequals.prototype.qual.NonPrototype; 014import typequals.prototype.qual.Prototype; 015 016/** 017 * Abstract base class for comparing long sequences to long variables. Note that the sequence 018 * must always be passed in first. An example is {@code x is a member of a[]}. 019 */ 020public abstract class SequenceScalar extends BinaryInvariant { 021 022 // We are Serializable, so we specify a version to allow changes to 023 // method signatures without breaking serialization. If you add or 024 // remove fields, you should change this number to the current date. 025 static final long serialVersionUID = 20040113L; 026 027 protected SequenceScalar(PptSlice ppt) { 028 super(ppt); 029 } 030 031 protected @Prototype SequenceScalar() { 032 super(); 033 } 034 035 /** 036 * Returns whether or not the specified types are valid. All subclasses accept a scalar in one 037 * parameter and an array over the same scalar type in the other. 038 */ 039 @Override 040 public boolean valid_types(VarInfo[] vis) { 041 042 if (vis.length != 2) { 043 return false; 044 } 045 046 if (!vis[0].file_rep_type.baseIsScalar() || !vis[1].file_rep_type.baseIsScalar()) { 047 return false; 048 } 049 050 return vis[0].file_rep_type.isArray() ^ vis[1].file_rep_type.isArray(); 051 } 052 053 /** 054 * Since the order is determined from the vars and the sequence is always first, no permute is 055 * necesesary. Subclasses can override if necessary. 056 */ 057 protected Invariant resurrect_done_swapped() { 058 return this; 059 } 060 061 /** 062 * Since the order is determined from the vars and the sequence is always first, this is 063 * essentially symmetric. Subclasses can override if necessary. 064 */ 065 @Pure 066 @Override 067 public boolean is_symmetric() { 068 return true; 069 } 070 071 // Check if swap occurred and call one of the other two methods 072 @Override 073 protected Invariant resurrect_done(int[] permutation) { 074 assert permutation.length == 2; 075 // assert ArraysPlume.fnIsPermutation(permutation); 076 if (permutation[0] == 1) { 077 return resurrect_done_swapped(); 078 } else { 079 return resurrect_done_unswapped(); 080 } 081 } 082 083 /** Subclasses can override in the rare cases they need to fix things even when not swapped. */ 084 protected Invariant resurrect_done_unswapped() { 085 // do nothing 086 return this; 087 } 088 089 protected final boolean seq_first(@GuardSatisfied SequenceScalar this) { 090 return ppt.var_infos[0].rep_type == ProglangType.INT_ARRAY; 091 } 092 093 protected final int seq_index(@GuardSatisfied SequenceScalar this) { 094 return seq_first() ? 0 : 1; 095 } 096 097 protected final int scl_index(@GuardSatisfied SequenceScalar this) { 098 return seq_first() ? 1 : 0; 099 } 100 101 public VarInfo seqvar(@GuardSatisfied SequenceScalar this) { 102 return ppt.var_infos[seq_index()]; 103 } 104 105 public VarInfo sclvar(@GuardSatisfied SequenceScalar this) { 106 return ppt.var_infos[scl_index()]; 107 } 108 109 /** 110 * Return the sequence variable in the tuple whose VarInfos are corresponds to this.ppt.var_infos. 111 */ 112 public VarInfo seqvar(VarInfo[] vis) { 113 return vis[seq_index()]; 114 } 115 116 /** 117 * Return the scalar variable in the tuple whose VarInfos are corresponds to this.ppt.var_infos. 118 */ 119 public VarInfo sclvar(VarInfo[] vis) { 120 return vis[scl_index()]; 121 } 122 123 @Override 124 public InvariantStatus check( 125 @Interned Object val1, @Interned Object val2, int mod_index, int count) { 126 assert !falsified; 127 assert (mod_index >= 0) && (mod_index < 4); 128 long[] v1 = (long[]) val1; 129 long v2 = ((Long) val2).longValue(); 130 if (v1 == null) { 131 } else if (mod_index == 0) { 132 return check_unmodified(v1, v2, count); 133 } else { 134 return check_modified(v1, v2, count); 135 } 136 return InvariantStatus.NO_CHANGE; 137 } 138 139 @Override 140 public InvariantStatus add( 141 @Interned Object val1, @Interned Object val2, int mod_index, int count) { 142 assert !falsified; 143 assert (mod_index >= 0) && (mod_index < 4); 144 long[] v1 = (long[]) val1; 145 long v2 = ((Long) val2).longValue(); 146 if (v1 == null) { 147 } else if (mod_index == 0) { 148 return add_unmodified(v1, v2, count); 149 } else { 150 return add_modified(v1, v2, count); 151 } 152 return InvariantStatus.NO_CHANGE; 153 } 154 155 /** 156 * Presents a sample to the invariant. Returns whether the sample is consistent with the 157 * invariant. Does not change the state of the invariant. 158 * 159 * @param count how many identical samples were observed in a row. For example, three calls to 160 * check_modified with a count parameter of 1 is equivalent to one call to check_modified with 161 * a count parameter of 3. 162 * @return whether or not the sample is consistent with the invariant 163 */ 164 public abstract InvariantStatus check_modified(long @Interned [] v1, long v2, int count); 165 166 public InvariantStatus check_unmodified(long @Interned [] v1, long v2, int count) { 167 return InvariantStatus.NO_CHANGE; 168 } 169 170 /** 171 * Similar to {@link #check_modified} except that it can change the state of the invariant if 172 * necessary. If the invariant doesn't have any state, then the implementation should simply call 173 * {@link #check_modified}. This method need not check for falsification; that is done by the 174 * caller. 175 */ 176 public abstract InvariantStatus add_modified(long @Interned [] v1, long v2, int count); 177 178 /** By default, do nothing if the value hasn't been seen yet. Subclasses can override this. */ 179 public InvariantStatus add_unmodified(long @Interned [] v1, long v2, int count) { 180 return InvariantStatus.NO_CHANGE; 181 } 182}