introduce a value assignment verb into the tree-diff-language

after sleeping one night over the problem, this seems to be
the most natural solution, since the possibility of assignment
naturally arises from the fact that, for tree diff, we have
to distinguish between the *identity* of an element node and
its payload (which could be recursive). Thus, IFF the payoad
is an assignable value, why not allow to assign it. Doing so
elegnatly solves the problem with assignment of attributes

Signed-off-by: Ichthyostega <prg@ichthyostega.de>
This commit is contained in:
Fischlurch 2016-02-19 17:22:41 +01:00
parent 40b69e1fd2
commit d22cc18c13
6 changed files with 92 additions and 15 deletions

View file

@ -73,7 +73,7 @@ namespace diff{
/** Implementation of content equality test
/** Implementation of content equality test, delgating to content
* @throws error::Logic when the given other DataCap
* does not hold a value of the same type than
* this DataCap.

View file

@ -363,6 +363,14 @@ namespace diff{
++src(); // get /after/ an explicitly given position
}
/** assignement of changed value in one step */
virtual void
set (GenNode const& n) override
{
GenNode const& elm = find_child (n.idi);
unConst(elm).data = n.data;
}
/** open nested scope to apply diff to child object */
virtual void
mut (GenNode const& n) override

View file

@ -40,8 +40,13 @@
** a \em nested record ("nested child object").
** - the typing of the elements is outside the scope of the diff language; it is
** assumed that the receiver knows what types to expect and how to deal with them.
** - only nested records may be \em mutated by the diff. All other elements can
** only be inserted, moved or deleted (like elements in list diff)
** - there is a notion of changing or mutating the data content, while retaining
** the identity of the element. Of course this requires the data content to be
** assignalbe, which makes content mutation an optional feature.
** - beyond that, like in list diff, elements might be changed through a sequence of
** deletion and insertion of a changed element with the same identity.
** - since the tree like data structure is _recursive_, mutation of nested records
** os represented by "opening" the nested record, followed by a recursive diff.
** By implementing the #TreeDiffInterpreter interface (visitor), a concrete usage
** can receive a diff description and possibly apply it to suitable target data.
**
@ -97,6 +102,12 @@ namespace diff{
* to the first child element, while \c after(Ref::END) means to accept
* all of the existing data contents as-is (presumably to append further
* elements beyond that point).
* - \c set assign a new value to the element designated element.
* This is primarily intended for primitive data values and requires
* the payload type to be assignable, without changing the element's
* identity. The element is identified by the payload's ID and needs
* to be present already, i.e. it has to be mentioned by preceding
* order defining verbs (the list diff verbs, `pick`, or `find`).
* - \c mut bracketing construct to open a nested sub scope, for mutation.
* The element designated by the ID of the argument needs to be a
* ["nested child object"](\ref Record). Moreover, this element must
@ -132,6 +143,7 @@ namespace diff{
virtual void skip(GenNode const& n) =0;
virtual void after(GenNode const&n) =0;
virtual void set (GenNode const&n) =0;
virtual void mut (GenNode const& n) =0;
virtual void emu (GenNode const& n) =0;
};
@ -150,6 +162,7 @@ namespace diff{
// Tree structure verbs
DiffStep_CTOR(after);
DiffStep_CTOR(set);
DiffStep_CTOR(mut);
DiffStep_CTOR(emu);
};

View file

@ -124,6 +124,10 @@ namespace test{
DiffSeq
mutationDiff()
{
// prepare for direkt assignement of new value
// NOTE: the target ID will be reconstructed, including hash
GenNode childA_upper(CHILD_A.idi.getSym(), "A");
return snapshot({after(Ref::ATTRIBS) // fast forward to the first child
, find(CHILD_T)
, pick(CHILD_A)
@ -142,6 +146,7 @@ namespace test{
, ins(TYPE_Y)
, ins(ATTRIB2)
, emu(CHILD_NODE)
, set(childA_upper) // direct assignment, target found by ID (out of order)
, mut(ATTRIB_NODE) // mutation can be out-of order, target found by ID
, ins(CHILD_A)
, ins(CHILD_A)
@ -189,7 +194,9 @@ namespace test{
.appendChild(CHILD_A) //
.genNode("δ")); //
auto subScope = nested.scope(); // and within the nested sub-scope we find
CHECK ( *subScope == CHILD_A); // CHILD_A
CHECK ( *subScope != CHILD_A); // CHILD_A has been altered by assigment
CHECK (CHILD_A.idi == subScope->idi); // ...: same ID as CHILD_A
CHECK ("A" == subScope->data.get<string>()); // ...: but mutated payload
CHECK (*++subScope == MakeRec().type("Y") // a yet-again nested sub-Record of type "Y"
.set("β", int64_t(2)) // with just an attribute "β" == 2L
.genNode(CHILD_NODE.idi.getSym())); // (and an empty child scope)

View file

@ -8128,7 +8128,7 @@ Within the context of GuiModelUpdate, we discern two distinct situations necessi
the second case is what poses the real challenge in terms of writing well organised code. Since in that case, the receiver side has to translate generic diff verbs into operations on hard wired language level data structures -- structures, we can not control, predict or limit beforhand. We deal with this situation by introducing a specific intermediary, the &amp;rarr; TreeMutator.
</pre>
</div>
<div title="TreeDiffModel" creator="Ichthyostega" modifier="Ichthyostega" created="201410270313" modified="201509300045" tags="Model GuiPattern spec draft" changecount="62">
<div title="TreeDiffModel" creator="Ichthyostega" modifier="Ichthyostega" created="201410270313" modified="201602191532" tags="Model GuiPattern spec draft" changecount="63">
<pre>for the purpose of handling updates in the GUI timeline display efficiently, we need to determine and represent //structural differences//
This leads to what could be considered the very opposite of data-centric programming. Instead of embody »the truth« into a central data model with predefined layout, we base our achitecture on a set of actors and their collaboration. In the mentioned example this would be the high-level view in the Session, the Builder, the UI-Bus and the presentation elements within the timeline view. Underlying to each such collaboration is a shared conception of data. There is no need to //actually represent that data// -- it can be conceived to exist in a more descriptive, declarative [[external tree description (ETD)|ExternalTreeDescription]]. In fact, what we //do represent// is a ''diff'' against such an external rendering.
@ -8180,6 +8180,7 @@ Diff description and diff handling can be applied to tree-like data structures a
Basically the transition from text diffing to changes on data structures is achieved by exchanging the //type of the tokens.// Instead of words, or lines of text, we now use //data elements.// To do so, we introduce a symbolic ExternalTreeDescription of tree-like core data structures. The elementary token element used in this tree diff, the GenNode, embodies either simple plain data elements (numbers, strings, booleans, id-hashes, time values) -- or it describes a //recursive data element,// given as {{{Record&lt;GenNode&gt;}}}. Such a recursive data element describes object-like entities as a sequence of metadata, named attributes and ordered child-nodes -- it is handled in two phases: the first step is to treat the presence and ordering of child data elements, insertions and deletes. The second phase opens for each structurally changed child data element a recursive bracketing construct, as indicated by explicit (and slightly redundant) //bracketing tokens://
*{{{mut}}}(node-ID) : recurse into the designated node, which must be present already as result of the preceding changes. The following diff tokens describe //mutations// of the child
*{{{emu}}}(node-ID) : close the current node context and return one step up; the node-ID is given for verification, but can be used to restore the working position at parent level
*{{{set}}}(node) : shortcut notation for simple value elements; assign the new payload value to the designated element, retaining identity
In addition, in a future extension, we might consider to introduce up/down folding primitives
*{{{fold}}}(node-ID) : pick the following elements and fold them down into a new child with given node-ID. The downfolding continues until the next {{{emu}}} token
*{{{lift}}}(node-ID) : remove the next child node, which must be node-ID, and insert its children at current position

View file

@ -474,7 +474,7 @@
<icon BUILTIN="full-3"/>
</node>
</node>
<node CREATED="1455668897947" HGAP="80" ID="ID_1897861223" MODIFIED="1455668911660" TEXT="Konseuenzen" VSHIFT="24">
<node CREATED="1455668897947" HGAP="80" ID="ID_1897861223" MODIFIED="1455898587145" TEXT="Konsequenzen" VSHIFT="24">
<node CREATED="1455668923175" ID="ID_1183550957" MODIFIED="1455668933577" TEXT="brauche passendes UI-Bus API"/>
<node CREATED="1455668935142" ID="ID_1274632216" MODIFIED="1455669141158">
<richcontent TYPE="NODE"><html>
@ -560,7 +560,8 @@
</node>
<node CREATED="1455833678448" HGAP="35" ID="ID_1439118587" MODIFIED="1455833692637" TEXT="Probleme" VSHIFT="6">
<icon BUILTIN="flag-pink"/>
<node CREATED="1455833736586" ID="ID_1233162987" MODIFIED="1455833741893" TEXT="Feld vs Attribut">
<node CREATED="1455833736586" ID="ID_1233162987" MODIFIED="1455898562792" TEXT="Feld vs Attribut">
<icon BUILTIN="info"/>
<node CREATED="1455834007278" ID="ID_196347476" MODIFIED="1455834009696" TEXT="Feld">
<node CREATED="1455834060110" ID="ID_1872959165" MODIFIED="1455834067177" TEXT="ist da per Struktur"/>
<node CREATED="1455834067837" ID="ID_944456076" MODIFIED="1455834075400" TEXT="hat immer einen Wert"/>
@ -577,9 +578,15 @@
<node CREATED="1455834252068" ID="ID_1918373755" MODIFIED="1455834285644" TEXT="Ordnung"/>
</node>
</node>
<node CREATED="1455833774965" ID="ID_677756898" MODIFIED="1455833794349" TEXT="&#xc4;ndern wider die Natur"/>
<node CREATED="1455833858794" ID="ID_483179827" MODIFIED="1455833863844" TEXT="zus&#xe4;tzliche Ordnungsstruktur"/>
<node CREATED="1455842653928" ID="ID_1996966445" MODIFIED="1455842665480">
<node CREATED="1455833774965" ID="ID_677756898" MODIFIED="1455833794349" TEXT="&#xc4;ndern wider die Natur">
<node CREATED="1455898722195" ID="ID_1299759861" MODIFIED="1455898728644" TEXT="Problem delegieren..."/>
<node CREATED="1455898713124" ID="ID_1862448261" MODIFIED="1455898720143" TEXT="ignorieren bzw. scheitern lassen"/>
</node>
<node CREATED="1455833858794" ID="ID_483179827" MODIFIED="1455833863844" TEXT="zus&#xe4;tzliche Ordnungsstruktur">
<node CREATED="1455898689479" ID="ID_1223705901" MODIFIED="1455898696898" TEXT="Attribut: ignorieren"/>
<node CREATED="1455898698670" ID="ID_1532643598" MODIFIED="1455898705001" TEXT="Kind: delegieren"/>
</node>
<node CREATED="1455842653928" FOLDED="true" ID="ID_1996966445" MODIFIED="1455898466662">
<richcontent TYPE="NODE"><html>
<head>
@ -591,23 +598,64 @@
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
<node CREATED="1455842674973" ID="ID_1910702757" MODIFIED="1455842682008" TEXT="L&#xf6;schen + Neueinf&#xfc;gen"/>
<node CREATED="1455842682524" ID="ID_1597781391" MODIFIED="1455842710444" TEXT="unn&#xf6;tiger Aufwand (Allokation)"/>
<node CREATED="1455842711008" ID="ID_1470911011" MODIFIED="1455842721083" TEXT="f&#xfc;hrt zu &quot;Flackern&quot; im UI"/>
<node CREATED="1455843001833" HGAP="46" ID="ID_617738816" MODIFIED="1455843009974" TEXT="L&#xf6;sungen" VSHIFT="16">
<node CREATED="1455843011048" ID="ID_1280199494" MODIFIED="1455843047471" TEXT="Spezialvereinbarung">
<node CREATED="1455843001833" HGAP="46" ID="ID_617738816" MODIFIED="1455898462725" TEXT="L&#xf6;sungen" VSHIFT="16">
<icon BUILTIN="idea"/>
<node CREATED="1455843011048" ID="ID_1280199494" MODIFIED="1455895527566" TEXT="Spezialvereinbarung">
<icon BUILTIN="button_cancel"/>
<node CREATED="1455843048699" ID="ID_1949875245" MODIFIED="1455843054766" TEXT="Einf&#xfc;gen des gleichen Attributes"/>
<node CREATED="1455843055122" ID="ID_880285017" MODIFIED="1455843061285" TEXT="geht nur unmittelbar danach"/>
<node CREATED="1455843061633" ID="ID_1466937234" MODIFIED="1455843065597" TEXT="geht nur mit Attributen"/>
</node>
<node CREATED="1455843068672" ID="ID_695348733" MODIFIED="1455843072795" TEXT="neues Verb">
<node CREATED="1455843068672" ID="ID_695348733" MODIFIED="1455898442763" TEXT="neues Verb">
<icon BUILTIN="button_ok"/>
<node CREATED="1455843074288" ID="ID_251586851" MODIFIED="1455843077987" TEXT="SET"/>
<node CREATED="1455843120961" ID="ID_1340712241" MODIFIED="1455843131556" TEXT="setzt Element-Identit&#xe4;t voraus"/>
<node CREATED="1455843134111" ID="ID_1830155209" MODIFIED="1455843174534" TEXT="funkioniert (theoretisch) auch bei Kindern"/>
<node CREATED="1455843262862" ID="ID_779223103" MODIFIED="1455843311047" TEXT="Frage: Auto-PICK">
<icon BUILTIN="help"/>
<node CREATED="1455843317119" ID="ID_755404987" MODIFIED="1455843331097" TEXT="Ja: aber was dann mit Umordnungen"/>
<node CREATED="1455843336405" ID="ID_1210482014" MODIFIED="1455843358109" TEXT="Nein: aber was dann wenn out-of-order"/>
<node CREATED="1455843317119" ID="ID_755404987" MODIFIED="1455895650565" TEXT="Ja: aber was dann mit Umordnungen">
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1455843336405" ID="ID_1210482014" MODIFIED="1455895717489">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Nein
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
<node CREATED="1455895664140" ID="ID_639070488" MODIFIED="1455895669295">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
aber was dann wenn out-of-order
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="help"/>
</node>
<node CREATED="1455895670603" ID="ID_1629566976" MODIFIED="1455895735146" TEXT="out-of-order">
<icon BUILTIN="yes"/>
<node CREATED="1455895687377" ID="ID_742953981" MODIFIED="1455895691763" TEXT="wird unterst&#xfc;tzt"/>
<node CREATED="1455895692304" ID="ID_1361195241" MODIFIED="1455895769838" TEXT="denn: analog zu mut-emu">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1455895701215" ID="ID_1720750220" MODIFIED="1455895710033" TEXT="erm&#xf6;glicht Postfix-Order"/>
</node>
</node>
</node>
</node>
</node>