Skip to content

Commit f9f3fff

Browse files
Print real condition in if labels (KeYProject#3222)
This PR modifies the labels in the proof tree to show the actual condition of ifs instead of the boolean variable introduced by the unfold taclet. With this change, the branch labels in the proof tree are much more useful. |previous|now| :-------------------------:|:-------------------------: ![Sum_pre](https://github.com/KeYProject/key/assets/12560461/2b274dbe-579f-4b39-82b3-29dc4e989381) | ![Sum_post](https://github.com/KeYProject/key/assets/12560461/8179dc72-76e1-49e3-8c03-57001ef36aa2) ![Contains_pre](https://github.com/KeYProject/key/assets/12560461/01157e0d-b360-40b7-a519-55cd31be36ad) | ![Contains_post](https://github.com/KeYProject/key/assets/12560461/c0d5cd54-f453-4cf4-a5d9-da323526d6a9)
2 parents ff3216d + 9582314 commit f9f3fff

File tree

8 files changed

+130
-10
lines changed

8 files changed

+130
-10
lines changed

key.core/src/main/java/de/uka/ilkd/key/java/visitor/JavaASTCollector.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
/**
1212
* Walks through a java AST in depth-left-fist-order. You can set the type of nodes you want to
13-
* collect and then start the walker. The found nodes of the given type are returned as a
14-
* IList<JavaProgramElement>
13+
* collect and then {@link #start()} the walker. The found nodes of the given type are returned as a
14+
* list of {@link ProgramElement}.
1515
*/
1616
public class JavaASTCollector extends JavaASTWalker {
1717

key.core/src/main/java/de/uka/ilkd/key/logic/OpCollector.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SPDX-License-Identifier: GPL-2.0-only */
44
package de.uka.ilkd.key.logic;
55

6+
import java.util.Collections;
67
import java.util.HashSet;
78
import java.util.LinkedHashSet;
89
import java.util.Set;
@@ -15,13 +16,14 @@
1516
*/
1617
public class OpCollector extends DefaultVisitor {
1718
/** the found operators */
18-
private final HashSet<Operator> ops;
19+
protected final HashSet<Operator> ops;
1920

2021
/** creates the Op collector */
2122
public OpCollector() {
2223
ops = new LinkedHashSet<>();
2324
}
2425

26+
@Override
2527
public void visit(Term t) {
2628
ops.add(t.op());
2729
if (t.op() instanceof ElementaryUpdate) {
@@ -34,6 +36,6 @@ public boolean contains(Operator op) {
3436
}
3537

3638
public Set<Operator> ops() {
37-
return ops;
39+
return Collections.unmodifiableSet(ops);
3840
}
3941
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* This file is part of KeY - https://key-project.org
2+
* KeY is licensed under the GNU General Public License Version 2
3+
* SPDX-License-Identifier: GPL-2.0-only */
4+
package de.uka.ilkd.key.logic;
5+
6+
import de.uka.ilkd.key.java.ProgramElement;
7+
import de.uka.ilkd.key.java.visitor.JavaASTCollector;
8+
import de.uka.ilkd.key.logic.op.LocationVariable;
9+
10+
/**
11+
* Extended {@link OpCollector} that also descends into Java blocks
12+
* and collects all {@link LocationVariable} there.
13+
*
14+
* @author Arne Keller
15+
*/
16+
public class OpCollectorJavaBlock extends OpCollector {
17+
@Override
18+
public void visit(Term t) {
19+
super.visit(t);
20+
if (t.javaBlock() != JavaBlock.EMPTY_JAVABLOCK) {
21+
var collect = new JavaASTCollector(t.javaBlock().program(), LocationVariable.class);
22+
collect.start();
23+
for (ProgramElement programElement : collect.getNodes()) {
24+
if (programElement instanceof LocationVariable locationVariable) {
25+
ops.add(locationVariable);
26+
}
27+
}
28+
}
29+
}
30+
}

key.core/src/main/java/de/uka/ilkd/key/logic/op/ProgramVariable.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ protected ProgramVariable(ProgramElementName name, Sort s, KeYJavaType t,
6464
assert sort() != Sort.UPDATE;
6565
}
6666

67-
6867
protected ProgramVariable(ProgramElementName name, Sort s, KeYJavaType t,
6968
KeYJavaType containingType, boolean isStatic, boolean isModel, boolean isGhost) {
7069
this(name, s, t, containingType, isStatic, isModel, isGhost, false);
@@ -263,6 +262,5 @@ public MatchConditions match(SourceData source, MatchConditions matchCond) {
263262
* @param name the new name
264263
* @return equivalent operator with the new name
265264
*/
266-
abstract public Operator rename(Name name);
267-
265+
public abstract Operator rename(Name name);
268266
}

key.core/src/main/java/de/uka/ilkd/key/proof/NodeInfo.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import de.uka.ilkd.key.logic.Term;
2020
import de.uka.ilkd.key.logic.TermBuilder;
2121
import de.uka.ilkd.key.logic.label.TermLabelManager;
22+
import de.uka.ilkd.key.logic.op.LocationVariable;
2223
import de.uka.ilkd.key.proof.io.ProofSaver;
2324
import de.uka.ilkd.key.rule.AbstractAuxiliaryContractBuiltInRuleApp;
2425
import de.uka.ilkd.key.rule.AbstractContractRuleApp;
@@ -30,6 +31,7 @@
3031
import de.uka.ilkd.key.rule.TacletApp;
3132
import de.uka.ilkd.key.rule.inst.TermInstantiation;
3233

34+
import org.key_project.proof.LocationVariableTracker;
3335
import org.key_project.util.collection.ImmutableList;
3436

3537
import org.slf4j.Logger;
@@ -310,8 +312,6 @@ public void setBranchLabel(String s) {
310312
}
311313
RuleApp ruleApp = node.parent().getAppliedRuleApp();
312314
if (ruleApp instanceof TacletApp tacletApp) {
313-
// XXX
314-
315315
Pattern p = Pattern.compile("#\\w+");
316316
Matcher m = p.matcher(s);
317317
StringBuffer sb = new StringBuffer();
@@ -337,6 +337,18 @@ public void setBranchLabel(String s) {
337337
val = TermLabelManager.removeIrrelevantLabels(
338338
((TermInstantiation) val).getInstantiation(),
339339
node.proof().getServices());
340+
} else if (val instanceof LocationVariable locVar) {
341+
var originTracker = node.proof().lookup(LocationVariableTracker.class);
342+
if (originTracker != null) {
343+
var origin = originTracker.getCreatedBy(locVar);
344+
if (origin instanceof PosTacletApp posTacletApp) {
345+
var name = posTacletApp.taclet().displayName();
346+
if (name.equals("ifElseUnfold") || name.equals("ifUnfold")) {
347+
val =
348+
posTacletApp.instantiations().lookupValue(new Name("#nse"));
349+
}
350+
}
351+
}
340352
}
341353
res = ProofSaver.printAnything(val, node.proof().getServices());
342354
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* This file is part of KeY - https://key-project.org
2+
* KeY is licensed under the GNU General Public License Version 2
3+
* SPDX-License-Identifier: GPL-2.0-only */
4+
package org.key_project.proof;
5+
6+
import java.util.Map;
7+
import java.util.WeakHashMap;
8+
9+
import de.uka.ilkd.key.logic.OpCollectorJavaBlock;
10+
import de.uka.ilkd.key.logic.op.LocationVariable;
11+
import de.uka.ilkd.key.proof.Proof;
12+
import de.uka.ilkd.key.proof.ProofEvent;
13+
import de.uka.ilkd.key.proof.RuleAppListener;
14+
import de.uka.ilkd.key.rule.RuleApp;
15+
16+
/**
17+
* Tracks which rule application introduced each {@link LocationVariable} in a proof.
18+
* Currently only checks for {@code ifElseUnfold} rules.
19+
*
20+
* @author Arne Keller
21+
*/
22+
public class LocationVariableTracker implements RuleAppListener {
23+
/**
24+
* The "origin" of the variables. Used to indicate which
25+
* {@link de.uka.ilkd.key.rule.TacletApp} created a new program variable.
26+
*/
27+
private final Map<LocationVariable, RuleApp> createdBy = new WeakHashMap<>();
28+
29+
/**
30+
* Register a new tracker on the provided proof.
31+
*
32+
* @param proof proof to track
33+
*/
34+
public static void handleProofLoad(Proof proof) {
35+
if (proof.lookup(LocationVariableTracker.class) != null) {
36+
return;
37+
}
38+
LocationVariableTracker self = new LocationVariableTracker();
39+
proof.register(self, LocationVariableTracker.class);
40+
proof.addRuleAppListener(self);
41+
}
42+
43+
/**
44+
* @param locationVariable some location variable
45+
* @return the rule app that created it, or null
46+
*/
47+
public RuleApp getCreatedBy(LocationVariable locationVariable) {
48+
return createdBy.get(locationVariable);
49+
}
50+
51+
@Override
52+
public void ruleApplied(ProofEvent e) {
53+
var rai = e.getRuleAppInfo();
54+
if (rai.getRuleApp().rule().displayName().equals("ifElseUnfold")) {
55+
rai.getReplacementNodes().forEach(x -> {
56+
var it = x.getNodeChanges();
57+
while (it.hasNext()) {
58+
var change = it.next();
59+
var sf = change.getPos().sequentFormula();
60+
var collect = new OpCollectorJavaBlock();
61+
sf.formula().execPreOrder(collect);
62+
for (var op : collect.ops()) {
63+
if (!(op instanceof LocationVariable) || createdBy.containsKey(op)) {
64+
continue;
65+
}
66+
createdBy.put((LocationVariable) op, rai.getRuleApp());
67+
}
68+
}
69+
});
70+
}
71+
}
72+
}

key.ui/src/main/java/de/uka/ilkd/key/core/KeYMediator.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import de.uka.ilkd.key.ui.AbstractMediatorUserInterfaceControl;
5454
import de.uka.ilkd.key.util.ThreadUtilities;
5555

56+
import org.key_project.proof.LocationVariableTracker;
5657
import org.key_project.util.collection.ImmutableList;
5758
import org.key_project.util.lookup.Lookup;
5859

@@ -89,6 +90,8 @@ public class KeYMediator {
8990

9091
/**
9192
* Registered proof load listeners.
93+
*
94+
* @see #fireProofLoaded(Proof)
9295
*/
9396
private final Collection<Consumer<Proof>> proofLoadListeners = new ArrayList<>();
9497

@@ -129,11 +132,13 @@ public KeYMediator(AbstractMediatorUserInterfaceControl ui) {
129132
keySelectionModel = new KeYSelectionModel();
130133

131134
ui.getProofControl().addAutoModeListener(proofListener);
135+
136+
registerProofLoadListener(LocationVariableTracker::handleProofLoad);
132137
}
133138

134139
/**
135140
* Register a proof load listener. Will be called whenever a new proof is loaded, but before
136-
* it is replayed.
141+
* it is replayed. The listener MUST be able to accept the same proof twice!
137142
*
138143
* @param listener callback
139144
*/

key.ui/src/main/java/de/uka/ilkd/key/gui/WindowUserInterfaceControl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ public boolean selectProofObligation(InitConfig initConfig) {
476476
@Override
477477
public void registerProofAggregate(ProofAggregate pa) {
478478
super.registerProofAggregate(pa);
479+
getMediator().fireProofLoaded(pa.getFirstProof());
479480
mainWindow.addProblem(pa);
480481
mainWindow.setStandardStatusLine();
481482
}

0 commit comments

Comments
 (0)