001// ***** This file is automatically generated from Numeric.java.jpp 002 003package daikon.inv.binary.twoString; 004 005import org.checkerframework.checker.lock.qual.GuardSatisfied; 006import org.checkerframework.checker.nullness.qual.NonNull; 007import org.checkerframework.checker.nullness.qual.Nullable; 008import org.checkerframework.checker.signature.qual.ClassGetName; 009import org.checkerframework.dataflow.qual.Pure; 010import org.checkerframework.dataflow.qual.SideEffectFree; 011import static daikon.inv.Invariant.asInvClass; 012 013import daikon.*; 014import daikon.Quantify.QuantFlags; 015import daikon.derive.binary.*; 016import daikon.inv.*; 017import daikon.inv.binary.twoScalar.*; 018import daikon.inv.binary.twoString.*; 019import daikon.inv.unary.scalar.*; 020import daikon.inv.unary.sequence.*; 021import daikon.suppress.*; 022import java.util.*; 023import org.plumelib.util.UtilPlume; 024import typequals.prototype.qual.NonPrototype; 025import typequals.prototype.qual.Prototype; 026 027/** 028 * Baseclass for binary numeric invariants. 029 * 030 * Each specific invariant is implemented in a subclass (typically, in this file). The subclass must 031 * provide the methods instantiate(), check(), and format(). Symmetric functions should define 032 * is_symmetric() to return true. 033 */ 034public abstract class StdString extends TwoString { 035 036 static final long serialVersionUID = 20060609L; 037 038 protected StdString(PptSlice ppt, boolean swap) { 039 super(ppt); 040 this.swap = swap; 041 } 042 043 protected StdString(boolean swap) { 044 super(); 045 this.swap = swap; 046 } 047 048 @Override 049 public boolean instantiate_ok(VarInfo[] vis) { 050 051 ProglangType type1 = vis[0].file_rep_type; 052 ProglangType type2 = vis[1].file_rep_type; 053 if (!type1.isString() || !type2.isString()) { 054 return false; 055 } 056 057 return true; 058 } 059 060 @Pure 061 @Override 062 public boolean isExact() { 063 return true; 064 } 065 066 @Override 067 public String repr(@GuardSatisfied StdString this) { 068 return getClass().getSimpleName() + ": " + format() 069 + (swap ? " [swapped]" : " [unswapped]"); 070 } 071 072 /** 073 * Returns a string in the specified format that describes the invariant. 074 * 075 * The generic format string is obtained from the subclass specific get_format_str(). Instances of 076 * %varN% are replaced by the variable name in the specified format. 077 */ 078 @SideEffectFree 079 @Override 080 public String format_using(@GuardSatisfied StdString this, OutputFormat format) { 081 082 if (ppt == null) { 083 return String.format("proto ppt [class %s] format %s", getClass(), 084 get_format_str(format)); 085 } 086 String fmt_str = get_format_str(format); 087 088 String v1 = var1().name_using(format); 089 String v2 = var2().name_using(format); 090 091 // Note that we do not use String.replaceAll here, because that's 092 // inseparable from the regex library, and we don't want to have to 093 // escape v1 with something like 094 // v1.replaceAll("([\\$\\\\])", "\\\\$1") 095 fmt_str = fmt_str.replace("%var1%", v1); 096 fmt_str = fmt_str.replace("%var2%", v2); 097 098 // if (false && (format == OutputFormat.DAIKON)) { 099 // fmt_str = "[" + getClass() + "]" + fmt_str + " (" 100 // + var1().get_value_info() + ", " + var2().get_value_info() + ")"; 101 // } 102 return fmt_str; 103 } 104 105 /** Calls the function specific equal check and returns the correct status. */ 106 107 @Override 108 public InvariantStatus check_modified(String x, String y, int count) { 109 110 try { 111 if (eq_check(x, y)) { 112 return InvariantStatus.NO_CHANGE; 113 } else { 114 return InvariantStatus.FALSIFIED; 115 } 116 } catch (Exception e) { 117 return InvariantStatus.FALSIFIED; 118 } 119 } 120 121 /** 122 * Checks to see if 'x[a] op y[b]' where 'x[] op y[]' and 'a == b'. Doesn't catch the case where 123 * a = b+1. 124 */ 125 public @Nullable DiscardInfo is_subscript(VarInfo[] vis) { 126 127 VarInfo v1 = var1(vis); 128 VarInfo v2 = var2(vis); 129 130 // Make sure each var is a sequence subscript 131 if (!v1.isDerived() || !(v1.derived instanceof SequenceStringSubscript)) { 132 return null; 133 } 134 if (!v2.isDerived() || !(v2.derived instanceof SequenceStringSubscript)) { 135 return null; 136 } 137 138 @NonNull SequenceStringSubscript der1 = (SequenceStringSubscript) v1.derived; 139 @NonNull SequenceStringSubscript der2 = (SequenceStringSubscript) v2.derived; 140 141 // Make sure the shifts match 142 if (der1.index_shift != der2.index_shift) { 143 return null; 144 } 145 146 // Look for this invariant over a sequence 147 String cstr = getClass().getName(); 148 cstr = cstr.replaceFirst("Numeric", "PairwiseNumeric"); 149 cstr = cstr.replaceFirst("twoScalar", "twoSequence"); 150 cstr = cstr.replaceFirst("twoFloat", "twoSequence"); 151 Class<? extends Invariant> pairwise_class; 152 try { 153 @SuppressWarnings("signature") // string manipulation; application invariants 154 @ClassGetName String cstr_cgn = cstr; 155 pairwise_class = asInvClass(Class.forName(cstr_cgn)); 156 } catch (Exception e) { 157 throw new Error("can't create class for " + cstr, e); 158 } 159 Invariant inv = find(pairwise_class, der1.seqvar(), der2.seqvar()); 160 if (inv == null) { 161 return null; 162 } 163 164 // Look to see if the subscripts are equal 165 Invariant subinv = find(StringEqual.class, der1.sclvar(), der2.sclvar()); 166 if (subinv == null) { 167 return null; 168 } 169 170 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " 171 + inv.format() + " and " + subinv.format()); 172 } 173 174 @Pure 175 @Override 176 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 177 178 DiscardInfo super_result = super.isObviousDynamically(vis); 179 if (super_result != null) { 180 return super_result; 181 } 182 183 // any relation across subscripts is made obvious by the same 184 // relation across the original sequence if the subscripts are equal 185 DiscardInfo result = is_subscript(vis); 186 if (result != null) { 187 return result; 188 } 189 190 // Check for invariant specific obvious checks. The obvious_checks 191 // method returns an array of arrays of antecedents. If all of the 192 // antecedents in an array are true, then the invariant is obvoius. 193 InvDef[][] obvious_arr = obvious_checks(vis); 194 obvious_loop: 195 for (int i = 0; i < obvious_arr.length; i++) { 196 InvDef[] antecedents = obvious_arr[i]; 197 StringBuilder why = null; 198 for (int j = 0; j < antecedents.length; j++) { 199 Invariant inv = antecedents[j].find(); 200 if (inv == null) { 201 continue obvious_loop; 202 } 203 if (why == null) { 204 why = new StringBuilder(inv.format()); 205 } else { 206 why.append(" and "); 207 why.append(inv.format()); 208 } 209 } 210 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + why); 211 } 212 213 return null; 214 } 215 216 /** 217 * Return a format string for the specified output format. Each instance of %varN% will be 218 * replaced by the correct name for varN. 219 */ 220 public abstract String get_format_str(@GuardSatisfied StdString this, OutputFormat format); 221 222 /** Returns true if x and y don't invalidate the invariant. */ 223 public abstract boolean eq_check(String x, String y); 224 225 /** 226 * Returns an array of arrays of antecedents. If all of the antecedents in any array are true, 227 * then the invariant is obvious. 228 */ 229 public InvDef[][] obvious_checks(VarInfo[] vis) { 230 return new InvDef[][] {}; 231 } 232 233 public static List<@Prototype Invariant> get_proto_all() { 234 235 List<@Prototype Invariant> result = new ArrayList<>(); 236 237 result.add(SubString.get_proto(false)); 238 result.add(SubString.get_proto(true)); 239 240 // System.out.printf("%s get proto: %s%n", StdString.class, result); 241 return result; 242 } 243 244 // suppressor definitions, used by many of the classes below 245 protected static NISuppressor 246 247 var1_eq_var2 = new NISuppressor(0, 1, StringEqual.class), 248 var2_eq_var1 = new NISuppressor(0, 1, StringEqual.class); 249 250 // 251 // Int and Float Numeric Invariants 252 // 253 254// 255// Standard String invariants 256// 257 258 /** 259 * Represents the substring invariant between two String scalars. 260 * Prints as {@code x is a substring of y}. 261 */ 262 public static class SubString extends StdString { 263 // We are Serializable, so we specify a version to allow changes to 264 // method signatures without breaking serialization. If you add or 265 // remove fields, you should change this number to the current date. 266 static final long serialVersionUID = 20081113L; 267 268 protected SubString(PptSlice ppt, boolean swap) { 269 super(ppt, swap); 270 } 271 272 protected SubString(boolean swap) { 273 super(swap); 274 } 275 276 private static @Prototype SubString proto = new @Prototype SubString(false); 277 private static @Prototype SubString proto_swap = new @Prototype SubString(true); 278 279 /** Returns the prototype invariant. */ 280 public static @Prototype SubString get_proto(boolean swap) { 281 if (swap) { 282 return proto_swap; 283 } else { 284 return proto; 285 } 286 } 287 288 // Variables starting with dkconfig_ should only be set via the 289 // daikon.config.Configuration interface. 290 /** Boolean. True iff SubString invariants should be considered. */ 291 public static boolean dkconfig_enabled = false; 292 293 @Override 294 public boolean enabled() { 295 return dkconfig_enabled; 296 } 297 298 @Override 299 protected SubString instantiate_dyn(@Prototype SubString this, PptSlice slice) { 300 return new SubString(slice, swap); 301 } 302 303 @Override 304 public String get_format_str(@GuardSatisfied SubString this, OutputFormat format) { 305 if (format == OutputFormat.DAIKON) { 306 return "%var1% is a substring of %var2%"; 307 } else if (format.isJavaFamily()) { 308 return "%var2%.contains(%var1%)"; 309 } else if (format == OutputFormat.CSHARPCONTRACT) { 310 311 return "%var2%.Contains(%var1%)"; 312 } else { 313 return format_unimplemented(format); 314 } 315 } 316 317 @Override 318 public boolean eq_check(String x, String y) { 319 return y.contains(x); 320 } 321 322 /** Justified as long as there are samples. */ 323 @Override 324 protected double computeConfidence() { 325 if (ppt.num_samples() == 0) { 326 return Invariant.CONFIDENCE_UNJUSTIFIED; 327 } 328 329 return Invariant.CONFIDENCE_JUSTIFIED; 330 } 331 332 /** Returns a list of non-instantiating suppressions for this invariant. */ 333 @Pure 334 @Override 335 public NISuppressionSet get_ni_suppressions() { 336 if (swap) { 337 return suppressions_swap; 338 } else { 339 return suppressions; 340 } 341 } 342 343 /** definition of this invariant (the suppressee) (unswapped) */ 344 private static NISuppressee suppressee = new NISuppressee(SubString.class, false); 345 346 private static NISuppressionSet suppressions = 347 new NISuppressionSet( 348 new NISuppression[] { 349 // v1 == v2 ==> v1 subsequence v2 350 new NISuppression(var1_eq_var2, suppressee), 351 }); 352 private static NISuppressionSet suppressions_swap = suppressions.swap(); 353 } 354 355}