Skip to content

Commit b173c75

Browse files
ProofManagement extension: Iterative NodeIntermediateWalker to avoid stack overflows (#3793)
2 parents 18c2bff + e066fd5 commit b173c75

1 file changed

Lines changed: 28 additions & 5 deletions

File tree

keyext.proofmanagement/src/main/java/org/key_project/proofmanagement/check/dependency/NodeIntermediateWalker.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
* SPDX-License-Identifier: GPL-2.0-only */
44
package org.key_project.proofmanagement.check.dependency;
55

6+
import java.util.Deque;
7+
import java.util.LinkedList;
8+
69
import de.uka.ilkd.key.proof.io.intermediate.NodeIntermediate;
710

811
/**
@@ -13,7 +16,7 @@
1316
*/
1417
public abstract class NodeIntermediateWalker {
1518
/** the root where the walker starts */
16-
private NodeIntermediate root;
19+
private final NodeIntermediate root;
1720

1821
/**
1922
* create a walker starting from the given root
@@ -24,21 +27,41 @@ protected NodeIntermediateWalker(NodeIntermediate root) {
2427
this.root = root;
2528
}
2629

30+
2731
/** starts the walker */
2832
public void start() {
29-
walk(root);
33+
walkIteratively();
3034
}
3135

3236
/**
33-
* walks the tree while performing specified action
37+
* Walks the tree while performing specified action.
38+
*
39+
* @deprecated Might run into stack overflow for medium to long proofs, use
40+
* {@link #walkIteratively()} instead.
3441
*
3542
* @param node the current position of the walker in tree
3643
*/
37-
protected void walk(NodeIntermediate node) {
44+
@Deprecated()
45+
protected void walkRecursively(NodeIntermediate node) {
3846
doAction(node);
3947

4048
for (NodeIntermediate child : node.getChildren()) {
41-
walk(child);
49+
walkRecursively(child);
50+
}
51+
}
52+
53+
/**
54+
* Walks the tree while performing specified action. This iterative variant avoids stack
55+
* overflows and is thus preferred. It performs a breadth-first search traversal.
56+
*/
57+
protected void walkIteratively() {
58+
Deque<NodeIntermediate> queue = new LinkedList<>();
59+
queue.add(root);
60+
61+
while (!queue.isEmpty()) {
62+
NodeIntermediate node = queue.pollFirst();
63+
doAction(node);
64+
queue.addAll(node.getChildren());
4265
}
4366
}
4467

0 commit comments

Comments
 (0)