Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

QVTd Relation Overriding

Revision as of 11:15, 16 May 2017 by Ed.willink.me.uk (Talk | contribs) (The low level / run-time mechanism)

The QVT specification has a relatively clear specification that QVTr relation may override, but no clues as to how this is mapped to QVTc that has no overrides concrete syntax, even though it inherits an overrides capability from QVTb.

This working document considers how overriding might be supported. It takes over from

QVTc Choices

QVTc refinement syntax is an additive capability and therefore not suitable for implementing the QVTr replacement semantics of QVTr overrides.

We could add overrides syntax to semantics to QVTc, which then passes the buck to QVTi. But since we already need an 'alternator' to dispatch multiple similar but differently predicated mappings efficiently, we may be able to kill two birds with one stone.

QVTc is relatively simple. It solves the mapping sequencing problem by inter-trace class references/dependencies. Can it solve the overrides problem as-is? Let's go with this.

The low level / run-time mechanism

Temporarily ignoring the additional complexities of multi-headed mappings, when an element is dequeued from a Connection, it is dispatched to all relevant mappings. This remains true for overrides. Predicates and type guards will suppress most irrelevant invocations, but we must suppress overrides. There will often be only one appropriate mapping, but we cannot avoid the possibility that the input model has new compound types that are multiply matched. We cannot avoid a multiplicity of matches and a lattice of fall-backs for failed predicates.

The original motivation for an alternator was to avoid repetition. If the alternator hoists all predicate functionality from all dispatch candidates, we maximize sharing, and can resolve all the fall-backs before 'returning' with the list of actual dispatches.

Perhaps the alternator is a function that is invoked as the predicate of each override. Possible because the failed predicates should participate in a decision tree. But how top pass context.

If the alternator is a mapping,it has a trace class that can have all the required shared content. The overrides just predicate the alternator-trace-class and its magic decision variables. Simple override choices may use a simple alternator class to avoid bloating the alternator trace withe all the context for every awkward choice. The alternator therefore conditionalizes its realized trace variable. But QVTc only conditionalizes by using one mapping per type which destroys the whole purpose. The QVTc alternator must create a ragbag of all possibilities. Optimizing this to exclude default valued-elements will have to be a QVTs/QVTi optimization.

The QVTc mechaniam

For each distinct polymorphic dispatch there is a single alternator mapping that hoists the predicates of all possible targets and encodes the dispatch decision, perhaps as a few Booleans, perhaps as an Enumeration, ... . Each dispatch target uses the alternator trace as its predicate with appropriate matches on the decision.

What about an override that participated in multiple distinct polymorphic dispatches?

Simple case, one is a super-type of the other. Re-use the larger ragbag, but provide distinct alternators to avoid run-time computation bloat.

Horrible case, multiple inheritance. Simple solution, ragbag the lot. More optimum, multiple trace class inheritance.

The QVTr2QVTc synthesis

The alternator trace ragbags all the predicates. If these aren't easy to test we may want an enumeration for orthogonal options.

Back to the top