public override PathCond Or(PathCond other) { if (this.Is(true) || other.Is(true)) { return(TRUE); } else if (this.Is(false)) { return(other); } else if (other.Is(false)) { return(this); } else if (conds.Contains(other)) { // Reduce ((p1 & ... & pn)) | pi to pi return(other); } else if (other is Disj) { // TODO: This doesn't preserve order of disjuncts: return(other.Or(this)); } else if (other is Conj) { if ((other as Conj).conds.Contains(this)) { // Reduce (pi | (p1 & ... & pn)) to pi return(this); } else { HashList <PathCond> intersect = HashList <PathCond> .Intersection(this.conds, (other as Conj).conds); if (intersect.Count > 0) { // Reduce (p1 & ... & pn & q1 & ... & qm) | (p1 & ... & pn & r1 & ... & rk) // to (p1 & ... & pn & (q1 & ... & qm | r1 & ... & rk). // The pi go in intersect, qi in thisRest, and ri in otherRest. HashList <PathCond> thisRest = HashList <PathCond> .Difference(this.conds, intersect); HashList <PathCond> otherRest = HashList <PathCond> .Difference((other as Conj).conds, intersect); // This recursion terminates because thisRest is smaller than this.conds intersect.Add(Conj.Make(thisRest.ToArray()).Or(Conj.Make(otherRest.ToArray()))); return(Conj.Make(intersect.ToArray())); } else { return(Disj.Make(AddItem(this.conds, other))); } } } else { return(Disj.Make(this, other)); } }