77import com .microsoft .z3 .FuncDecl ;
88import com .microsoft .z3 .Sort ;
99import java .util .ArrayList ;
10+ import java .util .HashMap ;
1011import java .util .List ;
1112import java .util .Map ;
1213import 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