Skip to content

Commit 66bebc2

Browse files
committed
Separated translation into phases
Translation is now done in 2 phases: a first one for enums, and storing their constant values and names, and the second one as previously done, but with special attention now due to the presence of enums. If the variable, when translating, is already present, it isn't added, and there are no duplicates.
1 parent 66e982f commit 66bebc2

File tree

1 file changed

+49
-11
lines changed

1 file changed

+49
-11
lines changed

liquidjava-verifier/src/main/java/liquidjava/smt/TranslatorContextToZ3.java

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.microsoft.z3.FuncDecl;
88
import com.microsoft.z3.Sort;
99
import java.util.ArrayList;
10+
import java.util.HashMap;
1011
import java.util.List;
1112
import java.util.Map;
1213
import java.util.stream.Stream;
@@ -23,13 +24,59 @@ public class TranslatorContextToZ3 {
2324
static void translateVariables(Context z3, Map<String, CtTypeReference<?>> ctx,
2425
Map<String, Expr<?>> varTranslation) {
2526

26-
for (String name : ctx.keySet())
27-
varTranslation.put(name, getExpr(z3, name, ctx.get(name)));
27+
Map<String, EnumSort<?>> enumSorts = new HashMap<>();
28+
translateEnums(z3, ctx, varTranslation, enumSorts);
29+
translateNonEnumVariables(z3, ctx, varTranslation, enumSorts);
2830

2931
varTranslation.put("true", z3.mkBool(true));
3032
varTranslation.put("false", z3.mkBool(false));
3133
}
3234

35+
private static void translateEnums(Context z3, Map<String, CtTypeReference<?>> ctx,
36+
Map<String, Expr<?>> varTranslation, Map<String, EnumSort<?>> enumSorts) {
37+
// First pass: create one EnumSort per enum type and store actual enum constants
38+
for (Map.Entry<String, CtTypeReference<?>> entry : ctx.entrySet()) {
39+
CtTypeReference<?> type = entry.getValue();
40+
if (!type.isEnum())
41+
continue;
42+
String typeName = type.getQualifiedName();
43+
if (enumSorts.containsKey(typeName))
44+
continue;
45+
CtType<?> decl = type.getDeclaration();
46+
if (decl instanceof CtEnum<?> enumDecl) {
47+
String[] enumValueNames = enumDecl.getEnumValues().stream().map(ev -> ev.getSimpleName())
48+
.toArray(String[]::new);
49+
EnumSort<?> enumSort = z3.mkEnumSort(typeName, enumValueNames);
50+
enumSorts.put(typeName, enumSort);
51+
52+
// Store actual enum constant values (not free variables)
53+
Expr<?>[] consts = enumSort.getConsts();
54+
for (int i = 0; i < enumValueNames.length; i++) {
55+
String varName = enumDecl.getSimpleName() + "." + enumValueNames[i];
56+
varTranslation.put(varName, consts[i]);
57+
}
58+
}
59+
}
60+
}
61+
62+
private static void translateNonEnumVariables(Context z3, Map<String, CtTypeReference<?>> ctx,
63+
Map<String, Expr<?>> varTranslation, Map<String, EnumSort<?>> enumSorts) {
64+
// Second pass: translate non-enum variables and enum-typed variables (not constants)
65+
for (Map.Entry<String, CtTypeReference<?>> entry : ctx.entrySet()) {
66+
String name = entry.getKey();
67+
if (varTranslation.containsKey(name))
68+
continue; // Already translated as an enum constant
69+
CtTypeReference<?> type = entry.getValue();
70+
if (type.isEnum()) {
71+
String typeName = type.getQualifiedName();
72+
EnumSort<?> enumSort = enumSorts.get(typeName);
73+
varTranslation.put(name, z3.mkConst(name, enumSort));
74+
} else {
75+
varTranslation.put(name, getExpr(z3, name, type));
76+
}
77+
}
78+
}
79+
3380
public static void storeVariablesSubtypes(Context z3, List<RefinedVariable> variables,
3481
Map<String, List<Expr<?>>> varSuperTypes) {
3582
for (RefinedVariable v : variables) {
@@ -44,15 +91,6 @@ public static void storeVariablesSubtypes(Context z3, List<RefinedVariable> vari
4491

4592
private static Expr<?> getExpr(Context z3, String name, CtTypeReference<?> type) {
4693
String typeName = type.getQualifiedName();
47-
48-
if (type.isEnum()) {
49-
CtType<?> decl = type.getDeclaration();
50-
if (decl instanceof CtEnum<?> enumDecl) {
51-
String[] enumValueNames = enumDecl.getEnumValues().stream().map(ev -> ev.getSimpleName()).toArray(String[]::new);
52-
EnumSort<Object> enumSort = z3.mkEnumSort(typeName, enumValueNames);
53-
return z3.mkConst(name, enumSort);
54-
}
55-
}
5694

5795
return switch (typeName) {
5896
case "int", "short", "char", "java.lang.Integer", "java.lang.Short", "java.lang.Character" -> z3

0 commit comments

Comments
 (0)