+Condition *CompoundCondition::flatten() const
+{
+ if(conditions.empty())
+ return 0;
+ else if(conditions.size()==1)
+ return conditions.front()->clone();
+
+ bool merge = true;
+ for(vector<Condition *>::const_iterator i=conditions.begin(); (merge && ++i!=conditions.end()); )
+ merge = conditions.front()->can_merge(**i, *this);
+
+ if(merge)
+ return conditions.front()->merge(conditions, *this);
+ else
+ {
+ Condition *result = 0;
+ for(vector<Condition *>::const_iterator i=conditions.begin(); i!=conditions.end(); ++i)
+ {
+ Condition *sub = (*i)->flatten();
+ if(!result)
+ result = sub;
+ else if(sub)
+ result = dispatch_flatten(result, sub);
+ }
+
+ if(result && result->is_viable())
+ return result;
+
+ delete result;
+ return 0;
+ }
+}
+
+Condition *CompoundCondition::dispatch_flatten(Condition *cond1, Condition *cond2) const
+{
+ OrCondition *or1 = dynamic_cast<OrCondition *>(cond1);
+ AndCondition *and1 = dynamic_cast<AndCondition *>(cond1);
+ OrCondition *or2 = dynamic_cast<OrCondition *>(cond2);
+ AndCondition *and2 = dynamic_cast<AndCondition *>(cond2);
+ if(or1 || or2)
+ {
+ if(or1 && or2)
+ return flatten(or1, or2);
+ else if(or1 && and2)
+ return flatten(or1, and2);
+ else if(or2 && and1)
+ return flatten(or2, and1);
+ else if(or1)
+ return flatten(or1, cond2);
+ else if(or2)
+ return flatten(or2, cond1);
+ }
+ else if(and1 || and2)
+ {
+ if(and1 && and2)
+ return flatten(and1, and2);
+ else if(and1)
+ return flatten(and1, cond2);
+ else if(and2)
+ return flatten(and2, cond1);
+ }
+ else
+ return flatten(cond1, cond2);
+
+ throw logic_error("CompoundCondition::dispatch_flatten");
+}
+
+Condition *CompoundCondition::merge_two(Condition *cond1, Condition *cond2, bool del) const
+{
+ vector<Condition *> parts;
+ parts.reserve(2);
+ parts.push_back(cond1);
+ parts.push_back(cond2);
+ Condition *result = cond1->merge(parts, *this);
+
+ if(del)
+ {
+ delete cond1;
+ delete cond2;
+
+ if(!result->is_viable())
+ {
+ delete result;
+ return 0;
+ }
+ }
+
+ return result;
+}
+
+Condition *CompoundCondition::add_merged_to(Condition *cond, CompoundCondition *target, bool del) const
+{
+ bool merged = false;
+ for(vector<Condition *>::iterator i=target->conditions.begin(); i!=target->conditions.end(); ++i)
+ if((*i)->can_merge(*cond, *target))
+ {
+ Condition *m = merge_two(cond, *i, false);
+ delete *i;
+ if(del)
+ delete cond;
+ *i = m;
+ merged = true;
+ break;
+ }
+
+ if(!merged)
+ target->add(del ? cond : cond->clone());
+
+ if(del && !target->is_viable())
+ {
+ delete target;
+ return 0;
+ }
+
+ return target;
+}
+
+Condition *CompoundCondition::merge_contents_to(CompoundCondition *cond, CompoundCondition *target) const
+{
+ for(vector<Condition *>::iterator i=cond->conditions.begin(); i!=cond->conditions.end(); ++i)
+ add_merged_to(*i, target, false);
+
+ delete cond;
+
+ if(target->is_viable())
+ return target;
+
+ delete target;
+ return 0;
+}
+
+
+AndCondition *AndCondition::clone() const