Skip to content

Commit 92c0a4f

Browse files
committed
Add VC Simplification Debug Logs
1 parent 6aa3a40 commit 92c0a4f

2 files changed

Lines changed: 56 additions & 57 deletions

File tree

liquidjava-verifier/src/main/java/liquidjava/diagnostics/DebugLog.java

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import liquidjava.rj_language.Predicate;
88
import liquidjava.rj_language.ast.BinaryExpression;
99
import liquidjava.rj_language.ast.Expression;
10+
import liquidjava.rj_language.opt.VCSimplificationResult;
1011
import liquidjava.utils.Utils;
1112
import spoon.reflect.cu.SourcePosition;
1213
import spoon.reflect.reference.CtTypeReference;
@@ -122,73 +123,47 @@ public static void smtStart(VCImplication chain, Predicate extraPremise, Predica
122123
System.out.println(SMT_TAG + " " + formatConclusion(conclusion));
123124
}
124125

125-
/**
126-
* Print the simplifier input and output side by side. This keeps the raw expression visible in debug traces while
127-
* callers continue using the simplified expression for user-facing diagnostics. Long predicates are split on
128-
* top-level {@code &&} so each conjunct lands on its own line.
129-
*/
130-
public static void simplification(Expression input, Expression output) {
131-
if (!enabled()) {
132-
return;
133-
}
134-
printSplitConjunction("Before simplification:", Colors.YELLOW, input);
135-
printSplitConjunction("After simplification: ", Colors.BOLD_YELLOW, output);
136-
}
137-
138-
private static void printSplitConjunction(String header, String color, Expression exp) {
139-
List<Expression> conjuncts = new ArrayList<>();
140-
flattenConjunction(exp, conjuncts);
141-
if (conjuncts.size() <= 1) {
142-
System.out.println(SMP_TAG + " " + header + " " + color + exp + Colors.RESET);
143-
return;
144-
}
145-
System.out.println(SMP_TAG + " " + header);
146-
String joiner = " " + Colors.GREY + "&&" + Colors.RESET;
147-
for (int i = 0; i < conjuncts.size(); i++) {
148-
String suffix = (i < conjuncts.size() - 1) ? joiner : "";
149-
System.out.println(SMP_TAG + " " + color + conjuncts.get(i) + Colors.RESET + suffix);
150-
}
151-
}
152-
153126
private static final String PASS_NAME_COLOR = Colors.GOLD;
154127
private static final int PASS_NAME_WIDTH = 28;
155128
private static int simplificationPass;
156129
private static String previousSimplification;
157130

158-
/**
159-
* Start a simplification log. DebugLog owns the running pass number and the previous expression snapshot because
160-
* both are only needed for debug output.
161-
*/
162-
public static void simplificationStart(Expression input) {
131+
public static void simplificationStart(VCImplication input) {
163132
if (!enabled()) {
164133
return;
165134
}
166-
previousSimplification = input.toString();
135+
previousSimplification = formatSimplification(input);
167136
simplificationPass = 0;
168-
printSimplificationPass(simplificationPass, "initial expression", previousSimplification);
137+
printSimplificationPass(simplificationPass, "initial VC", previousSimplification);
169138
}
170139

171-
/**
172-
* One line per simplifier phase.
173-
*/
174-
public static void simplificationPass(String name, Expression result) {
175-
if (!enabled()) {
140+
public static void simplificationPass(VCSimplificationResult result) {
141+
if (!enabled() || result == null || result.getSimplification() == null) {
176142
return;
177143
}
178-
String resultStr = result.toString();
179-
printSimplificationPass(++simplificationPass, name, previousSimplification, resultStr);
144+
if (previousSimplification == null && result.getOrigin() != null) {
145+
previousSimplification = formatSimplification(result.getOrigin().getImplication());
146+
}
147+
String resultStr = formatSimplification(result.getImplication());
148+
printSimplificationPass(++simplificationPass, result.getSimplification(), previousSimplification, resultStr);
180149
previousSimplification = resultStr;
181150
}
182151

152+
public static void simplificationEnd(VCSimplificationResult result) {
153+
if (!enabled()) {
154+
return;
155+
}
156+
String finalSimplification = result == null ? "" : formatSimplification(result.getImplication());
157+
printSimplificationPass(++simplificationPass, "Final VC", finalSimplification);
158+
System.out.printf("%s end: %sFixed Point%s%n", SMP_TAG, Colors.GREY, Colors.RESET);
159+
previousSimplification = null;
160+
simplificationPass = 0;
161+
}
162+
183163
/**
184-
* Prints {@code (no change)} when the step left the expression unchanged, and otherwise emits a unified-diff-style
185-
* pair (red {@code -} for the previous expression with removed tokens highlighted, green {@code +} for the new one
186-
* with added tokens highlighted), so substitutions inside a long predicate are obvious at a glance.
187-
*
188-
* <p>
189-
* {@code previous} is taken as a string rather than an {@link Expression} because the simplifier mutates the AST in
190-
* place: caching an {@code Expression} reference and re-stringifying it after a later pass would yield the
191-
* already-mutated form, masking real changes as "no change".
164+
* Prints {@code (no change)} when the step left the VC unchanged, and otherwise emits a unified-diff-style pair
165+
* (red {@code -} for the previous VC with removed tokens highlighted, green {@code +} for the new one with added
166+
* tokens highlighted), so substitutions inside a long VC are obvious at a glance.
192167
*/
193168
private static void printSimplificationPass(int pass, String name, String previous, String result) {
194169
if (previous != null && previous.equals(result)) {
@@ -198,16 +173,34 @@ private static void printSimplificationPass(int pass, String name, String previo
198173
}
199174
System.out.printf("%s pass %02d: %s%s%s%n", SMP_TAG, pass, PASS_NAME_COLOR, name, Colors.RESET);
200175
if (previous == null) {
201-
System.out.printf("%s %s%n", SMP_TAG, result);
176+
printBlock(result);
202177
return;
203178
}
204179
String[] diff = wordDiff(previous, result);
205-
System.out.printf("%s %s-%s %s%n", SMP_TAG, Colors.RED, Colors.RESET, diff[0]);
206-
System.out.printf("%s %s+%s %s%n", SMP_TAG, Colors.GREEN, Colors.RESET, diff[1]);
180+
printDiffBlock("-", Colors.RED, diff[0]);
181+
printDiffBlock("+", Colors.GREEN, diff[1]);
207182
}
208183

209184
private static void printSimplificationPass(int pass, String name, String result) {
210-
System.out.printf("%s pass %02d: %s%n %s%n", SMP_TAG, pass, paintPassName(name), result);
185+
System.out.printf("%s pass %02d: %s%n", SMP_TAG, pass, paintPassName(name));
186+
printBlock(result);
187+
}
188+
189+
private static String formatSimplification(VCImplication implication) {
190+
return implication == null ? "" : implication.toString().stripTrailing();
191+
}
192+
193+
private static void printBlock(String text) {
194+
for (String line : text.split("\\R", -1)) {
195+
System.out.printf("%s %s%n", SMP_TAG, line);
196+
}
197+
}
198+
199+
private static void printDiffBlock(String marker, String color, String text) {
200+
String prefix = color + marker + Colors.RESET;
201+
for (String line : text.split("\\R", -1)) {
202+
System.out.printf("%s %s %s%n", SMP_TAG, prefix, line);
203+
}
211204
}
212205

213206
/**
@@ -223,7 +216,7 @@ private static String paintPassName(String name) {
223216
/**
224217
* Word-level LCS diff. Returns {@code [previousColored, currentColored]} where tokens that don't appear in the LCS
225218
* are wrapped in red (for the previous string) and green (for the current string). Splitting on a single space is
226-
* intentional — the {@link Expression#toString()} output spaces operators and operands.
219+
* intentional because VC and expression formatting space operators and operands.
227220
*/
228221
private static String[] wordDiff(String previous, String current) {
229222
String[] prev = previous.split(" ");

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.List;
44

5+
import liquidjava.diagnostics.DebugLog;
56
import liquidjava.processor.VCImplication;
67

78
/**
@@ -19,11 +20,14 @@ public static VCSimplificationResult simplifyToFixedPoint(VCImplication implicat
1920
if (implication == null)
2021
return null;
2122

23+
DebugLog.simplificationStart(implication);
2224
VCSimplificationResult current = new VCSimplificationResult(implication);
2325
while (true) {
2426
VCSimplificationResult simplified = simplifyOnce(current);
25-
if (simplified == current)
27+
if (simplified == current) {
28+
DebugLog.simplificationEnd(current);
2629
return current; // fixed point reached
30+
}
2731
current = simplified;
2832
}
2933
}
@@ -50,6 +54,8 @@ public static VCSimplificationResult simplifyOnce(VCSimplificationResult implica
5054
VCImplication simplified = pass.apply(implication.getImplication());
5155
if (implication.getImplication().equals(simplified))
5256
return implication;
53-
return new VCSimplificationResult(simplified, implication, pass.getName());
57+
VCSimplificationResult result = new VCSimplificationResult(simplified, implication, pass.getName());
58+
DebugLog.simplificationPass(result);
59+
return result;
5460
}
5561
}

0 commit comments

Comments
 (0)