001package daikon.derive.ternary; 002 003import daikon.ValueTuple; 004import daikon.VarInfo; 005import daikon.derive.Derivation; 006import daikon.derive.ValueAndModified; 007import org.checkerframework.checker.lock.qual.GuardSatisfied; 008import org.checkerframework.dataflow.qual.Pure; 009import org.checkerframework.dataflow.qual.SideEffectFree; 010import org.plumelib.util.ArraysPlume; 011 012/** Abstract class to represent a derived variable that came from three base variables. */ 013public abstract class TernaryDerivation extends Derivation { 014 // We are Serializable, so we specify a version to allow changes to 015 // method signatures without breaking serialization. If you add or 016 // remove fields, you should change this number to the current date. 017 static final long serialVersionUID = 20020122L; 018 019 /** Original variable 1. */ 020 VarInfo base1; 021 022 /** Original variable 2. */ 023 VarInfo base2; 024 025 /** Original variable 3. */ 026 VarInfo base3; 027 028 /** 029 * Create a new TernaryDerivation from three varinfos. 030 * 031 * @param vi1 original variable 1 032 * @param vi2 original variable 2 033 * @param vi3 original variable 3 034 */ 035 protected TernaryDerivation(VarInfo vi1, VarInfo vi2, VarInfo vi3) { 036 base1 = vi1; 037 base2 = vi2; 038 base3 = vi3; 039 } 040 041 @SideEffectFree 042 @Override 043 public TernaryDerivation clone(@GuardSatisfied TernaryDerivation this) { 044 try { 045 return (TernaryDerivation) super.clone(); 046 } catch (CloneNotSupportedException e) { 047 throw new Error("This can't happen", e); 048 } 049 } 050 051 @SideEffectFree 052 @Override 053 public VarInfo[] getBases() { 054 return new VarInfo[] {base1, base2, base3}; 055 } 056 057 @Pure 058 @Override 059 public VarInfo getBase(int i) { 060 switch (i) { 061 case 0: 062 return base1; 063 case 1: 064 return base2; 065 case 2: 066 return base3; 067 default: 068 throw new Error("bad base: " + i); 069 } 070 } 071 072 @Override 073 public Derivation switchVars(VarInfo[] old_vars, VarInfo[] new_vars) { 074 TernaryDerivation result = this.clone(); 075 result.base1 = new_vars[ArraysPlume.indexOf(old_vars, result.base1)]; 076 result.base2 = new_vars[ArraysPlume.indexOf(old_vars, result.base2)]; 077 result.base3 = new_vars[ArraysPlume.indexOf(old_vars, result.base3)]; 078 return result; 079 } 080 081 @Override 082 public abstract ValueAndModified computeValueAndModified(ValueTuple full_vt); 083 084 @Pure 085 @Override 086 protected boolean isParam() { 087 return base1.isParam() || base2.isParam() || base3.isParam(); 088 } 089 090 @Override 091 public int derivedDepth() { 092 return 1 + Math.max(base1.derivedDepth(), Math.max(base2.derivedDepth(), base3.derivedDepth())); 093 } 094 095 @Override 096 public boolean canBeMissing() { 097 return base1.canBeMissing || base2.canBeMissing || base3.canBeMissing; 098 } 099 100 @Pure 101 @Override 102 public boolean isDerivedFromNonCanonical() { 103 // We insist that both are canonical, not just one. 104 return !(base1.isCanonical() && base2.isCanonical() && base3.isCanonical()); 105 } 106}