001 package daikon;
002
003 import utilMDE.*;
004
005 import java.util.logging.Logger;
006
007 // Internally, we use the names "array[]", "array[]-element", and
008 // "array[]-indexn". These may be different depending on the programming
009 // language; for instance, C uses "*array" in place of "array[]-element".
010
011
012 /**
013 * Represents the comparability of variables, including methods to
014 * determine if two VarComparabilities are comparable.
015 * VarComparability types have two formats: implicit and none.<p>
016 *
017 * A VarComparabilityImplicit is an arbitrary string, and comparisons
018 * succeed exactly if the two VarComparabilitys are identical.<p>
019 *
020 * VarComparabilityNone means no comparability information was provided.<p>
021 **/
022 public abstract class VarComparability {
023
024 /** Debug tracer. **/
025 public static final Logger debug =
026 Logger.getLogger("daikon.VarComparability");
027
028
029 public static final int NONE = 0;
030 public static final int IMPLICIT = 1;
031
032 /**
033 * Create a VarComparability representing the given arguments with
034 * respect to a variable.
035 * @param format the type of comparability, either NONE or IMPLICIT
036 * @param rep a regular expression indicating
037 * how to match. The form is "(a)[b][c]..." where each variable is
038 * string (or number) that is a UID for a basic type. a is the type
039 * of the element, b is the type of the first index, c the type of
040 * the second, etc. Index variables only apply if this is an array.
041 * @param vartype the declared type of the variable
042 **/
043 public static VarComparability parse(int format, String rep, ProglangType vartype) {
044 if (format == NONE) {
045 return VarComparabilityNone.parse(rep, vartype);
046 } else if (format == IMPLICIT) {
047 return VarComparabilityImplicit.parse(rep, vartype);
048 } else {
049 throw new IllegalArgumentException("bad format argument " + format
050 + " should have been in {0, 1, 2}");
051 }
052 }
053
054 /**
055 * Create a VarComparability based on comparabilities of indices.
056 * @return a new comparability that is an array with the same dimensionality
057 * and indices as given, but with a different element type.
058 *
059 * @param elemTypeName the new type of the elements of return value.
060 * @param old the varcomparability that this is derived from; has
061 * the same indices as this.
062 **/
063 public static VarComparability makeComparabilitySameIndices (String elemTypeName,
064 VarComparability old) {
065 if (old instanceof VarComparabilityNone) {
066 return VarComparabilityNone.it;
067 } else {
068 throw new Error ("makeComparabilitySameIndices not implemented for implicit comparables");
069 }
070 }
071
072 public static VarComparability makeAlias(VarInfo vi) {
073 return vi.comparability.makeAlias();
074 }
075 public abstract VarComparability makeAlias();
076
077 public abstract VarComparability elementType();
078 public abstract VarComparability indexType(int dim);
079
080 /** Return the comparability for the length of this string**/
081 public abstract VarComparability string_length_type();
082
083 /**
084 * Returns true if this is comparable to everything else.
085 */
086 public abstract boolean alwaysComparable();
087
088 /** Returns whether two variables are comparable. **/
089 public static boolean comparable(VarInfo v1, VarInfo v2) {
090 return comparable(v1.comparability, v2.comparability);
091 }
092
093 /** Returns whether two comparabilities are comparable. **/
094 public static boolean comparable (VarComparability type1,
095 VarComparability type2) {
096
097 if (type1 != null && type2 != null && type1.getClass() != type2.getClass())
098 throw new Error(String.format ("Trying to compare VarComparabilities " +
099 "of different types: %s (%s) and %s (%s)", type1,
100 type1.getClass(), type2, type2.getClass()));
101
102 if (type1 instanceof VarComparabilityNone || type1 == null || type2 == null) {
103 return VarComparabilityNone.comparable ((VarComparabilityNone)type1,
104 (VarComparabilityNone)type2);
105 } else if (type1 instanceof VarComparabilityImplicit) {
106 return VarComparabilityImplicit.comparable
107 ((VarComparabilityImplicit)type1,
108 (VarComparabilityImplicit)type2);
109 } else {
110 throw new Error("Unrecognized subtype of VarComparability: " + type1);
111 }
112 }
113
114 /**
115 * In general, if two items are comparable, they can be placed in the
116 * same equality set. This is not always true for some comparabilities
117 * (because they are not always transitive). They can override this
118 * method to provide the correct results
119 */
120 public boolean equality_set_ok (VarComparability other) {
121 return comparable (this, other);
122 }
123
124 }