Skip to content

Commit 9e79999

Browse files
committed
Refactored variable translation
1 parent 66bebc2 commit 9e79999

File tree

1 file changed

+28
-45
lines changed

1 file changed

+28
-45
lines changed

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

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,65 +16,48 @@
1616
import liquidjava.processor.context.GhostState;
1717
import liquidjava.processor.context.RefinedVariable;
1818
import spoon.reflect.declaration.CtEnum;
19-
import spoon.reflect.declaration.CtType;
2019
import spoon.reflect.reference.CtTypeReference;
2120

2221
public class TranslatorContextToZ3 {
2322

2423
static void translateVariables(Context z3, Map<String, CtTypeReference<?>> ctx,
25-
Map<String, Expr<?>> varTranslation) {
26-
24+
Map<String, Expr<?>> varTranslation) {
25+
// Translates all variables into z3 expressions, creating EnumSorts once per unique enum type.
2726
Map<String, EnumSort<?>> enumSorts = new HashMap<>();
28-
translateEnums(z3, ctx, varTranslation, enumSorts);
29-
translateNonEnumVariables(z3, ctx, varTranslation, enumSorts);
30-
31-
varTranslation.put("true", z3.mkBool(true));
32-
varTranslation.put("false", z3.mkBool(false));
33-
}
3427

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
3828
for (Map.Entry<String, CtTypeReference<?>> entry : ctx.entrySet()) {
29+
String name = entry.getKey();
3930
CtTypeReference<?> type = entry.getValue();
40-
if (!type.isEnum())
41-
continue;
42-
String typeName = type.getQualifiedName();
43-
if (enumSorts.containsKey(typeName))
31+
32+
if (varTranslation.containsKey(name)) continue;
33+
34+
if (type.isEnum() && type.getDeclaration() instanceof CtEnum<?> enumDecl) {
35+
EnumSort<?> enumSort = translateEnum(z3, varTranslation, enumSorts, type, enumDecl);
36+
// translateEnum may have already registered name as a literal constant
37+
// (e.g. Mode.Photo), no need to overwrite
38+
if (!varTranslation.containsKey(name))
39+
varTranslation.put(name, z3.mkConst(name, enumSort));
4440
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-
}
5841
}
42+
varTranslation.put(name, getExpr(z3, name, type));
5943
}
44+
45+
varTranslation.put("true", z3.mkBool(true));
46+
varTranslation.put("false", z3.mkBool(false));
6047
}
6148

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-
}
49+
private static EnumSort<?> translateEnum(Context z3, Map<String, Expr<?>> varTranslation, Map<String, EnumSort<?>> enumSorts, CtTypeReference<?> type, CtEnum<?> enumDecl) {
50+
// Creates (and caches if needed) a z3 EnumSort for a given enum type. Registers enum literal constants
51+
// on first creation.
52+
return enumSorts.computeIfAbsent(type.getQualifiedName(), k -> {
53+
String[] enumValueNames = enumDecl.getEnumValues().stream()
54+
.map(ev -> ev.getSimpleName()).toArray(String[]::new);
55+
EnumSort<?> enumSort = z3.mkEnumSort(k, enumValueNames);
56+
Expr<?>[] consts = enumSort.getConsts();
57+
for (int i = 0; i < enumValueNames.length; i++)
58+
varTranslation.put(enumDecl.getSimpleName() + "." + enumValueNames[i], consts[i]);
59+
return enumSort;
60+
});
7861
}
7962

8063
public static void storeVariablesSubtypes(Context z3, List<RefinedVariable> variables,

0 commit comments

Comments
 (0)