001package daikon.derive.ternary;
002
003import daikon.ProglangType;
004import daikon.VarInfo;
005import daikon.derive.DerivationFactory;
006import org.checkerframework.checker.nullness.qual.Nullable;
007
008/** Factory to produce TernaryDerivations. */
009public abstract class TernaryDerivationFactory implements DerivationFactory {
010
011  /**
012   * Create a set of derivations from three base variables. If the base variables aren't worth
013   * deriving from, returns null.
014   *
015   * @param vi1 the first of the three base variables
016   * @param vi2 the second of the three base variables
017   * @param vi3 the third of the three base variables
018   * @return a set of derivations based on three base variables. We allow more than one because the
019   *     base variables may have multiple derived variables, per type of derivation. Can also be
020   *     null if the variables have nothing to derive from.
021   */
022  public abstract TernaryDerivation @Nullable [] instantiate(VarInfo vi1, VarInfo vi2, VarInfo vi3);
023
024  /**
025   * Check if vi1 and vi2 can be a part of a VarInfo triple based on their types.
026   *
027   * @return true if vi1 and vi2 can belong to a valid VarInfo triple; false otherwise
028   */
029  public static boolean checkType(VarInfo vi1, VarInfo vi2) {
030    if ((vi1.rep_type == ProglangType.INT_ARRAY) && (vi2.rep_type == ProglangType.INT)) {
031      return true;
032    } else if ((vi1.rep_type == ProglangType.INT) && (vi2.rep_type == ProglangType.INT_ARRAY)) {
033      return true;
034    } else if ((vi1.rep_type == ProglangType.INT) && (vi2.rep_type == ProglangType.INT)) {
035      return true;
036    } else {
037      return false;
038    }
039  }
040
041  /**
042   * Check if vi1 and vi2 can be a part of a VarInfo triple based on their types.
043   *
044   * @return a ProglangType which is the type of VarInfo needed to make a valid VarInfo triple out
045   *     of vi1 and vi2 (null otherwise)
046   */
047  public static @Nullable ProglangType returnType(VarInfo vi1, VarInfo vi2) {
048    if ((vi1.rep_type == ProglangType.INT_ARRAY) && (vi2.rep_type == ProglangType.INT)) {
049      return ProglangType.INT;
050    } else if ((vi1.rep_type == ProglangType.INT) && (vi2.rep_type == ProglangType.INT_ARRAY)) {
051      return ProglangType.INT;
052    } else if ((vi1.rep_type == ProglangType.INT) && (vi2.rep_type == ProglangType.INT)) {
053      return ProglangType.INT_ARRAY;
054    } else {
055      return null;
056    }
057  }
058
059  /**
060   * Checks if two base variables are comparable to each other.
061   *
062   * @return true if vi1 and vi2 are comparable; false otherwise
063   */
064  public static boolean checkComparability(VarInfo vi1, VarInfo vi2) {
065    return vi1.indexCompatible(vi2);
066  }
067}