Commit graph

727 commits

Author SHA1 Message Date
130bc095d9 the new design takes the old name
The second design from 2017, based on a pipeline builder,
is now renamed `TreeExplorer` ⟼ `IterExplorer` and uses
the memorable entrance point `lib::explore(<seq>)`

✔
2023-06-22 20:23:55 +02:00
d109f5e1fb bye bye Monad (closes #1276)
after completing the recent clean-up and refactoring work,
the monad based framework for recursive tree expansion
can be abandoned and retracted.

This approach from functional programming leads to code,
which is ''cool to write'' yet ''hard to understand.''

A second design attempt was based on the pipeline and decorator pattern
and integrates the monadic expansion as a special case, used here to
discover the prerequisites for a render job. This turned out to be
more effective and prolific and became standard for several exploring
and backtracking algorithms in Lumiera.
2023-06-22 20:23:55 +02:00
a1c1456849 Job-Planning: dispose of FrameCoord in pipeline and Dispatcher interface
...as a preparation for solving a logical problem with the Planning-Pipeline;
it can not quite work as intended just by passing down the pair of
current ticket and dependent ticket, since we have to calculate a chained
calculation of job deadlines, leading up to the root ticket for a frame.

My solution idea is to create the JobPlanning earlier in the pipeline,
already *before* the expansion of prerequisites, and rather to integrate
the representation of the dependency relation direcly into JobPlanning
2023-06-18 03:50:48 +02:00
f84517547b Dispatcher-Pipeline: coordination of base tick and prerequisite expansion
- had to fix a logical inconsistency in the underlying Expander implementation
  in TreeExplorer: the source-pipeline was pulled in advance on expansion,
  in order to "consume" the expanded element immediately; now we retain
  this element (actually inaccessible) until all of the immediate
  children are consumed; thus the (visible) state of the PipeFrameTick
  stays at the frame number corresponding to the top-level frame Job,
  while possibly expanding a complete tree of flexible prerequisites

This test now gives a nice visualisation of the interconnected states
in the Job-Planning pipeline. This can be quite complex, yet I still think
that this semi-functional approach with a stateful pipeline and expand functors
is the cleanest way to handle this while encapsulating all details
2023-06-14 18:12:41 +02:00
ad173540d9 Library: allow for a stop condition in iterator pipeline
...introduced in preparation for building the Dispatcher pipeline,
which at its core means to iterate over a sequence of frame positions;
thus we need a way to stop rendering at a predetermined point...
2023-06-01 16:48:27 +02:00
94cec423d0 Job-Planning: switch to processing references
...which uncovers further deeply nested problems,
especially when referring to non-copyable types.

Thus need to construct a common type that can be used
both to refer to the source elements and the expanded elements,
and use this common type as result type and also attempt to
produce better diagnostic messages on type mismatch....
2023-05-23 01:08:05 +02:00
0df0fd001e Library: fix follow-up problems with const correctness
...the improved const correctness on STL iterators uncovered another
latent problem with out diagnositc format helper, which provide
consistently rounded float and double output, but failed to take
CV-qualifiaction into account
2023-05-23 01:07:53 +02:00
e176e54004 Library: adjust and fix semantics of nested 'value_type' binding
This is a subtle and far reaching fix, which hopefully removes
a roadblock regarding a Dispatcher pipeline: Our type rebinding
template used to pick up nested type definitions, especially
'value_type' and 'reference' from iterators and containers,
took an overly simplistic approach, which was then fixed
at various places driven by individual problems.

Now:
 - value_type is conceptually the "thing" exposed by the iterator
 - and pointers are treated as simple values, and no longer linked
   to their pointee type; rather we handle the twist regarding
   STL const_iterator direcly (it defines a non const value_type,
   which is sensible from the STL point of view, but breaks our
   generic iterator wrapping mechanism)
2023-05-23 01:07:53 +02:00
a940cd25bc Library: extract helper for unloading a sequence into a tuple 2023-05-10 14:49:51 +02:00
256045f91d Segmentation: add test case to cover instance management
- only the parts actually touched by the algo will be re-allocated
- when a segment is split, the clone copies carry on all data


Library: add function to check for a bare address (without type info)
2023-05-05 01:34:41 +02:00
52dad70753 Segmentation: Split-Splice algorithm implementation complete
...and verified including corner cases...
2023-05-04 15:59:17 +02:00
3f2f3db568 Segmentation: verify Split-Splice standard cases
Algorithm seems to work basically...
There was a copy-n-paste error in the treatment of the Successor,
leading to spurious duplication in some cases
2023-05-04 14:43:40 +02:00
c8f879ff3f Segmentation: extract invocation for test
typically you'd write an custom adaptor function
to define all the λ-bindings for the Algorithm
2023-05-04 12:01:25 +02:00
f9a4d6134c Segmentation: setup for simple demo test case works
due to having extracted the Algo implementation as template,
we can now instantiate it for isolated tests with simple integer intervals
2023-05-04 02:07:38 +02:00
00ca84a2aa test-helper for comparison with expected (string) result
...this is something I should have done since YEARS, really...

Whenever working with symbolically represented data, tests
typically involve checking *hundreds* of expected results,
and thus it can be really hard to find out where the
failure actually happens; it is better for readability
to have the expected result string immediately in the
test code; now this expected result can be marked
with a user-defined literal, and then on mismatch
the expected and the real value will be printed.
2023-05-04 00:48:29 +02:00
476c0f6493 Segmentation: build test-setup for Split-Splice-Algo
use simple intervals over integer numbers as test setup
- detect possible memory leaks
- detect corrupted Segmentation sequences
2023-05-03 15:27:46 +02:00
b582c35c9f Segmentation: structure analysis for splitSplice operation
There are 12 distinct cases regarding the orientation of two intervals;
The Segmentation::splitSplice() operation shall insert a new Segment
and adjust / truncate / expand / split / delete existing segments
such as to retain the *Invariant* (seamless segmentation covering
the complete time axis)
2023-05-02 04:29:34 +02:00
a807705185 Segmentation: draft simple mock-based setup for tests
- how to pass-in a specification given as GenNode
- now this might be translated into a MockJobTicket allocated in the MockSegmentation

Unimplemented: actually build the Segment with suitable start/end time
2023-05-01 17:02:11 +02:00
856d8a3b51 Library: allow to reverse intrusive single linked list
Looks like we'll actually retain and use this low-level solution
in cases where we just can not afford heap allocations but need
to keep polymorphic objects close to one another in memory.

Since single linked lists are filled by prepending, it is rather
common to need the reversed order of elements for traversal,
which can be achieved in linear time.

And while we're here, we can modernise the templated emplacement functions
2023-04-20 18:53:17 +02:00
bcd2b3d632 PlaybackVerticalSlice: design analysis for Frame Dispatcher and Scheduler
- decision: the Monad-style iteration framework will be abandoned
- the job-planning will be recast in terms of the iter-tree-explorer
- job-planning and frame dispatch will be disentangled
- the Scheduler will deliberately offer a high-level interface
- on this high-level, Scheduler will support dependency management
- the low-level implementation of the Scheduler will be based on Activity verbs
2023-04-14 04:43:39 +02:00
289f92da7e Timeline: safely calculate sum/difference of large fractional times
...in a similar vein as done for the product calculation.
In this case, we need to check the dimensions carefully and pick
the best calculation path, but as long as the overall result can
be represented, it should be possible to carry out the calculation
with fractional values, albeit introducing a small error.

As a follow-up, I have now also refactored the re-quantisation
functions, to be usable for general requantisation to another grid,
and I used these to replace the *naive* implementation of the
conversion FSecs -> µ-Grid, which caused a lot of integer-wrap-around

However, while the test now works basically without glitch or wrap,
the window position is still numerically of by 1e-6, which becomes
quite noticeably here due to the large overall span used for the test.
2022-12-01 23:23:50 +01:00
cfe3a6618f Lib: cover re-quantisation helper
...which I intend to use for sanitising poisonous rational numbers,
as prerequisite for handling divisor based time scales in the ZoomWindow
2022-11-15 02:13:57 +01:00
ce1220ee72 Lib: test coverage for rational-int corner cases and integer-log
- detailed documentation of known problematic behaviour
  when working with rational fractions
- demonstrate the heuristic predicate to detect dangerous numbers

- add extensive coverage and microbenchmarks for the integer-logarithm
  implementation, based on an example on Stackoverflow. Surprising result:
  The std::ilog(double) function is of comparable speed, at least for
  GCC-8 on Debian-Buster.
2022-11-14 05:20:37 +01:00
f393780845 Lib: fix a bug with diagnostic output
The header "format-cout.hpp" offers a convenience function
to print pretty much any object or data in human readable form.
However, the formatter for pointers used within this framework
switched std::cout into hexadecimal display of numbers and failed
to clean-up this state.

Since the "stickyness" of IOS stream manipulators is generally a problem,
we now provide a RAII helper to capture the previous stream state and
automatically restore it when leaving the scope.
2022-09-27 01:51:21 +02:00
ed7e3b4b32 ElementBox: extract builder qualifier support as library implementation
Complete the investigation and turn the solution into a generic
mix-in-template, which can be used in flexible ways to support
this qualifier notation.

Moreover, recapitulate requirements for the ElementBoxWidget
2022-08-28 23:36:27 +02:00
e15e893a01 Util: use case-insensitive matching for parsing bool values 2021-08-20 14:33:59 +02:00
4caf790339 Library: verify PlantingHandle's extended capabilities
- move construct into the buffer
- directly invoke the payload constructor through PlantingHandle
- reconsider type signature and size constraint
- extend the unit test
- document a corner case of c++ "perfect forwarding",
  which caused me some grief here
2021-05-07 22:50:13 +02:00
5a37bce855 Lib/Diff: extend PlantingHandle to allow for placment-new
...this extension was spurred by the previeous refactoring.
Since 'emplace' now clearly denotes an operation to move-embed an existing object,
we could as well offer a separate 'create' API, which would take forwarding
arguments as usual and just delegates to the placement-new operation 'create'
already available in the InPlaceBuffer class.

Such would be a convenience shortcut and is not strictly necessary,
since move-construction is typically optimised away; yet it would also
allow to support strictly non-copyable payload types.

This refactoring also highlights a fuzziness in the existing design,
where we just passed the interface type, while being sloppy about the
DEFAULT type. In fact this *is* relevant, since any kind of construction
might fail, necessitating to default-construct a placeholder, since
InPlaceBuffer was intended for zero-overhead usage and thus has in itself
no means to know about the state of its buffer's contents. Thus the
only sane contract is that there is always a valid object emplaced
into the buffer, which in turn forces us to provide a loophole for
class hierarchies with an abstract base class -- in such a case the
user has to provide a fallback type explicitly.
2021-05-02 19:40:11 +02:00
5aa41accfc Lib/Diff: prefer the name "emplace" over "build"
...for the operation on a PlantingHandle, which allows
to implant a sub type instance into the opaque buffer.

 * "create" should be used for a constructor invocation
 * "emplace" takes an existing object and move-constructs
2021-05-02 18:31:47 +02:00
acb674a9d2 Project: update and clean-up Doxygen configuration
...in an attempt to clarify why numerous cross links are not generated.
In the end, this attempt was not very successful, yet I could find some breadcrumbs...

- file comments generally seem to have a problem with auto link generation;
  only fully qualified names seem to work reliably

- cross links to entities within a namespace do not work,
  if the corresponding namespace is not documented in Doxygen

- documentation for entities within anonymous namespaces
  must be explicitly enabled. Of course this makes only sense
  for detailed documentation (but we do generate detailed
  documentation here, including implementation notes)

- and the notorious problem: each file needs a valid @file comment

- the hierarchy of Markdown headings must be consistent within each
  documentation section. This entails also to individual documented
  entities. Basically, there must be a level-one heading (prefix "#"),
  otherwise all headings will just disappear...

- sometimes the doc/devel/doxygen-warnings.txt gives further clues
2021-01-24 19:35:45 +01:00
06dbb9fad5 DiffFramework: simplify existing bindings
...by relying on the newly implemented automatic standard binding
Looks like a significant improvement for me, now the actual bindings
only details aspects, which are related to the target, and no longer
such technicalitis like how to place a Child-Mutator into a buffer handle
2021-01-23 12:55:10 +01:00
05b5ee9a7e Diff-Framework: investigate simplification for the most common case
After this long break during the "Covid Year 2020",
I pick this clean-up task as a means to fresh up my knowledge about the code base

The point to note is, when looking at all the existing diff bindings,
seemingly there is a lot of redundancy on some technical details,
which do not cary much meaining or relevance at the usage site:

- the most prominent case is binding to a collection of DiffMutables hold by smart-ptr
- all these objects expose an object identity (getID() function), which can be used as »Matcher«
- and all these objects can just delegate to the child's buildMutator() function
  for entering a recursive mutation.
2021-01-22 12:38:45 +01:00
657b94a4e3 ++ a strange year passed by ++
read the code, documentation and mindmap to find out
at what point I was when this story unfolded
2021-01-20 08:05:30 +01:00
dd016667ad Diff-Listener: add a variant to trigger also on value assignment (see #1206)
As it turned out, it is rather easy to extend the existing listener
for structural changes to detect also value assignments. Actually
it seems we'd need both flavours, so be it.
2020-03-15 23:11:14 +01:00
0f6f09180e Lib: simplified optional access to nested record attributes
Yeah, C++17, finally!

...not totally sure if we want to go that route.
However, the noise reduction in terms of code size at call site looks compelling
2020-03-14 23:52:04 +01:00
c7d157e295 Library: integrate generic min/max function
...built while investigating type deduction problems on PtrDerefIter
...also allow PtrDerefIter to work with std::unique_ptr
2020-03-08 02:05:39 +01:00
b2b5cf0f6d MERGE: upgrade to Debian/Buster and to C++17 2020-02-22 02:16:25 +01:00
421a2ed49a C++17: some related clean-up 2020-02-21 23:55:09 +01:00
00c9ecb659 C++17: fix detector for function signatures
failure was likewise caused by `noexcept` being part of the signature type now
2020-02-21 20:16:59 +01:00
8c12e88fd3 C++17: fix detector for STL container iterability
the reason for the failure, as it turned out,
is that 'noexcept' is part of the function signature since C++17

And, since typically a STL container has const and non-const variants
of the begin() and end() function, the match to a member function pointer
became ambuguous, when probing with a signature without 'noexcept'

However, we deliberately want to support "any STL container like" types,
and this IMHO should include types with a possibly throwing iterator.
The rationale is, sometimes we want to expose some element *generator*
behind a container-like interface.

At this point I did an investigation if we can emulate something
in the way of a Concept -- i.e. rather than checking for the presence
of some functions on the interface, better try to cover the necessary
behaviour, like in a type class.

Unfortunately, while doable, this turns out to become quite technical;
and this highlights why the C++20 concepts are such an important addition
to the language.

So for the time being, we'll amend the existing solution
and look ahead to C++20
2020-02-21 18:57:49 +01:00
577592c66e C++17: isolate problematic code segments (see Ticket #1138)
as it turns out, "almost" the whole codebase compiles in C++17 mode.

with the exception of two metaprogramming-related problems:

 - our "duck detector" for STL containers does not trigger anymore
 - the Metafunction to dissect Function sigantures (meta::_Fun) flounders
2020-02-18 04:16:03 +01:00
3cfe5a13b1 fix failing test - boost::format is getting better
"%broken" is not broken anymore, but renders a boolean,
and we configured the formatter not to complain on missing values.

Fortunately "%madness" is still broken ;-)
2020-02-17 03:32:43 +01:00
cef7917d8e Diff-Listener: finished and unit test pass (closes: #1206) 2019-12-15 21:40:09 +01:00
d8b20ae497 Diff-Listener: fill in implementation
...basically just need to intercept three TreeMutator-operations
2019-12-15 04:04:25 +01:00
a33e236630 Diff-Listener: define API 2019-12-14 23:35:16 +01:00
806d569e06 Diff-Framework: resolve lurking problems with specific STL containers
basically the solution was a bit too naive and assumed everything is similar to a vector.
It is not, and this leads to some insidious problems with std::map, which hereby
are resolved by introducing ContainerTraits
2019-12-14 01:29:21 +01:00
8a5f1bc8d7 Diff-Listener: add a similar simplistic demo for opaque binding
based on a TreeMutator binding to a STL vector

...because this is probably the most frequently used case
2019-12-13 01:05:04 +01:00
3321e5bc6b Diff-Listener: need a really basic test
All of the existing "simple" tests for the »Diff Framework« are way to much low-level;
they might indeed be elementary, but not introductory and simple to grasp.
We need a very simplistic example to show off the idea of mutation by diff,
and this simple example can then be used to build further usage test cases.

My actual goal for #1206 to have such a very basic usage demonstration and then
to attach a listener to this setup, and verify it is actually triggered.

PS: the name "GenNodeBasic_test" is somewhat pathetic, this test covers a lot
of ground and is anything but "basic". GenNode in fact became a widely used
fundamental data structure within Lumiera, and -- admittedly -- the existing
implementation might be somewhat simplistic, while the whole concept as such
is demanding, and we should accept that as the state of affairs
2019-12-12 23:41:26 +01:00
bdf3351f55 ClipDisplay: basic implementation of ViewHook helper 2019-11-08 20:49:37 +01:00
6b4bf0a6ea Library: allow to check if Advice was explicitly given
For context: The »Advice System« was coined a long time ago, in 2010,
based on the vague impression that it might be useful for that kind of application
we are about to build here. And, as can be expected, none of the usage situations
envisioned at that time was brought to bear. Non the less, the facility came in
handy at times, precisely because it is cross-cutting and allows to pass
information without imposing any systematic relationship between the
communication partners.

And now we've got again such a situation.
The global style manager in the UI has to build a virtual CSS path,
which is needed by drawing code somewhere deep down, and we absolutely
do not want to pass a reference to the style manager over 20 recursive calls.

The alternatives would be
 (1) to turn the style manager into a public service
 (2) to have a static access function somewhere
 (3) to use a global variable.
For rationale, (1) would be overblown, because we do not actually request
a service to do work for us, rather we need some global piece of information.
(2) would be equivalent to (1), just more confusing. And (3) is basically
what the Advice system does, with the added benefit of a clear-cut service
access point and a well defined lifecycle.

This changeset adds the ability to check if actual Advice has been published,
which allows us to invoke the (possibly expensive) GTK path building and
style context building code only once.
2019-07-13 17:00:23 +02:00
ab90d9c71d Functions-Commands: discard the ability to compare functors for equivalence (closes #294)
evil hack R.I.P
2019-06-23 19:45:30 +02:00
94edb5de86 BufferMetadata: likewise abandon use of function comparison for buffer handlers
The existing implementation created a Buffer-Type based on various traits,
including the constructor and destructor functions for the buffer content.
However, this necessitates calculating the hash_value of a std::function,
which (see #294) is generally not possible to implement.

So with this changeset we now store an additional identity hash value
right into the TypeHandler, based on the target type placed into the buffer
2019-06-23 18:57:21 +02:00
f6e5886348 Library: complete test coverage of VerbPack 2019-06-11 02:40:20 +02:00
3d5a67ed14 Library: finish and clean-up the solution for VerbPack dispatch 2019-06-10 16:08:50 +02:00
8f43c2591e Library: investigate malfunction in metaprogramming
the template lib::PolymorphicValue seemingly picked the wrong
implementation strategy for "virtual copy support": In fact it is possible
to use the optimal strategy here, since our interface inherits from CloneSupport,
yet the metaprogramming logic picked the mix-in-adapter (which requires one additional "slot"
of storage plus a dynamic_cast at runtime).

The reason for this malfunction was the fact that we used META_DETECT_FUNCTION
to detect the presence of a clone-support-function. This is not correct, since
it can only detect a function in the *same* class, not an inherited function.

Thus, switching to META_DETECT_FUNCTION_NAME solves this problem
Well, this solution has some downsides, but since I intend to rewrite the
whole virtual copy support (#1197) anyway, I'll deem this acceptable for now


TODO / WIP: still some diagnostics code to clean up, plus a better solution for the EmptyBase
2019-05-10 02:19:01 +02:00
23c9da7c62 Library: solve the dilemma by inheriting from VerbToken
...which, in the end, can even be considered the more logical design choice,
since the "verb visitor" is a more elaborated and sophisiticated Verb-Token,
adding the special twist of embedded storage for variable function arguments
2019-05-09 23:40:47 +02:00
a530665769 Library: fix some reference passing errors
...but bad news on the main issue:
the workaround consumes the tuple and thus is not tenable!

And what is even worse: the textbook implementation of std::apply is
equivalent to our workaround and also consumes the argument tuple
2019-04-22 16:54:22 +02:00
e28635a11a Library: investigate copy behaviour in forwarding calls 2019-04-21 03:52:34 +02:00
5191073558 Library: continue Investigation with workaround, inconclusive yet
A simple yet weird workaround (and basically equivalent to our helper function)
is to wrap the argument tuple itself into std::forward<Args> -- which has the
effect of exposing RValue references to the forwarding function, thus silencing
the compiler.

I am not happy with this result, since it contradicts the notion of perfect forwarding.

As an asside, the ressearch has sorted out some secondary suspicions..
- it is *not* the Varargs argument pack as such
- it is *not* the VerbToken type as such

The problem clearly is related to exposing tuple elements to a forwarding function.
2019-04-20 17:27:47 +02:00
6fbd1021ba Library: first attempt to get the flexible VerbToken to work
...still not decided yet if this whole apporach is sound...
2019-04-17 18:32:21 +02:00
9b5fdd39b8 Library: draft for a visitor-like VerbToken
this is a generalisation of what we use in the diff framework;
typically you'd package the VerbToken into some kind of container,
together with the concrete invocation argument.

However, the specific twist here is that we want *variable arguments*,
depending on the actual operation called on the interpreter interface.
2019-04-16 18:21:51 +02:00
ec9b2388da Timeline: consider how to integrate the drawing code
...which leads to a specific twist here; while in the simple version
we still could hope to get away with a simple uniform uint argument,
the situation has changed altogether now. The canvas has turned into
some generic component, since it is instantiated two times, onece for
the time ruler and once for the actual body content. Thus all of the
specifics of the drawing code need to be pushed into a new, dedicated
renderer component. And this more or less forces us to pass all the
actual presentation variations through the invocation arguments of
the visitor.

So we're now off again for a digression, we need a more generalised visitor
2019-04-14 15:38:57 +02:00
48a829d544 Library: clarify usage of the basic time scale
effectively we rely in the micro tick timescale promoted by libGAVL,
but it seems indicated to introduce our own constant definition.
And also clarify some comments and tests.

(this changeset does not change any values or functionality)
2018-12-10 00:12:52 +01:00
d3d7ea35ad Global-Layer-Renaming: fix remaining textual usages and IDs in the code
- most notably the NOBUG logging flags have been renamed now
 - but for the configuration, I'll stick to "GUI" for now,
   since "Stage" would be bewildering for an occasional user
 - in a similar vein, most documentation continues to refer to the GUI
2018-12-10 00:09:56 +01:00
02c5809707 Global-Layer-Renaming: adjust namespace qualification 2018-11-15 23:59:23 +01:00
2d5ebcd5fa Global-Layer-Renaming: adjust header includes 2018-11-15 23:42:43 +01:00
9e951e1eeb Global-Layer-Renaming: adapt lots of documentation 2018-11-15 21:13:52 +01:00
1bbe903202 GenNode: revert -- better not handle this problem on ETD level
...rather extend the "object builder" DSL notation to allow passing in a given EntryID literally.
Rationale is, we should handle the problem of unique IDs on the level of the domain model.
If we attempt to "fix" this within GenNode, the price would be to make the ETD creation stateful
2018-11-09 22:50:48 +01:00
572bd38fec DummySessionConnection: produce a simple population diff message
seems to work surprisingly well...
the diff application poceeds in the GUI up to the point
where the TrackPresenter need to be inserted into a two-fold display context
2018-10-15 02:54:42 +02:00
fa6ba76f85 investigate insidious ill-guided conversion
As it turns out, using the functional-notation form conversion
with *parentheses* will fall back on a C-style (wild, re-interpret) cast
when the target type is *not* a class. As in the case in question here, where
it is a const& to a class. To the contrary, using *curly braces* will always
attempt to go through a constructor, and thus fail as expected, when there is
no conversion path available.

I wasn't aware of that pitfall. I noticed it since the recently introduced
class TimelineGui lacked a conversion operator to BareEntryID const& and just
happily used the TimelineGui object itself and did a reinterpret_cast into BareEntryID
2018-10-12 23:42:56 +02:00
e81b0592d3 TreeMutator: combine no-op layer with selective other diff binding
...and complete unit test coverage.
This is complex stuff and we'd better be careful it actually works
2018-10-12 02:05:11 +02:00
fb93e349da TreeMutator: conjure up a black hole mutator
...which is a somewhat involved version of /dev/null
2018-10-11 23:56:33 +02:00
c6b8811af0 Library: utility to interpret a text as bool value (yes/no)
...also fixes the problem with the "expand" mark in DemoGuiRoundtrip
2018-10-03 04:43:16 +02:00
5a7a5a5720 DOC: fix syntax of some doxygen links
seemingly we really need the \ref in the link target expression
2018-09-21 14:33:12 +02:00
03a1d58198 EventLog: verify and complete the TestEventLog_test
can now cover all the cases as initially intended,
including backtracking
2018-09-19 02:52:38 +02:00
1683439b32 ChainSearch: backtracking verified -- finished 2018-09-16 01:08:49 +02:00
84399aa407 ChainSearch: verify proper interplay of two dynamic search conditions 2018-09-16 01:08:49 +02:00
38a1aad897 ChainSearch: bugfixes on reworked construction
...seems basically sane now.
Just we still need to wrap it one more time into IterableDecorator;
which means the overall scheme how to build and package the whole pipeline
is not correct yet.

Maybe it is not possible to get it packaged all into one single class?
2018-09-16 01:08:48 +02:00
05e6e7f316 ChainSearch: remould construction to get the logic correct
on closer investigation it turned out that the logic of the
first design attempt was broken altogether. It did not properly
support backtracking (which was the reason to start this whole
exercise) and it caused dangling references within the lambda
closure once the produced iterator pipeline was moved out
into the target location.

Reasoning from first principles then indicated that the only sane
way to build such a search evaluation component is to use *two*
closely collaborating layers. The actual filter configuration
and evaluation logic can not reside and work from within the
expander. Rather, it must sit in a layer on top and work in
a conventional, imperative way (with a while loop).

Sometimes, functional programming is *not* the natural way
of doing things, and we should then stop attempting to force
matters against their nature.
2018-09-16 01:08:45 +02:00
767156e912 TreeExplorer: unit test coverage for injected custom layer 2018-09-16 01:07:23 +02:00
8aae789b82 ChainSearch: test case to scrutinise chained filter reconfiguration
...and TADAA ... there we get an insidious bug:

we capture *this by reference into the expansion functor,
and then we move *this away, out from the builder into the target....
2018-09-14 21:06:15 +02:00
29d2c151b3 ChainSearch: add builder function just to replace the filter
Up to now, we had a very simplistic configuration option just
to search for a match, and we had the complete full-blown reconfiguration
builder option, which accepts a functor to work on and reconfigure the
embedded Filter chain.

It occurred to me that in many cases you'd rather want some intermediary
level of flexibility: you want to replace the filter predicate entirely
by some explicitly given functor, yet you don't need the full ability
to re-shape the Filter chain as a whole. In fact the intended use case
for IterChainSearch (which is the EventLog I am about to augment with
backtracking capabilities) will only ever need that intermediate level.


Thus wer're adding this intermediary level of configurability now.

The only twist is that doing so requires us to pass an "arbitrary function like thing"
(captured by universal reference) through a "layer of lambdas". Which means,
we have to capture an "arbitrary thingie" by value.

Fortunately, as I just found out today, C++14 allows something which comes
close to that requirement: the value capture of a lambda is allowe to have
an intialiser. Which means, we can std::forward into the value captured
by the intermediary lambda. I just hope I never need to know or understand
the actual type this captured "value" takes on.... :-)
2018-09-14 21:06:15 +02:00
10f21f77f8 ChainSearch: resolve the problems and get basic functionality to work
with the augmented TreeExplorer, we're now able to get rid of the
spurious base layer, and we're able to discard the filter and
continue with the unfiltered sequence starting from current position.
2018-09-14 21:06:15 +02:00
df7a9492b7 TreeExplorer: helper function so support ChainSearch::clearFilter()
build a special feature into the Explorer component of TreeExplorer,
causing it to "lock into" the current child sequence and discard
all previous sequences from the stack of child explorations
2018-09-14 21:06:15 +02:00
7cdd680e78 TreeExplorer: clean-up after refactoring
So we have now a reworked version of the internals of TreeExplorer in place.
It should be easier to debug template instantation traces now, since most
of the redundancy on the type parameters could be remove. Moreover, existing
pipelines can now be re-assigned with similarily built pipelines in many cases,
since the concrete type of the functor is now erased.

The price tag for this refactoring is that we have now to perform a call
through a function pointer on each functor invocation (due to the type erasure).
And seemingly the bloat in the debugging information has been increased slightly
(this overhead is removed by stripping the binary)
2018-09-14 21:06:15 +02:00
36d79be8b2 TreeExplorer: refactor Filter in a similar way 2018-09-14 21:06:15 +02:00
1e657acbff TreeExplorer: refactor Transformer to employ the improved wrapping style
...step by step switch over to the new usage pattern.
Transformer should be the blueprint for all other functor usages.


The reworked solutions behaves as expected;
we see two functor invocations; the outer functor, which does
the argument adaptation, is allocated in heap memory
2018-09-14 21:06:15 +02:00
e3ca8548a4 TreeExplorer: allow for a disabled filter
...considered as one of the building blocks to resolve Problems in the Design of ChainSearch
2018-09-14 21:06:15 +02:00
34b78fc47e ChainSearch: identify some possible problems
- as implemented now, we will finally backtrack into the unfiltered base iterator
- it is not possible to implement a clearFilter() operation
2018-09-14 21:06:15 +02:00
d923138d1c ChainSearch: configure the core of the chained search mechanism
...based on a monadic tree expansion: we define a single step,
which takes the current filter configuration and builds the next
filter configuration, based on a stored chain of configuration functions

The actual exhausting depth-first results just by the greedy application pattern,
and uses the stack embedded in the "Explorer" layer of TreeExplorer
2018-09-14 21:06:14 +02:00
d398177a71 ChainSearch: now actually build the processing pipeline in the ctor
..this resolves the most challenging part of the construction work;
we use the static helper functions to infer a type and construct a suitable
processing pipeline and we invoke the same helper to initialise the base class
in the ctor.

Incidentally... we can now drop all the placeholder stubs,
since we now inherit the full iterator and child explorer API.
The test now starts actually to work... we get spam and sausage!

TODO: now actually fill in the expand functor such as to pick the
concrete filter step in the chain from a sequence of preconfigured
filter bindings
2018-09-14 21:06:14 +02:00
9b0937bc63 ChainSearch: move into namespace iter
...seems to be a not-so-commonly used helper
2018-09-14 21:06:14 +02:00
a52ed91de0 ChainSearch: draft a solution how to construct the Expand functor type
...now matters start to get really nasty,
since we have to pick up an infered type from a partially built pipeline
and use it to construct the signature for a functor to bind into the more elaborate complete pipeline
2018-09-14 21:06:14 +02:00
6834c26470 ChainSearch: draft a solution how to construct the pipeline builder base type
this is a tricky undertaking, since our treeExplore() helper constructs
a complex wrapped type, depending on the actual builder expressions used.

Solution is to use decltype on the result of a helper function,
and let the _DecoratorTraits from TreeExplorer do the necessary type adaptations
2018-09-14 21:06:14 +02:00
4988153e15 Library: prevent implicit bool conversion on iterator-like objects
...it should have been this way all the time.
Generic code might otherwise be ill guided to assume a conversion
from the Iterator to its value type, while in fact an explicit dereferentiation is necessary
2018-09-14 21:06:14 +02:00
433543a2c7 DOC: some doxygen fixes 2018-09-14 21:06:14 +02:00
ec8d0557e8 ChainSearch: draft interface and possible implementation approach
The intention is to augment the iterator based (linear) search
used in EventLog to allow for real backtracking, based on a evaluation tree.
This should be rather staight forward to implement, relying on the
exploreChildren() functionality of TreeExplorer. The trick is to package
the chained search step as a monadic flatMap operation
2018-09-14 21:06:14 +02:00
604ffbf73c TreeExplorer: fix a bug and finish the feature
we did an unnecessary copy of the argument, which was uncovered
by the test case manipulating the state core.


Whew.
Now we have a beautiful new overengineered solution
2018-09-14 21:06:14 +02:00
be7f47d5b7 TreeExplorer: rework the solution to allow for arbitrary functor types
outift the Filter base class with the most generic form of the Functor
wrapper, and rather wrap each functor argument individually. This allows
then to combine various kinds of functors
2018-09-14 21:06:14 +02:00
90c0f43cfd TreeExplorer: code all the combination cases
...this solution works, but has a shortcoming:
the type of the passed lambdas is effectively pinned to conform
with the signature of the first lambda used initially when building the filter.

Well, this is the standard use case, but it kind of turns all the
tricky warpping and re-binding into a nonsense excercise; in this form
the filter can only be used in the monadic case (value -> bool).

Especially this rules out all the advanced usages, where the filter
collaborates with the internals of the source.
2018-09-14 21:06:14 +02:00