diff options
author | Ed Willink | 2017-04-19 17:48:02 +0000 |
---|---|---|
committer | Ed Willink | 2017-05-14 05:22:21 +0000 |
commit | c7530de7d233bbab1a71de65a6351643c6fed5f0 (patch) | |
tree | 9decf1ad1819e93a56f27a2b0febc4c29c82fb06 | |
parent | ef5f54b3f5360aa094aff62eae215dbbc1f06ee6 (diff) | |
download | org.eclipse.qvtd-c7530de7d233bbab1a71de65a6351643c6fed5f0.tar.gz org.eclipse.qvtd-c7530de7d233bbab1a71de65a6351643c6fed5f0.tar.xz org.eclipse.qvtd-c7530de7d233bbab1a71de65a6351643c6fed5f0.zip |
[514590] speculate only the trace node
4 files changed, 95 insertions, 25 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtm2qvts/RegionHelper.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtm2qvts/RegionHelper.java index 7fea8f564..b305b3401 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtm2qvts/RegionHelper.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtm2qvts/RegionHelper.java @@ -218,7 +218,7 @@ public class RegionHelper return dependencyNodes; } */ - protected @NonNull List<@NonNull Node> computeHeadNodes(@NonNull MappingRegion mappingRegion) { + 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 search for the least reachable nodes taking care to avoid hazards from the source-to-target / target-source asymmetry. @@ -265,6 +265,28 @@ public class RegionHelper // targetClosure.add(computationEdge.getSource()); // } } + List<@NonNull Node> headNodes = computeHeadNodes(targetFromSourceClosure); + // + // Check head node consistency + // + Set<@NonNull Node> debugHeadNodes = new HashSet<>(); + for (@NonNull Node node : QVTscheduleUtil.getOwnedNodes(mappingRegion)) { + if (node.isTrue() || node.isDependency()) { + debugHeadNodes.add(node); + node.setHead(); + assert !headNodes.contains(node); + headNodes.add(node); + } + else if (node.isHead()) { + debugHeadNodes.add(node); + } + } + assert debugHeadNodes.equals(new HashSet<>(headNodes)); + return headNodes; + } + + public @NonNull List<@NonNull Node> computeHeadNodes(@NonNull Map<@NonNull Node, @NonNull Set<@NonNull Node>> targetFromSourceClosure) { + Iterable <@NonNull Node> navigableNodes = targetFromSourceClosure.keySet(); // // Ripple the local target-from-source closure to compute the overall target-from-source closure. // @@ -330,22 +352,6 @@ public class RegionHelper headNodes.add(headNode); } // - // Check head node consistency - // - Set<@NonNull Node> debugHeadNodes = new HashSet<>(); - for (@NonNull Node node : QVTscheduleUtil.getOwnedNodes(mappingRegion)) { - if (node.isTrue() || node.isDependency()) { - debugHeadNodes.add(node); - node.setHead(); - assert !headNodes.contains(node); - headNodes.add(node); - } - else if (node.isHead()) { - debugHeadNodes.add(node); - } - } - assert debugHeadNodes.equals(new HashSet<>(headNodes)); - // return headNodes; } @@ -525,7 +531,7 @@ public class RegionHelper } public @NonNull List<@NonNull Node> initHeadNodes() { - List<@NonNull Node> headNodes = computeHeadNodes(mappingRegion); + List<@NonNull Node> headNodes = computeHeadNodes(); ((MappingRegionImpl)mappingRegion).getHeadNodes2().addAll(headNodes); return headNodes; } diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/Partitioner.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/Partitioner.java index 93519712c..f43266f9f 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/Partitioner.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/Partitioner.java @@ -23,6 +23,7 @@ import org.eclipse.ocl.pivot.Property; import org.eclipse.qvtd.compiler.CompilerProblem; import org.eclipse.qvtd.compiler.ProblemHandler; import org.eclipse.qvtd.compiler.internal.qvtm2qvts.QVTm2QVTs; +import org.eclipse.qvtd.compiler.internal.qvtm2qvts.RegionHelper; import org.eclipse.qvtd.compiler.internal.qvtm2qvts.RegionUtil; import org.eclipse.qvtd.compiler.internal.utilities.CompilerUtil; import org.eclipse.qvtd.pivot.qvtschedule.Edge; @@ -91,12 +92,16 @@ public class Partitioner } private static void gatherCorrolaries(@NonNull Set<@NonNull Property> corrolaryProperties, @NonNull MappingRegion region) { + List<@NonNull Node> middleNodes = new ArrayList<>(); for (@NonNull Node node : RegionUtil.getOwnedNodes(region)) { if (!node.isTrue() && node.isPattern() && node.isRealized() && RegionUtil.getClassDatumAnalysis(node).getDomainUsage().isMiddle()) { - for (@NonNull NavigableEdge edge : node.getNavigationEdges()) { - if (edge.isRealized() && edge.getEdgeTarget().isRealized()) { - corrolaryProperties.add(RegionUtil.getProperty(edge)); - } + middleNodes.add(node); + } + } + for (@NonNull Node node : middleNodes) { + for (@NonNull NavigableEdge edge : node.getNavigationEdges()) { + if (edge.isRealized() && edge.getEdgeTarget().isRealized()) { + corrolaryProperties.add(RegionUtil.getProperty(edge)); } } } @@ -117,6 +122,7 @@ public class Partitioner private final @NonNull Set<@NonNull NavigableEdge> navigableEdges = new HashSet<>(); private final @NonNull Set<@NonNull Edge> realizedEdges = new HashSet<>(); private final @NonNull List<@NonNull Edge> realizedOutputEdges = new ArrayList<>(); + private final @Nullable Node traceNode; private final @NonNull List<@NonNull Node> trueNodes = new ArrayList<>(); private boolean hasLoadedNodes = false; @@ -153,6 +159,7 @@ public class Partitioner this.region = region; this.corrolaryProperties = corrolaryProperties; analyzeNodes(); + this.traceNode = analyzeTraceNode(); analyzeEdges(); } @@ -288,6 +295,39 @@ public class Partitioner } } + private @Nullable Node analyzeTraceNode() { + if (realizedMiddleNodes.size() == 0) { + return null; + } + if (realizedMiddleNodes.size() == 1) { + return realizedMiddleNodes.get(0); + } + // + // Compute the Set of all source nodes from which each target can be reached by transitive to-one navigation. + // + Map<@NonNull Node, @NonNull Set<@NonNull Node>> targetFromSourceClosure = new HashMap<>(); + for (@NonNull Node targetNode : realizedMiddleNodes) { + targetFromSourceClosure.put(targetNode, Sets.newHashSet(targetNode)); + } + for (@NonNull Node sourceNode : realizedMiddleNodes) { + for (@NonNull NavigableEdge navigationEdge : sourceNode.getRealizedNavigationEdges()) { + Node targetNode = navigationEdge.getEdgeTarget(); + Set<@NonNull Node> sourceClosure = targetFromSourceClosure.get(targetNode); + if (sourceClosure != null) { + sourceClosure.add(sourceNode); + } + } + } + RegionHelper regionHelper = new RegionHelper(region); + List<@NonNull Node> headNodes = regionHelper.computeHeadNodes(targetFromSourceClosure); + if (headNodes.size() == 0) { + return null; + } + else { + return headNodes.get(0); + } + } + private void check() { for (@NonNull Node node : RegionUtil.getOwnedNodes(region)) { if ((node.isSpeculated() || node.isRealized()) && !hasRealizedNode(node)) { @@ -445,6 +485,10 @@ public class Partitioner return region; } + public @Nullable Node getTraceNode() { + return traceNode; + } + public @NonNull Iterable<@NonNull Node> getTrueNodes() { return trueNodes; } diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculatedPartition.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculatedPartition.java index b0a5b0e63..8bd7c0770 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculatedPartition.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculatedPartition.java @@ -254,12 +254,30 @@ class SpeculatedPartition extends AbstractPartition } protected void resolveRealizedMiddleNodes() { + Node traceNode = partitioner.getTraceNode(); + if (traceNode != null) { + if (traceNode.isMatched() && traceNode.isClass()) { + Role nodeRole = RegionUtil.getNodeRole(traceNode); + // assert nodeRole.isMatched(); + assert traceNode.isPattern();// + nodeRole = QVTscheduleUtil.asSpeculated(nodeRole); + // } + if (!hasNode(traceNode)) { + addNode(traceNode, nodeRole); + } + for (@NonNull NavigableEdge edge : traceNode.getNavigationEdges()) { + if (partitioner.hasRealizedEdge(edge)) { + tracedInputNodes.add(edge.getEdgeTarget()); + } + } + } + } for (@NonNull Node node : partitioner.getRealizedMiddleNodes()) { - if (node.isMatched() && node.isClass()) { + if ((node != traceNode) && node.isMatched() && node.isClass()) { Role nodeRole = RegionUtil.getNodeRole(node); // assert nodeRole.isMatched(); assert node.isPattern();// - nodeRole = QVTscheduleUtil.asSpeculated(nodeRole); + // nodeRole = QVTscheduleUtil.asSpeculated(nodeRole); // } if (!hasNode(node)) { addNode(node, nodeRole); diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculationPartition.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculationPartition.java index 894d893aa..a182d2faa 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculationPartition.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/partitioner/SpeculationPartition.java @@ -34,7 +34,9 @@ class SpeculationPartition extends AbstractPartition // All traced loaded nodes are retained as is to be traced by the speculation. // NB. Unreachable loaded nodes are effectively predicates nd so are deferred. // - for (@NonNull Node node : partitioner.getRealizedMiddleNodes()) { + // for (@NonNull Node node : partitioner.getRealizedMiddleNodes()) { + Node node = partitioner.getTraceNode(); + if (node != null) { if (node.isPattern() && node.isClass()) { // FIXME UML2RDBMS experiment Role speculationNodeRole = RegionUtil.asSpeculation(RegionUtil.getNodeRole(node)); addNode(node, speculationNodeRole); |