Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Willink2016-11-03 09:44:12 +0000
committerEd Willink2016-11-04 11:58:19 +0000
commit58741457d4a4b0879eb46fef0679c01a0c9f79ec (patch)
tree75acc0a9036ba56e5ce97ce43b60886ab0df089f
parent25c67f635cc3fc3e44947c0c020ca2a48f8ab6c1 (diff)
downloadorg.eclipse.qvtd-58741457d4a4b0879eb46fef0679c01a0c9f79ec.tar.gz
org.eclipse.qvtd-58741457d4a4b0879eb46fef0679c01a0c9f79ec.tar.xz
org.eclipse.qvtd-58741457d4a4b0879eb46fef0679c01a0c9f79ec.zip
[506806] Compute Edge/Node isUnconditional() to avoid conditional
variable hoisting
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractMappingRegion.java216
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/BasicMappingRegion.java5
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java10
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java32
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NavigableEdge.java5
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java31
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/OperationRegion.java2
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/EdgeImpl.java5
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NavigableEdgeImpl.java18
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NodeImpl.java28
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java80
11 files changed, 382 insertions, 50 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractMappingRegion.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractMappingRegion.java
index 890d15358..5dc78086b 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractMappingRegion.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractMappingRegion.java
@@ -21,6 +21,7 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.qvtd.pivot.qvtbase.graphs.GraphStringBuilder;
import com.google.common.collect.Iterables;
@@ -129,6 +130,11 @@ public abstract class AbstractMappingRegion extends AbstractRegion implements Ma
* The subsets of guardVariables from which all guardVariables are to-one navigable.
*/
private /*@LazyNonNull*/ @Nullable List<@NonNull Node> headNodes = null;
+ private /*@LazyNonNull*/ @Nullable List<@NonNull Node> stronglyMatchedNodes = null;
+ private /*@LazyNonNull*/ @Nullable List<@NonNull Node> unconditionalNodes = null;
+ private /*@LazyNonNull*/ @Nullable List<@NonNull Node> conditionalNodes = null;
+ // private /*@LazyNonNull*/ @Nullable List<@NonNull Node> dependencyNodes = null;
+ private /*@LazyNonNull*/ @Nullable List<@NonNull Node> deadNodes = null;
protected AbstractMappingRegion(@NonNull MultiRegion multiRegion) {
super(multiRegion);
@@ -141,6 +147,9 @@ public abstract class AbstractMappingRegion extends AbstractRegion implements Ma
@Override
public void addEdge(@NonNull Edge edge) {
+ assert stronglyMatchedNodes == null;
+ assert unconditionalNodes == null;
+ assert conditionalNodes == null;
assert (basicGetSymbolName() == null) || !edge.isNavigation();
super.addEdge(edge);
}
@@ -153,14 +162,75 @@ public abstract class AbstractMappingRegion extends AbstractRegion implements Ma
@Override
public void addNode(@NonNull Node node) {
+ assert stronglyMatchedNodes == null;
+ assert unconditionalNodes == null;
+ assert conditionalNodes == null;
assert basicGetSymbolName() == null;
super.addNode(node);
}
+ /**
+ * Any node with an edge to an unconditional node that is not itself unconditional must be conditional.
+ */
+ private @NonNull Set<@NonNull Node> computeConditionalNodes(@NonNull Set<@NonNull Node> unconditionalNodes) {
+ Set<@NonNull Node> conditionalNodes = new HashSet<>();
+ Set<@NonNull Node> moreNodes = unconditionalNodes;
+ while (moreNodes.size() > 0) {
+ Set<@NonNull Node> moreMoreNodes = new HashSet<>();
+ for (@NonNull Node node : moreNodes) {
+ for (@NonNull Edge incomingEdge : node.getIncomingEdges()) {
+ Node sourceNode = incomingEdge.getSource();
+ if (!unconditionalNodes.contains(sourceNode) && conditionalNodes.add(sourceNode)) {
+ moreMoreNodes.add(sourceNode);
+ }
+ }
+ for (@NonNull Edge outgoingEdge : node.getOutgoingEdges()) {
+ Node targetNode = outgoingEdge.getTarget();
+ if (!unconditionalNodes.contains(targetNode) && conditionalNodes.add(targetNode)) {
+ moreMoreNodes.add(targetNode);
+ }
+ }
+ }
+ if (moreMoreNodes.size() <= 0) {
+ break;
+ }
+ moreNodes = moreMoreNodes;
+ }
+ this.conditionalNodes = new ArrayList<>(conditionalNodes);
+ Collections.sort(this.conditionalNodes, NameUtil.NAMEABLE_COMPARATOR);
+ return conditionalNodes;
+ }
+
+ /**
+ * Any dependency node transitively connected to a deopendency head contributes to the dependency nodes.
+ *
+ private @NonNull Set<@NonNull Node> computeDependencyNodes(@NonNull Iterable <@NonNull Node> headNodes) {
+ Set<@NonNull Node> dependencyNodes = new HashSet<>();
+ Iterable<@NonNull Node> moreNodes = headNodes;
+ while (!Iterables.isEmpty(moreNodes)) {
+ Set<@NonNull Node> moreMoreNodes = new HashSet<>();
+ for (@NonNull Node node : moreNodes) {
+ if (node.isDependency() && dependencyNodes.add(node)) {
+ for (@NonNull NavigableEdge edge : node.getNavigationEdges()) {
+ Node targetNode = edge.getTarget();
+ moreMoreNodes.add(targetNode);
+ }
+ }
+ }
+ if (moreMoreNodes.size() <= 0) {
+ break;
+ }
+ moreNodes = moreMoreNodes;
+ }
+ this.dependencyNodes = new ArrayList<>(dependencyNodes);
+ Collections.sort(this.dependencyNodes, NameUtil.NAMEABLE_COMPARATOR);
+ return dependencyNodes;
+ } */
+
protected @NonNull List<@NonNull Node> computeHeadNodes() {
//
// A head node is reachable from very few nodes, typically just itself, occasionally from a small group of mutually bidirectional nodes,
- // so we searcvh for the least reachable nodes taking care to avoid hazrads from the source-to-target / target-source asymmetry.
+ // so we search for the least reachable nodes taking care to avoid hazrads from the source-to-target / target-source asymmetry.
//
List<@NonNull Node> navigableNodes = new ArrayList<>();
for (@NonNull Node node : getNodes()) {
@@ -283,9 +353,138 @@ public abstract class AbstractMappingRegion extends AbstractRegion implements Ma
}
}
assert debugHeadNodes.equals(new HashSet<>(headNodes));
+ //
+ computeUtilities(headNodes);
return headNodes;
}
+ private void computeStronglyMatchedNodes(@NonNull Node sourceNode, @NonNull Set<@NonNull Node> stronglyMatchedNodes) {
+ for (@NonNull NavigableEdge edge : sourceNode.getNavigationEdges()) {
+ Node targetNode = edge.getTarget();
+ if (isMatchable(targetNode)) {
+ boolean targetIsStronglyMatched = edge.isRequired();
+ if (targetIsStronglyMatched && stronglyMatchedNodes.add(targetNode)) {
+ computeStronglyMatchedNodes(targetNode, stronglyMatchedNodes);
+ }
+ }
+ }
+ }
+
+ private @NonNull Set<@NonNull Node> computeStronglyMatchedNodes(@NonNull Iterable<@NonNull Node> headNodes) {
+ Set<@NonNull Node> stronglyMatchedNodes = new HashSet<>();
+ for (@NonNull Node headNode : headNodes) {
+ if (!headNode.isDependency() && !headNode.isTrue() && stronglyMatchedNodes.add(headNode)) {
+ computeStronglyMatchedNodes(headNode, stronglyMatchedNodes);
+ }
+ }
+ this.stronglyMatchedNodes = new ArrayList<>(stronglyMatchedNodes);
+ Collections.sort(this.stronglyMatchedNodes, NameUtil.NAMEABLE_COMPARATOR);
+ return stronglyMatchedNodes;
+ }
+
+ private @NonNull Set<@NonNull Node> computeUnconditionalNodes(@NonNull Iterable<@NonNull Node> headNodes) {
+ @NonNull Set<@NonNull Node> unconditionalNodes = Sets.newHashSet(headNodes);
+ Iterables.addAll(unconditionalNodes, getNewNodes());
+ for (@NonNull Edge edge : getRealizedEdges()) {
+ Node sourceNode = edge.getSource();
+ assert isUnconditionable(sourceNode);
+ unconditionalNodes.add(sourceNode);
+ Node targetNode = edge.getTarget();
+ assert isUnconditionable(targetNode);
+ unconditionalNodes.add(targetNode);
+ }
+ Set<@NonNull Node> moreUnconditionalNodes = new HashSet<>(unconditionalNodes);
+ while (moreUnconditionalNodes.size() > 0) {
+ Set<@NonNull Node> moreMoreNodes = new HashSet<>();
+ for (@NonNull Node node : moreUnconditionalNodes) {
+ for (@NonNull Edge incomingEdge : node.getIncomingEdges()) {
+ Node sourceNode = incomingEdge.getSource();
+ if (!isUnconditionable(sourceNode)) {}
+ else if (incomingEdge.isNavigation()) {
+ if (unconditionalNodes.add(sourceNode)) {
+ moreMoreNodes.add(sourceNode);
+ }
+ }
+ else if (incomingEdge.isComputation()) {
+ if (!isConditionalEdge(incomingEdge) && unconditionalNodes.add(sourceNode)) {
+ moreMoreNodes.add(sourceNode);
+ }
+ }
+ else {
+ System.out.println("Unsupported incoming edge in " + this + " : " + incomingEdge);
+ }
+ }
+ for (@NonNull Edge outgoingEdge : node.getOutgoingEdges()) {
+ Node targetNode = outgoingEdge.getTarget();
+ if (!isUnconditionable(targetNode)) {}
+ else if (outgoingEdge.isNavigation()) {
+ if (((NavigableEdge)outgoingEdge).isRequired() && unconditionalNodes.add(targetNode)) {
+ moreMoreNodes.add(targetNode);
+ }
+ }
+ else if (outgoingEdge.isComputation()) {}
+ else {
+ System.out.println("Unsupported outgoing edge in " + this + " : " + outgoingEdge);
+ }
+ }
+ }
+ if (moreMoreNodes.size() <= 0) {
+ break;
+ }
+ moreUnconditionalNodes = moreMoreNodes;
+ }
+ this.unconditionalNodes = new ArrayList<>(unconditionalNodes);
+ Collections.sort(this.unconditionalNodes, NameUtil.NAMEABLE_COMPARATOR);
+ return unconditionalNodes;
+ }
+
+ private void computeUtilities(@NonNull Iterable<@NonNull Node> headNodes) { // FIXME remove assertions after 1-Jan-2017
+ Set<@NonNull Node> stronglyMatchedNodes = computeStronglyMatchedNodes(headNodes);
+ Set<@NonNull Node> unconditionalNodes = computeUnconditionalNodes(headNodes);
+ Set<@NonNull Node> conditionalNodes = computeConditionalNodes(unconditionalNodes);
+ // Set<@NonNull Node> dependencyNodes = computeDependencyNodes(headNodes);
+ Set<@NonNull Node> deadNodes = null;
+ //
+ for (@NonNull Node node : getNodes()) {
+ if (stronglyMatchedNodes.contains(node)) {
+ node.setUtility(Node.Utility.STRONGLY_MATCHED);
+ assert unconditionalNodes.contains(node);
+ // assert !dependencyNodes.contains(node);
+ }
+ else if (unconditionalNodes.contains(node) && !node.isDependency()) {
+ node.setUtility(Node.Utility.WEAKLY_MATCHED);
+ // assert !dependencyNodes.contains(node);
+ }
+ else if (conditionalNodes.contains(node)) {
+ node.setUtility(Node.Utility.CONDITIONAL);
+ // assert !dependencyNodes.contains(node);
+ }
+ else if (node.isDependency()) {
+ node.setUtility(Node.Utility.DEPENDENCY);
+ }
+ else {
+ System.err.println("Dead node in " + this + " : " + node);
+ if (deadNodes == null) {
+ deadNodes = new HashSet<>();
+ }
+ deadNodes.add(node);
+ node.setUtility(Node.Utility.DEAD);
+ toString();
+ }
+ }
+ if (deadNodes != null) {
+ this.deadNodes = new ArrayList<>(deadNodes);
+ Collections.sort(this.deadNodes, NameUtil.NAMEABLE_COMPARATOR);
+ }
+ for (@NonNull Node node : getNodes()) {
+ boolean isMatched = node.isMatched();
+ boolean isUnconditional = node.isUnconditional();
+ if (isMatched != isUnconditional) {
+ System.out.println("Inconsistently isMatched in " + this + " : " + node);
+ }
+ }
+ }
+
@Override
public @NonNull String getColor() {
return "green";
@@ -300,6 +499,21 @@ public abstract class AbstractMappingRegion extends AbstractRegion implements Ma
return headNodes2;
}
+ private boolean isConditionalEdge(@NonNull Edge edge) {
+ String edgeName = edge.getName();
+ return ExpressionAnalyzer.IF_THEN_NAME.equals(edgeName)
+ || ExpressionAnalyzer.IF_ELSE_NAME.equals(edgeName)
+ || ExpressionAnalyzer.LOOP_BODY_NAME.equals(edgeName);
+ }
+
+ private boolean isMatchable(@NonNull Node node) {
+ return node.isExplicitNull() || node.isPattern();
+ }
+
+ private boolean isUnconditionable(@NonNull Node node) {
+ return !node.isIterator();
+ }
+
@Override
public void resetHead(@NonNull Node headNode) {
boolean wasRemoved = getHeadNodes().remove(headNode);
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/BasicMappingRegion.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/BasicMappingRegion.java
index 2e88abaf8..69e4d4dca 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/BasicMappingRegion.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/BasicMappingRegion.java
@@ -52,6 +52,7 @@ public class BasicMappingRegion extends AbstractMappingRegion
{
public static @NonNull BasicMappingRegion createMappingRegion(@NonNull MultiRegion multiRegion, @NonNull Mapping mapping) {
BasicMappingRegion mappingRegion = new BasicMappingRegion(multiRegion, mapping);
+ @SuppressWarnings("unused")String name = mappingRegion.getName();
mappingRegion.initialize();
return mappingRegion;
}
@@ -310,7 +311,7 @@ public class BasicMappingRegion extends AbstractMappingRegion
if ((ownedInit instanceof OperationCallExp) && initNode.isOperation()) {
if (QVTbaseUtil.isIdentification(((OperationCallExp)ownedInit).getReferredOperation())) {
Node stepNode = RegionUtil.createRealizedStepNode(this, variable);
- RegionUtil.createExpressionEdge(initNode, "«equals»", stepNode);
+ RegionUtil.createExpressionEdge(initNode, ExpressionAnalyzer.EQUALS_NAME, stepNode);
initNode = stepNode;
}
// else if (variable.getType() instanceof CollectionType) {
@@ -321,7 +322,7 @@ public class BasicMappingRegion extends AbstractMappingRegion
else {
// Node stepNode = RegionUtil.STEP.createNode(this, variable.getName(), (OperationCallExp)ownedInit, initNode);
Node stepNode = RegionUtil.createLoadedStepNode(this, variable);
- RegionUtil.createExpressionEdge(initNode, "«equals»", stepNode);
+ RegionUtil.createExpressionEdge(initNode, ExpressionAnalyzer.EQUALS_NAME, stepNode);
initNode = stepNode;
}
}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java
index 2a0d0e955..5f67739a4 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java
@@ -115,7 +115,10 @@ public interface Edge extends GraphStringBuilder.GraphEdge, Nameable, Visitable
* Return true if after execution this edge exactly corresponds to a relationship between its matching ends.
* Conversely return false if this edge is a conditional execution path or its ends my be optional nulls.
* Collections are never null-valued, not even empty collections.
+ *
+ * @deprecated use isUnconditional or getUtility
*/
+ @Deprecated
boolean isMatched();
/**
@@ -158,6 +161,13 @@ public interface Edge extends GraphStringBuilder.GraphEdge, Nameable, Visitable
*/
boolean isSecondary();
+
+ /**
+ * Return true is this edge is used as part of an unconditional navigation or computation.
+ * i.e. it is not part of a loop or dependent upon if conditions.
+ */
+ boolean isUnconditional();
+
void setSource(@NonNull Node sourceNode);
void setTarget(@NonNull Node targetNode);
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java
index 736af6814..c44872e8b 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java
@@ -71,9 +71,15 @@ import com.google.common.collect.Iterables;
public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull Node, @NonNull BasicMappingRegion>
{
- private static final @NonNull String @NonNull [] ifArgNames = new @NonNull String[]{"«condition»", "«then»", "«else»"};
+ public static final @NonNull String EQUALS_NAME = "«equals»";
+ public static final @NonNull String IF_CONDITION_NAME = "«condition»";
+ public static final @NonNull String IF_ELSE_NAME = "«else»";
+ public static final @NonNull String IF_THEN_NAME = "«then»";
+ public static final @NonNull String LOOP_BODY_NAME = "«body»";
+ public static final @NonNull String LOOP_ITERATOR_NAME = "«iterator»";
+ private static final @NonNull String @NonNull [] ifArgNames = new @NonNull String[]{IF_CONDITION_NAME, IF_THEN_NAME, IF_ELSE_NAME};
private static final @NonNull String @NonNull [] mapArgNames = new @NonNull String[]{"«key»", "«value»"};
- private static final @NonNull String @NonNull [] nullArgNames = new @NonNull String[]{"«equals»"};
+ private static final @NonNull String @NonNull [] nullArgNames = new @NonNull String[]{EQUALS_NAME};
private static final @NonNull String @NonNull [] rangeArgNames = new @NonNull String[]{"«first»", "«last»"};
private static final @NonNull String @NonNull [] srcArgNames = new @NonNull String[]{"«source»", "«arg»"};
@@ -459,12 +465,12 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
if (navigationAssignment == null) {
Node stepNode = createNavigableDataTypeNode(sourceNode, source2targetProperty);
navigationEdge = createNavigationOrRealizedEdge(sourceNode, source2targetProperty, stepNode, navigationAssignment);
- createExpressionEdge(targetNode, "«equals»", stepNode);
+ createExpressionEdge(targetNode, EQUALS_NAME, stepNode);
}
else {
Node stepNode = createNavigableDataTypeNode(targetNode, navigationAssignment);
navigationEdge = createNavigationOrRealizedEdge(sourceNode, source2targetProperty, stepNode, navigationAssignment);
- createExpressionEdge(targetNode, "«equals»", stepNode);
+ createExpressionEdge(targetNode, EQUALS_NAME, stepNode);
}
}
}
@@ -472,7 +478,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
else {
// if (!navigationEdge.isRealized() || targetNode.isRealized()) {
if (targetNode != navigationEdge.getTarget()) {
- createExpressionEdge(targetNode, "«equals»", navigationEdge.getTarget());
+ createExpressionEdge(targetNode, EQUALS_NAME, navigationEdge.getTarget());
}
}
return navigationEdge;
@@ -484,7 +490,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
if (navigationEdge != null) {
Node target = navigationEdge.getTarget();
if (target != targetNode) {
- createExpressionEdge(targetNode, "«equals»", target);
+ createExpressionEdge(targetNode, EQUALS_NAME, target);
}
}
else {
@@ -509,12 +515,12 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
// Type type = source2targetProperty.getType();
/* if (type instanceof DataType) {
Node attributeNode = createRealizedDataTypeNode(sourceNode, source2targetProperty);
- createExpressionEdge(targetNode, "«equals»", attributeNode);
+ createExpressionEdge(targetNode, EQUALS_NAME, attributeNode);
targetNode = attributeNode;
}
else {
Node stepNode = createPredicatedClassNode(sourceNode, navigationAssignment);
- createExpressionEdge(targetNode, "«equals»", stepNode);
+ createExpressionEdge(targetNode, EQUALS_NAME, stepNode);
targetNode = stepNode;
} */
navigationEdge = createNavigationOrRealizedEdge(sourceNode, source2targetProperty, targetNode, navigationAssignment);
@@ -527,10 +533,10 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
assert valueNode.isRealized();
Type type = source2targetProperty.getType();
if (type instanceof DataType) {
- createRealizedExpressionEdge(targetNode, "«equals»", valueNode);
+ createRealizedExpressionEdge(targetNode, EQUALS_NAME, valueNode);
}
else {
- createExpressionEdge(targetNode, "«equals»", valueNode);
+ createExpressionEdge(targetNode, EQUALS_NAME, valueNode);
}
return navigationEdge;
}
@@ -649,7 +655,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
Type iteratorType = iterator.getType();
assert iteratorType != null;
// Property iterateProperty = context.getSchedulerConstants().getIterateProperty(iteratorType);
- createIteratedEdge(sourceNode, "«iterator»", iteratorNode);
+ createIteratedEdge(sourceNode, LOOP_ITERATOR_NAME, iteratorNode);
argNodes[i++] = iteratorNode;
}
if (loopExp instanceof IterateExp) {
@@ -659,7 +665,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
Type iteratorType = accumulator.getType();
assert iteratorType != null;
// Property iterateProperty = context.getSchedulerConstants().getIterateProperty(iteratorType);
- createIteratedEdge(sourceNode, "«iterator»", iteratorNode);
+ createIteratedEdge(sourceNode, LOOP_ITERATOR_NAME, iteratorNode);
argNodes[i++] = iteratorNode;
}
Node bodyNode = getConditionalExpressionAnalyzer().analyze(loopExp.getOwnedBody());
@@ -667,7 +673,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
String iterationName = "«" + loopExp.getReferredIteration().getName() + "»";
Node accumulateNode = createOperationNode(iterationName, loopExp, argNodes);
createExpressionEdge(sourceNode, "«source»", accumulateNode);
- createExpressionEdge(bodyNode, "«body»", accumulateNode);
+ createExpressionEdge(bodyNode, LOOP_BODY_NAME, accumulateNode);
i = 1;
for (@NonNull Variable iterator : ownedIterators) {
Node iteratorNode = argNodes[i++];
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NavigableEdge.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NavigableEdge.java
index de9aac7bc..ba969ed01 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NavigableEdge.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/NavigableEdge.java
@@ -44,6 +44,11 @@ public interface NavigableEdge extends Edge, ConnectionEnd
*/
@NonNull Property getProperty();
+ /**
+ * Return true if this edge has a non-zero target lower bound or if the target node isRequired.
+ */
+ boolean isRequired();
+
void removeIncomingConnection(@NonNull EdgeConnection edgeConnection);
void removeOutgoingConnection(@NonNull EdgeConnection edgeConnection);
} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java
index 71f15e42c..a00e4a582 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java
@@ -27,6 +27,20 @@ import org.eclipse.qvtd.pivot.qvtbase.graphs.GraphStringBuilder;
*/
public interface Node extends ConnectionEnd, GraphStringBuilder.GraphNode, Nameable, Visitable
{
+ /**
+ * The prioritized utility of each node.
+ */
+ public enum Utility {
+ STRONGLY_MATCHED, // Reachable by to-1 navigation from a head node, or by to-? to an ExplicitNull
+ WEAKLY_MATCHED, // else unconditionally used in a computation or navigation
+ // UNCONDITIONALLY_PREDICATING, // else always computable as part of a predicate
+ // CONDITIONALLY_PREDICATING, // else selectively computable as part of a predicate depending on if conditions
+ // UNCONDITIONALLY_COMPUTED, // else always computable
+ CONDITIONAL, // else selectively computable depending on if conditions / loops
+ DEPENDENCY, // else solely used to establish a dependency
+ DEAD // else never used
+ }
+
void addIncomingConnection(@NonNull NodeConnection connection);
void addIncomingEdge(@NonNull Edge edge);
void addOutgoingConnection(@NonNull NodeConnection connection);
@@ -95,6 +109,7 @@ public interface Node extends ConnectionEnd, GraphStringBuilder.GraphNode, Namea
@NonNull SchedulerConstants getSchedulerConstants();
@NonNull Iterable<@NonNull TypedElement> getTypedElements();
@NonNull Iterable<@NonNull Node> getUsedBindingSources();
+ @NonNull Utility getUtility();
/**
* Return true if this node is a Class object.
@@ -154,7 +169,10 @@ public interface Node extends ConnectionEnd, GraphStringBuilder.GraphNode, Namea
* Return true if after execution this node exactly corresponds to a non-null object or to a non-null value or to an explicit null.
* Conversely return false if this node is optionally null or part of a conditional expression evaluation.
* Collections are never null-valued, not even empty collections.
+ *
+ * @deprecated use isUnconditional or getUtility
*/
+ @Deprecated
boolean isMatched();
/**
@@ -190,6 +208,11 @@ public interface Node extends ConnectionEnd, GraphStringBuilder.GraphNode, Namea
boolean isRealized();
/**
+ * Return true if this is a required element, i.e. it has a TypedElement with a non-zetro lowrr bound.
+ */
+ boolean isRequired();
+
+ /**
* Return true if this node is a speculated middle trace element that may havew benn created in anticipation
* of other dependencies.
*
@@ -210,6 +233,12 @@ public interface Node extends ConnectionEnd, GraphStringBuilder.GraphNode, Namea
*/
boolean isTrue();
+ /**
+ * Return true if this node is unconditionally used in a computation of navigation. .e it does not form
+ * part of a loop or a then/else arm.
+ */
+ boolean isUnconditional();
+
boolean refineClassDatumAnalysis(@NonNull ClassDatumAnalysis newClassDatumAnalysis);
void removeIncomingConnection(@NonNull NodeConnection connection);
void removeIncomingEdge(@NonNull Edge edge);
@@ -226,6 +255,8 @@ public interface Node extends ConnectionEnd, GraphStringBuilder.GraphNode, Namea
*/
void setHead();
+ void setUtility(@NonNull Utility utility);
+
void toGraph(@NonNull GraphStringBuilder s);
@Override
@NonNull String toString();
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/OperationRegion.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/OperationRegion.java
index 8317895ba..bd5df14d5 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/OperationRegion.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/OperationRegion.java
@@ -67,7 +67,7 @@ public class OperationRegion extends AbstractRegion
dependencyNode = selfNode;
//
resultNode = RegionUtil.createStepNode("result", operationCallExp, dependencyNode, false);
- RegionUtil.createExpressionEdge(dependencyNode, "«equals»", resultNode);
+ RegionUtil.createExpressionEdge(dependencyNode, ExpressionAnalyzer.EQUALS_NAME, resultNode);
//
List<Variable> ownedParameters = specification.getOwnedParameters();
List<OCLExpression> ownedArguments = operationCallExp.getOwnedArguments();
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/EdgeImpl.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/EdgeImpl.java
index 23d0e96e8..12bb83e90 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/EdgeImpl.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/EdgeImpl.java
@@ -311,6 +311,11 @@ public abstract class EdgeImpl implements Edge
return false;
}
+ @Override
+ public boolean isUnconditional() {
+ return ClassUtil.nonNullState(sourceNode).isUnconditional() && ClassUtil.nonNullState(targetNode).isUnconditional();
+ }
+
protected void mergeRole(@NonNull EdgeRole edgeRole) {
if (this.edgeRole != edgeRole) {
assert this.edgeRole != null;
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NavigableEdgeImpl.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NavigableEdgeImpl.java
index 49e2488be..93c8c4ae6 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NavigableEdgeImpl.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NavigableEdgeImpl.java
@@ -195,6 +195,24 @@ public abstract class NavigableEdgeImpl extends EdgeImpl implements NavigableEdg
}
@Override
+ public boolean isRequired() {
+ Node targetNode = getTarget();
+ Property property = getProperty();
+ if (targetNode.isExplicitNull()) {
+ return true; // ?? a degenerate typedElement.isIsRequired()
+ }
+ else if (property.isIsRequired()) {
+ return true;
+ }
+ else if (targetNode.isRequired()) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
public boolean isSecondary() {
return isSecondary;
}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NodeImpl.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NodeImpl.java
index 87531cff8..5a8784889 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NodeImpl.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/impl/NodeImpl.java
@@ -87,6 +87,8 @@ public abstract class NodeImpl implements Node
private final @NonNull List<@NonNull TypedElement> typedElements = new ArrayList<@NonNull TypedElement>();
+ private /*@LazyNonNull*/ Utility utility = null; // Set by post region build analysis
+
@Override
public <R> R accept(@NonNull Visitor<R> visitor) {
return visitor.visitNode(this);
@@ -531,6 +533,11 @@ public abstract class NodeImpl implements Node
return sources;
}
+ @Override
+ public @NonNull Utility getUtility() {
+ return ClassUtil.nonNullState(utility);
+ }
+
protected void initialize(@NonNull NodeRole nodeRole, @NonNull Region region, @NonNull String name, @NonNull ClassDatumAnalysis classDatumAnalysis) {
this.nodeRole = nodeRole;
this.region = region;
@@ -639,6 +646,16 @@ public abstract class NodeImpl implements Node
}
@Override
+ public boolean isRequired() {
+ for (@NonNull TypedElement typedElement : getTypedElements()) {
+ if (typedElement.isIsRequired()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
public boolean isSpeculated() {
assert nodeRole != null;
return nodeRole.isSpeculated();
@@ -656,6 +673,11 @@ public abstract class NodeImpl implements Node
}
@Override
+ public boolean isUnconditional() {
+ return (utility == Utility.STRONGLY_MATCHED) || (utility == Utility.WEAKLY_MATCHED);
+ }
+
+ @Override
public boolean refineClassDatumAnalysis(@NonNull ClassDatumAnalysis newClassDatumAnalysis) {
ClassDatumAnalysis classDatumAnalysis2 = classDatumAnalysis;
assert classDatumAnalysis2 != null;
@@ -753,6 +775,12 @@ public abstract class NodeImpl implements Node
}
@Override
+ public void setUtility(@NonNull Utility utility) {
+ assert this.utility == null;
+ this.utility = utility;
+ }
+
+ @Override
public void toGraph(@NonNull GraphStringBuilder s) {
s.appendNode(this);
}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java
index 37e97f214..771d1d31d 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java
@@ -70,7 +70,6 @@ import org.eclipse.qvtd.compiler.internal.qvtp2qvts.NavigableEdge;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.Node;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.NodeConnection;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.Region;
-import org.eclipse.qvtd.compiler.internal.qvtp2qvts.RegionUtil;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.SchedulerConstants;
import org.eclipse.qvtd.pivot.qvtbase.Function;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
@@ -587,13 +586,13 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping
// this.expressionCreator = new ExpressionCreator();
// this.inlineExpressionCreator = new InlineExpressionCreator();
@SuppressWarnings("unused")String name = region.getName();
- createHeadAndGuardNodeVariables();
- createNavigablePredicates();
- createExternalPredicates();
- createRealizedVariables();
- createPropertyAssignments();
- createAddStatements();
- createObservedProperties();
+ createHeadAndGuardNodeVariables(); // BLUE/CYAN guard/append nodes
+ createNavigablePredicates(); // BLUE/CYAN navigable nodes and edges
+ createExternalPredicates(); // BLUE/CYAN computations involving a true guard node
+ createRealizedVariables(); // GREEN nodes
+ createPropertyAssignments(); // GREEN edges
+ createAddStatements(); // export to append nodes
+ createObservedProperties(); // wrap observable clauses around hazardous accesses
}
/* @Override
@@ -821,7 +820,7 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping
}
}
guardNodes.addAll(headNodes);
- for (@NonNull Node guardNode : region.getOldNodes()) {
+ /* for (@NonNull Node guardNode : region.getOldNodes()) {
if (!guardNodes.contains(guardNode)) {
NodeConnection connection = guardNode.getIncomingUsedConnection();
if (connection != null) { // null for LOADED
@@ -844,12 +843,12 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping
}
}
}
- }
+ } */
Collections.sort(guardNodes, NameUtil.NAMEABLE_COMPARATOR);
for (@NonNull Node guardNode : guardNodes) {
- if (!guardNode.isDependency()) {
- createGuardParameter(guardNode);
- }
+ assert !guardNode.isDependency();
+ createGuardParameter(guardNode);
+ // }
}
//
// Create any connectionVariable guards
@@ -930,9 +929,7 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping
//
List<@NonNull NavigableEdge> forestEdges = new ArrayList<>();
for (@NonNull NavigableEdge edge : region.getNavigationEdges()) {
- Node sourceNode = edge.getSource();
- Node targetNode = edge.getTarget();
- if (!sourceNode.isIterator() && !sourceNode.isDependency() && !targetNode.isIterator() && RegionUtil.isUnconditional(edge)) { // FIXME provide a better isExpression capability for pattern nodes
+ if (edge.isUnconditional()) {
forestEdges.add(edge);
}
}
@@ -1173,23 +1170,6 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping
return false;
}*/
- private boolean isHazardousWrite(@NonNull NavigableEdge edge) {
- Node sourceNode = edge.getSource();
- Property asProperty = edge.getProperty();
- TypedModel typedModel = sourceNode.getClassDatumAnalysis().getTypedModel();
- Iterable<@NonNull NavigableEdge> enforcedEdges = region.getEnforcedEdges(typedModel);
- if (enforcedEdges != null) {
- Property asOppositeProperty = asProperty.getOpposite();
- for (@NonNull NavigableEdge enforcedEdge : enforcedEdges) {
- Property edgeProperty = enforcedEdge.getProperty();
- if ((edgeProperty == asProperty) || (edgeProperty == asOppositeProperty)) {
- return true;
- }
- }
- }
- return false;
- }
-
private void createRealizedVariables() {
for (@NonNull Node newNode : region.getNewNodes()) {
if (newNode.isPattern() && newNode.isClass()) {
@@ -1345,6 +1325,40 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping
return false;
}
+ /* private boolean isHazardousRead(@NonNull NavigableEdge edge) {
+ Node sourceNode = edge.getSource();
+ Property asProperty = edge.getProperty();
+ TypedModel typedModel = sourceNode.getClassDatumAnalysis().getTypedModel();
+ Iterable<@NonNull NavigableEdge> checkedEdges = region.getCheckedEdges(typedModel);
+ if (checkedEdges != null) {
+ Property asOppositeProperty = asProperty.getOpposite();
+ for (@NonNull NavigableEdge checkedEdge : checkedEdges) {
+ Property edgeProperty = checkedEdge.getProperty();
+ if ((edgeProperty == asProperty) || (edgeProperty == asOppositeProperty)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }*/
+
+ private boolean isHazardousWrite(@NonNull NavigableEdge edge) {
+ Node sourceNode = edge.getSource();
+ Property asProperty = edge.getProperty();
+ TypedModel typedModel = sourceNode.getClassDatumAnalysis().getTypedModel();
+ Iterable<@NonNull NavigableEdge> enforcedEdges = region.getEnforcedEdges(typedModel);
+ if (enforcedEdges != null) {
+ Property asOppositeProperty = asProperty.getOpposite();
+ for (@NonNull NavigableEdge enforcedEdge : enforcedEdges) {
+ Property edgeProperty = enforcedEdge.getProperty();
+ if ((edgeProperty == asProperty) || (edgeProperty == asOppositeProperty)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
@Override
public boolean isInfinite() {
if (region.getRecursionEdges().iterator().hasNext()) { // FIXME unduly pessimistic

Back to the top