diff --git a/src/lib/diff/diff.cpp b/src/lib/diff/diff.cpp index 7bc2d54fb..eadc4d8b0 100644 --- a/src/lib/diff/diff.cpp +++ b/src/lib/diff/diff.cpp @@ -33,6 +33,7 @@ #include "lib/error.hpp" #include "lib/diff/diff-language.hpp" +#include "lib/diff/gen-node.hpp" namespace lib { @@ -40,5 +41,14 @@ namespace diff{ LUMIERA_ERROR_DEFINE(DIFF_CONFLICT, "Collision in diff application: contents of target not as expected."); + /* symbolic marker ID references + * used the tree diff language + * to mark specific scopes + */ + Ref Ref::END ("_END_"); + Ref Ref::THIS ("_THIS_"); + Ref Ref::CHILD ("_CHILD_"); + Ref Ref::ATTRIBS("_ATTRIBS_"); + }} // namespace lib::diff diff --git a/src/lib/diff/gen-node.hpp b/src/lib/diff/gen-node.hpp index 6fd239cad..cf395d6ac 100644 --- a/src/lib/diff/gen-node.hpp +++ b/src/lib/diff/gen-node.hpp @@ -123,6 +123,7 @@ namespace diff{ class GenNode; using Rec = Record; + using RecRef = RecordRef; using MakeRec = Rec::Mutator; using DataValues = meta::Types; @@ -265,6 +267,21 @@ namespace diff{ return n1.idi != n2.idi; } + + protected: + /** @internal for dedicated builder subclasses */ + GenNode (ID&& id, DataCap&& d) + : idi(std::move(id)) + , data(std::move(d)) + { } + + template + static GenNode::ID + fabricateRefID (string const& symbolicID) + { + X* typeID; + return ID(typeID, symbolicID); + } private: template @@ -276,6 +293,39 @@ namespace diff{ }; + /** + * Constructor for a specially crafted 'ref GenNode'. + * The identity record of the generated object will be prepared + * such as to be identical to a regular GenNode with Record payload. + * @note slicing in usage is intentional + */ + struct Ref + : GenNode + { + /** create an empty ID stand-in. + * @note the purpose is to create a symbolic reference by name + */ + explicit + Ref(string const& symbolicID) + : GenNode(fabricateRefID (symbolicID) + , DataCap(RecRef())) // note: places NIL into the reference part + { } + + /** build reference to a Record, using the original ID + * @throw error::Logic when oNode does not hold a Record + */ + Ref(GenNode& oNode) + : GenNode(ID(oNode) + , DataCap(RecRef(oNode.data.get()))) + { } + + static Ref END; ///< symbolic ID ref "_END_" + static Ref THIS; ///< symbolic ID ref "_THIS_" + static Ref CHILD; ///< symbolic ID ref "_CHILD_" + static Ref ATTRIBS; ///< symbolic ID ref "_ATTRIBS_" + }; + + /* === Specialisation to add fluent GenNode builder API to Record === */ diff --git a/src/lib/diff/record.hpp b/src/lib/diff/record.hpp index 2e1fe7714..07471ac63 100644 --- a/src/lib/diff/record.hpp +++ b/src/lib/diff/record.hpp @@ -485,6 +485,12 @@ namespace diff{ explicit operator bool() const + { + return empty(); + } + + bool + empty() const { return bool(record_); } diff --git a/tests/library/diff/gen-node-basic-test.cpp b/tests/library/diff/gen-node-basic-test.cpp index 8a4127e0d..cac1344a4 100644 --- a/tests/library/diff/gen-node-basic-test.cpp +++ b/tests/library/diff/gen-node-basic-test.cpp @@ -223,8 +223,8 @@ namespace test{ CHECK (hamID.getHash() == ham.idi.getHash()); CHECK (contains (string(hamID), "spam")); // Lovely spam! - GenNode ref1 = Ref("egg bacon sausage and spam"); - GenNode ref2 = Ref(ham); + Ref ref1("egg bacon sausage and spam"); + Ref ref2(ham); CHECK (ref1.idi == ham.idi); CHECK (ref2.idi == ham.idi); @@ -233,8 +233,8 @@ namespace test{ CHECK (isSameObject (ham, ref2.data.get())); VERIFY_ERROR (BOTTOM_VALUE, ref1.data.get()); - RecordRef rr1 = ref1.data.get(); - RecordRef rr2 = ref2.data.get(); + RecRef rr1 = ref1.data.get(); + RecRef rr2 = ref2.data.get(); CHECK ( isnil(rr1)); CHECK (!isnil(rr2)); @@ -248,10 +248,10 @@ namespace test{ CHECK ("_CHILD_" == name(Ref::CHILD)); CHECK ("_ATTRIBS_" == name(Ref::ATTRIBS)); - CHECK (isnil (Ref::END.data.get())); - CHECK (isnil (Ref::THIS.data.get())); - CHECK (isnil (Ref::CHILD.data.get())); - CHECK (isnil (Ref::ATTRIBS.data.get())); + CHECK (isnil (Ref::END.data.get())); + CHECK (isnil (Ref::THIS.data.get())); + CHECK (isnil (Ref::CHILD.data.get())); + CHECK (isnil (Ref::ATTRIBS.data.get())); } diff --git a/wiki/renderengine.html b/wiki/renderengine.html index c9d87bc26..65a3b8f0f 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -7947,7 +7947,7 @@ Used this way, diff representation helps to separate structure and raw data in e :Chunks of raw data are attached inline to the structural diff, assuming that each element implicitly knows the kind of data to expect -
+
//This page details decisions taken for implementation of Lumiera's diff handling framework//
 This topic is rather abstract, since diff handling is multi purpose within Lumiera: Diff representation is seen as a meta language and abstraction mechanism; it enables tight collaboration without the need to tie and tangle the involved implementation data structures. Used this way, diff representation reduces coupling and helps to cut down overall complexity -- so to justify the considerable amount of complexity seen within the diff framework implementation.
 
@@ -8010,7 +8010,7 @@ It should be noted, that the purpose of this whole architecture is to deal with
 ** as additional metadata information sent beforehand?
 * we need an object-reference element, since we do not want to copy whole subtrees while processing a diff
 
-"Objects" can be spelled out literally in code. We care to make the respective ctor syntax expressive enough. For nested objects, i.e. values of type{{{diff::Record}}}, a dedicated object builder notation is provided, (because this is the point, where the syntax gets convoluted
+"Objects" can be spelled out literally in code. We care to make the respective ctor syntax expressive enough. For nested objects, i.e. values of type {{{diff::Record}}}, a dedicated object builder notation is provided, because this is the point, where the syntax gets convoluted
 
 Within this framework, we represent //object-like// entities through a special flavour of the GenNode: Basically, an object is a flat collection of children, yet given in accordance to a distinct protocol. The relevant ''meta'' information is spelled out first, followed by the ''attributes'' and finally the ''children''. The distinction between these lies in the mode of handling. Meta information is something we need to know before we're able to deal with the actual stuff. Prominent example is the type of the object. Attributes are considered unordered, and will typically be addressed by-name. Children are an ordered collection of recursive instances of the same data structure. (Incidentally, we do not rule out the possibility that also an attribute holds a recursive subtree; only the mode of access is what makes the distinction).
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 517c951c3..3e1c1ae36 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -325,8 +325,8 @@
 
 
 
-
-
+
+
 
 
   
@@ -345,8 +345,10 @@
 
 
 
-
-
+
+
+
+
 
   
     
@@ -357,6 +359,41 @@
     

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

+ gemeint ist: +

+
    +
  • + man kann alternativ auch eine RecordRef direkt in eine elementare GenNode packen +
  • +
  • + diese verhält sich dann nicht transparent, denn sie hat eine andere Identität als ihr Ziel +
  • +
  • + das kann aber als spezielles Ausdrucksmittel genutzt werden +
  • +
+ + +
+
+ + + @@ -473,6 +510,9 @@
+ + +