implement fast-forward and assignment to value

...all of this implementation boils down to slightly adjusting
the code written for the test-mutation-target. Insofar it pays off now
having implemented this diagnostic and demonstration first.

Moreover I'm implementing this basic scheme of "diff application"
roughly the fourth time, thus things kindof fall into place now.
What's really hard is all those layers of abstraction in between.

Lesson learned (after being off for three weeks, due to LAC and
other obligations): I really need to document the meaning of the
closures, and I need to document the "abstract operational semantics"
of diff application, otherwise no one will be able to provide
the correct closures.
This commit is contained in:
Fischlurch 2016-04-17 01:07:07 +02:00
parent 7f42b9b7e7
commit 8167fbff77
5 changed files with 68 additions and 49 deletions

View file

@ -146,19 +146,31 @@
return pos;
}
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992
iterator
locate (GenNode::ID const& targetID)
locate (GenNode const& targetSpec)
{
if (!empty() and content_.back().matches(targetID))
if (not collection.empty() and matches (targetSpec, collection.back()))
return lastElm();
else
return search (targetID, eachElm(content_));
return search (targetSpec, eachElm(collection));
}
private:
/** @internal technicality
* Our iterator is actually a Lumiera RangeIter, and thus we need
* to construct a raw collection iterator pointing to the aftmost element
* and then create a range from this iterator and the `end()` iterator.
*/
iterator
lastElm()
{
using raw_iter = typename CollectionBinding::Coll::iterator;
return iterator (raw_iter(&collection.back()), collection.end());
}
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992
};
/**
* Attach to collection: Building block for a concrete `TreeMutator`.
* This decorator will be outfitted with actual binding and closures
@ -250,7 +262,6 @@
return found;
}
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #992
/** repeatedly accept, until after the designated location */
virtual bool
accept_until (GenNode const& spec)
@ -259,25 +270,23 @@
if (spec.matches (Ref::END))
for ( ; pos_; ++pos_)
target_.inject (move(*pos_), "accept_until END");
binding_.inject (move(*pos_));
else
{
string logMsg{"accept_until "+spec.idi.getSym()};
while (pos_ and not TestWireTap::matchSrc(spec))
while (pos_ and not ChildCollectionMutator::matchSrc(spec))
{
target_.inject (move(*pos_), logMsg);
binding_.inject (move(*pos_));
++pos_;
}
if (TestWireTap::matchSrc(spec))
if (ChildCollectionMutator::matchSrc(spec))
{
target_.inject (move(*pos_), logMsg);
binding_.inject (move(*pos_));
++pos_;
}
else
foundTarget = false;
}
return PAR::accept_until(spec)
or foundTarget;
return foundTarget;
}
/** locate element already accepted into the target sequence
@ -285,17 +294,12 @@
virtual bool
assignElm (GenNode const& spec)
{
Iter targetElm = target_.locate (spec.idi);
if (targetElm)
{
string logOldPayload{render(targetElm->data)};
*targetElm = spec;
target_.logAssignment (*targetElm, logOldPayload);
}
return PAR::assignElm(spec)
or targetElm;
Iter target_found = binding_.locate (spec);
return target_found? binding_.assign (*target_found, spec)
: 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

View file

@ -106,13 +106,13 @@ namespace lib {
/////////////////////////////TODO move over into opaque-holder.hpp
/**
* handle to allow for safe _»remote implantation«_
* of an unknown subclass into a given OpaqueHolder buffer,
* of an unknown subclass into a given opaque InPlaceBuffer,
* without having to disclose the concrete buffer type or size.
* @remarks this is especially geared towards use in APIs, allowing
* a not yet known implementation to implant an agent or collaboration
* partner into the likewise undisclosed innards of the exposed service.
* @warning the type BA must expose a virtual dtor, since the targeted
* OpaqueHolder has to take ownership of the implanted object.
* InPlaceBuffer has to take ownership of the implanted object.
*/
template<class BA>
class PlantingHandle

View file

@ -467,8 +467,10 @@ namespace test{
})
.assignElement ([&](Data& target, GenNode const& spec) -> bool
{
UNIMPLEMENTED ("binding for assignment");
return false;
cout << "assign "<<target<<" <- "<<spec<<endl;
CHECK (target.key == spec.idi.getSym(), "assignment to target with wrong identity");
target.val = render(spec.data);
return true;
})
.buildChildMutator ([&](Data& target, GenNode::ID const& subID, TreeMutator::MutatorBuffer buff) -> bool
{
@ -482,9 +484,9 @@ namespace test{
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 (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 ( 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;

View file

@ -8214,7 +8214,7 @@ On receiving the terms of this &quot;diff language&quot;, it is possible to gene
i.e. a ''unified diff'' or the ''predicate notation'' used above to describe the list diffing algorithm, just by accumulating changes.
</pre>
</div>
<div title="TreeMutator" creator="Ichthyostega" modifier="Ichthyostega" created="201503292115" modified="201603160345" tags="Model Concepts GuiPattern design draft" changecount="63">
<div title="TreeMutator" creator="Ichthyostega" modifier="Ichthyostega" created="201503292115" modified="201604162306" tags="Model Concepts GuiPattern design draft" changecount="65">
<pre>The TreeMutator is an intermediary to translate a generic structure pattern into heterogeneous local invocation sequences.
within the [[diff framework|TreeDiffModel]], this is a crucial joint, since here the abstract, generic, ~DOM-like ExternalTreeDescription meeds opaque, local and undisclosed data structures.
@ -8238,10 +8238,12 @@ This means, we do not share a data model -- rather we exchange ''diff messages''
So, from the usage side, some kind of implementation data structure will build a TreeMutator and tie itself into its binding Then, by exposing this {{{TreeMutator}}} implementation, this client data structure gets the ability to receive diff messages, which means this local and undisclosed data structure can be attached to and collaborate with some other subsystem; it can be altered, extended and reshaped remotely, without the need to share implementation details.
Incidentally, the ''diff language'' itself is meant to be readable and expressive. On the //sending side,// typically diff messages will be constructed direcly in code. To this end, the GenNode offers a constructor and mutator syntax specifically crafted to allow writing clear and compact diff messages. Since the tree diff language embedds a simple list diff language as a subset, it is possible to generate structural changes by observing changes on data collections. Such //detected diffs// may be embedded within explicitly written diff message sequences.
Incidentally, the ''diff language'' itself is meant to be readable and expressive. On the //sending side,// typically diff messages will be constructed directly in code. To this end, the GenNode offers a constructor and mutator syntax specifically crafted to allow writing clear and compact diff messages. Since the tree diff language embeds a simple list diff language as a subset, it is possible to generate structural changes by observing changes on data collections. Such //detected diffs// may be embedded within explicitly written diff message sequences.
The cannonical example are changes to the editing session. After maybe running some resolution steps, an actual effective change is determined within the session. At this point, a minimal diff message to describe this effective change will be created. This diff message can be logged, to make the change persistent. And then this message will be &quot;cast towards the UI&quot;. There is a communication structure, the UI-Bus, which allows to &quot;cast&quot; such a message towards an element only known and designated by its ID. In fact, this receiver element will be a widget within the UI, and this widget exposes a custom configured TreeMutator to consume this message and effect the corresponding changes within the widget structure of the UI.
</pre>
The canonical example are changes to the editing session. After maybe running some resolution steps, an actual effective change is determined within the session. At this point, a minimal diff message to describe this effective change will be created. This diff message can be logged, to make the change persistent. And then this message will be &quot;cast towards the UI&quot;. There is a communication structure, the UI-Bus, which allows to &quot;direct&quot; such a message towards an element only known and designated by its ID. In fact, this receiver element will be a widget within the UI, and this widget exposes a custom configured TreeMutator to consume this message and effect the corresponding changes within the widget structure of the UI.
!Semantics
The TreeMutator is an //adapter,// allowing the diff language to perform some abstracted generic operations, and at the same time enabling access to an (not further disclosed) implementation data structure in a standardised way.</pre>
</div>
<div title="TreeMutatorEvolution" creator="Ichthyostega" modifier="Ichthyostega" created="201603160255" modified="201603160313" tags="Model Concepts design draft" changecount="5">
<pre>The TreeMutator is an intermediary to translate a generic structure pattern into heterogeneous local invocation sequences.

View file

@ -497,8 +497,7 @@
Und ich mu&#223; das in einem Test zumindest emulieren k&#246;nnen!
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1455668935142" ID="ID_1274632216" MODIFIED="1455669141158">
@ -2126,8 +2125,7 @@
&quot;target <i>matches</i>&#160;spec&quot;
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<font NAME="SansSerif" SIZE="12"/>
</node>
<node CREATED="1458094428506" ID="ID_1753032814" MODIFIED="1458094435693" TEXT="darf Annahmen &#xfc;ber den Typ der Spec machen"/>
@ -2149,8 +2147,7 @@
aber existiert <i>nominell </i>und kontext-abh&#228;ngig
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1460755080894" ID="ID_107894920" MODIFIED="1460755106150" TEXT="und faktisch unabh&#xe4;ngig in jedem &#xbb;onion layer&#xab;"/>
</node>
@ -2446,8 +2443,7 @@
sofern es gelingt, die Funktionalit&#228;t gutm&#252;tig zu degradieren.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
@ -2522,8 +2518,7 @@
erfordert <i>wirklich</i>&#160;Kooperation
</p>
</body>
</html>
</richcontent>
</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"/>
@ -2569,8 +2564,7 @@
daneben auf die gr&#252;ne Wiese stellen. Ist ja nur ein Test :-D
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1460762330487" ID="ID_914518092" MODIFIED="1460762395843" TEXT="Nein! Schwein gehabt">
@ -2589,8 +2583,7 @@
dessen payload per default-konstruktor zu erzeugen.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
@ -2675,8 +2668,7 @@
Typisches Beispiel: eine STL-Collection von Strings.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1458850672705" ID="ID_1240263288" MODIFIED="1458850675197" TEXT="kein Setter"/>
<node CREATED="1458850675641" ID="ID_736176562" MODIFIED="1458850678564" TEXT="kein Mutator"/>
@ -2724,6 +2716,25 @@
</node>
</node>
<node CREATED="1458850212503" ID="ID_321552356" MODIFIED="1458850218977" TEXT="Signaturen f&#xfc;r Lambdas dokumentieren"/>
<node CREATED="1460847222865" ID="ID_362820787" MODIFIED="1460847316734" TEXT="abstrakte operationale Semantik der Diff-Anwendung dokumentieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...sonst wird niemand Lambdas bereitstellen k&#246;nnen, oder gar Diff-Nachrichten erzeugen.
</p>
<p>
Das ist nun kein spezielles Problem der gew&#228;hlten Implementierungs-Technik, sondern r&#252;hrt daher,
</p>
<p>
da&#223; der Client hier eigentlich ein Protokoll implementieren mu&#223;.
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1458850263688" ID="ID_555018476" MODIFIED="1458850272315" TEXT="Zusammenf&#xfc;hren">
<node CREATED="1458850294083" ID="ID_393704697" MODIFIED="1458850302901" TEXT="der normale GenNode-Applikator"/>
<node CREATED="1458850282285" ID="ID_435722140" MODIFIED="1458850293735" TEXT="Pr&#xfc;fen ob sinnvoll">