draft third round of mutation operations to be implemented
...now about opening a sub mutator within a nested scope
This commit is contained in:
parent
54fb335a9c
commit
7f42b9b7e7
4 changed files with 179 additions and 10 deletions
|
|
@ -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<class FUN>
|
||||
CollectionBindingBuilder<COLL, FUN ,CTR,SEL,ASS,MUT>
|
||||
matchElement(FUN matcher)
|
||||
matchElement (FUN matcher)
|
||||
{
|
||||
return { this->collection
|
||||
, matcher
|
||||
|
|
@ -345,7 +345,7 @@
|
|||
|
||||
template<class FUN>
|
||||
CollectionBindingBuilder<COLL,MAT, FUN ,SEL,ASS,MUT>
|
||||
constructFrom(FUN constructor)
|
||||
constructFrom (FUN constructor)
|
||||
{
|
||||
return { this->collection
|
||||
, this->matches
|
||||
|
|
@ -358,7 +358,7 @@
|
|||
|
||||
template<class FUN>
|
||||
CollectionBindingBuilder<COLL,MAT,CTR, FUN ,ASS,MUT>
|
||||
isApplicableIf(FUN selector)
|
||||
isApplicableIf (FUN selector)
|
||||
{
|
||||
return { this->collection
|
||||
, this->matches
|
||||
|
|
@ -371,7 +371,7 @@
|
|||
|
||||
template<class FUN>
|
||||
CollectionBindingBuilder<COLL,MAT,CTR,SEL, FUN ,MUT>
|
||||
assignElement(FUN setter)
|
||||
assignElement (FUN setter)
|
||||
{
|
||||
return { this->collection
|
||||
, this->matches
|
||||
|
|
@ -384,7 +384,7 @@
|
|||
|
||||
template<class FUN>
|
||||
CollectionBindingBuilder<COLL,MAT,CTR,SEL,ASS, FUN >
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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<string, VecD>;
|
||||
|
||||
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) <<endl;
|
||||
|
||||
|
||||
// --- third round: mutate data and sub-scopes ---
|
||||
|
||||
|
||||
// This time we build the Mutator bindings in a way to allow mutation
|
||||
// For one, "mutation" means to assign a changed value to a simple node / attribute.
|
||||
// And beyond that, mutation entails to open a nested scope and delve into that recursively.
|
||||
// Here, as this is really just a test and demonstration, we implement those nested scopes aside
|
||||
// managed within a map and keyed by the sub node's ID.
|
||||
auto mutator3 =
|
||||
TreeMutator::build()
|
||||
.attach (collection(target)
|
||||
.constructFrom ([&](GenNode const& spec) -> Data
|
||||
{
|
||||
cout << "constructor invoked on "<<spec<<endl;
|
||||
return {spec.idi.getSym(), render(spec.data)};
|
||||
})
|
||||
.matchElement ([&](GenNode const& spec, Data const& elm) -> bool
|
||||
{
|
||||
cout << "match? "<<spec.idi.getSym()<<"=?="<<elm.key<<endl;
|
||||
return spec.idi.getSym() == elm.key;
|
||||
})
|
||||
.assignElement ([&](Data& target, GenNode const& spec) -> 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) <<endl;
|
||||
|
||||
|
||||
// prepare for recursion into sub scope..
|
||||
// Since this is a demonstration, we do not actually recurse into anything,
|
||||
// rather we invoke the operations on a nested mutator right from here.
|
||||
|
||||
InPlaceBuffer<TreeMutator, sizeof(mutator3)> 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");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1970,7 +1970,8 @@
|
|||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1457741609884" ID="ID_1827838196" MODIFIED="1457741617108" TEXT="bin ich zuständig?">
|
||||
<node CREATED="1458094312266" ID="ID_233521483" MODIFIED="1458094316157" TEXT="isApplicable"/>
|
||||
<node CREATED="1458094316697" ID="ID_839136400" MODIFIED="1458094326204" TEXT="Festlegung:">
|
||||
<node CREATED="1458094316697" ID="ID_839136400" MODIFIED="1460755327191" TEXT="Festlegung:">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1458094327095" ID="ID_306307671" MODIFIED="1458094334354" TEXT="nur auf Basis der spec"/>
|
||||
<node CREATED="1458094334991" ID="ID_903070750" MODIFIED="1458094343401" TEXT="ohne Daten-Introspektion"/>
|
||||
</node>
|
||||
|
|
@ -2510,6 +2511,89 @@
|
|||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1460762013033" ID="ID_758721262" MODIFIED="1460762015093" TEXT="Mutation">
|
||||
<node CREATED="1460762015777" ID="ID_59179895" MODIFIED="1460762061424">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
erfordert <i>wirklich</i> Kooperation
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1460762025520" ID="ID_955853878" MODIFIED="1460762032675" TEXT="zwischen dem gesendeten Diff"/>
|
||||
<node CREATED="1460762033119" ID="ID_863964003" MODIFIED="1460762045704" TEXT="und der empfangenden Implementierungs-Datenstruktur"/>
|
||||
</node>
|
||||
<node CREATED="1460762065371" ID="ID_698989532" MODIFIED="1460762096048" TEXT="brauche wohl "Introspection light"">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
<node CREATED="1460762101046" ID="ID_1593562435" MODIFIED="1460762111448" TEXT="damit ich einen Sub-Scope vorbereiten kann"/>
|
||||
<node CREATED="1460762111924" ID="ID_125430023" MODIFIED="1460762120759" TEXT="in separater privater Datenstrukcur"/>
|
||||
<node CREATED="1460762121259" ID="ID_1558869553" MODIFIED="1460762308964" TEXT="ist aber nur rein hier im Test ein Problem">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...denn wir verwenden hier als "private" Datenstruktur
|
||||
</p>
|
||||
<p>
|
||||
eine etwas komische Collection von Strings,
|
||||
</p>
|
||||
<p>
|
||||
in die wir die String-Repräsentation der Spec-Payload schreiben.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
In der Praxis dagegen würde man wirklich einen privaten Datentyp verwenden,
|
||||
</p>
|
||||
<p>
|
||||
und dann auch voraussetzen, daß man <i>nur</i> Kinder dieses Typs (oder zuweisungskompatibel) bekommt.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Mein Poblem hier ist, daß ich in dieser Demonstrations-Datenstruktur keine nested scopes repräsentieren kann.
|
||||
</p>
|
||||
<p>
|
||||
Aber hey!, es ist meine private Datenstruktur -- also kann ich einfach eine Map von nested scopes
|
||||
</p>
|
||||
<p>
|
||||
daneben auf die grüne Wiese stellen. Ist ja nur ein Test :-D
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1460762330487" ID="ID_914518092" MODIFIED="1460762395843" TEXT="Nein! Schwein gehabt">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...dankenswerterweise hat der subscript-Operator von std::Map
|
||||
</p>
|
||||
<p>
|
||||
die nette Eigenschaft, beim ersten Zugriff auf einen neuen Key
|
||||
</p>
|
||||
<p>
|
||||
dessen payload per default-konstruktor zu erzeugen.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1458868836883" ID="ID_717368167" MODIFIED="1458868851053" TEXT="Beobachtungen">
|
||||
<node CREATED="1458868852849" ID="ID_1641586585" MODIFIED="1458869076689" TEXT="Sonderbarer "this"-Typ">
|
||||
|
|
|
|||
Loading…
Reference in a new issue