Commit graph

1847 commits

Author SHA1 Message Date
c5292dd0dd Clean-up: get rid of boost::filesystem
Since C++17 we can use the std::filesystem instead (and we ''do use it'' indeed)
- relocate the `/lib/file.hpp` header
- adapt the self-discovery of the executable to using std::filesystem

Furthermore, some recherche regarding XVideo and Video Output
2025-04-27 23:54:21 +02:00
555af315b3 Upgrade: improve Doxygen parameters and treat some warnings
- remove obsolete configuration settings
- walk through all settings according to the documentation
  https://www.doxygen.nl/manual/config.html
- now try to use the new feature to rely on Clang for C++ parsing
- walk through the doxygen-warnings.txt and fix some obvious misspellings
  and structural problems in the documentation comments.

With Debian-Trixie, we are now using Doxygen 1.9.8 —
which produces massively better results in various fine points.

However, there are still problems with automatic cross links,
especially from implementation to the corresponding test classes.
2025-04-27 05:00:14 +02:00
a68f145640 Upgrade: fix test-failures(3)
The Boost-Libraries changed their internal implementation
of the formula to chain hash values.

Fortunately, we had already extracted the existing implementation
from Boost 1.67 and incorporated it in-tree, in the Lumiera support libary.
After switching to that `lib:#️⃣:combine()` function, all the graph
computations related to the Scheduler-test-load can be shown to be identical.

So at the moment, the impact is still limited, but this incident highlights
the importance of a controlled, stable (and ideally also portable) hash implementation.
2025-04-25 19:54:28 +02:00
4ce936529e Upgrade: fix test-failures(2)
seems that I've played too much with »undefined behaviour« in this test;
basically we can not assume ''any'' specific placement of local variables
in a stack frame....

In this test, what I wanted to demonstrate is that the overflow-block can reside
just »anywhere«, and that HeteraoData is just a light-weight front-End and accessor.

However, I can just demonstrate that without totally ''undefined behaviour;''
placement-new can be used to force the storage at a specific location (in the UninitialiesdStorage);
continue to access and use that data after leaving the nested scope is still
kind-of borderline, yet demonstrates that the data itself is just residing in a storage block...
2025-04-25 19:02:04 +02:00
1d3cb6b23b Upgrade: fix test-failures (1)
- with Debian 12/13, the top-level `/bin`, `/sbin` and `/lib`
  are collapsed into `/usr`. Seemingly this has prompted changes
  to the way the shell prints some error messages. This broke
  the expectation of some test of the test-framework itself.

- SCons always had the policy to ''sanitise'' the invocation environment,
  to prevent unintended impact of environment settings to the test subject.
  Seemingly this now also leads to `$HOME` not being defined.
  Our file handling framework however expects to be able to expand "~"

- An old-style cast in the constructor lib::diff::Record(Mutator const&)
  is now translated into a static_cast (≙conversion); and since the appropriate
  conversion operator is missing on Mutator, the constructor attempts to
  create a temporary, by re-invoking the same constructor ⟹ Stackoverflow ↯
2025-04-24 23:39:58 +02:00
96c654f66c Upgrade: address further warnings
- conversion from pointer to bool now counts as ''narrowing conversion''
 - constructor names must not include template arguments (enforced with C++20)
 - better use std::array for some dummy test code

Several further warnings are due to known obsoleted or questionable constructs
and were left as-is (e.g. for ScopedHolder) or just commented for later referral
2025-04-15 23:40:14 +02:00
92c99e5b7d Upgrade: re-enable Doxygen generation
The new version indeed works as expected,
and current Doxygen produces much better cross links
:-)
2025-04-08 05:07:58 +02:00
8fe2deed95 Upgrade: allow for build on »Trixie« with GCC-14
* need to upgrade our custom packages to current standards
 * switch those packages from CDBS to dh
 * re-build on Trixie and upgrade the Lumiera DEB-Depot

After these (in detail quite expensive) preparations,
build with Scons and GCC-14 can be started.

Fix some further (basically trivial) compile problems,
uncovered by the improved type checking of modern compilers.

Note: a tremendous amount of warnings (and depreciations) is
also indicated, which will be addressed later....
2025-04-06 18:18:52 +02:00
efcb456e25 Invocation: ++ Milestone ++ invoke complex render graph
Based on the building blocks developed thus far,
it was possible to assemble a typical media processing chain
 * two source nodes
 * one of these passes data through a filter
 * a mixer node on top to combine both chains
 * time-based automation for processing parameters
As actual computation, hash-chaining on blocks of
reproducible random data was used, allowing to verify
for every data word that expected computations were
carried out, in the expected order.
2025-02-19 23:27:52 +01:00
93812d5a6d Invocation: build a complex Render Node network for integration test
Using basically the same topology as in the preceding test, which focused on connectivity. However, in this case we retrieve actual processing functions from the »Test-Rand« ontology in order to perform hash-chaining computations on full data blocks. And, in addition, a »Param Agent Node« is used.
2025-02-19 19:37:55 +01:00
6c2761b337 Invocation: complement NodeBase_test with simple example
While initially intended as introductory test, it meanwhile
focuses on intricate technical details on the level of
basic building blocks, notably the `FeedManifold`

Now I have added a simple end-to-end demonstration example
how a Render Node is built from scratch, leaving out all
technical details and all convenience front-ends like
the `NodeBuilder` — just one dummy port invoked directly.
2025-02-19 01:30:54 +01:00
8a4060861f Invocation: complete simple test case regarding TurnoutSystem
NodeBase_test demonstrates the building blocks of a Render Node,
and verifies low-level mechanics of those building blocks, which
can be quite technical. At the top of this test however are some
very basic interactions, which serve as an introduction.

__Remark__: renamed the low-level technical dispatch-access
for the parameter-accessors in `TurnoutSystem` to be more obvious,
and added comment (I was confused myself how to use them properly)
2025-02-18 23:55:58 +01:00
b7fc2df478 Invocation: NodeBuilder now handles all cases of partial-closure
This is a crucial feature, discovered only late, while building
an overall integration test: it is quite common for processing functionality
to require both a technical, and an artistic parametrisation. Obviously,
both are configured from quite different sources, and thus we need a way
to pre-configure ''some parameter values,'' while addressing other ones
later by an automation function. Probably there will be further similar
requirements, regarding the combination of automation and fixed
user-provided settings (but I'll leave that for later to settle).

On a technical level, wiring such independent sources of information
can be quite a challenging organisational problem — which however can be
decomposed using ''partial function closure'' (as building a value tuple
can be packaged into a builder function). Thus in the end I was able to
delegate a highly technical problem to an existing generic library function.
2025-02-18 20:42:25 +01:00
e014d88b2c Invocation: complete closure-helper and tests
* now able to demonstrate close-front, close-back and close-argument
 * can also apply the same cases to `std::array`, with input and
   output type seamlessly adapted to `std::array`
2025-02-18 00:24:55 +01:00
89f839854c Invocation / Library: analyse perfect-forwarding in function-closure
__Summary__:
 * the first part to prepare a binding involves creating a mapped tuple,
   with re-ordered elements and some elements replaced by placehoder-markers.
   This part **must not use RValue-References** (doing so would be possible
   only under very controlled conditions)
 * the second part, which transports these mapped-tuple elements into the binder
   ''could be converted to perfect-forwarding.'' This would require to replace
   the `Apply<N>' by a variadic template, delegating to `std::apply` and `std::bind`

With this changeset, I have modernised a lot of typedefs to make them more legible,
and I have introduced perfect-forwarding in the entrance path, up to the point
where the values are passed to `TupleConstructor`.
2025-02-17 23:34:06 +01:00
a5a3d46b6a Invocation: generalise partial-closure cases
With these additions, all conceivable cases are basically addressed.

Take this as opportunity to investigate how the existing implementation
transports values into the Binder, where they will be stored as data fields.
Notably the mechanism of the `TupleConstructor` / `ElmMapper` indeed
''essentially requires'' to pass the initialisers ''by-reference'',
because otherwise there would be limitations on possible mappings.

This implies that not much can be done for ''perfect forwarding'' of initialisers,
but at least the `BindToArgument` can be simplified to take the value directly.
2025-02-17 21:18:37 +01:00
0cad2dacc0 Invocation: build a solution to adapt std::array
...which should ''basically work,'' since `std::array` is ''»tuple-like«'' —
BUT unfortunately it has a quite distinct template signature which does not fit
into the generic scheme of a product type.

Obviously we'd need a partial specialisation, but even re-implementing this
turns out to be damn hard, because there is no way to generate a builder method
with a suitable explicit type signature directly, because such a builder would
need to accept precisely N arguments of same type. This leads to a different
solution approach: we can introduce an ''adapter type'', which will be layered
on top of `std::array` and just expose the proper type signature so that the
existing Implementation can handle the array, relying on the tuple-protocol.


__Note__: this changeset adds a convenient pretty-printer for `std::array`,
based on the same forward-declaration trick employed recently for `lib::Several`.
You need to include 'lib/format-util.hpp' to actually use it.
2025-02-17 18:36:23 +01:00
8bb332cc5e Invocation: reorganise and add test 2025-02-16 23:40:43 +01:00
769060b9dd Invocation: extract partial closure functionality
What emerges here, seems to be a generic helper to handle
partial closure of ''tuple-like'' data records. In any case,
this is highly technical meta-programming code and mandates
extraction into a separate header — simplifying `NodeBuilder`
2025-02-16 23:16:46 +01:00
3611bc94ee Invocation: investigate ways to provide partial application
...on top of the parameter-decorating functionality developed thus far.
The idea is to allow in the `NodeBuilder` to supply ''some parameters''
directly, while the remaining parameters will be drawn from automation.

Several years ago, I developed some helpers for partial function closure.
Unfortunately these utils are somewhat limited, and rely on some pre-C++11
constructs, yet seem to be usable for the task at hand, since parameters
are always expected as value objects by definition.

This changeset shows a working proof-of concept for left-closing a
parameter tuple with 5 elements; this turns out to surprisingly difficult
due to the full genericity of the acceptable parameter-aggregates...
2025-02-15 23:47:21 +01:00
79b45601c0 Invocation: rearrange for clearer definitions
seemingly the definition can not be much simplified,
since there is no way around handling several definition flavours
of the processing-functor distinctly.

However, the definitions can be rearranged to be clearer,
the resulting type of the `FeedPrototype` can be deduced from the
builder function, and more stringent assertions can be added
2025-02-13 16:27:50 +01:00
0e5ffe7780 Invocation: draft a way to decorate the processing-functor
...the idea is to limit the scope of possible changes
and rather directly accept a functor to transform the parameters.
We need then to account for the possible flexibility in processing-functor
arguments, while in fact only two cases must be actually handled.

''This proof-of-concept works in test setup''
2025-02-11 17:15:32 +01:00
61c685fa9f Invocation: draft missing feature for integration test
It seemed that the integration test will end up as a dull repetition
of already coded stuff, just with more ports and thus more boilerplate;
and so I reconsidered what an actually relevant integration test might encompass
- getting parameters from the invocation
- translating and wiring parameters
- which entails to adapt / partially close a processing function!

Thus — surprise — there is a new feature not yet supported by the `NodeBuilder`,
which would be very likely to be used in many real-world use cases: which is
to adapt the parameter tuple expected by the binding from the library.
Obviously we want this, since many »raw« processing functions will expose a mix
of technical and artistic parameters; and we'd like to ''close'' the technical ones.

Such a feature ''should be implementable,'' based on the already developed
technique with the »cross builder«, which implies to switch the template arguments
from within a builder expression. We already do this very thing for adapting
parameter functor, and thus the main difficulty would be to compose an
adaptor functor to the correct argument of the processing functor...

Which is... (well, it is nasty and technical, yet feasible).
2025-02-11 01:10:25 +01:00
8694d9ebc1 Invocation: also provide a mixer node backed by ''Test Rand'' 2025-02-10 22:48:31 +01:00
72d7a6c5b8 Invocation: ''Test Rand'' filter node test pass 2025-02-10 03:41:05 +01:00
ccb10f3c65 Invocation: chase down insidious use-after-free problem
Just wanted to use a helper function to build a source-data node.
However, the resulting node had a corrupted Node-ID spec.
Investigation with the debugger showed that the ID was still valid
while in construction and shows up corrupted after returning from the
helper function.

As it turned out, the reason is related to the de-duplication of ProcID data.
While the de-duplicated strings themselves are ''not'' affected, the corruption
happened by an intermediate instance of ProcID, which was inadvertently created
and bound by-value to the builder-λ. The created Port then picks up a reference
to this temporary, leading to the use-after-free of the string_view obejcts.

Obviously, `ProcID` must not be instantiated other than through the static
front-end `ProcID::describe`. Due to the private constructor, I can not make this
object non-copyable (because then the hash-set would not be allowed to emplace it).
But making it at least move-only will provoke a compiler error whenever binding
to a lambda capture by value, which hopefully helps to pinpoint this
insidious problem in the future...
2025-02-10 03:15:28 +01:00
5121bce156 Invocation: cover definition of a »Test-Rand« filter-node
The scheme to provide preconfigured nodes with random `TestFrame` data
seems to be suitable and easy to extend to further cases; should however
always document the setup through a dedicated case in `NodeDevel_test`
2025-02-09 23:05:41 +01:00
b9b80ce923 Invocation: draft setup for a Test-Node for data-manipulation
Seems to be straight forward now, based on the implementation
of `TestFrame` manipulation provided by the »Test Rand Ontology«


__Remark__: the next goal is to reproduce the complex Node tree
with operations on TestFrame and then to invoke these and verify results.
2025-02-09 18:04:39 +01:00
f767cce77b Invocation: also invoke all these nodes
...while this is not the main objective of this test case,
and another test will focus on invocation with full-fledged
`TestFrame` buffers and hash computation...

...it is still a nice achievement to see that these simple
algebraic operations used for demonstration can actually be
invoked in the whole connected network :-)
2025-02-09 01:44:45 +01:00
d54dbc93df Invocation: verify connectivity on complex network 2025-02-08 22:42:13 +01:00
dbbdac02c4 Invocation: now able to code verifications for the demo-network
Using a Node network with
 * two source nodes
 * one of them chained up linearly with a filter node
 * then on top a mix node to combine both chains

Can now verify the generated port specs and verify proper connections
at node level and at port level
2025-02-08 19:39:00 +01:00
72d7986b5e Invocation: build a DSL to verify connectivity (see #1377)
This was a lot of intricate technical work,
and is now verified in-depth, covering all possible cases.

__We can now__
 * build Nodes
 * verify in detail correct connectivity
 * read Node-IDs and processing specifications
 * maintain a symbolic spec for the arguments of a Port

(and beyond that, we can also **invoke nodes**, which remains to be formally verified)
2025-02-05 00:25:02 +01:00
d5a47bf3e4 Invocation: consider how to verify connectivity
An essential goal still to reach is a verification of the `NodeBuilder`'s products
Relying on the low-level diagnostic facilities pioneered last days,
it should now be possible to define simple and readable connectivity-clauses,
allowing to build some connected nodes and then verify the connections explicitly.
2025-02-04 20:25:33 +01:00
fa720ae975 Invocation: for now only set flags by builder
Handling of extended attributes in conjunction with the hash
turns out to be a rather complicated topic, with some tricky fine details.
And, most important, at the moment I am lacking the proper perspective
to address it and find adequate solutions. Luckily, the cache-key is
not required at the moment, ''and so this topic will be postponed''

As a minimum to complete the diagnostics functions, it is sufficient to set
the appropriate flags in the `ProcID` directly -- and to add some convenience wrappers.
2025-02-04 00:22:55 +01:00
72543a8b34 Invocation: investigate kind of data to be represented in ProcID
...especially the extended attributes remain somewhat nebulous,
since non of the prospective usages are close to being implemented right now.

It seems, we'll get two distinct sources at construction time of the Node
 * additional qualifiers from the Library plug-in
 * internal flags or qualifiers provided by the `NodeBuilder`

Another related concern seems to be generation of cache-keys,
which however will ''consume'' the proc-hash generated by the ProcID,
but not change the ID itself; cache-key generation is a tricky subject
and was somewhat overlooked regarding the connection to the `BufferProvider`.

Opened a new ticket #1292 as reminder for this issue.
2025-02-03 22:10:10 +01:00
583b73bc62 Invocation: now able to access predecessor-ports
...exploiting the ''backdoor access'' bypassing the VTable,
as made possible by a common congruent storage layout.

This is a first proof-of-concept, but also shows that the demo nodes
in NodeMeta_test are wired as expected. What is needed now is to make
this diagnostic access easier to invoke and more bullet-proof, by setting
the proper Attribute bits directly in the `NodeBuilder`
2025-02-03 03:54:21 +01:00
bcdcb36615 Invocation: rearrange MediaWeavingPattern storage layout
...to create an ''access path for diagnostics'' and further evaluations
while ''bypassing the VTable.''

It is a well-known downside of specifically typed, highly optimisable
template-based code to create a dangerous leverage for generating spurious,
mostly identical virtual function instances added for secondary concerns.

Thus it is a consequence of this design choice, either to forego some diagnostic
and analytical possibilities, or to exploit ''other means'' for retrieving
internal data, which is needed for tangential purposes only. The solution
pursued hereby exploits similar layout of various ''weaving pattern''
template instances to create an ''access backdoor'' for use cases
beyond the primary performance-critical path.
2025-02-03 03:27:06 +01:00
ead494e465 Invocation: Argument-spec evaluation sufficiently complete for now
Some additional tests to challenge the parser, which seems to work well.
Without extended analysis into the usage of those node specifications,
it is pointless to expand further on its capabilities. For now, it is
sufficient to have a foundation for hash-computation in place.

__Note__: found a nifty way to give lib::Several an easy toString rendering,
without cranking up the header inclusion load.
2025-02-02 17:22:16 +01:00
f6a2a641df Invocation: tricky pipeline to unfold the repetition-abbreviation
This is a nice little goodie: allow to write repeated arguments with the
shorthand notation known from lisp and logic programming. For multi-channel media,
structurally similar wirings for each channel will be quite common....
2025-02-02 03:49:13 +01:00
5c2b6b69f6 Invocation: can now ''just parse'' the argument spec
can you imagine?
spell out that convoluted syntax, and it just works!!!
2025-02-01 02:21:34 +01:00
bd70c5faec Invocation: pick up work on the render node spec
...at the point where I identified the need to parse nested terms.
The goals are still the same
 * write tests to ''verify connectivity'' of nodes generated by the new `NodeBuilder`
 * allow for ''extended custom attributes'' in the ProcID
 * provide the ability to mark specific parametrisations
 * build a Hash-Key to identify a given processing step

__Note Library__: this is the first time `lib::Several` was used to hold a ''const object''.
Some small adjustments in type detection were necessary to make that work.
Access to stored data happens through the `lib::Several` front-end and thus always includes
the const modifier; so casting any const-ness out of the way in the low-level memory management
is not a concern...
2025-01-31 19:29:04 +01:00
0a0369a4a5 Library: complete test and documentaton of parsing support
This finishes an ''exercise'' in tool design,
which was set off by the requirement to parse the spec-ID of a render node.
While generally within the confines of a helper utility for simple use cases,
the solution became quite succinct and generic, as it allows to handle arbitrary
LL(n) grammars, possibly with recursion.
2025-01-29 23:51:13 +01:00
cdbdf620ca Library: explore how to build a nested-spec parser
...which is the reason for this whole excursion into parser business;
we want to accept specification terms with elements from C++ type expressions,
which especially requires to accept complete comma separated lists within
angle brackets or parenthesis, while separating by comma at top level.

The idea is to model ''not as an expression'' but rather as an ''extended quote'',
and to use inverted regular expressions for non-quote-characters as terminal
2025-01-29 00:16:19 +01:00
f8d0c1cf0b Library: demonstrate »the« textbook example
...evaluating the recursive syntax of a numerical expression!
 * so this light-weight parsing support framework indeed allows
   to build fully capable LL(x) parsers, when the user knows how
   handle syntax clauses and bind the result models
 * furthermore, a notation is demonstrated how to arrange the
   binding functions so to keep the syntax definition legible
 * this involves a shortcut for homogeneous alternatives
2025-01-28 20:23:28 +01:00
ed5c6f7c17 Library: implement support for recursive syntax
The concept was indeed successful, albeit quite difficult to pull off in detail.
It requires a carefully crafted path of Deduction guides and overloads
to effect the switch from std::function to std::function& at the point
where a predeclared syntax clause placeholder is used recursively
2025-01-26 23:54:38 +01:00
5e86aa3880 Library: lay out foundation for recursive clauses
In accordance to the plan drafted yesterday, I will try to integrate
this essential capability into the framework established thus far by a trick,
requiring only minimal adjustment, but some work by the user.

Since the parse function is defined as a (unqualified) template argument,
it is possible to emplace either a `std::function`, or a reference thereto.
For this to work, the user is required to pre-define the expected result type,
and, furthermore, must later on assign a fully specified clause, which
also has a model transformation binding attached to yield this predeclared
result type
2025-01-26 15:55:01 +01:00
70a5a7a06c Library: make bindMatch() more robust and enable structured bindings
...several improvements as result from the more elaborate test cases
 - spelling out the model types taken as argument can be challenging and tedious,
   thus improve the ability to pass a λ-generic.
 - furthermore, using structured bindings on a SeqModel can also simplifiy
   binding code; this did not work because the compiler picks the wrong strategy
   and attempts to bind the structure fields; need to provide explicit speicalisations
   to support the »tuple protocol« for SeqModel.

..considered several further helpers, (like auto-joining into a single string),
but in the end did not implement them, due to questionable relevance
2025-01-26 01:24:10 +01:00
b024b0baa6 Library: generic model transformer to get accepted string
The `bindMatch()` as implemented yesterday works only directly on top
of the terminal parsers, which yield a `RegExp`-Matcher. However,
it would be desirable to provide a generic shortcut to always get
some string as result model. A simple fallback is to return
the part of the input-string accepted thus far.
2025-01-25 17:00:51 +01:00
57dc56f5c6 Library: implement model-binding with generic-λ
Basically the implementation is already in place;
yet for better error messages we need to find out if the given functor
can handle the model present at this stage. Since generic-λ are not
functions by themselves (but rather templates), we need to ''probe''
with the expected argument and see if instantiation is possible.

⚠ NOTE: still a strange bug related to using the same Syntax several times
2025-01-25 03:40:41 +01:00
860e2fa226 Library: investigate how to approach recursion
Allowing free recursion in grammars is the key enabling feature,
which allows to accept arbitrary complex structures (like numeric expressions).
It is however also the element which makes the task of parsing a challenging endeavour;
after weighting the arguments, I decided ''not to place the focus on advanced usage,''
yet to open a pathway towards representation of such grammars.

Essentially, I consider it acceptable to require some additional work by the user,
if arbitrary recursive grammars are desired; because this design relies on explicitly
given parse functions, we need to introduce some kind of indirection interface,
to allow ''declaring'' a recursive rule first and later to ''supply the definition,''
which obviously then will involve other rules (or itself) recursively.

This leads to a very ''nifty approach'' towards recursion: we require the user
to provide an ''explicit model type'' beforehand, which implies that this is a
simple type, that can be spelled out (no λ) — and so the user is also
''forced to augment the actual rule with a model-binding,'' thereby reducing
the structured return types from the parse into something simple and uniform.
The user ''has to do the hard work,'' but can ''exploit additional knowledge''
related to the specific use case.

All this framework needs to do then is to supply a `std::function`, using the
explicit return type given; everything else will still work as implemented,
since a `std::function` can always stand-in for any arbitrary λ.
2025-01-25 02:48:11 +01:00
41ded40a3a Library: add support for bracketed expressions
This is the very key feature that requires a real parser and can not be handled by regular expressions.

After all the groundwork, it is surprisingly easy provide now;
only coding up all those DSL-variants is tedious. Notably we also
support accepting an ''optional'' bracket, and we support arbitrary
expressions for the ''opening'' and ''closing construct.''
2025-01-24 01:41:55 +01:00
089fafc1bd Library: change DSL scheme to handle optional and repeated better
It seemed that using postfix-decorating operators would be a good fit
for the DSL. Exploring this idea further showed however, that such a scheme
is indeed a good fit from the implementation side, but leads to rather confusing
and hard to grasp DSL statements for many non-trivial syntax definition.
The reason is: such a postfix-decorator will by default work on ''everything defined''
up to that point; this is too much in many cases.

The other alternative would be a function-style definition, which has the benefit
to take the sub-clause directly as argument (so the scope is always explicit).
The downside is that argument arrangement is a bit more tricky for the repetition
combinator (there can be mis-matches, since we take the »SPEC« as free-template argument)
And, moreover, with function-style, having more top-level entrance points would
be helpful. Overall, no fundamental roadblock, just more technicalities in the setup
of the DSL functions.

With that re-arrangd structure, an optional combinator could be easily integrated,
and a solution was provided to pick up the parser function from a sub-expression
defined as Syntax object.
2025-01-23 19:48:30 +01:00
5fed95b929 Library: integrate repeated clauses into the DSL
Meanwhile, some kind of style scheme has emerged for the DSL:
We're working much with postfix-decorating operators, which
augment or extend the ''whole syntax clauses defined thus far''

In accordance with this scheme, I decided also to treat repeated expression
as a postfix operator (other than initially planned). This means, the actual
body to be repeated is ''the syntax clause defined thus far'', and the
repeat()-operator only details the number of repetitions and an optional delimiter.
2025-01-22 22:31:25 +01:00
6dc2561262 Library: draft mechanics for repetitive sequence 2025-01-22 16:42:28 +01:00
1a3781bbc0 Library: implementation of syntax-branching
...is now easy and follows entirely the scheme established thus far
2025-01-22 02:21:39 +01:00
e3fe8fe380 Library: use as a foundation for the branch-combinator
After all the preparation, now this panes out quite well:
 * use a simple 3-way branch structure
 * the model type was already pre-selected by the `_Join` Model selector
 * can just pass the result-model elements to a constructor/builder
 * incremental extension can be directly mapped to the predecessor model
2025-01-22 01:11:05 +01:00
a8231150a5 Library: need remapping of variadic sequence
This is a rather obnoxious limitation of C++ variadics:
the inability to properly match against a mixed sequence with variadics.
The argument pack must always be the last element, which precludes to match
the last or even the penultimate element (which we need here).

After some tinkering, I found a way to recast this as ''rebinding to a remoulded sequence'',
and could package a multitude of related tools into a single helper-template,
which works without any further library dependencies.

🠲 extract into a separate header (`variadic-rebind.hpp`) for ease of use.
2025-01-01 22:02:08 +01:00
4f676f7213 Library: test and documentation for the new variant-helper
So this turned out to be much more challenging than expected,
due to the fact that, with this design, typing information is
only available at compile-time. The key trick was to use a
''double-dispatch'' based on a generic lambda. In the end,
this could be rounded out to be self-contained library helper,
which is even fully copyable and assignable and properly
invokes all payload constructors and destructors.

The flip side is that such a design is obviously very flexible
and direct regarding the parser model-bindings, and it should
be fairly well optimisable, since the structure is entirely
static and without any virtual dispatch.

Proper handling of payload lifecycle was verified using
a tracking test object with checksum.
2025-01-21 04:53:53 +01:00
d052edf91d Library: try out building a variant-model on top
* the implementation of this ''Sum Type'' got quite technical and complicated;
   thus better to be extracted as separate library component
 * use this as base for the `AltModel`
 * make a usage sketch, invoking only the model interactions required
2025-01-21 01:02:07 +01:00
8c046ee2ea Library: generalise into a fully copyable type
After exploring the »nested decorator-chain« implementation variant,
I decided to stick to the solution with the λ-vistor, while attempting
to level and smooth-out the design.
 * allow to engage ''any'' «slot» at construction
 * reverse the order of type parameters to be ascending (as in `std::tuple`)
 * make it fully copyable, movable, assignable and provide a `swap()`,
   relying on a variant of the "copy-and-swap"-idiom
 * add an ''cross-constructor'' for an extended branch set
2025-01-20 20:22:16 +01:00
3e743ff3b5 Library: explore design of a Sum-Type
To represent the result-model for syntax alternatives,
we need a C++ representation for a ''sum type,'' i.e.
a type that can be one from a fixed set of alternatives.
Obviously the implementation will rely on some kind of Union,
or otherwise employ an opaque buffer and perform a forced cast.
Moreover, to be actually usable, a branch-selector-ID must be
captured and stored alongside, so that code processing the results
can detect which branch of the syntax was chosen.

There seem to be several possible avenues to build and structure
an actual class template to provide this implementation model
 * a nested decorator-chain
 * using a recursive selector-function with a generic-λ

''all these look quite unattractive, unfortunately....''
2025-01-19 23:14:03 +01:00
cf91f167dd Library: suppress leading whitespace automatically
Seems like a pragmatic choice, which simplifies most syntax definitions significantly.
In exceptional cases, it is still possible to enforce a situation with `\b` or `\B`
2025-01-18 22:25:03 +01:00
fb78c10996 Library: add generic chaining
* need to pass the parse end-point in the Eval-Result to allow composed models
 * this also prepares for support of generic model-binding-λ

With the help of the model-joining case definitions it is then possible to handle sequence extension.
Deliberately I do not engage into fine grained signature checking, since this would lead to very technical code and moreover this is an implementation feature and we control all invocations (with signatures guaranteed to be correct)
2025-01-18 04:22:37 +01:00
7998c8d724 Library: need support for specification parsing
Unfortunately, there are some common syntactic structures, which can not easily be dissected by regular expressions alone, since they entail nested subexpressions. While it is possible to get beyond those fundamental limitations with some trickery, doing so remains precisely that, ''trickery.''

After fighting some inner conflicts, since ''I do know how to write a parser'' —
in the end I have brought myself to just do it.

And indeed, as you'd might expect, I have looked into existing library solutions,
and I would not like to have any one of them as part of the project.
 * I do not want a ''parser engine'' or ''parser generator''
 * I want the directness of recursive-descent, but combined with Regular Expressions as terminal
 * I want to see the structure of the used grammar at the definition site of the custom parser function
 * I want deep integration of ''model bindings'' into the parse process, i.e. binding-λ
 * I do not want to write model-dissecting or pattern-matching code after the parse
 * I do not want to expose ''Monads'' as an interface, since they tend to spread unhealthy structure to surrounding code
 * I do not want to leak technicalities of the parse mechanics into the using code
 * I do not want to impose hard to remember specific conventions onto the user

Thus I've set the following aims:
 * The usage should require only a single header include (ideally header-only)
 * The entrance point should be a small number of DSL-starter functions
 * The parser shall be implemented by recursive-descent, using the parser-combinator technique
 * But I want that wrapped into a DSL, to be able to control what is (not) provided or exposed.
 * I want a stateful, applicative logic, since parsing, by its very nature, is stateful!
 * I want complete compile-time typing, visible to the optimiser, without a virtual »Parser« interface

And last but not least, ''I do not want to create a ticket, since I do not know if those goals can be achieved...''
2025-01-17 18:40:44 +01:00
55ad44590c Invocation: cover dissecting of ProcID spec
..with some slight changes
 * also recognise domain prefix
 * omit domain prefix in proc-name
2025-01-11 22:17:07 +01:00
6207f475eb Invocation: define aspects of ProcID to cover
Building a correct processing-identification is a complex and challenging task; only some aspects can be targeted and implemented right now, as part of the »Playback Vertical Slice«
 * components of the ProcID
 * parsing the argument-spec
 * dispatch of detail information function to retrieve source ports
2025-01-11 17:05:53 +01:00
abeca98233 Invocation: Analysis regarding dispatch of information functions for Nodes
The choice to rely on strictly typed functor bindings for the Node operation
bears the danger to produce ''template bloat'' — it would be dangerous to add
further functions to the Port-API naïvely; espeically simple information functions
will likely not depend on the full type information.

A remedy to explore would be to exploit properties marked into the Port's `ProcID`
as key for a dispatcher hashtable; assuming that the `NodeBuilder` will be responsible
for registering the corresponding implementation functions, such a solution could even
be somewhat type-safe, as long as the semantics of the ProcID are maintained correctly.
2025-01-11 00:20:36 +01:00
1aae4fdcdd Invocation: build complex Node tree ... ideas for verification
* this changeset builds a complex processing network for the first time
 * furthermore, some ideas towards verification are spelled out

''verification not implemented''
2025-01-08 17:39:38 +01:00
890cba49a2 Invocation: now able to return to integration testing effort
...which aims at building up increasingly more complex Node Graphs,
to validate that all clauses are defined and connected properly.

Reconsidering the testing plan: initially especially this test was aimed
primarily at driving me through the construction of the Node builder and
connection scheme. Surprisingly enough, already the first test case basically
forced the complete construction, by setting me on tangential routes,
notably the **parameter handling**.

Now I'm returning to this test plan with an already finished construction,
and thus it can be straightened just to give enough coverage to validate
the correctness of this construction...
2025-01-07 01:11:05 +01:00
e47f1db8c5 Invocation: reorg namespace for TestRandOntology
The namespace `steam::engine::test::ont` will hold some typical definitions
for the fake „media processing library“ — to be used for validating aspects of mapping and binding.
2025-01-06 22:02:09 +01:00
bbed729d94 Invocation: successfully invoke random-frame generation as Node
This picks up the efforts towards a »Test Ontology« from end November:
d80966c1f

The `TestRandOntology` is intended as a playground to gradually find out
how to maintain bindings processing functionality provided by a specific Library
and thus related to a ''Domain Ontology''

Remark: generating symbolic specs might seem like a mere test exercise, yet is in fact
quite crucial, since the node-identity is based on such a spec, which must be ''semantically correct,''
otherwise caching and especially cache invalidation will be broken.
Yesss .... in Lumiera naming and cache invalidation are linked directly ;-)
2025-01-06 19:47:51 +01:00
e444ad67c2 Invocation: complete demonstration of Node tree with Param Agent (closes #1386)
This is a high-level integration test to sum up this development effort
 * an advanced refactoring was carried out to introduce a
   flexible and fully-typed binding for the ''processing-functor''
 * this entailed a complete rework of the `FeedManifold` to integrate
   inline storage for a ''parameter tuple'' and input / output ''buffer tuples''
 * optional ''parameter functors'' were included into the design at a deep level,
   closely related to the binding of the processing-functor
 * the chosen design is thus a compromise between ''everything nodes''
   and a ''dedicated parameter-handling'' at invocation level

As a proof-of-concept, an scheme to handle extended parameters was devised,
using a special »Param Agent Node« and extension storage blocks in stack memory.
While not immediately necessary, this design exercise proves the overall design
is flexible enough to accommodate future extended needs.
2025-01-05 21:20:59 +01:00
fb2f0b0e2d Invocation: build and invoke a chain of Render Nodes
This is a first!
Now we can really invoke a tree of Nodes, as demonstrated with this simple test.
2025-01-05 05:58:36 +01:00
061d20e08d Invocation: implement support for simple time-based automation
Actually this is now quite easy to implement, as a shortcut on top of generic functionality;
just in this case the param-functor takes a Time value as argument.
So its more a matter of documentation to provide a dedicated hook for this common case.
2025-01-05 04:01:39 +01:00
32c21b6a8f Invocation: documentation for the ''Param Agent'' scheme 2025-01-05 02:57:07 +01:00
16a6a0d630 Invocation: integration test to use the Param Agent Node Builder
incidentally, this is also the first test case ever to involve linked nodes,
so it revealed several bugs in the related code, which was not yet tested.

This is a ''move-builder'' and thus represents a tricky and sometimes dangerous setup,
while allowing to switch the type context in the middle of the build process.
It is essential to return a RValue-Reference from all builder calls which
stay on the same builder context.

After fixing those minor (and potentially dangerous) aspects regarding move-references,
the code built yesterday worked as expected!
2025-01-04 19:28:58 +01:00
79f365df67 Invocation: connect remaining operations for the ParamAgentBuilder
This is some quite technical and redundant code, which largely maps
the configured elements from the Builder-DSL level down into the delegate
builder functors. For the ''Param Agent Node,'' most of the structure
is already embedded deep into the `ParamWeavingPattern`, by virtue of a
tuple of parameter-functors, which are supplied to the builder-API
as a `ParamBuildSpec` (which in fact is in itself a builder and will be
used on a higher level to fill in suitable parameter-functors)

This changeset is assumed to complete the definition of a builder and
weaving pattern for a ''Param Agent Scheme'' — yet only the tests to be
elaborated next will show the extent to which this is true....
2025-01-04 05:57:00 +01:00
e131320a81 Invocation: draft implementation of the weaving-pattern for parameters
Still having some doubts if using a ''weaving-pattern'' is the right approach here,
but if we do, then the steps would be mapped as drafted here. This includes
passing additional parameters, notably the `TurnoutSystem&` to every step.
2025-01-02 22:40:46 +01:00
2468f6d0ee Invocation: reshape scheme for data-access for Param-Weaving-Pattern
As it turns out, we need to embed the Param-Functor tuple,
but only for a single use from a »builder« component.

On the other hand, the nested »Slot« classes are deemed dangerous,
since they just seem to invite being bound into some functor, which
would create a dangling reference once the `ParamBuildSpec` is gone.

Thus it's better to do away with this reference and make those accessors
basically static, because this way they ''can'' be embedded into param-access
functors (and I'd expect precisely that to happen in real use)
2025-01-02 03:08:34 +01:00
93bb64d6a2 Invocation: storage layout for Param-Weaving-Pattern
...intended to be used as a Turnout for a ''Param Agent Node....''
This leads to several problems, since the ''chain-data-block'' was defined to be non-copyable,
which as such is a good idea, since it will be accessed by a force-cast through the TurnoutSystem.

So the question is how to group and arrange the various steps into the general scheme of a Weaving-Pattern...
2025-01-01 03:27:58 +01:00
fe75bed227 Invocation: demonstrate complete usage cycle of extension block
In `NodeFeed_test`...
Demonstrate the base mechanism of creating a ''Param Spec'' with a
functor-definition for each parameter. This can then later be used to
invoke those functors and materialise the results into a data tuple,
and this data tuple can be linked into the TurnoutSystem, so that
the parameter values can be accessed type-safe with getter-functors.
2024-12-30 01:56:18 +01:00
107d03f6ef Invocation: invoke the param-functors and build extension block
Relying basically on the trick to invoke std::apply with a generic variadic Lambda
onto the tuple of functors; within the lambda we can use variadic expansion
to pass the results directly into the builder and so construct the param-tuple in-place.


Oh well.
2024 is almost gone by now.
Had to endure yet another performance of Beethoven's 9th symphony...
2024-12-29 23:55:19 +01:00
ee59162418 Invocation: define accessor-functor to work on extension block
This is rather the easy part, building upon the foundation developed with `HeteroData`:
 * the `TurnoutSystem` will now accept a `HeteroData`-Accessor
 * the `ParamBuldSpec` can thus construct an Accessor-Type for each »slot«

...the more tricky part will be how actually to build, populate and attach
such an extension data slot, placed into the local stack frame...
2024-12-29 18:27:05 +01:00
f990f97c41 Invocation: groundwork for a Parameter-Build-Spec
...which in turn would then allow
 * to refer to extended parameters within scope
 * to build a Param(Agent)Node, which builds a parameter tuple
   by invoking the given parameter-functors

Can now demonstrate in the test
 * define several »slots«, each with either value or functor
 * apply these functors to a `TurnoutSystem`
2024-12-29 03:26:39 +01:00
3406b6abf5 Invocation: anchor data frame in TurnoutSystem
So this is a design sketch how a `ParamBuildSpec` descriptor could be created,
which in turn would provide the foundation to implement a ''Parameter Weaving Pattern...''

__Note__: since this is an extension for advanced usage, yet relies on a storage layout
defined to allow for extensions like this use case here, the anchor type is now defined
to reside in the `TurnoutSystem` in the form of a ''standard parameter block''.
Those standard invocation parameters are fixed and thus can be hard coded.
2024-12-29 01:17:06 +01:00
7d8c0c5753 Invocation: plan for extended parameter computations
Based on ''theoretical reasoning,'' I draw the conclusion that some advanced usages
of processing parameters can not be satisfied by the simple direct integration of a
parameter-functor...

Thus the concept for an extension point, which relies on a dedicated ''Param (Agent) Node''
and a specifically tailored ''Param Weaving Pattern'' to evaluate several parameter functors
and place the results into an extension data block in the invocation stack frame.
2024-12-28 21:48:31 +01:00
c4b2902dd4 Invocation: provide simplified API to inject fixed parameter values
* ...by defining a parameter-functor to »drop off« a given value
 * ...also add a static sanity check to reject unsuitable parameter-functor \\
   (e.g. for a processing-functor with different or even no parameters)
2024-12-28 21:48:30 +01:00
52d2c47439 Invocation: integrate passing a parameter-functor into the NodeBuilder
This required some ''type massaging'' to construct the proper follow-up builder type;
other than that, all components work together as expected.

This can be demonstrated both in a direct setup and using the builder.
2024-12-26 21:42:32 +01:00
b46e21e24d Invocation: investigate ways to introduce a parameter-functor
While the handling of invocation parameters is now integrated in the node processing,
there is still a gap to close in the Node Builder, which is tricky due to the way
the parameter-functor is now integrated deeply into the setup of the `FeedManifold`;
so the `PortBuilder` is tasked now with implanting a `FeedPrototype` -- which must be
adapted to a ''specific parameter-functor,'' which is only supplied optionally,
as a further build step.

At first this seemed to present a pattern very similar to a ''State Monad'' — and thus
I investigated if encapsulating the build of the prototype into such a State Monad would
simplify the structure of the builder — yet once again, Monads turned out as ''Anti Pattern''
rather: we'd had to ad an extra component, which is superficially generic
but without any tangible relation to patterns of the real world, it would be
rather technical (using lots of composed lambda primitives, which will be condensed
into a single builder function by the compiler / optimiser. But worse still,
this highly complicated setup does not actually solve the problem with N x M
typed contexts — implying that it ''is not actually an abstraction,'' rather just
pretends to be generic.

The benefit of this lengthy design exercise is to understand better the situation
in the builder, which amounts to building up mixed typed context with several
degrees of freedom. It is better to accept this reality and keep it in  plain sight,
i.e. let the builder be explicitly typed from end to end and do not try
to package parts of this selection process behind a virtualisation.
2024-12-26 18:03:08 +01:00
9f348e6944 Invocation: able to build and invoke a simple Render Node (see: #1367)
**This is a Milestone for the Render Engine integration effort**

After various rounds of prototyping and refactoring,
the Render Node builder and invocation code is now able to
 * bind a simple function
 * handle arbitrary input / output and parameter types
 * invoke a Render Node configured with this function
2024-12-24 06:23:55 +01:00
9484ea0b71 Invocation: identify problems with buffer handling
The ''design exercise'' started yesterday ran into a total rodadblock.
And this is a good thing, as this unveils inconsistencies in our memory handling protocols
 * Buffer Provider Protocol
 * Output Slot Protocol
The latter exposes a `BuffHandle`, which should be usable from within the Render Node code
like any other regular buffer handle — which especially would require to ''delegate the lifecycle calls...''

So while this topic does not hinder us right now to proceed with a Node invocation in test setup,
it must be addressed before we're able to deliver data into an actual OutputSlot.

Created #1387 to track this topic...
2024-12-24 03:21:22 +01:00
33c8f1c5b1 Invocation: investigate forwarding an output data block
This investigation started out as solving an already solved problem...
I'll continue this as a design exercise non the less.

__Some explanation__: To achieve the goal of invoking a Node end-to-end,
the gap between the `Port` API, the `ProcNode` API and the `RenderInvocation` must be closed.
This leads to questions of API design: ''what core operation should the `ProcNode` API expose?''
 * is `ProcNode` just a forwarding / delegating container and becoming redundant?
 * or does the API rather move in the direction of an ''Exit Node''?

This leads to the question how the opened `OutputSlot` can be exposed as a `BuffHandle`
to allow to set off the recursive Node invocation. As it turns out, the onerous for this step
lies on the actual `OutputSlot` implementation, since the API and output protocol already requires
to expose a `BuffHandle`. Yet there is no "real" implementation available, just a Mock setup based
on `DiagnosticBufferProvider`, which obviously can just be passed-through.

Which leaves me with mixed feelings. For one it is conveninent to skip this topic for now,
but on the other hand the design of `BufferProvider` does not seem well suited for such an proxying task.
Thus I decided to explore this aspect in the form of a prototyping test....
2024-12-23 02:31:29 +01:00
2068278616 Invocation: resume integration of Node building
After this extended excursion to lift the internals of Node invocation
to the use of structured and typed data (notably the invocation parameters),
the »Playback Vertical Slice« continues to push ahead towards the goal of integration.

The existing code has been re-oriented and some aspects of node invocation have been reworked
in a prototyping effort, which (in part though the aforementioned rework)
is meanwhile on a good path to lead to a consolidated final version.
 * ✔ building a simple Render Node works now with the revamped code
 * 🔁invoking this simple Node ''should be just one step away'' (since all parts are known to work)
 *  the next step would then be to build a Node outfitted with a ''Parameter Functor'', which is the new concept introduced by recent changes
 *  this should then get us at the point to take the hurdle of invoking one of our **Random Test** functions as a Render Node
2024-12-22 19:47:36 +01:00
81ef3c62e9 Invocation: code clean-up and documentation
Remove left-overs from the preceding prototypical implementation,
which is now obliterated by the change to a flexibly configured `FeedManifold`
with structured, typed storage for buffers and for parameter data.

The Render Node invocation sequence, as rearranged and reworked for the »Playback Vertical Slice«, now seems reasonably clear and settled.

Adding extensive documentation to describe the conventions and structures worked out thus far;
moreover, start makeover of old documentation in the !TiddlyWiki to remove concepts obviously obsoleted now...
2024-12-22 07:00:02 +01:00
e46ff7a8a7 Invocation: switch WeavingPattern and Level-1 builder to the reworked FeedManifold
After the complete makeover of the `FeedManifold` structure,
which among other entails a switch from ''buffer arrays'' to tuples
and the ''introduction of a parameter tuple'', this changeset now
switches the „downstream code“ of the builder and node invocation,
relying on an largely identical invocation API.

The partially finished NodeLink_test now **runs as before**
but on top of a drastically more flexible and open infrastructure.

Quite a feat.
2024-12-21 06:24:37 +01:00
0ccc2d0b89 Invocation: complete rework of the FeedManifold
This completes a deep and very challenging series of refactorings
with the goal to introduce support for **Parameters** into the Render invocation code.

A secondary goal was to re-assess the prototype code written thus far
and thereby to establish a standard processing scheme.

With these rearrangements, the `FeedManifold` is poised to act as **central link**
between the Render-Node invocation code and the actual Media-Processing code in a Library Plug-in


Up to this point, the existing code from the Prototype is still compilable, yet broken.
The __next step__ will be to harness the possible simplifications and enable
the actual invocation to work on arbitrary combinations of buffers and parameters,
enabled by the **compile-time use-case classification** now provided by `FeedManifold`
2024-12-20 22:18:04 +01:00
72703f70c9 Invocation: integrate active ''parameter functor''
While basically the `FeedPrototype` could be created directly,
passing both the processing- and the parameter-functor, in practice
a two-step configuration can be expected, since the processing-functor
is built by the Library-Plug-in, while the parameter-functor is then
later added as decoration by the builder.

Thus we need the ability to ''collect configuration'' within the Level-2 builder,
which can be achieved by a ''cross-builder'' mechanic, where we create an adapted builder
from the augmented configuration. A similar approach is also used to add
the configuration of the custom allocator.

Added an extensive demo in the test, playing with several instances
to highlight the point where the parameter-functor is actually invoked.
2024-12-20 07:05:43 +01:00
8923d0f7b5 Invocation: handle default case with disabled ''parameter functor''
Some further tweaks to the logic to allow using the `FeedPrototype` in the default setup,
where ''nothing shall be done with parameters...''

Provide the basic constructors and a type constructor in FeedManifold,
so that it is possible to install a ''processing functor'' into the prototype
and then drop off a copy into each new `FeedManifold`

With this additions, can now **demonstrate simple usage**

__Remark__: using the `DiagnosticBufferProvider` developed several years ago;
Seems to work well; however, when creating a new instance in the next test case,
we get a hard failure when the previous test case did not discard all buffers.
Not sure what to think about that
 * for one, it is good to get an alarm, since actually there should not be any leak
 * but on the other hand, `reset()` does imply IMHO „I want a clean slate“
Adding some code thus to clean out memory blocks marked as used.
When a test wants to check that all memory was released, there are tools to do so.
2024-12-20 01:47:40 +01:00
479ab8cb15 Invocation: decision logic for invoking a ''parameter functor''
Based on the usage concept developed thus far, we rely on a `FeedPrototype`
to generate the actual `FeedManifold` for each invocation — and this is the extension point
where a ''parameter functor'' can be attached.

Notably, such a parameter functor will be configured from a different part of the builder logic
than the underlying processing function, which is adapted by a Library Plug-in.
Parameters on the other hand will be controlled mostly by configuration within the
Session, because the user chooses to use specific settings, e.g. for an effect.
An important extension to this scheme is **Parameter Automation** — which will be
also attached over the extension point designed here.

Since Parameter can be defined in various flavours, there is some concern that we'll end up
with an excessive number of template instantiations. Thus, we'll explicitly create a »loop hole«
by allowing to define the ''parameter functor'' to be a `std::function`.
This would open a secondary possibility: configuring such a function, but leaving it empty,
which would be a further control switch usable by the builder.
2024-12-19 22:35:12 +01:00
07410e14f1 Invocation: now able to pass parameter tuples
This basically completes the reworked implementation of the `FeedManifold`
An important aspect however is now separated out and still remains to be solved:
''how to configure and invoke a Parameter-Functor?''
2024-12-19 19:58:21 +01:00