33 * SPDX-License-Identifier: GPL-2.0-only */
44package de .uka .ilkd .key .proof ;
55
6- import java .util .ArrayList ;
7- import java .util .Collection ;
8- import java .util .Collections ;
9- import java .util .HashSet ;
10- import java .util .Iterator ;
11- import java .util .LinkedHashSet ;
12- import java .util .LinkedList ;
13- import java .util .List ;
14- import java .util .ListIterator ;
15-
166import de .uka .ilkd .key .logic .RenamingTable ;
177import de .uka .ilkd .key .logic .op .IProgramVariable ;
188import de .uka .ilkd .key .proof .calculus .JavaDLSequentKit ;
2414import org .key_project .prover .rules .RuleApp ;
2515import org .key_project .prover .sequent .Sequent ;
2616import org .key_project .prover .sequent .SequentChangeInfo ;
17+ import de .uka .ilkd .key .util .Pair ;
18+ import org .jspecify .annotations .NonNull ;
19+ import org .jspecify .annotations .Nullable ;
2720import org .key_project .util .collection .DefaultImmutableSet ;
2821import org .key_project .util .collection .ImmutableList ;
2922import org .key_project .util .collection .ImmutableSLList ;
3023import org .key_project .util .collection .ImmutableSet ;
3124import org .key_project .util .collection .Pair ;
3225import org .key_project .util .lookup .Lookup ;
3326
34- import org .jspecify .annotations .NonNull ;
35- import org .jspecify .annotations .Nullable ;
27+ import java .util .*;
3628
3729public class Node implements Iterable <Node > {
3830 private static final String RULE_WITHOUT_NAME = "rule without name" ;
@@ -50,10 +42,14 @@ public class Node implements Iterable<Node> {
5042
5143 private static final String NODES = "nodes" ;
5244
53- /** the proof the node belongs to */
45+ /**
46+ * the proof the node belongs to
47+ */
5448 private final Proof proof ;
5549
56- /** The parent node. **/
50+ /**
51+ * The parent node.
52+ **/
5753 private @ Nullable Node parent = null ;
5854 /**
5955 * The branch location of this proof node.
@@ -82,7 +78,9 @@ public class Node implements Iterable<Node> {
8278
8379 private boolean closed = false ;
8480
85- /** contains non-logical content, used for user feedback */
81+ /**
82+ * contains non-logical content, used for user feedback
83+ */
8684 private NodeInfo nodeInfo ;
8785
8886 /**
@@ -118,7 +116,7 @@ public class Node implements Iterable<Node> {
118116 * taclet with an addrule section on this node, then these taclets are stored in this list
119117 */
120118 private ImmutableSet <NoPosTacletApp > localIntroducedRules =
121- DefaultImmutableSet .nil ();
119+ DefaultImmutableSet .nil ();
122120
123121 /**
124122 * Holds the undo methods for the information added by rules to the {@code Goal.strategyInfos}.
@@ -161,7 +159,9 @@ public void setSequent(Sequent seq) {
161159 this .seq = seq ;
162160 }
163161
164- /** returns the sequent of this node */
162+ /**
163+ * returns the sequent of this node
164+ */
165165 public Sequent sequent () {
166166 return seq ;
167167 }
@@ -175,7 +175,9 @@ public NodeInfo getNodeInfo() {
175175 return nodeInfo ;
176176 }
177177
178- /** returns the proof the Node belongs to */
178+ /**
179+ * returns the proof the Node belongs to
180+ */
179181 public Proof proof () {
180182 return proof ;
181183 }
@@ -225,7 +227,9 @@ public RuleApp getAppliedRuleApp() {
225227 return appliedRuleApp ;
226228 }
227229
228- /** Returns the set of NoPosTacletApps at this node */
230+ /**
231+ * Returns the set of NoPosTacletApps at this node
232+ */
229233 public Iterable <NoPosTacletApp > getLocalIntroducedRules () {
230234 return localIntroducedRules ;
231235 }
@@ -249,7 +253,7 @@ public void addLocalProgVars(Iterable<? extends IProgramVariable> elements) {
249253
250254 /**
251255 * Returns the set of freshly created function symbols known to this node.
252- *
256+ * <p>
253257 * In the resulting list, the newest additions come first.
254258 *
255259 * @return a non-null immutable list of function symbols.
@@ -444,7 +448,7 @@ List<Node> getLeaves() {
444448
445449 /**
446450 * @return an iterator for the leaves of the subtree below this node. The computation is called
447- * at every call!
451+ * at every call!
448452 */
449453 public Iterator <Node > leavesIterator () {
450454 return new NodeIterator (getLeaves ().iterator ());
@@ -471,13 +475,14 @@ public Iterator<Node> subtreeIterator() {
471475 return new SubtreeIterator (this );
472476 }
473477
474- /** @return number of children */
478+ /**
479+ * @return number of children
480+ */
475481 public int childrenCount () {
476482 return children .size ();
477483 }
478484
479485 /**
480- *
481486 * @param i an index (starting at 0).
482487 * @return the i-th child of this node.
483488 */
@@ -488,7 +493,7 @@ public Node child(int i) {
488493 /**
489494 * @param child a child of this node.
490495 * @return the number of the node <code>child</code>, if it is a child of this node (starting
491- * with <code>0</code>), <code>-1</code> otherwise
496+ * with <code>0</code>), <code>-1</code> otherwise
492497 */
493498 public int getChildNr (Node child ) {
494499 int res = 0 ;
@@ -528,16 +533,16 @@ public StringBuffer getUniqueTacletId() {
528533 * Helper for {@link #toString()}
529534 *
530535 * @param prefix needed to keep track if a line has to be printed
531- * @param tree the tree representation we want to add this subtree " @param preEnumeration the
532- * enumeration of the parent without the last number
536+ * @param tree the tree representation we want to add this subtree " @param preEnumeration the
537+ * enumeration of the parent without the last number
533538 * @param postNr the last number of the parents enumeration
534- * @param maxNr the number of nodes at this level
535- * @param ownNr the place of this node at this level
539+ * @param maxNr the number of nodes at this level
540+ * @param ownNr the place of this node at this level
536541 * @return the string representation of this node.
537542 */
538543
539544 private StringBuffer toString (String prefix , StringBuffer tree , String preEnumeration ,
540- int postNr , int maxNr , int ownNr ) {
545+ int postNr , int maxNr , int ownNr ) {
541546 Iterator <Node > childrenIt = childrenIterator ();
542547 // Some constants
543548 String frontIndent = (maxNr > 1 ? " " : "" );
@@ -588,7 +593,7 @@ private StringBuffer toString(String prefix, StringBuffer tree, String preEnumer
588593 while (childrenIt .hasNext ()) {
589594 childId ++;
590595 childrenIt .next ().toString (prefix , tree , newEnumeration , newPostNr , children .size (),
591- childId );
596+ childId );
592597 }
593598
594599 return tree ;
@@ -645,7 +650,7 @@ public String name() {
645650 * this node.
646651 *
647652 * @return true iff the parent of this node has this node as child and this condition holds also
648- * for the own children.
653+ * for the own children.
649654 */
650655 public boolean sanityCheckDoubleLinks () {
651656 if (!root ()) {
@@ -667,7 +672,9 @@ public boolean sanityCheckDoubleLinks() {
667672 return true ;
668673 }
669674
670- /** marks a node as closed */
675+ /**
676+ * marks a node as closed
677+ */
671678 Node close () {
672679 closed = true ;
673680 Node tmp = parent ;
@@ -684,7 +691,7 @@ Node close() {
684691 /**
685692 * Opens a previously closed node and all its closed parents.
686693 * <p>
687- *
694+ * <p>
688695 * This is, for instance, needed for the {@link MergeRule}: In a situation where a merge node
689696 * and its associated partners have been closed and the merge node is then pruned away, the
690697 * partners have to be reopened again. Otherwise, we have a soundness issue.
@@ -699,7 +706,9 @@ void reopen() {
699706 clearNameCache ();
700707 }
701708
702- /** @return true iff this inner node is closeable */
709+ /**
710+ * @return true iff this inner node is closeable
711+ */
703712 private boolean isCloseable () {
704713 assert childrenCount () > 0 ;
705714 for (Node child : children ) {
@@ -768,7 +777,7 @@ public void addStrategyInfoUndoMethod(StrategyInfoUndoMethod undoMethod) {
768777 /**
769778 * Register a user-defined data in this node info.
770779 *
771- * @param obj an object to be registered
780+ * @param obj an object to be registered
772781 * @param service the key under it should be registered
773782 * @param <T> the type of the object to be registered
774783 */
@@ -779,9 +788,9 @@ public <T> void register(T obj, Class<T> service) {
779788 /**
780789 * Remove a previous registered user-defined data.
781790 *
782- * @param obj registered object
791+ * @param obj registered object
783792 * @param service the key under which the data was registered
784- * @param <T> arbitray object
793+ * @param <T> arbitray object
785794 */
786795 public <T > void deregister (T obj , Class <T > service ) {
787796 if (userData != null ) {
@@ -838,4 +847,36 @@ public int getStepIndex() {
838847 void setStepIndex (int stepIndex ) {
839848 this .stepIndex = stepIndex ;
840849 }
850+
851+ /**
852+ * Calculates an array is the path from root node to this node. Each entry defines the child to be selected.
853+ *
854+ * @see #traversePath(Iterator)
855+ */
856+ public int [] getPosInProof () {
857+ // collect the path from the current to node to the root of the proof.
858+ // each entry is the children position
859+ var path = new LinkedList <Integer >();
860+ var current = this ;
861+ while (current .parent != null ) {
862+ path .add (0 , current .parent .getChildNr (current ));
863+ current = current .parent ;
864+ }
865+ return path .stream ().mapToInt (it -> it ).toArray ();
866+ }
867+
868+
869+ /**
870+ * Traverses a given iterator (child selection).
871+ *
872+ * @param traverse non-null
873+ */
874+ public Node traversePath (Iterator <Integer > traverse ) {
875+ var current = this ;
876+ while (traverse .hasNext ()) {
877+ int child = traverse .next ();
878+ current = current .child (child );
879+ }
880+ return current ;
881+ }
841882}
0 commit comments