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 static final long serialVersionUID = 20020122L; 015 016 /** Original variable 1. */ 017 VarInfo base1; 018 019 /** Original variable 2. */ 020 VarInfo base2; 021 022 /** Original variable 3. */ 023 VarInfo base3; 024 025 /** 026 * Create a new TernaryDerivation from three varinfos. 027 * 028 * @param vi1 original variable 1 029 * @param vi2 original variable 2 030 * @param vi3 original variable 3 031 */ 032 protected TernaryDerivation(VarInfo vi1, VarInfo vi2, VarInfo vi3) { 033 base1 = vi1; 034 base2 = vi2; 035 base3 = vi3; 036 } 037 038 @SideEffectFree 039 @Override 040 public TernaryDerivation clone(@GuardSatisfied TernaryDerivation this) { 041 try { 042 return (TernaryDerivation) super.clone(); 043 } catch (CloneNotSupportedException e) { 044 throw new Error("This can't happen", e); 045 } 046 } 047 048 @SideEffectFree 049 @Override 050 public VarInfo[] getBases() { 051 return new VarInfo[] {base1, base2, base3}; 052 } 053 054 @Pure 055 @Override 056 public VarInfo getBase(int i) { 057 switch (i) { 058 case 0: 059 return base1; 060 case 1: 061 return base2; 062 case 2: 063 return base3; 064 default: 065 throw new Error("bad base: " + i); 066 } 067 } 068 069 @Override 070 public Derivation switchVars(VarInfo[] old_vars, VarInfo[] new_vars) { 071 TernaryDerivation result = this.clone(); 072 result.base1 = new_vars[ArraysPlume.indexOf(old_vars, result.base1)]; 073 result.base2 = new_vars[ArraysPlume.indexOf(old_vars, result.base2)]; 074 result.base3 = new_vars[ArraysPlume.indexOf(old_vars, result.base3)]; 075 return result; 076 } 077 078 @Override 079 public abstract ValueAndModified computeValueAndModified(ValueTuple full_vt); 080 081 @Pure 082 @Override 083 protected boolean isParam() { 084 return base1.isParam() || base2.isParam() || base3.isParam(); 085 } 086 087 @Override 088 public int derivedDepth() { 089 return 1 + Math.max(base1.derivedDepth(), Math.max(base2.derivedDepth(), base3.derivedDepth())); 090 } 091 092 @Override 093 public boolean canBeMissing() { 094 return base1.canBeMissing || base2.canBeMissing || base3.canBeMissing; 095 } 096 097 @Pure 098 @Override 099 public boolean isDerivedFromNonCanonical() { 100 // We insist that both are canonical, not just one. 101 return !(base1.isCanonical() && base2.isCanonical() && base3.isCanonical()); 102 } 103}