1515import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_ARITH_CONST ;
1616import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_ARITH_GE_ATOM ;
1717import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_ARITH_SUM ;
18+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_ARRAY_SELECT ;
1819import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_BIT_TERM ;
1920import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_BOOL_CONST ;
2021import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_BV_ARRAY ;
4142import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_IMOD ;
4243import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_IS_INT_ATOM ;
4344import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_ITE_TERM ;
45+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_LAMBDA_TERM ;
4446import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_NOT_TERM ;
4547import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_OR_TERM ;
4648import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_POWER_PRODUCT ;
4749import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_RDIV ;
4850import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_SELECT_TERM ;
4951import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_UNINTERPRETED_TERM ;
52+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_UPDATE_TERM ;
5053import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_VARIABLE ;
5154import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .YICES_XOR_TERM ;
5255import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_abs ;
111114import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_bitsize ;
112115import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_child ;
113116import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_constructor ;
114- import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_is_bitvector ;
115- import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_is_bool ;
116117import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_is_int ;
117- import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_is_real ;
118118import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_num_children ;
119119import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_term_to_string ;
120120import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_true ;
121+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_child ;
121122import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_is_bitvector ;
123+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_is_bool ;
124+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_is_function ;
125+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_is_int ;
126+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_is_real ;
122127import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_of_term ;
123128import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_type_to_string ;
129+ import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_update ;
124130import static org .sosy_lab .java_smt .solvers .yices2 .Yices2NativeApi .yices_xor ;
125131
126132import com .google .common .base .Joiner ;
136142import java .math .BigInteger ;
137143import java .util .ArrayList ;
138144import java .util .Arrays ;
145+ import java .util .HashSet ;
139146import java .util .List ;
147+ import java .util .Set ;
140148import java .util .stream .Collectors ;
141149import org .sosy_lab .common .rationals .Rational ;
150+ import org .sosy_lab .java_smt .api .ArrayFormula ;
142151import org .sosy_lab .java_smt .api .BitvectorFormula ;
143152import org .sosy_lab .java_smt .api .BooleanFormula ;
144153import org .sosy_lab .java_smt .api .Formula ;
145154import org .sosy_lab .java_smt .api .FormulaType ;
155+ import org .sosy_lab .java_smt .api .FormulaType .ArrayFormulaType ;
146156import org .sosy_lab .java_smt .api .FormulaType .FloatingPointType ;
147157import org .sosy_lab .java_smt .api .FunctionDeclarationKind ;
148158import org .sosy_lab .java_smt .api .QuantifiedFormulaManager .Quantifier ;
149159import org .sosy_lab .java_smt .api .visitors .FormulaVisitor ;
150160import org .sosy_lab .java_smt .basicimpl .FormulaCreator ;
151161import org .sosy_lab .java_smt .basicimpl .FunctionDeclarationImpl ;
162+ import org .sosy_lab .java_smt .solvers .yices2 .Yices2Formula .Yices2ArrayFormula ;
152163import org .sosy_lab .java_smt .solvers .yices2 .Yices2Formula .Yices2BitvectorFormula ;
153164import org .sosy_lab .java_smt .solvers .yices2 .Yices2Formula .Yices2BooleanFormula ;
154165import org .sosy_lab .java_smt .solvers .yices2 .Yices2Formula .Yices2IntegerFormula ;
155166import org .sosy_lab .java_smt .solvers .yices2 .Yices2Formula .Yices2RationalFormula ;
156167
168+ @ SuppressWarnings ({"ClassTypeParameterName" , "MethodTypeParameterName" })
157169public class Yices2FormulaCreator extends FormulaCreator <Integer , Integer , Long , Integer > {
158170
159171 private static final ImmutableSet <Integer > CONSTANT_AND_VARIABLE_CONSTRUCTORS =
@@ -170,6 +182,14 @@ public class Yices2FormulaCreator extends FormulaCreator<Integer, Integer, Long,
170182 */
171183 private final Table <String , Integer , Integer > formulaCache = HashBasedTable .create ();
172184
185+ /**
186+ * List of all UF function declarations.
187+ *
188+ * <p>We need this in the visitor to tell the difference between functions and arrays. Both are
189+ * modeled internally by function terms.
190+ */
191+ private final Set <Integer > ufSymbols = new HashSet <>();
192+
173193 protected Yices2FormulaCreator () {
174194 super (null , yices_bool_type (), yices_int_type (), yices_real_type (), null , null );
175195 }
@@ -186,7 +206,7 @@ public Integer getFloatingPointType(FloatingPointType pType) {
186206
187207 @ Override
188208 public Integer getArrayType (Integer pIndexType , Integer pElementType ) {
189- throw new UnsupportedOperationException ( );
209+ return yices_function_type ( 1 , new int [] { pIndexType }, pElementType );
190210 }
191211
192212 @ Override
@@ -199,6 +219,20 @@ public Integer extractInfo(Formula pT) {
199219 return Yices2FormulaManager .getYicesTerm (pT );
200220 }
201221
222+ @ Override
223+ @ SuppressWarnings ("unchecked" )
224+ protected <TI extends Formula , TE extends Formula > FormulaType <TE > getArrayFormulaElementType (
225+ ArrayFormula <TI , TE > pArray ) {
226+ return ((Yices2ArrayFormula <TI , TE >) pArray ).getElementType ();
227+ }
228+
229+ @ Override
230+ @ SuppressWarnings ("unchecked" )
231+ protected <TI extends Formula , TE extends Formula > FormulaType <TI > getArrayFormulaIndexType (
232+ ArrayFormula <TI , TE > pArray ) {
233+ return ((Yices2ArrayFormula <TI , TE >) pArray ).getIndexType ();
234+ }
235+
202236 @ SuppressWarnings ("unchecked" )
203237 @ Override
204238 public <T extends Formula > T encapsulate (FormulaType <T > pType , Integer pTerm ) {
@@ -219,6 +253,10 @@ public <T extends Formula> T encapsulate(FormulaType<T> pType, Integer pTerm) {
219253 return (T ) new Yices2RationalFormula (pTerm );
220254 } else if (pType .isBitvectorType ()) {
221255 return (T ) new Yices2BitvectorFormula (pTerm );
256+ } else if (pType .isArrayType ()) {
257+ var range = ((ArrayFormulaType <?, ?>) pType ).getElementType ();
258+ var dom = ((ArrayFormulaType <?, ?>) pType ).getIndexType ();
259+ return (T ) encapsulateArray (pTerm , dom , range );
222260 }
223261 throw new IllegalArgumentException ("Cannot create formulas of type " + pType + " in Yices" );
224262 }
@@ -235,32 +273,51 @@ public BitvectorFormula encapsulateBitvector(Integer pTerm) {
235273 return new Yices2BitvectorFormula (pTerm );
236274 }
237275
276+ @ Override
277+ protected <TI extends Formula , TE extends Formula > ArrayFormula <TI , TE > encapsulateArray (
278+ Integer pTerm , FormulaType <TI > pIndexType , FormulaType <TE > pElementType ) {
279+ checkArgument (
280+ getFormulaType (pTerm ).equals (FormulaType .getArrayType (pIndexType , pElementType )),
281+ "Array formula has unexpected type: %s" ,
282+ getFormulaType (pTerm ));
283+ return new Yices2Formula .Yices2ArrayFormula <>(pTerm , pIndexType , pElementType );
284+ }
285+
238286 @ SuppressWarnings ("unchecked" )
239287 @ Override
240288 public <T extends Formula > FormulaType <T > getFormulaType (T pFormula ) {
241289 if (pFormula instanceof BitvectorFormula ) {
242290 int type = yices_type_of_term (extractInfo (pFormula ));
243291 return (FormulaType <T >) FormulaType .getBitvectorTypeWithSize (yices_bvtype_size (type ));
292+ } else if (pFormula instanceof ArrayFormula ) {
293+ return (FormulaType <T >) convertType (yices_type_of_term (extractInfo (pFormula )));
244294 } else {
245295 return super .getFormulaType (pFormula );
246296 }
247297 }
248298
249299 @ Override
250300 public FormulaType <?> getFormulaType (Integer pFormula ) {
251- if (yices_term_is_bool (pFormula )) {
301+ return convertType (yices_type_of_term (pFormula ));
302+ }
303+
304+ /** Convert from Yices2 types to JavaSMT FormulaTypes. */
305+ private FormulaType <?> convertType (Integer pType ) {
306+ if (yices_type_is_bool (pType )) {
252307 return FormulaType .BooleanType ;
253- } else if (yices_term_is_int ( pFormula )) {
308+ } else if (yices_type_is_int ( pType )) {
254309 return FormulaType .IntegerType ;
255- } else if (yices_term_is_real ( pFormula )) {
310+ } else if (yices_type_is_real ( pType )) {
256311 return FormulaType .RationalType ;
257- } else if (yices_term_is_bitvector (pFormula )) {
258- return FormulaType .getBitvectorTypeWithSize (yices_term_bitsize (pFormula ));
312+ } else if (yices_type_is_bitvector (pType )) {
313+ return FormulaType .getBitvectorTypeWithSize (yices_bvtype_size (pType ));
314+ } else if (yices_type_is_function (pType )) {
315+ var domain = yices_type_child (pType , 0 );
316+ var range = yices_type_child (pType , 1 );
317+ return FormulaType .getArrayType (convertType (domain ), convertType (range ));
259318 }
260319 throw new IllegalArgumentException (
261- String .format (
262- "Unknown formula type '%s' for formula '%s'" ,
263- yices_type_to_string (yices_type_of_term (pFormula )), yices_term_to_string (pFormula )));
320+ String .format ("Unknown formula type '%s'" , yices_type_to_string (pType )));
264321 }
265322
266323 /** Creates a named, free variable. Might retrieve it from the cache if created prior. */
@@ -335,6 +392,17 @@ public <R> R visit(FormulaVisitor<R> pVisitor, Formula pFormula, Integer pF) {
335392 return pVisitor .visitConstant (pFormula , convertValue (pF , pF ));
336393 case YICES_BV_CONST :
337394 return pVisitor .visitConstant (pFormula , convertValue (pF , pF ));
395+ case YICES_LAMBDA_TERM :
396+ // We use lambda terms as array constants
397+ return pVisitor .visitFunction (
398+ pFormula ,
399+ ImmutableList .of (encapsulateWithTypeOf (yices_term_child (pF , 1 ))),
400+ FunctionDeclarationImpl .of (
401+ "const" ,
402+ FunctionDeclarationKind .CONST ,
403+ ImmutableList .of (getFormulaType (yices_term_child (pF , 1 ))),
404+ getFormulaType (pF ),
405+ 0 ));
338406 case YICES_UNINTERPRETED_TERM :
339407 return pVisitor .visitFreeVariable (pFormula , yices_get_term_name (pF ));
340408 case YICES_VARIABLE :
@@ -398,11 +466,26 @@ private <R> R visitFunctionApplication(
398466 functionKind = FunctionDeclarationKind .ITE ;
399467 break ;
400468 case YICES_APP_TERM :
401- functionKind = FunctionDeclarationKind .UF ;
402- functionArgs = getArgs (pF );
403- functionName = yices_term_to_string (functionArgs .get (0 ));
404- functionDeclaration = functionArgs .get (0 );
405- functionArgs .remove (0 );
469+ var fun = yices_term_child (pF , 0 );
470+ if (ufSymbols .contains (fun )) {
471+ functionKind = FunctionDeclarationKind .UF ;
472+ functionArgs = getArgs (pF );
473+ functionName = yices_get_term_name (functionArgs .get (0 ));
474+ functionDeclaration = functionArgs .get (0 );
475+ functionArgs .remove (0 );
476+ } else {
477+ functionKind = FunctionDeclarationKind .SELECT ;
478+ functionArgs = getArgs (pF );
479+ functionName = "select" ;
480+ functionDeclaration = -YICES_ARRAY_SELECT ;
481+ }
482+ break ;
483+ case YICES_UPDATE_TERM :
484+ functionKind = FunctionDeclarationKind .STORE ;
485+ functionArgs =
486+ ImmutableList .of (
487+ yices_term_child (pF , 0 ), yices_term_child (pF , 1 ), yices_term_child (pF , 2 ));
488+ functionDeclaration = -YICES_UPDATE_TERM ;
406489 break ;
407490 case YICES_EQ_TERM :
408491 functionKind = FunctionDeclarationKind .EQ ; // Covers all equivalences
@@ -760,6 +843,10 @@ public Integer callFunctionImpl(Integer pDeclaration, List<Integer> pArgs) {
760843 return yices_bvproduct (pArgs .size (), Ints .toArray (pArgs ));
761844 case YICES_AND :
762845 return yices_and (pArgs .size (), Ints .toArray (pArgs ));
846+ case YICES_ARRAY_SELECT :
847+ return yices_application (pArgs .get (0 ), 1 , new int [] {pArgs .get (1 )});
848+ case YICES_UPDATE_TERM :
849+ return yices_update (pArgs .get (0 ), 1 , new int [] {pArgs .get (1 )}, pArgs .get (2 ));
763850 default :
764851 // TODO add more cases
765852 // if something bad happens here,
@@ -808,6 +895,7 @@ public Integer declareUFImpl(String pName, Integer pReturnType, List<Integer> pA
808895 yicesFuncType = yices_function_type (size , argTypeArray , pReturnType );
809896 }
810897 int uf = createNamedVariable (yicesFuncType , pName );
898+ ufSymbols .add (uf );
811899 return uf ;
812900 }
813901
0 commit comments