|
3 | 3 | import java.util.ArrayList; |
4 | 4 | import java.util.Comparator; |
5 | 5 | import java.util.HashSet; |
6 | | -import java.util.Iterator; |
7 | 6 | import java.util.List; |
8 | 7 | import java.util.Set; |
9 | 8 | import java.util.stream.Collectors; |
|
15 | 14 | import liquidjava.rj_language.ast.BinaryExpression; |
16 | 15 | import liquidjava.rj_language.ast.Enum; |
17 | 16 | import liquidjava.rj_language.ast.Expression; |
18 | | -import liquidjava.rj_language.ast.FunctionInvocation; |
19 | | -import liquidjava.rj_language.ast.LiteralBoolean; |
20 | | -import liquidjava.rj_language.ast.UnaryExpression; |
21 | 17 | import liquidjava.rj_language.ast.Var; |
22 | 18 | import liquidjava.rj_language.ast.formatter.VariableFormatter; |
23 | 19 | import liquidjava.rj_language.opt.VCSimplificationResult; |
|
27 | 23 | import liquidjava.utils.Utils; |
28 | 24 | import spoon.reflect.cu.SourcePosition; |
29 | 25 |
|
| 26 | +import static liquidjava.rj_language.opt.VCSimplificationUtils.factsOf; |
30 | 27 | import static liquidjava.rj_language.opt.VCSimplificationUtils.isTrue; |
| 28 | +import static liquidjava.rj_language.opt.VCSimplificationUtils.linkedTerms; |
| 29 | +import static liquidjava.rj_language.opt.VCSimplificationUtils.linkedToExpected; |
| 30 | +import static liquidjava.rj_language.opt.VCSimplificationUtils.termName; |
| 31 | +import static liquidjava.rj_language.opt.VCSimplificationUtils.termsOf; |
31 | 32 |
|
32 | 33 | /** |
33 | 34 | * Error indicating that a refinement constraint either was violated or cannot be proven |
@@ -72,21 +73,6 @@ private static String message(Predicate expected, VCSimplificationResult found) |
72 | 73 | expected.getExpression().toDisplayString()); |
73 | 74 | } |
74 | 75 |
|
75 | | - /** |
76 | | - * The facts of found linked to the terms of expected, as a conjunction, or true when there are none; found as |
77 | | - * written when every fact is linked |
78 | | - */ |
79 | | - static Expression linkedToExpected(Expression found, Expression expected) { |
80 | | - List<Expression> facts = factsOf(found); |
81 | | - Set<String> linked = linkedTerms(facts, termsOf(expected)); |
82 | | - List<Expression> linkedFacts = facts.stream().filter(fact -> termsOf(fact).stream().anyMatch(linked::contains)) |
83 | | - .toList(); |
84 | | - if (linkedFacts.size() == facts.size()) |
85 | | - return found; |
86 | | - return linkedFacts.stream().reduce((first, second) -> new BinaryExpression(first, "&&", second)) |
87 | | - .orElse(new LiteralBoolean(true)); |
88 | | - } |
89 | | - |
90 | 76 | /** Unknown when what was found says nothing about the values the expected refinement constrains */ |
91 | 77 | private static ErrorCategory categoryOf(Predicate expected, VCSimplificationResult found) { |
92 | 78 | List<String> foundVariables = found.getImplication().toPredicate().getVariableNames(); |
@@ -138,47 +124,6 @@ private Counterexample filterCounterexample(Counterexample counterexample) { |
138 | 124 | .toList()); |
139 | 125 | } |
140 | 126 |
|
141 | | - // Conjuncts of found, also splitting negated disjunctions (!(a || b) is !a && !b) and dropping double negations, so |
142 | | - // each fact links only the terms it relates |
143 | | - private static List<Expression> factsOf(Expression expression) { |
144 | | - List<Expression> facts = new ArrayList<>(); |
145 | | - if (expression instanceof BinaryExpression binary && "&&".equals(binary.getOperator())) { |
146 | | - facts.addAll(factsOf(binary.getFirstOperand())); |
147 | | - facts.addAll(factsOf(binary.getSecondOperand())); |
148 | | - } else if (expression instanceof UnaryExpression not && "!".equals(not.getOp()) |
149 | | - && not.getExpression()instanceof BinaryExpression binary && "||".equals(binary.getOperator())) { |
150 | | - facts.addAll(factsOf(new UnaryExpression("!", binary.getFirstOperand()))); |
151 | | - facts.addAll(factsOf(new UnaryExpression("!", binary.getSecondOperand()))); |
152 | | - } else if (expression instanceof UnaryExpression not && "!".equals(not.getOp()) |
153 | | - && not.getExpression()instanceof UnaryExpression inner && "!".equals(inner.getOp())) { |
154 | | - facts.addAll(factsOf(inner.getExpression())); |
155 | | - } else { |
156 | | - facts.add(expression); |
157 | | - } |
158 | | - return facts; |
159 | | - } |
160 | | - |
161 | | - // Terms of expected plus those of every fact sharing a term with them, directly or through other facts. The |
162 | | - // remaining facts constrain other values only, so any values satisfying them make the same counterexample |
163 | | - private static Set<String> linkedTerms(List<Expression> facts, List<String> expectedTerms) { |
164 | | - Set<String> linked = new HashSet<>(expectedTerms); |
165 | | - List<List<String>> unlinked = facts.stream().map(RefinementError::termsOf) |
166 | | - .collect(Collectors.toCollection(ArrayList::new)); |
167 | | - boolean changed = true; |
168 | | - while (changed) { |
169 | | - changed = false; |
170 | | - for (Iterator<List<String>> it = unlinked.iterator(); it.hasNext();) { |
171 | | - List<String> terms = it.next(); |
172 | | - if (terms.stream().anyMatch(linked::contains)) { |
173 | | - linked.addAll(terms); |
174 | | - it.remove(); |
175 | | - changed = true; |
176 | | - } |
177 | | - } |
178 | | - } |
179 | | - return linked; |
180 | | - } |
181 | | - |
182 | 127 | // Whether a fact of found is term == value, which the counterexample would only repeat |
183 | 128 | private static boolean isKnown(Pair<String, String> assignment, List<Expression> facts) { |
184 | 129 | return facts.stream() |
@@ -209,32 +154,4 @@ private static int relevance(String term, List<String> expectedTerms, List<Strin |
209 | 154 | return foundTerms.contains(term) ? 1 : 0; |
210 | 155 | return GeneratedNames.isGenerated(term) ? 3 : 2; |
211 | 156 | } |
212 | | - |
213 | | - // Variables and ghost applications of an expression, named as in the SMT model |
214 | | - private static List<String> termsOf(Expression expression) { |
215 | | - List<String> terms = new ArrayList<>(); |
216 | | - expression.getVariableNames(terms); |
217 | | - addGhostApplications(expression, terms); |
218 | | - return terms; |
219 | | - } |
220 | | - |
221 | | - private static void addGhostApplications(Expression expression, List<String> terms) { |
222 | | - String term = expression instanceof FunctionInvocation ? termName(expression) : null; |
223 | | - if (term != null && !terms.contains(term)) |
224 | | - terms.add(term); |
225 | | - for (Expression child : expression.getChildren()) |
226 | | - addGhostApplications(child, terms); |
227 | | - } |
228 | | - |
229 | | - // Name of a variable, or of a ghost application over variables, as in the SMT model; null for other expressions |
230 | | - private static String termName(Expression expression) { |
231 | | - if (expression instanceof Var var) |
232 | | - return var.getName(); |
233 | | - if (expression instanceof FunctionInvocation invocation |
234 | | - && invocation.getArgs().stream().allMatch(Var.class::isInstance)) { |
235 | | - String args = invocation.getArgs().stream().map(Expression::toString).collect(Collectors.joining(", ")); |
236 | | - return Utils.getSimpleName(invocation.getName()) + "(" + args + ")"; |
237 | | - } |
238 | | - return null; |
239 | | - } |
240 | 157 | } |
0 commit comments