Commit graph

1204 commits

Author SHA1 Message Date
9300a0baaf code up the first event log matching predicate
this establishes the basic pattern used for implementation
Note: test still fails
2015-12-05 02:40:03 +01:00
38fd7d6d69 use the new extensible filter iterator to implement event log matching 2015-12-05 02:07:25 +01:00
6659a7dee1 augment extensible filter to add the obvious variations
that is
 - allow also for a disjunctive extension
 - allow for negated conditions
 - allow to flip the current condition

unit test PASS
2015-12-05 02:00:44 +01:00
0e41555402 extensible filter: add re-evaluation (test PASS)
this is the tiny bit of operational functionality needed on top:
whenever we're reconfiguring the predicate, we need to re-trigger
the evaluation (and clear the cached value)

n.b.: I've verified in debugger that the closure is
allocated on the heap and the functors are passed by value
2015-12-05 01:31:23 +01:00
075653a815 define the expected behaviour for an extensible filter iterator 2015-12-05 00:52:45 +01:00
68dd8a9e03 refine implementation draft: make FilterIter extensible on-the-fly
after looking into our various iterator tools,
it seems obvious that our filtering iterator implementation
has almost all of the required behaviour; we only need to
add a hook to rewrite and extend the filtering functor,
which can now nicely done with a lambda closure.

This means all memory management, if necessary, is
pushed into std::function and the automated memory
management for closures provided by the runtime.
2015-12-05 00:28:07 +01:00
41626c363e WIP: draft how to implement those chained EventLog matchers
the solver is a Monad; succesively flatMap more conditions
and try to get some element from the solution
2015-12-02 23:37:54 +01:00
d38b28da5b implement initial EventLog entry 2015-12-02 01:31:37 +01:00
b2542b86f7 stub and rectify interfaces defined thus far.
...compilation PASS again
2015-11-28 23:50:56 +01:00
809ed36b56 WIP: draft initial test for event logging helper 2015-11-28 19:20:10 +01:00
1eda2a070b harmonise the form of the header include guards
no trailing underscore
2015-11-28 18:36:35 +01:00
d04e6d74d8 WIP: arrange some elements needed for MockElm implementation 2015-11-27 19:24:00 +01:00
6a0b9980e3 After a looong break.... start reading code
wtf was I doing before that damn release and packaing business
2015-11-21 03:39:07 +01:00
c5e96efed8 fix compilation problem with gcc-5
..while we should note at this point that the whole techique
of hijacking std::hash is superfluous now, since the standard libray
does no longer define a static assertion which defeats SFINAE
2015-11-20 02:53:16 +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
c94bbcbb15 extend storage arrangement to deal with nested child objects
It is difficult to reconcile our general architecture for the
linearised diff representation with the processing of recursive,
tree-like data structures. The natural and most clean way to
deal with trees is to use recursion, i.e. the processor stack.
But in our case, this means we'd have to peek into the next
token of the language and then forward the diff iterator
into a recursive call on the nested scope. Essentially, this
breaks the separation between receiving a token sequence and
interpretation for a concrete target data structure.

For this reason, it is preferrable to make the stack an
internal state of the concrete interpreter. The downside of
this approach is the quite confusing data storage management;
we try to make the role of the storage elements a bit more
clear through descriptive accessor functions.
2015-10-30 03:11:33 +01:00
e5ffcf224f implementation: list diff operations in tree-diff-applicator
implement the list handling primitives analogous to the
implementation of list-diff-applicator -- just again with
the additional twist to keep the attribute and child scopes
separated.
2015-10-29 04:14:18 +01:00
2882d78755 implementation: simplest case (insert element)
...so now the stage is set. We can reimplement
the handling of the list diff cases here in the context
of tree diff application. The additional twist of course
being the distinction between attribute and child scope
2015-10-24 03:15:35 +02:00
4356315021 diff-language interpreter: prefer to take payload by const&
each language token of our "linearised diff representation"
carries a payload data element, which typically is the piece
of data to be altered (added, mutated, etc).

Basically, these elements have value semantics and are
"sent over wire", and thus it seems natural when the
language interpreter functions accept that piece of payload
by-value. But since we're now sending GenNode elements as
parameter data in our diff, which typically are of the
size of 10 data elements (640 bit on a 64bit machine),
it seems more resonable to pass these argument elements
by const& through the interpreter function. This still
means we can (and will indeed) copy the mutated data
values when applying the diff, but we're able to
relay the data more efficiently to the point where
it's consumed.
2015-10-24 02:42:13 +02:00
2b619d6622 implement RecordContentMutator - unit test pass 2015-10-24 01:49:07 +02:00
aa46940daa indicate how RecordContentMutator will be used 2015-10-23 21:08:33 +02:00
5cbdcc0f22 stub ContentMutator implementation 2015-10-23 20:55:02 +02:00
e438a9fe51 chosing an implementation approach for tree-diff-application 2015-10-23 19:24:34 +02:00
c90e6a6f65 on second thought: yet a better solution
...is to let the diff applicator work *on* a Rec::Mutator
This is outright natural -- why is it that I needed 2 days
to come up with this solution?
2015-10-23 01:32:47 +02:00
eabeee3b7b decide on the implementation approach for tree diff application
this boils down to the two alternatives
 - manipulate the target data structure
 - build an altered copy

since our goal is to handle large tree structures efficiently,
the decision was cast in favour of data manipulation
2015-10-23 00:40:02 +02:00
90f31df8c0 stub the diff verb operations.
passes compilation again
2015-10-09 03:44:38 +02:00
2704b38da6 WIP rework demonstration diff to be valid type-wise
so basically it's time to explicate the way
our diff language will actually be written.

Similar to the list diff case, it's a linear sequence
of verb tokens, but in this case, the payload value
in each token is a GenNode. This is the very reason
why GenNode was conceived as value object with an
opaque DataCap payload
2015-10-09 03:03:27 +02:00
f43fb2167f WIP demonstration draft continued... 2015-10-02 19:41:14 +02:00
eaba418d15 WIP start definition with a basic tree diff example... 2015-10-02 18:47:44 +02:00
6b32d1f37d fix inconsistency in conception of HierarchyOrientationIndicator
while it's still not really clear how we'll use this helper
and if we need it at all -- some weeks ago I changed its
semantics to be strictly based on the delta to a reference level.

Now this means, we could go below level zero, but this doesn't
make any sense in the context of navigating a tree. Actually,
our test case triggered this situation, which caused the
reference level to wrap around, since it is stored in an
unsigned variable.

Thus I'll add a precondition to keep the level positive,
and I'll change the test to comply.
2015-09-25 03:57:29 +02:00
08e7e3df15 prefer more readable bool operator spelling
especially the '!' for negation is sometimes too terse
and easily overlooked.
2015-09-25 03:12:04 +02:00
7b7d12d99e add internal / diagnostic display for low-level time values and time spans
Initially I've deliberately omitted those, to nudge towards
using time quantisation and TCode formatting for any external
representation of time values.

While this recommendation is still valid, the overloaded
string conversion turns out to be helpful for unit testing
and diagnostics in compound data structures.
See Record<GenNode>
2015-09-25 03:12:04 +02:00