Skip to content

Commit d33af55

Browse files
authored
Add VC Substitution Simplification (#249)
1 parent 29b1d94 commit d33af55

11 files changed

Lines changed: 762 additions & 118 deletions

File tree

liquidjava-verifier/pom.xml

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -301,16 +301,28 @@
301301
<artifactId>junit-vintage-engine</artifactId>
302302
<scope>test</scope>
303303
</dependency>
304-
<dependency>
305-
<groupId>org.junit.jupiter</groupId>
306-
<artifactId>junit-jupiter-params</artifactId>
307-
<scope>test</scope>
308-
</dependency>
309-
<dependency>
310-
<groupId>ch.qos.logback</groupId>
311-
<artifactId>logback-classic</artifactId>
312-
<version>1.4.12</version>
313-
</dependency>
304+
<dependency>
305+
<groupId>org.junit.jupiter</groupId>
306+
<artifactId>junit-jupiter-params</artifactId>
307+
<scope>test</scope>
308+
</dependency>
309+
<dependency>
310+
<groupId>com.pholser</groupId>
311+
<artifactId>junit-quickcheck-core</artifactId>
312+
<version>1.0</version>
313+
<scope>test</scope>
314+
</dependency>
315+
<dependency>
316+
<groupId>com.pholser</groupId>
317+
<artifactId>junit-quickcheck-generators</artifactId>
318+
<version>1.0</version>
319+
<scope>test</scope>
320+
</dependency>
321+
<dependency>
322+
<groupId>ch.qos.logback</groupId>
323+
<artifactId>logback-classic</artifactId>
324+
<version>1.4.12</version>
325+
</dependency>
314326
<dependency>
315327
<groupId>org.mdkt.compiler</groupId>
316328
<artifactId>InMemoryJavaCompiler</artifactId>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package liquidjava.processor;
2+
3+
import java.util.Objects;
4+
5+
import liquidjava.rj_language.Predicate;
6+
7+
/**
8+
* Represents a VC implication node whose refinement was simplified from another quantified VC shape.
9+
*/
10+
public class SimplifiedVCImplication extends VCImplication {
11+
12+
private final VCImplication origin;
13+
14+
public SimplifiedVCImplication(VCImplication implication, Predicate refinement, VCImplication origin) {
15+
super(implication, refinement);
16+
this.origin = origin.clone();
17+
}
18+
19+
@Override
20+
public VCImplication getOrigin() {
21+
return origin;
22+
}
23+
24+
@Override
25+
public VCImplication copyWithRefinement(Predicate refinement) {
26+
return new SimplifiedVCImplication(this, refinement, origin);
27+
}
28+
29+
@Override
30+
public SimplifiedVCImplication clone() {
31+
SimplifiedVCImplication vc = new SimplifiedVCImplication(this, this.refinement.clone(), origin);
32+
if (this.next != null)
33+
vc.next = this.next.clone();
34+
return vc;
35+
}
36+
37+
@Override
38+
public int hashCode() {
39+
return Objects.hash(super.hashCode(), origin);
40+
}
41+
42+
@Override
43+
public boolean equals(Object obj) {
44+
if (this == obj)
45+
return true;
46+
if (!(obj instanceof SimplifiedVCImplication))
47+
return false;
48+
if (!super.equals(obj))
49+
return false;
50+
SimplifiedVCImplication other = (SimplifiedVCImplication) obj;
51+
return origin.equals(other.origin);
52+
}
53+
}

liquidjava-verifier/src/main/java/liquidjava/processor/VCImplication.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package liquidjava.processor;
22

3+
import java.util.Objects;
4+
35
import liquidjava.rj_language.Predicate;
46
import liquidjava.utils.Utils;
57
import spoon.reflect.reference.CtTypeReference;
@@ -23,6 +25,24 @@ public VCImplication(Predicate ref) {
2325
this.refinement = ref;
2426
}
2527

28+
public VCImplication(VCImplication implication, Predicate ref) {
29+
this.name = implication.name;
30+
this.type = implication.type;
31+
this.refinement = ref;
32+
}
33+
34+
public VCImplication getOrigin() {
35+
return new VCImplication(this, refinement.clone());
36+
}
37+
38+
public Predicate getOriginRefinement() {
39+
return getOrigin().getRefinement().clone();
40+
}
41+
42+
public VCImplication copyWithRefinement(Predicate refinement) {
43+
return new VCImplication(this, refinement);
44+
}
45+
2646
public void setNext(VCImplication c) {
2747
next = c;
2848
}
@@ -47,6 +67,14 @@ public VCImplication getNext() {
4767
return next;
4868
}
4969

70+
public boolean hasNext() {
71+
return next != null;
72+
}
73+
74+
public boolean hasBinder() {
75+
return name != null && type != null;
76+
}
77+
5078
public String toString() {
5179
if (name != null && type != null) {
5280
String qualType = type.getQualifiedName();
@@ -79,4 +107,26 @@ public VCImplication clone() {
79107
vc.next = this.next.clone();
80108
return vc;
81109
}
110+
111+
@Override
112+
public int hashCode() {
113+
return Objects.hash(name, typeName(), refinement, next);
114+
}
115+
116+
@Override
117+
public boolean equals(Object obj) {
118+
if (this == obj)
119+
return true;
120+
if (obj == null)
121+
return false;
122+
if (getClass() != obj.getClass())
123+
return false;
124+
VCImplication other = (VCImplication) obj;
125+
return Objects.equals(name, other.name) && Objects.equals(typeName(), other.typeName())
126+
&& Objects.equals(refinement, other.refinement) && Objects.equals(next, other.next);
127+
}
128+
129+
private String typeName() {
130+
return type == null ? null : type.getQualifiedName();
131+
}
82132
}

liquidjava-verifier/src/main/java/liquidjava/rj_language/Predicate.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ public Predicate clone() {
235235
return new Predicate(exp.clone());
236236
}
237237

238+
@Override
239+
public int hashCode() {
240+
return exp.hashCode();
241+
}
242+
238243
@Override
239244
public boolean equals(Object obj) {
240245
if (this == obj)
@@ -251,6 +256,10 @@ public Expression getExpression() {
251256
return exp;
252257
}
253258

259+
public Predicate getOrigin() {
260+
return this;
261+
}
262+
254263
public ValDerivationNode simplify(Context context) {
255264
// collect aliases from context
256265
Map<String, AliasDTO> aliases = new HashMap<>();

liquidjava-verifier/src/main/java/liquidjava/rj_language/SimplifiedPredicate.java

Lines changed: 0 additions & 108 deletions
This file was deleted.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package liquidjava.rj_language.opt;
2+
3+
import liquidjava.processor.VCImplication;
4+
5+
/**
6+
* Simplifies VCImplication chains by applying various simplification steps
7+
*/
8+
public class VCSimplification {
9+
10+
/**
11+
* Applies all available simplification steps to a VC chain
12+
*/
13+
public static VCImplication simplifyToFixedPoint(VCImplication implication) {
14+
if (implication == null)
15+
return null;
16+
17+
// keep applying simplification steps until a fixed point is reached
18+
VCImplication current = implication.clone();
19+
while (true) {
20+
VCImplication simplified = simplifyOnce(current);
21+
if (current.equals(simplified)) // fixed point reached
22+
return simplified;
23+
current = simplified;
24+
}
25+
}
26+
27+
/**
28+
* Applies one simplification step to a VC chain
29+
*/
30+
public static VCImplication simplifyOnce(VCImplication implication) {
31+
if (implication == null)
32+
return null;
33+
34+
// first try to apply substitution, then folding
35+
VCImplication substituted = VCSubstitution.apply(implication);
36+
if (!implication.equals(substituted))
37+
return substituted;
38+
39+
// TODO: add more simplification steps here (e.g., folding)
40+
return substituted;
41+
}
42+
}

0 commit comments

Comments
 (0)