Commit graph

246 commits

Author SHA1 Message Date
0d2335c9ed WIP: code organisation - create dedicated implementation unit
It occurred to me, that 90% of this template specialisation
are entirely generic and not dependant on the actual target type.
While the compiler/linker is able to sort such a situation out,
this might lead to template bloat and possibly subtle errors.

So it seems more adequate to emit the generic part of the code
right away from within a dedicated translation unit within the
library module; so the vtable is already in place and only
the flexible part of the code needs to be re-emitted on
each usage site.
2016-07-24 15:16:06 +02:00
4a2340ca5e solution for access to "tree mutator building closure"
- default recommendation is to implement DiffMutable interface
- ability to pick up similar non-virtual method on target
- for anything else client shall provide free function mutatorBinding(subject)


PERSONAL NOTE: this is the first commit after an extended leave,
where I was in hospital to get an abdominal cancer removed.
Right now it looks like surgery was successful.
2016-07-21 19:29:16 +02:00
5744244f73 considerations how to access the "tree mutator building closure"
this is at the core of the integration problem: how do we expose
the ability of some opaque data structure to create a TreeMutator?

The idea is
 - to use a marker/capability interface
 - to use template specialisation to fabricate an instance of that interface
   based on the given access point to the opaque data structure
2016-06-14 02:33:28 +02:00
61627b26a0 WIP: first attempt to use a TreeMutator based binding
but unfortunately this runs straight into a tough problem,
which I tried to avoid and circumvent all the time:
At some point, we're bound to reveal the concrete type
of the Mutator -- at least to such an extent that we're
able to determine the size of an allocator buffer.

Moreover, by the design chosen thus far, the active
TreeMutator instance (subclass) is assumed to live within
the top-level of a Stack, which means that we need to
place-construct it into that location. Thus, either
we know the type, or we need to move it into place.
2016-06-11 19:40:53 +02:00
57b105bbc5 fix a re-entrance problem
initially, even the diff applicator was meant to be a
"throwaway" object. But then, on writing some tests,
it seemed natural to allow re-using a single applicator,
after having attached it to some target.

With that change, I failed to care for the garbage
left back in the "old" sequence after applying one diff;
since in the typical usage sequence, the first use builds
content from scratch, this problem starts to show up only
with the third usage, where the garbage left from the input
of the second usage appears at the begin of the "new sequence"

Solution is to throw away that garbage explicitly on re-entrance
2016-06-10 02:48:22 +02:00
6fa54411b3 improved log msg
..because actually we don't know if the intention is
to drop those waste elements -- and for sure this
discarding of waste does not happen through the
invocation logged here; rather it happens by
abandoning the scope
2016-06-09 01:21:06 +02:00
37cfdbb7e1 better name for nested handle type 2016-06-09 01:18:21 +02:00
ef27c09fa2 round-up and document the attribute binding and test 2016-06-09 01:10:52 +02:00
b5ab5df929 supply implementation, basically working already
so this test case is more or less finished,
just needs some more polishing and documentation
2016-06-05 17:26:48 +02:00
6eff16f21c supply missing implementation
standard case of attribute binding, i.e.
the setter invocation is fully functional now.
2016-06-05 16:31:29 +02:00
1ae3c1991d second round of this test implemented
...which mostly just is either ignoring the
operations or indicating failure on attempt to
'reorder' attributes (which don't have any notion of 'ordering')
2016-06-04 15:08:10 +02:00
76b898b602 amend the design and then implement the two concrete setter/mutator cases
overall, the structure of this implementation is still rather confusing,
yet any alternatives seem even less convincing

- if we want to avoid the delegation to base-class, we'd have
  to duplicate several functions and the combined class would
  handle two distinct concerns.
- any attempt to handle the IDs more "symmetrically" seems to
  create additional problems on one side or the other
2016-06-04 14:20:59 +02:00
ee99c405fd Reorganise implementation into base class + overlay
...as preparation for implementing the two flavours of
binding attributes either via  a setter lambda or via
creation of a nested mutator.
2016-05-29 03:01:27 +02:00
e5bbcb27d8 identify attributes through an EntryID (including type hash)
this also supersedes and removes the initial implementation
draft for attribute binding with the 'setAttribute' API
The elementary part of diff application incl. setting
new attribute values works by now.
2016-05-28 03:41:03 +02:00
16086caf42 explicit error message
...turns out that inclusion of format-string.hpp
is almost irrelevant, since diff/record.hpp already
includes even format-util.hpp
2016-05-28 01:49:03 +02:00
201b6542f2 API change to allow to detect missing attribute binding
The way we build this attribute binding, there is no single
entity to handle all attribute bindings. Thus the only way
to detect a missing binding is when none of the binding layers
was able to handle a given INS verb
2016-05-28 01:17:45 +02:00
4073cdf797 first part of the implementation of attribute binding
...the simple checks and direct assignment.
Passes compiler, but test fails where it shouldn't
2016-05-27 03:33:56 +02:00
34f6d38919 WIP: implant outline of the implementation
...again by overriding all TreeMutator operations
2016-05-27 02:08:29 +02:00
06102b74ad rename test (no change) 2016-05-26 02:16:34 +02:00
4571d3fb0f introduce new mutation primitive as pointed out by preceding analysis
to summarise, it turned out that it is impossible to
provide an airtight 'emptySrc' implementation when binding
to object fields -- so we distinguish into positive and
negative tests, allowing to loosen the sanity check
only for the latter ones when binding to object fields.
2016-05-24 23:43:55 +02:00
b47b4c3f94 flip logic of emptySrc -> hasSrc
..as concluded from the preceding analysis.
NOTE this entails a semantical change, since this
predicate is now only meant to be indicative, not conclusive

remarks: the actual implementation of the diff application process
as bound via the TreeMutator remains yet to be written...
2016-05-24 21:34:08 +02:00
d3869d2280 Design/Analysis: Attribute TreeMutator binding
how can ordinary object fields be treated as "Attributes"
and thus tied into the Diff framework defined thus far.
This turns out to be really tricky, even questionable
2016-04-30 00:26:19 +02:00
835c43027d add support for Ref::THIS (questionable, #996)
while simple to add into the implementation, this whole feature
seems rather qestionable to me now, thus I've added a Ticket
to be revisited later.

In a nutshell, right here, when implementing the binding layer
for STL collections, it is easy to enable the framework to treat
Ref::THIS properly, but the *actual implementation* will necessarily
be offloaded onto each and every concrete binding implementation.
Thus client code would have to add support for an rather obscure
shortcut within the Diff language. The only way to avoid this
would be to change the semantics of the "match"-lambda: if this
binding would rather be a back-translation of implementation data
into GenNode::ID values, then we'd be able to implement Ref::THIS
natively. But such an approach looks like a way inferiour deisgn
to me; having delegated the meaning of a "match" to the client
seems like an asset, since it is both natural and opens a lot
of flexibility, without adding complexity.

For that reason I tend to avoid that shortcut now, in the hope
to be able to drop it entirely from the language
2016-04-18 01:21:38 +02:00
7bbfb4bc68 implement nested mutation of sub structures
...basically this worked right away and was easy to put together.
However, when considering how many components, indirections and
nested lambdas are working together here, I feel a bit dizzy...

:-/
2016-04-17 04:51:19 +02:00
69c63045e6 DOC: constituting elements of the TreeMutator
write down a first draft for a definiton section,
to describe the fundamental parts involved, when
applying a diff message onto implementation defined
data structures

After a break of tree weeks, I found it difficult to find may way
amidst all those various levels of abstraction. In addition to this
definition, we'll probably also need a high level overview of the
whole diff system operation.
2016-04-17 03:53:10 +02:00
8167fbff77 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.
2016-04-17 01:07:07 +02:00
7f42b9b7e7 draft third round of mutation operations to be implemented
...now about opening a sub mutator within a nested scope
2016-04-16 02:20:23 +02:00
54fb335a9c allow to "peek" into an embedded Record's type field
while I still keep my stance not to allow reflection and
switch-on-type, access to the internal / semantic type of
an embedded record seems a valid compromise to allow
to deal with collections of object-like children
of mixed kind.

Indirectly (and quite intentional) this also opens a loophole
to detect if a given GenNode might constitute a nested scope,
but with the for the actual nested element indeed to cary
a type symbol. Effectively this limits the use of this shortcut
to situations where the handling context does have some pre-established
knowledge about what types *might* be expected. This is precisely
the kind of constraint I intend to uphold: I do not want the
false notion of "total flexibility", as is conveyed by introspection.
2016-04-16 00:48:15 +02:00
ad6d348d8f make TreeMutator noncopyable to prevent dangling references
since we're moving elements around to apply the diff,
dangerous situation might arise in case anyone takes a copy
of the mutator. Thus we effectively limit the possible
usage pattern and only allow to build an anonymous
TreeMutator subclass through the Builder-DSL.

The concrete "onion layers" of the TreeMutator are now limited
- to be created by the chaining operations of the Builder DSl
- to be moved into target location, retaining ownership.
2016-03-26 02:01:31 +01:00
f9f2a225c3 implement content reordering mutation primitives
and cover result in test.
This also demonstrates that it is possible to install
a specific lambda on each usage
2016-03-26 01:22:40 +01:00
c49dd04b44 address an insidious dangling reference
I still feel somewhat queasy with this whole situation!
We need to return the product of the DSL/Builder by value,
but we also want to swap away the current contents before
starting the mutation, and we do not want a stateful lifecycle
for the mutator implementation. Which means, we need to swap
right at construction, and then we copy -- TADAAA!

Thus I'm going for the solution to disallow copying of the
mutator, yet to allow moving, and to change the builder
to move its product into place. Probably should even push
this policy up into the base class (TreeMutator) to set
everyone straight.

Looks like this didn't show up with the test dummy implementation
just because in this case the src buffer also lived within th
TestMutationTarget, which is assumed to sit where it is, so
effectively we moved around only pointers.
2016-03-26 00:48:38 +01:00
d98fde5b0e better verification in test
...actually iterate the populated collection
and verify each element in order. Also verify
and document the mutator's storage requirements
2016-03-25 23:12:54 +01:00
e84844142f implement inserting of new elements 2016-03-25 22:43:11 +01:00
91bf75d54a spelling in comments 2016-03-25 21:40:30 +01:00
fb1857423e implement mutation start and lifecycle
the whole implementation will very much be based on
my experiences with the TestMutationTarget and TestWireTap.
Insofar it was a good idea to implement this test dummy first,
as a prototype. Basically what emerges here is a standard pattern
how to implement a tree mutator:

- the TreeMutator will be a one-way-off "throwaway" object.
- its lifecylce starts with sucking away the previous contents
- consuming the diff moves contents back in place
- thus the mutator always attaches onto a target by reference
  and needs the ability to manipulate the target
2016-03-25 20:46:48 +01:00
1bf0753854 mark where function signature helpers should be refactored (#994) 2016-03-25 19:58:09 +01:00
e698a3800b verify signatures of binding lambdas
the collection binding can be configured with various
lambdas to supply the basic building blocks of the generated binding.

Since we allow picking up basically anything (functors,
function pointers, function objects, lamdas), and since
we speculate on inlining optimisation of lambdas, we can not
enforce a specific signature in the builder functions.

But at least we can static_assert on the effective signature
at the point where we're generating the actual binding configuration
2016-03-25 02:51:56 +01:00
7b6713bcab extend lamda-signature-extracting metafunction to several arguments 2016-03-25 02:25:51 +01:00
2098e69981 move metafunction to GenNode
because this is something of wider usage potential.
It allows us to detect if a type in question can be
placed within a GenNode
2016-03-24 21:32:56 +01:00
92d4e87ab9 raise a runtime error when unable to generate a sensible default collection binding
we can't generate a static assertion so easily here.
Problem is, when forming this type, we don't know if
the user will override and provide a custom binding
in some chained call within the nested DSL.

Might still be able to come up with some clever trick,
like e.g. returing an unsuitable marker type from these
dummy default implementations and then, later on, when
actually building the collection binding, to detect
those marker types and rise a static assert at that point.
This would at least give us a better error message,
and in theory, it should always be possible to
detect this kind of misuse at compile time
2016-03-24 17:44:58 +01:00
3b116fe6ef find a way to pick a default implementation for collection binding
...through the use of partial specialisation and SFINAE.
There are some rather specific (yet expectedly not uncommon) cases,
where we'd be able to provide a sensible default for the
- match predicate
- new element constructor
of the binding. While in all other cases, the user
has to provide an explicit implementation for these
crucial building blocks anyway.
2016-03-24 17:33:28 +01:00
cb2a95627d WIP: specify first example binding...
...but does not compile, since all of the fallback functions
will be instantiated, even while in fact we're overriding them
right away with something that *can* be compiled.

this prompts me to reconsider and question the basic approach
with closures for binding, while in fact what I am doing here
is to implement an ABC.
2016-03-24 17:32:30 +01:00
df8ca071a8 first outline of test and aggregate initialisation problem
- the test will use some really private data types,
  valid only within the scope of the test function.

- invoking the builder for real got me into problems
  with the aggregate initialisation I'd used.
  Maybe it's the function pointers? Anyway, working
  around that by definint a telescope ctor
2016-03-19 16:47:40 +01:00
b4fb767109 default/fallback configuration for the collection binding
when setting up a binding to child elements within a STL collection,
all the variable elements are preconfigured to a more or less
disabled and inactive state.
2016-03-19 01:24:11 +01:00
c909a67388 reorg: split, trim down and comment 2016-03-18 20:52:35 +01:00
08657bf199 reorg: split off implementation details
the concern is for the structure of the builder to be
incomprehensible and completely buried within the
implementation details of the various binding layers
2016-03-18 20:03:27 +01:00
1b24453f5b set up the full builder definition chain 2016-03-18 19:35:48 +01:00
5579e9c86f draft a way to configure the binding to a STL collection
this is the most relevant binding layer for TreeMutator,
enabling to transform and mutate child elements managed
within a STL collection.
2016-03-18 00:31:04 +01:00
3646c5df72 rearrange logic to allow for chaining / layering
most of the mutation primitives return bool(true)
when /any/ layer or part of the TreeMuator was able
to cope with the diff verb.

This is based on the assumption to configure the
TreeMutator in such a way that at most one facility
will actually handle and apply a given verb. That is,
we'll assume that the TreeMutator acutally wraps and
adapts *one* custom data structure, to which the
diff has to be applied.

The TestWireTap is special, insofar it indeed targets
a *second* data structure, albeit not a "real" one,
just a dest and diagnostics dummy.
2016-03-12 01:01:26 +01:00
9ef32e0d62 complete dummy/proof-of-concept implementation of TreeMutator primitives
the first part of the unit test (now passing)
is able to demonstrate the full set of diff operations
just by binding to a TestMutationTarget.

Now, after verifying the design of those primmitive operations,
we can now proceed with bindings to "real" data structures
2016-03-11 21:30:25 +01:00
b0c6ba0777 switch implementation of TestMutationTarget to storing full GenNodes
when implementing the assignment and mutation primitives
it became clear that the original approach of just storing
a log or string rendered elements does not work: for
assignment, we need to locate an element by ID
2016-03-11 17:39:25 +01:00
1016d792b9 implement accept_until for the test-dummy 2016-03-10 20:53:36 +01:00
7cceff8708 fix logic bug in existing tree diff applicator
this one went through unnoticed, because the situation
is not covered in unit-test. The tests written thus fare
are more like a proof-of-concept. I didn't want to spend
weeks on writing extensive coverage of all corner cases,
at least not before all aspects of the tree diff protocol
are settled. Seemingly this backfires already
2016-03-10 20:41:11 +01:00
6d5f336d40 fix self-assignment bug 2016-03-10 20:15:19 +01:00
75a6b4c05d specify and stub the test thus far to complete API design
now the full API for the "mutation primitives" is shaped.
Of course the actual implementation is missing, but that
should be low hanging fuit by now.

What still requires some thinking though is how to implement
the selector, so we'll actually get a onion shaped decorator
2016-03-06 03:55:31 +01:00
d2e7e1e06d idea how to crack the (daunting) problem regarding mutator storage
basically we'll establish a collaboration where both sides
know only the interface (contract) of the partner; a safe margin
for allocation size has to be established through metaprogramming (TODO)
2016-03-06 02:26:42 +01:00
75de98fe4d get the unit test to pass again
what's problematic is that we leave back waste in the
internal buffer holding the source. Thus it doesn't make
sense to check if this buffer is empty. Rather the
Mutator must offer an predicate emptySrc().

This will be relevant for other implementations as well
2016-03-04 23:18:25 +01:00
fcc2bc1e60 implement further re-ordering mutation primitives
...all for the first onion layer, which is a test dummy
2016-03-04 22:30:11 +01:00
1a20505c4f implement src position and simple match operation 2016-03-04 21:38:39 +01:00
6cf97f2478 forward operations to test/dummy onion layer
...first round of implementation happens here
2016-03-04 21:26:25 +01:00
b0ee330737 stub and decide about further part of the API 2016-03-04 21:13:49 +01:00
7d63167276 WIP: define usage of the reordering part of the mutation primitives
...this kind of settles the problem with the "opaque" position
2016-03-04 20:55:52 +01:00
9875c93ca7 add iteration and some diagnostics to the test 2016-03-04 19:23:21 +01:00
af50e84737 first partial implementation unit test PASS
that is, the dummy/diagnostic-implementation
of the first "mutation primitive", namely injectNew(elm)
2016-03-04 00:25:36 +01:00
d8fe9bce94 baseline of test-dummy implementation or a mutation target binding
- we're using the source / target buffer paradigm to implement the mutation
 - we're using Record<string> to account for "the current content"
2016-03-03 23:11:36 +01:00
3f8946c157 better naming of Record::Mutator content moving operation
while the original name, 'replace', conveys the intention,
this more standard name 'swap' reveals what is done
and thus opens a wider array of possible usage
2016-03-03 22:58:33 +01:00
48f519e785 align naming of mutation primitives
...convinced myself to retain an uniform naming scheme,
even while the implementation spans several onion-like layers
2016-03-03 22:02:01 +01:00
8bcd37df0a stub first round of mutation primitives to pass compiler again
now this feels like making progress again,
even when just writing stubs ;-)

Moreover, it became clear that the "typing" of typed child collections
will always be ad hoc, and thus needs to be ensured on a case by case
base. As a consequence, all mutation primitives must carry the
necessary information for the internal selector to decide if this
primitive is applicable to a given decorator layer. Because
otherwise it is not possible to uphold the concept of a single,
abstracted "source position", where in fact each typed sub-collection
of children (and thus each "onion layer" in the decorator chain)
maintains its own private position
2016-02-27 01:47:33 +01:00
bdf48e1b7b WIP: desperate attempt to get out of the design deadlock
Arrrrgh.
I go round in circles since hours now.
Whatever I attempt, it again relies on
yet further unsecured suppositions
2016-02-26 22:57:49 +01:00
a10db41d91 WIP: shaping a solution approach 2016-02-26 17:50:44 +01:00
2a037f49ee WIP: daft top layer of generic diff applicator
BUT the daunting question is how to deal with
the allocation of recursive mutator objects
2016-02-21 00:49:13 +01:00
dd1afef970 WIP: consider what kind of changes to support and how
especially the nagging question is:
- do we need to support children of mixed type
- and how can we support those, wihtout massively indirected calls
2016-02-20 00:19:01 +01:00
afbba968b5 WIP: decide how to target the task of mutating "unspecific" data structures 2016-02-19 20:25:30 +01:00
d22cc18c13 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>
2016-02-19 17:22:41 +01:00
40b69e1fd2 planning: consider implications of tree-diff application to arbitrary data structures 2016-02-19 16:34:32 +01:00
c0ee98d73d planning: find out what the next steps would be like
...we want to attack the structural mutaion, finally
2016-02-17 01:38:04 +01:00
f80982b52b gen-node: fix insidious data conssitency problem
I assumed that, since GenNode is composed of copyable and
assignable types, the standard implementation will do.
But I overlooked the run time type check on the opaque
payload type within lib::Variant. When a type mismatch
is detected, the default implementation has already
assigned and thus altered the IDs.

So we need to roll our own implementation, and to add
insult to injury, we can't use the copy-and-swap idiom either.
2016-02-13 22:55:59 +01:00
121cd41408 ouch: GCC-4.9 doesn't yet support the C++14 transparent comparators
This is actually a STL library feature, and was added precisely
for the reason encountered here: if we want logarithmic search,
we'll have to construct a new GenNode object, just to have something
for the set to invoke the comparison operator.

C++14 introduced the convention that the Comparator of the set
may define a marker type `is_transparent` alongside with a generic
comparison operator. But, as is obvious from the source code of
our GNU Standard library implementation, our std::set has no such
overload to make use of that feature

http://en.cppreference.com/w/cpp/container/set/find
http://stackoverflow.com/questions/20317413/what-are-transparent-comparators

The only good thing is that, just 10 minutes ago, I felt like
a complete moron because I'm writing a unit test for such a simple
storage class. ;-)
2016-02-13 22:55:59 +01:00
94fc160525 implementation of storage for state manager 2016-02-13 22:55:59 +01:00
1e5c1059d3 WIP: draft basics of state manager interface 2016-02-13 22:55:58 +01:00
44785859ea convenience shortcut to simplify command invocation via Bus 2016-02-13 22:55:57 +01:00
3f22150ab3 back to topic: get all the arguments of command binding logged
...when the Test-Nexus processes a command binding message.
In the real system of course we do not want to log every bind message.

The challenge here is the fact that command binding as such
is opaque, and the types of the data within the bind message
are opaque as well. Finally I settled on the compromise
to log them as strings, but only the DataCap part;
most value types applicable within GenNode
have a string representation to match.
2016-02-05 15:55:22 +01:00
536a3a94b9 add special iteration mechanism to visit enclosed child data
the rationale is that I deliberately do not want to provide
a mechanism to iterate "over all contents in stringified form".
Because this could be seen as an invitation to process GenNode-
datastructures in an imperative way. Please recall we do not
want that. Users shall either *match* contents (using a visitor),
or they are required to know the type of the contents beforehand.
Both cases favour structural and type based programming over
dynamic run-time based inspection of contents

The actual task prompting me to add this iteration mechanism
is that I want to build a diagnostic, which allows to verify
that a binding message was sent over the bus with some
specific parameter values.
2016-02-05 04:03:11 +01:00
ae7912dc99 refactoring: move new library helpers into final destination 2016-01-28 15:19:09 +01:00
f743784bc9 add accessor for Nth child to our Record type 2016-01-23 17:10:44 +01:00
334f542897 clean-up(#985): remove code superseded by this rework
now finally able to remove most of the cruft from format-util.hpp
and get rid of the infamous util::str
2016-01-09 02:05:23 +01:00
3c24b4f8e4 should provide a generic entry point for all "state mark" messages 2015-12-26 03:03:46 +01:00
5874b1b4dc change lib::Record string representation to handle empty parts better
...no need to enclose empty sections when there are no
attributes or no children. Makes test code way more readable.



TestEventLog_test PASS as far as implemented
2015-12-05 03:57:11 +01:00
d68b881fab fix test failure due to compilation order (see #973)
some tests rely on additional diagnostics code being linked in,
which happens, when lib/format-util.hpp is included prior to
the instantiation of lib::diff::Record rsp. lib::Variant.

The reason why i opended this can of worms was to avoid includion
of this formatting and diagnostics code into such basic headers
as lib/variant.hpp or lib/diff/gen-node.hpp

Now it turns out, that on some platforms the linker will use
a later instantiation of lib::Variant::Buff<GenNode>::operator string
in spite of a complete instantiation of this virtual function
being available already in liblumierasupport.so

But the real reason is that -- with this trickery -- we're violating
the single definition rule, so we get what we deserved.

TODO (Ticket #973): at a later point in development we have to re-assess,
the precise impact of including lib/format-util.hpp into
lib/diff/gen-node.hpp
Right now I expect GenNode to be used pervasively, so I am
reluctant to make that header too heavyweight.
2015-11-15 02:11:08 +01:00
0e615e531f DOC: extension of the diff framework to represent structural changes 2015-11-02 03:51:04 +01:00
4a3b077824 Bugfix: find verb should check for ID match
because otherwise we'd need to send a whole subtree
over the wire and then descend into it just to find an element.

This too is a ripple effect of making '==' deep
2015-11-01 23:11:55 +01:00
34d79ee8df tree-diff-application: unit test PASS
well... this was quite a piece of work
Added some documentation, but a complete documentation,
preferably to the website, would be desirable, as would
be a more complete test covering the negative corner cases
2015-11-01 07:03:47 +01:00
eb829e6994 Bugfix: yet another init problem after swapping contents
yeah, working with open fire is dangerous...

For performace reasons I've undercut the premise
to make GenNode / Record immutable. Now I'm dealing with
raw storage layout together with this quite hairy distinction
between "attribute scope" and "child scope"

In hindsight, it might have been better to implement Record
as a single list, and to maintain a shortcut pointer to jump
to the start of the attributes.
2015-11-01 04:49:22 +01:00
83bea7c6ef Bugfix: need also to init sub scopes
this is a consequence of b14943
we use now an explicit init() call, instead of preparing everything in the ctor
2015-11-01 04:12:55 +01:00
9e7680d688 allow for trace-logging the processed diff-tokens
run the program with NOBUG_LOG=diff:TRACE
2015-11-01 03:54:43 +01:00
289bc7114c implement mutation of the current element (_THIS_)
while implementing this, I've discovered a conceptual error:
we allow to accept attributes, even when we've already entered
the child scope. This means that we can not predictable get back
at the "last" (i.e. the currently touched) element, because this
might be such an attribute. So a really correct implementation
would have to memorise the "current" element, which is really
tricky, given the various ways of touching elements in our
diff language.

In the end I've decided to ignore this problem (maybe a better
solution would have been to disallow those "late" attributes?)
My reasoning is that attributes are unlikely to be full records,
rather just values, and values are never mutated. (but note
that it is definitively possible to have an record as attribute!)
2015-11-01 03:29:35 +01:00
daa13ab6dc implement anonymous pick or delete of children
...while I must admit that I'm a bit doubtful about that
language feature, but it does come in handy when manually
writing diff messages. The reason is the automatic naming
of child objects, which makes it often hard to refer to
a child after the fact, since the name can not be
reconstructed systematically.

Obviously the downside of this "anonymous pick / delete"
is that we allow to pick (accept) or even delete just
any child, which happens to sit there, without being
able to detect a synchronisation mismatch between
sender and receiver.
2015-11-01 02:33:35 +01:00
73eaa10caf semantics change: allow referral just by ID
i.e. flat match, not deep equality.
This allows to send just an Ref (with the ID) over the
wire to refer to an complete object to be picked, moved
or deleted on the receiver side.
2015-11-01 02:20:54 +01:00
b149432512 fix/change DiffApplicator to allow applying several diffs
basically we need a reset-Hook before applying the next diff,
because the existing elements need to be swaped and the
position reset to start
2015-10-31 05:15:47 +01:00
52b1a2b9ae wrong -- need to treat each case explicitly
and its better this way; those nested lambdas
where just a bit too much trickery
2015-10-31 04:43:18 +01:00