Bug 532011 - [qvts2qvti] success gets lost for non-guard traces
Summary: [qvts2qvti] success gets lost for non-guard traces
Status: NEW
Alias: None
Product: QVTd
Classification: Modeling
Component: Core (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 10
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 515236
  Show dependency tree
 
Reported: 2018-03-05 07:30 EST by Ed Willink CLA
Modified: 2018-03-07 09:55 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Willink CLA 2018-03-05 07:30:18 EST
The current success syntax annotates a guard parameter as having a success property. This does not work when the success is in a realized trace variable.

Example: MiToSi Class2Class if Package2Package fails.

Need a more arbitrary capability.

One day, Bug 480194, we might have if-else/try-catch clauses.

For now a SuccessStatement that is always executed may do better than a GuardParameter property.
Comment 1 Ed Willink CLA 2018-03-05 12:09:58 EST
Attempting to implement this runs into significant let-variable visibility scoping difficulties in the CG, which highlight that supporting true/false success on realized variables is stupid. By the time the variable is being realized, commit actions are in progress and so the only possible value for the success status is true.

Therefore either the success can be optimized away or exactly true can be written as a normal property assignment.
Comment 2 Ed Willink CLA 2018-03-06 04:31:42 EST
(In reply to Ed Willink from comment #1)
> supporting true/false success on realized variables is stupid

On arbitrary realized variables , yes, on trace variable, no.

On overridden relation may well need to test the failure of an overriding relation, therefore the trace of a failed relation must be available. 

This highlights a redundancy between the trace that when it exists may be used for navigation between relations and the derived AbstractInvocation that unifies multiple invocation of a relation for the same arguments. The derived AbstractInvocation is a minimal tuple of the identification of the invocation. The trace is generally an augmented tuple comprising all the fields of the minimal tuple. The minimal tuple is not exploited by navigation leading to the problem that accessing the status in the full tuple fails.

Clearly the trace tuple should always be created and its identification fields initialized even when a mapping fails. The derived AbstractInvocation is then obsolete, except in so far as all trace tuples might derive from AbstractInvocation.

QVTc whose manually designed trace classes may not mirror mappings discouraged exploiting the concept of THE trace class in QVTi. But where QVTc deviates we have had to introduce a disambiguator to try to characterize the trace classes.

If in QVTi we have a new header construct:

trace:traceModelName traceClassName{k1 = k1Exp, k2 = k2Exp, ... | success}

where

traceClassName::k1, traceClassName::k2, are the tuple elements that provide the unique identification.

k1Exp, k2Exp are 'simple' expressions that evaluate the trace keys with respect to the head variables. Typically just VariableExp, perhaps PropertyCallExp(VariableExp).

Optionally traceClassName::success is assigned the true/false success status.

Once execution is requested:
traceClassName::k1, traceClassName::k2 are assigned
traceClassName::success = null

Once execution fails:
traceClassName::k1, traceClassName::k2 are assigned
traceClassName::success = false
no other assignments have happened

Once execution succeeds:
traceClassName::k1, traceClassName::k2 are assigned
traceClassName::success = true
other assignments have happened

The trace may be located by k1Exp.traceClassName->select(k2 = k2Exp)->...

All mappings are requested by external creation of an instance of their trace class. For top relations, the root relation creates them, for non-top relations some when clause creates/reuses the trace.
Comment 3 Ed Willink CLA 2018-03-06 04:40:39 EST
(In reply to Ed Willink from comment #2)
> If in QVTi we have a new header construct:
> 
> trace:traceModelName traceClassName{k1 = k1Exp, k2 = k2Exp, ... | success}

But this is just a QVTs2QVTi policy. Once all mappings have an externally created trace the guards can be drastically simplified to just a single guard:

guard:traceModelName trace : traceClassName success successPropertyName;

no new syntax needed. If all trace classes extend AbstractInvocation then success maintenance may be built-in always.

Rather we just prune and optimize for the simpler usage.

It is the invoker that must be richer; perhaps a ShadowExp

new:traceModelName invokedTrace = invokedTraceClassName{k1 = k1Exp, k2 = k2Exp, ...};
Comment 4 Ed Willink CLA 2018-03-06 05:46:01 EST
(In reply to Ed Willink from comment #3)
> trace the guards can be drastically simplified to just a single guard:

So all mappings are single headed with the trace as head. All the analyses identifying heads are redundant for QVTr, since when/where traceability prohibits re-heading, and dubious for QVTc. If QVTc2QVTs extracts trace creation as a unified pre-micromapping we get much the same as QVTr. Realizing trace class instances within micromappings as suggested by QVTc was a big mistake.

What happens to genuine multi-headed cases? e.g a sub/super-class relationship. Rather than a naive 2D search, a secondary should be searched wrt a primary resulting in the two-class trace instances being created only at sensible combinations. We could be back to the efficiency of composition tree descent; a trace is created per actual combination, rather than per possible permutation.

-----

If all mappings have a single trace head, is partitioning into micro-mappings useful? Too disruptive. Moved to Bug 532059.
Comment 5 Ed Willink CLA 2018-03-06 06:07:00 EST
(In reply to Ed Willink from comment #4)
> So all mappings are single headed with the trace as head.

Step 1: Change QVTr2QVTs to treat top relations as non-top to use an external head, and create an activation mapping for them, as for non-top. 

Step 2: Ensure QVTi2CG recognises the trace heads to avoid a redundant derived AbstractInvocation.

In due course the top activation mappings can be merged into the input model traversal in the root region.
Comment 6 Ed Willink CLA 2018-03-07 09:55:25 EST
(In reply to Ed Willink from comment #4)
> So all mappings are single headed with the trace as head. All the analyses
> identifying heads are redundant for QVTr

No. For top relations, the activator packs the multiple head nodes into a trace node. Identification of the multiples requires a head analysis and selecting the best of a head group is a 'free' choice.