In order to have mirror(s) of a Context applied to an Element
expressions which involve
any Element field must be evaluated within
given Context and
Element result of an
expression must be used within that Context
It implies that if
a components is mirrored
within a Context and
we want to use its mirrored
counterpart
then
the object (its mirrored
counterpart) must not be returned
outside the Context where it is mirrored
any queries on this
component must be run within given Context
the Element must not get
mutated as that makes it lose all its
Shadows history
The only way to use the mirrored version from outer Context is to
inspect the
component
using a visitor object
visitor has call back
method(s)
which get evaluated within a target Context
the result to be returned
must be a primitive, or an object which is not
mirrored within a target Context
Otherwise, if the component is returned outside the Context, then
the object is resolved to
its previous identity - determined
by the last applied mirror
the shadows stack is unwound
the mirrored counterpart
gets resolved to its original
There is a way to return or pass an Element by value
to a different Context, and
to protect it from being mirrored or resolved
by creating
an empty mutation
all its shadows history is
lost
it has a new identity -
therefore mirrors of its original don't
apply to the mutation
it can't be unwound to any
of its originals anywhere in Context
stack
this method should be used
cautiously
Restrictions
Elements must not receive or
store any modifiable objects
No identity comparison
always compare Elements by
value.
Element objects serve as wrappers. They are created when needed.
no global variable neither
class-shared (static) variables
Static final Element seeds
are used. They get adjusted to local
Context by special a method.
Elements can be stored in
static non-final variables. However,
these
must not be used along with other Elements later, as that breaks some
core
engine assertions. Otherwise a less efficient mechanism would need to
be used - e.g.for Context.equals().
Deep queries
using visitor mechanism
components are to be used
within Context of their containers
ElementPures can't store
any values dependent on other
ElementPures. That's because
any of them may be mirrored, with no
change to other components. That would involve inconsistencies. Element
can cache values based on other components, because these are
Context-associated, and therefore no more mirrors can apply to them in
given Context.
simple header in any
non-static Element method - entered/up/dw
Mutations and Mirrors
Mutation creates ElementShadowed of entirely new identity. That implies:
Mutation loses all its Shadows history. The original Element could be a
result of one or several applied mirrors applied to top-level seed. It
can't
unwind mirrors
which were applied to original of the mutation. Otherwise the changes
carried
by the mutation would need to be applied to mirrored original as the
Element is returned from local Context. What identity would it
have? What mirrors would apply to it, and how?
When
a mutation is passed down to a deeper Context, mirrors of
mutation's original don't apply to the mutation itself. Otherwise
mirrors would apply to almost any ElementShadowed of given type. That's
because ElementShadowed instances of given class are supposed to be
created as mutation of one or a few seeds of that type, or as their
subsequent mutation.
TODO
Mirror [original, target]
don't get applied to mutation of original
Element. Otherwise that would involve dynamic mutation
"combinations".