diff --git a/src/lib/diff/tree-diff-application.hpp b/src/lib/diff/tree-diff-application.hpp index c78a65d6c..2112ee5c8 100644 --- a/src/lib/diff/tree-diff-application.hpp +++ b/src/lib/diff/tree-diff-application.hpp @@ -176,6 +176,8 @@ namespace diff{ { auto target = mutatorBinding (subject_); buildMutator (target); + TreeDiffMutatorBinding::scopeManger_ = &scopes_; + TreeDiffMutatorBinding::treeMutator_ = &scopes_.currentScope(); TreeDiffMutatorBinding::initDiffApplication(); } }; diff --git a/src/lib/diff/tree-diff-mutator-binding.cpp b/src/lib/diff/tree-diff-mutator-binding.cpp index 215c421a2..283d3ea22 100644 --- a/src/lib/diff/tree-diff-mutator-binding.cpp +++ b/src/lib/diff/tree-diff-mutator-binding.cpp @@ -236,6 +236,14 @@ namespace diff{ } + void + TreeDiffMutatorBinding::__failMismatch (GenNode const& spec, Literal oper) + { + throw error::State(_Fmt("Unable to %s element %s. Current target binding " + "did not match as expected") % oper % spec + , LUMIERA_ERROR_DIFF_CONFLICT); + } + void TreeDiffMutatorBinding::__expect_end_of_scope (GenNode::ID const& idi) { @@ -257,10 +265,10 @@ namespace diff{ UNIMPLEMENTED("skip next src element and advance abstract source position"); } - void + bool TreeDiffMutatorBinding::injectNew (GenNode const& n) { - UNIMPLEMENTED("inject a new element at current abstract position"); + return treeMutator_->injectNew(n); } bool @@ -312,7 +320,9 @@ namespace diff{ void TreeDiffMutatorBinding::ins (GenNode const& n) { - injectNew (n); + bool success = injectNew (n); + if (not success) + __failMismatch (n, "insert"); } void diff --git a/src/lib/diff/tree-diff-mutator-binding.hpp b/src/lib/diff/tree-diff-mutator-binding.hpp index b02edc20b..b50cad24b 100644 --- a/src/lib/diff/tree-diff-mutator-binding.hpp +++ b/src/lib/diff/tree-diff-mutator-binding.hpp @@ -137,6 +137,16 @@ namespace diff{ : scopes_() { } + TreeMutator& + currentScope() const + { + if (0 == depth()) + throw error::Logic("Attempt to access the current scope " + "without establishing a root scope beforehand." + , error::LUMIERA_ERROR_LIFECYCLE); + return *scopes_.top(); + } + /* ==== ScopeManager interface ==== */ @@ -169,7 +179,6 @@ namespace diff{ } - virtual size_t depth() const { @@ -261,6 +270,7 @@ namespace diff{ void __expect_in_target (GenNode const& elm, Literal oper); void __expect_further_elements (GenNode const& elm); void __fail_not_found (GenNode const& elm); + void __failMismatch (GenNode const& spec, Literal oper); void __expect_end_of_scope (GenNode::ID const& idi); void __expect_valid_parent_scope (GenNode::ID const& idi); @@ -269,7 +279,7 @@ namespace diff{ /* == Forwarding: mutation primitives == */ void skipSrc(); - void injectNew (GenNode const& n); + bool injectNew (GenNode const& n); bool matchSrc (GenNode const& n); bool acceptSrc (GenNode const& n); bool findSrc (GenNode const& n); diff --git a/tests/library/diff/diff-virtualised-application-test.cpp b/tests/library/diff/diff-virtualised-application-test.cpp index 70960ef70..6b059d070 100644 --- a/tests/library/diff/diff-virtualised-application-test.cpp +++ b/tests/library/diff/diff-virtualised-application-test.cpp @@ -186,7 +186,7 @@ namespace test{ }) .buildChildMutator ([&](Opaque& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool { - if (target.key_ != subID) return false; // require match on already existing child object + if (target.key_ != subID) return false; // require match on already existing child object target.buildMutator (buff); // delegate to child to build nested TreeMutator return true; })) @@ -216,6 +216,10 @@ namespace test{ })); } + /** override default size traits + * to allow for sufficient buffer, + * able to hold the mutator defined above. + */ friend constexpr size_t treeMutatorSize (const Opaque*) {