Skip to content

Commit bb5ac4f

Browse files
committed
Cover Remaining RHS Expressions
1 parent 821cc7e commit bb5ac4f

3 files changed

Lines changed: 90 additions & 5 deletions

File tree

liquidjava-example/src/main/java/testSuite/CorrectOperatorAssignments.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,45 @@ int remainder(@Refinement("_ >= 0") int x) {
4444
x %= 2; // x is now == 0 || x is now == 1
4545
return x;
4646
}
47+
48+
int remainderInvocation(@Refinement("_ >= 0") int x) {
49+
@Refinement("_ == 10 || _ == 11")
50+
int y = 10;
51+
y += remainder(x); // x is now >= 6
52+
return x;
53+
}
54+
55+
@Refinement("_ == 9")
56+
int plusUnaryInvocation() {
57+
int y = 10;
58+
y += -one();
59+
return y;
60+
}
61+
62+
@Refinement("_ == 11")
63+
int plusConditional(@Refinement("_ >= 0") int x) {
64+
int y = 10;
65+
y += x >= 0 ? one() : 2;
66+
return y;
67+
}
68+
69+
@Refinement("_ == 13")
70+
int plusBinaryExpression() {
71+
int y = 10;
72+
y += one() + 2;
73+
return y;
74+
}
75+
76+
int plusArrayRead(int[] values) {
77+
int y = 10;
78+
y += values[0];
79+
return y;
80+
}
81+
82+
@Refinement("_ == 11")
83+
int plusCast() {
84+
int y = 10;
85+
y += (int) one();
86+
return y;
87+
}
4788
}

liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/RefinementTypeChecker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ public <T, A extends T> void visitCtAssignment(CtAssignment<T, A> assignment) th
194194
}
195195

196196
@Override
197-
public <T, A extends T> void visitCtOperatorAssignment(CtOperatorAssignment<T, A> assignment) {
197+
public <T, A extends T> void visitCtOperatorAssignment(CtOperatorAssignment<T, A> assignment) throws LJError {
198198
super.visitCtOperatorAssignment(assignment);
199199
visitAssignment(assignment);
200200
}

liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/general_checkers/OperationsChecker.java

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.commons.lang3.NotImplementedException;
2323
import spoon.reflect.code.BinaryOperatorKind;
2424
import spoon.reflect.code.CtAssignment;
25+
import spoon.reflect.code.CtConditional;
2526
import spoon.reflect.code.CtBinaryOperator;
2627
import spoon.reflect.code.CtExpression;
2728
import spoon.reflect.code.CtFieldRead;
@@ -317,19 +318,62 @@ private Predicate getOperatorAssignmentRefinement(CtExpression<?> element) throw
317318
Predicate left = getOperatorAssignmentRefinement(binaryOperator.getLeftHandOperand());
318319
Predicate right = getOperatorAssignmentRefinement(binaryOperator.getRightHandOperand());
319320
return Predicate.createOperation(left, getOperatorFromKind(binaryOperator.getKind()), right);
321+
} else if (element instanceof CtConditional<?> conditional) {
322+
Predicate condition = getConditionRefinement(conditional.getCondition());
323+
Predicate thenExpression = getOperatorAssignmentRefinement(conditional.getThenExpression());
324+
Predicate elseExpression = getOperatorAssignmentRefinement(conditional.getElseExpression());
325+
return Predicate.createITE(condition, thenExpression, elseExpression);
320326
} else if (element instanceof CtLiteral<?> literal) {
321327
if (literal.getValue() == null)
322328
throw new CustomError("Null literals are not supported", literal.getPosition());
323329
return new Predicate(literal.getValue().toString(), element);
330+
} else if (element instanceof CtInvocation<?>) {
331+
VariableInstance invocationValue = (VariableInstance) element.getMetadata(Keys.TARGET);
332+
if (invocationValue != null)
333+
return Predicate.createVar(invocationValue.getName());
324334
}
325-
// unwrap wildcard equality: _ == expr -> expr
326-
Predicate refinement = rtc.getRefinement(element);
335+
return valueFromRefinement(element, rtc.getRefinement(element));
336+
}
337+
338+
private Predicate getConditionRefinement(CtExpression<Boolean> condition) throws LJError {
339+
Predicate refinement = rtc.getRefinement(condition);
340+
Optional<Predicate> value = unwrapWildcardEquality(refinement);
341+
if (value.isPresent())
342+
return value.get();
343+
return refinement;
344+
}
345+
346+
private Optional<Predicate> unwrapWildcardEquality(Predicate refinement) {
327347
Expression expression = unwrapGroupExpression(refinement.getExpression());
328348
if (expression instanceof BinaryExpression binaryExpression && Ops.EQ.equals(binaryExpression.getOperator())
329349
&& Keys.WILDCARD.equals(binaryExpression.getFirstOperand().toString())) {
330-
return new Predicate(binaryExpression.getSecondOperand());
350+
return Optional.of(new Predicate(binaryExpression.getSecondOperand()));
331351
}
332-
return refinement;
352+
return Optional.empty();
353+
}
354+
355+
private Predicate valueFromRefinement(CtExpression<?> element, Predicate refinement) {
356+
if (refinement == null)
357+
return createFreshValue(element, new Predicate());
358+
359+
Optional<Predicate> value = unwrapWildcardEquality(refinement);
360+
if (value.isPresent())
361+
return value.get();
362+
363+
Expression expression = unwrapGroupExpression(refinement.getExpression());
364+
boolean hasWildcard = refinement.getVariableNames().contains(Keys.WILDCARD);
365+
if (!hasWildcard && !expression.isBooleanExpression())
366+
return new Predicate(expression);
367+
368+
Predicate constraint = hasWildcard ? refinement : new Predicate();
369+
return createFreshValue(element, constraint);
370+
}
371+
372+
private Predicate createFreshValue(CtExpression<?> element, Predicate refinement) {
373+
String newName = String.format(Formats.FRESH, rtc.getContext().getCounter());
374+
Predicate freshRefinement = refinement.substituteVariable(Keys.WILDCARD, newName);
375+
rtc.getContext().addVarToContext(newName, element.getType(), freshRefinement, element);
376+
return Predicate.createVar(newName);
333377
}
334378

335379
private Expression unwrapGroupExpression(Expression expression) {

0 commit comments

Comments
 (0)