|
7 | 7 | import liquidjava.diagnostics.TranslationTable; |
8 | 8 | import liquidjava.processor.VCImplication; |
9 | 9 | import liquidjava.rj_language.Predicate; |
10 | | -import liquidjava.rj_language.ast.Expression; |
11 | 10 | import liquidjava.rj_language.ast.formatter.VariableFormatter; |
12 | 11 | import liquidjava.rj_language.opt.VCSimplificationResult; |
13 | 12 | import liquidjava.smt.Counterexample; |
@@ -38,38 +37,30 @@ public RefinementError(SourcePosition position, Predicate expected, VCSimplifica |
38 | 37 |
|
39 | 38 | @Override |
40 | 39 | public String getDetails() { |
41 | | - String counterexampleString = getCounterExampleString(); |
42 | | - if (counterexampleString == null) |
| 40 | + Counterexample counterexamples = getCounterExamples(); |
| 41 | + if (counterexamples == null) |
43 | 42 | return ""; |
| 43 | + |
| 44 | + String counterexampleString = counterexamples.assignments().stream() |
| 45 | + .map(a -> VariableFormatter.format(a.first()) + " == " + a.second()) |
| 46 | + .collect(Collectors.joining(" && ")); |
44 | 47 | return "Counterexample: " + counterexampleString; |
45 | 48 | } |
46 | 49 |
|
47 | | - public String getCounterExampleString() { |
| 50 | + // Filters counterexample assignments only in found VC and sorts them in the order of its binders |
| 51 | + public Counterexample getCounterExamples() { |
48 | 52 | if (counterexample == null || counterexample.assignments().isEmpty()) |
49 | 53 | return null; |
50 | 54 |
|
51 | | - List<String> foundVarNames = new ArrayList<>(); |
52 | | - Expression foundExpression = getFound().getImplication().toPredicate().getExpression(); |
53 | | - Expression expectedExpression = expected.getExpression(); |
54 | | - foundExpression.getVariableNames(foundVarNames); |
55 | | - // also keep resolved static-final constants (e.g. Integer.MAX_VALUE) referenced by either side of the |
56 | | - // subtyping check, so the counterexample maps the symbolic name back to its compile-time value |
57 | | - foundExpression.getResolvedConstantNames(foundVarNames); |
58 | | - expectedExpression.getResolvedConstantNames(foundVarNames); |
59 | | - List<String> foundAssignments = foundExpression.getConjuncts().stream().map(Expression::toString).toList(); |
60 | | - String counterexampleString = counterexample.assignments().stream() |
61 | | - // only include variables that appear in the found value and are not already fixed there |
62 | | - .filter(a -> foundVarNames.contains(a.first()) |
63 | | - && !foundAssignments.contains(a.first() + " == " + a.second())) |
64 | | - // format as "var == value" |
65 | | - .map(a -> VariableFormatter.format(a.first()) + " == " + a.second()) |
66 | | - // join with "&&" |
67 | | - .collect(Collectors.joining(" && ")); |
| 55 | + List<String> binderNames = getFound().getBinders(); |
| 56 | + var assignments = counterexample.assignments().stream().filter(a -> binderNames.contains(a.first())) |
| 57 | + .sorted((a, b) -> Integer.compare(binderNames.indexOf(a.first()), binderNames.indexOf(b.first()))) |
| 58 | + .toList(); |
68 | 59 |
|
69 | | - if (counterexampleString.isEmpty()) |
| 60 | + if (assignments.isEmpty()) |
70 | 61 | return null; |
71 | 62 |
|
72 | | - return counterexampleString; |
| 63 | + return new Counterexample(assignments); |
73 | 64 | } |
74 | 65 |
|
75 | 66 | public Counterexample getCounterexample() { |
|
0 commit comments