Commit graph

3075 commits

Author SHA1 Message Date
603f9e2b7d DOC: fix some Doxygen link syntax
I worked under the erroneous assumption, that Doxygen
will use its internal entity-IDs as the link-IDs when
generating mardown-links. Yes, this seemed logical and
this would be the way I'd implement it....

But seemingly, Doxygen is not so consistent when it
comes to questions of syntax. The same holds true for
markdown, which lacking a coherent definition anyway.

Another problem is that Doxygen's auto-link generation
frequently fails, for reasons not yet clear to me.
Sometimes it seems to be necessary to give it a nudge
by including the \ref command. While I'm not willing
to go into focussed invstigation of Doxygen syntax
right now, at least I've done a search-and-replace
to remove the malformed links I've written the
last days
2015-12-27 03:16:49 +01:00
dddcbe9994 DOC: supply basics of UI-Bus and generic UI-element protocol
the initial draft of this concept is in place now, and
the first round of unit tests pass. I've got some understanding
of the purpose of the interactions and involved elements
and I'm confident this design is evolving in a sane way.

Note: extensive documentation is in the TiddlyWiki,
here I've just pasted and reworded some paragraphs from there
and integrated them into the Doxygen docs
2015-12-27 01:58:15 +01:00
b9ef66b221 provide and cover a mock implementation of receiving notification messages 2015-12-26 04:40:38 +01:00
3c24b4f8e4 should provide a generic entry point for all "state mark" messages 2015-12-26 03:03:46 +01:00
9aa1fec369 UI-Element protocol: clarify the role of the doExpand() extension point
and let the concrete extension point decide if the corresponding
state change was actually relevant and should be persisted
2015-12-26 00:59:16 +01:00
3a287bf134 implement the generic expand/collapse mechanism 2015-12-25 03:53:26 +01:00
a9552ceace add stubs for the specific implementation within Widget and Controller 2015-12-25 03:51:19 +01:00
5564a51a79 build/platform: make lib SigC++ available for GUI test code
Explanation: sigC++ was already linked as transitive dependency
from gtkmm, since it is used for the "signal-slot" system wihin GTK.
But now we want to use sigC++ itself from our generic UI-Backbone,
so we need to pick up the additional compiler and linker flags
and use them when building the relevant parts of both the application
and the test suite
2015-12-25 03:06:33 +01:00
4d1fcd6dcb implement logging/identification of mock UI elements 2015-12-25 00:41:14 +01:00
972045d8f8 fix a segfault caused by re-entrance
at the point when we're connecting a new node to the UI-Bus,
the new node's BusTerm is not yet initialised, since we need
the uplink connection we're about to create for setting up
this BusTerm.

Consequently, the new nodes's ID is not yet initialised,
so we need to pass this endpoint-ID explicitly to the
registration function.
2015-12-24 22:43:41 +01:00
38e6d635dc implement routing in the UI-Bus hub 2015-12-24 22:27:37 +01:00
37802fd699 complete wiring of nexus and core services
since, by definition, the Nexus is "the" up-link,
all we need is clever overriding of the relevant
handling functions, so the nexus will care for the routing,
while the CoreService cares for command and presentation
state handling
2015-12-19 04:05:21 +01:00
449fa16444 WIP: draft of the UI backbone setup
- front-end handle
- Nexus == routing hub
- CoreService == service access point for command invocation
2015-12-19 03:40:19 +01:00
0f793e0a79 untangle the setup of test nexus 2015-12-18 19:50:57 +01:00
f19ebd63d0 pondering about how to connect the central bus hub
...especially since we need a faked UI backbone for unit testing
2015-12-18 19:50:02 +01:00
af98d75da4 consider the bus side of the generic UI base in more detail
especially define the outline of the bus communication
and connection management
2015-12-18 01:02:19 +01:00
a9a6aabcbc return to topic: UI element protocol
next step will be to rig the mock element and set up
and cover the basic / generic element behaviour

This changeset
 - adapts the (planned) unit test to the semantic of
   the EventLog, which is now fully implemented

 - adjusts the function names on the public Tangible interface,
   to be better in line with the naming convention of the
   corrsponding operations on the UI-Bus:

   * "mark" operations are towards the UI element
   * "note" messages are from the UI element towards some
     state manager, which can be reached via the bus
2015-12-16 02:16:53 +01:00
cb4a0a6e60 change the EventLog header to store a "this" attribute
seems more logical than calling the attribute "ID",
especially since we're now able to use the on("xyz") matcher
2015-12-15 23:44:34 +01:00
c8068496d1 EventLog unit test PASS
so this turned out to be rather expensive,
while actually not difficult to implement.
On the way, I've learned
- how to build a backtracking matcher, based on
  a filtering (monadic) structure and chained lambdas
- learned the hard way how (not) to return a container
  by move-reference
- made first contact with the regular expressions
  now available from the standard library
2015-12-13 05:03:36 +01:00
d0cdae2cee implement matching on regular expressions 2015-12-13 03:24:25 +01:00
42a5668831 implement further match refinements (type, attribute, target) 2015-12-12 23:41:24 +01:00
941fe3a9b9 factor out util function to "stringify" arbitrary arguments
this function is of use also for creating a vector of strings
from a bunch of C-Strings, but it could also be used to
construct other stuff initialised by strings (e.g. RegExps)
2015-12-12 23:18:25 +01:00
33f7fe116a implement refinement filter on log entry's arguments.
Whew! functional programming is such a powerful concept.
You get additional refinement and lazy backtracking
basically for free....
2015-12-12 03:13:32 +01:00
5bc6919bdb implement the specialised event or call-matching logic 2015-12-12 02:23:12 +01:00
80ffdc1f05 provide the remaining, specialised logging calls 2015-12-12 01:35:38 +01:00
261bcc9fdb implement logging of "events" with additional ID / classifier 2015-12-12 01:28:42 +01:00
4522e209fb implement generic log entry with arbitrary fields 2015-12-12 01:24:52 +01:00
894ef68a8f EventLog: implement logging of function invocations 2015-12-12 01:01:46 +01:00
7d9108a079 diagnostics formatting helper: set limited precision for doubles
this deals with a recurring problem in test code:
very common "simple" fractional values can not be represented
precisely as binary floating point. The classical example is 0.1

Since this is a diagnostics facility, we can cheat around this
insidious problem by just setting a limited rendering precision.

Floating point numbers behave deterministic; you just need
to know how to deal with limited precision.
2015-12-12 00:55:28 +01:00
761154ae63 stub the code into submission.... 2015-12-11 20:02:30 +01:00
bf92333339 implement log joining in shared heap storage 2015-12-09 01:18:15 +01:00
cd8e6d874c EventLog: switch to shared PImpl
this is prerequisite for joining and sharing logs
2015-12-08 22:14:29 +01:00
09afbb0e12 change implementation technique: use flags instead of exceptions
abandon the use of an assertion exception to signal match failure,
rather use a final bool conversion to retrieve the results.

Error messages are now delivered by side effect into STDERR


The reason is we're unable to deliver the desisred behaviour
with the chosen DSL syntax in C++ ; on a second thought the
new approach is even better aligned with the overall way
we're writing tests in Lumiera. And we produce match-trace
messages to indicate the complete matching path now
2015-12-08 03:20:52 +01:00
b3881696e5 this solution for negative matches is not usable
implemented a solution to determine negative matches.
But because this solution relies on throwing from a destructor,
it is not possible to catch the resulting assertion failure.
Not sure why (AFAIK there is no second exception thrown
while unwinding the stack), but throwing from dtors is
considered "undefined behaviour" anyway.

So this solution is of limited use


beyond that solution, I'm not sure if the desired syntax
can be implemented at all in C++. Seems that we need to build
a bracketing construct, first to initiate a negated match
and finally, after all queries, to detect if there happened
any failure or not
2015-12-08 01:10:02 +01:00
272d62d5a3 log handling const correctness
adding log entries requires full access,
whereas matching log entries is const,
since it doesn't alter the log
2015-12-06 04:37:41 +01:00
a95f9a6cac draft how "log joining" shall work 2015-12-06 04:21:35 +01:00
c9d113be87 EventLog: implement match backwards
..based on the new IterCursor, which gives us the ability
to switch the iteration direction
2015-12-06 03:35:07 +01:00
eb208ea145 direction switching iterator unit test PASS 2015-12-06 02:28:47 +01:00
f9c0c4c3d0 WIP: draft a direction switching iterator
...we need that to allow matching backwards in the EventLog
2015-12-06 00:10:27 +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
00abf9f1f9 err: got the naming and the junctor condition backwards
the junctor is called "before" but searches ahead.
And in this case we do not need to *extend* the filter condition,
just replace it with a new one...
2015-12-05 03:37:25 +01:00
09a560dfac add explicit diagnostics to assertion failure
...and fix an error (header include order of diagnostics facility)
which prevented the first matcher implementation to work

the after()-match now works as expected
2015-12-05 03:13:01 +01:00
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
d4c017fa73 WIP: settle on the Tangible interface 2015-11-28 21:43:09 +01:00
9af20b7cf6 WIP: BusTerm needs to be a concrete class
...providing the standard implementation of UI-Bus connectivity.
It seems reasonable to place all of the UI-Bus implementation into
a single translation unit
2015-11-28 20:55:28 +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
2704ad4512 decide upon the actual mechanics of command binding and invocation 2015-11-28 08:15:32 +01:00
42cec6d604 decision to follow the generic approach (#978, #979) 2015-11-28 05:51:53 +01:00
7b16c6b130 fundamental concerns regarding command binding
prompted by first attempt to define the Tangible interface...
ZOMG! And I thought I might be able just to code-up that stuff
2015-11-28 01:20:40 +01:00
d04e6d74d8 WIP: arrange some elements needed for MockElm implementation 2015-11-27 19:24:00 +01:00
bb627fc1f8 draft of the UI-Bus communication structure
what you see here now is just the tip of the icebearg...
If we follow this route, the Lumiera UI will become way more
elaborate and responsive than average desktop applications
2015-11-26 21:10:38 +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
51a58aacae swallow errors on CSS loading
preliminary workaround for Ticket #972
On Debian/Jessie, we observed the following error
"gtk-lumiera.css:38:19Theming engine 'adwaita' not found"
even though the package gnome-themes-standard *is* installed

This allows at least to bring the UI up, even if loading
our custom theme and stylesheet fails.
2015-11-14 22:28:34 +01:00
03eb0ff8f1 Pre-release 0.pre.03
This is a development snaphot pre release of Lumiera.
It features codebase maintenance, upgrade to C++14 and GTK-3
and some work towards a Proc-GUI connection (unfinished)

Update README, AUTHORS, LICENSE and similar release docs.
2015-11-02 22:19:26 +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
6da0785d0a decision how to support tree exploration/reconstruction
initially the intention was to include a "bracketing construct"
into the values returned by the iterator. After considering
the various implementation and representation approaches,
it seems more appropriate just to expose a measure for the
depth-in-tree through the iterator itself, leaving any concerns
about navigation and structure reconstruction to the usage site.

As rationale we consider the full tree reconstruction as a very
specialised use case, and as such the normal "just iteration" usage
should not pay for this in terms of iterator size and implementation
complexity. Once a "level" measure is exposed, the usage site
can do precisely the same, with the help of the
HierarchyOrientationIndicator.
2015-09-24 20:59:04 +02:00
8e8a67e6df test fixes up to (not including) the iteration scope bracketing
...since for the latter I'll actually chose quite another
approach, based on the HierarchyOrientationIndicator
2015-09-17 19:39:34 +02:00
269ef07655 introduce special treatment for RecRef payload
The intention is to allow a Ref to "stand-in" for
a GenNode holding a full Record inline
2015-09-17 19:00:55 +02:00
7f2e328ab3 generalise containment check to anything that matches the GenNode
Whooa!
Templates are powerful.
programming this way is really fun.

under the assumption that the parts are logical,
all conceivable combinations of theses parts are bound to be correct
2015-09-11 20:25:39 +02:00
07f45a58de implement containment check based on iteration 2015-09-11 20:12:26 +02:00
3576b30cd2 formally complete implementation of GenNode iteration
it passes compilation, but the test still fails, since
I've changed the expected semantics of the iteration,
in the light of the insights I've gained during
re-investigation of the IterExplorer.

What I now actually intend is rather to embed a
HierarchyOrientationIndicator into the iterator,
instead of returning a special "bracket" marker
reference to indicate return from a nested scope.
2015-09-11 20:00:36 +02:00
823b4fd322 WIP: implement the recursive scope expansion
Only a Record payload constitutes a nested scope.
For all other (primitive) values, we return an empty iterator.
When used within ScopeExplorer, this implementation will just
lead to exposing any simple value once, while delving into
iteration of nested scopes
2015-09-11 19:23:40 +02:00
3f91997cf1 WIP: rearrange types to make the recursive iteration work
The only substantial change (besides compilation fixes) is
to confine the iteration to *const access*

This is a good thing; the whole Record/GenNode structure
was designed to represent immutable data, necessitating
a dedicated *Mutator* for any reshaping.
2015-09-11 18:41:18 +02:00
82ef5964ba Fix to use IterAdapter with generic "position" types
seemingly the operator-> was not yet used in any real scenario.
The whole point with IterAdapter is that it uses an opaque "location type",
which is owned by the controlling container. In many cases this will
actually be just a pointer into the container storage, but we
must not assume it is this way. Thus the only way to obtain a
(language) pointer is to dereference the "position type" and
take the address of the result
2015-09-11 18:32:08 +02:00
0d10e62851 WIP: draft a monad-like scope expanding iterator implementation
Initially I intended just to supply an addapter to use
the monadic IterExplorer for this recursive expansion
of GenNode contents. Investigating this approach was
relevant to highlight the minimum requirements for
such an evaluation mechanics: since our GenNode
is an hierarchical structure without back-links,
we are bound to use a stack at some point. And
since an Iterator is a materialised continuation,
we can not use the processor stack and are forced
to represent this stack in memory.

Yet, on second thought, we do not need the full power
of the IterExplorer monad; especially we do not need
to bind arbitrary functions into the monad, just one
single scope exploring function, implemented as
Variant visitor. Based on these observations, we can
"inline" the monad structure into a double nested
iterator, where the outer capsule carries a stack
of scopes to be explored.
2015-09-11 04:06:51 +02:00
25459028cc extend and adjust semantics of the HierarchyOrientationIndicator
This helper was drafted for the Job / JobPlanning and Scheduler
interface in 2013, but seemingly not yet put into action. While
in the original use case, we have a genuine measuerment for the
tree depth (given by the depth of the processing stack), in other
use cases we want to use to offset embedded within the indicator
itself for keeping track of the depth. Thus I add a second
mark operation, which usess the current offset to set a new
reference level. This has the consequence that the offset
has now to reflect the new reference point immediately
2015-09-04 22:15:44 +02:00
9e35ed0e49 IterExplorer: remove the hard wired safeguard value copy
Since C++ is not a real functional programming language and
has unsafe unmanaged pointers, it is not difficult to produce
dangling references within an extended evaluation pipeline
involving transient objects and pass-by-reference.

In the initial implementation, I built in a safeguard copy
into the signature of the Explorer function, to make sure even
a transiently dressed-up input value gets materialised before
proceeding with the source sequence. Unfortunately this safeguard
turns out as a roadblock now; we might as well take the input
by reference and return an "expanded" state by value. We might
even want to do the full "expansion" on referred state, when
we're able to ensure the source values remain in memory
until consumption.

Thus now the full power of decision is placed on the signature
of the explorer function. The expansion strategies of IterExplorer
will no longer attempt to "sanitise" the signature of the passed-in
function to prevent desaster; I've added some warnings into the
documentation to highlight that danger. Basically, if you want
to be clever, then you're bound to read and understand inticacies
of the implementation.

If in doubt, use values and copying. C++ is optimised for that.
2015-09-04 17:55:34 +02:00
794e70a64b augment function type rebinding helper
allow to pick the bare function signature from any "function like" entity

Note: we're still unsing our own Typelist construct to represent
the function argument types. Since we're now using C++11, this
could be replaced by varargs, and we could get rid of those
various overloads for different numbers of arguments.
Unfortunately this transition is linked to the usage of
argument tuples in our command framework (which could then be
replaced by std::tuple), and this is still a bit of rather
technical work, which I do not want to spend much time on
right now
2015-09-04 17:14:11 +02:00
e77bc625d6 fix typo in strategy name 2015-09-02 01:49:09 +02:00
be70e58441 considering how to implement the GenNode sequence iteration
remembered that some years ago I had to deal with a very similar problem
for planning the frame rendering jobs. It turned out, that the
iterator monad developed for this looks promising for our task at hand
2015-08-31 03:34:23 +02:00
bcd6308dee reorganise compilation units
this really turned into an implementation part of GenNode
2015-08-30 04:57:32 +02:00
a56ca7308f implement the data matching predicate on GenNode
TODO: need built-in special treatment for RecRef
2015-08-30 04:44:20 +02:00
efe97b9174 util: epsilon comparison for doubles
add the usual standard implementation to compare floating point numbers
based on the machine epsilon and the magnitude of the involved numbers
2015-08-30 04:14:28 +02:00
25f78bfa83 draft a more premissive matching predicate
the intention is to combine this with content iteration
to build containment check and find operations
2015-08-30 00:00:41 +02:00
b0368a6d2b full unit test coverage of equality
horay!
seems like madness?
well -- found and squashed a bug: equality on RecordRef
implicitly converted to GenNode(RecordRef), which always
generates new (distinct) IDs and so never succeeds. What
we really want is equality test on the references
2015-08-29 21:27:33 +02:00
261b51998a rewrite equality on GenNode to rely on the new Predicate-Visitor 2015-08-29 19:14:42 +02:00
4c59e16f06 add the visitor-predicate as a second option
contrary to the Visitor, accepting a Predicate is const,
and -- of course -- the Predicate invocation returns bool.

This can be used to implement comparison operators or
search functions on Variant based data structures.
2015-08-29 18:56:19 +02:00
de3726c856 integrate the new construction just to replace the existing visitor 2015-08-29 18:34:34 +02:00
a05c9f81a6 Segfault: one move to much
the temporary was destroyed before moving it out.
2015-08-29 01:46:24 +02:00
bb92b49340 GenNode diagnostics -- debugging 2015-08-28 23:09:10 +02:00
33a6294a9b implement the remaining attribute handling functions for Record<GenNode>
There is no generic implementation for these functions, since
they are highly dependent on the payload used within Record<TY>
Here we use Record<GenNode>, which turns the whole setup into an
recursive data type; we especially rely on the fact that each
GenNode has an embedded symbolic ID, and we use this ID to encode
the 'key' for named attributes
2015-08-28 18:27:23 +02:00
96791d4a45 fix omission in generic ID functions and add unit test
while in debugging, it turned out that the short type-prefix
was implemented in a too simplistic way; it fails on stuff
like 'lib::diff::Record<lib::diff::GenNode>'


while I must add, that the whole purpose of these ID functions
is somewhat unclear and needs to reveal itself as we move forward
2015-08-28 17:18:52 +02:00
aa96cb6dd1 implement full data-based equality for GenNode
initially my intention was to use the ID for equality test.
But on a second thought, this seemed like a bad idea, since
it confuses the concepts of equality and identity.

Note: at the moment, I do not know if we even need an equality test,
so it is provided here rather for sake of completeness. And this
means even more that we want an 'equality' implementation that
does what one would naively expect: compare the object identity
*and* compare the contents.
2015-08-28 16:12:04 +02:00
1024cea2c8 fix a mistake 2015-08-28 13:40:57 +02:00
cc989d171f investigate hash collisions on 32bit platform
...while on the train back from FrOSCon.
still the same old problem: we need a better hash function
for generating our Entry-IDs. The default hash function from Boost performs
poor on strings with common prefix and trailing number.

We use a hackish workaround, which is sufficient to avoid collisions
among the first 10000 numbers.
2015-08-27 23:48:39 +02:00
a56226f297 Record "object" representation now finished and passes Test 2015-08-17 22:13:36 +02:00
0bff4f21d5 Record References: fix copy and assignment handling
not entirely sure about the design, but lets try this approach:
they can be "cloned" and likewise move-assigned, but we do not
allow the regular assignment, because this would enable to use
references like pointers (what we deliberately do not want)
2015-08-17 20:56:40 +02:00
7650b36f1e Generic Record: finish implementation of Mutator
especially setting (changing) attributes turned out to be tricky,
since in case of a GenNode this would mean to re-bind the hash ID;
we can not possibly do that properly without knowing the type of the payload,
and by design this payload type is opaque (erased).

As resort, I changed the semantics of the assign operation:
now it rather builds a new payload element, with a given initialiser.
In case of the strings, this ends up being the same operation,
while in case of GenNode, this is now something entirely different:
we can now build a new GenNode "in place" of the old one, and both
will have the same symbolic ID (attribute key). Incidentally,
our Variant implementation will reject such a re-building operatinon
when this means to change the (opaque) payload type.

in addition, I created a new API function on the Mutator,
allowing to move-in a complete attribute object. Actually this
new function became the working implementation. This way, it is
still possible to emplace a new attribute efficiently (consider
this to be a whole object graph!). But only, if the key (ID)
embedded in the attribute object is already what is the intended
key for this attribute. This way, we elegantly circumvent the
problem of having to re-bind a hash ID without knowing the type seed
2015-08-17 20:31:07 +02:00
46bfc0638f Generic Record: settle type handling
initially, the intention was to inject the type as a magic attribute.
But this turned out to make the implementation brittle, asymmetric
and either quite demanding, or inefficient.

The only sane approach would be to introduce a third collection,
the metadata attributes. Then it would be possible to handle these
automatically, but expose them through the iterator.

In the end I decided against it, just the type attribute
allone does not justify that effort. So now the type is an
special magic field and kept apart from any object data.
2015-08-17 06:34:51 +02:00
0cde55a67f Generic Record: finish basic implementation 2015-08-17 03:59:53 +02:00
657f0031f4 Generic Record: reorganise type configuration
this solves the problem how to deal with value access
- for the simple default (string) implementation,
  we use a 'key = val' syntax and thus have to split strings,
  which means we need to return contents by value
- for the actual relevant use case we have GenNode entries,
  which may recursively hold further Records. For dealing
  with diff messages over this data struture, its a good
  idea to allow for const& value access (otherwise we'd
  end up copying large subtrees for trivial operaions)
2015-08-17 02:40:57 +02:00
61b6868bff pick up work where I left one month ago
OMG, what was all this about?
OK... this cant possibly work this way.
At least we need to trim after splitting the attributes.
But this is not enough, we want the value, which implies
to make the type flexible (since we cant return a const& to
a substring extracted on-the-fly)
2015-08-17 01:22:01 +02:00
24d7f55935 Merge Platform upgrade and Diff-Framework development 2015-08-16 01:42:26 +02:00
40decd68d4 partial revert of preceding: rejected by GCC
this was an half hearted attempt to satisfy CLang,
but GCC as keen as a razor insists on these inherited
functions not being accessible --

seems like the time is over, when GCC used to be forgiving
and CLang briliantly precise...

So the conclusion of this "round trip" is: whenever GCC
also starts whining about shadowed overloaded virtual functions,
we'll just switch to "-Wno-overloaded-virtual" and be done with
that pointless discussion.

Since C++11, we have the Java style override specifier,
which does a way better job at spotting signature mismatches
2015-08-16 01:37:04 +02:00
9ff79b86cf fix warnings found by CLang (3.5)
Note: not fixing all relevant warnings.

Especially, the "-Woverloaded-virtual" of Clang defeats the whole purpose
of generated generic interfaces. For example, our Variant type is instantiated
with a list of types the variant can hold. Through metaprogramming, this
instantiation generates also an embedded Visitor interface, which has
virtual 'handle(TY)' functions for all the types in question

The client now may implement, or even partially implement this Visitor,
to retrieve specific data out of given Variant instance with unknown conent.
To complain that some other virtual overload is now shaddowed is besides the point,
so we might consider to disable this warning altogether
2015-08-16 01:37:04 +02:00
266cce9abe fix for compiling with CLang (3.5) 2015-08-16 01:35:31 +02:00
430107fcd8 draft impl of Record<string>
this specialisation of the Record template is provided as
default implementation for simple unit tests
2015-08-16 01:35:31 +02:00
f565ae4639 weird warning turns out to be GCC 4.7.2 Bug 56402
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56402

The lambda definition captures the this pointer,
but the ctor of the lamda does not initialise this capture.

In our case, we're lucky, as we don't use the "this" pointer;
otherwise, we'd get a crash a runtime.

Fixed since GCC-4.7.3  --> it's *really* time to upgrade to Debian/Jessie
2015-08-16 01:35:31 +02:00
00dc968d7b implement generic attribute access in Record type 2015-08-16 01:35:30 +02:00
bfb7bbd2f5 implement Record: operator string() for diagnostics 2015-08-16 01:35:30 +02:00
7f51a01631 clean-up some library and linkage problems
the object VTable is typically emitted when the compiler
encounters the first non-static non-inline function of
the class or a derived class.

Sometimes this happens within the wrong library and so
the compiler needs a nudge to emit those infrastructure functions.
But in most cases this works out of the box and need no further
magic incanctations, which might have a downside.
Especially because also a non-inline dtor does incur a call overhead,
whereas an inline dtor can be trivially elided.
2015-08-16 01:35:30 +02:00
5b0d58518e WIP: stub GenNode ref 2015-08-16 01:35:30 +02:00
ee6d044e33 WIP: implement the node builder API 2015-08-16 01:35:30 +02:00
d14c502ea9 WIP: decision about the builder sequence
after sleeping a night over this, it seems obvios
that we do not want to start the build proces "implicitly",
starting from a Record<GenNode>. Rather, we always want
the user to plant a dedicated Mutator object, which then
can remain noncopyable and is passed by reference through
the whole builder chain. Movin innards of *this object*
are moved away a the end of the chain does not pose much risk.
2015-08-16 01:35:30 +02:00
d92878876a WIP: attempt to define the object builder invocation chain
TODO still unresolved issues with the bootstrap.
Looks like we shall not initiate from the basic Rec(),
but reather require an explicit construction.
2015-08-16 01:35:30 +02:00