Skip to content

Commit 88f2c7f

Browse files
authored
Qualify Ghost Names (#52)
1 parent 471cb54 commit 88f2c7f

File tree

27 files changed

+402
-116
lines changed

27 files changed

+402
-116
lines changed

.vscode/launch.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"configurations": [
3+
{
4+
"type": "java",
5+
"name": "Run LiquidJava",
6+
"request": "launch",
7+
"mainClass": "liquidjava.api.CommandLineLauncher",
8+
"projectName": "liquidjava-verifier",
9+
"args": "liquidjava-example/src/main/java/test"
10+
}
11+
]
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package testSuite.classes.ambiguous_state_names_correct;
2+
3+
import liquidjava.specification.StateSet;
4+
import liquidjava.specification.StateRefinement;
5+
6+
@StateSet({"open", "closed"})
7+
public class Door {
8+
9+
@StateRefinement(to = "open(this)")
10+
public Door() { }
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package testSuite.classes.ambiguous_state_names_correct;
2+
3+
import liquidjava.specification.StateSet;
4+
import liquidjava.specification.StateRefinement;
5+
6+
@StateSet({"open", "closed"})
7+
public class Pipe {
8+
9+
@StateRefinement(to = "open(this)")
10+
public Pipe() { }
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package testSuite.classes.ambiguous_state_names_correct;
2+
3+
import liquidjava.specification.Refinement;
4+
5+
public class SimpleTest {
6+
7+
public static void main(String[] args) {
8+
Door d = new Door(); // contains 'open' and 'closed' states
9+
Pipe p = new Pipe(); // unrelated type with the same state names
10+
requiresOpen(d); // ok iff 'open' binds to Door.open otherwise it may bind to Pipe.open and fail
11+
}
12+
13+
public static void requiresOpen(@Refinement("open(s)") Door s) { }
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package testSuite.classes.conflicting_state_names_correct;
2+
3+
import liquidjava.specification.StateRefinement;
4+
import liquidjava.specification.StateSet;
5+
6+
@StateSet({"uninitialized", "initialized"})
7+
public class SM1 {
8+
9+
@StateRefinement(to="uninitialized(this)")
10+
public SM1() {}
11+
12+
13+
@StateRefinement(from="uninitialized(this)", to="initialized(this)")
14+
public void initialize() {}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package testSuite.classes.conflicting_state_names_correct;
2+
3+
import liquidjava.specification.StateRefinement;
4+
import liquidjava.specification.StateSet;
5+
6+
@StateSet({"uninitialized", "initialized"})
7+
public class SM2 {
8+
9+
@StateRefinement(to="uninitialized(this)")
10+
public SM2() {}
11+
12+
13+
@StateRefinement(from="uninitialized(this)", to="initialized(this)")
14+
public void initialize() {}
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package testSuite.classes.conflicting_state_names_correct;
2+
3+
class SimpleTest {
4+
public static void main(String[] args) {
5+
// both classes contain the same state names
6+
SM1 sm1 = new SM1();
7+
SM2 sm2 = new SM2();
8+
sm1.initialize();
9+
sm2.initialize();
10+
}
11+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package liquidjava.processor;
22

33
import liquidjava.rj_language.Predicate;
4+
import liquidjava.utils.Utils;
45
import spoon.reflect.reference.CtTypeReference;
56

67
/**
@@ -29,7 +30,7 @@ public void setNext(VCImplication c) {
2930
public String toString() {
3031
if (name != null && type != null) {
3132
String qualType = type.getQualifiedName();
32-
String simpleType = qualType.contains(".") ? qualType.substring(qualType.lastIndexOf(".") + 1) : qualType;
33+
String simpleType = qualType.contains(".") ? Utils.getSimpleName(qualType) : qualType;
3334
return String.format("%-20s %s %s", "∀" + name + ":" + simpleType + ",", refinement.toString(),
3435
next != null ? " => \n" + next.toString() : "");
3536
} else

liquidjava-verifier/src/main/java/liquidjava/processor/context/Context.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ public void addGhostFunction(GhostFunction gh) {
335335

336336
public boolean hasGhost(String name) {
337337
for (GhostFunction g : ghosts) {
338-
if (g.getName().equals(name))
338+
if (g.matches(name))
339339
return true;
340340
}
341341
return false;

liquidjava-verifier/src/main/java/liquidjava/processor/context/GhostFunction.java

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,39 @@ public class GhostFunction {
1212
private String name;
1313
private List<CtTypeReference<?>> param_types;
1414
private CtTypeReference<?> return_type;
15+
private String prefix;
1516

16-
private String klassName;
17-
18-
public GhostFunction(GhostDTO f, Factory factory, String path, String klass) {
19-
name = f.getName();
20-
return_type = Utils.getType(f.getReturn_type().equals(klass) ? path : f.getReturn_type(), factory);
21-
param_types = new ArrayList<>();
17+
public GhostFunction(GhostDTO f, Factory factory, String prefix) {
18+
String klass = this.getParentClassName(prefix);
19+
this.name = f.getName();
20+
this.return_type = Utils.getType(f.getReturn_type().equals(klass) ? prefix : f.getReturn_type(), factory);
21+
this.param_types = new ArrayList<>();
22+
this.prefix = prefix;
2223
for (String t : f.getParam_types()) {
23-
param_types.add(Utils.getType(t.equals(klass) ? path : t, factory));
24+
this.param_types.add(Utils.getType(t.equals(klass) ? prefix : t, factory));
2425
}
2526
}
2627

2728
public GhostFunction(String name, List<String> param_types, CtTypeReference<?> return_type, Factory factory,
28-
String path, String klass) {
29+
String prefix) {
30+
String klass = this.getParentClassName(prefix);
31+
String type = return_type.toString().equals(klass) ? prefix : return_type.toString();
2932
this.name = name;
30-
this.return_type = Utils.getType(return_type.toString().equals(klass) ? path : return_type.toString(), factory);
33+
this.return_type = Utils.getType(type, factory);
3134
this.param_types = new ArrayList<>();
35+
this.prefix = prefix;
3236
for (int i = 0; i < param_types.size(); i++) {
3337
String mType = param_types.get(i).toString();
34-
this.param_types.add(Utils.getType(mType.equals(klass) ? path : mType, factory));
38+
this.param_types.add(Utils.getType(mType.equals(klass) ? prefix : mType, factory));
3539
}
36-
this.klassName = klass;
3740
}
3841

39-
protected GhostFunction(String name, List<CtTypeReference<?>> list, CtTypeReference<?> return_type, String klass) {
42+
protected GhostFunction(String name, List<CtTypeReference<?>> list, CtTypeReference<?> return_type, String prefix) {
4043
this.name = name;
4144
this.return_type = return_type;
4245
this.param_types = new ArrayList<>();
4346
this.param_types = list;
44-
this.klassName = klass;
45-
}
46-
47-
public String getName() {
48-
return name;
47+
this.prefix = prefix;
4948
}
5049

5150
public CtTypeReference<?> getReturnType() {
@@ -67,7 +66,30 @@ public String toString() {
6766
return sb.toString();
6867
}
6968

69+
public String getName() {
70+
return name;
71+
}
72+
73+
public String getPrefix() {
74+
return prefix;
75+
}
76+
77+
public String getQualifiedName() {
78+
return Utils.qualifyName(prefix, name);
79+
}
80+
7081
public String getParentClassName() {
71-
return klassName;
82+
return getParentClassName(prefix);
83+
}
84+
85+
private String getParentClassName(String pref) {
86+
return Utils.getSimpleName(pref);
87+
}
88+
89+
// Match by fully qualified name, exact simple name or by comparing the simple name of the provided identifier
90+
// This allows references written in a different class (different prefix) to still match
91+
public boolean matches(String name) {
92+
return this.getQualifiedName().equals(name) || this.name.equals(name)
93+
|| this.name.equals(Utils.getSimpleName(name));
7294
}
7395
}

0 commit comments

Comments
 (0)