Commit graph

25 commits

Author SHA1 Message Date
75aa5c970e summarise my thoughts regarding the 'External Tree Description'
seems like a new concept, closely related to the 'systematic metadata' RfC
2015-05-26 16:17:00 +02:00
f9d0d13501 ability to pick up the attribute type from the closure/functor
The actual trick to make it work is to use decltype on the function operator
http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765

In addition, we now pick up the functor by template type and
store it under that very type. For one, this cuts the size
of the generated class by a factor of two. And it gives the
compiler the ability to inline a closure as much as is possible,
especially when the created Binder / Mutator lives in the same
reference frame the closure taps into.
2015-05-03 05:24:06 +02:00
f45884975b generalise to arbitrary acceptable attribute values
...not yet able to pick up the closure argument type automagically
however, right now we can only hypothesise this might be possible
2015-05-02 02:02:48 +02:00
2ce85a1449 use the attributeID to activate the right closure
...under the assumption that the number of attributes is small,
using just a chained sequence of inlined if-statements
"would be acceptable"
2015-05-02 01:39:58 +02:00
6de24bc7f0 Ticket #956: decide layout and handling of GenNode elements
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
2015-05-02 01:11:39 +02:00
51cdc85e58 back from LAC2015: re-read and simplify the code draft 2015-04-13 15:49:38 +02:00
2e1df16bdc settle on a concrete implementation approach based on inheritance chain
After some reconsideration, I decide to stick to the approach with the closures,
but to use a metaprotramming technique to build an inheritance chain.
While I can not decide on the real world impact of storing all those closures,
in theory this approach should enable the compiler to remove all of the
storage overhead. Since, when storing the result into an auto variable
right within scope (as demonstrated in the test), the compiler
sees the concrete type and might be able to boil down the actual
generated virtual function implementations, thereby inlining the
given closures.

Whereas, on the other hand, if we'd go the obvious conventional route
and place the closures into a Map allocated on the stack, I wouldn't
expect the compiler to do data flow analysis to prove this allocation
is not necessary and inline it away.


NOTE: there is now guarantee this inlining trick will ever work.
And, moreover, we don't know anything regarding the runtime effect.
The whole picture is way more involved as it might seem at first sight.
Even if we go the completely conventional route and require every
participating object to supply an implementation of some kind of
"Serializable" interface, we'll end up with a (hand written!)
implementation class for each participating setup, which takes
up space in the code segment of the executable. While the closure
based approach chosen here, consumes data segment (or heap) space
per instance for the functors (or function pointers) representing
the closures, plus code segment space for the closures, but the
latter with a way higher potential for inlining, since the closure
code and the generated virtual functions are necessarily emitted
within the same compilation unit and within a local (inline, not
publickly exposed) scope.
2015-04-05 18:26:49 +02:00
723d1e0164 settle architectural considerations regarding the TreeMuator concept
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.
2015-04-03 20:10:22 +02:00
e4a1261849 initial syntax draft
the envisioned DSL syntax for installing the binding closures
into a generic tree mutator object seems to work out
2015-04-02 03:30:20 +02:00
b051845835 identify and decide on some of the insidious questions of design
- how to deal with typing
- how to relate equality and mutations
2015-03-21 19:23:41 +01:00
f5ddfa0dbe decide on the foundations of tree diff representation
- 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
2015-03-21 02:00:55 +01:00
55b2c79aad Implementation of List Diff detection finished. Unit Test PASS 2015-01-04 15:13:16 +01:00
a12a739f05 allow for iterative access to the snapshot data in the lookup table 2015-01-04 14:23:12 +01:00
a8d1cd9c8b trivial implementation of index / snapshot table
lots of room for improvement here :)
2015-01-04 14:01:07 +01:00
80eec4132b factor out index table helper and define its contract 2015-01-04 13:23:57 +01:00
d0dcccbd1b move and split drafted code to the acutal library headers 2015-01-04 12:36:13 +01:00
eb8ad8ed11 code up the actual list diff generator algorithm
sans the implementation of the index lookup table(s)

The algorithm is KISS, a variant of insertion sort, i.e.
worst time quadratic, but known to perform well on small data sets.
The mere generation of the diff description is O(n log n), since
we do not verify that we can "find" out of order elements. We leave
this to the consumer of the diff, which at this point has to scan
into the rest of the data sequence (leading to quadratic complexity)
2015-01-04 12:02:41 +01:00
5427d659d7 definition reordering and comments 2015-01-04 09:26:25 +01:00
97c63e0472 solution how to place and use the diff token constructors
finally....
The problem is that the C++ "dependent types" defeat the typical
DSL usage, where you define some helper function in a generic
language setup class and mix this language in as superclass.
This is, C++ requires us to refer explicitly to any dependent type,
since, due to possible template specialisations, the parser
can't know if a given symbol is a inherited type or a field.

As a solution, we place the token constructor functors into a
static struct "token", which allows to write e.g. token.insert(xyz)
2015-01-04 09:08:36 +01:00
5c818aff69 better typename 2015-01-03 12:52:09 +01:00
5bae84392a implementation of demand-driven diff generating iterator
TODO: actual decision tree
2015-01-03 02:37:33 +01:00
25646337cd change list diff language to rely on 'find' instead of 'push'
As decided in beb57cde
this changeset switches our basic list diff language to work
in the style of an insertion sort. Rather than 'pushing back'
out-of-order elements, we scan and bring forward missing elements.

Later, when passing the original location of the elements
fetched this way, a 'skip' verb will help to clean up
possible leftowers, so implementation is possible
(and indeed acomplished) without shifting any other elements.
2015-01-02 13:18:25 +01:00
cd85b3425e fix: neat a dedicated translation unit for definitions
...yes, sometimes we even want to emit code ;-)
2015-01-02 11:26:27 +01:00
9707a8982c Diff Handling and Diff Application: framework and definitions
factored out of the concept test built last week.
2014-12-15 03:21:19 +01:00
658698407e use the successful concept test as starting point for a diff handling system
...basically move code from test to various headers
2014-12-15 01:27:03 +01:00