1919import liquidjava .rj_language .ast .Enum ;
2020import liquidjava .rj_language .ast .Expression ;
2121import liquidjava .rj_language .ast .Var ;
22- import liquidjava .rj_language .ast .formatter .VariableFormatter ;
22+ import liquidjava .processor .context .PlacementInCode ;
23+ import liquidjava .rj_language .ast .formatter .DisplayNames ;
24+ import liquidjava .rj_language .ast .formatter .ExpressionFormatter ;
2325import liquidjava .rj_language .opt .VCSimplificationResult ;
2426import liquidjava .smt .Counterexample ;
2527import liquidjava .utils .GeneratedNames ;
@@ -48,24 +50,32 @@ public class RefinementError extends LJError {
4850 private final List <AliasExpansion > foundAliases ;
4951 private final List <AliasExpansion > expectedAliases ;
5052 private final List <String > aliasDeclarations ;
53+ private final DisplayNames displayNames ;
5154
5255 public RefinementError (SourcePosition position , SourcePosition declarationPosition , Predicate expected ,
5356 VCSimplificationResult found , TranslationTable translationTable , Counterexample counterexample ,
5457 String customMessage , List <AliasWrapper > aliases ) {
55- super ("Refinement Error" , message (expected , found ), position , translationTable , customMessage );
58+ this (position , declarationPosition , expected , found , translationTable , counterexample , customMessage , aliases ,
59+ displayNames (expected , found , translationTable ));
60+ }
61+
62+ private RefinementError (SourcePosition position , SourcePosition declarationPosition , Predicate expected ,
63+ VCSimplificationResult found , TranslationTable translationTable , Counterexample counterexample ,
64+ String customMessage , List <AliasWrapper > aliases , DisplayNames displayNames ) {
65+ super ("Refinement Error" , message (expected , found , displayNames ), position , translationTable , customMessage );
5666 this .expected = expected ;
5767 this .found = found ;
5868 Expression foundExpression = found .getImplication ().toPredicate ().getExpression ();
59- this .foundAliases = AliasExpansion .of (foundExpression , aliases );
60- this .expectedAliases = AliasExpansion .of (expected .getExpression (), aliases );
69+ this .foundAliases = AliasExpansion .of (foundExpression , aliases , displayNames );
70+ this .expectedAliases = AliasExpansion .of (expected .getExpression (), aliases , displayNames );
6171 this .aliasDeclarations = aliasDeclarations (linkedToExpected (foundExpression , expected .getExpression ()),
62- expected .getExpression (), aliases );
72+ expected .getExpression (), aliases , displayNames );
6373 this .counterexample = filterCounterexample (counterexample );
6474 this .declarationPosition = declarationPosition ;
75+ this .displayNames = displayNames ;
6576 if (!this .counterexample .isEmpty ()) {
6677 String counterexampleString = this .counterexample .assignments ().stream ()
67- .map (a -> VariableFormatter .format (a .first ()) + " == " + a .second ())
68- .collect (Collectors .joining (" && " ));
78+ .map (a -> displayNames .get (a .first ()) + " == " + a .second ()).collect (Collectors .joining (" && " ));
6979 setCounterexampleStr ("Counterexample: " + counterexampleString );
7080 }
7181 setCategory (categoryOf (expected , found ));
@@ -76,21 +86,43 @@ public RefinementError(SourcePosition position, SourcePosition declarationPositi
7686
7787 // Only the facts of found about the values expected constrains; path conditions about other values stay in the
7888 // derivation
79- private static String message (Predicate expected , VCSimplificationResult found ) {
80- Expression shown = linkedToExpected ( found . getImplication (). toPredicate (). getExpression (),
81- expected .getExpression ());
89+ private static String message (Predicate expected , VCSimplificationResult found , DisplayNames names ) {
90+ Expression shown = shownFound ( expected , found );
91+ String expectedString = ExpressionFormatter . format ( expected .getExpression (), names );
8292 if (isTrue (shown ))
83- return String .format ("expected %s but could not prove it" , expected .getExpression ().toDisplayString ());
84- return String .format ("%s is not a subtype of %s" , shown .toDisplayString (),
85- expected .getExpression ().toDisplayString ());
93+ return String .format ("expected %s but could not prove it" , expectedString );
94+ return String .format ("%s is not a subtype of %s" , ExpressionFormatter .format (shown , names ), expectedString );
95+ }
96+
97+ /** The facts of found that the message shows */
98+ static Expression shownFound (Predicate expected , VCSimplificationResult found ) {
99+ return linkedToExpected (found .getImplication ().toPredicate ().getExpression (), expected .getExpression ());
100+ }
101+
102+ /**
103+ * The names of an error's variables: those of its message come first, then those only the steps of found show, each
104+ * with the line its value comes from
105+ */
106+ static DisplayNames displayNames (Predicate expected , VCSimplificationResult found ,
107+ TranslationTable translationTable ) {
108+ List <String > shown = new ArrayList <>();
109+ shownFound (expected , found ).getVariableNames (shown );
110+ expected .getExpression ().getVariableNames (shown );
111+ VCSimplificationResult original = original (found );
112+ List <String > others = original .getBinders ();
113+ original .getImplication ().toPredicate ().getExpression ().getVariableNames (others );
114+ return DisplayNames .of (shown , others , name -> {
115+ PlacementInCode placement = translationTable == null ? null : translationTable .get (name );
116+ return placement == null ? null : placement .getLine ();
117+ });
86118 }
87119
88120 // Each alias the message uses once, with those their definitions use, as declared
89121 private static List <String > aliasDeclarations (Expression shownFound , Expression expected ,
90- List <AliasWrapper > aliases ) {
122+ List <AliasWrapper > aliases , DisplayNames names ) {
91123 Map <String , String > declarations = new LinkedHashMap <>();
92124 for (Expression shown : List .of (shownFound , expected ))
93- for (AliasExpansion expansion : AliasExpansion .of (shown , aliases ))
125+ for (AliasExpansion expansion : AliasExpansion .of (shown , aliases , names ))
94126 declarations .putIfAbsent (expansion .alias (), expansion .declaration ());
95127 return new ArrayList <>(declarations .values ());
96128 }
@@ -135,6 +167,11 @@ public List<String> getMessageNotes() {
135167 return aliasDeclarations .stream ().map (declaration -> "where " + declaration ).toList ();
136168 }
137169
170+ /** The names this error gives its variables, for every view of it to show them alike */
171+ public DisplayNames getDisplayNames () {
172+ return displayNames ;
173+ }
174+
138175 // Keeps the counterexample assignments to the terms of expected and of the found facts linked to them, except
139176 // values found already states, so there is none when found fixes every value expected depends on. The terms of
140177 // expected come first, those found says nothing about before the rest, then the linked terms in the order of the
@@ -182,10 +219,14 @@ private static boolean states(Expression term, Expression value, Pair<String, St
182219
183220 // Binders of the VC chain before simplification, which keeps the variables in the order they were introduced
184221 private List <String > originalBinders () {
185- VCSimplificationResult original = getFound ();
222+ return original (getFound ()).getBinders ();
223+ }
224+
225+ private static VCSimplificationResult original (VCSimplificationResult found ) {
226+ VCSimplificationResult original = found ;
186227 while (original .getOrigin () != null )
187228 original = original .getOrigin ();
188- return original . getBinders () ;
229+ return original ;
189230 }
190231
191232 // 0 for terms of expected found says nothing about, whose values alone break it, 1 for the other terms of
0 commit comments