diff --git a/src/lib/diff/test-mutation-target.hpp b/src/lib/diff/test-mutation-target.hpp index beee23d35..4f9f79d4d 100644 --- a/src/lib/diff/test-mutation-target.hpp +++ b/src/lib/diff/test-mutation-target.hpp @@ -528,10 +528,10 @@ namespace diff{ template - Builder> + auto Builder::attachDummy (TestMutationTarget& dummy) { - return WireTap (dummy, move(*this)); + return chainedBuilder> (dummy); } } diff --git a/src/lib/diff/tree-diff-traits.hpp b/src/lib/diff/tree-diff-traits.hpp index 4f942df3b..9914a5e2b 100644 --- a/src/lib/diff/tree-diff-traits.hpp +++ b/src/lib/diff/tree-diff-traits.hpp @@ -208,8 +208,8 @@ namespace diff{ * the return value in local scope as long as necessary */ template - auto - mutatorBinding (TAR& subject) -> typename TreeDiffTraits::Ret + typename TreeDiffTraits::Ret + mutatorBinding (TAR& subject) { using Wrapper = typename TreeDiffTraits::Ret; return Wrapper{subject}; diff --git a/src/lib/diff/tree-mutator-attribute-binding.hpp b/src/lib/diff/tree-mutator-attribute-binding.hpp index 1167e6dfb..588a7a10d 100644 --- a/src/lib/diff/tree-mutator-attribute-binding.hpp +++ b/src/lib/diff/tree-mutator-attribute-binding.hpp @@ -84,9 +84,8 @@ ** constructing the concrete TreeMutator needs to have adequate understanding ** regarding mode of operation and "mechanics" of such a binding. ** - ** @note the header tree-mutator-attribute-binding.hpp with specific builder templates - ** is included way down, after the class definitions. This is done so for sake - ** of readability. + ** @note the header tree-mutator-attribute-binding.hpp was split off for sake of readability + ** and is included automatically from bottom of tree-mutator.hpp ** ** @see tree-mutator-test.cpp ** @see TreeMutator::build() @@ -96,13 +95,22 @@ #ifndef LIB_DIFF_TREE_MUTATOR_ATTRIBUTE_BINDING_H #define LIB_DIFF_TREE_MUTATOR_ATTRIBUTE_BINDING_H -#ifndef LIB_DIFF_TREE_MUTATOR_H - #error "this header shall not be used standalone (see tree-mutator.hpp)" -#endif - -//== anonymous namespace... +#include "lib/error.hpp" +#include "lib/symbol.hpp" +#include "lib/diff/gen-node.hpp" +#include "lib/diff/tree-mutator.hpp" +#include "lib/format-string.hpp" +#include "lib/idi/entry-id.hpp" + +#include + + +namespace lib { +namespace diff{ + + namespace { // Mutator-Builder decorator components... /** @@ -333,4 +341,30 @@ }; + + /** Entry point for DSL builder */ + template + template + inline auto + Builder::change (Symbol attributeID, CLO setterClosure) + { + return chainedBuilder> (attributeID, setterClosure); + } + + + /** Entry point for DSL builder */ + template + template + inline auto + Builder::mutateAttrib (Symbol attributeID, CLO mutatorBuilderClosure) + { + idi::EntryID key{attributeID}; + return chainedBuilder> (key, mutatorBuilderClosure); + } + + + + }//(END)Mutator-Builder decorator components... + +}} // namespace lib::diff #endif /*LIB_DIFF_TREE_MUTATOR_ATTRIBUTE_BINDING_H*/ diff --git a/src/lib/diff/tree-mutator-collection-binding.hpp b/src/lib/diff/tree-mutator-collection-binding.hpp index a8041e169..8f98e8eb1 100644 --- a/src/lib/diff/tree-mutator-collection-binding.hpp +++ b/src/lib/diff/tree-mutator-collection-binding.hpp @@ -35,9 +35,8 @@ ** a building block for one such layer, especially for binding to a representation ** of "child objects" managed within a typical STL container. ** - ** @note the header tree-mutator-collection-binding.hpp with specific builder templates - ** is included way down, after the class definitions. This is done so for sake - ** of readability. + ** @note the header tree-mutator-collection-binding.hpp was split off for sake of readability + ** and is included automatically from bottom of tree-mutator.hpp ** ** @see tree-mutator-test.cpp ** @see TreeMutator::build() @@ -47,13 +46,21 @@ #ifndef LIB_DIFF_TREE_MUTATOR_COLLECTION_BINDING_H #define LIB_DIFF_TREE_MUTATOR_COLLECTION_BINDING_H -#ifndef LIB_DIFF_TREE_MUTATOR_H - #error "this header shall not be used standalone (see tree-mutator.hpp)" -#endif +#include "lib/error.hpp" +#include "lib/meta/trait.hpp" +#include "lib/diff/gen-node.hpp" +#include "lib/diff/tree-mutator.hpp" +#include "lib/iter-adapter-stl.hpp" -//== anonymous namespace... +#include + + +namespace lib { +namespace diff{ + + namespace { // Mutator-Builder decorator components... @@ -447,6 +454,7 @@ } + template struct _EmptyBinding { @@ -589,7 +597,7 @@ * using lambdas as callback into the otherwise opaque implementation code. */ template - auto + inline auto collection (COLL& coll) { using Elm = typename COLL::value_type; @@ -599,4 +607,17 @@ + /** Entry point for DSL builder */ + template + template + inline auto + Builder::attach (BIN&& collectionBindingSetup) + { + return chainedBuilder> (forward(collectionBindingSetup)); + } + + + }//(END)Mutator-Builder decorator components... + +}} // namespace lib::diff #endif /*LIB_DIFF_TREE_MUTATOR_COLLECTION_BINDING_H*/ diff --git a/src/lib/diff/tree-mutator-gen-node-binding.hpp b/src/lib/diff/tree-mutator-gen-node-binding.hpp index 0fa172cb6..e55c3ca5b 100644 --- a/src/lib/diff/tree-mutator-gen-node-binding.hpp +++ b/src/lib/diff/tree-mutator-gen-node-binding.hpp @@ -32,8 +32,8 @@ ** Each concrete TreeMutator instance will be configured differently, and this ** adaptation is done by implementing binding templates, in the way of building ** blocks, layered on top of each other. This header defines a special setup, based - ** on the two layered bindings for STL collections. The reason is that our »External - ** Tree Description« of object-like structures is comprised of recursively nested + ** on two layered bindings for STL collections. The reason is that our »External + ** Tree Description« of object-like structures is comprised of recursively nested ** Record to represent "objects", and this representation is actually implemented ** internally based on two collections -- one to hold the _attributes_ and one to hold the ** _children._ So this special setup relies on implementation inside knowledge to apply @@ -44,9 +44,8 @@ ** structure of our _diff language_ -- thus it is sufficient just to layer two collection ** bindings, together with suitable closures (lambdas) for layer selection, matching, etc. ** - ** @note the header tree-mutator-collection-binding.hpp with specific builder templates - ** is included way down, after the class definitions. This is done so for sake - ** of readability. + ** @note the header tree-mutator-collection-binding.hpp was split off for sake of readability + ** and is included automatically from bottom of tree-mutator.hpp ** ** @see tree-mutator-test.cpp ** @see TreeMutator::build() @@ -56,16 +55,19 @@ #ifndef LIB_DIFF_TREE_MUTATOR_GEN_NODE_BINDING_H #define LIB_DIFF_TREE_MUTATOR_GEN_NODE_BINDING_H -#ifndef LIB_DIFF_TREE_MUTATOR_H - #error "this header shall not be used standalone (see tree-mutator.hpp)" -#endif +#include "lib/diff/gen-node.hpp" +#include "lib/diff/tree-mutator-collection-binding.hpp" +#include "lib/diff/tree-mutator.hpp" -//== anonymous namespace... - - - +#include + + +namespace lib { +namespace diff{ + + namespace { // Mutator-Builder decorator components... using Storage = RecordSetup::Storage; @@ -83,26 +85,23 @@ return std::get<1> (targetTree.exposeToDiff()); } - /** - * Attach to GenNode tree: Special setup to build a concrete `TreeMutator`. - * This decorator is already outfitted with the necessary closures to work on - * a diff::Record -- which is typically used as "meta representation" - * of object-like structures. Thus this binding allows to apply a diff message - * onto such a given »External Tree Description«, mutating it into new shape. - */ + + + /** Entry point for DSL builder */ template inline auto - twoLayeredGenNodeTreeMutator (Rec::Mutator& targetTree, PAR&& builderBase) + Builder::attach (Rec::Mutator& targetTree) { - return builderBase - .attach (collection (accessChildren(targetTree))) - .attach (collection (accessAttribs(targetTree))) - .isApplicableIf ([&](GenNode const& spec) - { - return spec.isNamed(); // »Selector« : treat key-value elements here - }); + return this-> attach (collection (accessChildren(targetTree))) + .attach (collection (accessAttribs(targetTree))) + .isApplicableIf ([&](GenNode const& spec) + { + return spec.isNamed(); // »Selector« : treat key-value elements here + }); } - - + }//(END)Mutator-Builder decorator components... + + +}} // namespace lib::diff #endif /*LIB_DIFF_TREE_MUTATOR_GEN_NODE_BINDING_H*/ diff --git a/src/lib/diff/tree-mutator.hpp b/src/lib/diff/tree-mutator.hpp index 7b8cf3824..6884f8548 100644 --- a/src/lib/diff/tree-mutator.hpp +++ b/src/lib/diff/tree-mutator.hpp @@ -324,6 +324,9 @@ namespace diff{ }; + + + namespace { // Mutator-Builder decorator components... using lib::meta::Strip; @@ -374,16 +377,7 @@ namespace diff{ - /* == implementation detail headers == */ -#include "lib/diff/tree-mutator-attribute-binding.hpp" -#include "lib/diff/tree-mutator-collection-binding.hpp" -#include "lib/diff/tree-mutator-gen-node-binding.hpp" - - - - template - struct TestWireTap; /** @@ -402,16 +396,13 @@ namespace diff{ : PAR{forward (par)} { } - template - using Change = ChangeOperation; + template + Builder + chainedBuilder (ARGS&&...args) + { + return Builder (BIN{forward(args)..., move(*this)}); + } - template - using MutateAttrib = MutationOperation; - - template - using Collection = ChildCollectionMutator; - - using WireTap = TestWireTap; /* ==== binding API ==== */ @@ -434,13 +425,12 @@ namespace diff{ * "applicable" to this attribute and binding. Similar to * GenNode, the provided attributeID is used as-is, * without further sanitising. + * @return a _chained builder,_ which establishes this building and + * can then be used to define additional binding layers on top */ template - Builder> - change (Symbol attributeID, CLO setterClosure) - { - return Change (attributeID, setterClosure, move(*this)); - } + auto change (Symbol attributeID, CLO setterClosure); + /** set up a binding for an object valued "attribute" or _named scope_. * This covers the rather special case, where some relevant sub object is @@ -458,12 +448,7 @@ namespace diff{ * @see CollectionBindingBuilder::buildChildMutator */ template - Builder> - mutateAttrib (Symbol attributeID, CLO mutatorBuilderClosure) - { - idi::EntryID key{attributeID}; - return MutateAttrib (key, mutatorBuilderClosure, move(*this)); - } + auto mutateAttrib (Symbol attributeID, CLO mutatorBuilderClosure); ///////////////////////////////////////TODO define variant taking a GenNode::ID ?? @@ -498,30 +483,33 @@ namespace diff{ * this nested mutator until encountering the corresponding `EMU` bracket verb. */ template - Builder> - attach (BIN&& collectionBindingSetup) - { - return Collection {forward(collectionBindingSetup), move(*this)}; - } + auto attach (BIN&& collectionBindingSetup); + + + /** set up binding to a GenNode tree: Special setup to build a concrete `TreeMutator`. + * This decorator is already outfitted with the necessary closures to work on a + * diff::Record -- which is typically used as "meta representation" of + * object-like structures. Thus this binding allows to apply a diff message onto + * such a given »External Tree Description«, mutating it into new shape. + * @remarks our meta representation of "objects" is based on Record, which + * is implemented through two STL collections, one for the attributes and + * one for the child elements. Thus we'll using two binding layers, based + * on the ChildCollectionMutator, configured with the necessary lambdas. + */ + auto attach (Rec::Mutator& targetTree); - auto - attach (Rec::Mutator& targetTree) - { - return twoLayeredGenNodeTreeSetup (targetTree, move(*this)); - } /** set up a diagnostic layer, binding to TestMutationTarget. * This can be used to monitor the behaviour of the resulting TreeMutator for tests. */ - Builder - attachDummy (TestMutationTarget& dummy); + auto attachDummy (TestMutationTarget& dummy); }; }//(END) Mutator-Builder... - Builder + inline Builder TreeMutator::build () { return TreeMutator(); @@ -530,3 +518,11 @@ namespace diff{ }} // namespace lib::diff #endif /*LIB_DIFF_TREE_MUTATOR_H*/ + + + /* == implementation detail headers == */ + +#include "lib/diff/tree-mutator-gen-node-binding.hpp" +#include "lib/diff/tree-mutator-attribute-binding.hpp" +#include "lib/diff/tree-mutator-collection-binding.hpp" +