From 7f42b9b7e7ca4e6e0c93d87cc26d9257c26e35fc Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 16 Apr 2016 02:20:23 +0200 Subject: [PATCH] draft third round of mutation operations to be implemented ...now about opening a sub mutator within a nested scope --- .../diff/tree-mutator-collection-binding.hpp | 14 +-- .../diff/diff-tree-application-test.cpp | 2 +- .../diff/tree-manipulation-binding-test.cpp | 87 ++++++++++++++++++- wiki/thinkPad.ichthyo.mm | 86 +++++++++++++++++- 4 files changed, 179 insertions(+), 10 deletions(-) diff --git a/src/lib/diff/tree-mutator-collection-binding.hpp b/src/lib/diff/tree-mutator-collection-binding.hpp index 8d61182bb..5438de3c8 100644 --- a/src/lib/diff/tree-mutator-collection-binding.hpp +++ b/src/lib/diff/tree-mutator-collection-binding.hpp @@ -99,7 +99,7 @@ ASSERT_VALID_SIGNATURE (CTR, Elm (GenNode const&)) ASSERT_VALID_SIGNATURE (SEL, bool(GenNode const&)) ASSERT_VALID_SIGNATURE (ASS, bool(Elm&, GenNode const&)) - ASSERT_VALID_SIGNATURE (MUT, bool(Elm&, TreeMutator::MutatorBuffer)) + ASSERT_VALID_SIGNATURE (MUT, bool(Elm&, GenNode::ID const&, TreeMutator::MutatorBuffer)) Coll& collection; @@ -332,7 +332,7 @@ template CollectionBindingBuilder - matchElement(FUN matcher) + matchElement (FUN matcher) { return { this->collection , matcher @@ -345,7 +345,7 @@ template CollectionBindingBuilder - constructFrom(FUN constructor) + constructFrom (FUN constructor) { return { this->collection , this->matches @@ -358,7 +358,7 @@ template CollectionBindingBuilder - isApplicableIf(FUN selector) + isApplicableIf (FUN selector) { return { this->collection , this->matches @@ -371,7 +371,7 @@ template CollectionBindingBuilder - assignElement(FUN setter) + assignElement (FUN setter) { return { this->collection , this->matches @@ -384,7 +384,7 @@ template CollectionBindingBuilder - buildChildMutator(FUN childMutationBuilder) + buildChildMutator (FUN childMutationBuilder) { return { this->collection , this->matches @@ -465,7 +465,7 @@ } static bool - disable_childMutation (Elm&, TreeMutator::MutatorBuffer) + disable_childMutation (Elm&, GenNode::ID const&, TreeMutator::MutatorBuffer) { return false; } diff --git a/tests/library/diff/diff-tree-application-test.cpp b/tests/library/diff/diff-tree-application-test.cpp index bfeb4cab0..3ff1f6515 100644 --- a/tests/library/diff/diff-tree-application-test.cpp +++ b/tests/library/diff/diff-tree-application-test.cpp @@ -125,7 +125,7 @@ namespace test{ DiffSeq mutationDiff() { - // prepare for direkt assignement of new value + // prepare for direct assignment of new value // NOTE: the target ID will be reconstructed, including hash GenNode childA_upper(CHILD_A.idi.getSym(), "A"); diff --git a/tests/library/diff/tree-manipulation-binding-test.cpp b/tests/library/diff/tree-manipulation-binding-test.cpp index 196c57319..bf7f0561d 100644 --- a/tests/library/diff/tree-manipulation-binding-test.cpp +++ b/tests/library/diff/tree-manipulation-binding-test.cpp @@ -71,7 +71,7 @@ namespace test{ CHILD_A("a"), // unnamed string child node CHILD_B('b'), // unnamed char child node CHILD_T(Time(12,34,56,78)), // unnamed time value child - SUB_NODE = MakeRec().type("ω").genNode(),// empty anonymous node used to open a sub scope + SUB_NODE = MakeRec().genNode(), // empty anonymous node used to open a sub scope ATTRIB_NODE = MakeRec().genNode("δ"), // empty named node to be attached as attribute δ CHILD_NODE = SUB_NODE, // yet another child node, same ID as SUB_NODE (!) GAMMA_PI("γ", 3.14159265); // happens to have the same identity (ID) as ATTRIB3AS @@ -313,6 +313,7 @@ namespace test{ using MapD = std::map; VecD target; + MapD subScopes; // now set up a binding to these opaque private structures... auto mutator = @@ -441,6 +442,90 @@ namespace test{ cout << "Content after reordering...." << join(target) < Data + { + cout << "constructor invoked on "< bool + { + cout << "match? "< bool + { + UNIMPLEMENTED ("binding for assignment"); + return false; + }) + .buildChildMutator ([&](Data& target, GenNode::ID const& subID, TreeMutator::MutatorBuffer buff) -> bool + { + UNIMPLEMENTED ("binding for sub-scope mutation"); + return false; + })); + + CHECK (isnil (target)); + CHECK (mutator3.matchSrc (ATTRIB3)); // new mutator starts out anew at the beginning + CHECK (mutator3.accept_until (ATTRIB2)); // fast forward behind attribute β + CHECK (mutator3.acceptSrc (ATTRIB3)); // and accept the second copy of attribute γ + CHECK (mutator3.matchSrc (SUB_NODE)); // this /would/ be the next source element, but... + + CHECK (not contains(join(target), "γ = 3.1415927")); + CHECK (mutator3.assignElm(GAMMA_PI)); // ...we assign a new payload to the current element first + CHECK ( contains(join(target), "γ = 3.1415927")); + CHECK (mutator3.accept_until (Ref::END)); // fast forward, since we do not want to re-order anything + cout << "Content after assignment; " + << join(target) < 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 (subMutatorBuffer->emptySrc()); + + // now use the Mutator *interface* to talk to the nested mutator... + // This code might be confusing, because in fact we're playing two roles here! + // For one, above, in the definition of mutator3 and in the declaration of MapD subScopes, + // 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...) + + subMutatorBuffer->injectNew (TYPE_X); + subMutatorBuffer->injectNew (ATTRIB3); + 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! + + // now back to parent scope.... + + // error handling: assignment might throw + GenNode differentTime{CHILD_T.idi.getSym(), Time(11,22)}; + VERIFY_ERROR (LOGIC, mutator3.assignElm (differentTime)); + + CHECK (join(target) == "γ = 3.45, α = 1, β = 2, γ = 3.1415927, Rec(ξ| β = 2 |{b, a}), b, 78:56:34.012"); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 212811311..c98fae9b1 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -1970,7 +1970,8 @@ - + + @@ -2510,6 +2511,89 @@ + + + + + + + +

+ erfordert wirklich Kooperation +

+ + +
+ + + + + + + + + + + + + + +

+ ...denn wir verwenden hier als "private" Datenstruktur +

+

+ eine etwas komische Collection von Strings, +

+

+ in die wir die String-Repräsentation der Spec-Payload schreiben. +

+

+ +

+

+ In der Praxis dagegen würde man wirklich einen privaten Datentyp verwenden, +

+

+ und dann auch voraussetzen, daß man nur Kinder dieses Typs (oder zuweisungskompatibel) bekommt. +

+

+ +

+

+ Mein Poblem hier ist, daß ich in dieser Demonstrations-Datenstruktur keine nested scopes repräsentieren kann. +

+

+ Aber hey!, es ist meine private Datenstruktur -- also kann ich einfach eine Map von nested scopes +

+

+ daneben auf die grüne Wiese stellen. Ist ja nur ein Test :-D +

+ + +
+
+
+ + + + + + +

+ ...dankenswerterweise hat der subscript-Operator von std::Map +

+

+ die nette Eigenschaft, beim ersten Zugriff auf einen neuen Key +

+

+ dessen payload per default-konstruktor zu erzeugen. +

+ + +
+ +
+