Skip to content

Commit bbdaaa5

Browse files
authored
Track Simplification Origins by Full VC Implication (#262)
1 parent e78891c commit bbdaaa5

21 files changed

Lines changed: 380 additions & 538 deletions

liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/RefinementError.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import liquidjava.rj_language.Predicate;
1010
import liquidjava.rj_language.ast.Expression;
1111
import liquidjava.rj_language.ast.formatter.VariableFormatter;
12+
import liquidjava.rj_language.opt.VCSimplificationResult;
1213
import liquidjava.smt.Counterexample;
1314
import spoon.reflect.cu.SourcePosition;
1415

@@ -20,13 +21,15 @@
2021
public class RefinementError extends LJError {
2122

2223
private final Predicate expected;
23-
private final VCImplication found;
24+
private final VCSimplificationResult found;
2425
private final Counterexample counterexample;
2526

26-
public RefinementError(SourcePosition position, Predicate expected, VCImplication found,
27+
public RefinementError(SourcePosition position, Predicate expected, VCSimplificationResult found,
2728
TranslationTable translationTable, Counterexample counterexample, String customMessage) {
28-
super("Refinement Error", String.format("%s is not a subtype of %s",
29-
found.toPredicate().getExpression().toDisplayString(), expected.getExpression().toDisplayString()),
29+
super("Refinement Error",
30+
String.format("%s is not a subtype of %s",
31+
found.getImplication().toPredicate().getExpression().toDisplayString(),
32+
expected.getExpression().toDisplayString()),
3033
position, translationTable, customMessage);
3134
this.expected = expected;
3235
this.found = found;
@@ -46,7 +49,7 @@ public String getCounterExampleString() {
4649
return null;
4750

4851
List<String> foundVarNames = new ArrayList<>();
49-
Expression foundExpression = found.toPredicate().getExpression();
52+
Expression foundExpression = getFound().getImplication().toPredicate().getExpression();
5053
Expression expectedExpression = expected.getExpression();
5154
foundExpression.getVariableNames(foundVarNames);
5255
// also keep resolved static-final constants (e.g. Integer.MAX_VALUE) referenced by either side of the
@@ -77,7 +80,7 @@ public Predicate getExpected() {
7780
return expected;
7881
}
7982

80-
public VCImplication getFound() {
83+
public VCSimplificationResult getFound() {
8184
return found;
8285
}
8386
}

liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/StateRefinementError.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import liquidjava.diagnostics.TranslationTable;
44
import liquidjava.processor.VCImplication;
55
import liquidjava.rj_language.Predicate;
6+
import liquidjava.rj_language.opt.VCSimplificationResult;
67
import spoon.reflect.cu.SourcePosition;
78

89
/**
@@ -13,13 +14,13 @@
1314
public class StateRefinementError extends LJError {
1415

1516
private final Predicate expected;
16-
private final VCImplication found;
17+
private final VCSimplificationResult found;
1718

18-
public StateRefinementError(SourcePosition position, Predicate expected, VCImplication found,
19+
public StateRefinementError(SourcePosition position, Predicate expected, VCSimplificationResult found,
1920
TranslationTable translationTable, String customMessage) {
2021
super("State Refinement Error",
2122
String.format("Expected state %s but found %s", expected.getExpression().toDisplayString(),
22-
found.toPredicate().getExpression().toDisplayString()),
23+
found.getImplication().toPredicate().getExpression().toDisplayString()),
2324
position, translationTable, customMessage);
2425
this.expected = expected;
2526
this.found = found;
@@ -30,6 +31,10 @@ public Predicate getExpected() {
3031
}
3132

3233
public VCImplication getFound() {
34+
return found.getImplication();
35+
}
36+
37+
public VCSimplificationResult getFoundSimplification() {
3338
return found;
3439
}
3540
}

liquidjava-verifier/src/main/java/liquidjava/processor/SimplifiedVCImplication.java

Lines changed: 0 additions & 53 deletions
This file was deleted.

liquidjava-verifier/src/main/java/liquidjava/processor/VCImplication.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import liquidjava.rj_language.Predicate;
66
import liquidjava.rj_language.opt.VCSimplification;
7+
import liquidjava.rj_language.opt.VCSimplificationResult;
78
import liquidjava.utils.Utils;
89
import spoon.reflect.reference.CtTypeReference;
910

@@ -32,21 +33,6 @@ public VCImplication(VCImplication implication, Predicate ref) {
3233
this.refinement = ref;
3334
}
3435

35-
public VCImplication getOrigin() {
36-
return null;
37-
}
38-
39-
public Predicate getOriginRefinement() {
40-
VCImplication origin = getOrigin();
41-
if (origin == null)
42-
return refinement.clone();
43-
return origin.getRefinement().clone();
44-
}
45-
46-
public VCImplication copyWithRefinement(Predicate refinement) {
47-
return new VCImplication(this, refinement);
48-
}
49-
5036
public void setNext(VCImplication c) {
5137
next = c;
5238
}
@@ -89,7 +75,7 @@ public String toString() {
8975
return String.format("%-20s %s", "", refinement.toString());
9076
}
9177

92-
public VCImplication simplify() {
78+
public VCSimplificationResult simplify() {
9379
return VCSimplification.simplifyToFixedPoint(this);
9480
}
9581

liquidjava-verifier/src/main/java/liquidjava/rj_language/Predicate.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import liquidjava.diagnostics.errors.LJError;
1111
import liquidjava.diagnostics.errors.NotFoundError;
1212
import liquidjava.processor.VCImplication;
13+
import liquidjava.rj_language.opt.VCSimplificationResult;
1314
import liquidjava.processor.context.AliasWrapper;
1415
import liquidjava.processor.context.Context;
1516
import liquidjava.processor.context.GhostFunction;
@@ -259,12 +260,6 @@ public Predicate getOrigin() {
259260
return this;
260261
}
261262

262-
public VCImplication simplify() {
263-
VCImplication result = new VCImplication(clone()).simplify();
264-
DebugLog.simplification(this.getExpression(), result.getRefinement().getExpression());
265-
return result;
266-
}
267-
268263
private static boolean isBooleanLiteral(Expression expr, boolean value) {
269264
return expr instanceof LiteralBoolean && expr.isBooleanTrue() == value;
270265
}

liquidjava-verifier/src/main/java/liquidjava/rj_language/opt/VCBinderSimplification.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package liquidjava.rj_language.opt;
22

33
import static liquidjava.rj_language.opt.VCSimplificationUtils.containsVar;
4+
import static liquidjava.rj_language.opt.VCSimplificationUtils.copyWithRefinement;
45
import static liquidjava.rj_language.opt.VCSimplificationUtils.isFalse;
56
import static liquidjava.rj_language.opt.VCSimplificationUtils.isTrue;
67

7-
import liquidjava.processor.SimplifiedVCImplication;
88
import liquidjava.processor.VCImplication;
99
import liquidjava.rj_language.Predicate;
1010
import liquidjava.rj_language.ast.LiteralBoolean;
@@ -41,7 +41,7 @@ private VCImplication simplify(VCImplication implication) {
4141
if (next == null)
4242
return null;
4343

44-
VCImplication result = implication.copyWithRefinement(implication.getRefinement().clone());
44+
VCImplication result = copyWithRefinement(implication, implication.getRefinement().clone());
4545
result.setNext(next);
4646
return result;
4747
}
@@ -53,17 +53,12 @@ private VCImplication removeTrueBinder(VCImplication implication) {
5353
VCImplication next = implication.getNext();
5454

5555
// ∀x. true => P -> P
56-
if (next != null) {
57-
VCImplication origin = new VCImplication(implication.getName(), implication.getType(),
58-
next.getOriginRefinement());
59-
VCImplication result = new SimplifiedVCImplication(next, next.getRefinement().clone(), origin);
60-
result.setNext(next.getNext() == null ? null : next.getNext().clone());
61-
return result;
62-
}
56+
if (next != null)
57+
return next.clone();
6358

6459
// ∀x. true -> true
6560
Predicate truePredicate = new Predicate(new LiteralBoolean(true));
66-
return new SimplifiedVCImplication(new VCImplication(truePredicate), truePredicate, implication);
61+
return new VCImplication(truePredicate);
6762
}
6863

6964
/**
@@ -72,7 +67,7 @@ private VCImplication removeTrueBinder(VCImplication implication) {
7267
private VCImplication collapseFalseBinder(VCImplication implication) {
7368
// ∀x. false => P -> true
7469
Predicate truePredicate = new Predicate(new LiteralBoolean(true));
75-
return new SimplifiedVCImplication(new VCImplication(truePredicate), truePredicate, implication);
70+
return new VCImplication(truePredicate);
7671
}
7772

7873
/**

liquidjava-verifier/src/main/java/liquidjava/rj_language/opt/VCExpressionSimplificationPass.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package liquidjava.rj_language.opt;
22

3-
import liquidjava.processor.SimplifiedVCImplication;
3+
import static liquidjava.rj_language.opt.VCSimplificationUtils.copyWithRefinement;
4+
45
import liquidjava.processor.VCImplication;
56
import liquidjava.rj_language.Predicate;
67
import liquidjava.rj_language.ast.Expression;
@@ -32,7 +33,7 @@ private VCImplication apply(VCImplication implication, C context) {
3233
Expression expression = implication.getRefinement().getExpression();
3334
Expression simplified = simplify(expression, context);
3435
if (!expression.equals(simplified)) {
35-
VCImplication result = new SimplifiedVCImplication(implication, new Predicate(simplified), implication);
36+
VCImplication result = copyWithRefinement(implication, new Predicate(simplified));
3637
result.setNext(implication.getNext() == null ? null : implication.getNext().clone());
3738
return result;
3839
}
@@ -41,7 +42,7 @@ private VCImplication apply(VCImplication implication, C context) {
4142
if (implication.getNext() == null || implication.getNext().equals(next))
4243
return implication;
4344

44-
VCImplication result = implication.copyWithRefinement(implication.getRefinement().clone());
45+
VCImplication result = copyWithRefinement(implication, implication.getRefinement().clone());
4546
result.setNext(next);
4647
return result;
4748
}

liquidjava-verifier/src/main/java/liquidjava/rj_language/opt/VCFunctionSubstitution.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package liquidjava.rj_language.opt;
22

3+
import static liquidjava.rj_language.opt.VCSimplificationUtils.copyWithRefinement;
4+
35
import java.util.Optional;
46

5-
import liquidjava.processor.SimplifiedVCImplication;
67
import liquidjava.processor.VCImplication;
78
import liquidjava.rj_language.Predicate;
89
import liquidjava.rj_language.ast.BinaryExpression;
@@ -46,41 +47,41 @@ private VCImplication substitute(VCImplication implication, VCImplication node,
4647

4748
// skip the source node to remove it from the chain and start substitution from the next node
4849
if (implication == node) {
49-
VCImplication result = implication.copyWithRefinement(implication.getRefinement().clone());
50-
result.setNext(substituteSuffix(implication.getNext(), node, invocation, replacement));
50+
VCImplication result = copyWithRefinement(implication, implication.getRefinement().clone());
51+
result.setNext(substituteSuffix(implication.getNext(), invocation, replacement));
5152
return result;
5253
}
5354

5455
// preserve the current node and continue rewriting the suffix
55-
VCImplication result = implication.copyWithRefinement(implication.getRefinement().clone());
56+
VCImplication result = copyWithRefinement(implication, implication.getRefinement().clone());
5657
result.setNext(substitute(implication.getNext(), node, invocation, replacement));
5758
return result;
5859
}
5960

6061
/**
6162
* Rewrites every node after the source equality with one function substitution
6263
*/
63-
private VCImplication substituteSuffix(VCImplication implication, VCImplication source,
64-
FunctionInvocation invocation, Expression replacement) {
64+
private VCImplication substituteSuffix(VCImplication implication, FunctionInvocation invocation,
65+
Expression replacement) {
6566
if (implication == null)
6667
return null;
6768

68-
VCImplication result = substituteNode(implication, source, invocation, replacement);
69-
result.setNext(substituteSuffix(implication.getNext(), source, invocation, replacement));
69+
VCImplication result = substituteNode(implication, invocation, replacement);
70+
result.setNext(substituteSuffix(implication.getNext(), invocation, replacement));
7071
return result;
7172
}
7273

7374
/**
74-
* Substitutes one exact function invocation inside one VC node while preserving simplification metadata
75+
* Substitutes one exact function invocation inside one VC node
7576
*/
76-
private VCImplication substituteNode(VCImplication implication, VCImplication source, FunctionInvocation invocation,
77+
private VCImplication substituteNode(VCImplication implication, FunctionInvocation invocation,
7778
Expression replacement) {
7879
Expression expression = implication.getRefinement().getExpression().clone();
7980
if (!containsExpression(expression, invocation))
80-
return implication.copyWithRefinement(new Predicate(expression));
81+
return copyWithRefinement(implication, new Predicate(expression));
8182

8283
Expression substituted = expression.substitute(invocation, replacement.clone());
83-
return new SimplifiedVCImplication(implication, new Predicate(substituted), source);
84+
return copyWithRefinement(implication, new Predicate(substituted));
8485
}
8586

8687
/**

0 commit comments

Comments
 (0)