Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/splitter/AbstractStage.java')
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/splitter/AbstractStage.java153
1 files changed, 153 insertions, 0 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/splitter/AbstractStage.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/splitter/AbstractStage.java
new file mode 100644
index 000000000..af4cdec98
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/splitter/AbstractStage.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * E.D.Willink - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.qvtd.compiler.internal.qvts2qvti.splitter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+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.compiler.internal.qvtp2qvts.Edge;
+import org.eclipse.qvtd.compiler.internal.qvtp2qvts.Node;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+/**
+ * A Stage specifies part of a multi-headed region split. It has a headNode to represent its primary content
+ * and an edge that defines the entry to the stage, null fir the first stage.
+ */
+abstract class AbstractStage implements Stage
+{
+ /**
+ * The Splitter supervising the region splitting.
+ */
+ protected final @NonNull SplitterAnalysis splitter;
+
+ protected AbstractStage(@NonNull SplitterAnalysis splitter) {
+ this.splitter = splitter;
+ }
+
+ protected abstract @NonNull String buildContents(@NonNull StringBuilder s);
+
+ protected void build(@NonNull StringBuilder s, @NonNull String title, @NonNull Iterable<@NonNull Node> nodes) {
+ if (!Iterables.isEmpty(nodes)) {
+ s.append("\n");
+ SplitterUtil.indent(s, 2);
+ s.append(title);
+ for (@NonNull Node node : nodes) {
+ s.append("\n");
+ SplitterUtil.indent(s, 3);
+ if (node.isHead()) {
+ s.append("*");
+ }
+ s.append(node.getName());
+ s.append(" : ");
+ s.append(node);
+ }
+ }
+ }
+
+ /**
+ * Verify that addition of nodes to accumulator contributes exclusively new content.
+ */
+ protected void checkAccumulate(@NonNull Set<@NonNull Node> accumulator, @NonNull Iterable<@NonNull Node> nodes) {
+ for (@NonNull Node node : nodes) {
+ boolean wasAdded = accumulator.add(node);
+ assert wasAdded;
+ }
+ }
+
+ /**
+ * Verify that the eaccumulator contributes exclusively new content.
+ */
+ protected void checkAccumulated(@NonNull Set<@NonNull Node> actualNodes, @NonNull Iterable<@NonNull Node> expectedNodes) {
+ Set<@NonNull Node> expectedNodesSet = Sets.newHashSet(expectedNodes);
+ if (!actualNodes.equals(expectedNodesSet)) {
+ StringBuilder s = new StringBuilder();
+ Set<@NonNull Node> extraNodesSet = Sets.newHashSet(actualNodes);
+ SplitterUtil.removeAll(extraNodesSet, expectedNodes);
+ for (@NonNull Node node : extraNodesSet) {
+ s.append("\nextra: ");
+ s.append(node);
+ }
+ Set<@NonNull Node> missingNodesSet = Sets.newHashSet(expectedNodes);
+ missingNodesSet.removeAll(actualNodes);
+ for (@NonNull Node node : missingNodesSet) {
+ s.append("\nmissing: ");
+ s.append(node);
+ }
+ assert false : "Bad nodes for " + this + s.toString();
+ }
+ }
+
+ /**
+ * The dead nodes are non-realized nodes that have outgoing edges only to dead nodes or head nodes.
+ */
+ protected @NonNull Iterable<@NonNull Node> computeDeadNodes(@NonNull Iterable<@NonNull Node> reachableNodes) {
+ Set<@NonNull Node> deadNodes = new HashSet<>();
+ Set<@NonNull Node> tryNodes = Sets.newHashSet(reachableNodes);
+ while (!tryNodes.isEmpty()) {
+ Set<@NonNull Node> retryNodes = new HashSet<>();
+ for (@NonNull Node node : tryNodes) {
+ if (!isLive(node, deadNodes)) {
+ deadNodes.add(node);
+ for (@NonNull Edge edge : node.getIncomingEdges()) {
+ if (!edge.isRealized()) {
+ Node sourceNode = edge.getSource();
+ if (!sourceNode.isRealized()) {
+ retryNodes.add(sourceNode);
+ }
+ }
+ }
+ }
+ }
+ retryNodes.removeAll(deadNodes);
+ tryNodes = retryNodes;
+ }
+ List<@NonNull Node> nodeList = new ArrayList<>(deadNodes);
+ Collections.sort(nodeList, NameUtil.NAMEABLE_COMPARATOR);
+ return nodeList;
+ }
+
+ @Override
+ public void debug() {
+ if (Splitter.STAGES.isActive()) {
+ StringBuilder s = new StringBuilder();
+ toString(s, 1);
+ String name = buildContents(s);
+ Splitter.STAGES.println(splitter.toString() + ":" + name + "\n" + s.toString());
+ }
+ }
+
+ @Override
+ public @Nullable Node getIteratedNode() {
+ return null;
+ }
+
+ @Override
+ public @Nullable Node getIteratorNode() {
+ return null;
+ }
+
+ protected abstract boolean isLive(@NonNull Node node, @NonNull Set<@NonNull Node> deadNodes);
+
+ @Override
+ public @NonNull String toString() {
+ StringBuilder s = new StringBuilder();
+ toString(s, 0);
+ return s.toString();
+ }
+} \ No newline at end of file

Back to the top