patch invert (patch p, tree t) { switch (get_type (p)) { case PATCH_MODIFICATION: return patch (get_inverse (p), get_modification (p)); case PATCH_BRANCH: ASSERT (N(p) <= 1, "ambiguous application"); case PATCH_COMPOUND: { int i, n=N(p); array<patch> r(n); for (i=0; i<n; i++) { r[n-1-i]= invert (p[i], t); t= clean_apply (p[i], t); } return patch (get_type (p) == PATCH_BRANCH, r); } case PATCH_BIRTH: return patch (get_author (p), !get_birth (p)); case PATCH_AUTHOR: return patch (get_author (p), invert (p[0], t)); default: FAILED ("unsupported patch type"); return patch (); } }
bool operator == (patch p1, patch p2) { if (get_type (p1) != get_type (p2)) return false; switch (get_type (p1)) { case PATCH_MODIFICATION: return get_modification (p1) == get_modification (p2) && get_inverse (p1) == get_inverse (p2); case PATCH_COMPOUND: case PATCH_BRANCH: if (N(p1) != N(p2)) return false; for (int i=0; i<N(p1); i++) if (p1[i] != p2[i]) return false; return true; case PATCH_BIRTH: return get_birth (p1) == get_birth (p2) && get_author (p1) == get_author (p2); case PATCH_AUTHOR: return get_author (p1) == get_author (p2) && p1[0] == p2[0]; default: FAILED ("unsupported patch type"); } return false; }
tm_ostream& operator << (tm_ostream& out, patch p) { switch (get_type (p)) { case PATCH_MODIFICATION: out << get_modification (p) << " -- " << get_inverse (p); break; case PATCH_COMPOUND: if (N(p) == 0) out << "No children"; else { out << "Composite" << INDENT; for (int i=0; i<N(p); i++) out << LF << p[i]; out << UNINDENT; } break; case PATCH_BRANCH: if (N(p) == 0) out << "No branches"; else for (int i=0; i<N(p); i++) { if (i != 0) out << LF; out << "Branch " << i << INDENT << LF << p[i] << UNINDENT; } break; case PATCH_BIRTH: if (get_birth (p)) out << "Birth "; else out << "Death "; out << get_author (p); break; case PATCH_AUTHOR: out << "Author " << get_author (p) << INDENT << LF; out << p[0]; out << UNINDENT; break; default: FAILED ("unsupported patch type"); } return out; }