Hi
At the moment I'm sounding out the broad technical direction. You
seem happy. Christopher seems happy. In a couple of days, in the
absence of new insights, perhaps from Sergey, I'll take another more
thorough shot at the resolution. e.g eliminating the "usual
object-oriented virtual call semantics" text. Then detailed
editorial comments will be helpful.
----
In my QVT Traceability talk at AMT, I indentied two use cases for
tracing the invoked/disjuncting mapping and two for tracing the
actual/candidate mapping. Declaratively, where incremental
re-execution is feasible, it's more interesting., The invoked
mapping must be traced to identify what candidate selection must be
re-assessed. The actual mapping must be traced to ensure that
chnages in additional inputs are detectable. (All matches are found
but matches to more refined mappings suppress execution of the less
refined.)
Regards
Ed
On 07/10/2015 13:47, Adolfo
Sanchez-Barbudo Herrera wrote:
Hi Ed,
Comments in-line below
Regards,
Adolfo.
On 07/10/2015 12:31, Ed Willink
wrote:
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.
Ok. Given the first "8.1.12 Mapping Overloading" section,
it seemed to me that the implict dijunct took place at compile
time. I think that it's a matter of adding additional
clarification, because if this concept implicit disjunct takes
place at runtime the proposal is sound to me. I'm unsure about the
benefit of calling it implicit disjunct rather than
clarifying/explaining what "mapping virtual call" means in QVT,
but if others feel comfortable with this new terminology, I'm OK
with that. We might then remove the terminology related "mapping
virtual call" to avoid confusion.
Do you prefer to bring a new text, or do you prefer I come up with
some suggestion ?
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.
As of the specification, which obviously only relates to explicit
disjunct: just the explicitly disjuncted mappings are the
considered mappings to execute, the disjuncting mapping body is
always empty (In Eclipse QVTo, If it is not empty you get a
warning which says "The body of disjuncting mapping 'xxxx' gets
never executed") , and if no candidates match, null is returned .
Although a change in the way you propose is not a backwards
incompatible one, I don't see the need to include it: Since a
group of overloaded mappings is resolved at run-time, we don't
need to be worried about which are the specific semantics of
explicit disjuncts.
---
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.)
Yes, and I don't see any reason why it should be different in OCL
and QVT => Something to solve in OCL, and BTW it's actually
considered in QVTo (See ImperativeCallExp::isVirtual at 8.2.1.20).
---
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.
I think that's exactly the scenario that Christopher pointed out.
I presume that this concept of "implicit disjunct" should also
apply to declarative languages, since this kind of rules
refinement (let's say overload) should also be supported.
Therefore in that example, tracee of two mappings might also be
registered: the disjuncting mapping (the internally and implicitly
created, which the end user will never will aware of) + the actual
disjuncted mapping which has been executed.
Is there any fundamental problem for tracing two mappings related
to just one input object?. No, actually it's a requirement,
because two different rules might create two different objects
from the same one...
... Well, one could argue that since we are creating two different
output objects, whereas the case above relates to the same output
object.... We need use cases, or some light on any fundamental
problem, to get better conclusions.
Responding to Christopher.
"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) ?"
Since statically you are directly calling the disjuncted mapping rather than the disjuncting one, I'd say that just a trace with the B::doIt() should be registered. But, I'm pretty sure you are coming up with an scenario in which you would like to have non-null object when b.resolveIn(A::doIt), right ? :)
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
_______________________________________________
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
|