diff --git a/src/lib/time/mutation.hpp b/src/lib/time/mutation.hpp index 0d5810b5a..81b57c454 100644 --- a/src/lib/time/mutation.hpp +++ b/src/lib/time/mutation.hpp @@ -47,8 +47,8 @@ ** the message into the target object's own time grid. ** ** @note this header is defined such as to be used with or without including the time quantisation - ** facility, which is a more heavyweight regarding code size and compilation times. For this - ** toggle to work, the header \c timequant.hpp needs to be included \em prior to \c mutation.hpp + ** facility, which is a more heavyweight inclusion regarding code size and compilation times. For + ** this toggle to work, the header `timequant.hpp` needs to be included \em prior to `mutation.hpp` ** Obviously, you can't define any mutation involving quantised (grid aligned) values without this. ** @warning when defining more fancy kinds of concrete mutations using the technique with ** the EncapsulatedMutation to hide the implementation, then please be sure to understand diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 022e8e6e3..68a47fc70 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -8340,7 +8340,7 @@ attached to a clip, or the mixture of clips, effects and labels found within a [ You should note that this entire design is recursive: only after understanding the part, where, for handling a sub-structure, a nested mutator is fabricated and placed into a given buffer, it becomes clear to what effect we're creating a customised mutator: we always need some (relative) parent scope, which happens to know more about the actual data to be treated with a TreeMutator. This scope assists with creating a suitable binding. Obviously, from within that binding, it is known what the sub-structures and children of that local data are all about and what semantics to give to the fundamental operations. -
The TreeMutator is an intermediary to translate a generic structure pattern into heterogeneous local invocation sequences.
!Motivation
@@ -8456,6 +8456,34 @@ Since our goal is to represent changes to structured objects in the form of a di
* attributes may be reordered
* attributes may be added and deleted
-- none of which has any tangible meaning for a regular (language) object. To the contrary, our ExternalTreeDescription was built specifically to support diff language and diff messages, and thus has the ability to represent those changes. So, in theory, a given diff, when applied both to a GenNode and via TreeMutator to a native data structure, might lead to states not semantically equivalent. We can not reliably protect ourselves against that possibility, but, on the other hand, it is not clear if such is an actual threat.
+
+''A possible path to reconcile'' these inner contradictions is to support the mutation primitives ''as far as is sensible''.
+Through analysis of the semantics, we could distinguish several flavours of "attributes", especially...
+;object fields
+:mandatory elements enforced by class definition, where values need to be supplied at construction time
+;defaultable object fields
+:regular object fields proper, where some construction logic is able to fill in defaults. After construction, they are indistinguishable from mandatory object fields
+;optional properties
+:elements rooted in the class definition, yet not necessarily given. The object is able to //detect their absence//, and may fill in a default or ignore missing properties
+;attribute map
+:an ordered collection of key-value associations, which can be enumerated, searched and extended
+Thus we //could define a sensible handling for each of those cases, and deal with combinations// -- but --
+it seems more adequate to limit ourselves just to object fields and to include the defaultable object fields through implementation leeway. Because, in the end we really do need object fields, and anything beyond is just a representation of special behaviour and can be kept out of the diff system altogether. Through diff messages, we want to express structured changes, not metadata, nor closures, nor strategies, nor prototypes. And the attribute map is really something different than an object, and should be implemented separately, when it comes to applying diff messages to GenNode elements; the latter are able to //emulate// or //represent// objects, but actually are rather key-value associations arranged in and nested scopes.
+
+!!!mapping rules to handle object fields
+So we basically ''disallow'' anything related to ''order'', ''re-ordering'' and ''deletion'' of object fields.
+* when an object requires field values at construction time, this requirement has to be satisfied when inserting the object. The {{{ins}}} message must hold a complete value description in this case
+* beyond that, fields can //only// be either assigned, or opened for nested mutation.
+* for sake of consistency with the handling of a GenNode based [[ETD|ExternalTreeDescription]], we translate an {{{ins}}} message into an auto-accept followed by an assignment. In fact, any //defaultable object field,// when specified for the first time, //should// be given as {{{ins}}} message, because otherwise we would not be able to apply the same diff sequence to an equivalent GenNode representation of the same logical structure.
+Consequently, we're left with only a very limited subset of diff expression applicable to an »object field onion layer«
+* either a {{{pick}}} for every known field, possibly (optionally) followed by a {{{set}}} message with a new value
+* or an {{{after END}}}, followed (optionally) by an arbitrary sequence of {{{set}}} messages.
+To create a ''binding'' for any object field, we need
+* a ''name'' for matching keys
+* either a ''setter'' (lambda) or a ''mutator builder'' (lambda)
+We have a distinct typing for each individual attribute, but this typing remains implicit: the lambda has to know what value to extract from the GenNode payload within the accepted diff message
+
+