Issues for MOF QVT 1.2 Revision Task Force
To comment on any of these issues, send email to qvt-rtf@omg.org. (Please include the issue number in the Subject: header, thusly: [Issue ###].) To submit a new issue, send email to issues@omg.org.
List of issues (green=resolved, yellow=pending Board vote, red=unresolved)
Issue 10646: Missing explanations in BNF
Issue 10947: 7.13.1 Multiple transformation extension
Issue 10948: 7.13.1 Qualified query name
Issue 11341: QVT 1.0 Section 7,8,9,10 : Navigating non-navigable opposite roles
Issue 12173: Section: 8.2.1.6
Issue 12198: Section: 8.2.1.7
Issue 12362: Section: 8.4.7
Issue 12373: Section: 8.2.2.22
Issue 12374: MOF QVT 1.0, 8.2.2.22, Unclear specification of Unpack notation shorthand
Issue 12375: Section: 8.1.14
Issue 13331: QVTo Standard Lybrary and typedefs Issue. Extending OCL predefined types
Issue 10646: Missing explanations in BNF (qvt-rtf)
Click here for this issue's archive.
Source: Nomos Software (Dr. Edward Willink, ed(at)willink.me.uk)
Nature: Uncategorized Issue
Severity:
Summary:
The OCL 2.0 spec has a 32 page section on concrete semantics.
QVTr has 1.5 pages of BNF but no explanation.
In particular:
What are the semantics of 'import' which has no abstract counterpart?
Where is the explanation of the role of [ '{' <oclExpressionCS> '}' ] in a <domain>?
Where is the instruction on how to treat the "_" identifier?
Resolution:
Revised Text: Add a sub-section in section 7.13 with the following content:
The mapping is specified using attribute grammar similar to how OCL' concrete to abstract syntax mapping is specified.
topLevelCS
topLevelCS ::= importListCS? transformationListCS?
Abstract syntax mapping
topLevelCS.ast : Set(RelationalTransformation)
Synthesized attributes
topLevelCS.ast = TransformationListCS.ast
Inherited attributes
transformationListCS.env =
if (importListCS.ast.notEmpty())
then
Environment.EMPTY_ENV.addElement('imported transformation', importListCS.ast)
else
Environment.EMPTY_ENV
endif
importListCS
importListCS[1] ::= 'import' unitCS ';' importListCS[2]?
Abstract syntax mapping
importListCS[1].ast : Set(RelationalTransformation)
Synthesized attributes
importListCS[1].ast = unitCS.ast->union(importListCS[2].ast)
unitCS
unitCS ::= identifierCS ('.' identifierCS)*
Abstract syntax mapping
unitCS.ast : Set(RelationalTransformation)
Synthesized attributes
<left unspecified>
The dot separated identifiers identify a compilation unit that is expected to contain transformation specifications. As explained in section 7.13.1 of the spec, how the dot separated identifiers are mapped to, say, a file system hierarchy is implementation specific.
transformationListCS
transformationListCS[1] ::= transformationCS transformationListCS[2]?
Abstract syntax mapping
transformationListCS[1].ast : Set(RelationalTransformation)
Synthesized attributes
transformationListCS[1].ast =
Set{transformationCS.ast}->union(transformationListCS[2].ast)
Inherited attributes
transformationCS[1].env = transformationListCS[1].env
transformationListCS[2].env = transformationListCS[1].env
transformationCS
transformationCS ::= 'transformation' identifierCS[1] '(' modelDeclListCS ')'
('extends' identifierCS[2])?
'{' keyDeclListCS? relQueryListCS? '}'
Abstract syntax mapping
transformationCS.ast : RelationalTransformation
Synthesized attributes
transformationCS.ast.name = identifierCS[1].ast
transformationCS.ast.modelParameter = modelDeclListCS.ast
if (not identifierCS[2].ast.oclIsUndefined())
then
transformationCS.ast.extends =
let importedTransformationSet:Set(RelationalTransformation) =
transformationCS.env.lookup('imported transformations').referredElement.oclAsType(SetType)
in
importedTransformationSet->any(t | t.name = identifierCS[2].ast)
endif
transformationCS.ast.rule = relQueryListCS->select(r | r.OclIsTypeOf(Relation))
transformationCS.ast.ownedOperation = relQueryListCS->select(r | r.OclIsTypeOf(Function))
transformationCS.ast.ownedKey = keyDeclListCS.ast
Inherited attributes
identifierCS[1].env = transformationCS.env
modelDeclListCS.env = transformationCS.env
identifierCS[2].env = transformationCS.env
let
env:Environment =
transformationCS.env.addElement('context transformation', transformationCS.ast)
in
keyDeclListCS.env = env
and
relQueryListCS.env = env
modelDeclListCS
modelDeclListCS[1] ::= modelDeclCS (',' modelDeclListCS[2])?
Abstract syntax mapping
modelDeclListCS[1].ast : Sequence(TypedModel)
Synthesized attributes
modelDeclListCS[1].ast = Sequence{modelDeclCS.ast}->union(modelDeclListCS[2].ast)
Inherited attributes
modelDeclCS.env = modelDeclListCS[1].env
modelDeclListCS[2].env = modelDeclListCS[1].env
keyDeclListCS
keyDeclListCS[1] ::= keyDeclCS keyDeclListCS[2]?
Abstract syntax mapping
keyDeclListCS[1].ast : Set(Key)
Synthesized attributes
keyDeclListCS[1].ast = Set{keyDeclCS.ast}->union(keyDeclListCS[2].ast)
Inherited attributes
keyDeclCS.env = keyDeclListCS[1].env
keyDeclListCS[2].env = keyDeclListCS[1].env
relQueryListCS
relQueryListCS[1] ::= relQueryCS relQueryListCS[2]?
Abstract syntax mapping
relQueryListCS[1].ast : Set(ModelElement)
Synthesized attributes
relQueryListCS[1].ast = Set{relQueryCS.ast}->union(relQueryListCS[2].ast)
Inherited attributes
relQueryCS.env = relQueryListCS[1].env
relQueryListCS[2].env = relQueryListCS[1].env
relQueryCS
[A] relQueryCS ::= relationCS
[B] relQueryCS ::= queryCS
Abstract syntax mapping
relQueryCS.ast : ModelElement
Synthesized attributes
[A] relQueryCS.ast = relationCS.ast
[B] relQueryCS.ast = queryCS.ast
Inherited attributes
[A] relationCS.env = relQueryCS.env
[B] queryCS.env = relQueryCS.env
modelDeclCS
modelDeclCS ::= modelIdCS ':' metaModelIdCS
Abstract syntax mapping
modelDeclCS.ast : TypedModel
Synthesized attributes
modelDeclCS.ast.name = modelIdCS.ast
modelDeclCS.ast.usedPackage = metaModelIdCS.ast
Inherited attributes
modelIdCS.env = modelDeclCS.env
metaModelIdCS.env = modelDeclCS.env
modelIdCS
modelIdCS ::= identifierCS
Abstract syntax mapping
modelIdCS.ast : String
Synthesized attributes
modelIdCS.ast = identifierCS.ast
metaModelIdCS
metaModelIdCS ::= identifierCS
Abstract syntax mapping
metaModelIdCS.ast : Package
Synthesized attributes
metaModelIdCS.ast = loadMetaModelPackage(identifierCS.ast)
// How the package is located and loaded is tool specific and so left unspecified.
keyDeclCS
keyDeclCS ::= 'key' classIdCS '{' keyPropertyListCS '}' ';'
Abstract syntax mapping
keyDeclCS.ast : Key
Synthesized attributes
keyDeclCS.ast.identifies = classIdCS.ast
keyDeclCS.ast.part->union(keyDeclCS.ast.oppositePart) = keyPropertyListCS.ast
Inherited attributes
classIdCS.env = keyDeclCS.env
keyPropertyListCS.env = keyDeclCS.env.addElement('context key', keyDeclCS.ast)
keyPropertyListCS
keyPropertyListCS[1] ::= keyPropertyCS (',' keyPropertyListCS[2])?
Abstract syntax mapping
keyPropertyListCS[1].ast : Set(Property)
Synthesized attributes
keyPropertyListCS[1].ast : Set{keyPropertyCS.ast}->union(keyPropertyListCS[2].ast)
Inherited attributes
keyPropertyCS.env = keyPropertyListCS[1].env
keyPropertyListCS[2].env = keyPropertyListCS[1].env
classIdCS
classIdCS ::= pathNameCS
Abstract syntax mapping
classIdCS.ast : Class
Synthesized attributes
classIdCS.ast =
let
trans:RelationalTransformation =
classIdCS.env.lookup('context transformation').
referredElement.oclAsType(RelationalTransformation)
in
trans.lookupClassName(pathNameCS.ast)
keyPropertyCS
[A] keyPropertyCS ::= identifierCS
[B] keyPropertyCS ::= 'opposite' '(' classIdCS '.' identifierCS ')'
Abstract syntax mapping:
keyPropertyCS.ast : Property
Synthesized attributes:
[A] keyPropertyCS.ast =
let
cls:Class = keyPropertyCS.env.lookup('context key').
referredElement.oclAsType(Key).identifies
in
cls.lookupProperty(identifierCS.ast)
keyPropertyCS.env.lookup('context key').referredElement.oclAsType(Key).
part->includes(keyPropertyCS.ast)
[B] keyPropertyCS.ast = classIdCS.ast.lookupProperty(identifierCS.ast)
keyPropertyCS.env.lookup('context key').referredElement.oclAsType(Key).
oppositePart->includes(keyPropertyCS.ast)
Inherited attributes:
[B] classIdCS.env = keyPropertyCS.env
relationCS
relationCS ::= topQualifierCS? 'relation' identifierCS[1]
('overrides' identifierCS[2])?
'{'
varDeclListCS?
domainListCS
whenCS?
whereCS?
'}'
Abstract syntax mapping
relationCS.ast : Relation
Synthesized attributes
relationCS.ast.isTopLevel = if (not topQualifierCS.ast.oclIsUndefined() and
topQualifierCS.ast = 'top')
then
true
else
false
endif
relationCS.ast.name = identifierCS[1].ast
if (not identifierCS[2].ast.oclIsUndefined())
then
relationCS.ast.overrides =
let
currTrans:RelationTransformation =
relationCS.env.lookup('context transformation').
referredElement.oclAsType(RelationalTransformation)
in
currTrans.extends.rule->any(r | r.name = identifierCS[2].ast)
endif
relationCS.ast.variable =
varDeclListCS.ast->union(
domainListCS->iterate(d:RelationDomain; domainVars:Set(Variable)={} |
domainVars->including(d.rootVariable))
)
relationCS.ast.domain = domainListCS.ast
relationCS.ast.when = whenCS.ast
relationCS.ast.where = whereCS.ast
Inherited attributes
let
env:Environment = relationCS.env.addElement('context relation', relationCS.ast)
in
varDeclListCS.env = env
domainListCS.env = env
whenCS.env = env
whereCS.env = env
topQualifierCS
topQualifierCS ::= 'top'
Abstract syntax mapping
topQualifierCS.ast : String
Synthesized attributes
topQualifierCS.ast = 'top'
varDeclListCS
varDeclListCS[1] ::= varDeclarationCS varDeclListCS[2]?
Abstract syntax mapping
varDeclListCS[1].ast : Set(Variable)
Synthesized attributes
varDeclListCS[1].ast ::= varDeclarationCS.ast->union(varDeclListCS[2].ast)
Inherited attributes
varDeclarationCS.env = varDeclListCS[1].env
varDeclListCS[2].env = varDeclListCS[1].env
varDeclarationCS
varDeclarationCS ::= varListCS ':' TypeCS ';'
Abstract syntax mapping
varDeclarationCS.ast : Set(Variable)
Synthesized attributes
varDeclarationCs.ast->size() = varListCS.ast->size()
varListCS.ast->forAll(vn |
varDeclarationCS.ast->exists(v | v.name = vn and v.type = TypeCS.ast)
)
Inherited attributes
TypeCS.env = varDeclarationCS.env
varListCS
varListCS[1] ::= identifierCS (',' varListCS[2])?
Abstract syntax mapping
varListCS[1].ast : Set(String)
Synthesized attributes
varListCS[1].ast : Set{identifierCS.ast}->union(varListCS[2].ast)
domainListCS
domainListCS[1] ::= domainCS domainListCS[2]?
Abstract syntax mapping
domainListCS[1].ast : Sequence(RelationDomain)
Synthesized attributes
domainListCS[1].ast = Sequence{domainCS.ast}->union(domainListCS[2].ast)
Inherited attributes
domainCS.env = domainListCS[1].env
domainListCS[2].env = domainListCS[1].env
domainCS
domainCS[A] ::= modelDomainCS
domainCS[B] ::= primitiveDomainCS
Abstract syntax mapping
domainCS.ast : RelationDomain
Synthesized attributes
[A] domainCS.ast = modelDomainCS.ast
[B] domainCS.ast = primitiveDomainCS.ast
Inherited attributes
[A] modelDomainCS.env = domainCS.env
[B] primitiveDomainCS.env = domainCS.env
modelDomainCS
modelDomainCS ::= checkEnforceQualifierCS? 'domain' modelIdCS templateCS
('implementedby' OperationCallExpCS)?
('default_values' '{' assignmentExpListCS '}')? ';'
Abstract syntax mapping
modelDomainCS.ast : RelationDomain
Synthesized attributes
if (checkEnforceQualifierCS.ast.oclIsUndefined())
then
modelDomainCS.ast.isCheckable = false
and
modelDomainCS.ast.isEnforceable = false
else
if (checkEnforceQualifierCS.ast = 'checkonly')
then
modelDomainCS.ast.isCheckable = true
and
modelDomainCS.ast.isEnforceable = false
else
modelDomainCS.ast.isCheckable = true
and
modelDomainCS.ast.isEnforceable = true
endif
endif
modelDomainCS.ast.typedModel =
modelDomainCS.env.lookup('context transformation').modelParameter->
any(t | t.name = modelIdCS.ast)
modelDomainCS.ast.pattern.templateExpression = templateCS.ast
modelDomainCS.ast.rootVariable = templateCS.ast.bindsTo
if (not OperationCallExpCS.ast.oclIsUndefined())
then
let
rel:Relation = modelDomainCS.env.lookup('context relation').
referredElement.oclAsType(Relation)
in
rel.operationalImpl.impl = OperationCallExpCS.ast.referredOperation
and
rel.operationalImpl.inDirectionOf = modelDomainCS.ast.typedModel
endif
if (assignmentExpListCS.ast.notEmpty())
then
modelDomainCS.ast.defaultAssignment = assignmentExpListCS.ast
endif
Inherited attributes
let
env:Environment = modelDomainCS.env.addElement('context domain', modelDomainCS.ast)
in
templateCS.env = env
OperationCallExpCS.env = env
assignmentExpListCS.env = env
primitiveTypeDomainCS
primitiveTypeDomainCS ::= 'primitive' 'domain' identifierCS ':' TypeCS ';'
Abstract syntax mapping
primitiveTypeDomainCS.ast : RelationDomain
Synthesized attributes
primitiveTypeDomainCS.ast.rootVariable.name = identifierCS.ast
primitiveTypeDomainCS.ast.rootVariable.type = TypeCS.ast
Inherited attributes
TypeCS.env = primitiveTypeDomainCS.env
checkEnforceQualifierCS
[A] checkEnforceQualifierCS ::= 'checkonly'
[B] checkEnforceQualifierCS ::= 'enforce'
Abstract syntax mapping
checkEnforceQualifierCS.ast : String
Synthesized attributes
[A] checkEnforceQualifierCS.ast = 'checkonly'
[B] checkEnforceQualifierCS.ast = 'enforce'
templateCS
[A] templateCS ::= objectTemplateCS ('{' OclExpressionCS '}')?
[B] templateCS ::= collectionTemplateCS ('{' OclExpressionCS '}')?
Abstract syntax mapping
templateCS.ast : TemplateExp
Synthesized attributes
[A] templateCS.ast = objectTemplateCS.ast
if (not OclExpressionCS.ast.oclIsUndefined())
then
templateCS.ast.where = OclExpressionCS.ast
endif
[B] templateCS.ast = collectionTemplateCS.ast
if (not OclExpressionCS.ast.oclIsUndefined())
then
templateCS.ast.where = OclExpressionCS.ast
endif
Inherited attributes
[A] objectTemplateCS.env = templateCS.env
OclExpressionCS.env = templateCS.env
[B] collectionTemplateCS.env = templateCS.env
OclExpressionCS.env = templateCS.env
objectTemplateCS
objectTemplateCS ::= identifierCS? ':' pathNameCS '{' propertyTemplateListCS? '}'
Abstract syntax mapping
objectTemplateCS.ast : ObjectTemplateExp
Synthesized attributes
let
cls:Class = objectTemplateCS.env.lookup('context domain').
referredElement.typedModel.usedPackage.getEnvironmentWithoutParents().
lookupPathName(pathNameCS.ast).referredElement.oclAsType(Class)
in
if (not identifierCS.ast.oclIsUndefined)
then
objectTemplateCS.ast.bindsTo.name = identifierCS.ast
and
objectTemplateCS.ast.bindsTo.type = cls
and
objectTemplateCS.env.lookup('context relation').
referredElement.oclAsType(Relation).variable->
exists(v | v = objectTemplateCS.ast.bindsTo)
endif
and
objectTemplateCS.ast.referredClass = cls
objectTemplateCS.ast.part = propertyTemplateListCS.ast
Inherited attributes
propertyTemplateListCS.env =
objectTemplateCS.env.addElement('context template', objectTemplateCS.ast)
propertyTemplateListCS
propertyTemplateListCS[1] ::= propertyTemplateCS (',' propertyTemplateListCS[2])?
Abstract syntax mapping
propertyTemplateListCS[1].ast : Set(PropertyTemplateItem)
Synthesized attributes
propertyTemplateListCS[1].ast = Set{propertyTemplateCS.ast}->
union(propertyTemplateListCS[2].ast)
Inherited attributes
propertyTemplateCS.env = propertyTemplateListCS[1].env
propertyTemplateListCS[2].env = propertyTemplateListCS[1].env
propertyTemplateCS
[A] propertyTemplateCS ::= identifierCS '=' ExtOclExpressionCS
[B] propertyTemplateCS ::= 'opposite' '(' classIdCS '.' identifierCS ')' '='
ExtOclExpressionCS
Abstract syntax mapping:
propertyTemplateCS.ast : PropertyTemplateItem
Synthesized attributes:
[A] propertyTemplateCS.ast.referredProperty =
propertyTemplateCS.env.lookup('context template').
referredElement.oclAsType(ObjectTemplateExp).
referredClass.lookupProperty(identifierCS.ast)
propertyTemplateCS.ast.isOpposite = false
propertyTemplateCS.ast.value = ExtOclExpressionCS.ast
[A] propertyTemplateCS.ast.referredProperty =
classIdCS.ast.lookupProperty(identifierCS.ast)
propertyTemplateCS.ast.isOpposite = true
propertyTemplateCS.ast.value = ExtOclExpressionCS.ast
Inherited attributes:
[A] ExtOclExpressionCS.env = propertyTemplateCS.env
[B] ExtOclExpressionCS.env = propertyTemplateCS.env
classIdCS.env = propertyTemplateCS.env
collectionTemplateCS
collectionTemplateCS ::= identifierCS? ':' CollectionTypeIdentifierCS '(' TypeCS ')'
'{' (memberListCS '++' restCS)? '}'
Abstract syntax mapping
collectionTemplateCS.ast : CollectionTemplateExp
Synthesized attributes
if (CollectionTypeIdentifierCS.ast = CollectionKind::Set)
then
collectionTemplateCS.ast.referredCollectionType.oclIsTypeOf(SetType)
else
if (CollectionTypeIdentifierCS.ast = CollectionKind::Sequence)
then
collectionTemplateCS.ast.referredCollectionType.oclIsTypeOf(SequenceType)
else
if (CollectionTypeIdentifierCS.ast = CollectionKind::Bag)
then
collectionTemplateCS.ast.referredCollectionType.oclIsTypeOf(BagType)
else
if (CollectionTypeIdentifierCS.ast = CollectionKind::OrderedSet)
then
collectionTemplateCS.ast.referredCollectionType.
oclIsTypeOf(OrderedSetType)
endif
endif
endif
endif
collectionTemplateCS.ast.referredCollectionType.elementType = TypeCS.ast
if (not identifierCS.ast.oclIsUndefined)
then
collectionTemplateCS.ast.bindsTo.name = identifierCS.ast
and
collectionTemplateCS.ast.bindsTo.type =
collectionTemplateCS.ast.referredCollectionType
and
collectionTemplateCS.env.lookup('context relation').
referredElement.oclAsType(Relation).variable->
exists(v | v = collectionTemplateCS.ast.bindsTo)
endif
if (memberListCS->notEmpty())
then
collectionTemplateCS.ast.member = memberListCS.ast
endif
if (not restCS.oclIsUndefined())
then
collectionTemplateCS.ast.rest = restCS.ast
endif
Inherited attributes
TypeCS.env = collectionTemplateCS.env
memberListCS.env = collectionTemplateCS.env
restCS.env = collectionTemplateCS.env
memberListCS
memberListCS[1] ::= memberCS (',' memberListCS[2])?
Abstract syntax mapping
memberListCS[1].ast : Sequence(OclExpression)
Synthesized attributes
memberListCS[1].ast = Sequence{memberCS.ast}->union(memberListCS[2].ast)
Inherited attributes
memberCS.env = memberListCS[1].env
memberListCS[2].env = memberListCS[1].env
restCS
[A] restCS ::= identifierCS
[B] restCS ::= '_'
Abstract syntax mapping
restCS.ast : Variable
Synthesized attributes
[A] restCS.ast = restCS.env.lookup('context relation').
referredElement.oclAsType(Relation).variable->any(v | v.name = identifierCS.ast)
[B] restCS.ast.name = '_'
memberCS
[A] memberCS ::= identifierCS
[B] memberCS ::= templateCS
[C] memberCS ::= '_'
Abstract syntax mapping
memberCS.ast : OclExpression
Synthesized attributes
[A] memberCS.ast = memberCS.env.lookup('context relation').
referredElement.oclAsType(Relation).variable->any(v | v.name = identifierCS.ast)
[B] memberCS.ast = templateCS.ast
[C] memberCS.ast.oclIsTypeOf(Variable)
memberCS.ast.oclAsType(Variable).name = '_'
Inherited attributes
[B] templateCS.env = memberCS.env
assignmentExpListCS
assignmentExpListCS[1] ::= assignmentExpCS assignmentExpListCS[2]?
Abstract syntax mapping
assignmentExpListCS[1].ast : Set(RelationDomainAssignment)
Synthesized attributes
assignmentExpListCS[1].ast = Set{assignmentExpCS.ast}->
union(assignmentExpListCS[2].ast)
Inherited attributes
assignmentExpListCS[2].env = assignmentExpListCS[1].env
assignmentExpCS.env = assignmentExpListCS[1].env
assignmentExpCS
assignmentExpCS ::= identifierCS '=' OclExpressionCS ';'
Abstract syntax mapping
assignmentExpCS.ast : RelationDomainAssignment
Synthesized attributes
assignmentExpCS.ast.variable = assignmentExpCS.env.lookup('context relation').
referredElement.oclAsType(Relation).variable->
any(v | v.name = identifierCS.ast)
assignmentExpCS.ast.valueExp = OclExpressionCS.ast
Inherited attributes
OclExpressionCS.env = assignmentExpCS.env
whenCS
whenCS ::= 'when' '{' predicateListCS '}'
Abstract syntax mapping
whenCS.ast : Pattern
Synthesized attributes
whenCS.ast.predicate = predicateListCS.ast
Inherited attributes
predicateListCS.env = whenCS.env
whereCS
whereCS ::= 'where' '{' predicateListCS '}'
Abstract syntax mapping
whereCS.ast : Pattern
Synthesized attributes
whereCS.ast.predicate = predicateListCS.ast
Inherited attributes
predicateListCS.env = whereCS.env
predicateListCS
predicateListCS[1] ::= predicateCS ';' predicateListCS[2]?
Abstract syntax mapping
predicateListCS[1].ast : Set(Predicate)
Synthesized attributes
predicateListCS[1].ast = Set{predicateCS.ast}->union(predicateListCS[2].ast)
Inherited attributes
predicateCS.env = predicateListCS[1].env
predicateListCS[2].env = predicateListCS[1].env
predicateCS
predicateCS ::= ExtOclExpressionCS
Abstract syntax mapping
predicateCS.ast : Predicate
Synthesized attributes
predicateCS.ast.conditionExpression = ExtOclExpressionCS.ast
Inherited attributes
ExtOclExpressionCS.env = predicateCS.env
queryCS
queryCS ::= 'query' identifierCS '(' paramDeclListCS? ')' ':' TypeCS
queryBodyCS
Abstract syntax mapping
queryCS.ast : Function
Synthesized attributes
queryCS.ast.name = identifierCS.ast
queryCS.ast.ownedParameter = paramDeclListCS.ast
queryCS.ast.type = TypeCS.ast
queryCS.ast.queryExpression = queryBodyCS.ast
Inherited attributes
paramDeclListCS.env = queryCS.env
queryBodyCS.env = queryCS.env
paramDeclListCS
paramDeclListCS[1] ::= paramDeclarationCS (',' paramDeclListCS[2])?
Abstract syntax mapping
paramDeclListCS[1].ast : Sequence(Parameter)
Synthesized attributes
paramDeclListCS[1].ast = Sequence{paramDeclarationCS.ast}->
union(paramDeclListCS[2].ast)
Inherited attributes
paramDeclarationCS.env = paramDeclListCS[1].env
paramDeclListCS[2].env = paramDeclListCS[1].env
paramDeclarationCS
paramDeclarationCS ::= identifierCS ':' TypeCS
Abstract syntax mapping
paramDeclarationCS.ast : Parameter
Synthesized attributes
paramDeclarationCS.ast.name = identifierCS.ast
paramDeclarationCS.ast.type = typeCS.ast
Inherited attributes
typeCS.env = paramDeclarationCS.env
queryBodyCS
[A] queryBodyCS ::= ';'
[B] queryBodyCS ::= '{' OclExpressionCS '}'
Abstract syntax mapping
queryBodyCS.ast : OclExpression
Synthesized attributes
[B] queryBodyCS.ast = OclExpressionCS.ast
Inherited attributes
[B] OclExpressionCS.env = queryBodyCS.env
ExtOclExpressionCS
[A] ExtOclExpressionCS ::= OclExpressionCS
[B] ExtOclExpressionCS ::= templateCS
[C] ExtOclExpressionCS ::= RelationCallExpCS
Abstract syntax mapping
ExtOclExpressionCS.ast : OclExpressionCS
Synthesized attributes
[A] ExtOclExpressionCS.ast = OclExpressionCS.ast
[B] ExtOclExpressionCS.ast = templateCS.ast
[C] ExtOclExpressionCS.ast = RelationCallExpCS.ast
Inherited attributes
[A] OclExpressionCS.env = ExtOclExpressionCS.env
[B] templateCS.env = ExtOclExpressionCS.env
[C] RelationCallExpCS.env = ExtOclExpressionCS.env
RelationCallExpCS
RelationCallExpCS ::= (identifierCS[1] '.')? identifierCS[2] '(' argumentsCS? ')'
Abstract syntax mapping
RelationCallExpCS.ast : RelationCallExp
Synthesized attributes
RelationCallExpCS.ast.referredRelation =
let
trans:RelationalTransformation =
if (not identifierCS[1].ast.oclIsUndefined)
then
RelationCallExpCS.env.lookup('imported transformation').
referredElement.oclAsType(CollectionType)->
any(t | t.name = identifierCS[1].ast)
else
RelationCallExpCS.env.lookup('context transformation').
referredElement.oclAsType(RelationalTransformation)
endif
in
trans.rule->any(r | r.name = identifierCS[2].ast).
oclAsType(RelationalTransformation)
RelationCallExpCS.ast.argument = argumentsCS.ast
Inherited attributes
argumentsCS.env = RelationCallExpCS.env
argumentsCS
argumentsCS[1] ::= OclExpressionCS (',' argumentsCS[2])?
Abstract syntax mapping
argumentsCS[1].ast : Sequence(OclExpression)
Synthesized attributes
argumentsCS[1].ast = Sequence{OclExpressionCS.ast}->union(argumentsCS[2].ast)
Inherited attributes
OclExpressionCS.env = argumentsCS[1].env
argumentsCS[2].env = argumentsCS[1].env
Operations
context RelationalTransformation::lookupClassName(names: Sequence(String)) : Class
post:
result =
let
typesPackage:Package =
self.modelParameter.usedPackage->any(p|
not p.getEnvironmentWithoutParents().lookupPathName(names).oclIsUndefined())
in
typesPackage.getEnvironmentWithoutParents().lookupPathName(names).oclAsType(Class)
Actions taken:
February 6, 2007: received issue
April 26, 2010: closed issue
Discussion: Resolution: Deferred
Comment:
Specifying more formally the mapping between the concrete syntax and the metamodel - as it was achieved for the OCL language - could be interesting. However it is a very time expensive task. Also, may be difficult to maintain. We prefer defer such decision to a future RTF.
Issue 10947: 7.13.1 Multiple transformation extension (qvt-rtf)
Click here for this issue's archive.
Source: Nomos Software (Dr. Edward Willink, ed(at)willink.me.uk)
Nature: Uncategorized Issue
Severity:
Summary: The concrete syntax for transformation supports multiple extension.
The abstract syntax supports only single extension.
Suggest: change the concrete syntax.
Resolution: Comment:
Concrete syntax is incorrect.
Resolution:
The concrete syntax of the production <transformation> given in Appendix A of this report is changed as follows:
<transformation> ::= 'transformation' <identifier>
'(' <modelDecl> (';' <modelDecl>)* ')'
['extends' <identifier>]
'{' <keyDecl>* ( <relation> | <query> )* '}'
Replace the content of section 7.13.1 and 7.13.2 by the new content given in Appendix A of this report.
Revised Text:
Actions taken:
March 26, 2007: received issue
November 7, 2007: closed issue
Issue 10948: 7.13.1 Qualified query name (qvt-rtf)
Click here for this issue's archive.
Source: Nomos Software (Dr. Edward Willink, ed(at)willink.me.uk)
Nature: Uncategorized Issue
Severity:
Summary: The concrete syntax for a query uses a pathNameCS, yet the query is defined
within the scope of a transformation.
How should a scoped name be interpreted?
? is a scoped name only applicable for declaring externally definedc queries ?
Resolution: Comment:
Concrete syntax is incorrect.
Resolution:
The concrete syntax of the production <query> given in Appendix A of this report is changed as follows:
<query> ::= 'query' <identifier>
'(' [<paramDeclaration> (',' <paramDeclaration>)*] ')' ':' <TypeCS>
(';' | '{' <OclExpressionCS> '}')
Replace the content of section 7.13.1 and 7.13.2 by the new content given in Appendix A of this report.
Revised Text:
Actions taken:
March 26, 2007: received issue
November 7, 2007: closed issue
Issue 11341: QVT 1.0 Section 7,8,9,10 : Navigating non-navigable opposite roles (qvt-rtf)
Click here for this issue's archive.
Source: Nomos Software (Dr. Edward Willink, ed(at)willink.me.uk)
Nature: Uncategorized Issue
Severity:
Summary: Issue : QVT 1.0 Section 7,8,9,10 : Navigating non-navigable opposite roles
UML models drawn with Rose allow an opposite role to be defined for a
uni-directional role. This practice is common but haphazard in UML Infrastructure,
EMOF, OCL and QVT specification diagrams.
However EMOF provides only the (run-time) usage of the model and so any
EMOF (or Ecore) model generator must strip non-navigable opposite roles.
QVT matches models at compile-time and matching has no inherent need to
observe navigation constraints. This is amply demonstrated by the Rel2Core
transformation that makes extensive use of, for instance, the inverse Key to Class
relationship.
----------------------------------
Problem: some QVT transformations require names for non-navigable opposite roles,
but those names cannot be present in layered multi-package EMOF meta-models.
The Rel2Core transformation of Section 10.3 cannot be implemented with QVT 1.0.
----------------------------------
Abandoning EMOF (or Ecore) compliance in favour of perhaps CMOF seems unacceptable.
Changing EMOF (or Ecore) to incorporate opposite roles is not possible because
an EMOF specification cannot be extended to include the opposite role of every
meta-model that will ever exist.
Even if it was, there would be a substantial delay until meta-modelling tools
adopted the change and a problem with poor standardisation and global
non-interference of opposite rolenames.
QVT must therefore support definition of non-navigable role names as part of a
transformation. ModelMorf provided a very practical concrete syntax solution,
whereby the reserved operation opposite(qualified-role-name) could be used as
the missing opposite role-name wherever a forward role-name could be used.
An upward compatible abstract syntax requires an additional is-opposite qualifier
for each referred property.
So for
QVTCore::PropertyAssignment add isOpposite:Boolean[0..1] default false.
QVTTemplate::PropertyTemplateItem add isOpposite:Boolean[0..1] default false.
QVTRelation::Key add oppositeParts:Property[0..*] { composed }
and possibly relax the lower bound for
QVTRelation::Key add parts:Property[0..*] { composed }
with the constraint that parts.size() + oppositeParts.size() > 0
Perhaps QVTOperational::Module needs an additional oppositeConfigProperty and
QVTOperational::ContextualProperty needs an additional isOpposite too.
Resolution:
Revised Text: (1) Replace the definition of Key (Section 7.11.3.5) by the following text:
7.11.3.5 Key
A key defines a set of properties of a class that uniquely identify an instance of the class in a model extent. A class may have multiple keys (as in relational databases). Sometimes it may be necessary to specify a key in terms of opposite properties that are not navigable from the class. Please refer to section 7.4 for a detailed description of the role played by keys in the enforcement semantics of relations.
Superclasses
Element
Associations
identifies: Class [1]
The class that is identified by the key.
part: Property [0..*]
Properties of the class that make up the key.
oppositePart: Property [0..*]
Opposite properties of the class that make up the key.
(2) In the definition of PropertyTemplateItem (Section 7.11.2.4), add the following attribute definition:
Attributes
isOpposite:Boolean
Specifies whether the referred property is owned by the opposite end class. An opposite property template item selects an object of the opposite end class that has this object as the value of the specified property. The default value of this property is false. Please refer to section 7.3 for an example that uses an opposite property in template specification.
(3) Modify the grammar rule <keyDecl>, <classId>, <keyproperty> and <propertyTemplate> in section 7.13.5 as follows:
<keyDecl> ::= 'key' <classId> '{' <keyProperty> (, <keyProperty>)* '}' ';'
<classId> ::= <pathNameCS>
<keyProperty> ::= <identifier>
| 'opposite' '(' <classId> '.' <identifier> ')'
<propertyTemplate> ::= <identifier> '=' <OclExpressionCS>
| 'opposite' '(' <classId> '.' <identifier> ')' '='
<OclExpressionCS>
(4) At the end of section 7.4 describing keys add the following text:
Sometimes it may be necessary to use a non-navigable opposite role in the specification of a key. For instance, an attribute is identified by a combination of its name and the owning class. Suppose we have a meta model in which the 'Class' to 'Attribute' association 'attribute' is only navigable from Class to Attribute. We should still be able to use this association in the key specification of Attribute.
E.g.
key Attribute {name, opposite(Class.attribute)};
This specifies that an attribute is uniquely identified by its name and the class it belongs to.
(5) At the end of section 7.3, just before the last sentence, add the following text:
Sometimes it may be necessary to use a non-navigable opposite role in the specification of object templates.
E.g.
domain myModel a:Attribute {name = n, opposite(Class.attribute) = c:Class{}};
This specifies that the pattern will only match if the class the attribute belongs to is equal to 'c'. This is equivalent to the following template definition with condition:
domain myModel a:Attribute {name = n} {c.attribute.includes(a)};
But the 'opposite' notation allows this to be specified in the template itself, leading to more compact specifications
(6) In figure 7.6, add the new 'isOpposite : Boolean' attribute to the PropertyTemplateItem metaclass.
(7) In Figure 7.7, add the additional 'oppositePart: Property [0..*]' association from Key metaclass to the Property metaclass.
Actions taken:
September 10, 2007: received issue
April 26, 2010: closed issue
Discussion: Agree with the suggested extensions to the key and property template parts of the relations language. As for a more general support in other expressions, we should perhaps wait until the next OCL revision.
Sometimes it may be necessary to use a non-navigable opposite role in the specification of a key. For instance, an attribute is identified by a combination of its name and the owning class. Suppose we have a meta model in which the 'Class' to 'Attribute' association 'attribute' is only navigable from Class to Attribute. We should still be able to use this association in the key specification of Attribute.
E.g.
key Attribute {name, opposite(Class.attribute)};
This specifies that an attribute is uniquely identified by its name and the class it belongs to.
Similarly, it is useful to be able to specify object templates in terms of opposite properties.
E.g.
domain myModel a:Attribute {name = n, opposite(Class.attribute) = c:Class{}};
This specifies that the pattern will only match if the class the attribute belongs to is equal to 'c'. This is equivalent to the following template definition with condition:
domain myModel a:Attribute {name = n} {c.attribute.includes(a)};
But the 'opposite' notation allows this to be specified in the template itself, leading to more compact specifications.
Issue 12173: Section: 8.2.1.6 (qvt-rtf)
Click here for this issue's archive.
Nature: Revision
Severity: Minor
Summary: The extraCondition association needs revision: 1. The name does match with the diagram. 2. The cardinality is incorrect. Suggestion: Change the text with the following line: additionalCondition: OclExpression [*] {composes, ordered}
Resolution:
Revised Text: In Section 8.2.1.6, replace
extraCondition: OclExpression [1..*] {composes, ordered}
By:
additionalCondition: OclExpression [*] {composes, ordered}
Actions taken:
January 14, 2008: received issue
April 26, 2010: closed issue
Discussion: That's true. The class description is obsolete in respect with the role naming found in Figure 8.1.
Issue 12198: Section: 8.2.1.7 (qvt-rtf)
Click here for this issue's archive.
Nature: Clarification
Severity: Minor
Summary: A clarification is needed in the text because it says "A variable parameter is an abstract concept..." and it can lead to confussion. A variable parameter can not be abstract because we could not create VarParameters for Helpers or Constructors (We could just create ModelParameters or MappingParameters). Suggestion: Remove the word "abstract".
Resolution:
Revised Text: In Section 8.2.1.7, replace
"A variable parameter is an abstract concept…"
By:
"A variable parameter is a concept…"
Actions taken:
January 25, 2008: received issue
April 26, 2010: closed issue
Issue 12362: Section: 8.4.7 (qvt-rtf)
Click here for this issue's archive.
Nature: Revision
Severity: Minor
Summary: The grammar rule used to produce a forExp doesn't coincide with the notation specified in the abstract syntax section for it (Pag 89, Section 8.2.2.6). The rule production in the grammar is wrong. Suggestion: Change the production rule: <for_exp> ::= ('forEach' | 'forOne') '(' <iter_declarator_list> ('|' <expression> )? ')' <expression_block>
Resolution:
Revised Text: Revised Text:
In Section 8.2.2.6, at the end of the "Notation" sub-section add
the following text.
"""
When using a forEach expression in conjunction with a compute expression
the following shorthand can be used:
mylist->forEach(i;x:X=...|cond) { … }
This is equivalent to:
compute (x:X=...) mylist->forEach(i|cond) { … }
This is similar to the shorthand notation for while expression (see 8.2.2.4).
"""
Actions taken:
April 1, 2008: received issue
April 26, 2010: closed issue
Discussion: The intent of syntax rule:
<for_exp> ::= ('forEach' | 'forOne') '(' <iter_declarator_list> (';' <declarator>)? ('|' <expression>)? ')' <expression_block>
was to allow shorthand with the computeExp
compute (x:X) mylist->forEach(i|cond) { … }
<==> mylist->forEach(i;x|cond) { … }
Similarly with what happens with While expression.
However the explanation was missing in the notation sub-section.
Issue 12373: Section: 8.2.2.22 (qvt-rtf)
Click here for this issue's archive.
Nature: Revision
Severity: Critical
Summary: UnpackExp should not compose targetVariable There are a lot of issues in this section: 1. name of Variable association was not updated to targetVariable. 2. {ordered} is missed. 3. variable should not compose. They should refer for instance a previously defined VarInitExp::referredVariable. 4. Parenthesis are missed in the first example (notation section). 5. Remember to update the diagram in figure 8.6 (pag 86). Note: These proposed changes are needed if you want to allow unpacking OrderedTuples using previously defined variables (which makes sense). Another (worst) alternative is forcing to declare new variables . In this case, the notation section should be changed.
Resolution:
Revised Text: (1) Replace:
variable : Variable [1..*] {composes}
by targetVariable : Variable [1..*] {ordered}
(2) Replace
var x, y , z := self.foo(); // assuming foo returns a tuple of three elements.
By
var (x,y,z) := self.foo(); // assuming foo returns a tuple of three elements.
(3) Update diagram 8.6 to reflect that targetVariable is not a composition
Actions taken:
April 7, 2008: received issue
April 26, 2010: closed issue
Issue 12374: MOF QVT 1.0, 8.2.2.22, Unclear specification of Unpack notation shorthand (qvt-rtf)
Click here for this issue's archive.
Source: Nomos Software (Dr. Edward Willink, ed(at)willink.me.uk)
Nature: Uncategorized Issue
Severity:
Summary: Section 8.2.2.22 provides no guidance on the meaning of:
var x:X;
var y:Y;
var z:Z;
...
var (x:X,y,z) := self.foo();
[If one of the variables in the left hand side, does exist ...]
Possible interpretations
a) x:X is always a syntactical shorthand.
Therefore the above is a shorthand for:
var x:X;
var y:Y;
var z:Z;
...
var x:X; var (x,y,z) := self.foo();
and consequently there is duplicate variable definition to be
reported as a semantic error.
b) x:X is a convenience type check assertion
Therefore the above is a shorthand for:
var x:X;
var y:Y;
var z:Z;
...
var (x,y,z) := self.foo();
with a successful validation of type consistency.
c) x:X is not available as a shorthand
Therefore the above is a syntax error.
------------------------------------
Interpretations b) and c) require semantic knowledge to resolve syntactic
sugar.
Interpretation a) is an unambiguous syntax shorthand that could be more
clearly
described by:
"The following example demonstrates a shorthand in which variables are both
declared
and assigned.
var (x:X,y:Y,z) := self.foo();
Any variable name qualified by a type name is both a declaration and an
assignment,
with all declarations proceding the unapack assignment.
The above example should therefore be analyzed as:
var x:X; var y:Y; var (x,y,z) := self.foo();"
---------------------------------------------------------------------
Recommend interpretation a) with the above textual clarification.
Resolution:
Revised Text: (1) Replace the text:
"""If one of the variables in the left hand side does not exist, the notation is a shorthand for declaring the missing variables prior to the unpack expression. In such case, the type of the variables can be given. For instance, in the example above, if 'x' and 'y' does not exist, the expression var (x:X,y:Y,z) := self.foo(); is equivalent to: var x:X; var y:Y; var (x,y,z) := foo();
"""
By the following text:
"""The following example demonstrates a shorthand in which variables are both
declared and assigned.
var (x:X,y:Y,z) := self.foo();
Any variable name which specifies a type name is both a declaration and an
assignment, with all declarations proceding the unpack assignment.
The above example should therefore be analyzed as:
var x:X; var y:Y; var (x,y,z) := self.foo();"
"""
Actions taken:
April 8, 2008: received issue
April 26, 2010: closed issue
Issue 12375: Section: 8.1.14 (qvt-rtf)
Click here for this issue's archive.
Nature: Revision
Severity: Significant
Summary: QVT Operational Mappings claims in the overview section, the use of ListLiteralExpression (for instance to initialize a list), as in the section 8.1.14 (Pag 55) is shown. However, there is no way to represent this literal expression in the abstract syntax, due to: 1. There is no ListLiteralExp in the imperativeOCL package. 2. CollectionLiteralExp (from EssentialOCL) can't be used. There is a way to initialize lists, making use of the asList operator which appears in the Standard Library section (8.3.85 / Pag 112), however this should be clarified. Therefore, two possible solutions could be taken: Suggestion 1: Create a ListLiteralExp which should extend CollectionLiteralExp (From EssentialOCL). Suggestion 2: Update the overview examples, to properly ilustrate how to initialize lists. Besides, the grammar ( Pag 124) )should be consequently changed as well. (List { 1, 2, 3, } literal expressions wouldn't be supported).
Resolution:
Revised Text: (1) Add a new subsection 8.2.2.33 ListLiteralExp, with the following content:
A list literal expression is a literal definition for a mutable list type (see 8.2.2.25) .
Superclasses: CollectionLiteralExp (From EssentialOCL)
Associations:
element : OclExpression [*] {composes,ordered}
The values of the literal list.
(2) Update the Figure 8.7 with the ListLiteralExp definition
(3) Add the 'List' keyword in 8.4.7.1.
Actions taken:
April 8, 2008: received issue
April 26, 2010: closed issue
Discussion:
Issue 13331: QVTo Standard Lybrary and typedefs Issue. Extending OCL predefined types (qvt-rtf)
Click here for this issue's archive.
Source: Open Canarias, SL (Mr. Adolfo Sanchez-Barbudo Herrera, adolfosbh(at)opencanarias.com)
Nature: Uncategorized Issue
Severity:
Summary: As interpretation from the especification (pag 104), the way of adding new operations to OCL predefined types is creating new Typedef instances
which must have the OCL predefined type as the base type. The new operations are added to this new typedef. However there are several problems:
1. The specification doesn't provide any name for these typedefs.
2. The specification doesn't specify which type (QVT typedef or OCL predefined type) should be used when referencing such OCL predefined types in a QVTo transformation.
Solution for 1).
Suggestion a: Name the typedef with the same name of the base type. This provokes name's clash with the predefined type's name, due to there are two different types from two standard libraries
which have the same name. A possible solution, would be expliciting that typedefs (aliases) will never clash its name with its base type.
Suggestion b: Name the tpyedef with a different name, such as QVToXXXXXX or XXXX_Alias.
Solution for 2).
Suggestion a: Taking the typedef as the referenced type in QVTo transformations.
Suggestion b: Taking the OCL predefined type as the referenced type in QVTo transformations.
Suggestion c: Considering resolution of issue 13168, so that only OCL predefined exists, and therefore, the only type which can be referenced.
It's a little bit weird having 2 different types (a type, and its alias typedef) which represent just the same type, specially when they are related by a reference.
My solution's preference in order are:
c) Just having one type to refer.
a) Since the typedef "extends" the behaviour of the predefined type (adding new operations), the former must be the referred one.
b) The OCL predefined type is referenced, but we must taking into account that operations added to the typedef are available.
Resolution: issue closed, duplicate of issue # 13252
Revised Text:
Actions taken:
December 22, 2008: received issue
January 26, 2009: issue closed, duplicate of issue # 13252