Breaking Changes In QVTO Implementation

Due to synchronization with the OMG standard specification ((MOF) 2.0 Query/View/Transformation) in QVTO 2.0 a range of breaking changes in the language implementation has been introduced. This section is to describe these changes.

Breaking changes list

Expressions in mapping population section

Usage of expressions within the population section of mappings was highly limited in QVTO 1.x. This was significantly improved in QVTO 2.0. According to the specification (sections 8.4.7.1, 8.2.1.19, 8.2.1.18 and 8.1.5), it is possible to have arbitrary expressions (assignments, variable declarations, if-expressions, etc.) in a mapping population section. Furthermore, within an implicit mapping population section (i.e. when the population keyword is omitted) properties of the result object can be accessed directly.
modeltype Ecore uses "http://www.eclipse.org/emf/2002/Ecore";

transformation test(in dummy : Ecore, out model : Ecore);

mapping EPackage::toEClass() : EClass {
	var x := 'ifExp'; -- local variable 'x'
	if x = 'ifExp' then {
		name := x; -- assignment to 'name' property of the result object of type EClass 
		           -- same as: result.name := x;
		name := name + name; -- 'name' property can be directly accessed in any parts of the expression
		                     -- same as: result.name := result.name + result.name;
	} else {
		name := 'wrong'; -- same as: result.name := 'wrong';
	} endif;
}
In case of a mapping with an inout context and without result, this is applicable to the properties of the context which is illustrated in the examples in the specification. Thus the mapping below is valid:
mapping inout EPackage::selfModification() {
	name := 'initialValue'; -- same as: self.name := 'initialValue'; 
}
As regards the previous implementation, the implicit population section in mappings could only consist of assignments to properties of the result object (or the context in case of a mapping with an inout context and without result). Moreover the left part of such assignments must have been a property name (direct assignment without source). The direct access to properties in the right part was unavailable. Thus the mapping below caused a compilation error:
mapping EPackage::toEClass() : EClass {
	name := name; -- in QVTO 1.x this line produced a compilation error
	              -- since properties in the right part could not be accessed directly
}
An important difference between the previous and the new versions is not only the ability to use expressions within the mapping population section but also the name clashing resolution. As already mentioned, the previous implementation considered the left part of the assignment as a property name while the right part was considered to be an ordinary OCL expression where properties could not be accessed directly. Therefore, the code below was correct and sensible.
mapping EPackage::toEClass(name : String) : EClass {
	name := name; -- in QVTO 1.x this line was the same as: result.name := name;
	              -- where 'name' in the right part resolved to the parameter
}
The current implementation treats properties in the left part of the assignment the same way as in the right part. Moreover, name clashes are resolved to local variables/parameters. This question is discussed in the bug comments. Thus in QVTO 2.0 the code above does not compile since it attempts to update a read-only parameter:
mapping EPackage::toEClass(name : String) : EClass {
	name := name; -- in QVTO 2.0 this line is the same as: name := name;
	              -- where 'name' in the expression resolves to the parameter
	              -- which is read-only
}
In the same manner, the example below updates the local variable and hence does not modify the corresponding property:
mapping EPackage::toEClass() : EClass {
	var name := 'a'; -- a local variable hiding the corresponding property
	name := name + 'b'; -- local variable 'name' is updated here
}
Note that the behaviour changes only in cases of name clashing and the majority of mappings written in QVTO 1.x are to be executed in QVTO 2.0 the same way as before.
See bug 252358 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=252358).

Expressions in ObjectExp body

In QVTO 1.x ObjectExp body could only contain assignments to the target object properties. In accordance with the specification (sections 8.4.7.1, 8.2.1.18 and 8.1.5), QVTO 2.0 allows to have arbitrary expressions (assignments, variable declarations, if-expressions, etc.) in an ObjectExp body. Furthermore, within the ObjectExp body properties of the referred object can be accessed directly.
object a : EClass {
	var x := 'ifExp'; -- local variable 'x'
	if x = 'ifExp' then {
		name := x; -- assignment to 'name' property of the referred object 'a' of type EClass 
		           -- same as: a.name := x;
		name := name + name; -- 'name' property can be directly accessed in any parts of the expression
		                     -- same as: a.name := a.name + a.name;
	} else {
		name := 'wrong'; -- same as: a.name := 'wrong';
	} endif;
}
As regards the previous implementation, ObjectExp body could only consist of assignments to properties of the referred object. Moreover, the left part of such assignments must have been a property name (direct assignment without source). The direct access to properties in the right part was unavailable. Thus the ObjectExp below caused a compilation error:
object a : EClass {
	name := name; -- in QVTO 1.x this line produced a compilation error
	              -- since properties in the right part could not be accessed directly
}
An important difference between the previous and the new versions is not only the ability to use expressions within ObjectExp body but also the name clashing resolution. As already mentioned, the previous implementation considered the left part of the assignment as a property name while the right part was considered to be an ordinary OCL expression where properties could not be accessed directly. Therefore, the code below was correct and sensible.
var name := 'a';
object a : EClass {
	name := name + 'b'; -- in QVTO 1.x this line was the same as: a.name := name;
	                    -- where 'name' in the right part resolved to the parameter
}
The current implementation treats properties in the left part of the assignment the same way as in the right part. Moreover, name clashes are resolved to local variables/parameters. Thus name clashes in ObjectExp body and in mapping population section are treated the way. Thus in QVTO 2.0 the code above compiles but produces a completely different result since it updates a local variable:
var name := 'a';
object a : EClass {
	name := name + 'b'; -- in QVTO 2.0 this line is the same as: name := name;
	                    -- where 'name' in the expression resolves to the local variable
	                    -- a.name remains unchanged
}
Note that the behaviour changes only in cases of name clashing and the majority of object expressions written in QVTO 1.x are to be executed in QVTO 2.0 the same way as before.
See bug 253051 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=253051).

ResolveExp/ResolveInExp implicit source resolution disablement

QVTO 1.x performed implicit source lookup for ResolveExp/ResolveInExp expressions. If such lookup was successful ResolveExp (consequently, ResolveInExp) was considered to be used with implicit source. In this way, the following code was allowed:
main() {
		var a := object EPackage{name := 'a'};
		var b := object EPackage{name := 'b'};
		var c := object EPackage{name := 'c'};
		a.map toEClass(); -- creates a trace record for 'a'
		b.map toEClass(); -- creates a trace record for 'b'
		c.map toEClass(); -- creates a trace record for 'c'
		var x := Bag {a, b} -> collect(resolve()); -- in QVTO 1.x the source of resolve() is the implicit iterator
		                                           -- of the collect expression
		                                           -- 'x' becomes a collection of 2 elements
		var y := Bag {a, b} -> collect(resolveIn(EPackage::toEClass)); -- in QVTO 1.x the source of resolveIn() is the implicit iterator
		                                                               -- of the collect expression
		                                                               -- note: this is not a resolveIn() call without source
		                                                               -- as in the next line.
		                                                               -- 'y' becomes a collection of 2 elements
		var z := resolveIn(EPackage::toEClass); -- no implicit source found
		                                        -- 'z' becomes a collection of 3 elements
		--var z1 := resolve(); -- implicit source for resolve() not found => compilation error                                                       
}
 
mapping EPackage::toEClass() : EClass {
}
However, no proof of this concept was found in the specification. Thus, QVTO 2.0 disallowed implicit source resolution for ResolveExp/ResolveInExp. Consequently, usage of ResolveExp (not ResolveInExp) without source is prohibited and usage of ResolveInExp without source is always considered a search though all objects created or updated by the referred mapping (8.2.1.23):
main() {
		var a := object EPackage{name := 'a'};
		var b := object EPackage{name := 'b'};
		var c := object EPackage{name := 'c'};
		a.map toEClass(); -- creates a trace record for 'a'
		b.map toEClass(); -- creates a trace record for 'b'
		c.map toEClass(); -- creates a trace record for 'c'
		--var x := Bag {a, b} -> collect(resolve()); -- in QVTO 2.0 resolve() without source is prohibited
		var y := Bag {a, b} -> collect(resolveIn(EPackage::toEClass)); -- in QVTO 2.0 this is a resolveIn() call without source
		                                                               -- as in the next line.
		                                                               -- 'y' becomes a collection of 6 elements
		var z := resolveIn(EPackage::toEClass); -- a resolveIn() call without source
		                                        -- 'z' becomes a collection of 3 elements
		--var z1 := resolve(); -- in QVTO 2.0 resolve() without source is prohibited                                                       
}
 
mapping EPackage::toEClass() : EClass {
}
Note that the behaviour changes only in case when ResolveExp/ResolveInExp is used without source and there are implicit variables in the corresponding scope (e.g. within collect, select, etc. with implicit iterator). Thus the majority of ResolveExp/ResolveInExp expressions written in QVTO 1.x are to be executed in QVTO 2.0 the same way as before.
See bug 254482 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=254482).

Keyword reservation

QVTO 2.0 reserves all keywords mentioned in the specification (8.4.7.1 Syntax for module definitions, keywords section). In addition, QVTO 2.0 also reserves the keyword List mistakenly forgotten in the section and the keyword invalid which is not present in the OCL implementation (where Invalid starting from the capital I is used).
To refer to a named element in case of clashing with keywords, use an underscore prefix "_" as described in the OCL specification (9.3)
See bug 251064 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=251064).