diff --git a/src/lib/diff/tree-diff-mutator-binding.cpp b/src/lib/diff/tree-diff-mutator-binding.cpp index 049a2c992..33070735c 100644 --- a/src/lib/diff/tree-diff-mutator-binding.cpp +++ b/src/lib/diff/tree-diff-mutator-binding.cpp @@ -58,30 +58,28 @@ namespace diff{ #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 + + using Mutator = Rec::Mutator; + using Content = Rec::ContentMutator; + using Iter = Content::Iter; + template<> - class DiffApplicationStrategy - : public TreeDiffInterpreter + struct DiffApplicationStrategy::ScopeFrame { - using Mutator = Rec::Mutator; - using Content = Rec::ContentMutator; - using Iter = Content::Iter; + Mutator& target; + Content content; - struct ScopeFrame + ScopeFrame(Mutator& toModify) + : target(toModify) + , content() + { } + + void init() { - Mutator& target; - Content content; - - ScopeFrame(Mutator& toModify) - : target(toModify) - , content() - { } - - void init() - { - target.swapContent (content); - content.resetPos(); - } - }; + target.swapContent (content); + content.resetPos(); + } + }; /** Storage: a stack of workspaces * used to handle nested child objects */ @@ -95,321 +93,321 @@ namespace diff{ Rec& alteredRec() { return out(); } - void - __expect_in_target (GenNode const& elm, Literal oper) - { - if (endOfData()) - throw error::State(_Fmt("Unable to %s element %s from target as demanded; " - "no (further) elements in target sequence") % oper % elm - , LUMIERA_ERROR_DIFF_CONFLICT); - - if (elm.matches(Ref::CHILD) and not srcPos()->isNamed()) - return; // allow for anonymous pick or delete of children - - if (not srcPos()->matches(elm)) - throw error::State(_Fmt("Unable to %s element %s from target as demanded; " - "found element %s on current target position instead") - % oper % elm % *srcPos() - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_further_elements (GenNode const& elm) - { - if (endOfData()) - throw error::State(_Fmt("Premature end of target sequence, still expecting element %s; " - "unable to apply diff further.") % elm - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_found (GenNode const& elm, Iter const& targetPos) - { - if (targetPos == src().end()) - throw error::State(_Fmt("Premature end of sequence; unable to locate " - "element %s in the remainder of the target.") % elm - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_successful_location (GenNode const& elm) - { - if (endOfData() - and not ( elm.matches(Ref::END) // after(_END_) -> its OK we hit the end - or (elm.matches(Ref::ATTRIBS) and src().children.empty()))) // after(_ATTRIBS_) -> if there are no children, it's OK to hit the end - throw error::State(_Fmt("Unable locate position 'after(%s)'") % elm.idi - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_valid_parent_scope (GenNode::ID const& idi) - { - if (scopes_.empty()) - throw error::State(_Fmt("Unbalanced child scope bracketing tokens in diff; " - "When leaving scope %s, we fell out of root scope.") % idi.getSym() - , LUMIERA_ERROR_DIFF_CONFLICT); - - if (alteredRec().empty()) - throw error::State(_Fmt("Corrupted state. When leaving scope %s, " - "we found an empty parent scope.") % idi.getSym() - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_end_of_scope (GenNode::ID const& idi) - { - if (not endOfData()) - throw error::State(_Fmt("Incomplete diff: when about to leave scope %s, " - "not all previously existing elements have been confirmed by the diff. " - "At least one spurious element %s was left over") % idi.getSym() % *srcPos() - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - - Iter - find_in_current_scope (GenNode const& elm) - { - Iter end_of_scope = src().currIsAttrib()? src().attribs.end() - : src().children.end(); - return std::find_if (srcPos() - ,end_of_scope - ,[&](auto& entry) - { - return entry.matches(elm); - }); - } - - GenNode const& - find_child (GenNode::ID const& idi) - { - if (alteredRec().empty()) - throw error::State(_Fmt("Attempt to mutate element %s, but current target data scope is empty. " - "Sender and receiver out of sync?") % idi.getSym() - , LUMIERA_ERROR_DIFF_CONFLICT); - - // Short-cut-mutation: look at the last element. - // this should be the one just added. BUT NOTE: this fails - // when adding an attribute after entering the child scope. - // Since attributes are typically values and not mutated, - // this inaccuracy was deemed acceptable - auto& current = out().accessLast(); - if (Ref::THIS.matches(idi) or current.matches(idi)) - return current; - - for (auto & child : alteredRec()) - if (child.idi == idi) - return child; - - throw error::State(_Fmt("Attempt to mutate non existing child record; unable to locate child %s " - "after applying the diff. Current scope: %s") % idi.getSym() % alteredRec() - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - move_into_new_sequence (Iter pos) - { - if (src().currIsAttrib()) - out().appendAttrib (move(*pos)); //////////////TICKET #969 was it a good idea to allow adding attributes "after the fact"? - else - out().appendChild (move(*pos)); - } + void + DiffApplicationStrategy::__expect_in_target (GenNode const& elm, Literal oper) + { + if (endOfData()) + throw error::State(_Fmt("Unable to %s element %s from target as demanded; " + "no (further) elements in target sequence") % oper % elm + , LUMIERA_ERROR_DIFF_CONFLICT); + + if (elm.matches(Ref::CHILD) and not srcPos()->isNamed()) + return; // allow for anonymous pick or delete of children + + if (not srcPos()->matches(elm)) + throw error::State(_Fmt("Unable to %s element %s from target as demanded; " + "found element %s on current target position instead") + % oper % elm % *srcPos() + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + DiffApplicationStrategy::__expect_further_elements (GenNode const& elm) + { + if (endOfData()) + throw error::State(_Fmt("Premature end of target sequence, still expecting element %s; " + "unable to apply diff further.") % elm + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + DiffApplicationStrategy::__expect_found (GenNode const& elm, Iter const& targetPos) + { + if (targetPos == src().end()) + throw error::State(_Fmt("Premature end of sequence; unable to locate " + "element %s in the remainder of the target.") % elm + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + DiffApplicationStrategy::__expect_successful_location (GenNode const& elm) + { + if (endOfData() + and not ( elm.matches(Ref::END) // after(_END_) -> its OK we hit the end + or (elm.matches(Ref::ATTRIBS) and src().children.empty()))) // after(_ATTRIBS_) -> if there are no children, it's OK to hit the end + throw error::State(_Fmt("Unable locate position 'after(%s)'") % elm.idi + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + DiffApplicationStrategy::__expect_valid_parent_scope (GenNode::ID const& idi) + { + if (scopes_.empty()) + throw error::State(_Fmt("Unbalanced child scope bracketing tokens in diff; " + "When leaving scope %s, we fell out of root scope.") % idi.getSym() + , LUMIERA_ERROR_DIFF_CONFLICT); + + if (alteredRec().empty()) + throw error::State(_Fmt("Corrupted state. When leaving scope %s, " + "we found an empty parent scope.") % idi.getSym() + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + DiffApplicationStrategy::__expect_end_of_scope (GenNode::ID const& idi) + { + if (not endOfData()) + throw error::State(_Fmt("Incomplete diff: when about to leave scope %s, " + "not all previously existing elements have been confirmed by the diff. " + "At least one spurious element %s was left over") % idi.getSym() % *srcPos() + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + + Iter + DiffApplicationStrategy::find_in_current_scope (GenNode const& elm) + { + Iter end_of_scope = src().currIsAttrib()? src().attribs.end() + : src().children.end(); + return std::find_if (srcPos() + ,end_of_scope + ,[&](auto& entry) + { + return entry.matches(elm); + }); + } + + GenNode const& + DiffApplicationStrategy::find_child (GenNode::ID const& idi) + { + if (alteredRec().empty()) + throw error::State(_Fmt("Attempt to mutate element %s, but current target data scope is empty. " + "Sender and receiver out of sync?") % idi.getSym() + , LUMIERA_ERROR_DIFF_CONFLICT); + + // Short-cut-mutation: look at the last element. + // this should be the one just added. BUT NOTE: this fails + // when adding an attribute after entering the child scope. + // Since attributes are typically values and not mutated, + // this inaccuracy was deemed acceptable + auto& current = out().accessLast(); + if (Ref::THIS.matches(idi) or current.matches(idi)) + return current; + + for (auto & child : alteredRec()) + if (child.idi == idi) + return child; + + throw error::State(_Fmt("Attempt to mutate non existing child record; unable to locate child %s " + "after applying the diff. Current scope: %s") % idi.getSym() % alteredRec() + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + DiffApplicationStrategy::move_into_new_sequence (Iter pos) + { + if (src().currIsAttrib()) + out().appendAttrib (move(*pos)); //////////////TICKET #969 was it a good idea to allow adding attributes "after the fact"? + else + out().appendChild (move(*pos)); + } #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - - /* == Forwarding: error handling == */ - - void - __expect_in_target (GenNode const& elm, Literal oper) - { - - } - - void - __expect_further_elements (GenNode const& elm) - { - - } - - void - __fail_not_found (GenNode const& elm) - { - - } - - void - __expect_end_of_scope (GenNode::ID const& idi) - { - - } - - void - __expect_valid_parent_scope (GenNode::ID const& idi) - { - - } - - - /* == Forwarding: mutation primitives == */ - - void - skipSrc() - { - UNIMPLEMENTED("skip next src element and advance abstract source position"); - } - - void - injectNew (GenNode const& n) - { - UNIMPLEMENTED("inject a new element at current abstract position"); - } - - bool - matchSrc (GenNode const& n) - { - UNIMPLEMENTED("ensure the next source element matches with given spec"); - } - - bool - acceptSrc (GenNode const& n) - { - UNIMPLEMENTED("accept existing element, when matching the given spec"); - } - - bool - findSrc (GenNode const& n) - { - UNIMPLEMENTED("locate designated element and accept it at current position"); - } - - bool - accept_until (GenNode const& refMark) - { - UNIMPLEMENTED("repeatedly accept until encountering the mark"); - } - - void - assignElm (GenNode const& n) - { - UNIMPLEMENTED("locate already accepted element and assign given new payload"); - } - - void - open_subScope (GenNode const& n) - { - UNIMPLEMENTED("locate already accepted element and open recursive sub-scope for mutation"); - } - - void - close_subScope() - { - UNIMPLEMENTED("finish and leave sub scope and return to invoking parent scope"); - } - - - - /* == Implementation of the list diff application primitives == */ - - virtual void - ins (GenNode const& n) override - { - injectNew (n); - } - - virtual void - del (GenNode const& n) override - { - __expect_in_target(n, "remove"); - skipSrc(); - } - - virtual void - pick (GenNode const& n) override - { - __expect_in_target(n, "pick"); - acceptSrc (n); - } - - virtual void - skip (GenNode const& n) override - { - __expect_further_elements (n); - skipSrc(); - } // assume the actual content has been moved away by a previous find() - - virtual void - find (GenNode const& n) override - { - __expect_further_elements (n); - // consume and leave waste, expected to be cleaned-up by skip() later - if (not findSrc(n)); - __fail_not_found (n); - } - - - /* == Implementation of the tree diff application primitives == */ - - /** cue to a position behind the named node, - * thereby picking (accepting) all traversed elements - * into the reshaped new data structure as-is */ - virtual void - after (GenNode const& n) override - { - if (not accept_until(n)) - __fail_not_found (n); - } - - /** assignment of changed value in one step */ - virtual void - set (GenNode const& n) override - { - assignElm (n); - } - - /** open nested scope to apply diff to child object */ - virtual void - mut (GenNode const& n) override - { - open_subScope (n); - + + /* == Forwarding: error handling == */ + + void + DiffApplicationStrategy::__expect_in_target (GenNode const& elm, Literal oper) + { + + } + + void + DiffApplicationStrategy::__expect_further_elements (GenNode const& elm) + { + + } + + void + DiffApplicationStrategy::__fail_not_found (GenNode const& elm) + { + + } + + void + DiffApplicationStrategy::__expect_end_of_scope (GenNode::ID const& idi) + { + + } + + void + DiffApplicationStrategy::__expect_valid_parent_scope (GenNode::ID const& idi) + { + + } + + + /* == Forwarding: mutation primitives == */ + + void + DiffApplicationStrategy::skipSrc() + { + UNIMPLEMENTED("skip next src element and advance abstract source position"); + } + + void + DiffApplicationStrategy::injectNew (GenNode const& n) + { + UNIMPLEMENTED("inject a new element at current abstract position"); + } + + bool + DiffApplicationStrategy::matchSrc (GenNode const& n) + { + UNIMPLEMENTED("ensure the next source element matches with given spec"); + } + + bool + DiffApplicationStrategy::acceptSrc (GenNode const& n) + { + UNIMPLEMENTED("accept existing element, when matching the given spec"); + } + + bool + DiffApplicationStrategy::findSrc (GenNode const& n) + { + UNIMPLEMENTED("locate designated element and accept it at current position"); + } + + bool + DiffApplicationStrategy::accept_until (GenNode const& refMark) + { + UNIMPLEMENTED("repeatedly accept until encountering the mark"); + } + + void + DiffApplicationStrategy::assignElm (GenNode const& n) + { + UNIMPLEMENTED("locate already accepted element and assign given new payload"); + } + + void + DiffApplicationStrategy::open_subScope (GenNode const& n) + { + UNIMPLEMENTED("locate already accepted element and open recursive sub-scope for mutation"); + } + + void + DiffApplicationStrategy::close_subScope() + { + UNIMPLEMENTED("finish and leave sub scope and return to invoking parent scope"); + } + + + + /* == Implementation of the list diff application primitives == */ + + void + DiffApplicationStrategy::ins (GenNode const& n) + { + injectNew (n); + } + + void + DiffApplicationStrategy::del (GenNode const& n) + { + __expect_in_target(n, "remove"); + skipSrc(); + } + + void + DiffApplicationStrategy::pick (GenNode const& n) + { + __expect_in_target(n, "pick"); + acceptSrc (n); + } + + void + DiffApplicationStrategy::skip (GenNode const& n) + { + __expect_further_elements (n); + skipSrc(); + } // assume the actual content has been moved away by a previous find() + + void + DiffApplicationStrategy::find (GenNode const& n) + { + __expect_further_elements (n); + // consume and leave waste, expected to be cleaned-up by skip() later + if (not findSrc(n)); + __fail_not_found (n); + } + + + /* == Implementation of the tree diff application primitives == */ + + /** cue to a position behind the named node, + * thereby picking (accepting) all traversed elements + * into the reshaped new data structure as-is */ + void + DiffApplicationStrategy::after (GenNode const& n) + { + if (not accept_until(n)) + __fail_not_found (n); + } + + /** assignment of changed value in one step */ + void + DiffApplicationStrategy::set (GenNode const& n) + { + assignElm (n); + } + + /** open nested scope to apply diff to child object */ + void + DiffApplicationStrategy::mut (GenNode const& n) + { + open_subScope (n); + #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - Rec const& childRecord = child.data.get(); - TRACE (diff, "tree-diff: ENTER scope %s", cStr(childRecord)); + Rec const& childRecord = child.data.get(); + TRACE (diff, "tree-diff: ENTER scope %s", cStr(childRecord)); #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - } - - /** finish and leave child object scope, return to parent */ - virtual void - emu (GenNode const& n) override - { + } + + /** finish and leave child object scope, return to parent */ + void + DiffApplicationStrategy::emu (GenNode const& n) + { #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - TRACE (diff, "tree-diff: LEAVE scope %s", cStr(describeScope())); + TRACE (diff, "tree-diff: LEAVE scope %s", cStr(describeScope())); #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - - __expect_end_of_scope (n.idi); - close_subScope(); - __expect_valid_parent_scope (n.idi); - } - - - public: - explicit - DiffApplicationStrategy(DiffMutable& targetBinding) - { - TODO("attach to the given Target"); + + __expect_end_of_scope (n.idi); + close_subScope(); + __expect_valid_parent_scope (n.idi); + } + + + + void + DiffApplicationStrategy::initDiffApplication() + { + TODO("(re)initialise the diff application machinery"); #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - scopes_.emplace(mutableTargetRecord); + REQUIRE (1 == scopes_.size()); + scopes_.top().init(); #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - } - - void - initDiffApplication() - { - TODO("(re)initialise the diff application machinery"); -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - REQUIRE (1 == scopes_.size()); - scopes_.top().init(); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - } - }; + } + + + + /* ==== trigger code generation of the generic part ==== */ + + /************************************************************************/ + /* explicit template instantiation DiffApplicationStrategy */ + /************************************************************************/ + + template class DiffApplicationStrategy; diff --git a/src/lib/diff/tree-diff-mutator-binding.hpp b/src/lib/diff/tree-diff-mutator-binding.hpp index 02de73b68..f27baf741 100644 --- a/src/lib/diff/tree-diff-mutator-binding.hpp +++ b/src/lib/diff/tree-diff-mutator-binding.hpp @@ -228,299 +228,60 @@ namespace diff{ Rec& alteredRec() { return out(); } - void - __expect_in_target (GenNode const& elm, Literal oper) - { - if (endOfData()) - throw error::State(_Fmt("Unable to %s element %s from target as demanded; " - "no (further) elements in target sequence") % oper % elm - , LUMIERA_ERROR_DIFF_CONFLICT); - - if (elm.matches(Ref::CHILD) and not srcPos()->isNamed()) - return; // allow for anonymous pick or delete of children - - if (not srcPos()->matches(elm)) - throw error::State(_Fmt("Unable to %s element %s from target as demanded; " - "found element %s on current target position instead") - % oper % elm % *srcPos() - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_further_elements (GenNode const& elm) - { - if (endOfData()) - throw error::State(_Fmt("Premature end of target sequence, still expecting element %s; " - "unable to apply diff further.") % elm - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_found (GenNode const& elm, Iter const& targetPos) - { - if (targetPos == src().end()) - throw error::State(_Fmt("Premature end of sequence; unable to locate " - "element %s in the remainder of the target.") % elm - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_successful_location (GenNode const& elm) - { - if (endOfData() - and not ( elm.matches(Ref::END) // after(_END_) -> its OK we hit the end - or (elm.matches(Ref::ATTRIBS) and src().children.empty()))) // after(_ATTRIBS_) -> if there are no children, it's OK to hit the end - throw error::State(_Fmt("Unable locate position 'after(%s)'") % elm.idi - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_valid_parent_scope (GenNode::ID const& idi) - { - if (scopes_.empty()) - throw error::State(_Fmt("Unbalanced child scope bracketing tokens in diff; " - "When leaving scope %s, we fell out of root scope.") % idi.getSym() - , LUMIERA_ERROR_DIFF_CONFLICT); - - if (alteredRec().empty()) - throw error::State(_Fmt("Corrupted state. When leaving scope %s, " - "we found an empty parent scope.") % idi.getSym() - , LUMIERA_ERROR_DIFF_CONFLICT); - } - - void - __expect_end_of_scope (GenNode::ID const& idi) - { - if (not endOfData()) - throw error::State(_Fmt("Incomplete diff: when about to leave scope %s, " - "not all previously existing elements have been confirmed by the diff. " - "At least one spurious element %s was left over") % idi.getSym() % *srcPos() - , LUMIERA_ERROR_DIFF_CONFLICT); - } + void __expect_in_target (GenNode const& elm, Literal oper); + void __expect_further_elements (GenNode const& elm); + void __expect_found (GenNode const& elm, Iter const& targetPos); + void __expect_successful_location (GenNode const& elm); + void __expect_valid_parent_scope (GenNode::ID const& idi); + void __expect_end_of_scope (GenNode::ID const& idi); - Iter - find_in_current_scope (GenNode const& elm) - { - Iter end_of_scope = src().currIsAttrib()? src().attribs.end() - : src().children.end(); - return std::find_if (srcPos() - ,end_of_scope - ,[&](auto& entry) - { - return entry.matches(elm); - }); - } + Iter find_in_current_scope (GenNode const& elm); - GenNode const& - find_child (GenNode::ID const& idi) - { - if (alteredRec().empty()) - throw error::State(_Fmt("Attempt to mutate element %s, but current target data scope is empty. " - "Sender and receiver out of sync?") % idi.getSym() - , LUMIERA_ERROR_DIFF_CONFLICT); - - // Short-cut-mutation: look at the last element. - // this should be the one just added. BUT NOTE: this fails - // when adding an attribute after entering the child scope. - // Since attributes are typically values and not mutated, - // this inaccuracy was deemed acceptable - auto& current = out().accessLast(); - if (Ref::THIS.matches(idi) or current.matches(idi)) - return current; - - for (auto & child : alteredRec()) - if (child.idi == idi) - return child; - - throw error::State(_Fmt("Attempt to mutate non existing child record; unable to locate child %s " - "after applying the diff. Current scope: %s") % idi.getSym() % alteredRec() - , LUMIERA_ERROR_DIFF_CONFLICT); - } + GenNode const& find_child (GenNode::ID const& idi); - void - move_into_new_sequence (Iter pos) - { - if (src().currIsAttrib()) - out().appendAttrib (move(*pos)); //////////////TICKET #969 was it a good idea to allow adding attributes "after the fact"? - else - out().appendChild (move(*pos)); - } + void move_into_new_sequence (Iter pos); #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 /* == Forwarding: error handling == */ - void - __expect_in_target (GenNode const& elm, Literal oper) - { - - } + void __expect_in_target (GenNode const& elm, Literal oper); + void __expect_further_elements (GenNode const& elm); + void __fail_not_found (GenNode const& elm); + void __expect_end_of_scope (GenNode::ID const& idi); + void __expect_valid_parent_scope (GenNode::ID const& idi); - void - __expect_further_elements (GenNode const& elm) - { - - } - - void - __fail_not_found (GenNode const& elm) - { - - } - - void - __expect_end_of_scope (GenNode::ID const& idi) - { - - } - - void - __expect_valid_parent_scope (GenNode::ID const& idi) - { - - } /* == Forwarding: mutation primitives == */ - void - skipSrc() - { - UNIMPLEMENTED("skip next src element and advance abstract source position"); - } - - void - injectNew (GenNode const& n) - { - UNIMPLEMENTED("inject a new element at current abstract position"); - } - - bool - matchSrc (GenNode const& n) - { - UNIMPLEMENTED("ensure the next source element matches with given spec"); - } - - bool - acceptSrc (GenNode const& n) - { - UNIMPLEMENTED("accept existing element, when matching the given spec"); - } - - bool - findSrc (GenNode const& n) - { - UNIMPLEMENTED("locate designated element and accept it at current position"); - } - - bool - accept_until (GenNode const& refMark) - { - UNIMPLEMENTED("repeatedly accept until encountering the mark"); - } - - void - assignElm (GenNode const& n) - { - UNIMPLEMENTED("locate already accepted element and assign given new payload"); - } - - void - open_subScope (GenNode const& n) - { - UNIMPLEMENTED("locate already accepted element and open recursive sub-scope for mutation"); - } - - void - close_subScope() - { - UNIMPLEMENTED("finish and leave sub scope and return to invoking parent scope"); - } + void skipSrc(); + void injectNew (GenNode const& n); + bool matchSrc (GenNode const& n); + bool acceptSrc (GenNode const& n); + bool findSrc (GenNode const& n); + bool accept_until (GenNode const& refMark); + void assignElm (GenNode const& n); + void open_subScope (GenNode const& n); + void close_subScope(); /* == Implementation of the list diff application primitives == */ - virtual void - ins (GenNode const& n) override - { - injectNew (n); - } - - virtual void - del (GenNode const& n) override - { - __expect_in_target(n, "remove"); - skipSrc(); - } - - virtual void - pick (GenNode const& n) override - { - __expect_in_target(n, "pick"); - acceptSrc (n); - } - - virtual void - skip (GenNode const& n) override - { - __expect_further_elements (n); - skipSrc(); - } // assume the actual content has been moved away by a previous find() - - virtual void - find (GenNode const& n) override - { - __expect_further_elements (n); - // consume and leave waste, expected to be cleaned-up by skip() later - if (not findSrc(n)); - __fail_not_found (n); - } + virtual void ins (GenNode const& n) override; + virtual void del (GenNode const& n) override; + virtual void pick (GenNode const& n) override; + virtual void skip (GenNode const& n) override; + virtual void find (GenNode const& n) override; /* == Implementation of the tree diff application primitives == */ - /** cue to a position behind the named node, - * thereby picking (accepting) all traversed elements - * into the reshaped new data structure as-is */ - virtual void - after (GenNode const& n) override - { - if (not accept_until(n)) - __fail_not_found (n); - } - - /** assignment of changed value in one step */ - virtual void - set (GenNode const& n) override - { - assignElm (n); - } - - /** open nested scope to apply diff to child object */ - virtual void - mut (GenNode const& n) override - { - open_subScope (n); - -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - Rec const& childRecord = child.data.get(); - TRACE (diff, "tree-diff: ENTER scope %s", cStr(childRecord)); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - } - - /** finish and leave child object scope, return to parent */ - virtual void - emu (GenNode const& n) override - { -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - TRACE (diff, "tree-diff: LEAVE scope %s", cStr(describeScope())); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - - __expect_end_of_scope (n.idi); - close_subScope(); - __expect_valid_parent_scope (n.idi); - } + virtual void after(GenNode const& n) override; + virtual void set (GenNode const& n) override; + virtual void mut (GenNode const& n) override; + virtual void emu (GenNode const& n) override; public: @@ -533,17 +294,14 @@ namespace diff{ #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 } - void - initDiffApplication() - { - TODO("(re)initialise the diff application machinery"); -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - REQUIRE (1 == scopes_.size()); - scopes_.top().init(); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 - } + void initDiffApplication(); }; + + /** use the explicit instantiation provided in library module */ + extern template class DiffApplicationStrategy; + + }} // namespace lib::diff #endif /*LIB_DIFF_TREE_DIFF_MUTATOR_BINDING_H*/