Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Seidewitz2015-06-10 03:26:39 +0000
committerArnaud Cuccuru2015-06-10 08:05:50 +0000
commitdb0f92e171a6d04f1caffab603ee917718258772 (patch)
tree43d5ed46bd9be21578502f701d41b88fcb02dcc7
parentd4d514bb3b88ee701346c371838191d8ab945ed4 (diff)
downloadorg.eclipse.papyrus-db0f92e171a6d04f1caffab603ee917718258772.tar.gz
org.eclipse.papyrus-db0f92e171a6d04f1caffab603ee917718258772.tar.xz
org.eclipse.papyrus-db0f92e171a6d04f1caffab603ee917718258772.zip
Partial mapping for template binding
- Temporarily implemented a "type erasure" approach for mapping casting and classification checking for template parameters. - Implemented mapping optimization for collection function calls so that it is not necessary to explicitly map template bindings. Change-Id: I26a9668229983212ce0e6953bec26c5f343ba4db Signed-off-by: Ed Seidewitz <ed-s@modeldriven.com> Reviewed-on: https://git.eclipse.org/r/49884 Tested-by: Hudson CI Reviewed-by: Arnaud Cuccuru <arnaud.cuccuru@cea.fr> Tested-by: Arnaud Cuccuru <arnaud.cuccuru@cea.fr>
-rw-r--r--plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/Alf2UML.qvto21
-rw-r--r--plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfCommon2UML.qvto17
-rw-r--r--plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto182
3 files changed, 128 insertions, 92 deletions
diff --git a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/Alf2UML.qvto b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/Alf2UML.qvto
index cf5b13dacf8..ba8592d112f 100644
--- a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/Alf2UML.qvto
+++ b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/Alf2UML.qvto
@@ -284,23 +284,6 @@ mapping UnitDefinition::toNamespace() : Namespace
init {
result := self.definition.map toNamespace();
}
- // TODO: Handle namespace declarations.
- /*
- if self.namespace <> null then
- let namespace =
- if self.namespace.isUml() then
- self.namespace.asUml().oclAsType(Namespace)
- else
- self.namespace.asAlf().oclAsType(NamespaceDefinition).map toNamespace()
- endif
- in
- if namespace.oclIsKindOf(Package) and result.oclIsKindOf(PackageableElement) then
- namespace.oclAsType(Package).packagedElement += result.oclAsType(PackageableElement)
- else if namespace.oclIsKindOf(Class) and result.oclIsKindOf(Classifier) then
- namespace.oclAsType(Class).nestedClassifier += result.oclAsType(Classifier)
- endif endif
- endif;
- */
elementImport := self._import[ElementImportReference]->map toElementImport();
packageImport := self._import[PackageImportReference]->map toPackageImport();
if self.annotation->notEmpty() then
@@ -454,9 +437,9 @@ init {
// log("template=" + template.toString());
result := template.newInstance();
}
- isAbstract := self.isAbstract;
+ isAbstract := template.isAbstract;
var templateSignature := template.ownedTemplateSignature;
- log("signature=" + templateSignature.toString());
+ // log("signature=" + templateSignature.toString());
if templateSignature <> null then
templateBinding := object uml::TemplateBinding {
signature := templateSignature;
diff --git a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfCommon2UML.qvto b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfCommon2UML.qvto
index afa597394ba..be348d59f4c 100644
--- a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfCommon2UML.qvto
+++ b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfCommon2UML.qvto
@@ -179,13 +179,6 @@ helper toType(reference : ElementReference) : Type {
helper BoundElementReference::toUml() : Element {
// TODO: Handle expansion of template bindings.
return self.referent.toUml();
- /*
- if self.isTemplateBinding() then
- self.templateBinding.toUml()
- else
- self.referent.toUml()
- endif;
- */
}
// Constructors
@@ -797,16 +790,6 @@ helper addEdgesToStructuredNode(inout structuredNode : StructuredActivityNode, i
var allOwnedNodes := structuredNode.allOwnedNodes();
var internalEdges := edges[allOwnedNodes->includes(source) and allOwnedNodes->includes(target)];
structuredNode.edge += internalEdges;
- /*
- edges->forEach(edge) {
- edge.ownedComment += object Comment {
- body := nameOf(structuredNode) + ": " +
- if allOwnedNodes->includes(edge.source) then "source " else "" endif +
- if allOwnedNodes->includes(edge.target) then "target " else "" endif ;
- annotatedElement := edge;
- }
- };
- */
return edges - internalEdges;
}
diff --git a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto
index 3aaf0d42630..5e7f8f3c690 100644
--- a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto
+++ b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto
@@ -423,28 +423,78 @@ helper InvocationExpression::InvocationExpression_mapTarget(inout graph : Expres
if self.isImplicit then {
graph.nodes += action := new DestroyObjectAction(self.feature.expression.type.toUml().oclAsType(Class));
} else {
- var element := self.referent.toUml();
- switch {
- case(element.oclIsKindOf(Operation)) {
- graph.nodes += action := new CallOperationAction(element.oclAsType(Operation));
- graph.resultSource := action.returnPin();
- }
- case(element.oclIsKindOf(Signal)) {
- graph.nodes += action := new SendSignalAction(element.oclAsType(Signal));
- }
- case(element.oclIsKindOf(Behavior)) {
- graph.nodes += action := new CallBehaviorAction(element.oclAsType(Behavior));
- graph.resultSource := action.returnPin();
- }
- case(element.oclIsKindOf(Property)) {
- graph.nodes += action := new ReadLinkAction(element.oclAsType(Property));
- graph.resultSource := action._'output'->at(1);
- }
+ var element :=
+ if self.isCollectionFunctionInvocation() then
+ // Optimize the invocation of a (not in-place) collection function by calling
+ // the corresponding sequence function directly.
+ self.sequenceFunction()
+ else
+ self.referent.toUml()
+ endif;
+
+ switch {
+ case(element = null) {
+ graph.nodes += action := new ValueSpecificationAction(new LiteralNull());
+ graph.resultSource := action.output->at(1);
+ }
+ case(element.oclIsKindOf(Operation)) {
+ graph.nodes += action := new CallOperationAction(element.oclAsType(Operation));
+ graph.resultSource := action.returnPin();
+ }
+ case(element.oclIsKindOf(Signal)) {
+ graph.nodes += action := new SendSignalAction(element.oclAsType(Signal));
+ }
+ case(element.oclIsKindOf(Behavior)) {
+ graph.nodes += action := new CallBehaviorAction(element.oclAsType(Behavior));
+ graph.resultSource := action.returnPin();
+ }
+ case(element.oclIsKindOf(Property)) {
+ graph.nodes += action := new ReadLinkAction(element.oclAsType(Property));
+ graph.resultSource := action.output->at(1);
+ };
};
} endif;
return action;
}
+helper InvocationExpression::isCollectionFunctionInvocation() : Boolean {
+ var referent := self.referent;
+ var template := referent.template();
+ return referent.isTemplateBinding() and
+ template.namespace() <> null and
+ template.namespace().equals(self.collectionFunctionsPackage());
+}
+
+query InvocationExpression::sequenceFunction() : Behavior {
+ var behavior : Behavior := null;
+ var name := self.referent.template().name();
+
+ if name <> "clear" then {
+ var sequenceFunctionName :=
+ switch {
+ case(name = "add") "Including";
+ case(name = "addAll") "Union";
+ case(name = "addAt") "IncludeAt";
+ case(name = "addAllAt") "IncludeAllAt";
+ case(name = "remove") "Excluding";
+ case(name = "removeAll") "Difference";
+ case(name = "removeOne") "ExcludingOne";
+ case(name = "removeAt") "ExcludeAt";
+ case(name = "replace") "Replacing";
+ case(name = "replaceOne") "ReplacingOne";
+ case(name = "replaceAt") "ReplacingAt";
+ else name.firstToUpper();
+ };
+ behavior := self.sequenceFunction(sequenceFunctionName);
+ } endif;
+
+ return behavior;
+}
+
+helper InvocationExpression::collectionFunctionsPackage() : ElementReference {
+ return self.resolveInLibrary("CollectionFunctions")![isPackage()];
+}
+
helper InvocationExpression::mapTuple(inout graph : ExpressionGraph, action : Action) : ActivityGraph {
return self.tuple.map toActivityGraph(graph, action, null, null);
}
@@ -606,32 +656,36 @@ mapping _Tuple::toActivityGraph(inout graph : ExpressionGraph, action : Action,
// Add collection and bit string conversions, if required.
self.mapConversions(inputGraph, expressionType, input.isCollectionConversion, input.isBitStringConversion);
- var inputPin := action.input->at(i);
- edges += new ObjectFlow(inputGraph.resultSource, inputPin);
-
- // Check for an index on the argument name (as opposed to the argument expression itself).
- var index := input.index;
- if index <> null or invocation.oclIsKindOf(LinkOperationExpression) and inputPin.isOrdered then {
- var indexSource : ActivityNode;
- if index = null then {
- inputGraph.nodes += var valueAction ::= new ValueSpecificationAction(self.literalUnlimited());
- indexSource := valueAction.result;
- } else {
- var indexGraph := index.map toActivityGraph();
- indexGraph.addTo(result);
- indexSource := indexGraph.resultSource;
- if self.isIntegerType(index.type) then {
- inputGraph.nodes += var callAction ::= new CallBehaviorAction(self.integerFunction("ToUnlimitedNatural"));
- inputGraph.edges += new ObjectFlow(inputGraph.resultSource, callAction.argument->at(1));
- indexSource := callAction.result->at(1);
+ // NOTE: For the mapping of CollectionFunctions::clear, the action will be a value specification action,
+ // with no input.
+ if i <= action.input->size() then {
+ var inputPin := action.input->at(i);
+ edges += new ObjectFlow(inputGraph.resultSource, inputPin);
+
+ // Check for an index on the argument name (as opposed to the argument expression itself).
+ var index := input.index;
+ if index <> null or invocation.oclIsKindOf(LinkOperationExpression) and inputPin.isOrdered then {
+ var indexSource : ActivityNode;
+ if index = null then {
+ inputGraph.nodes += var valueAction ::= new ValueSpecificationAction(self.literalUnlimited());
+ indexSource := valueAction.result;
+ } else {
+ var indexGraph := index.map toActivityGraph();
+ indexGraph.addTo(result);
+ indexSource := indexGraph.resultSource;
+ if self.isIntegerType(index.type) then {
+ inputGraph.nodes += var callAction ::= new CallBehaviorAction(self.integerFunction("ToUnlimitedNatural"));
+ inputGraph.edges += new ObjectFlow(inputGraph.resultSource, callAction.argument->at(1));
+ indexSource := callAction.result->at(1);
+ } endif;
} endif;
- } endif;
- // NOTE: This presumes that the "insertAt" or "destroyAt" pin comes directly after
- // the value pin in the list of input pins.
- i := i + 1;
- inputGraph.edges += new ObjectFlow(indexSource, action.input->at(i));
+ // NOTE: This presumes that the "insertAt" or "destroyAt" pin comes directly after
+ // the value pin in the list of input pins.
+ i := i + 1;
+ inputGraph.edges += new ObjectFlow(indexSource, action.input->at(i));
+ } endif;
} endif;
-
+
inputGraph.addTo(subgraph);
i := i + 1;
};
@@ -648,17 +702,22 @@ mapping _Tuple::toActivityGraph(inout graph : ExpressionGraph, action : Action,
outputParameters->forEach(parameter) {
var output := outputs![name = parameter.name()];
if output <> null and not output.expression.isNull() then {
- var outputGraph := object ExpressionGraph{};
+ var outputGraph := object ExpressionGraph{
+ resultSource := action.output->at(i)
+ };
+
var lhs := output.leftHandSide;
var lhsGraph := lhs.map toActivityGraph(objectSourceMap->get(output.name), indexSourceMap->get(output.name), -1);
lhsGraph.addTo(outputGraph);
-
- // Skip the return pin. The return parameter never has an output argument.
- outputGraph.resultSource := action.output->at(i);
- if outputGraph.resultSource = returnPin then {
+
+ if invocation.isCollectionFunctionInvocation() then {
+ graph.resultSource := lhsGraph.resultSource;
+ } else if outputGraph.resultSource = returnPin then {
+ // Unless this is the mapping of an in-place collection function invocation, skip a return pin.
+ // The return value is not normally given through a tuple argument.
i := i + 1;
outputGraph.resultSource := action.output->at(i);
- } endif;
+ } endif endif;
// Add collection and bit string conversion, if required.
self.mapConversions(outputGraph, parameter.type(), output.isCollectionConversion, output.isBitStringConversion);
@@ -1387,15 +1446,20 @@ mapping CastExpression::toActivityGraph() : ExpressionGraph
if type = null or
operandType <> null and operandType.conformsTo(self.type) and
- // The following condition is to treat up-casting of
- // naturals to unlimited naturals as a real conversion,
- // because naturals are represented as integers.
- not(self.isNaturalType(operandType) and self.isUnlimitedNaturalType(type)) or
+ // The following condition is to treat up-casting of
+ // naturals to unlimited naturals as a real conversion,
+ // because naturals are represented as integers.
+ not(self.isNaturalType(operandType) and self.isUnlimitedNaturalType(type)) or
// The following condition is an optimization to avoid
// generating an expansion region when the operand is known
// to be null.
- self.operand.isNull() then {
+ self.operand.isNull() or
+
+ // TODO: Implement casts to template parameters.
+ type.isTemplateParameter()
+
+ then {
// Up-cast, no conversion is necessary.
resultSource := operandGraph.resultSource;
@@ -1670,10 +1734,16 @@ mapping ClassificationExpression::toActivityGraph() : ExpressionGraph
var operandGraph := self.operand.map toActivityGraph();
operandGraph.addTo(result);
- var classifier := self.referent.toUml().oclAsType(Classifier);
- nodes += var action ::= new ReadIsClassifiedObjectAction(classifier, self.isDirect, self.booleanType().toType());
- edges += new ObjectFlow(operandGraph.resultSource, action._'object');
- resultSource := action.result;
+ if self.referent.isTemplateParameter() then {
+ // TODO: Implement classification check for template parameters.
+ nodes += var valueAction ::= new ValueSpecificationAction(self.literalBoolean(true));
+ resultSource := valueAction.result;
+ } else {
+ var classifier := self.referent.toUml().oclAsType(Classifier);
+ nodes += var action ::= new ReadIsClassifiedObjectAction(classifier, self.isDirect, self.booleanType().toType());
+ edges += new ObjectFlow(operandGraph.resultSource, action._'object');
+ resultSource := action.result;
+ } endif;
}
// Equality Expressions

Back to the top