Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [qvto-dev] What are the mapping refinement rules

Hi

Thanks. Three interesting points. We have 6 days before this gets semi-frozen in a Preview.

It is not my intention to require any run-time functionality to move to comple-time. I think I just highlight that unspecified but necessary functionality is at run-time.

The "usual object-oriented virtual call semantics" is:
execute the function corresponding to the derived type.

My suggested MappingCallExp semantics is a prioritized (run-time) disjunct search:
if A's predicates are satisfied doA
else if B's predicates are satisfied doB
...
else null

I observe that some static analysis can eliminate some of the cases. (In the case of unknown transformation extension, the static analysis could be at load-time, or JIT for each new invocation.)

In your example perhaps your internal doIt' is my internal list of candidates. Reifying the internal list may make the exposition clearer.

---

Given a body for both candidate and disjuncting mapping, when is each executed? Perhaps the disjuncting body (default null) is executed only when no candidate is found.

---

If a MappingCallExp.referredOperation references X::doA, it is currently unspecified in OCL and so in QVTo whether this invokes precisely X::A or the overload applicable to the actual source type. In OCL it should nearly always be the overload, though just occasionally as in super-calls it would be nice to suppress dynamic dispatch. Perhaps a Boolean isStaticDispatch flag is needed and set by the presence of a fully qualified name in the source code.

If a MappingCallExp used the "usual object-oriented virtual call semantics" then it is precisely the same problem. But it's different although with the same ambiguity. Does the the AS reference to X::A trigger the disjunct search for X::A or just call X::A regardless? Mostly it should do the disjunct search, but just X::A if we want a super-call. (A more optimized implementation looks up the precomp[uted source type specific list of candidate mappings.)

---

Tracing has a similar problem.

Is the disjuncting mapping traced or is the actual selected candidate mapping traced? Both are of some use. See my AMT 2015 talk. The most important usage is in resolveIn where the user cannot sensibly reference the candidate mapping, therefore resolveIn must at least work for a reference to the disjuncting mapping. However, particularly given that a candidate mapping may actually be candidate for multiple disjuncting mappings, it should also be possible to invoke resolveIn with respect to the actual candidate mapping. This is probably difficult and hard to support unless the trace record contains both disjuncting and candidate mapping identities. Both are needed internally, an arbitrary choice could be made for the qvttrace file for which the QVTo specification might evolve to dismiss as a proprietary convenience. Certainly nothing that is QVTr compatible and fully supporting incremental re-execution.

    Regards

        Ed


On 07/10/2015 11:31, Adolfo Sanchez-Barbudo Herrera wrote:
Hi Ed,

In principle, the implicit disjuncts seems a good idea, an there are some interesting clarifications in your proposal, but I need to point out a couple of concerns.

1. The disjuncting mapping itself is a kind of "intermediate" mapping (no logic goes there). So in your example:

mapping A::doIt() : AA {...}
mapping B::doIt() : BB {...}
mapping C::doIt() : CC {...}

The equivalent should be something like the following:

mapping A::doIt'() : AA
disjuncts B::doIt, C::doIt, A::doIt {...}
mapping A::doIt() : AA {...}
mapping B::doIt() : BB {...}
mapping C::doIt() : CC {...}
At compilation time any static call to A::doIt(), should be changed to the A::doIt'()

2. More seriously, you are moving a run-time dispatch mechanism, to a compile-time, which it should turn to be reflected in the AS. That in principle sounds OK for single transformations, i.e. for inter-transformation mappings extensions, but it doesn't seem so good in the inter-transformation reuse scenario, because we need cross-references from the extended transformation to the different extending ones. Compiled transformations wouldn't make less sense, or we would require many AS compiled copies/variants of a extended transformation, depending on how these implicit disjuncts come up from the extending ones.

I reluctant to replace the traditional virtual mapping call mechanism (performed at runtime) by this new implicit disjuncts mechanism (performed at compile time). That said, I think that much of what you have tried clarify, can be useful explain for instance, how signature of extending mappings should be, or how the virtual mapping call mechanism should be performed in QVT rather than "This follows usual object-oriented virtual call semantics" (page 93) .

I hope you find my comments useful.

Regards,
Adolfo.

On 07/10/2015 10:41, Ed Willink wrote:
Hi

A first attempt at a proposal. I think it says what is needed, but perhaps some of it should be moved/duplicated in 8.2.1.21 MappingCallExp.

I considered "abstract" since it is in the Concrete Syntax and another issue requests it. I'm not sure whether it is really that useful.

    Regards

        Ed Willink

Replace Section 8.1.13 with the following text to be placed before the current 8.1.12.

8.1.12 Mapping Overloading

Invocation of a mapping selects a disjunction of one or more candidate mappings at compile time. At run-time, the first matching candidate mapping is selected and invoked. The disjunction may be specified explicitly using the disjuncts keyword or implicitly by an overloaded mapping.

8.1.12.1 Explicit Disjuncts

In the following example, the explicit disjunction defines convertFeature as a disjuncting mapping name that may be invoked on a UML::Feature with a Boolean argument. convertAttribute, convertConstructor and convertOperation are candidate mapping names.

mapping UML::Feature::convertFeature(asUpper: Boolean) : JAVA::Element
disjuncts convertAttribute, convertOperation, convertConstructor {}
mapping UML::Attribute::convertAttribute(asUpper: Boolean) : JAVA::Field {
name := if asUpper then name.toUpper() else name endif;
}
mapping UML::Operation::convertConstructor(asUpper: Boolean) : JAVA::Constructor
when {self.name = self.namespace.name;} {
name := if asUpper then name.toUpper() else name endif;
}
mapping UML::Operation::convertOperation(asUpper: Boolean) : JAVA::Constructor
when {self.name <> self.namespace.name;} {
name := if asUpper then name.toUpper() else name endif;
}

The explicit disjuncts causes the mapping invocation to successively assess the implicit and explicit predicates of convertAttribute, convertConstructor and convertOperation to identify the first match. If no match is found the mapping invocation returns null.

The explicit predicates are provided by arbitrary constraints specified in when clauses. Implicit predicates are provided by the type signatures; each source and argument must conform to the type of the disjuncting mapping. An abstract mapping has a false implicit predicate; an abstract mapping cannot be executed.

The candidate return type must be covariant, that is the same as, or derived from that of, the disjuncting return type to ensure that no result incompatibility arises.

Since the argument types contribute to implicit predicates, the candidate argument types may be supertypes or subtypes of the disjuncting mapping. The number of candidate and disjuncting argument types must be the same.

An explicit candidate mapping is identified by its mapping identifier which identifier may contribute to more than one disjunction.

8.1.12.2 Implicit Disjuncts

An implicit disjunction groups overloaded mappings. One mapping overloads another when the overloading source type extends the overloaded source type and when the overloading and overloaded mappings have same name and argument count.

When UML::Attrbute and UML::Operation extend UML::Feature, the previous example may be simplified to use an implicit disjunction.

mapping UML::Feature::convertFeature(asUpper: Boolean) : JAVA::Element {}
mapping UML::Attribute::convertFeature(asUpper: Boolean) : JAVA::Field {
name := if asUpper then name.toUpper() else name endif;
}
mapping UML::Operation::convertFeature(asUpper: Boolean) : JAVA::Constructor
when {self.name = self.namespace.name;} {
name := if asUpper then name.toUpper() else name endif;
}
mapping UML::Operation::convertFeature(asUpper: Boolean) : JAVA::Constructor
when {self.name <> self.namespace.name;} {
name := if asUpper then name.toUpper() else name endif;
}

he explicit disjuncts provides distinct names and so facilitates explicit calls direct to the candidate mappings. The implicit disjuncts requires no disjuncting declaration and so faciltates extension by addition of further contributions.

8.1.12.3 Disjunct candidates

All mappings with the required name, argument and matching or derived source type are candidate mappings for the invocation of a disjuncting mapping. This includes mappings inherited from extended transformations. The candidate mappings referenced in a disjuncting mapping may introduce new names and consequently a further disjunction of candidate mappings; the explicit disjunct is transitive.

For instance invocation of convertFeature for a Property in the explicit disjuncts example should consider a Property::convertOperation(Boolean) inherited from an extended transformation since the explicit disjunct adds convertOperation to the transitive candidates. Conversely, the implicit disjunct example considers only candidates whose signature is convertFeature(Boolean).

For non-strict evaluation, a deterministic evaluation order for evaluation of the predicates of the candidates as guards is established by sorting using the following proritized criteria. A distinction by an earlier criteria overrules all later criteria.

  • directly invoked explicitly disjuncted candidate mappings are evaluated in declaration order
  • mappings in the current transformation are evaluated before those in an extended transformation, then mappings in an extended transformation before those in an extended extended transformation, and so forth
  • mappings for a more derived type are executed before those for a less derived type
  • mappings are prioritized by alphabetical mapping name order
  • mappings are prioritized by alphabetical context type name order
  • mappings are prioritized by alphabetical context type containing package name order, then by containing package containing package name order, and so forth

The ordering above ensures that an extending transformation can occlude a mapping in an extended transformation and that a mapping for a derived type occludes that for a base type. An implementation may use static analysis of the predicates to eliminate occluded candidates completely and to provide reduced candidate lists according to the source type of the mapping invocation.

For strict evaluation, the same ordering applies but the first candidate for which the source type conforms is selected without evaluating the predicate as a guard. The predicate is instead evaluated as a pre-condition giving a null return when not satisfied.

In the QVTo model and Fig 8.3. Add

MappingOperation ::isAbstract : Boolean[1] default false.

In 8.2.15 MappingOperation Attributes Add

isAbstract : Boolean[1]
Indicates whether the mapping is abstract, requiring an overload for all derived context types. Default is false.



On 06/10/2015 13:26, Christopher Gerking wrote:
Hi

+1 for choosing the most derived in case of a family of overloaded mappings.

I also like the approach of defining an overload as an implicit disjuncts. In particular, this could simplify the traceability recording rules.
When calling a.doIt() dispatches to B::doIt(), I expect a traceability record for a.resolveIn(A::doIt), even if A::doIt didn't really execute.
For disjuncts, Eclipse QVTo already records traceability links also for the disjuncting mapping. Therefore the above requirement would be fulfilled.

It is more interesting when we have b:B and call b.doIt(). Does it still consult A::doIt() and produce the traceability link for b.resolveIn(A::doIt) ?


Regards
Christopher



-----Ursprüngliche Nachricht-----
Von: qvto-dev-bounces@xxxxxxxxxxx [mailto:qvto-dev-bounces@xxxxxxxxxxx] Im Auftrag von Ed Willink
Gesendet: Sonntag, 4. Oktober 2015 13:30
An: QVTOML developer mailing list <qvto-dev@xxxxxxxxxxx>
Betreff: [qvto-dev] What are the mapping refinement rules

Hi

When preparing my "QVT Traceability : What does it really mean?" 
presentation to AMT 2015, I was forced to think hard about mapping signatures and their relationships.

https://www.eclipse.org/mmt/qvt/docs/ICMT2014/QVTtraceability.pdf
http://www.slideshare.net/EdWillink/qvt-traceability-what-does-it-really-mean

Declaratively, independent mappings are all invoked independently, dependent mappings such as refinements are arbitrated by their predicates to select the best of a group of related mappings.

Imperatively, it is much simpler, mappings are explicitly invoked, so exactly one compatible mapping is invoked per source object.

The simplest case is the invoked name corresponds to a declared mapping.

More interesting, the invoked name corresponds to a disjuncted mapping allowing the best match of the explicit disjuncts to be invoked, else null.

I am unclear about what happens when the invoked name corresponds to a family of 'overloaded' mappings analoguous to Java operation overloads.

e.g.

mapping A::doIt() : AA {...}
mapping B::doIt() : BB {...}
mapping C::doIt() : CC {...}

where C and B extend A

I presume that in QVTo we choose the most derived analoguously to Java.

I'm inclined to clarify this situation by defining such overloads as implicit disjuncts, so that all colliding names contribute to a disjunct

The example is then equivalent to

mapping A::doIt() : AA
disjuncts B::doIt, C::doIt {...}
mapping B::doIt() : BB {...}
mapping C::doIt() : CC {...}

This could make disjuncts extensible since an extending transformation could supply additional name collisions for the explicitly/implicitly disjuncted mapping.

In order to give deterministic dispatch, the order of disjuncts is: 
explicit disjuncts first, then implicit disjuncts successively ordered by the following criteria
- most derived source type,
- most derived first argument type,
- most derived second argument type,
- etc
- alphabetically by containing class name,
- alphabetically by containing class' containing package name,
- etc

The signatures of refinements are unclear. Since a mapping is explicitly invoked, we clearly require that disjuncting mappings have the same number, position and direction of arguments and a covariant
(same/derived) return type. (An explicit disjunct may omit trailing in
arguments.)

Since we are invoking mappings with predicates rather than invoking operations, we may allow disjuncting mappings to also have covariant or even contravariant arguments. When a disjuncting mapping has a distinct in/inout argument type, it is equivalent to an oclIsKindOf() when predicate for that argument type with a subsequent oclAsType() in the body.

     Regards

         Ed Willink


_______________________________________________
qvto-dev mailing list
qvto-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit https://dev.eclipse.org/mailman/listinfo/qvto-dev
_______________________________________________
qvto-dev mailing list
qvto-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/qvto-dev


-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2015.0.6140 / Virus Database: 4435/10768 - Release Date: 10/06/15







_______________________________________________
qvto-dev mailing list
qvto-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/qvto-dev



_______________________________________________
qvto-dev mailing list
qvto-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/qvto-dev


No virus found in this message.
Checked by AVG - www.avg.com
Version: 2015.0.6140 / Virus Database: 4435/10773 - Release Date: 10/07/15



Back to the top