Hi
Thanks for the review. Comments inline.
Regards
Ed Willink
On 14/10/2015 14:30, Adolfo
Sanchez-Barbudo Herrera wrote:
On 14/10/2015 12:40, Ed Willink wrote:
http://solitaire.omg.org/browse/QVT13#selectedTab=org.omg.jira.task-forces%3Ataskforce-issues-panel&view=HAS_PROPOSAL
is the 'active' work in progress/pending.
Hi Ed
After reading the "final" issue resolution, I add the following
comments here:
QVTo-dev is a more open/accessible list. So I'll add my comments
here about "http://solitaire.omg.org/browse/QVT13-102"
and add a link back in JIRA.
Since we don't have lines, I'll refer to "text" which you should
be able to identify with a Ctrl+F facility in the issue
resolution.
Here we go:
--------------------
Firstly you mention
"... In the case of a standard mode
execution for which no candidate mapping is selected, the trace
record contains null entries for executed-mapping, out-parameters and result-parameters fields."
Later one:
"...If no mapping is executed, the executed-mapping, out-parameters and result-parameters are null."
It sounded kinda redundant to me. Feel free to decide if
you keep both or not.
Yes. The lines migrated rather close together.
-------------------
An equivalent OCL-like query for SOURCE.resolve(T : TYPE |
CONDITION) is
I'm unsure (apologies for vagueness) if for inout parameters you
are allowed to return a different object/value, but I'm concerned
about what happens if the inout-parameter is the same object at
the end of the mapping execution as the object which came in
(regardless it is modified by the mapping or not), that might
provoke that calls to source.resolve might return the same source
object, which at least sounds awkward. I'm not sure what should be
done, but I throw the discussion about if:
selectedRecords->collect(out-parameters->union(result-parameters))...
Should be
selectedRecords->collect(out-parameters)->union(selectedRecords->collect(result-parameters))->excludingAll(selectedRecords->collect(in-parameters))...
or at least
selectedRecords->collect(out-parameters)->union(selectedRecords->collect(result-parameters))->excluding(SOURCE)...
Probably the former, in a short form:
selectedRecords.out-parameters->union(selectedRecords.result-parameters)->excludingAll(selectedRecords.in-parameters)...
[NB Is there no excludingAll (i.e. subtract or set complements
operation) in OCL library?. excludingAll works in Pivot- Eclipse
OCL]
I don't see a problem here. inout-parameters are traced twice.
Class instances are traced by reference and so are blind to
mutation. Specification-wise a pair of references is not a problem.
If Eclipse QVTo copies instance content, then that is an issue for
Eclipse QVTo. To fully support incremental execution traced Class
Instances would need to be treated as DataType values so that
everything is deepcloned, but of course taking care to share
referenced objects in their correct states.
Since the Class instance reference is a reference, it cannot be
chnaged to another object so the double trace is redundant.
DataType values (including Dict) are traced by value, so the entire
inout Dict is deepcloned twice. Not a problem specification-wise. An
implementation might save memory on one of the deepclones. My
original QVT Traceability paper thoughts dismissed inout Dict
tracing as too expensive in parctice and suggested that inout
parameters be excluded from tracing. However redundant
execution/re-use requires them to be in the trace. Eclipse Qvto
appears to deepclone. I have twice asked Christopher if he is happy
with this clear specification and he has not objected. Sergey seems
to be busy/elsewhere.
DataType values are passed by reference-to-variable so the entire
value may be changed, and so a double trace is necessary.
In the same OCL _expression_. ->collect flattens the result, so
->flatten() seems unnecessary ]
Yes.
-----------------------
invresolve at 8.1.x.4
Whereas from one source object we might produce different output
objects through different mappings, from one target there should
be just one source object. In any case, filtering types/conditions
should apply to source domain. Suggestion
replace
target.invresolve(t : Table | t.name.startsWith('_'))
target.invresolveIn(Class2Table, t : Table | t.name.startsWith('_'))
by
invresolve(Class)
invresolveIn(Class2Table, c : Class | c.name.startsWith('_'))
target.invresolve() // No filtering conditions: just one object can be the source of a created object
No. This is an ambiguity that my words and pseudo-code clear up.
Given:
Tuple{gOut, hOut} t := aIn.map m(bIn, cIn, dInout, eOut, fOut)
{aIn,bIn,cIn,dInOut} are traced to {dInout,eOut,fOut,gOut,hOut}
so all sources for the dInout target/ m mapping are
{aIn,bIn,cIn,dInOut}.
[NB
8.1.x.5 has similar issues with the same invresolveone
expressions]
-----------------------------
"deep value equality". Is this a standarized/well-known concept ?.
I think I know that you refer, but... others might not.
Dotting every I and crossing every T formally is beyond my current
ambition. Once QVT 2.0 provides a solid CS2AS and perhaps AS
evaluation semantics, we can try to do better. Otherwise I'll wait
for the 'what does deep equality mean' issue.
-----------------
In 8.1.x.7. Redundant execution
In second paragraph, you comment what happens when input objects
are modified, with respect to decide if a mapping is not
re-executed (and returns previous outputs)
In last paragraph, perhaps evident, but I think a sentence might
be similarly added with respect to the out-put objects which also
might be modified between redundant mapping calls.
Yes.
"...matching name and argument count." => "...matching name and
arguments."
No. If you mean in the 8.2.1.15 Replace.
This is not OO. arguments may be covariant or contravariant.
m(Real) is a candidate implicit disjunct of m(String). However when
the candidate list of an invocation of m(Real) is built giving the
choices {m(Real), m(String)} static analysis can reveal that String
is neither a supertype nor subtype of Real. Its implicit argument
type predicate can never match and so there is no point seeing if it
does.
In practice this is very important.
OO does not allow f(A) to be overloaded by f(BextendsA). A mapping
call does so we achieve the utopia of a layer of derived types that
work together unlike OO where we need to keep downcasting.
-----------------
Removal of Mapping disjuncts as a reuse facility.
To me disjunct is arguably a reuse facility, but I like the
direction you want to give to that part. Perhaps using "mapping
extension" rather than "re-use facility" is more appropriate.
It's hardly that either. It is really just a mapping
selection/switch.
Another issue I find in that part is that you:
1. firstly mention mapping inheritance/merge as the only two reuse
facility,
2. then clarify a disjuncting mapping.
3. then you mention: The
execution semantics subsection below provides the details of
these reuse facilities.
Probably just being lazy and trying to rewrite not enough.
Therefore I'd rework that part as follows:
In section 8.2.15 Replace
There are three reuse and composition facilities associated to
mapping operations:
1. A mapping operation may inherit from another mapping operation.
This means invoking the initialization section of
the inherited operation after executing its own initialization
section.
2. A mapping operation may also merge other mapping operations.
This means invoking the merged operations after the
termination section.
3. A mapping operation may be defined as a disjunction of other
mapping operations. This means selecting, among the
set of disjuncted mappings, the first that satisfies the when
clause and then invoking it. The execution semantics subsection
below provides the details of these reuse facilities
By
A mapping operation may be defined as an explicit
disjunction of candidate mapping operations. This means
selecting and executing the first candidate mapping whose when
clause and other predicates are satisfied. The empty body of the
disjuncting mapping is not executed. An implicit disjunction of
candidate mappings is formed by overloaded mappings with
matching name and argument count.
Additionally, there are two extension mechanisms
associated to mapping operations:
1. A mapping operation may inherit from another mapping
operation. This means invoking the initialization section of the
inherited operation after executing its own initialization
section.
2. A mapping operation may also merge other mapping operations.
This means invoking the merged operations after the termination
section.
The execution semantics subsection below provides the
details of these mapping extension mechanisms.
Probably. More important to get the more interesting replies out
sooner.
----------------
Final corrections:
"In strict mode failure to evaluate..." => "In strict mode,
failure to evaluate..."
Yes.
"This is shorthand for invoking it in the body of a ForExp
_expression_" => "This is shorthand for invoking it in the body
of a xcollect ImperativeIterateExp _expression_."
Yes.
|