diff --git a/src/lib/diff/tree-mutator-collection-binding.hpp b/src/lib/diff/tree-mutator-collection-binding.hpp index 4e64e4c37..b7c4f5120 100644 --- a/src/lib/diff/tree-mutator-collection-binding.hpp +++ b/src/lib/diff/tree-mutator-collection-binding.hpp @@ -299,27 +299,15 @@ : false; } -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 /** locate the designated target element and build a suitable * sub-mutator for this element into the provided target buffer */ virtual bool mutateChild (GenNode const& spec, TreeMutator::MutatorBuffer targetBuff) { - if (PAR::mutateChild (spec, targetBuff)) - return true; - else // Test mode only -- - { // no other layer was able to provide a mutator - Iter targetElm = target_.locate (spec.idi); - if (targetElm) - { - targetBuff.create (TreeMutator::build()); - target_.logMutation (*targetElm); - return true; - } - return false; - } + Iter target_found = binding_.locate (spec); + return target_found? binding_.openSub (*target_found, spec.idi, targetBuff) + : false; } -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992 }; diff --git a/tests/library/diff/tree-manipulation-binding-test.cpp b/tests/library/diff/tree-manipulation-binding-test.cpp index 073284676..bc3d6985b 100644 --- a/tests/library/diff/tree-manipulation-binding-test.cpp +++ b/tests/library/diff/tree-manipulation-binding-test.cpp @@ -316,7 +316,7 @@ namespace test{ MapD subScopes; // now set up a binding to these opaque private structures... - auto mutator = + auto mutator1 = TreeMutator::build() .attach (collection(target) .constructFrom ([&](GenNode const& spec) -> Data @@ -325,28 +325,28 @@ namespace test{ return {spec.idi.getSym(), render(spec.data)}; })); - CHECK (sizeof(mutator) <= sizeof(VecD) // the buffer for pending elements - + sizeof(VecD*) // the reference to the original collection - + sizeof(void*) // the reference from the ChildCollectionMutator to the CollectionBinding - + 2 * sizeof(VecD::iterator) // one Lumiera RangeIter (comprised of pos and end iterators) - + 4 * sizeof(void*) // the four unused default configured binding functions - + 1 * sizeof(void*)); // one back reference from the closure to this scope + CHECK (sizeof(mutator1) <= sizeof(VecD) // the buffer for pending elements + + sizeof(VecD*) // the reference to the original collection + + sizeof(void*) // the reference from the ChildCollectionMutator to the CollectionBinding + + 2 * sizeof(VecD::iterator) // one Lumiera RangeIter (comprised of pos and end iterators) + + 4 * sizeof(void*) // the four unused default configured binding functions + + 1 * sizeof(void*)); // one back reference from the closure to this scope // --- first round: populate the collection --- CHECK (isnil (target)); - CHECK (mutator.emptySrc()); + CHECK (mutator1.emptySrc()); - mutator.injectNew (ATTRIB1); + mutator1.injectNew (ATTRIB1); CHECK (!isnil (target)); CHECK (contains(join(target), "≺α∣1≻")); - mutator.injectNew (ATTRIB3); - mutator.injectNew (ATTRIB3); - mutator.injectNew (CHILD_B); - mutator.injectNew (CHILD_B); - mutator.injectNew (CHILD_T); + mutator1.injectNew (ATTRIB3); + mutator1.injectNew (ATTRIB3); + mutator1.injectNew (CHILD_B); + mutator1.injectNew (CHILD_B); + mutator1.injectNew (CHILD_T); auto contents = stringify(eachElm(target)); CHECK ("≺α∣1≻" == *contents); @@ -386,7 +386,7 @@ namespace test{ })); // we have two lambdas now and thus can save on the size of one function pointer.... - CHECK (sizeof(mutator) - sizeof(mutator2) == sizeof(void*)); + CHECK (sizeof(mutator1) - sizeof(mutator2) == sizeof(void*)); CHECK (isnil (target)); // the "visible" new content is still void @@ -474,8 +474,22 @@ namespace test{ }) .buildChildMutator ([&](Data& target, GenNode::ID const& subID, TreeMutator::MutatorBuffer buff) -> bool { - UNIMPLEMENTED ("binding for sub-scope mutation"); - return false; + // use our "inside knowledge" to get at the nested scope implementation + VecD& subScope = subScopes[subID]; + buff.create ( + TreeMutator::build() + .attach (collection(subScope) + .constructFrom ([&](GenNode const& spec) -> Data + { + cout << "SubScope| constructor invoked on "< subMutatorBuffer; + InPlaceBuffer subMutatorBuffer; TreeMutator::MutatorBuffer placementHandle(subMutatorBuffer); CHECK (mutator3.mutateChild (SUB_NODE, placementHandle)); - CHECK (isnil (subScopes[SUB_NODE])); // ...this is where the nested mutator is expected to work on + CHECK (isnil (subScopes[SUB_NODE.idi])); // ...this is where the nested mutator is expected to work on CHECK (subMutatorBuffer->emptySrc()); // now use the Mutator *interface* to talk to the nested mutator... @@ -510,24 +524,36 @@ namespace test{ // the test code represents what a private data structure and binding would do. // But below we enact the TreeDiffAplicattor, which *would* use the Mutator interface // to talk to an otherwise opaque nested mutator implementation. Actually, here this - // nested opaque mutator is created on-the-fly, embedded within the .buildChildMutator(..lambda...) + // nested opaque mutator is created on-the-fly, embedded within the .buildChildMutator(..lambda...) + // Incidentally, we "just happen to know" how large the buffer needs to be to hold that mutator, + // since this is a topic beyond the scope of this test. In real usage, the DiffApplicator cares + // to provide a stack of suitably sized buffers for the nested mutators. subMutatorBuffer->injectNew (TYPE_X); - subMutatorBuffer->injectNew (ATTRIB3); + subMutatorBuffer->injectNew (ATTRIB2); subMutatorBuffer->injectNew (CHILD_B); subMutatorBuffer->injectNew (CHILD_A); - CHECK (not subMutatorBuffer->emptySrc()); - CHECK (not isnil (subScopes[SUB_NODE])); // ...and "magically" these instructions happened to insert - CHECK (join(subScopes[SUB_NODE]) == "β = 2, b, a"); // some new content into our implementation defined sub scope! + CHECK (not isnil (subScopes[SUB_NODE.idi])); // ...and "magically" these instructions happened to insert + cout << "Sub|" << join(subScopes[SUB_NODE.idi]) <