Commit graph

139 commits

Author SHA1 Message Date
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
2dec96663f implement the last missing verb 'after' 2015-10-31 04:25:43 +01:00
614e1f81e5 Generic Record: implement equivalence of Record and RecRef in comparison
...that is, we have "magic" in the access functions, which allows
a RecRef to "stand-in" for the Record it points to
2015-10-30 22:02:09 +01:00
bc072ab336 Generic Record: change semantics of the "match" operation for objects
in the first version, I defined equality to just compare the IDs
But that didn't seem right, or what one would expect by the concept
of equality (this is a long standing discussion with persistent
object-relationally mapped data).

So I changed the semantics of equaility to be "deep".
As this means possiblty to visit a whole tree depth-first,
it seems reasonable to provide the shallow "identity-comparison" likewise.
And the most reaonable choice is to use the "matches(object)" API
for that, since, in case of objects, the matches was defined
as full equality, which now seems redundant.

Thus: from now on: obj.matches(otherObj)
means they share the same IDs
2015-10-30 21:44:43 +01:00
9267b57c54 fix endless recursion on copy initialisation from Ref
The Ref-GenNode is just a specifically constructed GenNode,
and intended to be sliced down to an ordinary GenNode
immediately after construction. It seems, GCC didn't "get that"
and instead emitted an recursive invocation of the same ctor,
which obviously leads to stack overflow.

Problem solved by explicitly coding the copy initialisation,
after the full definition of Ref is available.
2015-10-30 05:41:36 +01:00
0e769601b7 add explicit handling to change the typeID
the type is the only meta attribute supported by now,
thus the decision was to handle this manually, instead of
introducing a full scope for meta attributes. Unfortunately
this leads to an assymetry: while it is possible to send an
attribute named "type", which will be intercepted and used
as a new type ID, the type will not show up when iterating
or searching through attributes.

When applying a diff, the only possibility is to *insert*
a new type attribute, and we need to check and handle this
likewise manually.
2015-10-30 05:10:16 +01:00
e231a51dc6 implement closing nested scope and return to parent 2015-10-30 04:51:13 +01:00
1101ce7210 implement opening a nested child scope for diff application 2015-10-30 04:45:22 +01:00