...all of this implementation boils down to slightly adjusting
the code written for the test-mutation-target. Insofar it pays off now
having implemented this diagnostic and demonstration first.
Moreover I'm implementing this basic scheme of "diff application"
roughly the fourth time, thus things kindof fall into place now.
What's really hard is all those layers of abstraction in between.
Lesson learned (after being off for three weeks, due to LAC and
other obligations): I really need to document the meaning of the
closures, and I need to document the "abstract operational semantics"
of diff application, otherwise no one will be able to provide
the correct closures.
while I still keep my stance not to allow reflection and
switch-on-type, access to the internal / semantic type of
an embedded record seems a valid compromise to allow
to deal with collections of object-like children
of mixed kind.
Indirectly (and quite intentional) this also opens a loophole
to detect if a given GenNode might constitute a nested scope,
but with the for the actual nested element indeed to cary
a type symbol. Effectively this limits the use of this shortcut
to situations where the handling context does have some pre-established
knowledge about what types *might* be expected. This is precisely
the kind of constraint I intend to uphold: I do not want the
false notion of "total flexibility", as is conveyed by introspection.
...and write down some insights about the architecure
and design of tree binding and tree description related
to the TreeMutator.
When reading my notes from last year, it became clear
to me that the design of the TreeMutator has evolved
significantly, and became quite something different
than I'd imagined at start
after sleeping one night over the problem, this seems to be
the most natural solution, since the possibility of assignment
naturally arises from the fact that, for tree diff, we have
to distinguish between the *identity* of an element node and
its payload (which could be recursive). Thus, IFF the payoad
is an assignable value, why not allow to assign it. Doing so
elegnatly solves the problem with assignment of attributes
Signed-off-by: Ichthyostega <prg@ichthyostega.de>
This basically finishes definition of the fundamental
UI-Element and Bus protocol -- with one notable exception:
how to mutate elements by diff.
This will be the next topic to address
not sure yet if any of this works, because the
technicalities of dealing with variadic types are
quite different to our LISP-style typelist processing.
The good news is that with variadic templates it is
indeed possible, to supply dynamically picked arguments
to another function taking arbitrary arguments.
This all relies on the feature to unpack argument packs,
and, more specifically, about the possiblity to "wrap"
this unpacking around interspersed function call syntax
template<size_t...i>
Xyz
do_something(MyTuple myTuple)
{
return Xyz (std::get<i> (myTuple) ... );
}
Here the '...' will be applied to the i... and then
the whole std::get-construct will be wrapped around
each element. Mind bogging, but very powerful
next step will be to rig the mock element and set up
and cover the basic / generic element behaviour
This changeset
- adapts the (planned) unit test to the semantic of
the EventLog, which is now fully implemented
- adjusts the function names on the public Tangible interface,
to be better in line with the naming convention of the
corrsponding operations on the UI-Bus:
* "mark" operations are towards the UI element
* "note" messages are from the UI element towards some
state manager, which can be reached via the bus
what you see here now is just the tip of the icebearg...
If we follow this route, the Lumiera UI will become way more
elaborate and responsive than average desktop applications
initially my intention was to use the ID for equality test.
But on a second thought, this seemed like a bad idea, since
it confuses the concepts of equality and identity.
Note: at the moment, I do not know if we even need an equality test,
so it is provided here rather for sake of completeness. And this
means even more that we want an 'equality' implementation that
does what one would naively expect: compare the object identity
*and* compare the contents.
especially I've now decided how to handle const-ness:
We're open to all forms of const-ness, the actual usage decides.
const GenNode will only expose a const& to the data values
still TODO is the object builder notation for diff::Record
for the purpose of working out the inner logic, I frequently use the
help of a mindmap -- so why not commiting this alongside? For sure,
it is preliminary and the worked out concepts will be cast in code
and documented on the website. Yet the thought-process leading to
these decisions might be of some interest, at least for myself.
before engaging into the implementation of lib::Record,
I prefer to conduct a round of planning, to get a clearer
view about the requirements we'll meet when extending
our existing list diff to tree structures
Introduce the new term "Fork" at various relevant places
within the documentation. We do not entirely purge the
term "track" though; rather we
- make clear that "Fork" is the entity to build tracks
- use "fork" also synonymous to the "tree of tracks"
to carry out that rather obvious step, I was bound to consider
all the implications of choosing a given layout and handling pattern
for our external structure representation.
Finally, I settled upon the following decisions
- the value space represented within the DataCap is flat, not further structured
- the distinction between "attribute" and "nested object" is merely conceptual
and will be enforced solely by the diff detection / representation protocol
- basically, a nested subtree may appear as an attribute; the difference
between attributes and children lies solely in the way of access and referral:
by-name vs. positional
- it is pointless to save space for the representation of the discriminator ID
- but we can omit any further explicit type tag, because
- we do *not* support programming by switch-on-type, and thus
- we do *not* support full introspection, only a passive type-safety check
- this is *not* a limitation, since we acknowledge that GenNode is a *Monad*
- and the partial function needed within any flatMap implementation
maps naturally onto our Variant-Visitor; thus
- the DataCap can basically just *be* a Variant
- and GenNode has just to supply the neccessary shaffolding
to turn that into a full fledged Monad implementation, including
direct construction by wrapping a value and flatMap with tree walk
so yes, it is complicated, and inevitably involves three layers
of indirection. The alternative seems to bind the GUI direcly to
the Session interface -- is there a middle gound?
For the messages from GUI to Proc, we have our commands, based
on PlacementRef entities. But for feeding model updates to the
GUI, whatever I consider, I end up either with diff messages or
an synchronised access to Session attributes, which ties the
responsiveness of the GUI to the Builder operation.
- we use a GenNode element
- this holds a polymorphic value known as DataCap
- besides simple attribute values, this may hold collections of GenNode sub elements
- a special kind of GenNode collection, the Record, is used to represent objects
The purpose of this setup is to enable an external model representation
which is only loosely coupled to the interndal data representation
through the exchange of (tree)diff messages
previously this operation was named 'attach', which an be confused
with attching an object to this location. Indeed, the session interface
even offers such an attach function. By renaming the focus moving
operation into QueryFocus::shift(Scope), this ambiguity is resolved
This is the first step towards a generic backbone to connect
any GUI elements to the session within Proc-Layer.
It is based on a spefic understanding of Model-View-Controller,
which turns the Model-Controller interactions into messages.
Remove some orphaned diagrams and PNG images not actually used
in the TiddlyWiki. Add a page with some hints regarding Bouml
See also #960 -- Bouml has been discontinued and is closed source now
not sure how to proceed with this
This means to discontinue any research into emitting an optimal
diff verb sequence for now and just to document the possible path
I see to reach at such a optimal solution later, when it turns out
to be really necessary performance wise.
Personal note: I arrived at this conclusion while whatching the
New Year fireworks 2014/2015 at the banks of the Isar river in
the centre of the city.
Too sad that 2014 didn't bring us World War III
we want a simple and straight forward way of defining tokens
of the "diff language". Each token is bound to a specific
handler function in the language interpreter interface.
Problem is that likely we'll get a ListDiffLanguage and a TreeDiffLanguage;
after all, I really don't know yet how far to take this whole
diff representation endeavour...
...first step is to design a generic linearised list diff representation.
Basically just need to pull together the theoretical work of the last weeks.
Next steps will be to extend to typed ordered trees.
Actually I arried at the conclusion, that the *receiving* of
a diff representation is actually a typical double-dispatch situation.
This leads to the attempt to come up with a specialised visitor
as standard pattern to handle and apply a diff. Obviously,
we do not want the classical GoF-Visitor, but (yes, we had
that discussion allready) -- well in terms of runtime cost,
we have to deal with at least two indirections anyway;
so now I'm exploring the idea to implement one of these
indirections through a functor object, which at the same time
acts as "Tag" in the diff representation language (instead
of using an enum as tag)
This DSL is usable as wire format for sending
structural change data to another, loosely coupled entity.
A similar format could be used for model serialisation later on.
initial considerations; there is a concurrency problem, since
all of session handling within Proc is deliberately not threadsafe.
Thus the decision is to make this the gui::model::SessionFacade's responsibility
Actually this is nothing new, just making explicit what is evident
from the definition of the Proc-Layer model entities. By following
these conventions, it should be possible to come up with a
clearer structure for the custom timeline widget(s).
Notably TiddlyWiki provides now a fallback mechanism
in case the saving to a local file fails due to security
restrictions. When this happens, TiddlyWiki generates a
download link pointing to the current content; this way
one is at least able to "save as" through the browser
context menu.
Due to some controversial policy changes in recent Firefox versions
the support for saving to local files was removed. The rationale
given by the Firefox developers was that this is a rarely used
and generally outdated concept; preferrably people shall use
extensions and save to cloud services (!)
Anyway, Jeremy Ruston, the original author of TiddlyWiki, wrote
a Firefox plugin called "TiddlyFox" to work around these
arcane limitations.
this draft fills in the structure how to get from an invocation
of the engine service to the starting of actual CalcStream instances.
Basically the EngineService implementation is repsonsile to
instruct the Segmentation to provide a suitable Dispatcher.
we were using an very ancient TiddlyWiki version, basically
unaltered since the start of the Lumiera project.
Recent Firefox versions (starting with FF-17) effectively
removed the ability for JavaScript code to get additional
privileges for writing local files; this change seriuosly
undermines the usability of TiddlyWiki and a lot of similar
portable local JavaScript applications.
The original author of TiddlyWiki, Jeremy Ruston, has written
a Firefox plug-in to work around this restriction; this prompts
us to upgrade to a recent TiddlyWiki version as well.
The good news is: recent TiddlyWiki versions are able to import
Tiddlers from older Wikis without much hassle.
brainstorming how to implement the job planning stage
the idea is to built on top of the IterExplorer,
but have the "stack" of re-evaluation integrated
into a custom type, which exploits the static
node network structure to avoid heap allocations
solution idea: again use a builder function?
this draft is based on
- Cehteh's draft for the scheduler
- my plannings about segmentation and JobTicket
it defines "Job" as a closure which can be invoked
from plain-C, using the information in the
job descriptor datastructure
also touches the question how to represent the job
descriptor datastructure. @Cehteh: I've just pasted
in your preliminary data struct definitinons
from the relevant mailing list discussions.
These pages from the TiddlyWiky feature a complete glossary
of terms relevant for time and timecode handling, plus the
architecural decisions related to this topic
removed that inheritance relation; it was a typical
example of abusing inheritance and violated the
Liscov substitution principle. It is sufficient
to allow promotion of an offset into a Duration.
Note: Duration is the time metric