1 /*
2  * This file is part of the Yices SMT Solver.
3  * Copyright (C) 2017 SRI International.
4  *
5  * Yices is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Yices is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * YICES API
21  */
22 
23 /*
24  * This module implements the API defined in yices.h.
25  *
26  * It also implements the functions defined in yices_extensions.h, yices_api_lock_free.h and
27  * yices_iterators.h
28  */
29 
30 
31 /*
32  * Visibility control: all extern functions declared here are in libyices's API
33  * Other extern functions should have visibility=hidden (cf. Makefile).
34  *
35  * On cygwin/mingw, we have two cases:
36  * - static build: NOYICES_DLL is defined.
37  * - dynamic build: NOYICES_DLL is not defined.
38  *
39  * We don't want the attribute __declspec(dllexport) when NOYICES_DLL is defined
40  * otherwise clang gives compilation warnings
41  */
42 #if defined(CYGWIN) || defined(MINGW)
43 // Windows build
44 #if defined(NOYICES_DLL)
45 #define EXPORTED
46 #else
47 #define EXPORTED __declspec(dllexport)
48 #define __YICES_DLLSPEC__ EXPORTED
49 #endif
50 #else
51 // Not Windows
52 #define EXPORTED __attribute__((visibility("default")))
53 #endif
54 
55 #include <assert.h>
56 #include <stddef.h>
57 #include <string.h>
58 #include <errno.h>
59 #include <unistd.h>
60 
61 #include "api/context_config.h"
62 #include "api/search_parameters.h"
63 #include "api/smt_logic_codes.h"
64 #include "api/yices_error.h"
65 #include "api/yices_error_report.h"
66 #include "api/yices_api_lock_free.h"
67 #include "api/yices_extensions.h"
68 #include "api/yices_globals.h"
69 #include "api/yices_iterators.h"
70 #include "api/yval.h"
71 
72 #include "context/context.h"
73 
74 #include "frontend/yices/yices_parser.h"
75 
76 #include "io/model_printer.h"
77 #include "io/term_printer.h"
78 #include "io/type_printer.h"
79 #include "io/yices_pp.h"
80 
81 #include "model/generalization.h"
82 #include "model/literal_collector.h"
83 #include "model/map_to_model.h"
84 #include "model/model_queries.h"
85 #include "model/models.h"
86 #include "model/val_to_term.h"
87 
88 #include "solvers/cdcl/delegate.h"
89 
90 #include "terms/bv64_constants.h"
91 #include "terms/bvarith64_buffer_terms.h"
92 #include "terms/bvarith_buffer_terms.h"
93 #include "terms/rba_buffer_terms.h"
94 #include "terms/term_explorer.h"
95 #include "terms/term_manager.h"
96 #include "terms/term_substitution.h"
97 #include "terms/term_utils.h"
98 #include "terms/types.h"
99 
100 #include "utils/dl_lists.h"
101 #include "utils/int_array_sort.h"
102 #include "utils/refcount_strings.h"
103 #include "utils/sparse_arrays.h"
104 #include "utils/string_utils.h"
105 
106 #ifdef HAVE_MCSAT
107 #include <poly/algebraic_number.h>
108 #else
109 // We need a definition for (lp_algebraic_number_t *)
110 typedef void lp_algebraic_number_t;
111 #endif
112 
113 
114 #include "mt/thread_macros.h"
115 
116 
117 #include "yices.h"
118 
119 
120 
121 /****************************
122  *  GLOBAL DATA STRUCTURES  *
123  ***************************/
124 
125 
126 // rational for building terms: protected by ownership of global lock.
127 static rational_t r0;
128 
129 // buffer for building bitvector constants: protected by ownership of global lock.
130 static bvconstant_t bv0;
131 
132 /*
133  * Initial sizes of the type and term tables.
134  */
135 #define INIT_TYPE_SIZE  16
136 #define INIT_TERM_SIZE  64
137 
138 /*
139  * Global table. The actual initialization is done in yices_init() and
140  * init_globals().
141  */
142 yices_globals_t __yices_globals = {
143 };
144 
145 
146 
147 /*
148  * SYNCHRONIZING ACCESS TO GLOBAL TABLE.
149  */
150 
151 /*
152  * Attempt to obtain sole access to yices' global data structures.
153  * In thread safe mode, calling this function will block all other
154  * yices API routines from accessing the global data structures.
155  *
156  * It is an error to call this more than once.
157  */
yices_obtain_mutex(void)158 int32_t yices_obtain_mutex(void){
159 #ifdef THREAD_SAFE
160   return get_yices_lock(&__yices_globals.lock);
161 #else
162   return 0;
163 #endif
164 }
165 
166 /*
167  * Release the claim to sole access to yices' global data structures.
168  *
169  * The callee must have already obtained sole access via yices_obtain_mutex();
170  */
yices_release_mutex(void)171 int32_t yices_release_mutex(void){
172 #ifdef THREAD_SAFE
173   return release_yices_lock(&__yices_globals.lock);
174 #else
175   return 0;
176 #endif
177 }
178 
179 
180 
181 
182 /*
183  * Registry tables for root terms and types (for garbage collection).
184  * - the two tables are statically allocated but initialized only
185  *   when needed.
186  * - we keep pointers to the tables:
187  *   Initially, we set root_terms = NULL and root_types = NULL
188  *   On the first call to register a term or type, we initialize the
189  *   static tables and update root_terms/root_types to point to it
190  *
191  * - In the thread safe version they are protected by the __yices_globals.lock
192  *
193  */
194 static sparse_array_t *root_terms;
195 static sparse_array_t *root_types;
196 
197 static sparse_array_t the_root_terms;
198 static sparse_array_t the_root_types;
199 
200 
201 
202 /************************************
203  *  DYNAMICALLY ALLOCATED OBJECTS   *
204  ***********************************/
205 
206 /*
207  * All objects that can be allocated via the API
208  * are stored in doubly-linked lists. This will help
209  * implement some form of garbage collection at some point.
210  * For now, this  makes it possible to delete all
211  * global objects when yices_exit is called.
212  */
213 
214 /*
215  * Doubly-linked list of arithmetic buffers
216  */
217 typedef struct {
218   dl_list_t header;
219   rba_buffer_t buffer;
220 } arith_buffer_elem_t;
221 
222 static dl_list_t arith_buffer_list;
223 #ifdef THREAD_SAFE
224 static yices_lock_t arith_buffer_list_lock;
225 #endif
226 
227 /*
228  * Doubly-linked list of bitvector arithmetic buffers
229  */
230 typedef struct {
231   dl_list_t header;
232   bvarith_buffer_t buffer;
233 } bvarith_buffer_elem_t;
234 
235 static dl_list_t bvarith_buffer_list;
236 #ifdef THREAD_SAFE
237 static yices_lock_t bvarith_buffer_list_lock;
238 #endif
239 
240 
241 /*
242  * Variant: 64bit buffers
243  */
244 typedef struct {
245   dl_list_t header;
246   bvarith64_buffer_t buffer;
247 } bvarith64_buffer_elem_t;
248 
249 static dl_list_t bvarith64_buffer_list;
250 #ifdef THREAD_SAFE
251 static yices_lock_t bvarith64_buffer_list_lock;
252 #endif
253 
254 
255 /*
256  * Doubly-linked list of bitvector buffers
257  */
258 typedef struct {
259   dl_list_t header;
260   bvlogic_buffer_t buffer;
261 } bvlogic_buffer_elem_t;
262 
263 static dl_list_t bvlogic_buffer_list;
264 #ifdef THREAD_SAFE
265 static yices_lock_t bvlogic_buffer_list_lock;
266 #endif
267 
268 
269 /*
270  * Doubly-linked list of contexts
271  */
272 typedef struct {
273   dl_list_t header;
274   context_t context;
275 } context_elem_t;
276 
277 static dl_list_t context_list;
278 #ifdef THREAD_SAFE
279 static yices_lock_t context_list_lock;
280 #endif
281 
282 
283 /*
284  * Models
285  */
286 typedef struct {
287   dl_list_t header;
288   model_t model;
289 } model_elem_t;
290 
291 static dl_list_t model_list;
292 #ifdef THREAD_SAFE
293 static yices_lock_t model_list_lock;
294 #endif
295 
296 
297 /*
298  * Context configuration and parameter descriptors
299  * are stored in one list.
300  */
301 typedef struct {
302   dl_list_t header;
303   ctx_config_t config;
304 } ctx_config_elem_t;
305 
306 typedef struct {
307   dl_list_t header;
308   param_t param;
309 } param_structure_elem_t;
310 
311 static dl_list_t generic_list;
312 #ifdef THREAD_SAFE
313 static yices_lock_t generic_list_lock;
314 #endif
315 
316 
init_list_locks(void)317 static inline void init_list_locks(void){
318 #ifdef THREAD_SAFE
319   create_yices_lock(&arith_buffer_list_lock);
320   create_yices_lock(&bvarith_buffer_list_lock);
321   create_yices_lock(&bvarith64_buffer_list_lock);
322   create_yices_lock(&bvlogic_buffer_list_lock);
323   create_yices_lock(&context_list_lock);
324   create_yices_lock(&model_list_lock);
325   create_yices_lock(&generic_list_lock);
326 #endif
327 }
328 
delete_list_locks(void)329 static inline void delete_list_locks(void){
330 #ifdef THREAD_SAFE
331   destroy_yices_lock(&arith_buffer_list_lock);
332   destroy_yices_lock(&bvarith_buffer_list_lock);
333   destroy_yices_lock(&bvarith64_buffer_list_lock);
334   destroy_yices_lock(&bvlogic_buffer_list_lock);
335   destroy_yices_lock(&context_list_lock);
336   destroy_yices_lock(&model_list_lock);
337   destroy_yices_lock(&generic_list_lock);
338 #endif
339 }
340 
341 /* the garbage collector must get all the locks */
get_list_locks(void)342 static inline void get_list_locks(void){
343 #ifdef THREAD_SAFE
344   get_yices_lock(&arith_buffer_list_lock);
345   get_yices_lock(&bvarith_buffer_list_lock);
346   get_yices_lock(&bvarith64_buffer_list_lock);
347   get_yices_lock(&bvlogic_buffer_list_lock);
348   get_yices_lock(&context_list_lock);
349   get_yices_lock(&model_list_lock);
350   get_yices_lock(&generic_list_lock);
351 #endif
352 }
353 
354 /* the garbage collector must also release all the locks */
release_list_locks(void)355 static inline void release_list_locks(void){
356 #ifdef THREAD_SAFE
357   release_yices_lock(&arith_buffer_list_lock);
358   release_yices_lock(&bvarith_buffer_list_lock);
359   release_yices_lock(&bvarith64_buffer_list_lock);
360   release_yices_lock(&bvlogic_buffer_list_lock);
361   release_yices_lock(&context_list_lock);
362   release_yices_lock(&model_list_lock);
363   release_yices_lock(&generic_list_lock);
364 #endif
365 }
366 
367 
368 
369 
370 /**********************************
371  *  ARITHMETIC-BUFFER ALLOCATION  *
372  *********************************/
373 
374 /*
375  * Get header of buffer b, assuming b is embedded into an arith_buffer_elem
376  */
arith_buffer_header(rba_buffer_t * b)377 static inline dl_list_t *arith_buffer_header(rba_buffer_t *b) {
378   return (dl_list_t *)(((char *)b) - offsetof(arith_buffer_elem_t, buffer));
379 }
380 
381 /*
382  * Get buffer of header l
383  */
arith_buffer(dl_list_t * l)384 static inline rba_buffer_t *arith_buffer(dl_list_t *l) {
385   return (rba_buffer_t *)(((char *) l) + offsetof(arith_buffer_elem_t, buffer));
386 }
387 
388 /*
389  * Allocate an arithmetic buffer and insert it into the list
390  */
alloc_arith_buffer(void)391 static inline rba_buffer_t *alloc_arith_buffer(void) {
392   arith_buffer_elem_t *new_elem;
393 
394   new_elem = (arith_buffer_elem_t *) safe_malloc(sizeof(arith_buffer_elem_t));
395   MT_PROTECT_VOID(arith_buffer_list_lock, list_insert_next(&arith_buffer_list, &new_elem->header));
396   return &new_elem->buffer;
397 }
398 
399 /*
400  * Remove b from the list and free b
401  */
_o_free_arith_buffer(rba_buffer_t * b)402 static inline void _o_free_arith_buffer(rba_buffer_t *b) {
403   dl_list_t *elem;
404 
405   elem = arith_buffer_header(b);
406   list_remove(elem);
407   safe_free(elem);
408 }
free_arith_buffer(rba_buffer_t * b)409 static void free_arith_buffer(rba_buffer_t *b) {  //BD could this be inline?
410   MT_PROTECT_VOID(arith_buffer_list_lock, _o_free_arith_buffer(b));
411 }
412 
413 /*
414  * Clean up the arith buffer list: free all elements and empty the list
415  */
_o_free_arith_buffer_list(void)416 static void _o_free_arith_buffer_list(void) {
417   dl_list_t *elem, *aux;
418 
419   elem = arith_buffer_list.next;
420   while (elem != &arith_buffer_list) {
421     aux = elem->next;
422     delete_rba_buffer(arith_buffer(elem));
423     safe_free(elem);
424     elem = aux;
425   }
426 
427   clear_list(&arith_buffer_list);
428 }
free_arith_buffer_list(void)429 static void free_arith_buffer_list(void) {
430   MT_PROTECT_VOID(arith_buffer_list_lock, _o_free_arith_buffer_list());
431 }
432 
433 
434 
435 /********************************************
436  *  BITVECTOR ARITHMETIC BUFFER ALLOCATION  *
437  *******************************************/
438 
439 /*
440  * Get header of buffer b, assuming b is embedded into an bvarith_buffer_elem
441  */
bvarith_buffer_header(bvarith_buffer_t * b)442 static inline dl_list_t *bvarith_buffer_header(bvarith_buffer_t *b) {
443   return (dl_list_t *)(((char *)b) - offsetof(bvarith_buffer_elem_t, buffer));
444 }
445 
446 /*
447  * Get buffer of header l
448  */
bvarith_buffer(dl_list_t * l)449 static inline bvarith_buffer_t *bvarith_buffer(dl_list_t *l) {
450   return (bvarith_buffer_t *)(((char *) l) + offsetof(bvarith_buffer_elem_t, buffer));
451 }
452 
453 /*
454  * Allocate a bv-arithmetic buffer and insert it into the list
455  */
_o_alloc_bvarith_buffer(void)456 static inline bvarith_buffer_t *_o_alloc_bvarith_buffer(void) {
457   bvarith_buffer_elem_t *new_elem;
458 
459   new_elem = (bvarith_buffer_elem_t *) safe_malloc(sizeof(bvarith_buffer_elem_t));
460   list_insert_next(&bvarith_buffer_list, &new_elem->header);
461   return &new_elem->buffer;
462 }
463 
alloc_bvarith_buffer(void)464 static bvarith_buffer_t *alloc_bvarith_buffer(void) {
465   MT_PROTECT(bvarith_buffer_t *, bvarith_buffer_list_lock, _o_alloc_bvarith_buffer());
466 }
467 
468 /*
469  * Remove b from the list and free b
470  */
_o_free_bvarith_buffer(bvarith_buffer_t * b)471 static inline void _o_free_bvarith_buffer(bvarith_buffer_t *b) {
472   dl_list_t *elem;
473 
474   elem = bvarith_buffer_header(b);
475   list_remove(elem);
476   safe_free(elem);
477 }
478 
free_bvarith_buffer(bvarith_buffer_t * b)479 static void free_bvarith_buffer(bvarith_buffer_t *b) {
480   MT_PROTECT_VOID(bvarith_buffer_list_lock, _o_free_bvarith_buffer(b));
481 }
482 
483 /*
484  * Clean up the arith buffer list: free all elements and empty the list
485  */
free_bvarith_buffer_list(void)486 static void free_bvarith_buffer_list(void) {
487   dl_list_t *elem, *aux;
488 
489   elem = bvarith_buffer_list.next;
490   while (elem != &bvarith_buffer_list) {
491     aux = elem->next;
492     delete_bvarith_buffer(bvarith_buffer(elem));
493     safe_free(elem);
494     elem = aux;
495   }
496 
497   clear_list(&bvarith_buffer_list);
498 }
499 
500 
501 
502 /*********************************
503  *  BVARITH64 BUFFER ALLOCATION  *
504  ********************************/
505 
506 /*
507  * Get header of buffer b, assuming b is embedded into an bvarith64_buffer_elem
508  */
bvarith64_buffer_header(bvarith64_buffer_t * b)509 static inline dl_list_t *bvarith64_buffer_header(bvarith64_buffer_t *b) {
510   return (dl_list_t *)(((char *)b) - offsetof(bvarith64_buffer_elem_t, buffer));
511 }
512 
513 /*
514  * Get buffer of header l
515  */
bvarith64_buffer(dl_list_t * l)516 static inline bvarith64_buffer_t *bvarith64_buffer(dl_list_t *l) {
517   return (bvarith64_buffer_t *)(((char *) l) + offsetof(bvarith64_buffer_elem_t, buffer));
518 }
519 
520 /*
521  * Allocate a bv-arithmetic buffer and insert it into the list
522  */
_o_alloc_bvarith64_buffer(void)523 static inline bvarith64_buffer_t *_o_alloc_bvarith64_buffer(void) {
524   bvarith64_buffer_elem_t *new_elem;
525 
526   new_elem = (bvarith64_buffer_elem_t *) safe_malloc(sizeof(bvarith64_buffer_elem_t));
527   list_insert_next(&bvarith64_buffer_list, &new_elem->header);
528   return &new_elem->buffer;
529 }
530 
alloc_bvarith64_buffer(void)531 static bvarith64_buffer_t *alloc_bvarith64_buffer(void) {
532   MT_PROTECT(bvarith64_buffer_t *, bvarith64_buffer_list_lock, _o_alloc_bvarith64_buffer());
533 }
534 
535 /*
536  * Remove b from the list and free b
537  */
_o_free_bvarith64_buffer(bvarith64_buffer_t * b)538 static inline void _o_free_bvarith64_buffer(bvarith64_buffer_t *b) {
539   dl_list_t *elem;
540 
541   elem = bvarith64_buffer_header(b);
542   list_remove(elem);
543   safe_free(elem);
544 }
545 
free_bvarith64_buffer(bvarith64_buffer_t * b)546 static void free_bvarith64_buffer(bvarith64_buffer_t *b) {
547   MT_PROTECT_VOID(bvarith64_buffer_list_lock, _o_free_bvarith64_buffer(b));
548 }
549 
550 /*
551  * Clean up the buffer list: free all elements and empty the list
552  */
free_bvarith64_buffer_list(void)553 static void free_bvarith64_buffer_list(void) {
554   dl_list_t *elem, *aux;
555 
556   elem = bvarith64_buffer_list.next;
557   while (elem != &bvarith64_buffer_list) {
558     aux = elem->next;
559     delete_bvarith64_buffer(bvarith64_buffer(elem));
560     safe_free(elem);
561     elem = aux;
562   }
563 
564   clear_list(&bvarith64_buffer_list);
565 }
566 
567 
568 
569 /*****************************
570  *  LOGIC BUFFER ALLOCATION  *
571  ****************************/
572 
573 /*
574  * Get header of buffer b, assuming b is embedded into an bvlogic_buffer_elem
575  */
bvlogic_buffer_header(bvlogic_buffer_t * b)576 static inline dl_list_t *bvlogic_buffer_header(bvlogic_buffer_t *b) {
577   return (dl_list_t *)(((char *)b) - offsetof(bvlogic_buffer_elem_t, buffer));
578 }
579 
580 /*
581  * Get buffer of header l
582  */
bvlogic_buffer(dl_list_t * l)583 static inline bvlogic_buffer_t *bvlogic_buffer(dl_list_t *l) {
584   return (bvlogic_buffer_t *)(((char *) l) + offsetof(bvlogic_buffer_elem_t, buffer));
585 }
586 
587 /*
588  * Allocate an arithmetic buffer and insert it into the list
589  */
_o_alloc_bvlogic_buffer(void)590 static inline bvlogic_buffer_t *_o_alloc_bvlogic_buffer(void) {
591   bvlogic_buffer_elem_t *new_elem;
592 
593   new_elem = (bvlogic_buffer_elem_t *) safe_malloc(sizeof(bvlogic_buffer_elem_t));
594   list_insert_next(&bvlogic_buffer_list, &new_elem->header);
595   return &new_elem->buffer;
596 }
597 
alloc_bvlogic_buffer(void)598 static bvlogic_buffer_t *alloc_bvlogic_buffer(void) {
599   MT_PROTECT(bvlogic_buffer_t *, bvlogic_buffer_list_lock, _o_alloc_bvlogic_buffer());
600 }
601 
602 /*
603  * Remove b from the list and free b
604  */
_o_free_bvlogic_buffer(bvlogic_buffer_t * b)605 static inline void _o_free_bvlogic_buffer(bvlogic_buffer_t *b) {
606   dl_list_t *elem;
607 
608   elem = bvlogic_buffer_header(b);
609   list_remove(elem);
610   safe_free(elem);
611 }
612 
free_bvlogic_buffer(bvlogic_buffer_t * b)613 static void free_bvlogic_buffer(bvlogic_buffer_t *b) {
614   MT_PROTECT_VOID(bvlogic_buffer_list_lock, _o_free_bvlogic_buffer(b));
615 }
616 
617 /*
618  * Clean up the arith buffer list: free all elements and empty the list
619  */
free_bvlogic_buffer_list(void)620 static void free_bvlogic_buffer_list(void) {
621   dl_list_t *elem, *aux;
622 
623   elem = bvlogic_buffer_list.next;
624   while (elem != &bvlogic_buffer_list) {
625     aux = elem->next;
626     delete_bvlogic_buffer(bvlogic_buffer(elem));
627     safe_free(elem);
628     elem = aux;
629   }
630 
631   clear_list(&bvlogic_buffer_list);
632 }
633 
634 
635 
636 
637 /*************************
638  *  CONTEXT ALLOCATION   *
639  ************************/
640 
641 /*
642  * Get the header of a context c, assuming c is embedded in a context_elem
643  */
header_of_context(context_t * c)644 static inline dl_list_t *header_of_context(context_t *c) {
645   return (dl_list_t *)(((char *) c) - offsetof(context_elem_t, context));
646 }
647 
648 /*
649  * Get the context of header l
650  */
context_of_header(dl_list_t * l)651 static inline context_t *context_of_header(dl_list_t *l) {
652   return (context_t *) (((char *) l) + offsetof(context_elem_t, context));
653 }
654 
655 /*
656  * Allocate a fresh context object and insert it in the context_list
657  * - WARNING: the context is not initialized
658  */
_o_alloc_context(void)659 static inline context_t *_o_alloc_context(void) {
660   context_elem_t *new_elem;
661 
662   new_elem = (context_elem_t *) safe_malloc(sizeof(context_elem_t));
663   list_insert_next(&context_list, &new_elem->header);
664   return &new_elem->context;
665 }
666 
alloc_context(void)667 static context_t *alloc_context(void) {
668   MT_PROTECT(context_t *, context_list_lock, _o_alloc_context());
669 }
670 
671 
672 /*
673  * Remove c from the list and free c
674  * - WARNING: make sure to call delete_context(c) before this
675  *   function
676  */
_o_free_context(context_t * c)677 static inline void _o_free_context(context_t *c) {
678   dl_list_t *elem;
679 
680   elem = header_of_context(c);
681   list_remove(elem);
682   safe_free(elem);
683 }
684 
free_context(context_t * c)685 static void free_context(context_t *c) {
686   MT_PROTECT_VOID(context_list_lock, _o_free_context(c));
687 }
688 
689 
690 /*
691  * Cleanup the context list
692  */
free_context_list(void)693 static void free_context_list(void) {
694   dl_list_t *elem, *aux;
695 
696   elem = context_list.next;
697   while (elem != &context_list) {
698     aux = elem->next;
699     delete_context(context_of_header(elem));
700     safe_free(elem);
701     elem = aux;
702   }
703 
704   clear_list(&context_list);
705 }
706 
707 
708 
709 /***********************
710  *  MODEL ALLOCATION   *
711  **********************/
712 
713 /*
714  * Get the header of a context m, assuming m is embedded in a model_elem
715  */
header_of_model(model_t * m)716 static inline dl_list_t *header_of_model(model_t *m) {
717   return (dl_list_t *)(((char *) m) - offsetof(model_elem_t, model));
718 }
719 
720 /*
721  * Get the model of header l
722  */
model_of_header(dl_list_t * l)723 static inline model_t *model_of_header(dl_list_t *l) {
724   return (model_t *) (((char *) l) + offsetof(model_elem_t, model));
725 }
726 
727 /*
728  * Allocate a fresh model object and insert it in the model_list
729  * - WARNING: the model is not initialized
730  */
_o_alloc_model(void)731 static inline model_t *_o_alloc_model(void) {
732   model_elem_t *new_elem;
733 
734   new_elem = (model_elem_t *) safe_malloc(sizeof(model_elem_t));
735   list_insert_next(&model_list, &new_elem->header);
736   return &new_elem->model;
737 }
738 
alloc_model(void)739 static model_t *alloc_model(void) {
740   MT_PROTECT(model_t *, model_list_lock, _o_alloc_model());
741 }
742 
743 
744 /*
745  * Remove c from the list and free m
746  * - WARNING: make sure to call delete_model(c) before this
747  *   function
748  */
_o_free_model(model_t * m)749 static inline void _o_free_model(model_t *m) {
750   dl_list_t *elem;
751 
752   elem = header_of_model(m);
753   list_remove(elem);
754   safe_free(elem);
755 }
free_model(model_t * m)756 static inline void free_model(model_t *m) {
757   MT_PROTECT_VOID(model_list_lock, _o_free_model(m));
758 }
759 
760 
761 /*
762  * Cleanup the model list
763  */
free_model_list(void)764 static void free_model_list(void) {
765   dl_list_t *elem, *aux;
766 
767   elem = model_list.next;
768   while (elem != &model_list) {
769     aux = elem->next;
770     delete_model(model_of_header(elem));
771     safe_free(elem);
772     elem = aux;
773   }
774 
775   clear_list(&model_list);
776 }
777 
778 
779 
780 
781 /********************************************
782  *  CONFIG AND SEARCH PARAMETER STRUCTURES  *
783  *******************************************/
784 
785 /*
786  * Get the header
787  */
header_of_config_structure(ctx_config_t * c)788 static inline dl_list_t *header_of_config_structure(ctx_config_t *c) {
789   return (dl_list_t *) (((char *) c) - offsetof(ctx_config_elem_t, config));
790 }
791 
header_of_param_structure(param_t * p)792 static inline dl_list_t *header_of_param_structure(param_t *p) {
793   return (dl_list_t *) (((char *) p) - offsetof(param_structure_elem_t, param));
794 }
795 
796 /*
797  * Allocate a structure and insert it into the generic
798  * WARNING: the record is not initialized
799  */
_o_alloc_config_structure(void)800 static inline ctx_config_t *_o_alloc_config_structure(void) {
801   ctx_config_elem_t *new_elem;
802 
803   new_elem = (ctx_config_elem_t *) safe_malloc(sizeof(ctx_config_elem_t));
804   list_insert_next(&generic_list, &new_elem->header);
805   return &new_elem->config;
806 }
807 
alloc_config_structure(void)808 static ctx_config_t *alloc_config_structure(void) {
809   MT_PROTECT(ctx_config_t *, generic_list_lock, _o_alloc_config_structure());
810 }
811 
_o_alloc_param_structure(void)812 static inline param_t *_o_alloc_param_structure(void) {
813   param_structure_elem_t *new_elem;
814 
815   new_elem = (param_structure_elem_t *) safe_malloc(sizeof(param_structure_elem_t));
816   list_insert_next(&generic_list, &new_elem->header);
817   return &new_elem->param;
818 }
819 
alloc_param_structure(void)820 static param_t *alloc_param_structure(void) {
821   MT_PROTECT(param_t *, generic_list_lock,  _o_alloc_param_structure());
822 }
823 
824 /*
825  * Remove a structure form the generic list
826  */
_o_free_config_structure(ctx_config_t * c)827 static inline void _o_free_config_structure(ctx_config_t *c) {
828   dl_list_t *elem;
829 
830   elem = header_of_config_structure(c);
831   list_remove(elem);
832   safe_free(elem);
833 }
834 
free_config_structure(ctx_config_t * c)835 static void free_config_structure(ctx_config_t *c) {
836   MT_PROTECT_VOID(generic_list_lock, _o_free_config_structure(c));
837 }
838 
_o_free_param_structure(param_t * p)839 static inline void _o_free_param_structure(param_t *p) {
840   dl_list_t *elem;
841 
842   elem = header_of_param_structure(p);
843   list_remove(elem);
844   safe_free(elem);
845 }
846 
free_param_structure(param_t * p)847 static void free_param_structure(param_t *p) {
848   MT_PROTECT_VOID(generic_list_lock, _o_free_param_structure(p));
849 }
850 
851 
852 /*
853  * Empty the generic list
854  */
free_generic_list(void)855 static void free_generic_list(void) {
856   dl_list_t *elem, *aux;
857 
858   elem = generic_list.next;
859   while (elem != &generic_list) {
860     aux = elem->next;
861     safe_free(elem);
862     elem = aux;
863   }
864 
865   clear_list(&generic_list);
866 }
867 
868 
869 
870 /***********************************
871  *  PARSER AND RELATED STRUCTURES  *
872  **********************************/
873 
874 /*
875  * Return the internal parser
876  * - initialize it to read from the given string
877  * - s must be non-NULL, terminated by '\0'
878  */
get_parser(const char * s)879 static parser_t *get_parser(const char *s) {
880   if (__yices_globals.parser == NULL) {
881     assert(__yices_globals.lexer == NULL && __yices_globals.tstack == NULL);
882 
883     __yices_globals.tstack = (tstack_t *) safe_malloc(sizeof(tstack_t));
884     init_tstack(__yices_globals.tstack, NUM_BASE_OPCODES);
885 
886     __yices_globals.lexer = (lexer_t *) safe_malloc(sizeof(lexer_t));
887     init_string_lexer(__yices_globals.lexer, s, "yices");
888 
889     __yices_globals.parser = (parser_t *) safe_malloc(sizeof(parser_t));
890     init_parser(__yices_globals.parser, __yices_globals.lexer, __yices_globals.tstack);
891 
892   } else {
893     // reset the input string
894     assert(__yices_globals.lexer != NULL && __yices_globals.tstack != NULL);
895     reset_string_lexer(__yices_globals.lexer, s);
896   }
897 
898   return __yices_globals.parser;
899 }
900 
901 
902 /*
903  * Delete the internal parser, lexer, term stack
904  * (it they exist)
905  */
delete_parsing_objects(void)906 static void delete_parsing_objects(void) {
907   if (__yices_globals.parser != NULL) {
908     assert(__yices_globals.lexer != NULL && __yices_globals.tstack != NULL);
909     delete_parser(__yices_globals.parser);
910     safe_free(__yices_globals.parser);
911     __yices_globals.parser = NULL;
912 
913     close_lexer(__yices_globals.lexer);
914     safe_free(__yices_globals.lexer);
915     __yices_globals.lexer = NULL;
916 
917     delete_tstack(__yices_globals.tstack);
918     safe_free(__yices_globals.tstack);
919     __yices_globals.tstack = NULL;
920   }
921 
922   assert(__yices_globals.lexer == NULL && __yices_globals.tstack == NULL);
923 }
924 
925 
926 /************************
927  *  VARIABLE COLLECTOR  *
928  ***********************/
929 
930 /*
931  * Return the free variable collector
932  * - allocate and initialize it if necessary
933  */
get_fvars(void)934 static fvar_collector_t *get_fvars(void) {
935   if (__yices_globals.fvars == NULL) {
936     __yices_globals.fvars = (fvar_collector_t *) safe_malloc(sizeof(fvar_collector_t));
937     init_fvar_collector(__yices_globals.fvars, __yices_globals.terms);
938   }
939 
940   return __yices_globals.fvars;
941 }
942 
943 
944 /*
945  * Delete the free variable collector if it exists
946  */
delete_fvars(void)947 static void delete_fvars(void) {
948   if (__yices_globals.fvars != NULL) {
949     delete_fvar_collector(__yices_globals.fvars);
950     safe_free(__yices_globals.fvars);
951     __yices_globals.fvars = NULL;
952   }
953 }
954 
955 
956 
957 /***************************************
958  *  GLOBAL INITIALIZATION AND CLEANUP  *
959  **************************************/
960 
961 /*
962  * Initialize the table of global objects
963  */
init_globals(yices_globals_t * glob)964 static void init_globals(yices_globals_t *glob) {
965   type_table_t *types = (type_table_t *)safe_malloc(sizeof(type_table_t));
966   term_table_t *terms = (term_table_t *)safe_malloc(sizeof(term_table_t));
967   term_manager_t *manager = (term_manager_t *)safe_malloc(sizeof(term_manager_t));
968   pprod_table_t *pprods = (pprod_table_t *)safe_malloc(sizeof(pprod_table_t));
969 
970   memset(types, 0, sizeof(type_table_t));
971   memset(terms, 0, sizeof(term_table_t));
972   memset(manager, 0, sizeof(term_manager_t));
973   memset(pprods, 0, sizeof(pprod_table_t));
974 
975   glob->types = types;
976   glob->terms = terms;
977   glob->manager = manager;
978   glob->pprods = pprods;
979 
980   glob->parser = NULL;
981   glob->lexer = NULL;
982   glob->tstack = NULL;
983   glob->fvars = NULL;
984 
985 #ifdef THREAD_SAFE
986   create_yices_lock(&(glob->lock));
987 #endif
988 
989 }
990 
991 
992 /*
993  * Reset all to NULL
994  */
clear_globals(yices_globals_t * glob)995 static void clear_globals(yices_globals_t *glob) {
996   safe_free(glob->types);
997   safe_free(glob->terms);
998   safe_free(glob->manager);
999   safe_free(glob->pprods);
1000 
1001   glob->types = NULL;
1002   glob->terms = NULL;
1003   glob->manager = NULL;
1004 
1005 #ifdef THREAD_SAFE
1006   destroy_yices_lock(&(glob->lock));
1007 #endif
1008 
1009 }
1010 
1011 
1012 /*
1013  * Initialize all global objects
1014  */
yices_init(void)1015 EXPORTED void yices_init(void) {
1016   error_report_t *error;
1017   // setup the TLS and error report structure
1018   init_yices_error();
1019   error = get_yices_error();
1020   error->code = NO_ERROR;
1021 
1022   // prepare the global table
1023   init_globals(&__yices_globals);
1024 
1025   // make the global list locks
1026   init_list_locks();
1027 
1028   init_yices_pp_tables();
1029   init_bvconstants();
1030   init_rationals();
1031 
1032   q_init(&r0);
1033   init_bvconstant(&bv0);
1034 
1035   // tables
1036   init_type_table(__yices_globals.types, INIT_TYPE_SIZE);
1037   init_pprod_table(__yices_globals.pprods, 0);
1038   init_term_table(__yices_globals.terms, INIT_TERM_SIZE, __yices_globals.types, __yices_globals.pprods);
1039   init_term_manager(__yices_globals.manager, __yices_globals.terms);
1040 
1041   // buffer lists
1042   clear_list(&arith_buffer_list);
1043   clear_list(&bvarith_buffer_list);
1044   clear_list(&bvarith64_buffer_list);
1045   clear_list(&bvlogic_buffer_list);
1046 
1047   // other dynamic object lists
1048   clear_list(&context_list);
1049   clear_list(&model_list);
1050   clear_list(&generic_list);
1051 
1052   // registries for garbage collection
1053   root_terms = NULL;
1054   root_types = NULL;
1055 
1056 }
1057 
1058 
1059 /*
1060  * Cleanup: delete all tables and internal data structures
1061  */
yices_exit(void)1062 EXPORTED void yices_exit(void) {
1063   // registries
1064   if (root_terms != NULL) {
1065     assert(root_terms == &the_root_terms);
1066     delete_sparse_array(&the_root_terms);
1067   }
1068   if (root_types != NULL) {
1069     assert(root_types == &the_root_types);
1070     delete_sparse_array(&the_root_types);
1071   }
1072 
1073   delete_parsing_objects();
1074   delete_fvars();
1075 
1076   delete_term_manager(__yices_globals.manager);
1077   delete_term_table(__yices_globals.terms);
1078   delete_pprod_table(__yices_globals.pprods);
1079   delete_type_table(__yices_globals.types);
1080 
1081   clear_globals(&__yices_globals);
1082 
1083   free_bvlogic_buffer_list();
1084   free_bvarith_buffer_list();
1085   free_bvarith64_buffer_list();
1086   free_arith_buffer_list();
1087 
1088   free_context_list();
1089   free_model_list();
1090   free_generic_list();
1091 
1092   delete_list_locks();
1093 
1094   q_clear(&r0);
1095   delete_bvconstant(&bv0);
1096 
1097   cleanup_rationals();
1098   cleanup_bvconstants();
1099 
1100   free_yices_error();
1101 }
1102 
1103 
1104 
1105 /*
1106  * Full reset: delete everything
1107  */
yices_reset(void)1108 EXPORTED void yices_reset(void) {
1109   yices_exit();
1110   yices_init();
1111 }
1112 
1113 
1114 /**********************************
1115  *  ERRORS AND FILE IO UTILITIES  *
1116  *********************************/
1117 
1118 /*
1119  * Open a stream for output file fd
1120  * - fd = file descriptor
1121  * - return NULL if something goes wrong
1122  */
fd_2_tmp_fp(int fd)1123 static FILE *fd_2_tmp_fp(int fd) {
1124   int tmp_fd;
1125 
1126   tmp_fd = dup(fd);
1127   if (tmp_fd < 0) {
1128     return NULL;
1129   }
1130   return fdopen(tmp_fd, "a");
1131 }
1132 
1133 
1134 /*
1135  * Get the last error report
1136  */
yices_error_report(void)1137 EXPORTED error_report_t *yices_error_report(void) {
1138   return get_yices_error();
1139 }
1140 
1141 
1142 /*
1143  * Get the last error code
1144  */
yices_error_code(void)1145 EXPORTED error_code_t yices_error_code(void) {
1146   error_report_t *error = get_yices_error();
1147   return error->code;
1148 }
1149 
1150 
1151 /*
1152  * Set an error code. Leave other fields unchanged
1153  */
set_error_code(error_code_t code)1154 static void set_error_code(error_code_t code) {
1155   error_report_t *error = get_yices_error();
1156   error->code = code;
1157 }
1158 
1159 /*
1160  * Clear the last error report
1161  */
yices_clear_error(void)1162 EXPORTED void yices_clear_error(void) {
1163   set_error_code(NO_ERROR);
1164 }
1165 
1166 
1167 /*
1168  * Record that a file io operation failed
1169  * set the error_code to OUTPUT_ERROR
1170  */
file_output_error(void)1171 static inline void file_output_error(void) {
1172   set_error_code(OUTPUT_ERROR);
1173 }
1174 
1175 
1176 /*
1177  * Print an errormessage on f
1178  */
yices_print_error(FILE * f)1179 EXPORTED int32_t yices_print_error(FILE *f) {
1180   return print_error(f);
1181 }
1182 
yices_print_error_fd(int fd)1183 EXPORTED int32_t yices_print_error_fd(int fd) {
1184   FILE *tmp_fp;
1185   int32_t retval;
1186 
1187   tmp_fp = fd_2_tmp_fp(fd);
1188   if (tmp_fp == NULL) {
1189     file_output_error();
1190     return -1;
1191   }
1192   retval = print_error(tmp_fp);
1193   fclose(tmp_fp);
1194 
1195   return retval;
1196 }
1197 
1198 
1199 /*
1200  * Build an error string
1201  */
yices_error_string(void)1202 EXPORTED char *yices_error_string(void) {
1203   return error_string();
1204 }
1205 
1206 
1207 /*
1208  * Reset the internal term/types/pprod tables
1209  */
yices_reset_tables(void)1210 void yices_reset_tables(void) {
1211   reset_term_manager(__yices_globals.manager);
1212   reset_term_table(__yices_globals.terms);
1213   reset_pprod_table(__yices_globals.pprods);
1214   reset_type_table(__yices_globals.types);
1215 }
1216 
1217 
1218 /*
1219  * Install a call back function that will be invoked
1220  * if Yices runs out of memory.
1221  * - if this callback returns, the process is killed
1222  */
_o_yices_set_out_of_mem_callback(void (* callback)(void))1223 static void _o_yices_set_out_of_mem_callback(void (*callback)(void)) {
1224   __out_of_mem_callback = callback;
1225 }
1226 
yices_set_out_of_mem_callback(void (* callback)(void))1227 EXPORTED void yices_set_out_of_mem_callback(void (*callback)(void)) {
1228   MT_PROTECT_VOID(__yices_globals.lock,_o_yices_set_out_of_mem_callback(callback));
1229 }
1230 
1231 
1232 /*
1233  * Test support for MCSAT
1234  */
1235 #if HAVE_MCSAT
yices_has_mcsat(void)1236 EXPORTED int32_t yices_has_mcsat(void) {
1237   return 1;
1238 }
1239 #else
yices_has_mcsat(void)1240 EXPORTED int32_t yices_has_mcsat(void) {
1241   return 0;
1242 }
1243 #endif
1244 
1245 /*
1246  * Test for thread safety.
1247  */
1248 #ifdef THREAD_SAFE
yices_is_thread_safe(void)1249 EXPORTED int32_t yices_is_thread_safe(void) {
1250   return 1;
1251 }
1252 #else
yices_is_thread_safe(void)1253 EXPORTED int32_t yices_is_thread_safe(void) {
1254   return 0;
1255 }
1256 #endif
1257 
1258 
1259 
1260 /***********************
1261  *  BUFFER ALLOCATION  *
1262  **********************/
1263 
1264 /*
1265  * These functions are not part of the API.
1266  * They are exported to be used by other yices modules.
1267  */
1268 
1269 /*
1270  * Short cuts: extract manager components
1271  */
get_nodes(void)1272 static inline node_table_t *get_nodes(void) {
1273   return term_manager_get_nodes(__yices_globals.manager);
1274 }
1275 
get_bvarith_store(void)1276 static inline object_store_t *get_bvarith_store(void) {
1277   return term_manager_get_bvarith_store(__yices_globals.manager);
1278 }
1279 
get_bvarith64_store(void)1280 static inline object_store_t *get_bvarith64_store(void) {
1281   return term_manager_get_bvarith64_store(__yices_globals.manager);
1282 }
1283 
1284 
get_arith_buffer(void)1285 static inline rba_buffer_t *get_arith_buffer(void) {
1286   return term_manager_get_arith_buffer(__yices_globals.manager);
1287 }
1288 
get_bvarith_buffer(void)1289 static inline bvarith_buffer_t *get_bvarith_buffer(void) {
1290   return term_manager_get_bvarith_buffer(__yices_globals.manager);
1291 }
1292 
get_bvarith64_buffer(void)1293 static inline bvarith64_buffer_t *get_bvarith64_buffer(void) {
1294   return term_manager_get_bvarith64_buffer(__yices_globals.manager);
1295 }
1296 
get_bvlogic_buffer(void)1297 static inline bvlogic_buffer_t *get_bvlogic_buffer(void) {
1298   return term_manager_get_bvlogic_buffer(__yices_globals.manager);
1299 }
1300 
1301 
1302 /*
1303  * Allocate an arithmetic buffer, initialized to the zero polynomial.
1304  * Add it to the buffer list
1305  */
yices_new_arith_buffer(void)1306 rba_buffer_t *yices_new_arith_buffer(void) {
1307   rba_buffer_t *b;
1308 
1309   b = alloc_arith_buffer();
1310   init_rba_buffer(b, __yices_globals.pprods);
1311   return b;
1312 }
1313 
1314 
1315 /*
1316  * Free an allocated buffer
1317  */
yices_free_arith_buffer(rba_buffer_t * b)1318 void yices_free_arith_buffer(rba_buffer_t *b) {
1319   delete_rba_buffer(b);
1320   free_arith_buffer(b);
1321 }
1322 
1323 
1324 /*
1325  * Allocate and initialize a bvarith_buffer
1326  * - the buffer is initialized to 0b0...0 (with n bits)
1327  * - n must be positive and no more than YICES_MAX_BVSIZE
1328  */
yices_new_bvarith_buffer(uint32_t n)1329 bvarith_buffer_t *yices_new_bvarith_buffer(uint32_t n) {
1330   bvarith_buffer_t *b;
1331 
1332   b = alloc_bvarith_buffer();
1333   init_bvarith_buffer(b, __yices_globals.pprods, get_bvarith_store());
1334   bvarith_buffer_prepare(b, n);
1335 
1336   return b;
1337 }
1338 
1339 
1340 /*
1341  * Free an allocated bvarith_buffer
1342  */
yices_free_bvarith_buffer(bvarith_buffer_t * b)1343 void yices_free_bvarith_buffer(bvarith_buffer_t *b) {
1344   delete_bvarith_buffer(b);
1345   free_bvarith_buffer(b);
1346 }
1347 
1348 
1349 /*
1350  * Allocate and initialize a bvarith64_buffer
1351  * - the buffer is initialized to 0b0000..0 (with n bits)
1352  * - n must be between 1 and 64
1353  */
yices_new_bvarith64_buffer(uint32_t n)1354 bvarith64_buffer_t *yices_new_bvarith64_buffer(uint32_t n) {
1355   bvarith64_buffer_t *b;
1356 
1357   b = alloc_bvarith64_buffer();
1358   init_bvarith64_buffer(b, __yices_globals.pprods, get_bvarith64_store());
1359   bvarith64_buffer_prepare(b, n);
1360 
1361   return b;
1362 }
1363 
1364 
1365 /*
1366  * Free an allocated bvarith64_buffer
1367  */
yices_free_bvarith64_buffer(bvarith64_buffer_t * b)1368 void yices_free_bvarith64_buffer(bvarith64_buffer_t *b) {
1369   delete_bvarith64_buffer(b);
1370   free_bvarith64_buffer(b);
1371 }
1372 
1373 
1374 /*
1375  * Allocate and initialize a bvlogic buffer
1376  * - the buffer is empty (bitsize = 0)
1377  */
yices_new_bvlogic_buffer(void)1378 bvlogic_buffer_t *yices_new_bvlogic_buffer(void) {
1379   bvlogic_buffer_t *b;
1380 
1381   b = alloc_bvlogic_buffer();
1382   init_bvlogic_buffer(b, get_nodes());
1383 
1384   return b;
1385 }
1386 
1387 
1388 /*
1389  * Free buffer b allocated by the previous function
1390  */
yices_free_bvlogic_buffer(bvlogic_buffer_t * b)1391 void yices_free_bvlogic_buffer(bvlogic_buffer_t *b) {
1392   bvlogic_buffer_clear(b);
1393   delete_bvlogic_buffer(b);
1394   free_bvlogic_buffer(b);
1395 }
1396 
1397 
1398 
1399 /***************
1400  *  ITERATORS  *
1401  **************/
1402 
arith_buffer_iterate(void * aux,void (* f)(void *,rba_buffer_t *))1403 void arith_buffer_iterate(void *aux, void (*f)(void *, rba_buffer_t *)) {
1404   dl_list_t *elem;
1405 
1406   for (elem = arith_buffer_list.next;
1407        elem != &arith_buffer_list;
1408        elem = elem->next) {
1409     f(aux, arith_buffer(elem));
1410   }
1411 }
1412 
bvarith_buffer_iterate(void * aux,void (* f)(void *,bvarith_buffer_t *))1413 void bvarith_buffer_iterate(void *aux, void (*f)(void *, bvarith_buffer_t *)) {
1414   dl_list_t *elem;
1415 
1416   for (elem = bvarith_buffer_list.next;
1417        elem != &bvarith_buffer_list;
1418        elem = elem->next) {
1419     f(aux, bvarith_buffer(elem));
1420   }
1421 }
1422 
bvarith64_buffer_iterate(void * aux,void (* f)(void *,bvarith64_buffer_t *))1423 void bvarith64_buffer_iterate(void *aux, void (*f)(void *, bvarith64_buffer_t *)) {
1424   dl_list_t *elem;
1425 
1426   for (elem = bvarith64_buffer_list.next;
1427        elem != &bvarith64_buffer_list;
1428        elem = elem->next) {
1429     f(aux, bvarith64_buffer(elem));
1430   }
1431 }
1432 
bvlogic_buffer_iterate(void * aux,void (* f)(void *,bvlogic_buffer_t *))1433 void bvlogic_buffer_iterate(void *aux, void (*f)(void *, bvlogic_buffer_t *)) {
1434   dl_list_t *elem;
1435 
1436   for (elem = bvlogic_buffer_list.next;
1437        elem != &bvlogic_buffer_list;
1438        elem = elem->next) {
1439     f(aux, bvlogic_buffer(elem));
1440   }
1441 }
1442 
context_iterate(void * aux,void (* f)(void *,context_t *))1443 void context_iterate(void *aux, void (*f)(void *, context_t *)) {
1444   dl_list_t *elem;
1445 
1446   for (elem = context_list.next;
1447        elem != &context_list;
1448        elem = elem->next) {
1449     f(aux, context_of_header(elem));
1450   }
1451 }
1452 
model_iterate(void * aux,void (* f)(void *,model_t *))1453 void model_iterate(void *aux, void (*f)(void *, model_t *)) {
1454   dl_list_t *elem;
1455 
1456   for (elem = context_list.next;
1457        elem != &context_list;
1458        elem = elem->next) {
1459     f(aux, model_of_header(elem));
1460   }
1461 }
1462 
1463 
1464 
1465 /****************************************
1466  *  VECTOR INITIALIZATION AND DELETION  *
1467  ***************************************/
1468 
yices_init_term_vector(term_vector_t * v)1469 EXPORTED void yices_init_term_vector(term_vector_t *v) {
1470   v->capacity = 0;
1471   v->size = 0;
1472   v->data = NULL;
1473 }
1474 
yices_init_type_vector(type_vector_t * v)1475 EXPORTED void yices_init_type_vector(type_vector_t *v) {
1476   v->capacity = 0;
1477   v->size = 0;
1478   v->data = NULL;
1479 }
1480 
yices_delete_term_vector(term_vector_t * v)1481 EXPORTED void yices_delete_term_vector(term_vector_t *v) {
1482   safe_free(v->data);
1483   v->data = NULL;
1484 }
1485 
yices_delete_type_vector(type_vector_t * v)1486 EXPORTED void yices_delete_type_vector(type_vector_t *v) {
1487   safe_free(v->data);
1488   v->data = NULL;
1489 }
1490 
1491 #define VECTOR_REDUCE_THRESHOLD 16384
1492 
yices_reset_term_vector(term_vector_t * v)1493 EXPORTED void yices_reset_term_vector(term_vector_t *v) {
1494   v->size = 0;
1495   if (v->capacity > VECTOR_REDUCE_THRESHOLD) {
1496     safe_free(v->data);
1497     v->data = NULL;
1498     v->capacity = 0;
1499   }
1500 }
1501 
yices_reset_type_vector(type_vector_t * v)1502 EXPORTED void yices_reset_type_vector(type_vector_t *v) {
1503   v->size = 0;
1504   if (v->capacity > VECTOR_REDUCE_THRESHOLD) {
1505     safe_free(v->data);
1506     v->data = NULL;
1507     v->capacity = 0;
1508   }
1509 }
1510 
1511 
1512 /*
1513  * Add data at the end of a vector
1514  */
type_vector_push(type_vector_t * v,type_t tau)1515 static inline void type_vector_push(type_vector_t *v, type_t tau) {
1516   ivector_push((ivector_t *) v, tau);
1517 }
1518 
1519 
1520 
1521 /******************
1522  *  TYPECHECKING  *
1523  *****************/
1524 
1525 /*
1526  * All check_ functions return true if the check succeeds.
1527  * Otherwise they return false and set the error code and diagnostic data.
1528  */
1529 
1530 // Check whether n is positive
check_positive(uint32_t n)1531 static bool check_positive(uint32_t n) {
1532   if (n == 0) {
1533     error_report_t *error = get_yices_error();
1534     error->code = POS_INT_REQUIRED;
1535     error->badval = n;
1536     return false;
1537   }
1538   return true;
1539 }
1540 
1541 // Check whether n is less than YICES_MAX_ARITY
check_arity(uint32_t n)1542 static bool check_arity(uint32_t n) {
1543   if (n > YICES_MAX_ARITY) {
1544     error_report_t *error = get_yices_error();
1545     error->code = TOO_MANY_ARGUMENTS;
1546     error->badval = n;
1547     return false;
1548   }
1549   return true;
1550 }
1551 
1552 // Check whether n is less than TYPE_MACRO_MAX_ARITY
check_macro_arity(uint32_t n)1553 static bool check_macro_arity(uint32_t n) {
1554   if (n == 0) {
1555     error_report_t *error = get_yices_error();
1556     error->code = POS_INT_REQUIRED;
1557     error->badval = n;
1558     return false;
1559   }
1560   if (n > TYPE_MACRO_MAX_ARITY) {
1561     error_report_t *error = get_yices_error();
1562     error->code = TOO_MANY_MACRO_PARAMS;
1563     error->badval = n;
1564     return false;
1565   }
1566   return true;
1567 }
1568 
1569 // Check whether n is less than YICES_MAX_VARS
check_maxvars(uint32_t n)1570 static bool check_maxvars(uint32_t n) {
1571   if (n > YICES_MAX_VARS) {
1572     error_report_t *error = get_yices_error();
1573     error->code = TOO_MANY_VARS;
1574     error->badval = n;
1575     return false;
1576   }
1577   return true;
1578 }
1579 
1580 // Check whether n is less than YICES_MAX_BVSIZE
check_maxbvsize(uint32_t n)1581 static bool check_maxbvsize(uint32_t n) {
1582   if (n > YICES_MAX_BVSIZE) {
1583     error_report_t *error = get_yices_error();
1584     error->code = MAX_BVSIZE_EXCEEDED;
1585     error->badval = n;
1586     return false;
1587   }
1588   return true;
1589 }
1590 
1591 // Check whether d is no more than YICES_MAX_DEGREE
check_maxdegree(uint32_t d)1592 static bool check_maxdegree(uint32_t d) {
1593   if (d > YICES_MAX_DEGREE) {
1594     error_report_t *error = get_yices_error();
1595     error->code = DEGREE_OVERFLOW;
1596     error->badval = d;
1597     return false;
1598   }
1599   return true;
1600 }
1601 
1602 // Check whether tau is a valid type
check_good_type(type_table_t * tbl,type_t tau)1603 static bool check_good_type(type_table_t *tbl, type_t tau) {
1604   if (bad_type(tbl, tau)) {
1605     error_report_t *error = get_yices_error();
1606     error->code = INVALID_TYPE;
1607     error->type1 = tau;
1608     return false;
1609   }
1610   return true;
1611 }
1612 
1613 // Check whether all types in a[0 ... n-1] are valid
check_good_types(type_table_t * tbl,uint32_t n,const type_t * a)1614 static bool check_good_types(type_table_t *tbl, uint32_t n, const type_t *a) {
1615   uint32_t i;
1616 
1617   for (i=0; i<n; i++) {
1618     if (bad_type(tbl, a[i])) {
1619       error_report_t *error = get_yices_error();
1620       error->code = INVALID_TYPE;
1621       error->type1 = a[i];
1622       return false;
1623     }
1624   }
1625   return true;
1626 }
1627 
1628 // Check whether all types in a[0 ... n-1] are type variables
check_all_type_variables(type_table_t * tbl,uint32_t n,const type_t * a)1629 static bool check_all_type_variables(type_table_t *tbl, uint32_t n, const type_t *a) {
1630   uint32_t i;
1631 
1632   for (i=0; i<n; i++) {
1633     if (! is_type_variable(tbl, a[i])) {
1634       error_report_t *error = get_yices_error();
1635       error->code = TYPE_VAR_REQUIRED;
1636       error->type1 = a[i];
1637       return false;
1638     }
1639   }
1640   return true;
1641 }
1642 
1643 // Check whether all variables in a[0...n-1] are distinct
check_no_duplicate_type_vars(uint32_t n,const type_t * a)1644 static bool check_no_duplicate_type_vars(uint32_t n, const type_t *a) {
1645   type_t aux[10];
1646   type_t *b;
1647   uint32_t i;
1648   bool result;
1649 
1650   assert(n <= UINT32_MAX/sizeof(type_t)); // because n <= TYPE_MACRO_MAX_ARITY
1651 
1652   result = true;
1653   if (n > 1) {
1654     b = aux;
1655     if (n > 10) {
1656       b = (int32_t *) safe_malloc(n * sizeof(int32_t));
1657     }
1658     for (i=0; i<n; i++) {
1659       b[i] = a[i];
1660     }
1661     int_array_sort(b, n);
1662     for (i=1; i<n; i++) {
1663       if (b[i-1] == b[i]) {
1664 	error_report_t *error = get_yices_error();
1665 	error->code = DUPLICATE_TYPE_VAR;
1666 	error->type1 = b[i];
1667 	result = false;
1668 	break;
1669       }
1670     }
1671     if (n > 10) {
1672       safe_free(b);
1673     }
1674   }
1675 
1676   return result;
1677 }
1678 
1679 
1680 // Check whether tau is a scalar type. tau must be a good type in tbl
check_scalar_type(type_table_t * tbl,type_t tau)1681 static bool check_scalar_type(type_table_t *tbl, type_t tau) {
1682   if (! is_scalar_type(tbl, tau)) {
1683     error_report_t *error = get_yices_error();
1684     error->code = INVALID_TYPE_OP;
1685     error->type1 = tau;
1686     return false;
1687   }
1688   return true;
1689 }
1690 
1691 // Check whether tau is uninterpreted or scalar, and whether
1692 // i a valid constant index for type tau.
check_good_constant(type_table_t * tbl,type_t tau,int32_t i)1693 static bool check_good_constant(type_table_t *tbl, type_t tau, int32_t i) {
1694   type_kind_t kind;
1695 
1696   if (bad_type(tbl, tau)) {
1697     error_report_t *error = get_yices_error();
1698     error->code = INVALID_TYPE;
1699     error->type1 = tau;
1700     return false;
1701   }
1702   kind = type_kind(tbl, tau);
1703   if (kind != UNINTERPRETED_TYPE && kind != SCALAR_TYPE) {
1704     error_report_t *error = get_yices_error();
1705     error->code = SCALAR_OR_UTYPE_REQUIRED;
1706     error->type1 = tau;
1707     return false;
1708   }
1709   if (i < 0 ||
1710       (kind == SCALAR_TYPE && i >= scalar_type_cardinal(tbl, tau))) {
1711     error_report_t *error = get_yices_error();
1712     error->code = INVALID_CONSTANT_INDEX;
1713     error->type1 = tau;
1714     error->badval = i;
1715     return false;
1716   }
1717   return true;
1718 }
1719 
1720 // Check whether tau is a bitvector type (tau is valid)
check_bvtype(type_table_t * tbl,type_t tau)1721 static bool check_bvtype(type_table_t *tbl, type_t tau) {
1722   if (! is_bv_type(tbl, tau)) {
1723     error_report_t *error = get_yices_error();
1724     error->code = BVTYPE_REQUIRED;
1725     error->type1 = tau;
1726     return false;
1727   }
1728   return true;
1729 }
1730 
1731 // Check whether t is a valid term
check_good_term(term_manager_t * mngr,term_t t)1732 static bool check_good_term(term_manager_t *mngr, term_t t) {
1733   term_table_t *tbl;
1734 
1735   tbl = term_manager_get_terms(mngr);
1736   if (bad_term(tbl, t)) {
1737     error_report_t *error = get_yices_error();
1738     error->code = INVALID_TERM;
1739     error->term1 = t;
1740     return false;
1741   }
1742   return true;
1743 }
1744 
1745 // Check that terms in a[0 ... n-1] are valid
check_good_terms(term_manager_t * mngr,uint32_t n,const term_t * a)1746 static bool check_good_terms(term_manager_t *mngr, uint32_t n, const term_t *a) {
1747   term_table_t *tbl;
1748   uint32_t i;
1749 
1750   tbl = term_manager_get_terms(mngr);
1751 
1752   for (i=0; i<n; i++) {
1753     if (bad_term(tbl, a[i])) {
1754       error_report_t *error = get_yices_error();
1755       error->code = INVALID_TERM;
1756       error->term1 = a[i];
1757       return false;
1758     }
1759   }
1760   return true;
1761 }
1762 
1763 // check that terms a[0 ... n-1] have types that match tau[0 ... n-1].
check_arg_types(term_manager_t * mngr,uint32_t n,const term_t * a,const type_t * tau)1764 static bool check_arg_types(term_manager_t *mngr, uint32_t n, const term_t *a, const type_t *tau) {
1765   term_table_t *tbl;
1766   uint32_t i;
1767 
1768   tbl = term_manager_get_terms(mngr);
1769 
1770   for (i=0; i<n; i++) {
1771     if (! is_subtype(tbl->types, term_type(tbl, a[i]), tau[i])) {
1772       error_report_t *error = get_yices_error();
1773       error->code = TYPE_MISMATCH;
1774       error->term1 = a[i];
1775       error->type1 = tau[i];
1776       return false;
1777     }
1778   }
1779 
1780   return true;
1781 }
1782 
1783 // check whether (f a[0] ... a[n-1]) is type correct
check_good_application(term_manager_t * mngr,term_t f,uint32_t n,const term_t * a)1784 static bool check_good_application(term_manager_t *mngr, term_t f, uint32_t n, const term_t *a) {
1785   term_table_t *tbl;
1786   function_type_t *ft;
1787 
1788   if (! check_positive(n) ||
1789       ! check_good_term(mngr, f) ||
1790       ! check_good_terms(mngr, n, a)) {
1791     return false;
1792   }
1793 
1794   tbl = term_manager_get_terms(mngr);
1795 
1796   if (! is_function_term(tbl, f)) {
1797     error_report_t *error = get_yices_error();
1798     error->code = FUNCTION_REQUIRED;
1799     error->term1 = f;
1800     return false;
1801   }
1802 
1803   ft = function_type_desc(tbl->types, term_type(tbl, f));
1804   if (n != ft->ndom) {
1805     error_report_t *error = get_yices_error();
1806     error->code = WRONG_NUMBER_OF_ARGUMENTS;
1807     error->type1 = term_type(tbl, f);
1808     error->badval = n;
1809     return false;
1810   }
1811 
1812   return check_arg_types(mngr, n, a, ft->domain);
1813 }
1814 
1815 // Check whether t is a boolean term. t must be a valid term
check_boolean_term(term_manager_t * mngr,term_t t)1816 static bool check_boolean_term(term_manager_t *mngr, term_t t) {
1817   term_table_t *tbl;
1818 
1819   tbl = term_manager_get_terms(mngr);
1820 
1821   if (! is_boolean_term(tbl, t)) {
1822     error_report_t *error = get_yices_error();
1823     error->code = TYPE_MISMATCH;
1824     error->term1 = t;
1825     error->type1 = bool_type(tbl->types);
1826     return false;
1827   }
1828   return true;
1829 }
1830 
1831 // Check whether t is an arithmetic term, t must be valid.
check_arith_term(term_manager_t * mngr,term_t t)1832 static bool check_arith_term(term_manager_t *mngr, term_t t) {
1833   term_table_t *tbl;
1834 
1835   tbl = term_manager_get_terms(mngr);
1836 
1837   if (! is_arithmetic_term(tbl, t)) {
1838     error_report_t *error = get_yices_error();
1839     error->code = ARITHTERM_REQUIRED;
1840     error->term1 = t;
1841     return false;
1842   }
1843   return true;
1844 }
1845 
1846 // Check whether t is an arithmetic constant, t must be valid
check_arith_constant(term_manager_t * mngr,term_t t)1847 static bool check_arith_constant(term_manager_t *mngr, term_t t) {
1848   term_table_t *tbl;
1849 
1850   tbl = term_manager_get_terms(mngr);
1851 
1852   if (term_kind(tbl, t) != ARITH_CONSTANT) {
1853     error_report_t *error = get_yices_error();
1854     error->code = ARITHCONSTANT_REQUIRED;
1855     error->term1 = t;
1856     return false;
1857   }
1858 
1859   return true;
1860 }
1861 
1862 // Check whether t is a bitvector term, t must be valid
check_bitvector_term(term_manager_t * mngr,term_t t)1863 static bool check_bitvector_term(term_manager_t *mngr, term_t t) {
1864   term_table_t *tbl;
1865 
1866   tbl = term_manager_get_terms(mngr);
1867 
1868   if (! is_bitvector_term(tbl, t)) {
1869     error_report_t *error = get_yices_error();
1870     error->code = BITVECTOR_REQUIRED;
1871     error->term1 = t;
1872     return false;
1873   }
1874   return true;
1875 }
1876 
1877 // Check whether t has a scalar or uninterpreted type, t must be valid
check_scalar_term(term_manager_t * mngr,term_t t)1878 static bool check_scalar_term(term_manager_t *mngr, term_t t) {
1879   term_table_t *tbl;
1880 
1881   tbl = term_manager_get_terms(mngr);
1882 
1883   if (!is_scalar_term(tbl, t) && !is_utype_term(tbl, t)) {
1884     error_report_t *error = get_yices_error();
1885     error->code = SCALAR_TERM_REQUIRED;
1886     error->term1 = t;
1887     return false;
1888   }
1889   return true;
1890 }
1891 
1892 // Check whether t1 and t2 have compatible types (i.e., (= t1 t2) is well-typed)
1893 // t1 and t2 must both be valid
check_compatible_terms(term_manager_t * mngr,term_t t1,term_t t2)1894 static bool check_compatible_terms(term_manager_t *mngr, term_t t1, term_t t2) {
1895   term_table_t *tbl;
1896   type_t tau1, tau2;
1897 
1898   tbl = term_manager_get_terms(mngr);
1899 
1900   tau1 = term_type(tbl, t1);
1901   tau2 = term_type(tbl, t2);
1902   if (! compatible_types(tbl->types, tau1, tau2)) {
1903     error_report_t *error = get_yices_error();
1904     error->code = INCOMPATIBLE_TYPES;
1905     error->term1 = t1;
1906     error->type1 = tau1;
1907     error->term2 = t2;
1908     error->type2 = tau2;
1909     return false;
1910   }
1911 
1912   return true;
1913 }
1914 
1915 // Check whether (= t1 t2) is type correct
check_good_eq(term_manager_t * mngr,term_t t1,term_t t2)1916 static bool check_good_eq(term_manager_t *mngr, term_t t1, term_t t2) {
1917   return check_good_term(mngr, t1) && check_good_term(mngr, t2) &&
1918     check_compatible_terms(mngr, t1, t2);
1919 }
1920 
1921 // Check whether t1 and t2 are two valid arithmetic terms
check_both_arith_terms(term_manager_t * mngr,term_t t1,term_t t2)1922 static bool check_both_arith_terms(term_manager_t *mngr, term_t t1, term_t t2) {
1923   return check_good_term(mngr, t1) && check_good_term(mngr, t2) &&
1924     check_arith_term(mngr, t1) && check_arith_term(mngr, t2);
1925 }
1926 
1927 
1928 // Check that t1 and t2 are bitvectors of the same size
check_compatible_bv_terms(term_manager_t * mngr,term_t t1,term_t t2)1929 static bool check_compatible_bv_terms(term_manager_t *mngr, term_t t1, term_t t2) {
1930   return check_good_term(mngr, t1) && check_good_term(mngr, t2)
1931     && check_bitvector_term(mngr, t1) && check_bitvector_term(mngr, t2)
1932     && check_compatible_terms(mngr, t1, t2);
1933 }
1934 
1935 
1936 // Check whether terms a[0 ... n-1] are all boolean
check_boolean_args(term_manager_t * mngr,uint32_t n,const term_t * a)1937 static bool check_boolean_args(term_manager_t *mngr, uint32_t n, const term_t *a) {
1938   term_table_t *tbl;
1939   uint32_t i;
1940 
1941   tbl = term_manager_get_terms(mngr);
1942 
1943   for (i=0; i<n; i++) {
1944     if (! is_boolean_term(tbl, a[i])) {
1945       error_report_t *error = get_yices_error();
1946       error->code = TYPE_MISMATCH;
1947       error->term1 = a[i];
1948       error->type1 = bool_type(tbl->types);
1949       return false;
1950     }
1951   }
1952 
1953   return true;
1954 }
1955 
1956 // Check whether a[0 ... n-1] are all valid bitvectors
check_bitvector_args(term_manager_t * mngr,uint32_t n,const term_t * a)1957 static bool check_bitvector_args(term_manager_t *mngr, uint32_t n, const term_t *a) {
1958   term_table_t *tbl;
1959   uint32_t i;
1960 
1961   tbl = term_manager_get_terms(mngr);
1962 
1963   for (i=0; i<n; i++) {
1964     if (! is_bitvector_term(tbl, a[i])) {
1965       error_report_t *error = get_yices_error();
1966       error->code = BITVECTOR_REQUIRED;
1967       error->term1 = a[i];
1968       return false;
1969     }
1970   }
1971   return true;
1972 }
1973 
1974 
1975 // Check whether a[0 ... n-1] all have the same type (n must be positive)
1976 // this is used for (bv-and a[0] .... a[n-1]) and other associative bit-vector
1977 // operators
check_same_type(term_manager_t * mngr,uint32_t n,const term_t * a)1978 static bool check_same_type(term_manager_t *mngr, uint32_t n, const term_t *a) {
1979   term_table_t *tbl;
1980   type_t tau0, tau;
1981   uint32_t i;
1982 
1983   assert(n > 0);
1984 
1985   tbl = term_manager_get_terms(mngr);
1986 
1987   tau0 = term_type(tbl, a[0]);
1988   for (i=1; i<n; i++) {
1989     tau = term_type(tbl, a[i]);
1990     if (tau != tau0) {
1991       error_report_t *error = get_yices_error();
1992       error->code = INCOMPATIBLE_TYPES;
1993       error->term1 = a[0];
1994       error->type1 = tau0;
1995       error->term2 = a[i];
1996       error->type2 = tau;
1997       return false;
1998     }
1999   }
2000 
2001   return true;
2002 }
2003 
2004 
2005 
2006 // Check whether terms a[0 ... n-1] are all arithmetic terms
check_arithmetic_args(term_manager_t * mngr,uint32_t n,const term_t * a)2007 static bool check_arithmetic_args(term_manager_t *mngr, uint32_t n, const term_t *a) {
2008   term_table_t *tbl;
2009   uint32_t i;
2010 
2011   tbl = term_manager_get_terms(mngr);
2012 
2013   for (i=0; i<n; i++) {
2014     if (! is_arithmetic_term(tbl, a[i])) {
2015       error_report_t *error = get_yices_error();
2016       error->code = ARITHTERM_REQUIRED;
2017       error->term1 = a[i];
2018       return false;
2019     }
2020   }
2021 
2022   return true;
2023 }
2024 
2025 
2026 // Check whether all numbers den[0 ... n-1] are positive
check_denominators32(uint32_t n,const uint32_t * den)2027 static bool check_denominators32(uint32_t n, const uint32_t *den) {
2028   uint32_t i;
2029 
2030   for (i=0; i<n; i++) {
2031     if (den[i] == 0) {
2032       set_error_code(DIVISION_BY_ZERO);
2033       return false;
2034     }
2035   }
2036 
2037   return true;
2038 }
2039 
2040 
check_denominators64(uint32_t n,const uint64_t * den)2041 static bool check_denominators64(uint32_t n, const uint64_t *den) {
2042   uint32_t i;
2043 
2044   for (i=0; i<n; i++) {
2045     if (den[i] == 0) {
2046       set_error_code(DIVISION_BY_ZERO);
2047       return false;
2048     }
2049   }
2050 
2051   return true;
2052 }
2053 
2054 
2055 // Check whether (tuple-select i t) is well-typed
check_good_select(term_manager_t * mngr,uint32_t i,term_t t)2056 static bool check_good_select(term_manager_t *mngr, uint32_t i, term_t t) {
2057   term_table_t *tbl;
2058   type_t tau;
2059 
2060   if (! check_good_term(mngr, t)) {
2061     return false;
2062   }
2063 
2064   tbl = term_manager_get_terms(mngr);
2065 
2066   tau = term_type(tbl, t);
2067   if (type_kind(tbl->types, tau) != TUPLE_TYPE) {
2068     error_report_t *error = get_yices_error();
2069     error->code = TUPLE_REQUIRED;
2070     error->term1 = t;
2071     return false;
2072   }
2073 
2074   if (i == 0 || i > tuple_type_arity(tbl->types, tau)) {
2075     error_report_t *error = get_yices_error();
2076     error->code = INVALID_TUPLE_INDEX;
2077     error->type1 = tau;
2078     error->badval = i;
2079     return false;
2080   }
2081 
2082   return true;
2083 }
2084 
2085 // Check that (update f (a_1 ... a_n) v) is well typed
check_good_update(term_manager_t * mngr,term_t f,uint32_t n,const term_t * a,term_t v)2086 static bool check_good_update(term_manager_t *mngr, term_t f, uint32_t n, const term_t *a, term_t v) {
2087   term_table_t *tbl;
2088   function_type_t *ft;
2089 
2090   if (! check_positive(n) ||
2091       ! check_good_term(mngr, f) ||
2092       ! check_good_term(mngr, v) ||
2093       ! check_good_terms(mngr, n, a)) {
2094     return false;
2095   }
2096 
2097   tbl = term_manager_get_terms(mngr);
2098 
2099   if (! is_function_term(tbl, f)) {
2100     error_report_t *error = get_yices_error();
2101     error->code = FUNCTION_REQUIRED;
2102     error->term1 = f;
2103     return false;
2104   }
2105 
2106   ft = function_type_desc(tbl->types, term_type(tbl, f));
2107   if (n != ft->ndom) {
2108     error_report_t *error = get_yices_error();
2109     error->code = WRONG_NUMBER_OF_ARGUMENTS;
2110     error->type1 = term_type(tbl, f);
2111     error->badval = n;
2112     return false;
2113   }
2114 
2115   if (! is_subtype(tbl->types, term_type(tbl, v), ft->range)) {
2116     error_report_t *error = get_yices_error();
2117     error->code = TYPE_MISMATCH;
2118     error->term1 = v;
2119     error->type1 = ft->range;
2120     return false;
2121   }
2122 
2123   return check_arg_types(mngr, n, a, ft->domain);
2124 }
2125 
2126 // Check (distinct t_1 ... t_n)
check_good_distinct_term(term_manager_t * mngr,uint32_t n,const term_t * a)2127 static bool check_good_distinct_term(term_manager_t *mngr, uint32_t n, const term_t *a) {
2128   term_table_t *tbl;
2129   uint32_t i;
2130   type_t tau;
2131 
2132   if (! check_positive(n) ||
2133       ! check_arity(n) ||
2134       ! check_good_terms(mngr, n, a)) {
2135     return false;
2136   }
2137 
2138   tbl = term_manager_get_terms(mngr);
2139 
2140   tau = term_type(tbl, a[0]);
2141   for (i=1; i<n; i++) {
2142     tau = super_type(tbl->types, tau, term_type(tbl, a[i]));
2143     if (tau == NULL_TYPE) {
2144       error_report_t *error = get_yices_error();
2145       error->code = INCOMPATIBLE_TYPES;
2146       error->term1 = a[0];
2147       error->type1 = term_type(tbl, a[0]);
2148       error->term2 = a[i];
2149       error->type2 = term_type(tbl, a[i]);
2150       return false;
2151     }
2152   }
2153 
2154   return true;
2155 }
2156 
2157 // Check whether all elements of v are variables
2158 // (this assumes that they are all good terms)
check_good_variables(term_manager_t * mngr,uint32_t n,const term_t * v)2159 static bool check_good_variables(term_manager_t *mngr, uint32_t n, const term_t *v) {
2160   term_table_t *tbl;
2161   uint32_t i;
2162 
2163   tbl = term_manager_get_terms(mngr);
2164 
2165   for (i=0; i<n; i++) {
2166     if (is_neg_term(v[i]) || term_kind(tbl, v[i]) != VARIABLE) {
2167       error_report_t *error = get_yices_error();
2168       error->code = VARIABLE_REQUIRED;
2169       error->term1 = v[i];
2170       return false;
2171     }
2172   }
2173 
2174   return true;
2175 }
2176 
2177 // Check quantified formula (FORALL/EXISTS (v_1 ... v_n) body)
2178 // v must be sorted.
check_good_quantified_term(term_manager_t * mngr,uint32_t n,const term_t * v,term_t body)2179 static bool check_good_quantified_term(term_manager_t *mngr, uint32_t n, const term_t *v, term_t body) {
2180   uint32_t i;
2181 
2182   if (! check_positive(n) ||
2183       ! check_maxvars(n) ||
2184       ! check_good_term(mngr, body) ||
2185       ! check_good_terms(mngr, n, v) ||
2186       ! check_good_variables(mngr, n, v) ||
2187       ! check_boolean_term(mngr, body)) {
2188     return false;
2189   }
2190 
2191   for (i=1; i<n; i++) {
2192     if (v[i-1] == v[i]) {
2193       error_report_t *error = get_yices_error();
2194       error->code = DUPLICATE_VARIABLE;
2195       error->term1 = v[i];
2196       return false;
2197     }
2198   }
2199 
2200   return true;
2201 }
2202 
2203 // Check for duplicates in array v: don't modify v
check_no_duplicates(uint32_t n,const term_t * v)2204 static bool check_no_duplicates(uint32_t n, const term_t *v) {
2205   term_t buffer[10];
2206   term_t *a;
2207   uint32_t i;
2208   bool result;
2209 
2210   assert(n <= UINT32_MAX/sizeof(term_t)); // because n <= YICES_MAX_VARS
2211 
2212   result = true;
2213   if (n > 1) {
2214     a = buffer;
2215     if (n > 10) {
2216       a = (term_t *) safe_malloc(n * sizeof(term_t));
2217     }
2218 
2219     for (i=0; i<n; i++) {
2220       a[i] = v[i];
2221     }
2222     int_array_sort(a, n);
2223     for (i=1; i<n; i++) {
2224       if (a[i-1] == a[i]) {
2225 	error_report_t *error = get_yices_error();
2226         error->code = DUPLICATE_VARIABLE;
2227         error->term1 = a[i];
2228         result = false;
2229         break;
2230       }
2231     }
2232 
2233     if (n > 10) {
2234       safe_free(a);
2235     }
2236   }
2237 
2238   return result;
2239 }
2240 
2241 // Check lambda term: (LAMBDA (v_1 ... v_n) body)
check_good_lambda_term(term_manager_t * mngr,uint32_t n,const term_t * v,term_t body)2242 static bool check_good_lambda_term(term_manager_t *mngr, uint32_t n, const term_t *v, term_t body) {
2243   return
2244     check_positive(n) &&
2245     check_maxvars(n) &&
2246     check_good_term(mngr, body) &&
2247     check_good_terms(mngr, n, v) &&
2248     check_good_variables(mngr, n, v) &&
2249     check_no_duplicates(n, v);
2250 }
2251 
2252 // Check whether (tuple-select i t v) is well-typed
check_good_tuple_update(term_manager_t * mngr,uint32_t i,term_t t,term_t v)2253 static bool check_good_tuple_update(term_manager_t *mngr, uint32_t i, term_t t, term_t v) {
2254   term_table_t *tbl;
2255   type_t tau;
2256   tuple_type_t *desc;
2257 
2258   if (! check_good_term(mngr, t) ||
2259       ! check_good_term(mngr, v)) {
2260     return false;
2261   }
2262 
2263   tbl = term_manager_get_terms(mngr);
2264 
2265   tau = term_type(tbl, t);
2266   if (type_kind(tbl->types, tau) != TUPLE_TYPE) {
2267     error_report_t *error = get_yices_error();
2268     error->code = TUPLE_REQUIRED;
2269     error->term1 = t;
2270     return false;
2271   }
2272 
2273   desc = tuple_type_desc(tbl->types, tau);
2274   if (i == 0 || i > desc->nelem) {
2275     error_report_t *error = get_yices_error();
2276     error->code = INVALID_TUPLE_INDEX;
2277     error->type1 = tau;
2278     error->badval = i;
2279     return false;
2280   }
2281 
2282   // types are indexed from 0 to desc->elem-1 in desc
2283   i --;
2284   if (! is_subtype(tbl->types, term_type(tbl, v), desc->elem[i])) {
2285     error_report_t *error = get_yices_error();
2286     error->code = TYPE_MISMATCH;
2287     error->term1 = v;
2288     error->type1 = desc->elem[i];
2289     return false;
2290   }
2291 
2292   return true;
2293 }
2294 
2295 // Check that the degree of t1 * t2 is at most MAX_DEGREE
check_product_degree(term_manager_t * mngr,term_t t1,term_t t2)2296 static bool check_product_degree(term_manager_t *mngr, term_t t1, term_t t2) {
2297   term_table_t *tbl;
2298   uint32_t d1, d2;
2299 
2300   tbl = term_manager_get_terms(mngr);
2301 
2302   d1 = term_degree(tbl, t1);
2303   d2 = term_degree(tbl, t2);
2304   assert(d1 <= YICES_MAX_DEGREE && d2 <= YICES_MAX_DEGREE);
2305 
2306   return check_maxdegree(d1 + d2);
2307 }
2308 
2309 
2310 // Check that the degree of t^2 does not overflow
check_square_degree(term_manager_t * mngr,term_t t)2311 static bool check_square_degree(term_manager_t *mngr, term_t t) {
2312   term_table_t *tbl;
2313   uint32_t d;
2314 
2315   tbl = term_manager_get_terms(mngr);
2316   d = term_degree(tbl, t);
2317   assert(d <= YICES_MAX_DEGREE);
2318 
2319   return check_maxdegree(d + d);
2320 }
2321 
2322 // Check that the degree of t^n does not overflow
check_power_degree(term_manager_t * mngr,term_t t,uint32_t n)2323 static bool check_power_degree(term_manager_t *mngr, term_t t, uint32_t n) {
2324   term_table_t *tbl;
2325   uint64_t d;
2326 
2327   tbl = term_manager_get_terms(mngr);
2328 
2329   d = (uint64_t) term_degree(tbl, t) * n;
2330   if (d > ((uint64_t) YICES_MAX_DEGREE)) {
2331     error_report_t *error = get_yices_error();
2332     error->code = DEGREE_OVERFLOW;
2333     error->badval = UINT32_MAX;
2334     return false;
2335   }
2336 
2337   return check_maxdegree((uint32_t) d);
2338 }
2339 
2340 
2341 // Check that the degree of t[0] x .... x t[n-1] does not overflow
check_multi_prod_degree(term_manager_t * mngr,uint32_t n,const term_t * t)2342 static bool check_multi_prod_degree(term_manager_t *mngr, uint32_t n, const term_t *t) {
2343   term_table_t *tbl;
2344   uint32_t i, d;
2345 
2346   tbl = term_manager_get_terms(mngr);
2347 
2348   d = 0;
2349   for (i=0; i<n; i++) {
2350     d += term_degree(tbl, t[i]);
2351     if (d > YICES_MAX_DEGREE) {
2352       error_report_t *error = get_yices_error();
2353       error->code = DEGREE_OVERFLOW;
2354       error->badval = d;
2355       return false;
2356     }
2357   }
2358 
2359   return true;
2360 }
2361 
2362 
2363 // Check whether i is a valid shift for bitvectors of size n
check_bitshift(uint32_t i,uint32_t n)2364 static bool check_bitshift(uint32_t i, uint32_t n) {
2365   if (i > n) {
2366     error_report_t *error = get_yices_error();
2367     error->code = INVALID_BITSHIFT;
2368     error->badval = i;
2369     return false;
2370   }
2371 
2372   return true;
2373 }
2374 
2375 // Check whether [i, j] is a valid segment for bitvectors of size n
check_bvextract(uint32_t i,uint32_t j,uint32_t n)2376 static bool check_bvextract(uint32_t i, uint32_t j, uint32_t n) {
2377   if (i > j || j >= n) {
2378     set_error_code(INVALID_BVEXTRACT);
2379     return false;
2380   }
2381   return true;
2382 }
2383 
2384 // Check whether i is a valid bit index for a bitvector of size n
check_bitextract(uint32_t i,uint32_t n)2385 static bool check_bitextract(uint32_t i, uint32_t n) {
2386   if (i >= n) {
2387     set_error_code(INVALID_BITEXTRACT);
2388     return false;
2389   }
2390   return true;
2391 }
2392 
2393 
2394 // Check that t is either a variable or an uninterpreted term
term_is_var_or_uninterpreted(term_table_t * tbl,term_t t)2395 static bool term_is_var_or_uninterpreted(term_table_t *tbl, term_t t) {
2396   assert(good_term(tbl, t) && is_pos_term(t));
2397   switch (term_kind(tbl, t)) {
2398   case VARIABLE:
2399   case UNINTERPRETED_TERM:
2400     return true;
2401   default:
2402   return false;
2403  }
2404 }
2405 
2406 // Check that all terms of v are variables or uninterpreted terms
2407 // all elements of v must be good terms
check_good_vars_or_uninterpreted(term_manager_t * mngr,uint32_t n,const term_t * v)2408 static bool check_good_vars_or_uninterpreted(term_manager_t *mngr, uint32_t n, const term_t *v) {
2409   term_table_t *tbl;
2410   uint32_t i;
2411 
2412   tbl = term_manager_get_terms(mngr);
2413   for (i=0; i<n; i++) {
2414     if (is_neg_term(v[i]) || !term_is_var_or_uninterpreted(tbl, v[i])) {
2415       error_report_t *error = get_yices_error();
2416       error->code = VARIABLE_REQUIRED;
2417       error->term1 = v[i];
2418       return false;
2419     }
2420   }
2421 
2422   return true;
2423 }
2424 
2425 // Check whether arrays v and a define a valid substitution
2426 // both must be arrays of n elements
check_good_substitution(term_manager_t * mngr,uint32_t n,const term_t * v,const term_t * a)2427 static bool check_good_substitution(term_manager_t *mngr, uint32_t n, const term_t *v, const term_t *a) {
2428   term_table_t *tbl;
2429   type_t tau;
2430   uint32_t i;
2431 
2432   if (! check_good_terms(mngr, n, v) ||
2433       ! check_good_terms(mngr, n, a) ||
2434       ! check_good_vars_or_uninterpreted(mngr, n, v)) {
2435     return false;
2436   }
2437 
2438   tbl = term_manager_get_terms(mngr);
2439 
2440   for (i=0; i<n; i++) {
2441     tau = term_type(tbl, v[i]);
2442     if (! is_subtype(tbl->types, term_type(tbl, a[i]), tau)) {
2443       error_report_t *error = get_yices_error();
2444       error->code = TYPE_MISMATCH;
2445       error->term1 = a[i];
2446       error->type1 = tau;
2447       return false;
2448     }
2449   }
2450 
2451   return true;
2452 }
2453 
2454 
2455 /*
2456  * Support for direct model construction given two arrays var and map
2457  */
2458 
2459 // Check that all elements of v are uninterpreted terms
check_all_uninterpreted(term_table_t * terms,uint32_t n,const term_t * var)2460 static bool check_all_uninterpreted(term_table_t *terms, uint32_t n, const term_t *var) {
2461   uint32_t i;
2462   term_t x;
2463 
2464   for (i=0; i<n; i++) {
2465     x = var[i];
2466     if (is_neg_term(x) || term_kind(terms, x) != UNINTERPRETED_TERM) {
2467       error_report_t *error = get_yices_error();
2468       error->code = MDL_UNINT_REQUIRED;
2469       error->term1 = x;
2470       return false;
2471     }
2472   }
2473 
2474   return true;
2475 }
2476 
2477 
2478 // Check that all elements of map are constant (tuple or primitive constants)
check_all_constant(term_table_t * terms,uint32_t n,const term_t * map)2479 static bool check_all_constant(term_table_t *terms, uint32_t n, const term_t *map) {
2480   uint32_t i;
2481 
2482   for (i=0; i<n; i++) {
2483     if (! is_constant_term(terms, map[i])) {
2484       error_report_t *error = get_yices_error();
2485       error->code = MDL_CONSTANT_REQUIRED;
2486       error->term1 = map[i];
2487       return false;
2488     }
2489   }
2490 
2491   return true;
2492 }
2493 
2494 // Check that all elements of var are distinct
2495 // Could be improved: avoid sorting for large n?
check_all_distinct(term_table_t * terms,uint32_t n,const term_t * var)2496 static bool check_all_distinct(term_table_t *terms, uint32_t n, const term_t *var) {
2497   term_t buffer[100];
2498   term_t *a;
2499   uint32_t i;
2500   bool result;
2501 
2502 
2503   result = true;
2504   if (n > 1) {
2505 
2506     if (n > terms->live_terms) {
2507       /*
2508        * there must be duplicates
2509        * we check this first just to be safe
2510        * since n <= terms->live_terms <= YICES_MAX_TERMS,
2511        * we know that n * sizeof(term_t) fits in 32bits
2512        * (which matters when we call safe_malloc(n * sizeof(term_t)).
2513        */
2514       error_report_t *error = get_yices_error();
2515       error->code = MDL_DUPLICATE_VAR;
2516       error->term1 = NULL_TERM;
2517       return false;
2518     }
2519 
2520     assert(n <= UINT32_MAX/sizeof(term_t));
2521 
2522     a = buffer;
2523     if (n > 100) {
2524       a = (term_t *) safe_malloc(n * sizeof(term_t));
2525     }
2526 
2527     for (i=0; i<n; i++) {
2528       a[i] = var[i];
2529     }
2530     int_array_sort(a, n);
2531 
2532     for (i=1; i<n; i++) {
2533       if (a[i-1] == a[i]) {
2534 	error_report_t *error = get_yices_error();
2535 	error->code = MDL_DUPLICATE_VAR;
2536 	error->term1 = a[i];
2537 	result = false;
2538 	break;
2539       }
2540     }
2541 
2542     if (n > 100) {
2543       safe_free(a);
2544     }
2545   }
2546 
2547   return result;
2548 }
2549 
2550 
check_good_model_map(term_manager_t * mngr,uint32_t n,const term_t * var,const term_t * map)2551 static bool check_good_model_map(term_manager_t *mngr, uint32_t n, const term_t *var, const term_t *map) {
2552   term_table_t *terms;
2553   type_t tau;
2554   uint32_t i;
2555 
2556   terms = term_manager_get_terms(mngr);
2557 
2558   if (! check_good_terms(mngr, n, var) ||
2559       ! check_good_terms(mngr, n, map) ||
2560       ! check_all_uninterpreted(terms, n, var) ||
2561       ! check_all_constant(terms, n, map)) {
2562     return false;
2563   }
2564 
2565   for (i=0; i<n; i++) {
2566     tau = term_type(terms, var[i]);
2567     if (! is_subtype(terms->types, term_type(terms, map[i]), tau)) {
2568       error_report_t *error = get_yices_error();
2569       error->code = TYPE_MISMATCH;
2570       error->term1 = map[i];
2571       error->type1 = tau;
2572       return false;
2573     }
2574   }
2575 
2576   if (! check_all_distinct(terms, n, var)) {
2577     return false;
2578   }
2579 
2580   return true;
2581 }
2582 
2583 
2584 
2585 /*
2586  * Check that all elements in var are uninterpreted and have a simple type (for model generalization)
2587  * - for now, simple means either Boolean, or bit-vector, or real, or a scalar type
2588  */
check_elim_vars(term_manager_t * mngr,uint32_t n,const term_t * var)2589 static bool check_elim_vars(term_manager_t *mngr, uint32_t n, const term_t *var) {
2590   term_table_t *terms;
2591   type_table_t *types;
2592   type_t tau;
2593   uint32_t i;
2594 
2595   terms = term_manager_get_terms(mngr);
2596   types = term_manager_get_types(mngr);
2597 
2598   if (! check_good_terms(mngr, n, var) ||
2599       ! check_all_uninterpreted(terms, n, var)) {
2600     return false;
2601   }
2602 
2603   for (i=0; i<n; i++) {
2604     tau = term_type(terms, var[i]);
2605     switch (type_kind(types, tau)) {
2606     case BOOL_TYPE:
2607     case INT_TYPE:
2608     case REAL_TYPE:
2609     case BITVECTOR_TYPE:
2610     case SCALAR_TYPE:
2611       break;
2612 
2613     default:
2614       {
2615 	error_report_t *error = get_yices_error();
2616 	error->code = MDL_GEN_TYPE_NOT_SUPPORTED;
2617 	error->type1 = tau;
2618 	return false;
2619       }
2620     }
2621   }
2622 
2623   return true;
2624 }
2625 
2626 
2627 
2628 /*
2629  * Checks for the term-exploration functions.
2630  * All these checks set the error code to INVALID_TERM_OP
2631  * - t must be a valid term.
2632  */
check_composite(term_table_t * terms,term_t t)2633 static bool check_composite(term_table_t *terms, term_t t) {
2634   if (! term_is_composite(terms, t)) {
2635     set_error_code(INVALID_TERM_OP);
2636     return false;
2637   }
2638 
2639   return true;
2640 }
2641 
check_projection(term_table_t * terms,term_t t)2642 static bool check_projection(term_table_t *terms, term_t t) {
2643   if (! term_is_projection(terms, t)) {
2644     set_error_code(INVALID_TERM_OP);
2645     return false;
2646   }
2647   return true;
2648 }
2649 
check_constructor(term_table_t * terms,term_t t,term_constructor_t c)2650 static bool check_constructor(term_table_t *terms, term_t t, term_constructor_t c) {
2651   if (term_constructor(terms, t) != c) {
2652     set_error_code(INVALID_TERM_OP);
2653     return false;
2654   }
2655   return true;
2656 }
2657 
check_child_idx(term_table_t * terms,term_t t,int32_t i)2658 static bool check_child_idx(term_table_t *terms, term_t t, int32_t i) {
2659   if (i < 0 || i >= term_num_children(terms, t)) {
2660     set_error_code(INVALID_TERM_OP);
2661     return false;
2662   }
2663 
2664   return true;
2665 }
2666 
2667 
2668 
2669 
2670 /***********************
2671  *  TYPE CONSTRUCTORS  *
2672  **********************/
2673 
yices_bool_type(void)2674 EXPORTED type_t yices_bool_type(void) {
2675   MT_PROTECT(type_t, __yices_globals.lock, _o_yices_bool_type());
2676 }
2677 
_o_yices_bool_type(void)2678 type_t _o_yices_bool_type(void) {
2679   return bool_type(__yices_globals.types);
2680 }
2681 
yices_int_type(void)2682 EXPORTED type_t yices_int_type(void) {
2683   MT_PROTECT(type_t, __yices_globals.lock, _o_yices_int_type());
2684 }
2685 
_o_yices_int_type(void)2686 type_t _o_yices_int_type(void) {
2687   return int_type(__yices_globals.types);
2688 }
2689 
yices_real_type(void)2690 EXPORTED type_t yices_real_type(void) {
2691   MT_PROTECT(type_t, __yices_globals.lock, _o_yices_real_type());
2692 }
2693 
_o_yices_real_type(void)2694 type_t _o_yices_real_type(void) {
2695   return real_type(__yices_globals.types);
2696 }
2697 
yices_bv_type(uint32_t size)2698 EXPORTED type_t yices_bv_type(uint32_t size) {
2699   MT_PROTECT(type_t, __yices_globals.lock, _o_yices_bv_type(size));
2700 }
2701 
_o_yices_bv_type(uint32_t size)2702 type_t _o_yices_bv_type(uint32_t size) {
2703   if (! check_positive(size) || ! check_maxbvsize(size)) {
2704     return NULL_TYPE;
2705   }
2706   return bv_type(__yices_globals.types, size);
2707 }
2708 
yices_new_uninterpreted_type(void)2709 EXPORTED type_t yices_new_uninterpreted_type(void) {
2710   MT_PROTECT(type_t, __yices_globals.lock, _o_yices_new_uninterpreted_type());
2711 }
2712 
_o_yices_new_uninterpreted_type(void)2713 type_t _o_yices_new_uninterpreted_type(void) {
2714   return new_uninterpreted_type(__yices_globals.types);
2715 }
2716 
yices_new_scalar_type(uint32_t card)2717 EXPORTED type_t yices_new_scalar_type(uint32_t card) {
2718   MT_PROTECT(type_t, __yices_globals.lock, _o_yices_new_scalar_type(card));
2719 }
2720 
_o_yices_new_scalar_type(uint32_t card)2721 type_t _o_yices_new_scalar_type(uint32_t card) {
2722   if (! check_positive(card)) {
2723     return NULL_TYPE;
2724   }
2725   return new_scalar_type(__yices_globals.types, card);
2726 }
2727 
yices_tuple_type(uint32_t n,const type_t elem[])2728 EXPORTED type_t yices_tuple_type(uint32_t n, const type_t elem[]) {
2729   MT_PROTECT(type_t, __yices_globals.lock, _o_yices_tuple_type(n, elem));
2730 }
2731 
_o_yices_tuple_type(uint32_t n,const type_t elem[])2732 type_t _o_yices_tuple_type(uint32_t n, const type_t elem[]) {
2733   if (! check_positive(n) ||
2734       ! check_arity(n) ||
2735       ! check_good_types(__yices_globals.types, n, elem)) {
2736     return NULL_TYPE;
2737   }
2738   return tuple_type(__yices_globals.types, n, elem);
2739 }
2740 
yices_function_type(uint32_t n,const type_t dom[],type_t range)2741 EXPORTED type_t yices_function_type(uint32_t n, const type_t dom[], type_t range) {
2742   MT_PROTECT( type_t, __yices_globals.lock, _o_yices_function_type(n, dom, range));
2743 }
2744 
_o_yices_function_type(uint32_t n,const type_t dom[],type_t range)2745 type_t _o_yices_function_type(uint32_t n, const type_t dom[], type_t range) {
2746   if (! check_positive(n) ||
2747       ! check_arity(n) ||
2748       ! check_good_type(__yices_globals.types, range) ||
2749       ! check_good_types(__yices_globals.types, n, dom)) {
2750     return NULL_TYPE;
2751   }
2752   return function_type(__yices_globals.types, range, n, dom);
2753 }
2754 
2755 
2756 /*
2757  * Variants/short cuts for tuple and function types
2758  */
yices_tuple_type1(type_t tau1)2759 EXPORTED type_t yices_tuple_type1(type_t tau1) {
2760   return yices_tuple_type(1, &tau1);
2761 }
2762 
yices_tuple_type2(type_t tau1,type_t tau2)2763 EXPORTED type_t yices_tuple_type2(type_t tau1, type_t tau2) {
2764   type_t aux[2];
2765 
2766   aux[0] = tau1;
2767   aux[1] = tau2;
2768 
2769   return yices_tuple_type(2, aux);
2770 }
2771 
yices_tuple_type3(type_t tau1,type_t tau2,type_t tau3)2772 EXPORTED type_t yices_tuple_type3(type_t tau1, type_t tau2, type_t tau3) {
2773   type_t aux[3];
2774 
2775   aux[0] = tau1;
2776   aux[1] = tau2;
2777   aux[2] = tau3;
2778 
2779   return yices_tuple_type(3, aux);
2780 }
2781 
yices_function_type1(type_t tau1,type_t range)2782 EXPORTED type_t yices_function_type1(type_t tau1, type_t range) {
2783   return yices_function_type(1, &tau1, range);
2784 }
2785 
yices_function_type2(type_t tau1,type_t tau2,type_t range)2786 EXPORTED type_t yices_function_type2(type_t tau1, type_t tau2, type_t range) {
2787   type_t aux[2];
2788 
2789   aux[0] = tau1;
2790   aux[1] = tau2;
2791 
2792   return yices_function_type(2, aux, range);
2793 }
2794 
yices_function_type3(type_t tau1,type_t tau2,type_t tau3,type_t range)2795 EXPORTED type_t yices_function_type3(type_t tau1, type_t tau2, type_t tau3, type_t range) {
2796   type_t aux[3];
2797 
2798   aux[0] = tau1;
2799   aux[1] = tau2;
2800   aux[2] = tau3;
2801 
2802   return yices_function_type(3, aux, range);
2803 }
2804 
2805 
2806 
2807 /*
2808  * Type macros and constructors
2809  */
2810 
2811 /*
2812  * Type variable with the given id
2813  */
yices_type_variable(uint32_t id)2814 type_t yices_type_variable(uint32_t id) {
2815   return type_variable(__yices_globals.types, id);
2816 }
2817 
2818 /*
2819  * Create a type constructor:
2820  * - name = its name
2821  * - n = arity
2822  * return -1 if there's an error or the macro id otherwise
2823  */
yices_type_constructor(const char * name,uint32_t n)2824 int32_t yices_type_constructor(const char *name, uint32_t n) {
2825   char *clone;
2826 
2827   if (! check_macro_arity(n)) {
2828     return -1;
2829   }
2830   clone = clone_string(name);
2831   return add_type_constructor(__yices_globals.types, clone, n);
2832 }
2833 
2834 /*
2835  * Create a type macro:
2836  * - name = its name
2837  * - n = arity
2838  * - vars = array of n distinct type variables
2839  * - body = type
2840  *
2841  * return -1 if there's an error or the macro id otherwise
2842  */
yices_type_macro(const char * name,uint32_t n,type_t * vars,type_t body)2843 int32_t yices_type_macro(const char *name, uint32_t n, type_t *vars, type_t body) {
2844   char *clone;
2845 
2846   if (! check_macro_arity(n) ||
2847       ! check_good_type(__yices_globals.types, body) ||
2848       ! check_good_types(__yices_globals.types, n, vars) ||
2849       ! check_all_type_variables(__yices_globals.types, n, vars) ||
2850       ! check_no_duplicate_type_vars(n, vars)) {
2851     return -1;
2852   }
2853 
2854   clone = clone_string(name);
2855   return add_type_macro(__yices_globals.types, clone, n, vars, body);
2856 }
2857 
2858 
2859 /*
2860  * Instance of a macro or constructor
2861  * - cid = constructor or macro id
2862  * - n = number of arguments
2863  * - tau[0 ... n-1] = argument types
2864  *
2865  * return NULL_TYPE if there's an error
2866  */
yices_instance_type(int32_t cid,uint32_t n,type_t tau[])2867 type_t yices_instance_type(int32_t cid, uint32_t n, type_t tau[]) {
2868   type_macro_t *macro;
2869 
2870   macro = type_macro(__yices_globals.types, cid);
2871   if (macro == NULL) {
2872     error_report_t *error = get_yices_error();
2873     error->code = INVALID_MACRO;
2874     error->badval = cid;
2875     return NULL_TYPE;
2876   }
2877 
2878   if (n != macro->arity) {
2879     error_report_t *error = get_yices_error();
2880     error->code = WRONG_NUMBER_OF_ARGUMENTS;
2881     error->type1 = NULL_TYPE;
2882     error->badval = n;
2883     return NULL_TYPE;
2884   }
2885 
2886   if (! check_good_types(__yices_globals.types, n, tau)) {
2887     return NULL_TYPE;
2888   }
2889 
2890   return instantiate_type_macro(__yices_globals.types, cid, n, tau);
2891 }
2892 
2893 
2894 /*
2895  * Get the macro id for a given name
2896  * - return -1 if there's no macro or constructor with that name
2897  */
yices_get_macro_by_name(const char * name)2898 int32_t yices_get_macro_by_name(const char *name) {
2899   return get_type_macro_by_name(__yices_globals.types, name);
2900 }
2901 
2902 
2903 /*
2904  * Remove the mapping of name --> macro id
2905  * - no change if no such mapping exists
2906  */
yices_remove_type_macro_name(const char * name)2907 void yices_remove_type_macro_name(const char *name) {
2908   remove_type_macro_name(__yices_globals.types, name);
2909 }
2910 
2911 /*
2912  * Remove a macro with the given id
2913  * - id must be a valid macro index (non-negative)
2914  */
yices_delete_type_macro(int32_t id)2915 void yices_delete_type_macro(int32_t id) {
2916   delete_type_macro(__yices_globals.types, id);
2917 }
2918 
2919 
2920 
2921 
2922 /***********************
2923  *  TERM CONSTRUCTORS  *
2924  **********************/
2925 
2926 /*
2927  * When constructing a term to singleton type tau, we always
2928  * return the representative for tau (except for variables).
2929  */
yices_true(void)2930 EXPORTED term_t yices_true(void) {
2931   return true_term;
2932 }
2933 
yices_false(void)2934 EXPORTED term_t yices_false(void) {
2935   return false_term;
2936 }
2937 
yices_constant(type_t tau,int32_t index)2938 EXPORTED term_t yices_constant(type_t tau, int32_t index) {
2939   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_constant(tau, index));
2940 }
2941 
_o_yices_constant(type_t tau,int32_t index)2942 term_t _o_yices_constant(type_t tau, int32_t index) {
2943   if (! check_good_constant(__yices_globals.types, tau, index)) {
2944     return NULL_TERM;
2945   }
2946 
2947   return mk_constant(__yices_globals.manager, tau, index);
2948 }
2949 
yices_new_uninterpreted_term(type_t tau)2950 EXPORTED term_t yices_new_uninterpreted_term(type_t tau) {
2951   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_new_uninterpreted_term(tau));
2952 }
2953 
_o_yices_new_uninterpreted_term(type_t tau)2954 term_t _o_yices_new_uninterpreted_term(type_t tau) {
2955   if (! check_good_type(__yices_globals.types, tau)) {
2956     return NULL_TERM;
2957   }
2958 
2959   return mk_uterm(__yices_globals.manager, tau);
2960 }
2961 
yices_new_variable(type_t tau)2962 EXPORTED term_t yices_new_variable(type_t tau) {
2963   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_new_variable(tau));
2964 }
2965 
_o_yices_new_variable(type_t tau)2966 term_t _o_yices_new_variable(type_t tau) {
2967   if (! check_good_type(__yices_globals.types, tau)) {
2968     return NULL_TERM;
2969   }
2970 
2971   return mk_variable(__yices_globals.manager, tau);
2972 }
2973 
2974 
2975 /*
2976  * Apply fun to arg[0 ...n-1]
2977  * - we apply beta-reduction eagerly here
2978  */
yices_application(term_t fun,uint32_t n,const term_t arg[])2979 EXPORTED term_t yices_application(term_t fun, uint32_t n, const term_t arg[]) {
2980   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_application(fun, n, arg));
2981 }
2982 
_o_yices_application(term_t fun,uint32_t n,const term_t arg[])2983 term_t _o_yices_application(term_t fun, uint32_t n, const term_t arg[]) {
2984   term_t t;
2985 
2986   if (! check_good_application(__yices_globals.manager, fun, n, arg)) {
2987     return NULL_TERM;
2988   }
2989 
2990   t = mk_application(__yices_globals.manager, fun, n, arg);
2991   t = beta_reduce(__yices_globals.manager, t);
2992 
2993   if (t < 0) {
2994     // error during beta reduction
2995     error_report_t *error = get_yices_error();
2996     if (t == -1) {
2997       // degree overflow
2998       error->code = DEGREE_OVERFLOW;
2999       error->badval = YICES_MAX_DEGREE + 1;
3000     } else {
3001       // BUG
3002       error->code = INTERNAL_EXCEPTION;
3003     }
3004 
3005     t = NULL_TERM;
3006   }
3007 
3008   return t;
3009 }
3010 
3011 /*
3012  * Variants for small n
3013  */
yices_application1(term_t fun,term_t arg1)3014 EXPORTED term_t yices_application1(term_t fun, term_t arg1) {
3015   return yices_application(fun, 1, &arg1);
3016 }
3017 
yices_application2(term_t fun,term_t arg1,term_t arg2)3018 EXPORTED term_t yices_application2(term_t fun, term_t arg1, term_t arg2) {
3019   term_t aux[2];
3020 
3021   aux[0] = arg1;
3022   aux[1] = arg2;
3023   return yices_application(fun, 2, aux);
3024 }
3025 
yices_application3(term_t fun,term_t arg1,term_t arg2,term_t arg3)3026 EXPORTED term_t yices_application3(term_t fun, term_t arg1, term_t arg2, term_t arg3) {
3027   term_t aux[3];
3028 
3029   aux[0] = arg1;
3030   aux[1] = arg2;
3031   aux[2] = arg3;
3032   return yices_application(fun, 3, aux);
3033 }
3034 
3035 
yices_ite(term_t cond,term_t then_term,term_t else_term)3036 EXPORTED term_t yices_ite(term_t cond, term_t then_term, term_t else_term) {
3037   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_ite(cond, then_term, else_term));
3038 }
3039 
_o_yices_ite(term_t cond,term_t then_term,term_t else_term)3040 term_t _o_yices_ite(term_t cond, term_t then_term, term_t else_term) {
3041   term_table_t *tbl;
3042   type_t tau;
3043 
3044   // Check type correctness: first steps
3045   if (! check_good_term(__yices_globals.manager, cond) ||
3046       ! check_good_term(__yices_globals.manager, then_term) ||
3047       ! check_good_term(__yices_globals.manager, else_term) ||
3048       ! check_boolean_term(__yices_globals.manager, cond)) {
3049     return NULL_TERM;
3050   }
3051 
3052   // Check whether then/else are compatible and get the supertype
3053   tbl = __yices_globals.terms;
3054   tau = super_type(__yices_globals.types, term_type(tbl, then_term), term_type(tbl, else_term));
3055 
3056   if (tau == NULL_TYPE) {
3057     // type error
3058     error_report_t *error = get_yices_error();
3059     error->code = INCOMPATIBLE_TYPES;
3060     error->term1 = then_term;
3061     error->type1 = term_type(tbl, then_term);
3062     error->term2 = else_term;
3063     error->type2 = term_type(tbl, else_term);
3064     return NULL_TERM;
3065   }
3066 
3067   return mk_ite(__yices_globals.manager, cond, then_term, else_term, tau);
3068 }
3069 
yices_eq(term_t left,term_t right)3070 EXPORTED term_t yices_eq(term_t left, term_t right) {
3071   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_eq(left, right));
3072 }
3073 
_o_yices_eq(term_t left,term_t right)3074 term_t _o_yices_eq(term_t left, term_t right) {
3075   if (! check_good_eq(__yices_globals.manager, left, right)) {
3076     return NULL_TERM;
3077   }
3078 
3079   return mk_eq(__yices_globals.manager, left, right);
3080 }
3081 
yices_neq(term_t left,term_t right)3082 EXPORTED term_t yices_neq(term_t left, term_t right) {
3083   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_neq(left, right));
3084 }
3085 
_o_yices_neq(term_t left,term_t right)3086 term_t _o_yices_neq(term_t left, term_t right) {
3087   if (! check_good_eq(__yices_globals.manager, left, right)) {
3088     return NULL_TERM;
3089   }
3090 
3091   return mk_neq(__yices_globals.manager, left, right);
3092 }
3093 
3094 
3095 /*
3096  * BOOLEAN NEGATION
3097  */
yices_not(term_t arg)3098 EXPORTED term_t yices_not(term_t arg) {
3099   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_not(arg));
3100 }
3101 
_o_yices_not(term_t arg)3102 term_t _o_yices_not(term_t arg) {
3103   if (! check_good_term(__yices_globals.manager, arg) ||
3104       ! check_boolean_term(__yices_globals.manager, arg)) {
3105     return NULL_TERM;
3106   }
3107 
3108   return opposite_term(arg);
3109 }
3110 
3111 
3112 /*
3113  * OR, AND, and XOR may modify arg
3114  */
yices_or(uint32_t n,term_t arg[])3115 EXPORTED term_t yices_or(uint32_t n, term_t arg[]) {
3116   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_or(n, arg));
3117 }
3118 
_o_yices_or(uint32_t n,term_t arg[])3119 term_t _o_yices_or(uint32_t n, term_t arg[]) {
3120   if (! check_arity(n) ||
3121       ! check_good_terms(__yices_globals.manager, n, arg) ||
3122       ! check_boolean_args(__yices_globals.manager, n, arg)) {
3123     return NULL_TERM;
3124   }
3125 
3126   switch (n) {
3127   case 0:
3128     return false_term;
3129   case 1:
3130     return arg[0];
3131   case 2:
3132     return mk_binary_or(__yices_globals.manager, arg[0], arg[1]);
3133   default:
3134     return mk_or(__yices_globals.manager, n, arg);
3135   }
3136 }
3137 
yices_and(uint32_t n,term_t arg[])3138 EXPORTED term_t yices_and(uint32_t n, term_t arg[]) {
3139   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_and(n, arg));
3140 }
3141 
_o_yices_and(uint32_t n,term_t arg[])3142 term_t _o_yices_and(uint32_t n, term_t arg[]) {
3143   if (! check_arity(n) ||
3144       ! check_good_terms(__yices_globals.manager, n, arg) ||
3145       ! check_boolean_args(__yices_globals.manager, n, arg)) {
3146     return NULL_TERM;
3147   }
3148 
3149   switch (n) {
3150   case 0:
3151     return true_term;
3152   case 1:
3153     return arg[0];
3154   case 2:
3155     return mk_binary_and(__yices_globals.manager, arg[0], arg[1]);
3156   default:
3157     return mk_and(__yices_globals.manager, n, arg);
3158   }
3159 }
3160 
yices_xor(uint32_t n,term_t arg[])3161 EXPORTED term_t yices_xor(uint32_t n, term_t arg[]) {
3162   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_xor(n, arg));
3163 }
3164 
_o_yices_xor(uint32_t n,term_t arg[])3165 term_t _o_yices_xor(uint32_t n, term_t arg[]) {
3166   if (! check_arity(n) ||
3167       ! check_good_terms(__yices_globals.manager, n, arg) ||
3168       ! check_boolean_args(__yices_globals.manager, n, arg)) {
3169     return NULL_TERM;
3170   }
3171 
3172   switch (n) {
3173   case 0:
3174     return false_term;
3175   case 1:
3176     return arg[0];
3177   case 2:
3178     return mk_binary_xor(__yices_globals.manager, arg[0], arg[1]);
3179   default:
3180     return mk_xor(__yices_globals.manager, n, arg);
3181   }
3182 }
3183 
3184 
3185 
3186 // Variant: 3 arguments
yices_or3(term_t t1,term_t t2,term_t t3)3187 EXPORTED term_t yices_or3(term_t t1, term_t t2, term_t t3) {
3188   term_t aux[3];
3189 
3190   aux[0] = t1;
3191   aux[1] = t2;
3192   aux[2] = t3;
3193 
3194   return yices_or(3, aux);
3195 }
3196 
yices_and3(term_t t1,term_t t2,term_t t3)3197 EXPORTED term_t yices_and3(term_t t1, term_t t2, term_t t3) {
3198   term_t aux[3];
3199 
3200   aux[0] = t1;
3201   aux[1] = t2;
3202   aux[2] = t3;
3203 
3204   return yices_and(3, aux);
3205 }
3206 
yices_xor3(term_t t1,term_t t2,term_t t3)3207 EXPORTED term_t yices_xor3(term_t t1, term_t t2, term_t t3) {
3208   term_t aux[3];
3209 
3210   aux[0] = t1;
3211   aux[1] = t2;
3212   aux[2] = t3;
3213 
3214   return yices_xor(3, aux);
3215 }
3216 
3217 
3218 
3219 /*
3220  * BINARY VERSIONS OF OR/AND/XOR
3221  */
yices_or2(term_t left,term_t right)3222 EXPORTED term_t yices_or2(term_t left, term_t right) {
3223   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_or2(left, right));
3224 }
3225 
_o_yices_or2(term_t left,term_t right)3226 term_t _o_yices_or2(term_t left, term_t right) {
3227   if (! check_good_term(__yices_globals.manager, left) ||
3228       ! check_good_term(__yices_globals.manager, right) ||
3229       ! check_boolean_term(__yices_globals.manager, left) ||
3230       ! check_boolean_term(__yices_globals.manager, right)) {
3231     return NULL_TERM;
3232   }
3233 
3234   return mk_binary_or(__yices_globals.manager, left, right);
3235 }
3236 
yices_and2(term_t left,term_t right)3237 EXPORTED term_t yices_and2(term_t left, term_t right) {
3238   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_and2(left, right));
3239 }
3240 
_o_yices_and2(term_t left,term_t right)3241 term_t _o_yices_and2(term_t left, term_t right) {
3242   if (! check_good_term(__yices_globals.manager, left) ||
3243       ! check_good_term(__yices_globals.manager, right) ||
3244       ! check_boolean_term(__yices_globals.manager, left) ||
3245       ! check_boolean_term(__yices_globals.manager, right)) {
3246     return NULL_TERM;
3247   }
3248 
3249   return mk_binary_and(__yices_globals.manager, left, right);
3250 }
3251 
yices_xor2(term_t left,term_t right)3252 EXPORTED term_t yices_xor2(term_t left, term_t right) {
3253   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_xor2(left, right));
3254 }
3255 
_o_yices_xor2(term_t left,term_t right)3256 term_t _o_yices_xor2(term_t left, term_t right) {
3257   if (! check_good_term(__yices_globals.manager, left) ||
3258       ! check_good_term(__yices_globals.manager, right) ||
3259       ! check_boolean_term(__yices_globals.manager, left) ||
3260       ! check_boolean_term(__yices_globals.manager, right)) {
3261     return NULL_TERM;
3262   }
3263 
3264   return mk_binary_xor(__yices_globals.manager, left, right);
3265 }
3266 
3267 
yices_iff(term_t left,term_t right)3268 EXPORTED term_t yices_iff(term_t left, term_t right) {
3269   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_iff(left, right));
3270 }
3271 
_o_yices_iff(term_t left,term_t right)3272 term_t _o_yices_iff(term_t left, term_t right) {
3273   if (! check_good_term(__yices_globals.manager, left) ||
3274       ! check_good_term(__yices_globals.manager, right) ||
3275       ! check_boolean_term(__yices_globals.manager, left) ||
3276       ! check_boolean_term(__yices_globals.manager, right)) {
3277     return NULL_TERM;
3278   }
3279 
3280   return mk_iff(__yices_globals.manager, left, right);
3281 }
3282 
yices_implies(term_t left,term_t right)3283 EXPORTED term_t yices_implies(term_t left, term_t right) {
3284   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_implies(left, right));
3285 }
3286 
_o_yices_implies(term_t left,term_t right)3287 term_t _o_yices_implies(term_t left, term_t right) {
3288   if (! check_good_term(__yices_globals.manager, left) ||
3289       ! check_good_term(__yices_globals.manager, right) ||
3290       ! check_boolean_term(__yices_globals.manager, left) ||
3291       ! check_boolean_term(__yices_globals.manager, right)) {
3292     return NULL_TERM;
3293   }
3294 
3295   return mk_implies(__yices_globals.manager, left, right);
3296 }
3297 
3298 
yices_tuple(uint32_t n,const term_t arg[])3299 EXPORTED term_t yices_tuple(uint32_t n, const term_t arg[]) {
3300   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_tuple(n, arg));
3301 }
3302 
_o_yices_tuple(uint32_t n,const term_t arg[])3303 term_t _o_yices_tuple(uint32_t n, const term_t arg[]) {
3304   if (! check_positive(n) ||
3305       ! check_arity(n) ||
3306       ! check_good_terms(__yices_globals.manager, n, arg)) {
3307     return NULL_TERM;
3308   }
3309 
3310   return mk_tuple(__yices_globals.manager, n, arg);
3311 }
3312 
3313 // variants for n=2 or n=3
yices_pair(term_t arg1,term_t arg2)3314 EXPORTED term_t yices_pair(term_t arg1, term_t arg2) {
3315   term_t aux[2];
3316 
3317   aux[0] = arg1;
3318   aux[1] = arg2;
3319 
3320   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_tuple(2, aux));
3321 }
3322 
yices_triple(term_t arg1,term_t arg2,term_t arg3)3323 EXPORTED term_t yices_triple(term_t arg1, term_t arg2, term_t arg3) {
3324   term_t aux[3];
3325 
3326   aux[0] = arg1;
3327   aux[1] = arg2;
3328   aux[2] = arg3;
3329 
3330   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_tuple(3, aux));
3331 }
3332 
3333 
3334 
yices_select(uint32_t index,term_t tuple)3335 EXPORTED term_t yices_select(uint32_t index, term_t tuple) {
3336   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_select(index, tuple));
3337 }
3338 
_o_yices_select(uint32_t index,term_t tuple)3339 term_t _o_yices_select(uint32_t index, term_t tuple) {
3340   if (! check_good_select(__yices_globals.manager, index, tuple)) {
3341     return NULL_TERM;
3342   }
3343 
3344   // Warning: internally, tuple components are indexed from 0 to n-1
3345   return mk_select(__yices_globals.manager, index-1, tuple);
3346 }
3347 
yices_update(term_t fun,uint32_t n,const term_t arg[],term_t new_v)3348 EXPORTED term_t yices_update(term_t fun, uint32_t n, const term_t arg[], term_t new_v) {
3349   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_update(fun, n, arg, new_v));
3350 }
3351 
_o_yices_update(term_t fun,uint32_t n,const term_t arg[],term_t new_v)3352 term_t _o_yices_update(term_t fun, uint32_t n, const term_t arg[], term_t new_v) {
3353   if (! check_good_update(__yices_globals.manager, fun, n, arg, new_v)) {
3354     return NULL_TERM;
3355   }
3356 
3357   return mk_update(__yices_globals.manager, fun, n, arg, new_v);
3358 }
3359 
3360 // Variants for n=1, 2, or 3
yices_update1(term_t fun,term_t arg1,term_t new_v)3361 EXPORTED term_t yices_update1(term_t fun, term_t arg1, term_t new_v) {
3362   return yices_update(fun, 1, &arg1, new_v);
3363 }
3364 
yices_update2(term_t fun,term_t arg1,term_t arg2,term_t new_v)3365 EXPORTED term_t yices_update2(term_t fun, term_t arg1, term_t arg2, term_t new_v) {
3366   term_t aux[2];
3367 
3368   aux[0] = arg1;
3369   aux[1] = arg2;
3370   return yices_update(fun, 2, aux, new_v);
3371 }
3372 
yices_update3(term_t fun,term_t arg1,term_t arg2,term_t arg3,term_t new_v)3373 EXPORTED term_t yices_update3(term_t fun, term_t arg1, term_t arg2, term_t arg3, term_t new_v) {
3374   term_t aux[3];
3375 
3376   aux[0] = arg1;
3377   aux[1] = arg2;
3378   aux[2] = arg3;
3379   return yices_update(fun, 3, aux, new_v);
3380 }
3381 
3382 
3383 
yices_distinct(uint32_t n,term_t arg[])3384 EXPORTED term_t yices_distinct(uint32_t n, term_t arg[]) {
3385   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_distinct(n, arg));
3386 }
3387 
_o_yices_distinct(uint32_t n,term_t arg[])3388 term_t _o_yices_distinct(uint32_t n, term_t arg[]) {
3389   if (! check_positive(n) ||
3390       ! check_arity(n) ||
3391       ! check_good_distinct_term(__yices_globals.manager, n, arg)) {
3392     return NULL_TERM;
3393   }
3394 
3395   return mk_distinct(__yices_globals.manager, n, arg);
3396 }
3397 
yices_tuple_update(term_t tuple,uint32_t index,term_t new_v)3398 EXPORTED term_t yices_tuple_update(term_t tuple, uint32_t index, term_t new_v) {
3399   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_tuple_update(tuple, index, new_v));
3400 }
3401 
_o_yices_tuple_update(term_t tuple,uint32_t index,term_t new_v)3402 term_t _o_yices_tuple_update(term_t tuple, uint32_t index, term_t new_v) {
3403   if (! check_good_tuple_update(__yices_globals.manager, index, tuple, new_v)) {
3404     return NULL_TERM;
3405   }
3406 
3407   // Warning: internally components are indexed from 0 to n-1
3408   return mk_tuple_update(__yices_globals.manager, tuple, index-1, new_v);
3409 }
3410 
yices_forall(uint32_t n,term_t var[],term_t body)3411 EXPORTED term_t yices_forall(uint32_t n, term_t var[], term_t body) {
3412   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_forall(n, var, body));
3413 }
3414 
_o_yices_forall(uint32_t n,term_t var[],term_t body)3415 term_t _o_yices_forall(uint32_t n, term_t var[], term_t body) {
3416   if (n > 1) {
3417     int_array_sort(var, n);
3418   }
3419 
3420   if (! check_good_quantified_term(__yices_globals.manager, n, var, body)) {
3421     return NULL_TERM;
3422   }
3423 
3424   return mk_forall(__yices_globals.manager, n, var, body);
3425 }
3426 
yices_exists(uint32_t n,term_t var[],term_t body)3427 EXPORTED term_t yices_exists(uint32_t n, term_t var[], term_t body) {
3428   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_exists(n, var, body));
3429 }
3430 
_o_yices_exists(uint32_t n,term_t var[],term_t body)3431 term_t _o_yices_exists(uint32_t n, term_t var[], term_t body) {
3432   if (n > 1) {
3433     int_array_sort(var, n);
3434   }
3435 
3436   if (! check_good_quantified_term(__yices_globals.manager, n, var, body)) {
3437     return NULL_TERM;
3438   }
3439 
3440   return mk_exists(__yices_globals.manager, n, var, body);
3441 }
3442 
yices_lambda(uint32_t n,const term_t var[],term_t body)3443 EXPORTED term_t yices_lambda(uint32_t n, const term_t var[], term_t body) {
3444   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_lambda(n, var, body));
3445 }
3446 
_o_yices_lambda(uint32_t n,const term_t var[],term_t body)3447 term_t _o_yices_lambda(uint32_t n, const term_t var[], term_t body) {
3448   if (! check_good_lambda_term(__yices_globals.manager, n, var, body)) {
3449     return NULL_TERM;
3450   }
3451 
3452   return mk_lambda(__yices_globals.manager, n, var, body);
3453 }
3454 
3455 
3456 
3457 
3458 /*************************
3459  *  RATIONAL CONSTANTS   *
3460  ************************/
3461 
3462 /*
3463  * Integer constants
3464  */
yices_zero(void)3465 EXPORTED term_t yices_zero(void) {
3466   return zero_term;
3467 }
3468 
yices_int32(int32_t val)3469 EXPORTED term_t yices_int32(int32_t val) {
3470   MT_PROTECT(term_t, __yices_globals.lock, _o_yices_int32(val));
3471 }
3472 
_o_yices_int32(int32_t val)3473 term_t _o_yices_int32(int32_t val) {
3474   q_set32(&r0, val);
3475   return  mk_arith_constant(__yices_globals.manager, &r0);
3476 }
3477 
3478 
yices_int64(int64_t val)3479 EXPORTED term_t yices_int64(int64_t val) {
3480   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_int64(val));
3481 }
3482 
_o_yices_int64(int64_t val)3483 term_t _o_yices_int64(int64_t val) {
3484   q_set64(&r0, val);
3485   return mk_arith_constant(__yices_globals.manager, &r0);
3486 }
3487 
3488 
3489 /*
3490  * Rational constants
3491  */
yices_rational32(int32_t num,uint32_t den)3492 EXPORTED term_t yices_rational32(int32_t num, uint32_t den) {
3493   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_rational32(num, den));
3494 }
3495 
_o_yices_rational32(int32_t num,uint32_t den)3496 term_t _o_yices_rational32(int32_t num, uint32_t den) {
3497   if (den == 0) {
3498     set_error_code(DIVISION_BY_ZERO);
3499     return NULL_TERM;
3500   }
3501 
3502   q_set_int32(&r0, num, den);
3503   return mk_arith_constant(__yices_globals.manager, &r0);
3504 }
3505 
3506 
yices_rational64(int64_t num,uint64_t den)3507 EXPORTED term_t yices_rational64(int64_t num, uint64_t den) {
3508   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_rational64(num, den));
3509 }
3510 
_o_yices_rational64(int64_t num,uint64_t den)3511 term_t _o_yices_rational64(int64_t num, uint64_t den) {
3512   if (den == 0) {
3513     set_error_code(DIVISION_BY_ZERO);
3514     return NULL_TERM;
3515   }
3516 
3517   q_set_int64(&r0, num, den);
3518   return mk_arith_constant(__yices_globals.manager, &r0);
3519 }
3520 
3521 
3522 /*
3523  * Constant from GMP integers or rationals
3524  */
yices_mpz(const mpz_t z)3525 EXPORTED term_t yices_mpz(const mpz_t z) {
3526   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_mpz(z));
3527 }
3528 
_o_yices_mpz(const mpz_t z)3529 term_t _o_yices_mpz(const mpz_t z) {
3530   term_t t;
3531 
3532   q_set_mpz(&r0, z);
3533   t = mk_arith_constant(__yices_globals.manager, &r0);
3534   q_clear(&r0);
3535 
3536   return t;
3537 }
3538 
yices_mpq(const mpq_t q)3539 EXPORTED term_t yices_mpq(const mpq_t q) {
3540   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_mpq(q));
3541 }
3542 
_o_yices_mpq(const mpq_t q)3543 term_t _o_yices_mpq(const mpq_t q) {
3544   term_t t;
3545 
3546   q_set_mpq(&r0, q);
3547   t = mk_arith_constant(__yices_globals.manager, &r0);
3548   q_clear(&r0);
3549 
3550   return t;
3551 }
3552 
3553 
3554 /*
3555  * Convert a string to a rational or integer term.
3556  * The string format is
3557  *     <optional_sign> <numerator>/<denominator>
3558  *  or <optional_sign> <numerator>
3559  *
3560  * where <optional_sign> is + or - or nothing
3561  * <numerator> and <denominator> are sequences of
3562  * decimal digits.
3563  *
3564  * Error report:
3565  *    code = INVALID_RATIONAL_FORMAT
3566  * or code = DIVISION_BY_ZERO
3567  */
3568 
yices_parse_rational(const char * s)3569 EXPORTED term_t yices_parse_rational(const char *s) {
3570   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_parse_rational(s));
3571 }
3572 
_o_yices_parse_rational(const char * s)3573 term_t _o_yices_parse_rational(const char *s) {
3574   int32_t code;
3575   term_t t;
3576 
3577   code = q_set_from_string(&r0, s);
3578   if (code < 0) {
3579     if (code == -1) {
3580       // wrong format
3581       set_error_code(INVALID_RATIONAL_FORMAT);
3582     } else {
3583       // denominator is 0
3584       set_error_code(DIVISION_BY_ZERO);
3585     }
3586     return NULL_TERM;
3587   }
3588 
3589   t = mk_arith_constant(__yices_globals.manager, &r0);
3590   q_clear(&r0);
3591 
3592   return t;
3593 }
3594 
3595 
3596 /*
3597  * Convert a string in floating point format to a rational
3598  * The string must be in one of the following formats:
3599  *   <optional sign> <integer part> . <fractional part>
3600  *   <optional sign> <integer part> <exp> <optional sign> <integer>
3601  *   <optional sign> <integer part> . <fractional part> <exp> <optional sign> <integer>
3602  *
3603  * where <optional sign> is + or - or nothing
3604  *       <exp> is either 'e' or 'E'
3605  *
3606  * Error report:
3607  * code = INVALID_FLOAT_FORMAT
3608  */
yices_parse_float(const char * s)3609 EXPORTED term_t yices_parse_float(const char *s) {
3610   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_parse_float(s));
3611 }
3612 
_o_yices_parse_float(const char * s)3613 term_t _o_yices_parse_float(const char *s) {
3614   term_t t;
3615 
3616   if (q_set_from_float_string(&r0, s) < 0) {
3617     // wrong format
3618     set_error_code(INVALID_FLOAT_FORMAT);
3619     return NULL_TERM;
3620   }
3621 
3622   t = mk_arith_constant(__yices_globals.manager, &r0);
3623   q_clear(&r0);
3624 
3625   return t;
3626 }
3627 
3628 
3629 /***************************
3630  *  ARITHMETIC OPERATIONS  *
3631  **************************/
3632 
3633 /*
3634  * Add t1 and t2
3635  */
yices_add(term_t t1,term_t t2)3636 EXPORTED term_t yices_add(term_t t1, term_t t2) {
3637   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_add(t1, t2));
3638 }
3639 
_o_yices_add(term_t t1,term_t t2)3640 term_t _o_yices_add(term_t t1, term_t t2) {
3641   rba_buffer_t *b;
3642   term_table_t *tbl;
3643 
3644   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
3645     return NULL_TERM;
3646   }
3647 
3648   b = get_arith_buffer();
3649   tbl = __yices_globals.terms;
3650   reset_rba_buffer(b);
3651   rba_buffer_add_term(b, tbl, t1);
3652   rba_buffer_add_term(b, tbl, t2);
3653 
3654   return mk_arith_term(__yices_globals.manager, b);
3655 }
3656 
3657 
3658 /*
3659  * Subtract t2 from t1
3660  */
yices_sub(term_t t1,term_t t2)3661 EXPORTED term_t yices_sub(term_t t1, term_t t2) {
3662   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_sub(t1, t2));
3663 }
3664 
_o_yices_sub(term_t t1,term_t t2)3665 term_t _o_yices_sub(term_t t1, term_t t2) {
3666   rba_buffer_t *b;
3667   term_table_t *tbl;
3668 
3669   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
3670     return NULL_TERM;
3671   }
3672 
3673   b = get_arith_buffer();
3674   tbl = __yices_globals.terms;
3675   reset_rba_buffer(b);
3676   rba_buffer_add_term(b, tbl, t1);
3677   rba_buffer_sub_term(b, tbl, t2);
3678 
3679   return mk_arith_term(__yices_globals.manager, b);
3680 }
3681 
3682 
3683 /*
3684  * Negate t1
3685  */
yices_neg(term_t t1)3686 EXPORTED term_t yices_neg(term_t t1) {
3687   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_neg(t1));
3688 }
3689 
_o_yices_neg(term_t t1)3690 term_t _o_yices_neg(term_t t1) {
3691   rba_buffer_t *b;
3692   term_table_t *tbl;
3693 
3694   if (! check_good_term(__yices_globals.manager, t1) ||
3695       ! check_arith_term(__yices_globals.manager, t1)) {
3696     return NULL_TERM;
3697   }
3698 
3699   b = get_arith_buffer();
3700   tbl = __yices_globals.terms;
3701   reset_rba_buffer(b);
3702   rba_buffer_sub_term(b, tbl, t1);
3703 
3704   return mk_arith_term(__yices_globals.manager, b);
3705 }
3706 
3707 
3708 /*
3709  * Multiply t1 and t2
3710  */
yices_mul(term_t t1,term_t t2)3711 EXPORTED term_t yices_mul(term_t t1, term_t t2) {
3712   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_mul(t1, t2));
3713 }
3714 
_o_yices_mul(term_t t1,term_t t2)3715 term_t _o_yices_mul(term_t t1, term_t t2) {
3716   rba_buffer_t *b;
3717   term_table_t *tbl;
3718 
3719   if (! check_both_arith_terms(__yices_globals.manager, t1, t2) ||
3720       ! check_product_degree(__yices_globals.manager, t1, t2)) {
3721     return NULL_TERM;
3722   }
3723 
3724   b = get_arith_buffer();
3725   tbl = __yices_globals.terms;
3726   reset_rba_buffer(b);
3727   rba_buffer_add_term(b, tbl, t1);
3728   rba_buffer_mul_term(b, tbl, t2);
3729 
3730   return mk_arith_term(__yices_globals.manager, b);
3731 }
3732 
3733 
3734 /*
3735  * Compute the square of t1
3736  */
yices_square(term_t t1)3737 EXPORTED term_t yices_square(term_t t1) {
3738   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_square(t1));
3739 }
3740 
_o_yices_square(term_t t1)3741 term_t _o_yices_square(term_t t1) {
3742   rba_buffer_t *b;
3743   term_table_t *tbl;
3744 
3745   if (! check_good_term(__yices_globals.manager, t1) ||
3746       ! check_arith_term(__yices_globals.manager, t1) ||
3747       ! check_square_degree(__yices_globals.manager, t1)) {
3748     return NULL_TERM;
3749   }
3750 
3751   b = get_arith_buffer();
3752   tbl = __yices_globals.terms;
3753   reset_rba_buffer(b);
3754   rba_buffer_add_term(b, tbl, t1);
3755   rba_buffer_mul_term(b, tbl, t1);
3756 
3757   return mk_arith_term(__yices_globals.manager, b);
3758 }
3759 
3760 
3761 /*
3762  * Compute t1 ^ d
3763  */
yices_power(term_t t1,uint32_t d)3764 EXPORTED term_t yices_power(term_t t1, uint32_t d) {
3765   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_power(t1, d));
3766 }
3767 
_o_yices_power(term_t t1,uint32_t d)3768 term_t _o_yices_power(term_t t1, uint32_t d) {
3769   rba_buffer_t *b;
3770   term_table_t *tbl;
3771 
3772   if (! check_good_term(__yices_globals.manager, t1) ||
3773       ! check_arith_term(__yices_globals.manager, t1) ||
3774       ! check_power_degree(__yices_globals.manager, t1, d)) {
3775     return NULL_TERM;
3776   }
3777 
3778   b = get_arith_buffer();
3779   tbl = __yices_globals.terms;
3780   rba_buffer_set_one(b);
3781   rba_buffer_mul_term_power(b, tbl, t1, d);
3782 
3783   return mk_arith_term(__yices_globals.manager, b);
3784 }
3785 
3786 
3787 /*
3788  * Sum of n terms t[0] ... t[n-1]
3789  */
yices_sum(uint32_t n,const term_t t[])3790 EXPORTED term_t yices_sum(uint32_t n, const term_t t[]) {
3791   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_sum(n, t));
3792 }
3793 
_o_yices_sum(uint32_t n,const term_t t[])3794 term_t _o_yices_sum(uint32_t n, const term_t t[]) {
3795   rba_buffer_t *b;
3796   term_table_t *tbl;
3797   uint32_t i;
3798 
3799   if (! check_good_terms(__yices_globals.manager, n, t) ||
3800       ! check_arithmetic_args(__yices_globals.manager, n, t)) {
3801     return NULL_TERM;
3802   }
3803 
3804   b = get_arith_buffer();
3805   tbl = __yices_globals.terms;
3806   reset_rba_buffer(b);
3807   for (i=0; i<n; i++) {
3808     rba_buffer_add_term(b, tbl, t[i]);
3809   }
3810 
3811   return mk_arith_term(__yices_globals.manager, b);
3812 }
3813 
3814 
3815 /*
3816  * Product of n terms t[0] ... t[n-1]
3817  */
yices_product(uint32_t n,const term_t t[])3818 EXPORTED term_t yices_product(uint32_t n, const term_t t[]) {
3819   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_product(n, t));
3820 }
3821 
_o_yices_product(uint32_t n,const term_t t[])3822 term_t _o_yices_product(uint32_t n, const term_t t[]) {
3823   rba_buffer_t *b;
3824   term_table_t *tbl;
3825   uint32_t i;
3826 
3827   if (! check_good_terms(__yices_globals.manager, n, t) ||
3828       ! check_arithmetic_args(__yices_globals.manager, n, t)) {
3829     return NULL_TERM;
3830   }
3831 
3832   /*
3833    * Check whether one of t[i] is zero.  We must do this first
3834    * otherwise the degree computation won't be correct.
3835    */
3836   for (i=0; i<n; i++) {
3837     if (t[i] == zero_term) {
3838       return zero_term;
3839     }
3840   }
3841 
3842   if (! check_multi_prod_degree(__yices_globals.manager, n, t)) {
3843     return NULL_TERM;
3844   }
3845 
3846   b = get_arith_buffer();
3847   tbl = __yices_globals.terms;
3848   rba_buffer_set_one(b);
3849   for (i=0; i<n; i++) {
3850     rba_buffer_mul_term(b, tbl, t[i]);
3851   }
3852 
3853   return mk_arith_term(__yices_globals.manager, b);
3854 }
3855 
3856 
3857 
3858 
3859 /*
3860  * DIVISION
3861  */
yices_division(term_t t1,term_t t2)3862 EXPORTED term_t yices_division(term_t t1, term_t t2) {
3863   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_division(t1, t2));
3864 }
3865 
_o_yices_division(term_t t1,term_t t2)3866 term_t _o_yices_division(term_t t1, term_t t2) {
3867   if (! check_good_term(__yices_globals.manager, t1) ||
3868       ! check_good_term(__yices_globals.manager, t2) ||
3869       ! check_arith_term(__yices_globals.manager, t1) ||
3870       ! check_arith_term(__yices_globals.manager, t2)) {
3871     return NULL_TERM;
3872   }
3873 
3874   return mk_arith_rdiv(__yices_globals.manager, t1, t2);
3875 }
3876 
3877 
3878 
3879 /***************************
3880  *  DIV/MOD AND RELATIVES  *
3881  **************************/
3882 
yices_idiv(term_t t1,term_t t2)3883 EXPORTED term_t yices_idiv(term_t t1, term_t t2) {
3884   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_idiv(t1, t2));
3885 }
3886 
_o_yices_idiv(term_t t1,term_t t2)3887 term_t _o_yices_idiv(term_t t1, term_t t2) {
3888   if (! check_good_term(__yices_globals.manager, t1) ||
3889       ! check_good_term(__yices_globals.manager, t2) ||
3890       ! check_arith_term(__yices_globals.manager, t1) ||
3891       ! check_arith_term(__yices_globals.manager, t2)) {
3892     return NULL_TERM;
3893   }
3894 
3895   return mk_arith_idiv(__yices_globals.manager, t1, t2);
3896 }
3897 
3898 
yices_imod(term_t t1,term_t t2)3899 EXPORTED term_t yices_imod(term_t t1, term_t t2) {
3900   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_imod(t1, t2));
3901 }
3902 
_o_yices_imod(term_t t1,term_t t2)3903 term_t _o_yices_imod(term_t t1, term_t t2) {
3904   if (! check_good_term(__yices_globals.manager, t1) ||
3905       ! check_good_term(__yices_globals.manager, t2) ||
3906       ! check_arith_term(__yices_globals.manager, t1) ||
3907       ! check_arith_term(__yices_globals.manager, t2)) {
3908     return NULL_TERM;
3909   }
3910 
3911   return mk_arith_mod(__yices_globals.manager, t1, t2);
3912 }
3913 
3914 /*
3915  * Divisibility test: check whether t1 divides t2
3916  */
yices_divides_atom(term_t t1,term_t t2)3917 EXPORTED term_t yices_divides_atom(term_t t1, term_t t2) {
3918   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_divides_atom(t1, t2));
3919 }
3920 
_o_yices_divides_atom(term_t t1,term_t t2)3921 term_t _o_yices_divides_atom(term_t t1, term_t t2) {
3922   if (! check_good_term(__yices_globals.manager, t1) ||
3923       ! check_good_term(__yices_globals.manager, t2) ||
3924       ! check_arith_constant(__yices_globals.manager, t1) ||
3925       ! check_arith_term(__yices_globals.manager, t2)) {
3926     return NULL_TERM;
3927   }
3928 
3929   return mk_arith_divides(__yices_globals.manager, t1, t2);
3930 }
3931 
3932 /*
3933  * Integer test
3934  */
yices_is_int_atom(term_t t)3935 EXPORTED term_t yices_is_int_atom(term_t t) {
3936   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_is_int_atom(t));
3937 }
3938 
_o_yices_is_int_atom(term_t t)3939 term_t _o_yices_is_int_atom(term_t t) {
3940   if (! check_good_term(__yices_globals.manager, t) ||
3941       ! check_arith_term(__yices_globals.manager, t)) {
3942     return NULL_TERM;
3943   }
3944 
3945   return mk_arith_is_int(__yices_globals.manager, t);
3946 }
3947 
3948 
3949 /*
3950  * ABS/FLOOR/CEIL
3951  */
yices_abs(term_t t)3952 EXPORTED term_t yices_abs(term_t t) {
3953   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_abs(t));
3954 }
3955 
_o_yices_abs(term_t t)3956 term_t _o_yices_abs(term_t t) {
3957   if (! check_good_term(__yices_globals.manager, t) ||
3958       ! check_arith_term(__yices_globals.manager, t)) {
3959     return NULL_TERM;
3960   }
3961 
3962   return mk_arith_abs(__yices_globals.manager, t);
3963 }
3964 
yices_floor(term_t t)3965 EXPORTED term_t yices_floor(term_t t) {
3966   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_floor(t));
3967 }
3968 
_o_yices_floor(term_t t)3969 term_t _o_yices_floor(term_t t) {
3970   if (! check_good_term(__yices_globals.manager, t) ||
3971       ! check_arith_term(__yices_globals.manager, t)) {
3972     return NULL_TERM;
3973   }
3974 
3975   return mk_arith_floor(__yices_globals.manager, t);
3976 }
3977 
yices_ceil(term_t t)3978 EXPORTED term_t yices_ceil(term_t t) {
3979   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_ceil(t));
3980 }
3981 
_o_yices_ceil(term_t t)3982 term_t _o_yices_ceil(term_t t) {
3983   if (! check_good_term(__yices_globals.manager, t) ||
3984       ! check_arith_term(__yices_globals.manager, t)) {
3985     return NULL_TERM;
3986   }
3987 
3988   return mk_arith_ceil(__yices_globals.manager, t);
3989 }
3990 
3991 
3992 /*******************
3993  *   POLYNOMIALS   *
3994  ******************/
3995 
3996 /*
3997  * integer coefficients
3998  */
yices_poly_int32(uint32_t n,const int32_t a[],const term_t t[])3999 EXPORTED term_t yices_poly_int32(uint32_t n, const int32_t a[], const term_t t[]) {
4000   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_poly_int32(n, a, t));
4001 }
4002 
_o_yices_poly_int32(uint32_t n,const int32_t a[],const term_t t[])4003 term_t _o_yices_poly_int32(uint32_t n, const int32_t a[], const term_t t[]) {
4004   rba_buffer_t *b;
4005   term_table_t *tbl;
4006   uint32_t i;
4007 
4008   if (! check_good_terms(__yices_globals.manager, n, t) ||
4009       ! check_arithmetic_args(__yices_globals.manager, n, t)) {
4010     return NULL_TERM;
4011   }
4012 
4013   b = get_arith_buffer();
4014   tbl = __yices_globals.terms;
4015   reset_rba_buffer(b);
4016   for (i=0; i<n; i++) {
4017     q_set32(&r0, a[i]);
4018     rba_buffer_add_const_times_term(b, tbl, &r0, t[i]);
4019   }
4020 
4021   return mk_arith_term(__yices_globals.manager, b);
4022 }
4023 
yices_poly_int64(uint32_t n,const int64_t a[],const term_t t[])4024 EXPORTED term_t yices_poly_int64(uint32_t n, const int64_t a[], const term_t t[]) {
4025   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_poly_int64(n, a, t));
4026 }
4027 
_o_yices_poly_int64(uint32_t n,const int64_t a[],const term_t t[])4028 term_t _o_yices_poly_int64(uint32_t n, const int64_t a[], const term_t t[]) {
4029 
4030   rba_buffer_t *b;
4031   term_table_t *tbl;
4032   uint32_t i;
4033 
4034   if (! check_good_terms(__yices_globals.manager, n, t) ||
4035       ! check_arithmetic_args(__yices_globals.manager, n, t)) {
4036     return NULL_TERM;
4037   }
4038 
4039   b = get_arith_buffer();
4040   tbl = __yices_globals.terms;
4041   reset_rba_buffer(b);
4042   for (i=0; i<n; i++) {
4043     q_set64(&r0, a[i]);
4044     rba_buffer_add_const_times_term(b, tbl, &r0, t[i]);
4045   }
4046 
4047   return mk_arith_term(__yices_globals.manager, b);
4048 }
4049 
4050 
4051 /*
4052  * Polynomial with rational coefficients
4053  * - den, num, and t must be arrays of size n
4054  * - the coefficient a_i is num[i]/den[i]
4055  *
4056  * Error report:
4057  * if den[i] is 0
4058  *   code = DIVISION_BY_ZERO
4059  */
yices_poly_rational32(uint32_t n,const int32_t num[],const uint32_t den[],const term_t t[])4060 EXPORTED term_t yices_poly_rational32(uint32_t n, const int32_t num[], const uint32_t den[], const term_t t[]) {
4061   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_poly_rational32(n, num, den, t));
4062 }
4063 
_o_yices_poly_rational32(uint32_t n,const int32_t num[],const uint32_t den[],const term_t t[])4064 term_t _o_yices_poly_rational32(uint32_t n, const int32_t num[], const uint32_t den[], const term_t t[]) {
4065   rba_buffer_t *b;
4066   term_table_t *tbl;
4067   uint32_t i;
4068 
4069   if (! check_good_terms(__yices_globals.manager, n, t) ||
4070       ! check_arithmetic_args(__yices_globals.manager, n, t) ||
4071       ! check_denominators32(n, den)) {
4072     return NULL_TERM;
4073   }
4074 
4075   b = get_arith_buffer();
4076   tbl = __yices_globals.terms;
4077   reset_rba_buffer(b);
4078   for (i=0; i<n; i++) {
4079     q_set_int32(&r0, num[i], den[i]);
4080     rba_buffer_add_const_times_term(b, tbl, &r0, t[i]);
4081   }
4082 
4083   return mk_arith_term(__yices_globals.manager, b);
4084 }
4085 
yices_poly_rational64(uint32_t n,const int64_t num[],const uint64_t den[],const term_t t[])4086 EXPORTED term_t yices_poly_rational64(uint32_t n, const int64_t num[], const uint64_t den[], const term_t t[]) {
4087   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_poly_rational64(n, num, den, t));
4088 }
4089 
_o_yices_poly_rational64(uint32_t n,const int64_t num[],const uint64_t den[],const term_t t[])4090 term_t _o_yices_poly_rational64(uint32_t n, const int64_t num[], const uint64_t den[], const term_t t[]) {
4091   rba_buffer_t *b;
4092   term_table_t *tbl;
4093   uint32_t i;
4094 
4095   if (! check_good_terms(__yices_globals.manager, n, t) ||
4096       ! check_arithmetic_args(__yices_globals.manager, n, t) ||
4097       ! check_denominators64(n, den)) {
4098     return NULL_TERM;
4099   }
4100 
4101   b = get_arith_buffer();
4102   tbl = __yices_globals.terms;
4103   reset_rba_buffer(b);
4104   for (i=0; i<n; i++) {
4105     q_set_int64(&r0, num[i], den[i]);
4106     rba_buffer_add_const_times_term(b, tbl, &r0, t[i]);
4107   }
4108 
4109   return mk_arith_term(__yices_globals.manager, b);
4110 }
4111 
4112 
4113 /*
4114  * GMP integers and rationals
4115  */
yices_poly_mpz(uint32_t n,const mpz_t z[],const term_t t[])4116 EXPORTED term_t yices_poly_mpz(uint32_t n, const mpz_t z[], const term_t t[]) {
4117   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_poly_mpz(n, z, t));
4118 }
4119 
_o_yices_poly_mpz(uint32_t n,const mpz_t z[],const term_t t[])4120 term_t _o_yices_poly_mpz(uint32_t n, const mpz_t z[], const term_t t[]) {
4121   rba_buffer_t *b;
4122   term_table_t *tbl;
4123   uint32_t i;
4124 
4125   if (! check_good_terms(__yices_globals.manager, n, t) ||
4126       ! check_arithmetic_args(__yices_globals.manager, n, t)) {
4127     return NULL_TERM;
4128   }
4129 
4130   b = get_arith_buffer();
4131   tbl = __yices_globals.terms;
4132   reset_rba_buffer(b);
4133   for (i=0; i<n; i++) {
4134     q_set_mpz(&r0, z[i]);
4135     rba_buffer_add_const_times_term(b, tbl, &r0, t[i]);
4136   }
4137 
4138   q_clear(&r0);
4139 
4140   return mk_arith_term(__yices_globals.manager, b);
4141 }
4142 
4143 
4144 
yices_poly_mpq(uint32_t n,const mpq_t q[],const term_t t[])4145 EXPORTED term_t yices_poly_mpq(uint32_t n, const mpq_t q[], const term_t t[]) {
4146   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_poly_mpq(n, q, t));
4147 }
4148 
_o_yices_poly_mpq(uint32_t n,const mpq_t q[],const term_t t[])4149 term_t _o_yices_poly_mpq(uint32_t n, const mpq_t q[], const term_t t[]) {
4150   rba_buffer_t *b;
4151   term_table_t *tbl;
4152   uint32_t i;
4153 
4154   if (! check_good_terms(__yices_globals.manager, n, t) ||
4155       ! check_arithmetic_args(__yices_globals.manager, n, t)) {
4156     return NULL_TERM;
4157   }
4158 
4159   b = get_arith_buffer();
4160   tbl = __yices_globals.terms;
4161   reset_rba_buffer(b);
4162   for (i=0; i<n; i++) {
4163     q_set_mpq(&r0, q[i]);
4164     rba_buffer_add_const_times_term(b, tbl, &r0, t[i]);
4165   }
4166 
4167   q_clear(&r0);
4168 
4169   return mk_arith_term(__yices_globals.manager, b);
4170 }
4171 
4172 
4173 
4174 
4175 
4176 
4177 /**********************
4178  *  ARITHMETIC ATOMS  *
4179  *********************/
4180 
yices_arith_eq_atom(term_t t1,term_t t2)4181 EXPORTED term_t yices_arith_eq_atom(term_t t1, term_t t2) {
4182   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_eq_atom(t1, t2));
4183 }
4184 
_o_yices_arith_eq_atom(term_t t1,term_t t2)4185 term_t _o_yices_arith_eq_atom(term_t t1, term_t t2) {
4186   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
4187     return NULL_TERM;
4188   }
4189   return mk_arith_eq(__yices_globals.manager, t1, t2);
4190 }
4191 
yices_arith_neq_atom(term_t t1,term_t t2)4192 EXPORTED term_t yices_arith_neq_atom(term_t t1, term_t t2) {
4193   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_neq_atom(t1, t2));
4194 }
4195 
_o_yices_arith_neq_atom(term_t t1,term_t t2)4196 term_t _o_yices_arith_neq_atom(term_t t1, term_t t2) {
4197   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
4198     return NULL_TERM;
4199   }
4200   return mk_arith_neq(__yices_globals.manager, t1, t2);
4201 }
4202 
yices_arith_geq_atom(term_t t1,term_t t2)4203 EXPORTED term_t yices_arith_geq_atom(term_t t1, term_t t2) {
4204   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_geq_atom(t1, t2));
4205 }
4206 
_o_yices_arith_geq_atom(term_t t1,term_t t2)4207 term_t _o_yices_arith_geq_atom(term_t t1, term_t t2) {
4208   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
4209     return NULL_TERM;
4210   }
4211   return mk_arith_geq(__yices_globals.manager, t1, t2);
4212 }
4213 
yices_arith_lt_atom(term_t t1,term_t t2)4214 EXPORTED term_t yices_arith_lt_atom(term_t t1, term_t t2) {
4215   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_lt_atom(t1, t2));
4216 }
4217 
_o_yices_arith_lt_atom(term_t t1,term_t t2)4218 term_t _o_yices_arith_lt_atom(term_t t1, term_t t2) {
4219   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
4220     return NULL_TERM;
4221   }
4222   return mk_arith_lt(__yices_globals.manager, t1, t2);
4223 }
4224 
yices_arith_gt_atom(term_t t1,term_t t2)4225 EXPORTED term_t yices_arith_gt_atom(term_t t1, term_t t2) {
4226   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_gt_atom(t1, t2));
4227 }
4228 
_o_yices_arith_gt_atom(term_t t1,term_t t2)4229 term_t _o_yices_arith_gt_atom(term_t t1, term_t t2) {
4230   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
4231     return NULL_TERM;
4232   }
4233   return mk_arith_gt(__yices_globals.manager, t1, t2);
4234 }
4235 
yices_arith_leq_atom(term_t t1,term_t t2)4236 EXPORTED term_t yices_arith_leq_atom(term_t t1, term_t t2) {
4237   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_leq_atom(t1, t2));
4238 }
4239 
_o_yices_arith_leq_atom(term_t t1,term_t t2)4240 term_t _o_yices_arith_leq_atom(term_t t1, term_t t2) {
4241   if (! check_both_arith_terms(__yices_globals.manager, t1, t2)) {
4242     return NULL_TERM;
4243   }
4244   return mk_arith_leq(__yices_globals.manager, t1, t2);
4245 }
4246 
4247 
4248 /*
4249  * Comparison with zero
4250  */
yices_arith_eq0_atom(term_t t)4251 EXPORTED term_t yices_arith_eq0_atom(term_t t) {
4252   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_eq0_atom(t));
4253 }
4254 
_o_yices_arith_eq0_atom(term_t t)4255 term_t _o_yices_arith_eq0_atom(term_t t) {
4256   if (! check_good_term(__yices_globals.manager, t) ||
4257       ! check_arith_term(__yices_globals.manager, t)) {
4258     return NULL_TERM;
4259   }
4260   return mk_arith_term_eq0(__yices_globals.manager, t);
4261 }
4262 
yices_arith_neq0_atom(term_t t)4263 EXPORTED term_t yices_arith_neq0_atom(term_t t) {
4264   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_neq0_atom(t));
4265 }
4266 
_o_yices_arith_neq0_atom(term_t t)4267 term_t _o_yices_arith_neq0_atom(term_t t) {
4268   if (! check_good_term(__yices_globals.manager, t) ||
4269       ! check_arith_term(__yices_globals.manager, t)) {
4270     return NULL_TERM;
4271   }
4272   return mk_arith_term_neq0(__yices_globals.manager, t);
4273 }
4274 
yices_arith_geq0_atom(term_t t)4275 EXPORTED term_t yices_arith_geq0_atom(term_t t) {
4276   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_geq0_atom(t));
4277 }
4278 
_o_yices_arith_geq0_atom(term_t t)4279 term_t _o_yices_arith_geq0_atom(term_t t) {
4280   if (! check_good_term(__yices_globals.manager, t) ||
4281       ! check_arith_term(__yices_globals.manager, t)) {
4282     return NULL_TERM;
4283   }
4284   return mk_arith_term_geq0(__yices_globals.manager, t);
4285 }
4286 
yices_arith_leq0_atom(term_t t)4287 EXPORTED term_t yices_arith_leq0_atom(term_t t) {
4288   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_leq0_atom(t));
4289 }
4290 
_o_yices_arith_leq0_atom(term_t t)4291 term_t _o_yices_arith_leq0_atom(term_t t) {
4292   if (! check_good_term(__yices_globals.manager, t) ||
4293       ! check_arith_term(__yices_globals.manager, t)) {
4294     return NULL_TERM;
4295   }
4296   return mk_arith_term_leq0(__yices_globals.manager, t);
4297 }
4298 
yices_arith_gt0_atom(term_t t)4299 EXPORTED term_t yices_arith_gt0_atom(term_t t) {
4300   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_gt0_atom(t));
4301 }
4302 
_o_yices_arith_gt0_atom(term_t t)4303 term_t _o_yices_arith_gt0_atom(term_t t) {
4304   if (! check_good_term(__yices_globals.manager, t) ||
4305       ! check_arith_term(__yices_globals.manager, t)) {
4306     return NULL_TERM;
4307   }
4308   return mk_arith_term_gt0(__yices_globals.manager, t);
4309 }
4310 
yices_arith_lt0_atom(term_t t)4311 EXPORTED term_t yices_arith_lt0_atom(term_t t) {
4312   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_arith_lt0_atom(t));
4313 }
4314 
_o_yices_arith_lt0_atom(term_t t)4315 term_t _o_yices_arith_lt0_atom(term_t t) {
4316   if (! check_good_term(__yices_globals.manager, t) ||
4317       ! check_arith_term(__yices_globals.manager, t)) {
4318     return NULL_TERM;
4319   }
4320   return mk_arith_term_lt0(__yices_globals.manager, t);
4321 }
4322 
4323 
4324 
4325 /**************************
4326  *  BITVECTOR CONSTANTS   *
4327  *************************/
4328 
yices_bvconst_uint32(uint32_t n,uint32_t x)4329 EXPORTED term_t yices_bvconst_uint32(uint32_t n, uint32_t x) {
4330   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_uint32(n,x));
4331 }
4332 
_o_yices_bvconst_uint32(uint32_t n,uint32_t x)4333 term_t _o_yices_bvconst_uint32(uint32_t n, uint32_t x) {
4334   if (!check_positive(n) || !check_maxbvsize(n)) {
4335     return NULL_TERM;
4336   }
4337 
4338   bvconstant_set_bitsize(&bv0, n);
4339   bvconst_set32(bv0.data, bv0.width, x);
4340 
4341   return mk_bv_constant(__yices_globals.manager, &bv0);
4342 }
4343 
yices_bvconst_uint64(uint32_t n,uint64_t x)4344 EXPORTED term_t yices_bvconst_uint64(uint32_t n, uint64_t x) {
4345   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_uint64(n,x));
4346 }
4347 
_o_yices_bvconst_uint64(uint32_t n,uint64_t x)4348 term_t _o_yices_bvconst_uint64(uint32_t n, uint64_t x) {
4349   if (!check_positive(n) || !check_maxbvsize(n)) {
4350     return NULL_TERM;
4351   }
4352 
4353   bvconstant_set_bitsize(&bv0, n);
4354   bvconst_set64(bv0.data, bv0.width, x);
4355 
4356   return mk_bv_constant(__yices_globals.manager, &bv0);
4357 }
4358 
yices_bvconst_int32(uint32_t n,int32_t x)4359 EXPORTED term_t yices_bvconst_int32(uint32_t n, int32_t x) {
4360   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_int32(n,x));
4361 }
4362 
_o_yices_bvconst_int32(uint32_t n,int32_t x)4363 term_t _o_yices_bvconst_int32(uint32_t n, int32_t x) {
4364   if (!check_positive(n) || !check_maxbvsize(n)) {
4365     return NULL_TERM;
4366   }
4367 
4368   bvconstant_set_bitsize(&bv0, n);
4369   bvconst_set32_signed(bv0.data, bv0.width, x);
4370 
4371   return mk_bv_constant(__yices_globals.manager, &bv0);
4372 }
4373 
yices_bvconst_int64(uint32_t n,int64_t x)4374 EXPORTED term_t yices_bvconst_int64(uint32_t n, int64_t x) {
4375   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_int64(n,x));
4376 }
4377 
_o_yices_bvconst_int64(uint32_t n,int64_t x)4378 term_t _o_yices_bvconst_int64(uint32_t n, int64_t x) {
4379   if (!check_positive(n) || !check_maxbvsize(n)) {
4380     return NULL_TERM;
4381   }
4382 
4383   bvconstant_set_bitsize(&bv0, n);
4384   bvconst_set64_signed(bv0.data, bv0.width, x);
4385 
4386   return mk_bv_constant(__yices_globals.manager, &bv0);
4387 }
4388 
yices_bvconst_mpz(uint32_t n,const mpz_t x)4389 EXPORTED term_t yices_bvconst_mpz(uint32_t n, const mpz_t x) {
4390   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_mpz(n,x));
4391 }
4392 
_o_yices_bvconst_mpz(uint32_t n,const mpz_t x)4393 term_t _o_yices_bvconst_mpz(uint32_t n, const mpz_t x) {
4394   mpz_t aux;
4395 
4396   if (!check_positive(n) || !check_maxbvsize(n)) {
4397     return NULL_TERM;
4398   }
4399 
4400   /*
4401    * bvconst_set_mpz requires x>=0
4402    * for sign-extend, we copy |x| into aux
4403    * copy aux into bv0 then negate bv0
4404    */
4405   bvconstant_set_bitsize(&bv0, n);
4406   if (mpz_sgn(x) >= 0) {
4407     bvconst_set_mpz(bv0.data, bv0.width, x);
4408   } else {
4409     mpz_init_set(aux, x);
4410     mpz_abs(aux, aux);
4411     bvconst_set_mpz(bv0.data, bv0.width, aux);
4412     bvconst_negate(bv0.data, bv0.width);
4413     mpz_clear(aux);
4414   }
4415 
4416   return mk_bv_constant(__yices_globals.manager, &bv0);
4417 }
4418 
4419 
4420 /*
4421  * bvconst_zero: set all bits to 0
4422  * bvconst_one: set low-order bit to 1, all the others to 0
4423  * bvconst_minus_one: set all bits to 1
4424  */
yices_bvconst_zero(uint32_t n)4425 EXPORTED term_t yices_bvconst_zero(uint32_t n) {
4426   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_zero(n));
4427 }
4428 
_o_yices_bvconst_zero(uint32_t n)4429 term_t _o_yices_bvconst_zero(uint32_t n) {
4430   if (!check_positive(n) || !check_maxbvsize(n)) {
4431     return NULL_TERM;
4432   }
4433 
4434   bvconstant_set_all_zero(&bv0, n);
4435 
4436   return mk_bv_constant(__yices_globals.manager, &bv0);
4437 }
4438 
yices_bvconst_one(uint32_t n)4439 EXPORTED term_t yices_bvconst_one(uint32_t n) {
4440   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_one(n));
4441 }
4442 
_o_yices_bvconst_one(uint32_t n)4443 term_t _o_yices_bvconst_one(uint32_t n) {
4444   if (!check_positive(n) || !check_maxbvsize(n)) {
4445     return NULL_TERM;
4446   }
4447 
4448   bvconstant_set_bitsize(&bv0, n);
4449   bvconst_set_one(bv0.data, bv0.width);
4450 
4451   return mk_bv_constant(__yices_globals.manager, &bv0);
4452 }
4453 
yices_bvconst_minus_one(uint32_t n)4454 EXPORTED term_t yices_bvconst_minus_one(uint32_t n) {
4455   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_minus_one(n));
4456 }
4457 
_o_yices_bvconst_minus_one(uint32_t n)4458 term_t _o_yices_bvconst_minus_one(uint32_t n) {
4459   if (!check_positive(n) || !check_maxbvsize(n)) {
4460     return NULL_TERM;
4461   }
4462 
4463   bvconstant_set_all_one(&bv0, n);
4464 
4465   return mk_bv_constant(__yices_globals.manager, &bv0);
4466 }
4467 
4468 
4469 /*
4470  * Convert an integer array to a bit constant
4471  * - a[i] =  0 --> bit i = 0
4472  * - a[i] != 0 --> bit i = 1
4473  */
yices_bvconst_from_array(uint32_t n,const int32_t a[])4474 EXPORTED term_t yices_bvconst_from_array(uint32_t n, const int32_t a[]) {
4475   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconst_from_array(n,a));
4476 }
4477 
_o_yices_bvconst_from_array(uint32_t n,const int32_t a[])4478 term_t _o_yices_bvconst_from_array(uint32_t n, const int32_t a[]) {
4479   if (!check_positive(n) || !check_maxbvsize(n)) {
4480     return NULL_TERM;
4481   }
4482 
4483   bvconstant_set_bitsize(&bv0, n);
4484   bvconst_set_array(bv0.data, a, n);
4485 
4486   return mk_bv_constant(__yices_globals.manager, &bv0);
4487 }
4488 
4489 
4490 
4491 /*
4492  * Parse a string of '0' and '1' and convert to a bit constant
4493  * - the number of bits is the length of s
4494  * - the string is read in big-endian format: the first character
4495  *   is the high-order bit.
4496  */
yices_parse_bvbin(const char * s)4497 EXPORTED term_t yices_parse_bvbin(const char *s) {
4498   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_parse_bvbin(s));
4499 }
4500 
_o_yices_parse_bvbin(const char * s)4501 term_t _o_yices_parse_bvbin(const char *s) {
4502   size_t len;
4503   uint32_t n;
4504   int32_t code;
4505 
4506   len = strlen(s);
4507   if (len == 0) {
4508     set_error_code(INVALID_BVBIN_FORMAT);
4509     return NULL_TERM;
4510   }
4511 
4512   if (len > YICES_MAX_BVSIZE) {
4513     error_report_t *error = get_yices_error();
4514     error->code = MAX_BVSIZE_EXCEEDED;
4515     error->badval = len;
4516     return NULL_TERM;
4517   }
4518 
4519   n = (uint32_t) len;
4520   bvconstant_set_bitsize(&bv0, n);
4521   code = bvconst_set_from_string(bv0.data, n, s);
4522   if (code < 0) {
4523     set_error_code(INVALID_BVBIN_FORMAT);
4524     return NULL_TERM;
4525   }
4526 
4527   return mk_bv_constant(__yices_globals.manager, &bv0);
4528 }
4529 
4530 
4531 /*
4532  * Parse a string of hexadecimal digits and convert it to a bit constant
4533  * - return NULL_TERM if there's a format error
4534  * - the number of bits is four times the length of s
4535  * - the string is read in big-endian format (the first character defines
4536  *   the four high-order bits).
4537  */
yices_parse_bvhex(const char * s)4538 EXPORTED term_t yices_parse_bvhex(const char *s) {
4539   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_parse_bvhex(s));
4540 }
4541 
_o_yices_parse_bvhex(const char * s)4542 term_t _o_yices_parse_bvhex(const char *s) {
4543   size_t len;
4544   uint32_t n;
4545   int32_t code;
4546 
4547   len = strlen(s);
4548   if (len == 0) {
4549     set_error_code(INVALID_BVHEX_FORMAT);
4550     return NULL_TERM;
4551   }
4552 
4553   if (len > YICES_MAX_BVSIZE/4) {
4554     error_report_t *error = get_yices_error();
4555     error->code = MAX_BVSIZE_EXCEEDED;
4556 
4557     // badval is int64_t. It could overflow or get negative here
4558     // if s is a giant string.  We ignore this issue, since it's
4559     // only for information.
4560     error->badval = ((uint64_t) len) * 4;
4561     return NULL_TERM;
4562   }
4563 
4564   n = (uint32_t) len;
4565   bvconstant_set_bitsize(&bv0, 4 * n);
4566   code = bvconst_set_from_hexa_string(bv0.data, n, s);
4567   if (code < 0) {
4568     set_error_code(INVALID_BVHEX_FORMAT);
4569     return NULL_TERM;
4570   }
4571 
4572   return mk_bv_constant(__yices_globals.manager, &bv0);
4573 }
4574 
4575 
4576 
4577 /***************************
4578  *  BIT-VECTOR ARITHMETIC  *
4579  ***************************/
4580 
4581 /*
4582  * Every operation: add/sub/neg/mul/square has two variants
4583  * - one for bitvectors of small size (1 to 64 bits)
4584  * - one for bitvectors of more than 64 bits
4585  */
mk_bvadd64(term_t t1,term_t t2)4586 term_t mk_bvadd64(term_t t1, term_t t2) {
4587   bvarith64_buffer_t *b;
4588   term_table_t *tbl;
4589 
4590   b = get_bvarith64_buffer();
4591   tbl = __yices_globals.terms;
4592   bvarith64_buffer_set_term(b, tbl, t1);
4593   bvarith64_buffer_add_term(b, tbl, t2);
4594 
4595   return mk_bvarith64_term(__yices_globals.manager, b);
4596 }
4597 
mk_bvadd(term_t t1,term_t t2)4598 term_t mk_bvadd(term_t t1, term_t t2) {
4599   bvarith_buffer_t *b;
4600   term_table_t *tbl;
4601 
4602   b = get_bvarith_buffer();
4603   tbl = __yices_globals.terms;
4604   bvarith_buffer_set_term(b, tbl, t1);
4605   bvarith_buffer_add_term(b, tbl, t2);
4606 
4607   return mk_bvarith_term(__yices_globals.manager, b);
4608 }
4609 
yices_bvadd(term_t t1,term_t t2)4610 EXPORTED term_t yices_bvadd(term_t t1, term_t t2) {
4611   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvadd(t1, t2));
4612 }
4613 
_o_yices_bvadd(term_t t1,term_t t2)4614 term_t _o_yices_bvadd(term_t t1, term_t t2) {
4615   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
4616     return NULL_TERM;
4617   }
4618 
4619   if (term_bitsize(__yices_globals.terms, t1) <= 64) {
4620     return mk_bvadd64(t1, t2);
4621   } else {
4622     return mk_bvadd(t1, t2);
4623   }
4624 }
4625 
4626 
mk_bvsub64(term_t t1,term_t t2)4627 term_t mk_bvsub64(term_t t1, term_t t2) {
4628   bvarith64_buffer_t *b;
4629   term_table_t *tbl;
4630 
4631   b = get_bvarith64_buffer();
4632   tbl = __yices_globals.terms;
4633   bvarith64_buffer_set_term(b, tbl, t1);
4634   bvarith64_buffer_sub_term(b, tbl, t2);
4635 
4636   return mk_bvarith64_term(__yices_globals.manager, b);
4637 }
4638 
mk_bvsub(term_t t1,term_t t2)4639 term_t mk_bvsub(term_t t1, term_t t2) {
4640   bvarith_buffer_t *b;
4641   term_table_t *tbl;
4642 
4643   b = get_bvarith_buffer();
4644   tbl = __yices_globals.terms;
4645   bvarith_buffer_set_term(b, tbl, t1);
4646   bvarith_buffer_sub_term(b, tbl, t2);
4647 
4648   return mk_bvarith_term(__yices_globals.manager, b);
4649 }
4650 
yices_bvsub(term_t t1,term_t t2)4651 EXPORTED term_t yices_bvsub(term_t t1, term_t t2) {
4652   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsub(t1, t2));
4653 }
4654 
_o_yices_bvsub(term_t t1,term_t t2)4655 term_t _o_yices_bvsub(term_t t1, term_t t2) {
4656   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
4657     return NULL_TERM;
4658   }
4659 
4660   if (term_bitsize(__yices_globals.terms, t1) <= 64) {
4661     return mk_bvsub64(t1, t2);
4662   } else {
4663     return mk_bvsub(t1, t2);
4664   }
4665 }
4666 
4667 
mk_bvneg64(term_t t1)4668 term_t mk_bvneg64(term_t t1) {
4669   bvarith64_buffer_t *b;
4670   term_table_t *tbl;
4671 
4672   b = get_bvarith64_buffer();
4673   tbl = __yices_globals.terms;
4674   bvarith64_buffer_set_term(b, tbl, t1);
4675   bvarith64_buffer_negate(b);
4676 
4677   return mk_bvarith64_term(__yices_globals.manager, b);
4678 }
4679 
mk_bvneg(term_t t1)4680 term_t mk_bvneg(term_t t1) {
4681   bvarith_buffer_t *b;
4682   term_table_t *tbl;
4683 
4684   b = get_bvarith_buffer();
4685   tbl = __yices_globals.terms;
4686   bvarith_buffer_set_term(b, tbl, t1);
4687   bvarith_buffer_negate(b);
4688 
4689   return mk_bvarith_term(__yices_globals.manager, b);
4690 }
4691 
yices_bvneg(term_t t1)4692 EXPORTED term_t yices_bvneg(term_t t1) {
4693   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvneg(t1));
4694 }
4695 
_o_yices_bvneg(term_t t1)4696 term_t _o_yices_bvneg(term_t t1) {
4697   if (! check_good_term(__yices_globals.manager, t1) ||
4698       ! check_bitvector_term(__yices_globals.manager, t1)) {
4699     return NULL_TERM;
4700   }
4701 
4702   if (term_bitsize(__yices_globals.terms, t1) <= 64) {
4703     return mk_bvneg64(t1);
4704   } else {
4705     return mk_bvneg(t1);
4706   }
4707 }
4708 
4709 
mk_bvmul64(term_t t1,term_t t2)4710 term_t mk_bvmul64(term_t t1, term_t t2) {
4711   bvarith64_buffer_t *b;
4712   term_table_t *tbl;
4713 
4714   b = get_bvarith64_buffer();
4715   tbl = __yices_globals.terms;
4716   bvarith64_buffer_set_term(b, tbl, t1);
4717   bvarith64_buffer_mul_term(b, tbl, t2);
4718 
4719   return mk_bvarith64_term(__yices_globals.manager, b);
4720 }
4721 
mk_bvmul(term_t t1,term_t t2)4722 term_t mk_bvmul(term_t t1, term_t t2) {
4723   bvarith_buffer_t *b;
4724   term_table_t *tbl;
4725 
4726   b = get_bvarith_buffer();
4727   tbl = __yices_globals.terms;
4728   bvarith_buffer_set_term(b, tbl, t1);
4729   bvarith_buffer_mul_term(b, tbl, t2);
4730 
4731   return mk_bvarith_term(__yices_globals.manager, b);
4732 }
4733 
yices_bvmul(term_t t1,term_t t2)4734 EXPORTED term_t yices_bvmul(term_t t1, term_t t2) {
4735   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvmul(t1, t2));
4736 }
4737 
_o_yices_bvmul(term_t t1,term_t t2)4738 term_t _o_yices_bvmul(term_t t1, term_t t2) {
4739   /*
4740    * check_product_degree may overestimate the degree of the product
4741    * (since the product of the coefficients of the leading terms in t1
4742    * and t2 are could be zero).  We can't really do much about this,
4743    * because the bvarith_buffers can't represent the intermediate terms.
4744    */
4745   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2) ||
4746       ! check_product_degree(__yices_globals.manager, t1, t2)) {
4747     return NULL_TERM;
4748   }
4749 
4750   if (term_bitsize(__yices_globals.terms, t1) <= 64) {
4751     return mk_bvmul64(t1, t2);
4752   } else {
4753     return mk_bvmul(t1, t2);
4754   }
4755 }
4756 
4757 
mk_bvsquare64(term_t t1)4758 static term_t mk_bvsquare64(term_t t1) {
4759   bvarith64_buffer_t *b;
4760   term_table_t *tbl;
4761 
4762   b = get_bvarith64_buffer();
4763   tbl = __yices_globals.terms;
4764   bvarith64_buffer_set_term(b, tbl, t1);
4765   bvarith64_buffer_square(b);
4766 
4767   return mk_bvarith64_term(__yices_globals.manager, b);
4768 }
4769 
mk_bvsquare(term_t t1)4770 static term_t mk_bvsquare(term_t t1) {
4771   bvarith_buffer_t *b;
4772   term_table_t *tbl;
4773 
4774   b = get_bvarith_buffer();
4775   tbl = __yices_globals.terms;
4776   bvarith_buffer_set_term(b, tbl, t1);
4777   bvarith_buffer_square(b);
4778 
4779   return mk_bvarith_term(__yices_globals.manager, b);
4780 }
4781 
yices_bvsquare(term_t t1)4782 EXPORTED term_t yices_bvsquare(term_t t1) {
4783   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsquare(t1));
4784 }
4785 
_o_yices_bvsquare(term_t t1)4786 term_t _o_yices_bvsquare(term_t t1) {
4787   /*
4788    * check_square_degree may overestimate the degree of the product
4789    * but we ignore this issue for now. (cf. yices_bvmul)
4790    */
4791   if (! check_good_term(__yices_globals.manager, t1) ||
4792       ! check_bitvector_term(__yices_globals.manager, t1) ||
4793       ! check_square_degree(__yices_globals.manager, t1)) {
4794     return NULL_TERM;
4795   }
4796 
4797   if (term_bitsize(__yices_globals.terms, t1) <= 64) {
4798     return mk_bvsquare64(t1);
4799   } else {
4800     return mk_bvsquare(t1);
4801   }
4802 }
4803 
4804 
mk_bvpower64(term_t t1,uint32_t d)4805 static term_t mk_bvpower64(term_t t1, uint32_t d) {
4806   bvarith64_buffer_t *b;
4807   term_table_t *tbl;
4808   uint32_t n;
4809 
4810   b = get_bvarith64_buffer();
4811   tbl = __yices_globals.terms;
4812   n = term_bitsize(tbl, t1);
4813   bvarith64_buffer_prepare(b, n);
4814   bvarith64_buffer_set_one(b);
4815   bvarith64_buffer_mul_term_power(b, tbl, t1, d);
4816 
4817   return mk_bvarith64_term(__yices_globals.manager, b);
4818 }
4819 
mk_bvpower(term_t t1,uint32_t d)4820 static term_t mk_bvpower(term_t t1, uint32_t d) {
4821   bvarith_buffer_t *b;
4822   term_table_t *tbl;
4823   uint32_t n;
4824 
4825   b = get_bvarith_buffer();
4826   tbl = __yices_globals.terms;
4827   n = term_bitsize(tbl, t1);
4828   bvarith_buffer_prepare(b, n);
4829   bvarith_buffer_set_one(b);
4830   bvarith_buffer_mul_term_power(b, tbl, t1, d);
4831 
4832   return mk_bvarith_term(__yices_globals.manager, b);
4833 }
4834 
yices_bvpower(term_t t1,uint32_t d)4835 EXPORTED term_t yices_bvpower(term_t t1, uint32_t d) {
4836   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvpower(t1, d));
4837 }
4838 
_o_yices_bvpower(term_t t1,uint32_t d)4839 term_t _o_yices_bvpower(term_t t1, uint32_t d) {
4840   /*
4841    * check_power_degree may overestimate the degree of (t1^d)
4842    * but we ignore this for now (cf. yices_bvmul).
4843    */
4844   if (! check_good_term(__yices_globals.manager, t1) ||
4845       ! check_bitvector_term(__yices_globals.manager, t1) ||
4846       ! check_power_degree(__yices_globals.manager, t1, d)) {
4847     return NULL_TERM;
4848   }
4849 
4850   if (term_bitsize(__yices_globals.terms, t1) <= 64) {
4851     return mk_bvpower64(t1, d);
4852   } else {
4853     return mk_bvpower(t1, d);
4854   }
4855 }
4856 
4857 
4858 /************************************
4859  *  N-ARY BIT-VECTOR SUMS/PRODUCTS  *
4860  ***********************************/
4861 
mk_bvsum64(uint32_t n,const term_t t[])4862 static term_t mk_bvsum64(uint32_t n, const term_t t[]) {
4863   bvarith64_buffer_t *b;
4864   term_table_t *tbl;
4865   uint32_t i;
4866 
4867   b = get_bvarith64_buffer();
4868   tbl = __yices_globals.terms;
4869   bvarith64_buffer_set_term(b, tbl, t[0]);
4870   for (i=1; i<n; i++) {
4871     bvarith64_buffer_add_term(b, tbl, t[i]);
4872   }
4873 
4874   return mk_bvarith64_term(__yices_globals.manager, b);
4875 }
4876 
mk_bvsum(uint32_t n,const term_t t[])4877 static term_t mk_bvsum(uint32_t n, const term_t t[]) {
4878   bvarith_buffer_t *b;
4879   term_table_t *tbl;
4880   uint32_t i;
4881 
4882   b = get_bvarith_buffer();
4883   tbl = __yices_globals.terms;
4884   bvarith_buffer_set_term(b, tbl, t[0]);
4885   for (i=1; i<n; i++) {
4886     bvarith_buffer_add_term(b, tbl, t[i]);
4887   }
4888 
4889   return mk_bvarith_term(__yices_globals.manager, b);
4890 }
4891 
yices_bvsum(uint32_t n,const term_t t[])4892 EXPORTED term_t yices_bvsum(uint32_t n, const term_t t[]) {
4893   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsum(n,t));
4894 }
4895 
_o_yices_bvsum(uint32_t n,const term_t t[])4896 term_t _o_yices_bvsum(uint32_t n, const term_t t[]) {
4897   if (! check_positive(n) ||
4898       ! check_good_terms(__yices_globals.manager, n, t) ||
4899       ! check_bitvector_args(__yices_globals.manager, n, t) ||
4900       ! check_same_type(__yices_globals.manager, n, t)) {
4901     return NULL_TERM;
4902   }
4903 
4904   if (term_bitsize(__yices_globals.terms, t[0]) <= 64) {
4905     return mk_bvsum64(n, t);
4906   } else {
4907     return mk_bvsum(n, t);
4908   }
4909 }
4910 
4911 
mk_bvproduct64(uint32_t n,const term_t t[])4912 static term_t mk_bvproduct64(uint32_t n, const term_t t[]) {
4913   bvarith64_buffer_t *b;
4914   term_table_t *tbl;
4915   uint32_t i;
4916 
4917   b = get_bvarith64_buffer();
4918   tbl = __yices_globals.terms;
4919   bvarith64_buffer_set_term(b, tbl, t[0]);
4920   for (i=1; i<n; i++) {
4921     bvarith64_buffer_mul_term(b, tbl, t[i]);
4922   }
4923 
4924   return mk_bvarith64_term(__yices_globals.manager, b);
4925 }
4926 
mk_bvproduct(uint32_t n,const term_t t[])4927 static term_t mk_bvproduct(uint32_t n, const term_t t[]) {
4928   bvarith_buffer_t *b;
4929   term_table_t *tbl;
4930   uint32_t i;
4931 
4932   b = get_bvarith_buffer();
4933   tbl = __yices_globals.terms;
4934   bvarith_buffer_set_term(b, tbl, t[0]);
4935   for (i=1; i<n; i++) {
4936     bvarith_buffer_mul_term(b, tbl, t[i]);
4937   }
4938 
4939   return mk_bvarith_term(__yices_globals.manager, b);
4940 }
4941 
yices_bvproduct(uint32_t n,const term_t t[])4942 EXPORTED term_t yices_bvproduct(uint32_t n, const term_t t[]) {
4943   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvproduct(n,t));
4944 }
4945 
_o_yices_bvproduct(uint32_t n,const term_t t[])4946 term_t _o_yices_bvproduct(uint32_t n, const term_t t[]) {
4947   uint32_t i;
4948 
4949   if (! check_positive(n) ||
4950       ! check_good_terms(__yices_globals.manager, n, t) ||
4951       ! check_bitvector_args(__yices_globals.manager, n, t) ||
4952       ! check_same_type(__yices_globals.manager, n, t)) {
4953     return NULL_TERM;
4954   }
4955 
4956   // check whether one t[i] is zero before checking degrees
4957   for (i=0; i<n; i++) {
4958     if (bvterm_is_zero(__yices_globals.terms, t[i])) {
4959       return t[i];
4960     }
4961   }
4962 
4963   if (! check_multi_prod_degree(__yices_globals.manager, n, t)) {
4964     /*
4965      * check_multi_prod_degree may overestimate  the actual degree but
4966      * a bvarith_buffer/bvarith64_buffer can't  store the intermediate
4967      * results  even  if  the  final   result  has  degree  less  than
4968      * MAX_DEGREE.
4969      */
4970     return NULL_TERM;
4971   }
4972 
4973   if (term_bitsize(__yices_globals.terms, t[0]) <= 64) {
4974     return mk_bvproduct64(n, t);
4975   } else {
4976     return mk_bvproduct(n, t);
4977   }
4978 
4979 }
4980 
4981 
4982 
4983 /***********************************
4984  *  BITWISE BIT-VECTOR OPERATIONS  *
4985  **********************************/
4986 
4987 
yices_bvnot(term_t t1)4988 EXPORTED term_t yices_bvnot(term_t t1) {
4989   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvnot(t1));
4990 }
4991 
_o_yices_bvnot(term_t t1)4992 term_t _o_yices_bvnot(term_t t1) {
4993   bvlogic_buffer_t *b;
4994   term_table_t *tbl;
4995 
4996   if (! check_good_term(__yices_globals.manager, t1) ||
4997       ! check_bitvector_term(__yices_globals.manager, t1)) {
4998     return NULL_TERM;
4999   }
5000 
5001   b = get_bvlogic_buffer();
5002   tbl = __yices_globals.terms;
5003   bvlogic_buffer_set_term(b, tbl, t1);
5004   bvlogic_buffer_not(b);
5005 
5006   return mk_bvlogic_term(__yices_globals.manager, b);
5007 }
5008 
5009 
5010 
yices_bvnand(term_t t1,term_t t2)5011 EXPORTED term_t yices_bvnand(term_t t1, term_t t2) {
5012   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvnand(t1, t2));
5013 }
5014 
_o_yices_bvnand(term_t t1,term_t t2)5015 term_t _o_yices_bvnand(term_t t1, term_t t2) {
5016   bvlogic_buffer_t *b;
5017   term_table_t *tbl;
5018 
5019   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5020     return NULL_TERM;
5021   }
5022 
5023   b = get_bvlogic_buffer();
5024   tbl = __yices_globals.terms;
5025   bvlogic_buffer_set_term(b, tbl, t1);
5026   bvlogic_buffer_and_term(b, tbl, t2);
5027   bvlogic_buffer_not(b);
5028 
5029   return mk_bvlogic_term(__yices_globals.manager, b);
5030 }
5031 
yices_bvnor(term_t t1,term_t t2)5032 EXPORTED term_t yices_bvnor(term_t t1, term_t t2) {
5033   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvnor(t1, t2));
5034 }
5035 
_o_yices_bvnor(term_t t1,term_t t2)5036 term_t _o_yices_bvnor(term_t t1, term_t t2) {
5037   bvlogic_buffer_t *b;
5038   term_table_t *tbl;
5039 
5040   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5041     return NULL_TERM;
5042   }
5043 
5044   b = get_bvlogic_buffer();
5045   tbl = __yices_globals.terms;
5046   bvlogic_buffer_set_term(b, tbl, t1);
5047   bvlogic_buffer_or_term(b, tbl, t2);
5048   bvlogic_buffer_not(b);
5049 
5050   return mk_bvlogic_term(__yices_globals.manager, b);
5051 }
5052 
yices_bvxnor(term_t t1,term_t t2)5053 EXPORTED term_t yices_bvxnor(term_t t1, term_t t2) {
5054   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvxnor(t1, t2));
5055 }
5056 
_o_yices_bvxnor(term_t t1,term_t t2)5057 term_t _o_yices_bvxnor(term_t t1, term_t t2) {
5058   bvlogic_buffer_t *b;
5059   term_table_t *tbl;
5060 
5061   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5062     return NULL_TERM;
5063   }
5064 
5065   b = get_bvlogic_buffer();
5066   tbl = __yices_globals.terms;
5067   bvlogic_buffer_set_term(b, tbl, t1);
5068   bvlogic_buffer_xor_term(b, tbl, t2);
5069   bvlogic_buffer_not(b);
5070 
5071   return mk_bvlogic_term(__yices_globals.manager, b);
5072 }
5073 
5074 
5075 /************************************
5076  *  ASSOCIATIVE BITWISE OPERATIONS  *
5077  ***********************************/
5078 
yices_bvand(uint32_t n,const term_t t[])5079 EXPORTED term_t yices_bvand(uint32_t n, const term_t t[]) {
5080   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvand(n, t));
5081 }
5082 
_o_yices_bvand(uint32_t n,const term_t t[])5083 term_t _o_yices_bvand(uint32_t n, const term_t t[]) {
5084   bvlogic_buffer_t *b;
5085   term_table_t *tbl;
5086   uint32_t i;
5087 
5088   if (! check_positive(n) ||
5089       ! check_good_terms(__yices_globals.manager, n, t) ||
5090       ! check_bitvector_args(__yices_globals.manager, n, t) ||
5091       ! check_same_type(__yices_globals.manager, n, t)) {
5092     return NULL_TERM;
5093   }
5094 
5095   b = get_bvlogic_buffer();
5096   tbl = __yices_globals.terms;
5097   bvlogic_buffer_set_term(b, tbl, t[0]);
5098   for (i=1; i<n; i++) {
5099     bvlogic_buffer_and_term(b, tbl, t[i]);
5100   }
5101 
5102   return mk_bvlogic_term(__yices_globals.manager, b);
5103 }
5104 
yices_bvor(uint32_t n,const term_t t[])5105 EXPORTED term_t yices_bvor(uint32_t n, const term_t t[]) {
5106   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvor(n, t));
5107 }
5108 
_o_yices_bvor(uint32_t n,const term_t t[])5109 term_t _o_yices_bvor(uint32_t n, const term_t t[]) {
5110   bvlogic_buffer_t *b;
5111   term_table_t *tbl;
5112   uint32_t i;
5113 
5114   if (! check_positive(n) ||
5115       ! check_good_terms(__yices_globals.manager, n, t) ||
5116       ! check_bitvector_args(__yices_globals.manager, n, t) ||
5117       ! check_same_type(__yices_globals.manager, n, t)) {
5118     return NULL_TERM;
5119   }
5120 
5121   b = get_bvlogic_buffer();
5122   tbl = __yices_globals.terms;
5123   bvlogic_buffer_set_term(b, tbl, t[0]);
5124   for (i=1; i<n; i++) {
5125     bvlogic_buffer_or_term(b, tbl, t[i]);
5126   }
5127 
5128   return mk_bvlogic_term(__yices_globals.manager, b);
5129 }
5130 
yices_bvxor(uint32_t n,const term_t t[])5131 EXPORTED term_t yices_bvxor(uint32_t n, const term_t t[]) {
5132   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvxor(n, t));
5133 }
5134 
_o_yices_bvxor(uint32_t n,const term_t t[])5135 term_t _o_yices_bvxor(uint32_t n, const term_t t[]) {
5136   bvlogic_buffer_t *b;
5137   term_table_t *tbl;
5138   uint32_t i;
5139 
5140   if (! check_positive(n) ||
5141       ! check_good_terms(__yices_globals.manager, n, t) ||
5142       ! check_bitvector_args(__yices_globals.manager, n, t) ||
5143       ! check_same_type(__yices_globals.manager, n, t)) {
5144     return NULL_TERM;
5145   }
5146 
5147   b = get_bvlogic_buffer();
5148   tbl = __yices_globals.terms;
5149   bvlogic_buffer_set_term(b, tbl, t[0]);
5150   for (i=1; i<n; i++) {
5151     bvlogic_buffer_xor_term(b, tbl, t[i]);
5152   }
5153 
5154   return mk_bvlogic_term(__yices_globals.manager, b);
5155 }
5156 
5157 
yices_bvand2(term_t t1,term_t t2)5158 EXPORTED term_t yices_bvand2(term_t t1, term_t t2) {
5159   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvand2(t1, t2));
5160 }
5161 
_o_yices_bvand2(term_t t1,term_t t2)5162 term_t _o_yices_bvand2(term_t t1, term_t t2) {
5163   bvlogic_buffer_t *b;
5164   term_table_t *tbl;
5165 
5166   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5167     return NULL_TERM;
5168   }
5169 
5170   b = get_bvlogic_buffer();
5171   tbl = __yices_globals.terms;
5172   bvlogic_buffer_set_term(b, tbl, t1);
5173   bvlogic_buffer_and_term(b, tbl, t2);
5174 
5175   return mk_bvlogic_term(__yices_globals.manager, b);
5176 }
5177 
yices_bvor2(term_t t1,term_t t2)5178 EXPORTED term_t yices_bvor2(term_t t1, term_t t2) {
5179   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvor2(t1, t2));
5180 }
5181 
_o_yices_bvor2(term_t t1,term_t t2)5182 term_t _o_yices_bvor2(term_t t1, term_t t2) {
5183   bvlogic_buffer_t *b;
5184   term_table_t *tbl;
5185 
5186   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5187     return NULL_TERM;
5188   }
5189 
5190   b = get_bvlogic_buffer();
5191   tbl = __yices_globals.terms;
5192   bvlogic_buffer_set_term(b, tbl, t1);
5193   bvlogic_buffer_or_term(b, tbl, t2);
5194 
5195   return mk_bvlogic_term(__yices_globals.manager, b);
5196 }
5197 
yices_bvxor2(term_t t1,term_t t2)5198 EXPORTED term_t yices_bvxor2(term_t t1, term_t t2) {
5199   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvxor2(t1,t2));
5200 }
5201 
_o_yices_bvxor2(term_t t1,term_t t2)5202 term_t _o_yices_bvxor2(term_t t1, term_t t2) {
5203   bvlogic_buffer_t *b;
5204   term_table_t *tbl;
5205 
5206   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5207     return NULL_TERM;
5208   }
5209 
5210   b = get_bvlogic_buffer();
5211   tbl = __yices_globals.terms;
5212   bvlogic_buffer_set_term(b, tbl, t1);
5213   bvlogic_buffer_xor_term(b, tbl, t2);
5214 
5215   return mk_bvlogic_term(__yices_globals.manager, b);
5216 }
5217 
5218 
yices_bvand3(term_t t1,term_t t2,term_t t3)5219 EXPORTED term_t yices_bvand3(term_t t1, term_t t2, term_t t3) {
5220   term_t aux[3];
5221 
5222   aux[0] = t1;
5223   aux[1] = t2;
5224   aux[2] = t3;
5225 
5226   return yices_bvand(3, aux);
5227 }
5228 
yices_bvor3(term_t t1,term_t t2,term_t t3)5229 EXPORTED term_t yices_bvor3(term_t t1, term_t t2, term_t t3) {
5230   term_t aux[3];
5231 
5232   aux[0] = t1;
5233   aux[1] = t2;
5234   aux[2] = t3;
5235 
5236   return yices_bvor(3, aux);
5237 }
5238 
yices_bvxor3(term_t t1,term_t t2,term_t t3)5239 EXPORTED term_t yices_bvxor3(term_t t1, term_t t2, term_t t3) {
5240   term_t aux[3];
5241 
5242   aux[0] = t1;
5243   aux[1] = t2;
5244   aux[2] = t3;
5245 
5246   return yices_bvor(3, aux);
5247 }
5248 
5249 
5250 
5251 
5252 /*********************************************
5253  *   BITVECTOR SHIFT/ROTATION BY A CONSTANT  *
5254  ********************************************/
5255 
5256 /*
5257  * Shift or rotation by an integer constant n
5258  * - shift_left0 sets the low-order bits to zero
5259  * - shift_left1 sets the low-order bits to one
5260  * - shift_right0 sets the high-order bits to zero
5261  * - shift_right1 sets the high-order bits to one
5262  * - ashift_right is arithmetic shift, it copies the sign bit &
5263  * - rotate_left: circular rotation
5264  * - rotate_right: circular rotation
5265  *
5266  * If t is a vector of m bits, then n must satisfy 0 <= n <= m.
5267  *
5268  * The functions return NULL_TERM (-1) if there's an error.
5269  *
5270  * Error reports:
5271  * if t is not valid
5272  *   code = INVALID_TERM
5273  *   term1 = t
5274  * if t is not a bitvector term
5275  *   code = BITVECTOR_REQUIRED
5276  *   term1 = t
5277  * if n > size of t
5278  *   code = INVALID_BITSHIFT
5279  *   badval = n
5280  */
yices_shift_left0(term_t t,uint32_t n)5281 EXPORTED term_t yices_shift_left0(term_t t, uint32_t n) {
5282   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_shift_left0(t, n));
5283 }
5284 
_o_yices_shift_left0(term_t t,uint32_t n)5285 term_t _o_yices_shift_left0(term_t t, uint32_t n) {
5286   bvlogic_buffer_t *b;
5287   term_table_t *tbl;
5288 
5289   tbl = __yices_globals.terms;
5290 
5291   if (! check_good_term(__yices_globals.manager, t) ||
5292       ! check_bitvector_term(__yices_globals.manager, t) ||
5293       ! check_bitshift(n, term_bitsize(tbl, t))) {
5294     return NULL_TERM;
5295   }
5296 
5297   b = get_bvlogic_buffer();
5298   bvlogic_buffer_set_term(b, tbl, t);
5299   bvlogic_buffer_shift_left0(b, n);
5300 
5301   return mk_bvlogic_term(__yices_globals.manager, b);
5302 }
5303 
yices_shift_left1(term_t t,uint32_t n)5304 EXPORTED term_t yices_shift_left1(term_t t, uint32_t n) {
5305   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_shift_left1(t, n));
5306 }
5307 
_o_yices_shift_left1(term_t t,uint32_t n)5308 term_t _o_yices_shift_left1(term_t t, uint32_t n) {
5309   bvlogic_buffer_t *b;
5310   term_table_t *tbl;
5311 
5312   tbl = __yices_globals.terms;
5313 
5314   if (! check_good_term(__yices_globals.manager, t) ||
5315       ! check_bitvector_term(__yices_globals.manager, t) ||
5316       ! check_bitshift(n, term_bitsize(tbl, t))) {
5317     return NULL_TERM;
5318   }
5319 
5320   b = get_bvlogic_buffer();
5321   bvlogic_buffer_set_term(b, tbl, t);
5322   bvlogic_buffer_shift_left1(b, n);
5323 
5324   return mk_bvlogic_term(__yices_globals.manager, b);
5325 }
5326 
yices_shift_right0(term_t t,uint32_t n)5327 EXPORTED term_t yices_shift_right0(term_t t, uint32_t n) {
5328   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_shift_right0(t, n));
5329 }
5330 
_o_yices_shift_right0(term_t t,uint32_t n)5331 term_t _o_yices_shift_right0(term_t t, uint32_t n) {
5332   bvlogic_buffer_t *b;
5333   term_table_t *tbl;
5334 
5335   tbl = __yices_globals.terms;
5336 
5337   if (! check_good_term(__yices_globals.manager, t) ||
5338       ! check_bitvector_term(__yices_globals.manager, t) ||
5339       ! check_bitshift(n, term_bitsize(tbl, t))) {
5340     return NULL_TERM;
5341   }
5342 
5343   b = get_bvlogic_buffer();
5344   bvlogic_buffer_set_term(b, tbl, t);
5345   bvlogic_buffer_shift_right0(b, n);
5346 
5347   return mk_bvlogic_term(__yices_globals.manager, b);
5348 }
5349 
yices_shift_right1(term_t t,uint32_t n)5350 EXPORTED term_t yices_shift_right1(term_t t, uint32_t n) {
5351   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_shift_right1(t, n));
5352 }
5353 
_o_yices_shift_right1(term_t t,uint32_t n)5354 term_t _o_yices_shift_right1(term_t t, uint32_t n) {
5355   bvlogic_buffer_t *b;
5356   term_table_t *tbl;
5357 
5358   tbl = __yices_globals.terms;
5359 
5360   if (! check_good_term(__yices_globals.manager, t) ||
5361       ! check_bitvector_term(__yices_globals.manager, t) ||
5362       ! check_bitshift(n, term_bitsize(tbl, t))) {
5363     return NULL_TERM;
5364   }
5365 
5366   b = get_bvlogic_buffer();
5367   bvlogic_buffer_set_term(b, tbl, t);
5368   bvlogic_buffer_shift_right1(b, n);
5369 
5370   return mk_bvlogic_term(__yices_globals.manager, b);
5371 }
5372 
yices_ashift_right(term_t t,uint32_t n)5373 EXPORTED term_t yices_ashift_right(term_t t, uint32_t n) {
5374   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_ashift_right(t, n));
5375 }
5376 
_o_yices_ashift_right(term_t t,uint32_t n)5377 term_t _o_yices_ashift_right(term_t t, uint32_t n) {
5378   bvlogic_buffer_t *b;
5379   term_table_t *tbl;
5380 
5381   tbl = __yices_globals.terms;
5382 
5383   if (! check_good_term(__yices_globals.manager, t) ||
5384       ! check_bitvector_term(__yices_globals.manager, t) ||
5385       ! check_bitshift(n, term_bitsize(tbl, t))) {
5386     return NULL_TERM;
5387   }
5388 
5389   b = get_bvlogic_buffer();
5390   bvlogic_buffer_set_term(b, tbl, t);
5391   bvlogic_buffer_ashift_right(b, n);
5392 
5393   return mk_bvlogic_term(__yices_globals.manager, b);
5394 }
5395 
yices_rotate_left(term_t t,uint32_t n)5396 EXPORTED term_t yices_rotate_left(term_t t, uint32_t n) {
5397   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_rotate_left(t, n));
5398 }
5399 
_o_yices_rotate_left(term_t t,uint32_t n)5400 term_t _o_yices_rotate_left(term_t t, uint32_t n) {
5401   bvlogic_buffer_t *b;
5402   term_table_t *tbl;
5403 
5404   tbl = __yices_globals.terms;
5405 
5406   if (! check_good_term(__yices_globals.manager, t) ||
5407       ! check_bitvector_term(__yices_globals.manager, t) ||
5408       ! check_bitshift(n, term_bitsize(tbl, t))) {
5409     return NULL_TERM;
5410   }
5411 
5412   b = get_bvlogic_buffer();
5413   bvlogic_buffer_set_term(b, tbl, t);
5414   if (n < b->bitsize) {
5415     bvlogic_buffer_rotate_left(b, n);
5416   }
5417 
5418   return mk_bvlogic_term(__yices_globals.manager, b);
5419 }
5420 
yices_rotate_right(term_t t,uint32_t n)5421 EXPORTED term_t yices_rotate_right(term_t t, uint32_t n) {
5422   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_rotate_right(t, n));
5423 }
5424 
_o_yices_rotate_right(term_t t,uint32_t n)5425 term_t _o_yices_rotate_right(term_t t, uint32_t n) {
5426   bvlogic_buffer_t *b;
5427   term_table_t *tbl;
5428 
5429   tbl = __yices_globals.terms;
5430 
5431   if (! check_good_term(__yices_globals.manager, t) ||
5432       ! check_bitvector_term(__yices_globals.manager, t) ||
5433       ! check_bitshift(n, term_bitsize(tbl, t))) {
5434     return NULL_TERM;
5435   }
5436 
5437   b = get_bvlogic_buffer();
5438   bvlogic_buffer_set_term(b, tbl, t);
5439   if (n < b->bitsize) {
5440     bvlogic_buffer_rotate_right(b, n);
5441   }
5442 
5443   return mk_bvlogic_term(__yices_globals.manager, b);
5444 }
5445 
5446 
5447 
5448 /****************************************
5449  *  BITVECTOR EXTRACTION/CONCATENATION  *
5450  ***************************************/
5451 
5452 /*
5453  * Extract a subvector of t
5454  * - t must be a bitvector term of size m
5455  * - i and j must satisfy 0 <= i <= j <= m-1
5456  * The result is the bits i to j of t.
5457  *
5458  * Return NULL_TERM (-1) if there's an error.
5459  *
5460  * Error reports:
5461  * if t is not valid
5462  *   code = INVALID_TERM
5463  *   term1 = t
5464  * if t is not a bitvector term
5465  *   code = BITVECTOR_REQUIRED
5466  *   term1 = t
5467  * if 0 <= i <= j <= m-1 does not hold
5468  *   code = INVALID_BVEXTRACT
5469  */
yices_bvextract(term_t t,uint32_t i,uint32_t j)5470 EXPORTED term_t yices_bvextract(term_t t, uint32_t i, uint32_t j) {
5471   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvextract(t, i, j));
5472 }
5473 
_o_yices_bvextract(term_t t,uint32_t i,uint32_t j)5474 term_t _o_yices_bvextract(term_t t, uint32_t i, uint32_t j) {
5475   bvlogic_buffer_t *b;
5476   term_table_t *tbl;
5477   uint32_t n;
5478 
5479   if (! check_good_term(__yices_globals.manager, t) ||
5480       ! check_bitvector_term(__yices_globals.manager, t)) {
5481     return NULL_TERM;
5482   }
5483 
5484   tbl = __yices_globals.terms;
5485   n = term_bitsize(tbl, t);
5486   if (! check_bvextract(i, j, n)) {
5487     return NULL_TERM;
5488   }
5489 
5490   if (i == 0 && j == n-1) {
5491     return t;
5492   } else {
5493     b = get_bvlogic_buffer();
5494     bvlogic_buffer_set_slice_term(b, tbl, i, j, t);
5495     return mk_bvlogic_term(__yices_globals.manager, b);
5496   }
5497 }
5498 
5499 
5500 /*
5501  * Concatenation
5502  * - t1 and t2 must be bitvector terms
5503  *
5504  * Return NULL_TERM (-1) if there's an error.
5505  *
5506  * Error reports
5507  * if t1 or t2 is not a valid term
5508  *   code = INVALID_TERM
5509  *   term1 = t1 or t2
5510  * if t1 or t2 is not a bitvector term
5511  *   code = BITVECTOR_REQUIRED
5512  *   term1 = t1 or t2
5513  * if the size of the result would be larger than MAX_BVSIZE
5514  *   code = MAX_BVSIZE_EXCEEDED
5515  *   badval = n1 + n2 (n1 = size of t1, n2 = size of t2)
5516  */
yices_bvconcat2(term_t t1,term_t t2)5517 EXPORTED term_t yices_bvconcat2(term_t t1, term_t t2) {
5518   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconcat2(t1, t2));
5519 }
5520 
_o_yices_bvconcat2(term_t t1,term_t t2)5521 term_t _o_yices_bvconcat2(term_t t1, term_t t2) {
5522   bvlogic_buffer_t *b;
5523   term_table_t *tbl;
5524 
5525   tbl = __yices_globals.terms;
5526 
5527   if (! check_good_term(__yices_globals.manager, t1) ||
5528       ! check_good_term(__yices_globals.manager, t2) ||
5529       ! check_bitvector_term(__yices_globals.manager, t1) ||
5530       ! check_bitvector_term(__yices_globals.manager, t2) ||
5531       ! check_maxbvsize(term_bitsize(tbl, t1) + term_bitsize(tbl, t2))) {
5532     return NULL_TERM;
5533   }
5534 
5535   b = get_bvlogic_buffer();
5536   bvlogic_buffer_set_term(b, tbl, t2);
5537   bvlogic_buffer_concat_left_term(b, tbl, t1);
5538 
5539   return mk_bvlogic_term(__yices_globals.manager, b);
5540 }
5541 
5542 
5543 /*
5544  * Generic form
5545  */
yices_bvconcat(uint32_t n,const term_t t[])5546 EXPORTED term_t yices_bvconcat(uint32_t n, const term_t t[]) {
5547   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvconcat(n, t));
5548 }
5549 
_o_yices_bvconcat(uint32_t n,const term_t t[])5550 term_t _o_yices_bvconcat(uint32_t n, const term_t t[]) {
5551   bvlogic_buffer_t *b;
5552   term_table_t *tbl;
5553   uint64_t bvsize;
5554   uint32_t i;
5555 
5556   if (! check_positive(n) ||
5557       ! check_good_terms(__yices_globals.manager, n, t) ||
5558       ! check_bitvector_args(__yices_globals.manager, n, t)) {
5559     return NULL_TERM;
5560   }
5561 
5562   tbl = __yices_globals.terms;
5563   bvsize = 0;
5564   for (i=0; i<n; i++) {
5565     bvsize += term_bitsize(tbl, t[i]);
5566   }
5567   if (bvsize > (uint64_t) YICES_MAX_BVSIZE) {
5568     error_report_t *error = get_yices_error();
5569     error->code = MAX_BVSIZE_EXCEEDED;
5570     error->badval = bvsize;
5571     return NULL_TERM;
5572   }
5573 
5574   b = get_bvlogic_buffer();
5575   bvlogic_buffer_clear(b);
5576   while (n>0) {
5577     n --;
5578     bvlogic_buffer_concat_left_term(b, tbl, t[n]);
5579   }
5580 
5581   return mk_bvlogic_term(__yices_globals.manager, b);
5582 }
5583 
5584 
5585 /*
5586  * Repeated concatenation:
5587  * - make n copies of t and concatenate them
5588  * - n must be positive
5589  *
5590  * Return NULL_TERM (-1) if there's an error
5591  *
5592  * Error report:
5593  * if t is not valid
5594  *   code = INVALID_TERM
5595  *   term1 = t
5596  * if t is not a bitvector term
5597  *   code = BITVECTOR_REQUIRED
5598  *   term1 = t
5599  * if n <= 0
5600  *   code = POSINT_REQUIRED
5601  *   badval = n
5602  * if size of the result would be more than MAX_BVSIZE
5603  *   code = MAX_BVSIZE_EXCEEDED
5604  *   badval = n * bitsize of t
5605  */
yices_bvrepeat(term_t t,uint32_t n)5606 EXPORTED term_t yices_bvrepeat(term_t t, uint32_t n) {
5607   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvrepeat(t, n));
5608 }
5609 
_o_yices_bvrepeat(term_t t,uint32_t n)5610 term_t _o_yices_bvrepeat(term_t t, uint32_t n) {
5611   bvlogic_buffer_t *b;
5612   term_table_t *tbl;
5613   uint64_t m;
5614 
5615   if (! check_good_term(__yices_globals.manager, t) ||
5616       ! check_bitvector_term(__yices_globals.manager, t) ||
5617       ! check_positive(n)) {
5618     return NULL_TERM;
5619   }
5620 
5621   // check size
5622   tbl = __yices_globals.terms;
5623   m = ((uint64_t) n) * term_bitsize(tbl, t);
5624   if (m > (uint64_t) YICES_MAX_BVSIZE) {
5625     error_report_t *error = get_yices_error();
5626     error->code = MAX_BVSIZE_EXCEEDED;
5627     error->badval = m;
5628     return NULL_TERM;
5629   }
5630 
5631   b = get_bvlogic_buffer();
5632   bvlogic_buffer_set_term(b, tbl, t);
5633   bvlogic_buffer_repeat_concat(b, n);
5634 
5635   return mk_bvlogic_term(__yices_globals.manager, b);
5636 }
5637 
5638 
5639 /*
5640  * Sign extension
5641  * - add n copies of t's sign bit
5642  * - n must be non-negative
5643  *
5644  * Return NULL_TERM if there's an error.
5645  *
5646  * Error reports:
5647  * if t is invalid
5648  *   code = INVALID_TERM
5649  *   term1 = t
5650  * if t is not a bitvector
5651  *   code = BITVECTOR_REQUIRED
5652  *   term1 = t
5653  * if n + bitsize of t is too large:
5654  *   code = MAX_BVSIZE_EXCEEDED
5655  *   badval = n + bitsize of t
5656  */
yices_sign_extend(term_t t,uint32_t n)5657 EXPORTED term_t yices_sign_extend(term_t t, uint32_t n) {
5658   MT_PROTECT(term_t,  __yices_globals.lock,_o_yices_sign_extend(t, n));
5659 }
5660 
_o_yices_sign_extend(term_t t,uint32_t n)5661 term_t _o_yices_sign_extend(term_t t, uint32_t n) {
5662   bvlogic_buffer_t *b;
5663   term_table_t *tbl;
5664   uint64_t m;
5665 
5666   if (! check_good_term(__yices_globals.manager, t) ||
5667       ! check_bitvector_term(__yices_globals.manager, t)) {
5668     return NULL_TERM;
5669   }
5670 
5671 
5672   // check size
5673   tbl = __yices_globals.terms;
5674   m = ((uint64_t) n) + term_bitsize(tbl, t);
5675   if (m > (uint64_t) YICES_MAX_BVSIZE) {
5676     error_report_t *error = get_yices_error();
5677     error->code = MAX_BVSIZE_EXCEEDED;
5678     error->badval = m;
5679     return NULL_TERM;
5680   }
5681 
5682   b = get_bvlogic_buffer();
5683   bvlogic_buffer_set_term(b, tbl, t);
5684   bvlogic_buffer_sign_extend(b, b->bitsize + n);
5685 
5686   return mk_bvlogic_term(__yices_globals.manager, b);
5687 }
5688 
5689 
5690 /*
5691  * Zero extension
5692  * - add n zeros to t
5693  * - n must be non-negative
5694  *
5695  * Return NULL_TERM if there's an error.
5696  *
5697  * Error reports:
5698  * if t is invalid
5699  *   code = INVALID_TERM
5700  *   term1 = t
5701  * if t is not a bitvector
5702  *   code = BITVECTOR_REQUIRED
5703  *   term1 = t
5704  * if n + bitsize of t is too large:
5705  *   code = MAX_BVSIZE_EXCEEDED
5706  *   badval = n + bitsize of t
5707  */
yices_zero_extend(term_t t,uint32_t n)5708 EXPORTED term_t yices_zero_extend(term_t t, uint32_t n) {
5709   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_zero_extend(t, n));
5710 }
5711 
_o_yices_zero_extend(term_t t,uint32_t n)5712 term_t _o_yices_zero_extend(term_t t, uint32_t n) {
5713   bvlogic_buffer_t *b;
5714   term_table_t *tbl;
5715   uint64_t m;
5716 
5717   if (! check_good_term(__yices_globals.manager, t) ||
5718       ! check_bitvector_term(__yices_globals.manager, t)) {
5719     return NULL_TERM;
5720   }
5721 
5722   // check size
5723   tbl = __yices_globals.terms;
5724   m = ((uint64_t) n) + term_bitsize(tbl, t);
5725   if (m > (uint64_t) YICES_MAX_BVSIZE) {
5726     error_report_t *error = get_yices_error();
5727     error->code = MAX_BVSIZE_EXCEEDED;
5728     error->badval = m;
5729     return NULL_TERM;
5730   }
5731 
5732   b = get_bvlogic_buffer();
5733   bvlogic_buffer_set_term(b, tbl, t);
5734   bvlogic_buffer_zero_extend(b, b->bitsize + n);
5735 
5736   return mk_bvlogic_term(__yices_globals.manager, b);
5737 }
5738 
5739 
5740 
5741 /*
5742  * AND-reduction:
5743  * if t is b[m-1] ... b[0], then the result is a bit-vector of 1 bit
5744  * equal to the conjunction of all bits of t (i.e., (and b[0] ... b[m-1])
5745  *
5746  * OR-reduction: compute (or b[0] ... b[m-1])
5747  *
5748  * Return NULL_TERM if there's an error
5749  *
5750  * Error reports:
5751  * if t is invalid
5752  *   code = INVALID_TERM
5753  *   term1 = t
5754  * if t is not a bitvector
5755  *   code = BITVECTOR_REQUIRED
5756  *   term1 = t
5757  */
yices_redand(term_t t)5758 EXPORTED term_t yices_redand(term_t t) {
5759   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_redand(t));
5760 }
5761 
_o_yices_redand(term_t t)5762 term_t _o_yices_redand(term_t t) {
5763   bvlogic_buffer_t *b;
5764   term_table_t *tbl;
5765 
5766   if (! check_good_term(__yices_globals.manager, t) ||
5767       ! check_bitvector_term(__yices_globals.manager, t)) {
5768     return NULL_TERM;
5769   }
5770 
5771   b = get_bvlogic_buffer();
5772   tbl = __yices_globals.terms;
5773   bvlogic_buffer_set_term(b, tbl, t);
5774   bvlogic_buffer_redand(b);
5775 
5776   return mk_bvlogic_term(__yices_globals.manager, b);
5777 }
5778 
yices_redor(term_t t)5779 EXPORTED term_t yices_redor(term_t t) {
5780   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_redor(t));
5781 }
5782 
_o_yices_redor(term_t t)5783 term_t _o_yices_redor(term_t t) {
5784   bvlogic_buffer_t *b;
5785   term_table_t *tbl;
5786 
5787   if (! check_good_term(__yices_globals.manager, t) ||
5788       ! check_bitvector_term(__yices_globals.manager, t)) {
5789     return NULL_TERM;
5790   }
5791 
5792   b = get_bvlogic_buffer();
5793   tbl = __yices_globals.terms;
5794   bvlogic_buffer_set_term(b, tbl, t);
5795   bvlogic_buffer_redor(b);
5796 
5797   return mk_bvlogic_term(__yices_globals.manager, b);
5798 }
5799 
5800 
5801 /*
5802  * Bitwise equality comparison: if t1 and t2 are bitvectors of size n,
5803  * construct (bvand (bvxnor t1 t2))
5804  *
5805  * Return NULL_TERM if there's an error
5806  *
5807  * Error reports:
5808  * if t1 or t2 is not valid
5809  *   code = INVALID_TERM
5810  *   term1 = t1 or t2
5811  *   index = -1
5812  * if t1 or t2 is not a bitvector term
5813  *   code = BITVECTOR_REQUIRED
5814  *   term1 = t1 or t2
5815  * if t1 and t2 do not have the same bitvector type
5816  *   code = INCOMPATIBLE_TYPES
5817  *   term1 = t1
5818  *   type1 = type of t1
5819  *   term2 = t2
5820  *   type2 = type of t2
5821  */
yices_redcomp(term_t t1,term_t t2)5822 EXPORTED term_t yices_redcomp(term_t t1, term_t t2) {
5823   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_redcomp(t1, t2));
5824 }
5825 
_o_yices_redcomp(term_t t1,term_t t2)5826 term_t _o_yices_redcomp(term_t t1, term_t t2) {
5827   bvlogic_buffer_t *b;
5828   term_table_t *tbl;
5829 
5830   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5831     return NULL_TERM;
5832   }
5833 
5834   b = get_bvlogic_buffer();
5835   tbl = __yices_globals.terms;
5836   bvlogic_buffer_set_term(b, tbl, t1);
5837   bvlogic_buffer_comp_term(b, tbl, t2);
5838 
5839   return mk_bvlogic_term(__yices_globals.manager, b);
5840 }
5841 
5842 
5843 
5844 
5845 /*******************************
5846  *  GENERIC BIT-VECTOR SHIFTS  *
5847  *****************************/
5848 
5849 
yices_bvshl(term_t t1,term_t t2)5850 EXPORTED term_t yices_bvshl(term_t t1, term_t t2) {
5851   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvshl(t1, t2));
5852 }
5853 
_o_yices_bvshl(term_t t1,term_t t2)5854 term_t _o_yices_bvshl(term_t t1, term_t t2) {
5855   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5856     return NULL_TERM;
5857   }
5858 
5859   return mk_bvshl(__yices_globals.manager, t1, t2);
5860 }
5861 
5862 
yices_bvlshr(term_t t1,term_t t2)5863 EXPORTED term_t yices_bvlshr(term_t t1, term_t t2) {
5864   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvlshr(t1, t2));
5865 }
5866 
_o_yices_bvlshr(term_t t1,term_t t2)5867 term_t _o_yices_bvlshr(term_t t1, term_t t2) {
5868   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5869     return NULL_TERM;
5870   }
5871 
5872   return mk_bvlshr(__yices_globals.manager, t1, t2);
5873 }
5874 
5875 
yices_bvashr(term_t t1,term_t t2)5876 EXPORTED term_t yices_bvashr(term_t t1, term_t t2) {
5877   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvashr(t1, t2));
5878 }
5879 
_o_yices_bvashr(term_t t1,term_t t2)5880 term_t _o_yices_bvashr(term_t t1, term_t t2) {
5881   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5882     return NULL_TERM;
5883   }
5884 
5885   return mk_bvashr(__yices_globals.manager, t1, t2);
5886 }
5887 
5888 
5889 
5890 
5891 
5892 /**********************************
5893  *  BITVECTOR DIVISION OPERATORS  *
5894  *********************************/
5895 
yices_bvdiv(term_t t1,term_t t2)5896 EXPORTED term_t yices_bvdiv(term_t t1, term_t t2) {
5897   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvdiv(t1, t2));
5898 }
5899 
_o_yices_bvdiv(term_t t1,term_t t2)5900 term_t _o_yices_bvdiv(term_t t1, term_t t2) {
5901   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5902     return NULL_TERM;
5903   }
5904   return mk_bvdiv(__yices_globals.manager, t1, t2);
5905 }
5906 
5907 
yices_bvrem(term_t t1,term_t t2)5908 EXPORTED term_t yices_bvrem(term_t t1, term_t t2) {
5909   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvrem(t1,t2));
5910 }
5911 
_o_yices_bvrem(term_t t1,term_t t2)5912 term_t _o_yices_bvrem(term_t t1, term_t t2) {
5913   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5914     return NULL_TERM;
5915   }
5916   return mk_bvrem(__yices_globals.manager, t1, t2);
5917 }
5918 
5919 
yices_bvsdiv(term_t t1,term_t t2)5920 EXPORTED term_t yices_bvsdiv(term_t t1, term_t t2) {
5921   MT_PROTECT(term_t,  __yices_globals.lock,  _o_yices_bvsdiv(t1, t2));
5922 }
5923 
_o_yices_bvsdiv(term_t t1,term_t t2)5924 term_t _o_yices_bvsdiv(term_t t1, term_t t2) {
5925   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5926     return NULL_TERM;
5927   }
5928   return mk_bvsdiv(__yices_globals.manager, t1, t2);
5929 }
5930 
5931 
yices_bvsrem(term_t t1,term_t t2)5932 EXPORTED term_t yices_bvsrem(term_t t1, term_t t2) {
5933   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsrem(t1, t2));
5934 }
5935 
_o_yices_bvsrem(term_t t1,term_t t2)5936 term_t _o_yices_bvsrem(term_t t1, term_t t2) {
5937   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5938     return NULL_TERM;
5939   }
5940   return mk_bvsrem(__yices_globals.manager, t1, t2);
5941 }
5942 
5943 
yices_bvsmod(term_t t1,term_t t2)5944 EXPORTED term_t yices_bvsmod(term_t t1, term_t t2) {
5945   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsmod(t1, t2));
5946 }
5947 
_o_yices_bvsmod(term_t t1,term_t t2)5948 term_t _o_yices_bvsmod(term_t t1, term_t t2) {
5949   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
5950     return NULL_TERM;
5951   }
5952   return mk_bvsmod(__yices_globals.manager, t1, t2);
5953 }
5954 
5955 
5956 
5957 /*
5958  * Convert an array of boolean terms arg[0 ... n-1] into
5959  * a bitvector term.
5960  *
5961  * Error report:
5962  * if n == 0
5963  *    code = POSINT_REQUIRED
5964  *    badval = n
5965  * if n > YICES_MAX_BVSIZE
5966  *    code = MAX_BVSIZE_EXCEEDED
5967  *    badval = size
5968  * if arg[i] is invalid
5969  *    code = INVALID_TERM
5970  *    term1 = arg[i]
5971  *    index = i
5972  * if arg[i] is not a boolean
5973  *    code = TYPE_MISMATCH
5974  *    term1 = arg[i]
5975  *    type1 = bool
5976  *    index = i
5977  */
yices_bvarray(uint32_t n,const term_t arg[])5978 EXPORTED term_t yices_bvarray(uint32_t n, const term_t arg[]) {
5979   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvarray(n, arg));
5980 }
5981 
_o_yices_bvarray(uint32_t n,const term_t arg[])5982 term_t _o_yices_bvarray(uint32_t n, const term_t arg[]) {
5983   if (! check_positive(n) ||
5984       ! check_maxbvsize(n) ||
5985       ! check_good_terms(__yices_globals.manager, n, arg) ||
5986       ! check_boolean_args(__yices_globals.manager, n, arg)) {
5987     return NULL_TERM;
5988   }
5989   return mk_bvarray(__yices_globals.manager, n, arg);
5990 }
5991 
5992 
5993 
5994 /*
5995  * Extract bit i of vector v (as a boolean)
5996  *
5997  * Error report:
5998  * if v is invalid
5999  *    code = INVALID_TERM
6000  *    term1 = v
6001  *    index = -1
6002  * if v is not a bitvector term
6003  *    code = BITVECTOR_REQUIRES
6004  *    term1 = t
6005  * if i >= v's bitsize
6006  *    code = INVALID_BVEXTRACT
6007  */
yices_bitextract(term_t t,uint32_t i)6008 EXPORTED term_t yices_bitextract(term_t t, uint32_t i) {
6009   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bitextract(t, i));
6010 }
6011 
_o_yices_bitextract(term_t t,uint32_t i)6012 term_t _o_yices_bitextract(term_t t, uint32_t i) {
6013   if (! check_good_term(__yices_globals.manager, t) ||
6014       ! check_bitvector_term(__yices_globals.manager, t) ||
6015       ! check_bitextract(i, term_bitsize(__yices_globals.terms, t))) {
6016     return NULL_TERM;
6017   }
6018   return mk_bitextract(__yices_globals.manager, t, i);
6019 }
6020 
6021 
6022 
6023 
6024 /*********************
6025  *  BITVECTOR ATOMS  *
6026  ********************/
6027 
yices_bveq_atom(term_t t1,term_t t2)6028 EXPORTED term_t yices_bveq_atom(term_t t1, term_t t2) {
6029   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bveq_atom(t1, t2));
6030 }
6031 
_o_yices_bveq_atom(term_t t1,term_t t2)6032 term_t _o_yices_bveq_atom(term_t t1, term_t t2) {
6033   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6034     return NULL_TERM;
6035   }
6036   return mk_bveq(__yices_globals.manager, t1, t2);
6037 }
6038 
6039 
yices_bvneq_atom(term_t t1,term_t t2)6040 EXPORTED term_t yices_bvneq_atom(term_t t1, term_t t2) {
6041   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvneq_atom(t1, t2));
6042 }
6043 
_o_yices_bvneq_atom(term_t t1,term_t t2)6044 term_t _o_yices_bvneq_atom(term_t t1, term_t t2) {
6045   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6046     return NULL_TERM;
6047   }
6048   return mk_bvneq(__yices_globals.manager, t1, t2);
6049 }
6050 
6051 
yices_bvge_atom(term_t t1,term_t t2)6052 EXPORTED term_t yices_bvge_atom(term_t t1, term_t t2) {
6053   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvge_atom(t1, t2));
6054 }
6055 
_o_yices_bvge_atom(term_t t1,term_t t2)6056 term_t _o_yices_bvge_atom(term_t t1, term_t t2) {
6057   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6058     return NULL_TERM;
6059   }
6060   return mk_bvge(__yices_globals.manager, t1, t2);
6061 }
6062 
6063 
yices_bvgt_atom(term_t t1,term_t t2)6064 EXPORTED term_t yices_bvgt_atom(term_t t1, term_t t2) {
6065   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvgt_atom(t1, t2));
6066 }
6067 
_o_yices_bvgt_atom(term_t t1,term_t t2)6068 term_t _o_yices_bvgt_atom(term_t t1, term_t t2) {
6069   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6070     return NULL_TERM;
6071   }
6072   return mk_bvgt(__yices_globals.manager, t1, t2);
6073 }
6074 
6075 
yices_bvle_atom(term_t t1,term_t t2)6076 EXPORTED term_t yices_bvle_atom(term_t t1, term_t t2) {
6077   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvle_atom(t1, t2));
6078 }
6079 
_o_yices_bvle_atom(term_t t1,term_t t2)6080 term_t _o_yices_bvle_atom(term_t t1, term_t t2) {
6081   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6082     return NULL_TERM;
6083   }
6084   return mk_bvle(__yices_globals.manager, t1, t2);
6085 }
6086 
6087 
yices_bvlt_atom(term_t t1,term_t t2)6088 EXPORTED term_t yices_bvlt_atom(term_t t1, term_t t2) {
6089   MT_PROTECT(term_t,  __yices_globals.lock,  _o_yices_bvlt_atom(t1, t2));
6090 }
6091 
_o_yices_bvlt_atom(term_t t1,term_t t2)6092 term_t _o_yices_bvlt_atom(term_t t1, term_t t2) {
6093   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6094     return NULL_TERM;
6095   }
6096   return mk_bvlt(__yices_globals.manager, t1, t2);
6097 }
6098 
6099 
yices_bvsge_atom(term_t t1,term_t t2)6100 EXPORTED term_t yices_bvsge_atom(term_t t1, term_t t2) {
6101   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsge_atom(t1, t2));
6102 }
6103 
_o_yices_bvsge_atom(term_t t1,term_t t2)6104 term_t _o_yices_bvsge_atom(term_t t1, term_t t2) {
6105   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6106     return NULL_TERM;
6107   }
6108   return mk_bvsge(__yices_globals.manager, t1, t2);
6109 }
6110 
6111 
yices_bvsgt_atom(term_t t1,term_t t2)6112 EXPORTED term_t yices_bvsgt_atom(term_t t1, term_t t2) {
6113   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsgt_atom(t1, t2));
6114 }
6115 
_o_yices_bvsgt_atom(term_t t1,term_t t2)6116 term_t _o_yices_bvsgt_atom(term_t t1, term_t t2) {
6117   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6118     return NULL_TERM;
6119   }
6120   return mk_bvsgt(__yices_globals.manager, t1, t2);
6121 }
6122 
6123 
yices_bvsle_atom(term_t t1,term_t t2)6124 EXPORTED term_t yices_bvsle_atom(term_t t1, term_t t2) {
6125   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvsle_atom(t1, t2));
6126 }
6127 
_o_yices_bvsle_atom(term_t t1,term_t t2)6128 term_t _o_yices_bvsle_atom(term_t t1, term_t t2) {
6129   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6130     return NULL_TERM;
6131   }
6132   return mk_bvsle(__yices_globals.manager, t1, t2);
6133 }
6134 
6135 
yices_bvslt_atom(term_t t1,term_t t2)6136 EXPORTED term_t yices_bvslt_atom(term_t t1, term_t t2) {
6137   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_bvslt_atom(t1, t2));
6138 }
6139 
_o_yices_bvslt_atom(term_t t1,term_t t2)6140 term_t _o_yices_bvslt_atom(term_t t1, term_t t2) {
6141   if (! check_compatible_bv_terms(__yices_globals.manager, t1, t2)) {
6142     return NULL_TERM;
6143   }
6144   return mk_bvslt(__yices_globals.manager, t1, t2);
6145 }
6146 
6147 
6148 
6149 /*********************
6150  *  PRETTY PRINTING  *
6151  ********************/
6152 
6153 /*
6154  * Pretty print type tau
6155  * - f = output file to use
6156  * - width, height, offset = print area
6157  */
yices_pp_type(FILE * f,type_t tau,uint32_t width,uint32_t height,uint32_t offset)6158 EXPORTED int32_t yices_pp_type(FILE *f, type_t tau, uint32_t width, uint32_t height, uint32_t offset) {
6159   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_pp_type(f, tau, width, height, offset));
6160 }
6161 
_o_yices_pp_type(FILE * f,type_t tau,uint32_t width,uint32_t height,uint32_t offset)6162 int32_t _o_yices_pp_type(FILE *f, type_t tau, uint32_t width, uint32_t height, uint32_t offset) {
6163   yices_pp_t printer;
6164   pp_area_t area;
6165   int32_t code;
6166 
6167   if (! check_good_type(__yices_globals.types, tau)) {
6168     return -1;
6169   }
6170 
6171   if (width < 4) width = 4;
6172   if (height == 0) height = 1;
6173 
6174   area.width = width;
6175   area.height = height;
6176   area.offset = offset;
6177   area.stretch = false;
6178   area.truncate = true;
6179 
6180   init_default_yices_pp(&printer, f, &area);
6181   pp_type_exp(&printer, __yices_globals.types, tau);
6182   flush_yices_pp(&printer);
6183 
6184   // check for error
6185   code = 0;
6186   if (yices_pp_print_failed(&printer)) {
6187     code = -1;
6188     errno = yices_pp_errno(&printer);
6189     file_output_error();
6190   }
6191   delete_yices_pp(&printer, false);
6192 
6193   return code;
6194 }
6195 
yices_pp_type_fd(int fd,type_t tau,uint32_t width,uint32_t height,uint32_t offset)6196 EXPORTED int32_t yices_pp_type_fd(int fd, type_t tau, uint32_t width, uint32_t height, uint32_t offset) {
6197   FILE *tmp_fp;
6198   int32_t retval;
6199 
6200   tmp_fp = fd_2_tmp_fp(fd);
6201   if (tmp_fp == NULL) {
6202     file_output_error();
6203     return -1;
6204   }
6205   retval = yices_pp_type(tmp_fp, tau, width, height, offset);
6206   fclose(tmp_fp);
6207 
6208   return retval;
6209 }
6210 
6211 
6212 
6213 /*
6214  * Pretty print term t
6215  * - f = output file to use
6216  * - width, height, offset = print area
6217  */
yices_pp_term(FILE * f,term_t t,uint32_t width,uint32_t height,uint32_t offset)6218 EXPORTED int32_t yices_pp_term(FILE *f, term_t t, uint32_t width, uint32_t height, uint32_t offset) {
6219   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_pp_term(f, t, width, height, offset));
6220 }
6221 
_o_yices_pp_term(FILE * f,term_t t,uint32_t width,uint32_t height,uint32_t offset)6222 int32_t _o_yices_pp_term(FILE *f, term_t t, uint32_t width, uint32_t height, uint32_t offset) {
6223   yices_pp_t printer;
6224   pp_area_t area;
6225   int32_t code;
6226 
6227   if (! check_good_term(__yices_globals.manager, t)) {
6228     return -1;
6229   }
6230 
6231   if (width < 4) width = 4;
6232   if (height == 0) height = 1;
6233 
6234   area.width = width;
6235   area.height = height;
6236   area.offset = offset;
6237   area.stretch = false;
6238   area.truncate = true;
6239 
6240   init_default_yices_pp(&printer, f, &area);
6241   pp_term_full(&printer, __yices_globals.terms, t);
6242   flush_yices_pp(&printer);
6243 
6244   // check for error
6245   code = 0;
6246   if (yices_pp_print_failed(&printer)) {
6247     code = -1;
6248     errno = yices_pp_errno(&printer);
6249     file_output_error();
6250   }
6251   delete_yices_pp(&printer, false);
6252 
6253   return code;
6254 }
6255 
yices_pp_term_fd(int fd,term_t t,uint32_t width,uint32_t height,uint32_t offset)6256 EXPORTED int32_t yices_pp_term_fd(int fd, term_t t, uint32_t width, uint32_t height, uint32_t offset) {
6257   FILE *tmp_fp;
6258   int32_t retval;
6259 
6260   tmp_fp = fd_2_tmp_fp(fd);
6261   if (tmp_fp == NULL) {
6262     file_output_error();
6263     return -1;
6264   }
6265   retval = yices_pp_term(tmp_fp, t, width, height, offset);
6266   fclose(tmp_fp);
6267 
6268   return retval;
6269 }
6270 
6271 /*
6272  * Pretty print terms a[0 ... n-1]
6273  * - f = output file to use
6274  * - width, height, offset = print area
6275  */
yices_pp_term_array(FILE * f,uint32_t n,const term_t a[],uint32_t width,uint32_t height,uint32_t offset,int32_t horiz)6276 EXPORTED int32_t yices_pp_term_array(FILE *f, uint32_t n, const term_t a[], uint32_t width, uint32_t height, uint32_t offset, int32_t horiz) {
6277   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_pp_term_array(f, n, a, width, height, offset, horiz));
6278 }
6279 
_o_yices_pp_term_array(FILE * f,uint32_t n,const term_t a[],uint32_t width,uint32_t height,uint32_t offset,int32_t horiz)6280 int32_t _o_yices_pp_term_array(FILE *f, uint32_t n, const term_t a[], uint32_t width, uint32_t height, uint32_t offset, int32_t horiz) {
6281   yices_pp_t printer;
6282   pp_area_t area;
6283   int32_t code;
6284   uint32_t i;
6285 
6286   if (! check_good_terms(__yices_globals.manager, n, a)) {
6287     return -1;
6288   }
6289 
6290   if (width < 4) width = 4;
6291   if (height == 0) height = 1;
6292 
6293   area.width = width;
6294   area.height = height;
6295   area.offset = offset;
6296   area.stretch = false;
6297   area.truncate = true;
6298 
6299   if (horiz == 0) {
6300     init_default_yices_pp(&printer, f, &area); // default: PP_VMODE
6301   } else {
6302     init_yices_pp(&printer, f, &area, PP_HVMODE, 0); // horizontal/vertical mode
6303   }
6304 
6305   for (i=0; i<n; i++) {
6306     pp_term_full(&printer, __yices_globals.terms, a[i]);
6307   }
6308   flush_yices_pp(&printer);
6309 
6310   // check for error
6311   code = 0;
6312   if (yices_pp_print_failed(&printer)) {
6313     code = -1;
6314     errno = yices_pp_errno(&printer);
6315     file_output_error();
6316   }
6317   delete_yices_pp(&printer, false);
6318 
6319   return code;
6320 }
6321 
yices_pp_term_array_fd(int fd,uint32_t n,const term_t a[],uint32_t width,uint32_t height,uint32_t offset,int32_t horiz)6322 EXPORTED int32_t yices_pp_term_array_fd(int fd, uint32_t n, const term_t a[], uint32_t width, uint32_t height, uint32_t offset, int32_t horiz) {
6323   FILE *tmp_fp;
6324   int32_t retval;
6325 
6326   tmp_fp = fd_2_tmp_fp(fd);
6327   if (tmp_fp == NULL) {
6328     file_output_error();
6329     return -1;
6330   }
6331   retval = yices_pp_term_array(tmp_fp, n, a, width, height, offset,  horiz);
6332   fclose(tmp_fp);
6333 
6334   return retval;
6335 }
6336 
6337 
6338 
6339 /*
6340  * Conversion to strings
6341  */
yices_type_to_string(type_t tau,uint32_t width,uint32_t height,uint32_t offset)6342 EXPORTED char *yices_type_to_string(type_t tau, uint32_t width, uint32_t height, uint32_t offset) {
6343   MT_PROTECT(char*,  __yices_globals.lock, _o_yices_type_to_string(tau, width, height, offset));
6344 }
6345 
_o_yices_type_to_string(type_t tau,uint32_t width,uint32_t height,uint32_t offset)6346 char *_o_yices_type_to_string(type_t tau, uint32_t width, uint32_t height, uint32_t offset) {
6347   yices_pp_t printer;
6348   pp_area_t area;
6349   char *str;
6350   uint32_t len;
6351 
6352   if (! check_good_type(__yices_globals.types, tau)) {
6353     return NULL;
6354   }
6355 
6356   if (width < 4) width = 4;
6357   if (height == 0) height = 1;
6358 
6359   area.width = width;
6360   area.height = height;
6361   area.offset = offset;
6362   area.stretch = false;
6363   area.truncate = true;
6364 
6365   init_default_yices_pp(&printer, NULL, &area);
6366   pp_type_exp(&printer, __yices_globals.types, tau);
6367   flush_yices_pp(&printer);
6368 
6369   str = yices_pp_get_string(&printer, &len);
6370   delete_yices_pp(&printer, false);
6371 
6372   return str;
6373 }
6374 
yices_term_to_string(term_t t,uint32_t width,uint32_t height,uint32_t offset)6375 EXPORTED char *yices_term_to_string(term_t t, uint32_t width, uint32_t height, uint32_t offset) {
6376   MT_PROTECT(char*,  __yices_globals.lock, _o_yices_term_to_string(t, width, height, offset));
6377 }
6378 
_o_yices_term_to_string(term_t t,uint32_t width,uint32_t height,uint32_t offset)6379 char *_o_yices_term_to_string(term_t t, uint32_t width, uint32_t height, uint32_t offset) {
6380   yices_pp_t printer;
6381   pp_area_t area;
6382   char *str;
6383   uint32_t len;
6384 
6385   if (! check_good_term(__yices_globals.manager, t)) {
6386     return NULL;
6387   }
6388 
6389   if (width < 4) width = 4;
6390   if (height == 0) height = 1;
6391 
6392   area.width = width;
6393   area.height = height;
6394   area.offset = offset;
6395   area.stretch = false;
6396   area.truncate = true;
6397 
6398   init_default_yices_pp(&printer, NULL, &area);
6399   pp_term_full(&printer, __yices_globals.terms, t);
6400   flush_yices_pp(&printer);
6401 
6402   str = yices_pp_get_string(&printer, &len);
6403   delete_yices_pp(&printer, false);
6404 
6405   return str;
6406 }
6407 
6408 
yices_free_string(char * s)6409 EXPORTED void yices_free_string(char *s) {
6410   safe_free(s);
6411 }
6412 
6413 
6414 
6415 /*********************
6416  *  CHECKS ON TYPES  *
6417  ********************/
6418 
6419 /*
6420  * Checks on a type tau:
6421  * - all functions return 0 for false, 1 for true
6422  *
6423  * yices_type_is_arithmetic(tau) returns true if tau is either int or real.
6424  *
6425  * if tau not a valid type, the functions return false
6426  * and set the error report:
6427  *   code = INVALID_TYPE
6428  *   type1 = tau
6429  */
yices_type_is_bool(type_t tau)6430 EXPORTED int32_t yices_type_is_bool(type_t tau) {
6431   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_bool(tau));
6432 }
6433 
_o_yices_type_is_bool(type_t tau)6434 int32_t _o_yices_type_is_bool(type_t tau) {
6435   return check_good_type(__yices_globals.types, tau) && is_boolean_type(tau);
6436 }
6437 
yices_type_is_int(type_t tau)6438 EXPORTED int32_t yices_type_is_int(type_t tau) {
6439   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_int(tau));
6440 }
6441 
_o_yices_type_is_int(type_t tau)6442 int32_t _o_yices_type_is_int(type_t tau) {
6443   return check_good_type(__yices_globals.types, tau) && is_integer_type(tau);
6444 }
6445 
yices_type_is_real(type_t tau)6446 EXPORTED int32_t yices_type_is_real(type_t tau) {
6447   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_real(tau));
6448 }
6449 
_o_yices_type_is_real(type_t tau)6450 int32_t _o_yices_type_is_real(type_t tau) {
6451   return check_good_type(__yices_globals.types, tau) && is_real_type(tau);
6452 }
6453 
yices_type_is_arithmetic(type_t tau)6454 EXPORTED int32_t yices_type_is_arithmetic(type_t tau) {
6455   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_arithmetic(tau));
6456 }
6457 
_o_yices_type_is_arithmetic(type_t tau)6458 int32_t _o_yices_type_is_arithmetic(type_t tau) {
6459   return check_good_type(__yices_globals.types, tau) && is_arithmetic_type(tau);
6460 }
6461 
yices_type_is_bitvector(type_t tau)6462 EXPORTED int32_t yices_type_is_bitvector(type_t tau) {
6463   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_bitvector(tau));
6464 }
6465 
_o_yices_type_is_bitvector(type_t tau)6466 int32_t _o_yices_type_is_bitvector(type_t tau) {
6467   return check_good_type(__yices_globals.types, tau) && is_bv_type(__yices_globals.types, tau);
6468 }
6469 
yices_type_is_tuple(type_t tau)6470 EXPORTED int32_t yices_type_is_tuple(type_t tau) {
6471   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_tuple(tau));
6472 }
6473 
_o_yices_type_is_tuple(type_t tau)6474 int32_t _o_yices_type_is_tuple(type_t tau) {
6475   return check_good_type(__yices_globals.types, tau) && is_tuple_type(__yices_globals.types, tau);
6476 }
6477 
yices_type_is_function(type_t tau)6478 EXPORTED int32_t yices_type_is_function(type_t tau) {
6479   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_function(tau));
6480 }
6481 
_o_yices_type_is_function(type_t tau)6482 int32_t _o_yices_type_is_function(type_t tau) {
6483   return check_good_type(__yices_globals.types, tau) && is_function_type(__yices_globals.types, tau);
6484 }
6485 
yices_type_is_scalar(type_t tau)6486 EXPORTED int32_t yices_type_is_scalar(type_t tau) {
6487   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_scalar(tau));
6488 }
6489 
_o_yices_type_is_scalar(type_t tau)6490 int32_t _o_yices_type_is_scalar(type_t tau) {
6491   return check_good_type(__yices_globals.types, tau) && is_scalar_type(__yices_globals.types, tau);
6492 }
6493 
yices_type_is_uninterpreted(type_t tau)6494 EXPORTED int32_t yices_type_is_uninterpreted(type_t tau) {
6495   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_is_uninterpreted(tau));
6496 }
6497 
_o_yices_type_is_uninterpreted(type_t tau)6498 int32_t _o_yices_type_is_uninterpreted(type_t tau) {
6499   return check_good_type(__yices_globals.types, tau) && is_uninterpreted_type(__yices_globals.types, tau);
6500 }
6501 
6502 
6503 /*
6504  * Check whether tau is a subtype of sigma
6505  * - return 0 for false, 1 for true
6506  *
6507  * If tau or sigma is not a valid type, the function returns false
6508  * and sets the error report:
6509  *   code = INVALID_TYPE
6510  *   type1 = tau or sigma
6511  */
yices_test_subtype(type_t tau,type_t sigma)6512 EXPORTED int32_t yices_test_subtype(type_t tau, type_t sigma) {
6513   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_test_subtype(tau, sigma));
6514 }
6515 
_o_yices_test_subtype(type_t tau,type_t sigma)6516 int32_t _o_yices_test_subtype(type_t tau, type_t sigma) {
6517   return check_good_type(__yices_globals.types, tau) && check_good_type(__yices_globals.types, sigma) && is_subtype(__yices_globals.types, tau, sigma);
6518 }
6519 
6520 
6521 /*
6522  * Check whether tau and sigma are compatible
6523  * - return 0 for false, 1 for true
6524  *
6525  * If tau or sigma is not a valid type, the function returns 0 and
6526  * Sets the error report:
6527  *   code = INVALID_TYPE
6528  *   type1 = tau or sigma
6529  */
yices_compatible_types(type_t tau,type_t sigma)6530 EXPORTED int32_t yices_compatible_types(type_t tau, type_t sigma) {
6531   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_compatible_types(tau, sigma));
6532 }
6533 
_o_yices_compatible_types(type_t tau,type_t sigma)6534 int32_t _o_yices_compatible_types(type_t tau, type_t sigma) {
6535   return check_good_type(__yices_globals.types, tau) && check_good_type(__yices_globals.types, sigma)
6536     && compatible_types(__yices_globals.types, tau, sigma);
6537 }
6538 
6539 
6540 /*
6541  * Number of bits for type tau
6542  * - return 0 if there's an error
6543  *
6544  * Error report:
6545  * if tau is not a valid type
6546  *    code = INVALID_TYPE
6547  *    type1 = tau
6548  * if tau is not a bitvector type
6549  *    code = BVTYPE_REQUIRED
6550  *    type1 = tau
6551  */
yices_bvtype_size(type_t tau)6552 EXPORTED uint32_t yices_bvtype_size(type_t tau) {
6553   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_bvtype_size(tau));
6554 }
6555 
_o_yices_bvtype_size(type_t tau)6556 uint32_t _o_yices_bvtype_size(type_t tau) {
6557   if (! check_good_type(__yices_globals.types, tau) ||
6558       ! check_bvtype(__yices_globals.types, tau)) {
6559     return 0;
6560   }
6561   return bv_type_size(__yices_globals.types, tau);
6562 }
6563 
6564 
6565 /*
6566  * Cardinality of a scalar type
6567  * - return 0 if there's an error
6568  */
yices_scalar_type_card(type_t tau)6569 EXPORTED uint32_t yices_scalar_type_card(type_t tau) {
6570   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_scalar_type_card(tau));
6571 }
6572 
_o_yices_scalar_type_card(type_t tau)6573 uint32_t _o_yices_scalar_type_card(type_t tau) {
6574   if (! check_good_type(__yices_globals.types, tau) ||
6575       ! check_scalar_type(__yices_globals.types, tau)) {
6576     return 0;
6577   }
6578   return scalar_type_cardinal(__yices_globals.types, tau);
6579 }
6580 
6581 
6582 /*
6583  * Number of children of type tau
6584  * - if tau is a tuple type (tuple tau_1 ... tau_n), returns n
6585  * - if tau is a function type (-> tau_1 ... tau_n sigma), returns n+1
6586  * - if tau is any other type, returns 0
6587  *
6588  * - returns -1 if tau is not a valid type
6589  *
6590  * Error report:
6591  * if tau is not a valid type
6592  *   code = INVALID_TYPE
6593  *   type1 = tau
6594  */
yices_type_num_children(type_t tau)6595 EXPORTED int32_t yices_type_num_children(type_t tau) {
6596   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_num_children(tau));
6597 }
6598 
_o_yices_type_num_children(type_t tau)6599 int32_t _o_yices_type_num_children(type_t tau) {
6600   int32_t n;
6601 
6602   if (! check_good_type(__yices_globals.types, tau)) {
6603     return -1;
6604   }
6605 
6606   // it's safe to convert from unsigned to signed here
6607   // since YICES_MAX_ARITY is (UINT32_MAX/16)
6608   n = 0;
6609   if (is_tuple_type(__yices_globals.types, tau)) {
6610     n = tuple_type_arity(__yices_globals.types, tau);
6611   } else if (is_function_type(__yices_globals.types, tau)) {
6612     n = function_type_arity(__yices_globals.types, tau) + 1;
6613   }
6614 
6615   return n;
6616 }
6617 
6618 
6619 /*
6620  * Get the i-th child of type tau
6621  * - return NULL_TYPE if there's an error
6622  */
yices_type_child(type_t tau,int32_t i)6623 EXPORTED type_t yices_type_child(type_t tau, int32_t i) {
6624   MT_PROTECT(type_t,  __yices_globals.lock, _o_yices_type_child(tau, i));
6625 }
6626 
_o_yices_type_child(type_t tau,int32_t i)6627 type_t _o_yices_type_child(type_t tau, int32_t i) {
6628   tuple_type_t *tup;
6629   function_type_t *fun;
6630 
6631   if (! check_good_type(__yices_globals.types, tau)) {
6632     return NULL_TYPE;
6633   }
6634 
6635   if (i >= 0) {
6636     if (is_tuple_type(__yices_globals.types, tau)) {
6637       tup = tuple_type_desc(__yices_globals.types, tau);
6638       if (i < tup->nelem) {
6639 	return tup->elem[i];
6640       }
6641     } else if (is_function_type(__yices_globals.types, tau)) {
6642       fun = function_type_desc(__yices_globals.types, tau);
6643       if (i < fun->ndom) {
6644 	return fun->domain[i];
6645       } else if (i == fun->ndom) {
6646 	return fun->range;
6647       }
6648     }
6649   } else {
6650     // bad index or atomic type
6651     set_error_code(INVALID_TYPE_OP);
6652   }
6653   return NULL_TYPE;
6654 }
6655 
6656 
6657 
6658 /*
6659  * Collect all the children in vector *v
6660  * - returns -1 for error, 0 if all fine.
6661  */
yices_type_children(type_t tau,type_vector_t * v)6662 EXPORTED int32_t yices_type_children(type_t tau, type_vector_t *v) {
6663   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_type_children(tau, v));
6664 }
6665 
_o_yices_type_children(type_t tau,type_vector_t * v)6666 int32_t _o_yices_type_children(type_t tau, type_vector_t *v) {
6667   tuple_type_t *tup;
6668   function_type_t *fun;
6669   uint32_t i, n;
6670 
6671   if (! check_good_type(__yices_globals.types, tau)) {
6672     return -1;
6673   }
6674 
6675   v->size = 0;
6676   if (is_tuple_type(__yices_globals.types, tau)) {
6677     tup = tuple_type_desc(__yices_globals.types, tau);
6678     n = tup->nelem;
6679     for (i=0; i<n; i++) {
6680       type_vector_push(v, tup->elem[i]);
6681     }
6682   } else if (is_function_type(__yices_globals.types, tau)) {
6683     fun = function_type_desc(__yices_globals.types, tau);
6684     n = fun->ndom;
6685     for (i=0; i<n; i++) {
6686       type_vector_push(v, fun->domain[i]);
6687     }
6688     type_vector_push(v, fun->range);
6689   }
6690 
6691   return 0;
6692 }
6693 
6694 
6695 
6696 
6697 /***********************
6698  *  TERM EXPLORATION   *
6699  **********************/
6700 
6701 /*
6702  * Get the type of term t
6703  * return NULL_TYPE if t is not a valid term
6704  * and set the error report:
6705  *   code = INVALID_TERM
6706  *   term1 = t
6707  *   index = -1
6708  */
yices_type_of_term(term_t t)6709 EXPORTED type_t yices_type_of_term(term_t t) {
6710   MT_PROTECT(type_t,  __yices_globals.lock, _o_yices_type_of_term(t));
6711 }
6712 
_o_yices_type_of_term(term_t t)6713 type_t _o_yices_type_of_term(term_t t) {
6714   if (! check_good_term(__yices_globals.manager, t)) {
6715     return NULL_TYPE;
6716   }
6717   return term_type(__yices_globals.terms, t);
6718 }
6719 
6720 
6721 /*
6722  * Check the type of a term t:
6723  * - term_is_arithmetic check whether t's type is either int or real
6724  * - term_is_real check whether t's type is real (return false if t's type is int)
6725  * - term_is_int check whether t's type is int
6726  * If t is not a valid term, the check functions return false
6727  * and set the error report as above.
6728  */
yices_term_is_bool(term_t t)6729 EXPORTED int32_t yices_term_is_bool(term_t t) {
6730   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_bool(t));
6731 }
6732 
_o_yices_term_is_bool(term_t t)6733 int32_t _o_yices_term_is_bool(term_t t) {
6734   return check_good_term(__yices_globals.manager, t) && is_boolean_term(__yices_globals.terms, t);
6735 }
6736 
yices_term_is_int(term_t t)6737 EXPORTED int32_t yices_term_is_int(term_t t) {
6738   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_int(t));
6739 }
6740 
_o_yices_term_is_int(term_t t)6741 int32_t _o_yices_term_is_int(term_t t) {
6742   return check_good_term(__yices_globals.manager, t) && is_integer_term(__yices_globals.terms, t);
6743 }
6744 
yices_term_is_real(term_t t)6745 EXPORTED int32_t yices_term_is_real(term_t t) {
6746   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_real(t));
6747 }
6748 
_o_yices_term_is_real(term_t t)6749 int32_t _o_yices_term_is_real(term_t t) {
6750   return check_good_term(__yices_globals.manager, t) && is_real_term(__yices_globals.terms, t);
6751 }
6752 
yices_term_is_arithmetic(term_t t)6753 EXPORTED int32_t yices_term_is_arithmetic(term_t t) {
6754   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_arithmetic(t));
6755 }
6756 
_o_yices_term_is_arithmetic(term_t t)6757 int32_t _o_yices_term_is_arithmetic(term_t t) {
6758   return check_good_term(__yices_globals.manager, t) && is_arithmetic_term(__yices_globals.terms, t);
6759 }
6760 
yices_term_is_bitvector(term_t t)6761 EXPORTED int32_t yices_term_is_bitvector(term_t t) {
6762   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_bitvector(t));
6763 }
6764 
_o_yices_term_is_bitvector(term_t t)6765 int32_t _o_yices_term_is_bitvector(term_t t) {
6766   return check_good_term(__yices_globals.manager, t) && is_bitvector_term(__yices_globals.terms, t);
6767 }
6768 
yices_term_is_tuple(term_t t)6769 EXPORTED int32_t yices_term_is_tuple(term_t t) {
6770   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_tuple(t));
6771 }
6772 
_o_yices_term_is_tuple(term_t t)6773 int32_t _o_yices_term_is_tuple(term_t t) {
6774   return check_good_term(__yices_globals.manager, t) && is_tuple_term(__yices_globals.terms, t);
6775 }
6776 
yices_term_is_function(term_t t)6777 EXPORTED int32_t yices_term_is_function(term_t t) {
6778   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_function(t));
6779 }
6780 
_o_yices_term_is_function(term_t t)6781 int32_t _o_yices_term_is_function(term_t t) {
6782   return check_good_term(__yices_globals.manager, t) && is_function_term(__yices_globals.terms, t);
6783 }
6784 
yices_term_is_scalar(term_t t)6785 EXPORTED int32_t yices_term_is_scalar(term_t t) {
6786   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_scalar(t));
6787 }
6788 
_o_yices_term_is_scalar(term_t t)6789 int32_t _o_yices_term_is_scalar(term_t t) {
6790   term_table_t *tbl;
6791 
6792   tbl = __yices_globals.terms;
6793   return check_good_term(__yices_globals.manager, t) && (is_scalar_term(tbl, t) || is_utype_term(tbl, t));
6794 }
6795 
6796 
6797 /*
6798  * Size of bitvector term t.
6799  * return 0 if t is not a bitvector
6800  */
yices_term_bitsize(term_t t)6801 EXPORTED uint32_t yices_term_bitsize(term_t t) {
6802   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_term_bitsize(t));
6803 }
6804 
_o_yices_term_bitsize(term_t t)6805 uint32_t _o_yices_term_bitsize(term_t t) {
6806   if (! check_bitvector_term(__yices_globals.manager, t)) {
6807     return 0;
6808   }
6809   return term_bitsize(__yices_globals.terms, t);
6810 }
6811 
6812 
6813 /*
6814  * Check whether t is ground
6815  * - return false if t is not valid and set the error report
6816  */
yices_term_is_ground(term_t t)6817 EXPORTED int32_t yices_term_is_ground(term_t t) {
6818   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_ground(t));
6819 }
6820 
_o_yices_term_is_ground(term_t t)6821 int32_t _o_yices_term_is_ground(term_t t) {
6822   return check_good_term(__yices_globals.manager, t) && term_is_ground(get_fvars(), t);
6823 }
6824 
6825 
6826 /*
6827  * Get the free variables of t
6828  * - not part of the official API (because it exports a pointer
6829  *   to some internal data structures).
6830  * - return NULL if t is ground
6831  */
yices_free_vars_of_term(term_t t)6832 harray_t *yices_free_vars_of_term(term_t t) {
6833   assert(check_good_term(__yices_globals.manager, t));
6834   return get_free_vars_of_term(get_fvars(), t);
6835 }
6836 
6837 
6838 /*
6839  * Check structure of term t
6840  * - return false if t is not valid
6841  */
yices_term_is_atomic(term_t t)6842 EXPORTED int32_t yices_term_is_atomic(term_t t) {
6843   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_atomic(t));
6844 }
6845 
_o_yices_term_is_atomic(term_t t)6846 int32_t _o_yices_term_is_atomic(term_t t) {
6847   return check_good_term(__yices_globals.manager, t) && term_is_atomic(__yices_globals.terms, t);
6848 }
6849 
yices_term_is_composite(term_t t)6850 EXPORTED int32_t yices_term_is_composite(term_t t) {
6851   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_composite(t));
6852 }
6853 
_o_yices_term_is_composite(term_t t)6854 int32_t _o_yices_term_is_composite(term_t t) {
6855   return check_good_term(__yices_globals.manager, t) && term_is_composite(__yices_globals.terms, t);
6856 }
6857 
yices_term_is_projection(term_t t)6858 EXPORTED int32_t yices_term_is_projection(term_t t) {
6859   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_projection(t));
6860 }
6861 
_o_yices_term_is_projection(term_t t)6862 int32_t _o_yices_term_is_projection(term_t t) {
6863   return check_good_term(__yices_globals.manager, t) && term_is_projection(__yices_globals.terms, t);
6864 }
6865 
6866 
yices_term_is_sum(term_t t)6867 EXPORTED int32_t yices_term_is_sum(term_t t) {
6868   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_sum(t));
6869 }
6870 
_o_yices_term_is_sum(term_t t)6871 int32_t _o_yices_term_is_sum(term_t t) {
6872   return check_good_term(__yices_globals.manager, t) && term_is_sum(__yices_globals.terms, t);
6873 }
6874 
yices_term_is_bvsum(term_t t)6875 EXPORTED int32_t yices_term_is_bvsum(term_t t) {
6876   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_bvsum(t));
6877 }
6878 
_o_yices_term_is_bvsum(term_t t)6879 int32_t _o_yices_term_is_bvsum(term_t t) {
6880   return check_good_term(__yices_globals.manager, t) && term_is_bvsum(__yices_globals.terms, t);
6881 }
6882 
yices_term_is_product(term_t t)6883 EXPORTED int32_t yices_term_is_product(term_t t) {
6884   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_is_product(t));
6885 }
6886 
_o_yices_term_is_product(term_t t)6887 int32_t _o_yices_term_is_product(term_t t) {
6888   return check_good_term(__yices_globals.manager, t) && term_is_product(__yices_globals.terms, t);
6889 }
6890 
6891 
6892 /*
6893  * Constructor for term t:
6894  * - the return code is defined in yices_types.h
6895  */
yices_term_constructor(term_t t)6896 EXPORTED term_constructor_t yices_term_constructor(term_t t) {
6897   MT_PROTECT(term_constructor_t,  __yices_globals.lock, _o_yices_term_constructor(t));
6898 }
6899 
_o_yices_term_constructor(term_t t)6900 term_constructor_t _o_yices_term_constructor(term_t t) {
6901   if (! check_good_term(__yices_globals.manager, t)) {
6902     return YICES_CONSTRUCTOR_ERROR;
6903   } else {
6904     return term_constructor(__yices_globals.terms, t);
6905   }
6906 }
6907 
6908 
6909 /*
6910  * Number of children of term t
6911  * - for atomic terms, returns 0
6912  * - for composite terms, returns the number of children
6913  * - for projections, returns 1
6914  * - for sums, returns the number of summands
6915  * - for products, returns the number of factors
6916  *
6917  * - returns -1 if t is not a valid term
6918  */
yices_term_num_children(term_t t)6919 EXPORTED int32_t yices_term_num_children(term_t t) {
6920   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_num_children(t));
6921 }
6922 
_o_yices_term_num_children(term_t t)6923 int32_t _o_yices_term_num_children(term_t t) {
6924   if (! check_good_term(__yices_globals.manager, t)) {
6925     return -1;
6926   }
6927   return term_num_children(__yices_globals.terms, t);
6928 }
6929 
6930 
6931 /*
6932  * Get i-th child of a composite term
6933  */
yices_term_child(term_t t,int32_t i)6934 EXPORTED term_t yices_term_child(term_t t, int32_t i) {
6935   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_term_child(t, i));
6936 }
6937 
_o_yices_term_child(term_t t,int32_t i)6938 term_t _o_yices_term_child(term_t t, int32_t i) {
6939   if (! check_good_term(__yices_globals.manager, t) ||
6940       ! check_composite(__yices_globals.terms, t) ||
6941       ! check_child_idx(__yices_globals.terms, t, i)) {
6942     return NULL_TERM;
6943   }
6944   return term_child(__yices_globals.terms, t, i);
6945 }
6946 
6947 
6948 /*
6949  * Store all children of a composite term t in vector v
6950  */
yices_term_children(term_t t,term_vector_t * v)6951 EXPORTED int32_t yices_term_children(term_t t, term_vector_t *v) {
6952   MT_PROTECT(int32_t, __yices_globals.lock, _o_yices_term_children(t, v));
6953 }
6954 
_o_yices_term_children(term_t t,term_vector_t * v)6955 int32_t _o_yices_term_children(term_t t, term_vector_t *v) {
6956   if (! check_good_term(__yices_globals.manager, t) ||
6957       ! check_composite(__yices_globals.terms, t))  {
6958     return -1;
6959   }
6960 
6961   yices_reset_term_vector(v);
6962   get_term_children(__yices_globals.terms, t, (ivector_t *) v);
6963 
6964   return 0;
6965 }
6966 
6967 
6968 /*
6969  * Get the argument and index of a projection
6970  */
yices_proj_index(term_t t)6971 EXPORTED int32_t yices_proj_index(term_t t) {
6972   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_proj_index(t));
6973 }
6974 
_o_yices_proj_index(term_t t)6975 int32_t _o_yices_proj_index(term_t t) {
6976   int32_t idx;
6977 
6978   if (! check_good_term(__yices_globals.manager, t) ||
6979       ! check_projection(__yices_globals.terms, t)) {
6980     return -1;
6981   }
6982   idx = proj_term_index(__yices_globals.terms, t);
6983 
6984   // for tuple projection: the internal index is between 0 and n-1
6985   // but the API uses an index between 1 and n
6986   if (term_kind(__yices_globals.terms, t) == SELECT_TERM) {
6987     idx ++;
6988   }
6989   return idx;
6990 }
6991 
yices_proj_arg(term_t t)6992 EXPORTED term_t yices_proj_arg(term_t t) {
6993   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_proj_arg(t));
6994 }
6995 
_o_yices_proj_arg(term_t t)6996 term_t _o_yices_proj_arg(term_t t) {
6997   if (! check_good_term(__yices_globals.manager, t) ||
6998       ! check_projection(__yices_globals.terms, t)) {
6999     return NULL_TERM;
7000   }
7001   return proj_term_arg(__yices_globals.terms, t);
7002 }
7003 
7004 
7005 /*
7006  * Value of a constant term
7007  */
yices_bool_const_value(term_t t,int32_t * val)7008 EXPORTED int32_t yices_bool_const_value(term_t t, int32_t *val) {
7009   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_bool_const_value(t, val));
7010 }
7011 
_o_yices_bool_const_value(term_t t,int32_t * val)7012 int32_t _o_yices_bool_const_value(term_t t, int32_t *val) {
7013   if (! check_good_term(__yices_globals.manager, t) ||
7014       ! check_constructor(__yices_globals.terms, t, YICES_BOOL_CONSTANT)) {
7015     return -1;
7016   }
7017   *val = bool_const_value(__yices_globals.terms, t);
7018   return 0;
7019 }
7020 
7021 
yices_bv_const_value(term_t t,int32_t val[])7022 EXPORTED int32_t yices_bv_const_value(term_t t, int32_t val[]) {
7023   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_bv_const_value(t, val));
7024 }
7025 
_o_yices_bv_const_value(term_t t,int32_t val[])7026 int32_t _o_yices_bv_const_value(term_t t, int32_t val[]) {
7027   if (! check_good_term(__yices_globals.manager, t) ||
7028       ! check_constructor(__yices_globals.terms, t, YICES_BV_CONSTANT)) {
7029     return -1;
7030   }
7031   bv_const_value(__yices_globals.terms, t, val);
7032   return 0;
7033 }
7034 
yices_scalar_const_value(term_t t,int32_t * val)7035 EXPORTED int32_t yices_scalar_const_value(term_t t, int32_t *val) {
7036   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_scalar_const_value(t, val));
7037 }
7038 
_o_yices_scalar_const_value(term_t t,int32_t * val)7039 int32_t _o_yices_scalar_const_value(term_t t, int32_t *val) {
7040   if (! check_good_term(__yices_globals.manager, t) ||
7041       ! check_constructor(__yices_globals.terms, t, YICES_SCALAR_CONSTANT)) {
7042     return -1;
7043   }
7044   *val = generic_const_value(__yices_globals.terms, t);
7045   return 0;
7046 }
7047 
yices_rational_const_value(term_t t,mpq_t q)7048 EXPORTED int32_t yices_rational_const_value(term_t t, mpq_t q) {
7049   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_rational_const_value(t, q));
7050 }
7051 
_o_yices_rational_const_value(term_t t,mpq_t q)7052 int32_t _o_yices_rational_const_value(term_t t, mpq_t q) {
7053   if (! check_good_term(__yices_globals.manager, t) ||
7054       ! check_constructor(__yices_globals.terms, t, YICES_ARITH_CONSTANT)) {
7055     return -1;
7056   }
7057   arith_const_value(__yices_globals.terms, t, q);
7058   return 0;
7059 }
7060 
7061 
7062 /*
7063  * Components of a sum t
7064  * - i = index (must be between 0 and t's number of children - 1)
7065  * - for an arithmetic sum, each component is a pair (rational, term)
7066  * - for a bitvector sum, each component is a pair (bvconstant, term)
7067  * - the number of bits in the bvconstant is the same as in t
7068  */
yices_sum_component(term_t t,int32_t i,mpq_t coeff,term_t * term)7069 EXPORTED int32_t yices_sum_component(term_t t, int32_t i, mpq_t coeff, term_t *term) {
7070   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_sum_component(t, i, coeff, term));
7071 }
7072 
_o_yices_sum_component(term_t t,int32_t i,mpq_t coeff,term_t * term)7073 int32_t _o_yices_sum_component(term_t t, int32_t i, mpq_t coeff, term_t *term) {
7074   if (! check_good_term(__yices_globals.manager, t) ||
7075       ! check_constructor(__yices_globals.terms, t, YICES_ARITH_SUM) ||
7076       ! check_child_idx(__yices_globals.terms, t, i)) {
7077     return -1;
7078   }
7079   sum_term_component(__yices_globals.terms, t, i, coeff, term);
7080   return 0;
7081 }
7082 
yices_bvsum_component(term_t t,int32_t i,int32_t val[],term_t * term)7083 EXPORTED int32_t yices_bvsum_component(term_t t, int32_t i, int32_t val[], term_t *term) {
7084   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_bvsum_component(t, i, val, term));
7085 }
7086 
_o_yices_bvsum_component(term_t t,int32_t i,int32_t val[],term_t * term)7087 int32_t _o_yices_bvsum_component(term_t t, int32_t i, int32_t val[], term_t *term) {
7088   if (! check_good_term(__yices_globals.manager, t) ||
7089       ! check_constructor(__yices_globals.terms, t, YICES_BV_SUM) ||
7090       ! check_child_idx(__yices_globals.terms, t, i)) {
7091     return -1;
7092   }
7093   bvsum_term_component(__yices_globals.terms, t, i, val, term);
7094   return 0;
7095 }
7096 
7097 
7098 /*
7099  * Component of power product t
7100  * - i = index (must be between 0 and t's arity - 1)
7101  * - the component is of the form (term, exponent)
7102  *   (where exponent is a positive integer)
7103  */
yices_product_component(term_t t,int32_t i,term_t * term,uint32_t * exp)7104 EXPORTED int32_t yices_product_component(term_t t, int32_t i, term_t *term, uint32_t *exp) {
7105   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_product_component(t, i, term, exp));
7106 }
7107 
_o_yices_product_component(term_t t,int32_t i,term_t * term,uint32_t * exp)7108 int32_t _o_yices_product_component(term_t t, int32_t i, term_t *term, uint32_t *exp) {
7109   if (! check_good_term(__yices_globals.manager, t) ||
7110       ! check_constructor(__yices_globals.terms, t, YICES_POWER_PRODUCT) ||
7111       ! check_child_idx(__yices_globals.terms, t, i)) {
7112     return -1;
7113   }
7114   product_term_component(__yices_globals.terms, t, i, term, exp);
7115   return 0;
7116 }
7117 
7118 
7119 /***********************************
7120  *  EXTENSIONS: TERM CONSTRUCTORS  *
7121  **********************************/
7122 
7123 /*
7124  * These term constructors are used in term_stack
7125  *
7126  * IAM: we should probably have a naming convention that indicates their THREAD-SAFE use
7127  */
arith_buffer_get_term(rba_buffer_t * b)7128 term_t arith_buffer_get_term(rba_buffer_t *b) {
7129   return mk_arith_term(__yices_globals.manager, b);
7130 }
7131 
arith_buffer_get_eq0_atom(rba_buffer_t * b)7132 term_t arith_buffer_get_eq0_atom(rba_buffer_t *b) {
7133   return mk_arith_eq0(__yices_globals.manager, b);
7134 }
7135 
arith_buffer_get_geq0_atom(rba_buffer_t * b)7136 term_t arith_buffer_get_geq0_atom(rba_buffer_t *b) {
7137   return mk_arith_geq0(__yices_globals.manager, b);
7138 }
7139 
arith_buffer_get_leq0_atom(rba_buffer_t * b)7140 term_t arith_buffer_get_leq0_atom(rba_buffer_t *b) {
7141   return mk_arith_leq0(__yices_globals.manager, b);
7142 }
7143 
arith_buffer_get_gt0_atom(rba_buffer_t * b)7144 term_t arith_buffer_get_gt0_atom(rba_buffer_t *b) {
7145   return mk_arith_gt0(__yices_globals.manager, b);
7146 }
7147 
arith_buffer_get_lt0_atom(rba_buffer_t * b)7148 term_t arith_buffer_get_lt0_atom(rba_buffer_t *b) {
7149   return mk_arith_lt0(__yices_globals.manager, b);
7150 }
7151 
bvlogic_buffer_get_term(bvlogic_buffer_t * b)7152 term_t bvlogic_buffer_get_term(bvlogic_buffer_t *b) {
7153   return mk_bvlogic_term(__yices_globals.manager, b);
7154 }
7155 
bvlogic_buffer_get_bit(bvlogic_buffer_t * b,uint32_t i)7156 term_t bvlogic_buffer_get_bit(bvlogic_buffer_t *b, uint32_t i) {
7157   return bvl_get_bit(__yices_globals.manager, b, i);
7158 }
7159 
bvarith_buffer_get_term(bvarith_buffer_t * b)7160 term_t bvarith_buffer_get_term(bvarith_buffer_t *b) {
7161   return mk_bvarith_term(__yices_globals.manager, b);
7162 }
7163 
bvarith64_buffer_get_term(bvarith64_buffer_t * b)7164 term_t bvarith64_buffer_get_term(bvarith64_buffer_t *b) {
7165   return mk_bvarith64_term(__yices_globals.manager, b);
7166 }
7167 
yices_bvconst_term(uint32_t n,uint32_t * v)7168 term_t yices_bvconst_term(uint32_t n, uint32_t *v) {
7169   assert(64 < n && n <= YICES_MAX_BVSIZE);
7170   return bvconst_term(__yices_globals.terms, n, v);
7171 }
7172 
yices_bvconst64_term(uint32_t n,uint64_t c)7173 term_t yices_bvconst64_term(uint32_t n, uint64_t c) {
7174   assert(1 <= n && n <= 64 && c == norm64(c, n));
7175   return bv64_constant(__yices_globals.terms, n, c);
7176 }
7177 
yices_rational_term(rational_t * q)7178 term_t yices_rational_term(rational_t *q) {
7179   return arith_constant(__yices_globals.terms, q);
7180 }
7181 
7182 
7183 /*******************************************
7184  *  EXTENSIONS: SUPPORT FOR TYPE CHECKING  *
7185  ******************************************/
7186 
7187 /*
7188  * Check whether t is a valid boolean term
7189  * - if not set the internal error report
7190  *
7191  * If t is not a valid term:
7192  *   code = INVALID_TERM
7193  *   term1 = t
7194  *   index = -1
7195  * If t is not Boolean
7196  *   code = TYPE_MISMATCH
7197  *   term1 = t
7198  *   type = bool
7199  */
yices_check_boolean_term(term_t t)7200 bool yices_check_boolean_term(term_t t) {
7201   return check_good_term(__yices_globals.manager, t) && check_boolean_term(__yices_globals.manager, t);
7202 }
7203 
7204 /*
7205  * Check whether t is a valid arithmetic term
7206  * - if not set the internal error report:
7207  *
7208  * If t is not a valid term:
7209  *   code = INVALID_TERM
7210  *   term1 = t
7211  *   index = -1
7212  * If t is not an arithmetic term;
7213  *   code = ARITHTERM_REQUIRED
7214  *   term1 = t
7215  */
yices_check_arith_term(term_t t)7216 bool yices_check_arith_term(term_t t) {
7217   return check_good_term(__yices_globals.manager, t) && check_arith_term(__yices_globals.manager, t);
7218 }
7219 
7220 
7221 /*
7222  * Check for degree overflow in the product (b * t)
7223  * - b must be a buffer obtained via yices_new_arith_buffer().
7224  * - t must be a valid arithmetic term.
7225  *
7226  * Return true if there's no overflow.
7227  *
7228  * Return false otherwise and set the error report:
7229  *   code = DEGREE_OVERFLOW
7230  *   badval = degree of b + degree of t
7231  */
yices_check_mul_term(rba_buffer_t * b,term_t t)7232 bool yices_check_mul_term(rba_buffer_t *b, term_t t) {
7233   term_table_t *tbl;
7234   uint32_t d1, d2;
7235 
7236   tbl = __yices_globals.terms;
7237 
7238   assert(good_term(tbl, t) && is_arithmetic_term(tbl, t));
7239 
7240   d1 = rba_buffer_degree(b);
7241   d2 = term_degree(tbl, t);
7242   assert(d1 <= YICES_MAX_DEGREE && d2 <= YICES_MAX_DEGREE);
7243 
7244   return check_maxdegree(d1 + d2);
7245 }
7246 
7247 
7248 /*
7249  * Same thing for the product of two buffers b1 and b2.
7250  * - both must be buffers allocated using yices_new_arith_buffer().
7251  */
yices_check_mul_buffer(rba_buffer_t * b1,rba_buffer_t * b2)7252 bool yices_check_mul_buffer(rba_buffer_t *b1, rba_buffer_t *b2) {
7253   uint32_t d1, d2;
7254 
7255   d1 = rba_buffer_degree(b1);
7256   d2 = rba_buffer_degree(b2);
7257   assert(d1 <= YICES_MAX_DEGREE && d2 <= YICES_MAX_DEGREE);
7258 
7259   return check_maxdegree(d1 + d2);
7260 }
7261 
7262 
7263 /*
7264  * Check whether t's type is a subtype of tau
7265  */
yices_check_term_type(term_t t,type_t tau)7266 bool yices_check_term_type(term_t t, type_t tau) {
7267   term_table_t *tbl;
7268 
7269   tbl = __yices_globals.terms;
7270   if (! is_subtype(tbl->types, term_type(tbl, t), tau)) {
7271     error_report_t *error = get_yices_error();
7272     error->code = TYPE_MISMATCH;
7273     error->term1 = t;
7274     error->type1 = tau;
7275     return false;
7276   }
7277 
7278   return true;
7279 }
7280 
7281 /*
7282  * Check whether n <= YICES_MAX_BVSIZE and if not set the error report.
7283  */
yices_check_bvsize(uint32_t n)7284 bool yices_check_bvsize(uint32_t n) {
7285   return check_maxbvsize(n);
7286 }
7287 
7288 
7289 /*
7290  * Check whether t is a valid bitvector term
7291  * - if not set the internal error report:
7292  *
7293  * If t is not a valid term:
7294  *   code = INVALID_TERM
7295  *   term1 = t
7296  *   index = -1
7297  * If t is not an arithmetic term;
7298  *   code = BITVECTOR_REQUIRED
7299  *   term1 = t
7300  */
yices_check_bv_term(term_t t)7301 bool yices_check_bv_term(term_t t) {
7302   return check_good_term(__yices_globals.manager, t) && check_bitvector_term(__yices_globals.manager, t);
7303 }
7304 
7305 
7306 /*
7307  * Check whether b is non empty
7308  * Error report:
7309  *   code = EMPTY_BITVECTOR
7310  */
yices_check_bvlogic_buffer(bvlogic_buffer_t * b)7311 bool yices_check_bvlogic_buffer(bvlogic_buffer_t *b) {
7312   if (bvlogic_buffer_is_empty(b)) {
7313     set_error_code(EMPTY_BITVECTOR);
7314     return false;
7315   }
7316   return true;
7317 }
7318 
7319 
7320 /*
7321  * Check whether s is a valid shift amount for buffer b:
7322  * - return true if 0 <= s <= b->bitsize
7323  * - otherwise set the error report and return false.
7324  */
yices_check_bitshift(bvlogic_buffer_t * b,int32_t s)7325 bool yices_check_bitshift(bvlogic_buffer_t *b, int32_t s) {
7326   if (s < 0 || s > bvlogic_buffer_bitsize(b)) {
7327     error_report_t *error = get_yices_error();
7328     error->code = INVALID_BITSHIFT;
7329     error->badval = s;
7330     return false;
7331   }
7332 
7333   return true;
7334 }
7335 
7336 
7337 /*
7338  * Check whether s is a valid shift amount for rotate_left/rotate_right in SMT-LIB2
7339  * - SMT allows rotate by arbitrary amounts: ((_ rotate_left k) t) is the same
7340  *   as ((_ rotate_left (k % n) t)) where n = number of bits in t.
7341  *
7342  * This function
7343  * - return true if 0 <= s and store the normalize shift (s % b->nbits) in *s
7344  * - otherwise set the error report and return false.
7345  */
yices_check_smt2_rotate(bvlogic_buffer_t * b,int32_t * s)7346 bool yices_check_smt2_rotate(bvlogic_buffer_t *b, int32_t *s) {
7347   int32_t shift;
7348   uint32_t n;
7349 
7350   shift = *s;
7351   if (shift < 0) {
7352     error_report_t *error = get_yices_error();
7353     error->code = INVALID_BITSHIFT;
7354     error->badval = shift;
7355     return false;
7356   }
7357 
7358   n = bvlogic_buffer_bitsize(b);
7359   if (shift >= n && n > 0) {
7360     shift = shift % n;
7361     *s = shift;
7362   }
7363 
7364   return true;
7365 }
7366 
7367 
7368 /*
7369  * Check whether [i, j] is a valid segment for a vector of n bits
7370  * - return true if 0 <= i <= j <= n
7371  * - otherwise set the error report and return false.
7372  */
yices_check_bvextract(uint32_t n,int32_t i,int32_t j)7373 bool yices_check_bvextract(uint32_t n, int32_t i, int32_t j) {
7374   if (i < 0 || i > j || j >= n) {
7375     set_error_code(INVALID_BVEXTRACT);
7376     return false;
7377   }
7378 
7379   return true;
7380 }
7381 
7382 
7383 /*
7384  * Check whether i is a valid bit index for a bitvector of size n
7385  * - return true if 0 <= i < n
7386  * - otherwise set the error report and return false.
7387  */
yices_check_bitextract(uint32_t n,int32_t i)7388 bool yices_check_bitextract(uint32_t n, int32_t i) {
7389   if (i < 0 || i >= n) {
7390     set_error_code(INVALID_BITEXTRACT);
7391     return false;
7392   }
7393   return true;
7394 }
7395 
7396 
7397 /*
7398  * Check whether repeat_concat(b, n) is valid
7399  * - return true if it is
7400  * - return false and set error report if it's not.
7401  *
7402  * Error report:
7403  * if n <= 0
7404  *   code = POSINT_REQUIRED
7405  *   badval = n
7406  * if size of the result would be more than MAX_BVSIZE
7407  *   code = MAX_BVSIZE_EXCEEDED
7408  *   badval = n * bitsize of t
7409  */
yices_check_bvrepeat(bvlogic_buffer_t * b,int32_t n)7410 bool yices_check_bvrepeat(bvlogic_buffer_t *b, int32_t n) {
7411   uint64_t m;
7412 
7413   if (n <= 0) {
7414     error_report_t *error = get_yices_error();
7415     error->code = POS_INT_REQUIRED;
7416     error->badval = n;
7417     return false;
7418   }
7419 
7420   m = ((uint64_t) n) * bvlogic_buffer_bitsize(b);
7421   if (m > ((uint64_t) YICES_MAX_BVSIZE)) {
7422     error_report_t *error = get_yices_error();
7423     error->code = MAX_BVSIZE_EXCEEDED;
7424     error->badval = m;
7425     return false;
7426   }
7427 
7428   return true;
7429 }
7430 
7431 
7432 
7433 /*
7434  * Check whether zero_extend(b, n) and sign_extend(b, n) are valid;
7435  * - n is the number of bits to add
7436  * - return true if 0 <= n, b->bitsize != 0, and (n + b->bitsize) <= MAX_BVSIZE
7437  * - return false and set an error report otherwise.
7438  *
7439  * Error reports:
7440  * - if b is empty: EMPTY_BITVECTOR
7441  * - if n < 0: NONNEG_INT_REQUIRED
7442  * - if n + b->bitsize > MAX_BVSIZE: MAX_BVSIZE_EXCEEDED
7443  */
yices_check_bvextend(bvlogic_buffer_t * b,int32_t n)7444 bool yices_check_bvextend(bvlogic_buffer_t *b, int32_t n) {
7445   uint64_t m;
7446 
7447   if (n < 0) {
7448     error_report_t *error = get_yices_error();
7449     error->code = NONNEG_INT_REQUIRED;
7450     error->badval = n;
7451     return false;
7452   }
7453 
7454   m = bvlogic_buffer_bitsize(b);
7455   if (m == 0) {
7456     set_error_code(EMPTY_BITVECTOR);
7457     return false;
7458   }
7459 
7460   m += n;
7461   if (m >= ((uint64_t) YICES_MAX_BVSIZE)) {
7462     error_report_t *error = get_yices_error();
7463     error->code = MAX_BVSIZE_EXCEEDED;
7464     error->badval = m;
7465     return false;
7466   }
7467 
7468   return true;
7469 }
7470 
7471 
7472 /*
7473  * Checks for degree overflow in bitvector multiplication:
7474  * - four variants depending on the type of buffer used
7475  *   and on whether the argument is a term or a buffer
7476  *
7477  * In all cases, the function set the error report and
7478  * return false if there's an overflow:
7479  *   code = DEGREE_OVERFLOW
7480  *   badval = degree of the product
7481  *
7482  * All return true if there's no overflow.
7483  */
yices_check_bvmul64_term(bvarith64_buffer_t * b,term_t t)7484 bool yices_check_bvmul64_term(bvarith64_buffer_t *b, term_t t) {
7485   term_table_t *tbl;
7486   uint32_t d1, d2;
7487 
7488   tbl = __yices_globals.terms;
7489 
7490   assert(good_term(tbl, t) && is_bitvector_term(tbl, t));
7491 
7492   d1 = bvarith64_buffer_degree(b);
7493   d2 = term_degree(tbl, t);
7494 
7495   assert(d1 <= YICES_MAX_DEGREE && d2 <= YICES_MAX_DEGREE);
7496 
7497   return check_maxdegree(d1 + d2);
7498 }
7499 
yices_check_bvmul64_buffer(bvarith64_buffer_t * b1,bvarith64_buffer_t * b2)7500 bool yices_check_bvmul64_buffer(bvarith64_buffer_t *b1, bvarith64_buffer_t *b2) {
7501   uint32_t d1, d2;
7502 
7503   d1 = bvarith64_buffer_degree(b1);
7504   d2 = bvarith64_buffer_degree(b2);
7505 
7506   assert(d1 <= YICES_MAX_DEGREE && d2 <= YICES_MAX_DEGREE);
7507 
7508   return check_maxdegree(d1 + d2);
7509 }
7510 
yices_check_bvmul_term(bvarith_buffer_t * b,term_t t)7511 bool yices_check_bvmul_term(bvarith_buffer_t *b, term_t t) {
7512   term_table_t *tbl;
7513   uint32_t d1, d2;
7514 
7515   tbl = __yices_globals.terms;
7516 
7517   assert(good_term(tbl, t) && is_bitvector_term(tbl, t));
7518 
7519   d1 = bvarith_buffer_degree(b);
7520   d2 = term_degree(tbl, t);
7521 
7522   assert(d1 <= YICES_MAX_DEGREE && d2 <= YICES_MAX_DEGREE);
7523 
7524   return check_maxdegree(d1 + d2);
7525 }
7526 
yices_check_bvmul_buffer(bvarith_buffer_t * b1,bvarith_buffer_t * b2)7527 bool yices_check_bvmul_buffer(bvarith_buffer_t *b1, bvarith_buffer_t *b2) {
7528   uint32_t d1, d2;
7529 
7530   d1 = bvarith_buffer_degree(b1);
7531   d2 = bvarith_buffer_degree(b2);
7532 
7533   assert(d1 <= YICES_MAX_DEGREE && d2 <= YICES_MAX_DEGREE);
7534 
7535   return check_maxdegree(d1 + d2);
7536 }
7537 
7538 
7539 /*
7540  * Check whether b contains an integer polynomial
7541  */
yices_arith_buffer_is_int(rba_buffer_t * b)7542 bool yices_arith_buffer_is_int(rba_buffer_t *b) {
7543   return arith_poly_is_integer(__yices_globals.terms, b);
7544 }
7545 
7546 
7547 
7548 
7549 /************************
7550  *  TERM SUBSTITUTION   *
7551  ***********************/
7552 
7553 /*
7554  * Apply the substitution defined by arrays var and map to a term t -
7555  * var must be an array of n variables (variables are created using
7556  * yices_new_variables).
7557  * - map must be an array of n terms
7558  * - the type of map[i] must be a subtype of var[i]'s type
7559  * - every occurrence of var[i] in t is replaced by map[i]
7560  *
7561  *
7562  * Return the resulting term or NULL_TERM if there's an error.
7563  *
7564  * Error codes:
7565  * - INVALID_TERM if var[i] or map[i] is not valid
7566  * - VARIABLE_REQUIRED if var[i] is not a variable
7567  * - TYPE_MISMATCH if map[i]'s type is not a subtype of var[i]'s type
7568  * - DEGREE_OVERFLOW if the substitution causes an overflow
7569  */
yices_subst_term(uint32_t n,const term_t var[],const term_t map[],term_t t)7570 EXPORTED term_t yices_subst_term(uint32_t n, const term_t var[], const term_t map[], term_t t) {
7571   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_subst_term(n, var, map, t));
7572 }
7573 
_o_yices_subst_term(uint32_t n,const term_t var[],const term_t map[],term_t t)7574 term_t _o_yices_subst_term(uint32_t n, const term_t var[], const term_t map[], term_t t) {
7575   term_subst_t subst;
7576   term_t u;
7577 
7578   if (! check_good_term(__yices_globals.manager, t) ||
7579       ! check_good_substitution(__yices_globals.manager, n, var, map)) {
7580     return NULL_TERM;
7581   }
7582 
7583   init_term_subst(&subst, __yices_globals.manager, n, var, map);
7584   u = apply_term_subst(&subst, t);
7585   delete_term_subst(&subst);
7586 
7587   if (u < 0) {
7588     error_report_t *error = get_yices_error();
7589     if (u == -1) {
7590       // degree overflow
7591       error->code = DEGREE_OVERFLOW;
7592       error->badval = YICES_MAX_DEGREE + 1;
7593     } else {
7594       // BUG
7595       error->code = INTERNAL_EXCEPTION;
7596     }
7597     u = NULL_TERM;
7598   }
7599 
7600   return u;
7601 }
7602 
7603 
7604 /*
7605  * Variant: apply the substitution to m terms t[0 .. m-1]
7606  */
yices_subst_term_array(uint32_t n,const term_t var[],const term_t map[],uint32_t m,term_t t[])7607 EXPORTED int32_t yices_subst_term_array(uint32_t n, const term_t var[], const term_t map[], uint32_t m, term_t t[]) {
7608   MT_PROTECT(int32_t, __yices_globals.lock, _o_yices_subst_term_array(n, var, map, m, t));
7609 }
7610 
_o_yices_subst_term_array(uint32_t n,const term_t var[],const term_t map[],uint32_t m,term_t t[])7611 int32_t _o_yices_subst_term_array(uint32_t n, const term_t var[], const term_t map[], uint32_t m, term_t t[]) {
7612   term_subst_t subst;
7613   term_t u;
7614   uint32_t i;
7615 
7616   if (! check_good_terms(__yices_globals.manager, m, t) ||
7617       ! check_good_substitution(__yices_globals.manager, n, var, map)) {
7618     return -1;
7619   }
7620 
7621   init_term_subst(&subst, __yices_globals.manager, n, var, map);
7622   for (i=0; i<m; i++) {
7623     u = apply_term_subst(&subst, t[i]);
7624     if (u < 0)  goto subst_error;
7625     t[i] = u;
7626   }
7627   delete_term_subst(&subst);
7628 
7629   return 0;
7630 
7631  subst_error:
7632   if (u == -1) {
7633     error_report_t *error = get_yices_error();
7634     // degree overflow
7635     error->code = DEGREE_OVERFLOW;
7636     error->badval = YICES_MAX_DEGREE + 1;
7637   } else {
7638     // BUG
7639     set_error_code(INTERNAL_EXCEPTION);
7640   }
7641   delete_term_subst(&subst);
7642 
7643   return -1;
7644 }
7645 
7646 
7647 
7648 /**************
7649  *  PARSING   *
7650  *************/
7651 
7652 /*
7653  * Parse s as a type expression in the Yices language.
7654  * Return NULL_TYPE if there's an error.
7655  */
yices_parse_type(const char * s)7656 EXPORTED type_t yices_parse_type(const char *s) {
7657   MT_PROTECT(type_t,  __yices_globals.lock, _o_yices_parse_type(s));
7658 }
7659 
_o_yices_parse_type(const char * s)7660 type_t _o_yices_parse_type(const char *s) {
7661   parser_t *p;
7662 
7663   p = get_parser(s);
7664   return parse_yices_type(p, NULL);
7665 }
7666 
7667 
7668 /*
7669  * Parse s as a term in the Yices language.
7670  * Return NULL_TERM if there's an error.
7671  */
yices_parse_term(const char * s)7672 EXPORTED term_t yices_parse_term(const char *s) {
7673   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_parse_term(s));
7674 }
7675 
_o_yices_parse_term(const char * s)7676 term_t _o_yices_parse_term(const char *s) {
7677   parser_t *p;
7678 
7679   p = get_parser(s);
7680   return parse_yices_term(p, NULL);
7681 }
7682 
7683 
7684 
7685 
7686 
7687 /************
7688  *  NAMES   *
7689  ***********/
7690 
7691 /*
7692  * Create mapping (name -> tau) in the type table.
7693  * If a previous mapping (name -> tau') is in the table, then
7694  * it is hidden.
7695  *
7696  * return -1 if tau is invalid and set error report
7697  * return 0 otherwise.
7698  */
yices_set_type_name(type_t tau,const char * name)7699 EXPORTED int32_t yices_set_type_name(type_t tau, const char *name) {
7700   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_set_type_name(tau, name));
7701 }
7702 
_o_yices_set_type_name(type_t tau,const char * name)7703 int32_t _o_yices_set_type_name(type_t tau, const char *name) {
7704   char *clone;
7705 
7706   if (! check_good_type(__yices_globals.types, tau)) {
7707     return -1;
7708   }
7709 
7710   // make a copy of name
7711   clone = clone_string(name);
7712   set_type_name(__yices_globals.types, tau, clone);
7713 
7714   return 0;
7715 }
7716 
7717 
7718 /*
7719  * Create mapping (name -> t) in the term table.
7720  * If a previous mapping (name -> t') is in the table, then
7721  * it is hidden.
7722  *
7723  * return -1 if  is invalid and set error report
7724  * return 0 otherwise.
7725  */
yices_set_term_name(term_t t,const char * name)7726 EXPORTED int32_t yices_set_term_name(term_t t, const char *name) {
7727   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_set_term_name(t, name));
7728 }
7729 
_o_yices_set_term_name(term_t t,const char * name)7730 int32_t _o_yices_set_term_name(term_t t, const char *name) {
7731   char *clone;
7732 
7733   if (! check_good_term(__yices_globals.manager, t)) {
7734     return -1;
7735   }
7736 
7737   // make a copy of name
7738   clone = clone_string(name);
7739   set_term_name(__yices_globals.terms, t, clone);
7740 
7741   return 0;
7742 }
7743 
7744 
7745 /*
7746  * Get name of type tau
7747  * - return NULL if tau has no name (or if tau is not a valid type)
7748  */
yices_get_type_name(type_t tau)7749 EXPORTED const char *yices_get_type_name(type_t tau) {
7750   MT_PROTECT(const char *,  __yices_globals.lock, _o_yices_get_type_name(tau));
7751 }
7752 
_o_yices_get_type_name(type_t tau)7753 const char *_o_yices_get_type_name(type_t tau) {
7754   if (! check_good_type(__yices_globals.types, tau)) {
7755     return NULL;
7756   }
7757   return type_name(__yices_globals.types, tau);
7758 }
7759 
7760 
7761 /*
7762  * Get name of term t
7763  * - return NULL is t has no name (or if t is not a valid term)
7764  */
yices_get_term_name(term_t t)7765 EXPORTED const char *yices_get_term_name(term_t t) {
7766   MT_PROTECT(const char *,  __yices_globals.lock, _o_yices_get_term_name(t));
7767 }
7768 
_o_yices_get_term_name(term_t t)7769 const char *_o_yices_get_term_name(term_t t) {
7770   if (! check_good_term(__yices_globals.manager, t)) {
7771     return NULL;
7772   }
7773   return term_name(__yices_globals.terms, t);
7774 }
7775 
7776 
7777 
7778 /*
7779  * Remove name from the type table.
7780  */
yices_remove_type_name(const char * name)7781 EXPORTED void yices_remove_type_name(const char *name) {
7782   MT_PROTECT_VOID(__yices_globals.lock, _o_yices_remove_type_name(name));
7783 }
7784 
_o_yices_remove_type_name(const char * name)7785 void _o_yices_remove_type_name(const char *name) {
7786   remove_type_name(__yices_globals.types, name);
7787 }
7788 
7789 
7790 /*
7791  * Remove name from the term table.
7792  */
yices_remove_term_name(const char * name)7793 EXPORTED void yices_remove_term_name(const char *name) {
7794   MT_PROTECT_VOID(__yices_globals.lock, _o_yices_remove_term_name(name));
7795 }
7796 
_o_yices_remove_term_name(const char * name)7797 void _o_yices_remove_term_name(const char *name) {
7798   remove_term_name(__yices_globals.terms, name);
7799 }
7800 
7801 
7802 /*
7803  * Get type of the given name or return NULL_TYPE (-1)
7804  */
yices_get_type_by_name(const char * name)7805 EXPORTED type_t yices_get_type_by_name(const char *name) {
7806   MT_PROTECT(type_t,  __yices_globals.lock, _o_yices_get_type_by_name(name));
7807 }
7808 
_o_yices_get_type_by_name(const char * name)7809 type_t _o_yices_get_type_by_name(const char *name) {
7810   return get_type_by_name(__yices_globals.types, name);
7811 }
7812 
7813 
7814 /*
7815  * Get term of the given name or return NULL_TERM
7816  */
yices_get_term_by_name(const char * name)7817 EXPORTED term_t yices_get_term_by_name(const char *name) {
7818   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_get_term_by_name(name));
7819 }
7820 
_o_yices_get_term_by_name(const char * name)7821 term_t _o_yices_get_term_by_name(const char *name) {
7822   return get_term_by_name(__yices_globals.terms, name);
7823 }
7824 
7825 
7826 /*
7827  * Remove the name of type tau (if any)
7828  * Return -1 if tau is not a valid type and set the error code.
7829  * Return 0 otherwise.
7830  */
yices_clear_type_name(type_t tau)7831 EXPORTED int32_t yices_clear_type_name(type_t tau) {
7832   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_clear_type_name(tau));
7833 }
7834 
_o_yices_clear_type_name(type_t tau)7835 int32_t _o_yices_clear_type_name(type_t tau) {
7836   if (! check_good_type(__yices_globals.types, tau)) {
7837     return -1;
7838   }
7839 
7840   clear_type_name(__yices_globals.types, tau);
7841   return 0;
7842 }
7843 
7844 
7845 /*
7846  * Remove the name of term t (if any)
7847  *
7848  * Return -1 if t is not a valid term (and set the error code)
7849  * Return 0 otherwise.
7850  */
yices_clear_term_name(term_t t)7851 EXPORTED int32_t yices_clear_term_name(term_t t) {
7852   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_clear_term_name(t));
7853 }
7854 
_o_yices_clear_term_name(term_t t)7855 int32_t _o_yices_clear_term_name(term_t t) {
7856   if (! check_good_term(__yices_globals.manager, t)) {
7857     return -1;
7858   }
7859 
7860   clear_term_name(__yices_globals.terms, t);
7861   return 0;
7862 }
7863 
7864 
7865 
7866 /****************************
7867  *  CONTEXT CONFIGURATIONS  *
7868  ***************************/
7869 
7870 /*
7871  * Allocate a new configuration descriptor
7872  * - initialize it do defaults
7873  */
yices_new_config(void)7874 EXPORTED ctx_config_t *yices_new_config(void) {
7875   ctx_config_t *tmp;
7876 
7877   tmp = alloc_config_structure();
7878   init_config_to_defaults(tmp);
7879 
7880   return tmp;
7881 }
7882 
7883 
7884 /*
7885  * Delete
7886  */
yices_free_config(ctx_config_t * config)7887 EXPORTED void yices_free_config(ctx_config_t *config) {
7888   free_config_structure(config);
7889 }
7890 
7891 
7892 /*
7893  * Set a configuration parameter
7894  */
yices_set_config(ctx_config_t * config,const char * name,const char * value)7895 EXPORTED int32_t yices_set_config(ctx_config_t *config, const char *name, const char *value) {
7896   int32_t k;
7897 
7898   k = config_set_field(config, name, value);
7899   if (k < 0) {
7900     if (k == -1) {
7901       // invalid name
7902       set_error_code(CTX_UNKNOWN_PARAMETER);
7903     } else {
7904       set_error_code(CTX_INVALID_PARAMETER_VALUE);
7905     }
7906     return -1;
7907   }
7908 
7909   return 0;
7910 }
7911 
7912 
7913 /*
7914  * Set config to a default solver combination for the given logic
7915  * - return -1 if there's an error
7916  * - return 0 otherwise
7917  */
yices_default_config_for_logic(ctx_config_t * config,const char * logic)7918 EXPORTED int32_t yices_default_config_for_logic(ctx_config_t *config, const char *logic) {
7919   int32_t k;
7920 
7921   k = config_set_logic(config, logic);
7922   if (k < 0) {
7923     if (k == -1) {
7924       set_error_code(CTX_UNKNOWN_LOGIC);
7925     } else {
7926       set_error_code(CTX_LOGIC_NOT_SUPPORTED);
7927     }
7928     return -1;
7929   }
7930 
7931   return 0;
7932 }
7933 
7934 
7935 
7936 /*******************************************
7937  *  SIMPLIFICATION/PREPROCESSING OPTIONS   *
7938  ******************************************/
7939 
7940 /*
7941  * Parameters are identified by an integer in the following range
7942  */
7943 typedef enum ctx_option {
7944   CTX_OPTION_VAR_ELIM,
7945   CTX_OPTION_ARITH_ELIM,
7946   CTX_OPTION_BVARITH_ELIM,
7947   CTX_OPTION_FLATTEN,
7948   CTX_OPTION_LEARN_EQ,
7949   CTX_OPTION_BREAK_SYMMETRIES,
7950   CTX_OPTION_KEEP_ITE,
7951   CTX_OPTION_EAGER_ARITH_LEMMAS,
7952   CTX_OPTION_ASSERT_ITE_BOUNDS,
7953 } ctx_option_t;
7954 
7955 #define NUM_CTX_OPTIONS (CTX_OPTION_ASSERT_ITE_BOUNDS+1)
7956 
7957 
7958 /*
7959  * Option names in lexicographic order
7960  */
7961 static const char * const ctx_option_names[NUM_CTX_OPTIONS] = {
7962   "arith-elim",
7963   "assert-ite-bounds",
7964   "break-symmetries",
7965   "bvarith-elim",
7966   "eager-arith-lemmas",
7967   "flatten",
7968   "keep-ite",
7969   "learn-eq",
7970   "var-elim",
7971 };
7972 
7973 
7974 /*
7975  * Corresponding index (cf. string_utils.h for parse_as_keyword)
7976  */
7977 static const int32_t ctx_option_key[NUM_CTX_OPTIONS] = {
7978   CTX_OPTION_ARITH_ELIM,
7979   CTX_OPTION_ASSERT_ITE_BOUNDS,
7980   CTX_OPTION_BREAK_SYMMETRIES,
7981   CTX_OPTION_BVARITH_ELIM,
7982   CTX_OPTION_EAGER_ARITH_LEMMAS,
7983   CTX_OPTION_FLATTEN,
7984   CTX_OPTION_KEEP_ITE,
7985   CTX_OPTION_LEARN_EQ,
7986   CTX_OPTION_VAR_ELIM,
7987 };
7988 
7989 
7990 /*
7991  * Enable a specific option
7992  */
yices_context_enable_option(context_t * ctx,const char * option)7993 EXPORTED int32_t yices_context_enable_option(context_t *ctx, const char *option) {
7994   int32_t k, r;
7995 
7996   r = 0; // default return code: no error
7997   k = parse_as_keyword(option, ctx_option_names, ctx_option_key, NUM_CTX_OPTIONS);
7998   switch (k) {
7999   case CTX_OPTION_VAR_ELIM:
8000     enable_variable_elimination(ctx);
8001     break;
8002 
8003   case CTX_OPTION_ARITH_ELIM:
8004     enable_arith_elimination(ctx);
8005     break;
8006 
8007   case CTX_OPTION_BVARITH_ELIM:
8008     enable_bvarith_elimination(ctx);
8009     break;
8010 
8011   case CTX_OPTION_FLATTEN:
8012     enable_diseq_and_or_flattening(ctx);
8013     break;
8014 
8015   case CTX_OPTION_LEARN_EQ:
8016     enable_eq_abstraction(ctx);
8017     break;
8018 
8019   case CTX_OPTION_BREAK_SYMMETRIES:
8020     enable_symmetry_breaking(ctx);
8021     break;
8022 
8023   case CTX_OPTION_KEEP_ITE:
8024     enable_keep_ite(ctx);
8025     break;
8026 
8027   case CTX_OPTION_EAGER_ARITH_LEMMAS:
8028     enable_splx_eager_lemmas(ctx);
8029     break;
8030 
8031   case CTX_OPTION_ASSERT_ITE_BOUNDS:
8032     enable_assert_ite_bounds(ctx);
8033     break;
8034 
8035   default:
8036     assert(k == -1);
8037     // not recognized
8038     set_error_code(CTX_UNKNOWN_PARAMETER);
8039     r = -1;
8040     break;
8041   }
8042 
8043   return r;
8044 }
8045 
8046 
8047 /*
8048  * Disable a specific option
8049  */
yices_context_disable_option(context_t * ctx,const char * option)8050 EXPORTED int32_t yices_context_disable_option(context_t *ctx, const char *option) {
8051   int32_t k, r;
8052 
8053   r = 0; // default return code: no error
8054   k = parse_as_keyword(option, ctx_option_names, ctx_option_key, NUM_CTX_OPTIONS);
8055   switch (k) {
8056   case CTX_OPTION_VAR_ELIM:
8057     disable_variable_elimination(ctx);
8058     break;
8059 
8060   case CTX_OPTION_ARITH_ELIM:
8061     disable_arith_elimination(ctx);
8062     break;
8063 
8064   case CTX_OPTION_BVARITH_ELIM:
8065     disable_bvarith_elimination(ctx);
8066     break;
8067 
8068   case CTX_OPTION_FLATTEN:
8069     disable_diseq_and_or_flattening(ctx);
8070     break;
8071 
8072   case CTX_OPTION_LEARN_EQ:
8073     disable_eq_abstraction(ctx);
8074     break;
8075 
8076   case CTX_OPTION_BREAK_SYMMETRIES:
8077     disable_symmetry_breaking(ctx);
8078     break;
8079 
8080   case CTX_OPTION_KEEP_ITE:
8081     disable_keep_ite(ctx);
8082     break;
8083 
8084   case CTX_OPTION_EAGER_ARITH_LEMMAS:
8085     disable_splx_eager_lemmas(ctx);
8086     break;
8087 
8088   case CTX_OPTION_ASSERT_ITE_BOUNDS:
8089     disable_assert_ite_bounds(ctx);
8090     break;
8091 
8092   default:
8093     set_error_code(CTX_UNKNOWN_PARAMETER);
8094     r = -1;
8095     break;
8096   }
8097 
8098   return r;
8099 }
8100 
8101 
8102 
8103 /*************************************
8104  *  SEARCH PARAMETER CONFIGURATIONS  *
8105  ************************************/
8106 
8107 /*
8108  * Allocate a new configuration descriptor
8109  * - initialize it do defaults
8110  */
yices_new_param_record(void)8111 EXPORTED param_t *yices_new_param_record(void) {
8112   param_t *tmp;
8113 
8114   tmp = alloc_param_structure();
8115   init_params_to_defaults(tmp);
8116   return tmp;
8117 }
8118 
8119 /*
8120  * Delete
8121  */
yices_free_param_record(param_t * param)8122 EXPORTED void yices_free_param_record(param_t *param) {
8123   free_param_structure(param);
8124 }
8125 
8126 /*
8127  * Set a search parameter
8128  */
yices_set_param(param_t * param,const char * name,const char * value)8129 EXPORTED int32_t yices_set_param(param_t *param, const char *name, const char *value) {
8130   int32_t k;
8131 
8132   k = params_set_field(param, name, value);
8133   if (k < 0) {
8134     if (k == -1) {
8135       set_error_code(CTX_UNKNOWN_PARAMETER);
8136     } else {
8137       set_error_code(CTX_INVALID_PARAMETER_VALUE);
8138     }
8139     return -1;
8140   }
8141 
8142   return 0;
8143 }
8144 
8145 
8146 
8147 /*************************
8148  *  CONTEXT OPERATIONS   *
8149  ************************/
8150 
8151 /*
8152  * Set the default preprocessing options for a context
8153  * - logic = logic code (or SMT_UNKNOWN)
8154  * - arch = architecture
8155  * - iflag = true if integer solver is active
8156  * - qflag = true if quantifier support is required
8157  *
8158  * Note: these settings are based on benchmarking using the SMT-LIB 1.2
8159  * benchmarks (cf. yices_smtcomp.c)
8160  */
context_set_default_options(context_t * ctx,smt_logic_t logic,context_arch_t arch,bool iflag,bool qflag)8161 static void context_set_default_options(context_t *ctx, smt_logic_t logic, context_arch_t arch, bool iflag, bool qflag) {
8162   enable_variable_elimination(ctx);
8163   enable_eq_abstraction(ctx);
8164   enable_arith_elimination(ctx);
8165   enable_bvarith_elimination(ctx);
8166 
8167   if (iflag) {
8168     enable_splx_periodic_icheck(ctx);
8169   }
8170 
8171   // Special preprocessing
8172   if (logic == QF_LRA) {
8173     enable_cond_def_preprocessing(ctx);
8174   }
8175   if (logic == QF_LIRA) {
8176     enable_or_factoring(ctx);
8177   }
8178 
8179   switch (arch) {
8180   case CTX_ARCH_EG:
8181     enable_diseq_and_or_flattening(ctx);
8182     if (context_get_mode(ctx) == CTX_MODE_ONECHECK) {
8183       enable_symmetry_breaking(ctx);
8184     }
8185     break;
8186 
8187   case CTX_ARCH_BV:
8188     // flattening makes things worse for QF_BV
8189     //   disable_diseq_and_or_flattening(ctx); FOR TESTING THE SHARING STUFF (2015/04/22)
8190     enable_diseq_and_or_flattening(ctx); // FOR TESTING THE SHARING STUFF (2015/04/22)
8191     break;
8192 
8193   case CTX_ARCH_SPLX:
8194     enable_splx_eager_lemmas(ctx);
8195     enable_diseq_and_or_flattening(ctx);
8196     enable_assert_ite_bounds(ctx);
8197     enable_ite_flattening(ctx);
8198     break;
8199 
8200   case CTX_ARCH_EGSPLX:
8201   case CTX_ARCH_EGFUNSPLX:
8202     enable_splx_eager_lemmas(ctx);
8203     enable_diseq_and_or_flattening(ctx);
8204     enable_splx_eqprop(ctx);
8205     enable_assert_ite_bounds(ctx);
8206     enable_ite_flattening(ctx);
8207     break;
8208 
8209   case CTX_ARCH_EGBV:
8210   case CTX_ARCH_EGFUNBV:
8211     // no ite_flattening (TO BE CONFIRMED)
8212     enable_diseq_and_or_flattening(ctx);
8213     break;
8214 
8215   default:
8216     enable_diseq_and_or_flattening(ctx);
8217     break;
8218   }
8219 
8220 }
8221 
8222 
8223 
8224 /*
8225  * Allocate and initialize a new context.
8226  * The configuration is specified by logic/arch/mode/iflag/qflag.
8227  * - logic = SMT_UNKNOWN or a logic code
8228  * - arch = architecture to use
8229  * - mode = which optional features are supported
8230  * - iflag = true to active the integer solver
8231  * - qflag = true to support quantifiers
8232  */
_o_yices_create_context(smt_logic_t logic,context_arch_t arch,context_mode_t mode,bool iflag,bool qflag)8233 static context_t *_o_yices_create_context(smt_logic_t logic, context_arch_t arch, context_mode_t mode, bool iflag, bool qflag) {
8234   context_t *ctx;
8235 
8236   ctx = alloc_context();
8237   init_context(ctx, __yices_globals.terms, logic, mode, arch, qflag);
8238   context_set_default_options(ctx, logic, arch, iflag, qflag);
8239 
8240   return ctx;
8241 }
8242 
yices_create_context(smt_logic_t logic,context_arch_t arch,context_mode_t mode,bool iflag,bool qflag)8243 context_t *yices_create_context(smt_logic_t logic, context_arch_t arch, context_mode_t mode, bool iflag, bool qflag) {
8244   MT_PROTECT(context_t *, __yices_globals.lock, _o_yices_create_context(logic, arch, mode, iflag, qflag));
8245 }
8246 
8247 
8248 /*
8249  * Allocate and initialize and new context
8250  * - the configuration is defined by config.
8251  * - if config is NULL, the default is used.
8252  * - otherwise, if the configuration is not supported, the function returns NULL.
8253  */
yices_new_context(const ctx_config_t * config)8254 EXPORTED context_t *yices_new_context(const ctx_config_t *config) {
8255   MT_PROTECT(context_t *, __yices_globals.lock, _o_yices_new_context(config));
8256 }
_o_yices_new_context(const ctx_config_t * config)8257 context_t *_o_yices_new_context(const ctx_config_t *config) {
8258   smt_logic_t logic;
8259   context_arch_t arch;
8260   context_mode_t mode;
8261   bool iflag;
8262   bool qflag;
8263   int32_t k;
8264 
8265   if (config == NULL) {
8266     // Default configuration: all solvers, mode = push/pop
8267     logic = SMT_UNKNOWN;
8268     arch = CTX_ARCH_EGFUNSPLXBV;
8269     mode = CTX_MODE_PUSHPOP;
8270     iflag = true;
8271     qflag = false;
8272   } else {
8273     // read the config
8274     k = decode_config(config, &logic, &arch, &mode, &iflag, &qflag);
8275     if (k < 0) {
8276       // invalid configuration
8277       set_error_code(CTX_INVALID_CONFIG);
8278       return NULL;
8279     }
8280   }
8281 
8282   return _o_yices_create_context(logic, arch, mode, iflag, qflag);
8283 }
8284 
8285 
8286 /*
8287  * Delete ctx
8288  */
yices_free_context(context_t * ctx)8289 EXPORTED void yices_free_context(context_t *ctx) {
8290   delete_context(ctx);
8291   free_context(ctx);
8292 }
8293 
8294 
8295 /*
8296  * Get status: return the context's status flag
8297  * - return one of the codes defined in yices_types.h
8298  */
yices_context_status(context_t * ctx)8299 EXPORTED smt_status_t yices_context_status(context_t *ctx) {
8300   return context_status(ctx);
8301 }
8302 
8303 
8304 /*
8305  * Reset: remove all assertions and restore ctx's status to IDLE
8306  */
yices_reset_context(context_t * ctx)8307 EXPORTED void yices_reset_context(context_t *ctx) {
8308   reset_context(ctx);
8309 }
8310 
8311 
8312 /*
8313  * Push: mark a backtrack point
8314  * - return 0 if this operation is supported by the context
8315  *         -1 otherwise
8316  *
8317  * Error report:
8318  * - if the context is not configured to support push/pop
8319  *   code = CTX_OPERATION_NOT_SUPPORTED
8320  * - if the context status is UNSAT or SEARCHING or INTERRUPTED
8321  *   code = CTX_INVALID_OPERATION
8322  */
yices_push(context_t * ctx)8323 EXPORTED int32_t yices_push(context_t *ctx) {
8324   if (! context_supports_pushpop(ctx)) {
8325     set_error_code(CTX_OPERATION_NOT_SUPPORTED);
8326     return -1;
8327   }
8328 
8329   switch (context_status(ctx)) {
8330   case STATUS_UNKNOWN:
8331   case STATUS_SAT:
8332     context_clear(ctx);
8333     break;
8334 
8335   case STATUS_IDLE:
8336     break;
8337 
8338   case STATUS_UNSAT:
8339     // try to remove assumptions
8340     context_clear_unsat(ctx);
8341     if (context_status(ctx) == STATUS_IDLE) {
8342       break;
8343     }
8344     assert(context_status(ctx) == STATUS_UNSAT);
8345     // fall through
8346   case STATUS_INTERRUPTED:
8347   case STATUS_SEARCHING:
8348     set_error_code(CTX_INVALID_OPERATION);
8349     return -1;
8350 
8351   case STATUS_ERROR:
8352   default:
8353     set_error_code(INTERNAL_EXCEPTION);
8354     return -1;
8355   }
8356 
8357   assert(context_status(ctx) == STATUS_IDLE);
8358   context_push(ctx);
8359 
8360   return 0;
8361 }
8362 
8363 
8364 
8365 /*
8366  * Pop: backtrack to the previous backtrack point (i.e., the matching
8367  * call to yices_push).
8368  * - return 0 if the operation succeeds, -1 otherwise.
8369  *
8370  * Error report:
8371  * - if the context is not configured to support push/pop
8372  *   code = CTX_OPERATION_NOT_SUPPORTED
8373  * - if there's no matching push (i.e., the context stack is empty)
8374  *   or if the context's status is SEARCHING or INTERRUPTED
8375  *   code = CTX_INVALID_OPERATION
8376  */
yices_pop(context_t * ctx)8377 EXPORTED int32_t yices_pop(context_t *ctx) {
8378   if (! context_supports_pushpop(ctx)) {
8379     set_error_code(CTX_OPERATION_NOT_SUPPORTED);
8380     return -1;
8381   }
8382 
8383   if (context_base_level(ctx) == 0) {
8384     set_error_code(CTX_INVALID_OPERATION);
8385     return -1;
8386   }
8387 
8388   switch (context_status(ctx)) {
8389   case STATUS_UNKNOWN:
8390   case STATUS_SAT:
8391   case STATUS_INTERRUPTED:
8392     context_clear(ctx);
8393     break;
8394 
8395   case STATUS_IDLE:
8396     break;
8397 
8398   case STATUS_UNSAT:
8399     context_clear_unsat(ctx);
8400     break;
8401 
8402   case STATUS_SEARCHING:
8403     set_error_code(CTX_INVALID_OPERATION);
8404     return -1;
8405 
8406   case STATUS_ERROR:
8407   default:
8408     set_error_code(INTERNAL_EXCEPTION);
8409     return -1;
8410   }
8411 
8412   assert(context_status(ctx) == STATUS_IDLE ||
8413 	 context_status(ctx) == STATUS_UNSAT);
8414   context_pop(ctx);
8415 
8416   return 0;
8417 }
8418 
8419 
8420 
8421 /*
8422  * Convert an error code reported by assert_formula
8423  * into the corresponding yices_error value.
8424  */
8425 static const error_code_t intern_code2error[NUM_INTERNALIZATION_ERRORS] = {
8426   NO_ERROR,                  // CTX_NO_ERROR
8427   INTERNAL_EXCEPTION,        // INTERNAL_ERROR
8428   INTERNAL_EXCEPTION,        // TYPE_ERROR. Should not happen if the assertions are type correct
8429   CTX_FREE_VAR_IN_FORMULA,
8430   CTX_LOGIC_NOT_SUPPORTED,
8431   CTX_UF_NOT_SUPPORTED,
8432   CTX_SCALAR_NOT_SUPPORTED,
8433   CTX_TUPLE_NOT_SUPPORTED,
8434   CTX_UTYPE_NOT_SUPPORTED,
8435   CTX_ARITH_NOT_SUPPORTED,
8436   CTX_BV_NOT_SUPPORTED,
8437   CTX_ARRAYS_NOT_SUPPORTED,
8438   CTX_QUANTIFIERS_NOT_SUPPORTED,
8439   CTX_LAMBDAS_NOT_SUPPORTED,
8440   CTX_FORMULA_NOT_IDL,
8441   CTX_FORMULA_NOT_RDL,
8442   CTX_NONLINEAR_ARITH_NOT_SUPPORTED,
8443   CTX_TOO_MANY_ARITH_VARS,
8444   CTX_TOO_MANY_ARITH_ATOMS,
8445   CTX_ARITH_SOLVER_EXCEPTION,
8446   CTX_BV_SOLVER_EXCEPTION,
8447   MCSAT_ERROR_UNSUPPORTED_THEORY
8448 };
8449 
convert_internalization_error(int32_t code)8450 static inline void convert_internalization_error(int32_t code) {
8451   assert(-NUM_INTERNALIZATION_ERRORS < code && code < 0);
8452   set_error_code(intern_code2error[-code]);
8453 }
8454 
8455 
8456 /*
8457  * Exports the previous function for front-end tools
8458  */
yices_internalization_error(int32_t code)8459 void yices_internalization_error(int32_t code) {
8460   convert_internalization_error(code);
8461 }
8462 
8463 
8464 /*
8465  * Assert formula t in ctx
8466  * - ctx status must be IDLE or UNSAT or SAT or UNKNOWN
8467  * - t must be a boolean term
8468  *
8469  * If ctx's status is UNSAT, nothing is done.
8470  *
8471  * If ctx's status is IDLE, SAT, or UNKNOWN, then the formula is
8472  * simplified and asserted in the context. The context status is
8473  * changed to UNSAT if the formula is simplified to 'false' or
8474  * to IDLE if it does not simplify to false.
8475  *
8476  * This returns 0 if there's no error or -1 if there's an error.
8477  *
8478  * Error report:
8479  * if t is invalid
8480  *   code = INVALID_TERM
8481  *   term1 = t
8482  * if t is not boolean
8483  *   code = TYPE_MISMATCH
8484  *   term1 = t
8485  *   type1 = bool (expected type)
8486  * if ctx's status is not IDLE or UNSAT or SAT or UNKNOWN
8487  *   code = CTX_INVALID_OPERATION
8488  * if ctx's status is neither IDLE nor UNSAT, and the context is
8489  * not configured for multiple checks
8490  *   code = CTX_OPERATION_NOT_SUPPORTED
8491  *
8492  * Other error codes are defined in yices_types.h to report that t is
8493  * outside the logic supported by ctx.
8494  */
_o_yices_assert_formula_checks(term_t t)8495 static inline bool _o_yices_assert_formula_checks(term_t t) {
8496   return check_good_term(__yices_globals.manager, t) && check_boolean_term(__yices_globals.manager, t);
8497 }
8498 
yices_assert_formula_checks(term_t t)8499 static inline bool yices_assert_formula_checks(term_t t) {
8500   MT_PROTECT(bool,  __yices_globals.lock, _o_yices_assert_formula_checks(t));
8501 }
8502 
yices_assert_formula(context_t * ctx,term_t t)8503 EXPORTED int32_t yices_assert_formula(context_t *ctx, term_t t) {
8504   int32_t code;
8505 
8506   if (! yices_assert_formula_checks(t)) {
8507     return -1;
8508   }
8509 
8510   switch (context_status(ctx)) {
8511   case STATUS_UNKNOWN:
8512   case STATUS_SAT:
8513     if (! context_supports_multichecks(ctx)) {
8514       set_error_code(CTX_OPERATION_NOT_SUPPORTED);
8515       return -1;
8516     }
8517     context_clear(ctx);
8518     break;
8519 
8520   case STATUS_IDLE:
8521     break;
8522 
8523   case STATUS_UNSAT:
8524     // try to remove assumptions
8525     context_clear_unsat(ctx);
8526     if (context_status(ctx) == STATUS_UNSAT) {
8527       // nothing to do
8528       return 0;
8529     }
8530     break;
8531 
8532   case STATUS_SEARCHING:
8533   case STATUS_INTERRUPTED:
8534     set_error_code(CTX_INVALID_OPERATION);
8535     return -1;
8536 
8537   case STATUS_ERROR:
8538   default:
8539     set_error_code(INTERNAL_EXCEPTION);
8540     return -1;
8541   }
8542 
8543   assert(context_status(ctx) == STATUS_IDLE);
8544 
8545   code = assert_formula(ctx, t);
8546   if (code < 0) {
8547     // error during internalization
8548     convert_internalization_error(code);
8549     return -1;
8550   }
8551   assert(code == TRIVIALLY_UNSAT || code == CTX_NO_ERROR);
8552 
8553   return 0;
8554 }
8555 
8556 
8557 
8558 
8559 
8560 
8561 /*
8562  * Same thing for an array of n formulas t[0 ... n-1]
8563  */
8564 
_o_yices_assert_formulas_checks(uint32_t n,const term_t t[])8565 static inline bool _o_yices_assert_formulas_checks(uint32_t n, const term_t t[]) {
8566   return check_good_terms(__yices_globals.manager, n, t) && check_boolean_args(__yices_globals.manager, n, t);
8567 }
8568 
yices_assert_formulas_checks(uint32_t n,const term_t t[])8569 static inline bool yices_assert_formulas_checks(uint32_t n, const term_t t[]) {
8570   MT_PROTECT(bool,  __yices_globals.lock, _o_yices_assert_formulas_checks(n, t));
8571 }
8572 
yices_assert_formulas(context_t * ctx,uint32_t n,const term_t t[])8573 EXPORTED int32_t yices_assert_formulas(context_t *ctx, uint32_t n, const term_t t[]) {
8574   int32_t code;
8575 
8576   if (! yices_assert_formulas_checks(n, t)) {
8577     return -1;
8578   }
8579 
8580   switch (context_status(ctx)) {
8581   case STATUS_UNKNOWN:
8582   case STATUS_SAT:
8583     if (! context_supports_multichecks(ctx)) {
8584       set_error_code(CTX_OPERATION_NOT_SUPPORTED);
8585       return -1;
8586     }
8587     context_clear(ctx);
8588     break;
8589 
8590   case STATUS_IDLE:
8591     break;
8592 
8593   case STATUS_UNSAT:
8594     // try to remove assumptions
8595     context_clear_unsat(ctx);
8596     if (context_status(ctx) == STATUS_UNSAT) {
8597       // nothing to do
8598       return 0;
8599     }
8600     break;
8601 
8602   case STATUS_SEARCHING:
8603   case STATUS_INTERRUPTED:
8604     set_error_code(CTX_INVALID_OPERATION);
8605     return -1;
8606 
8607   case STATUS_ERROR:
8608   default:
8609     set_error_code(INTERNAL_EXCEPTION);
8610     return -1;
8611   }
8612 
8613   assert(context_status(ctx) == STATUS_IDLE);
8614 
8615   code = assert_formulas(ctx, n, t);
8616   if (code < 0) {
8617     // error during internalization
8618     convert_internalization_error(code);
8619     return -1;
8620   }
8621   assert(code == TRIVIALLY_UNSAT || code == CTX_NO_ERROR);
8622 
8623   return 0;
8624 }
8625 
8626 
8627 
8628 /*
8629  * Add a blocking clause: this is intended to support all-sat and variants.
8630  * - if ctx's status is SAT or UNKNOWN, then a new clause is added to ctx
8631  *   to remove the current truth assignment from the search space.
8632  *   The status is then updated to IDLE (if the new clause is not empty) or
8633  *   to UNSAT (if the new clause is the empty clause).
8634  *
8635  * Return code: 0 if there's no error, -1 if there's an error.
8636  *
8637  * Error report:
8638  * if ctx's status is different from SAT or UNKNOWN
8639  *    code = CTX_INVALID_OPERATION
8640  * if ctx is not configured to support multiple checks
8641  *    code = CTX_OPERATION_NOT_SUPPORTED
8642  */
yices_assert_blocking_clause(context_t * ctx)8643 EXPORTED int32_t yices_assert_blocking_clause(context_t *ctx) {
8644   switch (context_status(ctx)) {
8645   case STATUS_UNKNOWN:
8646   case STATUS_SAT:
8647     if (context_supports_multichecks(ctx)) {
8648       assert_blocking_clause(ctx);
8649       return 0;
8650     } else {
8651       set_error_code(CTX_OPERATION_NOT_SUPPORTED);
8652       return -1;
8653     }
8654 
8655   case STATUS_UNSAT:
8656   case STATUS_IDLE:
8657   case STATUS_SEARCHING:
8658   case STATUS_INTERRUPTED:
8659     set_error_code(CTX_INVALID_OPERATION);
8660     return -1;
8661 
8662   case STATUS_ERROR:
8663   default:
8664     set_error_code(INTERNAL_EXCEPTION);
8665     return -1;
8666   }
8667 }
8668 
8669 
8670 
8671 /*
8672  * Set default search parameters based on architecture, logic, and mode
8673  * - the parameter settings are based on SMT-LIB2 benchmarks
8674  */
yices_set_default_params(param_t * params,smt_logic_t logic,context_arch_t arch,context_mode_t mode)8675 void yices_set_default_params(param_t *params, smt_logic_t logic, context_arch_t arch, context_mode_t mode) {
8676   init_params_to_defaults(params);
8677   switch (arch) {
8678   case CTX_ARCH_EG:
8679     // QF_UF options: --var-elim --cache-tclauses --learn-eq --dyn-bool-ack
8680     params->use_bool_dyn_ack = true;
8681     params->use_dyn_ack = true;
8682     //    params->max_ackermann = 100;
8683     params->cache_tclauses = true;
8684     params->tclause_size = 12;
8685     break;
8686 
8687   case CTX_ARCH_SPLX:
8688     // options: --flatten --theory-branching --cache-tclauses --arith-elim --var-elim
8689     params->branching = BRANCHING_THEORY;
8690     params->cache_tclauses = true;
8691     params->tclause_size = 8;
8692     if (logic == QF_LIA || logic == QF_LIRA) {
8693       params->use_simplex_prop = true;
8694       params->tclause_size = 20;
8695     }
8696     break;
8697 
8698   case CTX_ARCH_BV:
8699 #if 0
8700     // QF_BV options: --var-elim --fast-restarts --randomness=0 --bvarith-elim
8701     params->fast_restart = true;
8702     params->c_factor = 1.05;
8703     params->d_factor = 1.05;
8704     params->randomness = 0.0;
8705 #endif
8706     // HACK: try Luby restart, period = 10
8707     params->fast_restart = true;
8708     params->c_factor = 0.0;
8709     params->c_threshold = 10;
8710     params->randomness = 0.0;
8711     break;
8712 
8713   case CTX_ARCH_EGSPLX:       // egraph+simplex
8714   case CTX_ARCH_EGFUNSPLX:    // egraph+fun+simplex
8715     params->use_dyn_ack = true;
8716     params->use_bool_dyn_ack = true;
8717     params->use_simplex_prop = true;
8718     params->adjust_simplex_model = true;
8719     params->cache_tclauses = true;
8720     params->tclause_size = 8;
8721     params->use_optimistic_fcheck = true;
8722     if (logic == QF_UFLIA || logic == QF_UFLIRA || logic == QF_AUFLIA || logic == QF_ALIA || logic == QF_UFIDL) {
8723       params->branching = BRANCHING_NEGATIVE;
8724       params->max_interface_eqs = 15;
8725     } else {
8726       params->branching = BRANCHING_THEORY;
8727       params->max_interface_eqs = 30;
8728     }
8729 
8730     /*
8731      * For QF_UFLIA: optimistic_fcheck works better on the incremental benchmarks
8732      * but it's worse on the non-incremental benchmarks.
8733      */
8734     if ((logic == QF_UFLIA || logic == QF_UFLIRA) && mode == CTX_MODE_ONECHECK) {
8735       params->use_optimistic_fcheck = false;
8736     }
8737     break;
8738 
8739   case CTX_ARCH_EGBV:         // egraph+bitvector solver
8740   case CTX_ARCH_EGFUNBV:      // egraph+fun+bitvector
8741     // QF_BV options: --var-elim --fast-restarts --randomness=0 --bvarith-elim
8742 #if 1
8743     params->fast_restart = true;
8744     params->c_factor = 1.05;
8745     params->d_factor = 1.05;
8746 #else
8747     // HACK: try Luby restart, period = 10
8748     // This didn't work.
8749     params->fast_restart = true;
8750     params->c_factor = 0.0;
8751     params->c_threshold = 10;
8752 #endif
8753     params->randomness = 0.0;
8754     params->max_interface_eqs = 15;
8755     if (logic == QF_UFBV) {
8756       // randomness helps for the SMT benchmarks
8757       params->randomness = 0.02;
8758     }
8759     break;
8760 
8761   case CTX_ARCH_IFW:
8762   case CTX_ARCH_RFW:
8763     params->cache_tclauses = true;
8764     params->tclause_size = 20;
8765     params->fast_restart = true;
8766     params->c_factor = 1.1;
8767     params->d_factor = 1.1;
8768     break;
8769 
8770   case CTX_ARCH_EGFUNSPLXBV:
8771     // egraph+bitvector+simplex+fun solver
8772     // this is the default if no logic is specified
8773     params->use_dyn_ack = true;
8774     params->use_bool_dyn_ack = true;
8775     params->use_optimistic_fcheck = true;
8776     params->use_simplex_prop = true;
8777     params->adjust_simplex_model = true;
8778     params->cache_tclauses = true;
8779     params->tclause_size = 8;
8780     params->max_interface_eqs = 15;
8781     break;
8782 
8783   case CTX_ARCH_EGFUN:
8784   case CTX_ARCH_AUTO_IDL:
8785   case CTX_ARCH_AUTO_RDL:
8786   default:
8787     // nothing required
8788     break;
8789   }
8790 
8791 }
8792 
8793 /*
8794  * Set default search parameters for ctx (based on architecture and theories)
8795  * - this is based on benchmarking on the SMT-LIB 1.2 benchmarks (cf. yices_smtcomp.c)
8796  */
yices_default_params_for_context(const context_t * ctx,param_t * params)8797 EXPORTED void yices_default_params_for_context(const context_t *ctx, param_t *params) {
8798   yices_set_default_params(params, ctx->logic, ctx->arch, ctx->mode);
8799 }
8800 
8801 
8802 
8803 /*
8804  * Check satisfiability: check whether the assertions stored in ctx
8805  * are satisfiable.
8806  * - params is an optional structure that stores heuristic parameters.
8807  * - if params is NULL, default parameter settings are used.
8808  *
8809  * It's better to keep params=NULL unless you encounter performance
8810  * problems.  Then you may want to play with the heuristics to see if
8811  * performance improves.
8812  *
8813  * The behavior and returned value depend on ctx's current status:
8814  *
8815  * 1) If ctx's status is SAT, UNSAT, or UNKNOWN, the function
8816  *    does nothing and just return the status.
8817  *
8818  * 2) If ctx's status is IDLE, then the solver searches for a
8819  *    satisfying assignment. If param != NULL, the search parameters
8820  *    defined by params are used.
8821  *
8822  *    The function returns one of the following codes:
8823  *    - SAT: the context is satisfiable
8824  *    - UNSAT: the context is not satisfiable
8825  *    - UNKNOWN: satisfiability can't be proved or disproved
8826  *    - INTERRUPTED: the search was interrupted
8827  *
8828  *    The returned status is also stored as the new ctx's status flag.
8829  *
8830  * 3) Otherwise, the function does nothing and returns 'STATUS_ERROR',
8831  *    it also sets the yices error report (code = CTX_INVALID_OPERATION).
8832  */
yices_check_context(context_t * ctx,const param_t * params)8833 EXPORTED smt_status_t yices_check_context(context_t *ctx, const param_t *params) {
8834   param_t default_params;
8835   smt_status_t stat;
8836 
8837   stat = context_status(ctx);
8838   switch (stat) {
8839   case STATUS_UNKNOWN:
8840   case STATUS_SAT:
8841     break;
8842 
8843   case STATUS_UNSAT:
8844     // remove assumptions if any
8845     context_clear_unsat(ctx);
8846     if (context_status(ctx) == STATUS_UNSAT) {
8847       // no assumptions removed: still unsat
8848       break;
8849     }
8850     assert(context_status(ctx) == STATUS_IDLE);
8851 
8852     // fall through intended
8853   case STATUS_IDLE:
8854     if (params == NULL) {
8855       yices_default_params_for_context(ctx, &default_params);
8856       params = &default_params;
8857     }
8858     stat = check_context(ctx, params);
8859     if (stat == STATUS_INTERRUPTED && context_supports_cleaninterrupt(ctx)) {
8860       context_cleanup(ctx);
8861     }
8862     break;
8863 
8864   case STATUS_SEARCHING:
8865   case STATUS_INTERRUPTED:
8866     set_error_code(CTX_INVALID_OPERATION);
8867     stat = STATUS_ERROR;
8868     break;
8869 
8870   case STATUS_ERROR:
8871   default:
8872     set_error_code(INTERNAL_EXCEPTION);
8873     stat = STATUS_ERROR;
8874     break;
8875   }
8876 
8877   return stat;
8878 }
8879 
8880 //IAM: experiment to see if we can keep some concurrency.
_o_unsat_core_check_assumptions(uint32_t n,const term_t a[])8881 static bool _o_unsat_core_check_assumptions(uint32_t n, const term_t a[]) {
8882   if (! check_good_terms(__yices_globals.manager, n, a) ||
8883       ! check_boolean_args(__yices_globals.manager, n, a)) {
8884     return false; // Bad assumptions
8885   }
8886   return true;
8887 }
8888 
unsat_core_check_assumptions(uint32_t n,const term_t a[])8889 static bool unsat_core_check_assumptions(uint32_t n, const term_t a[]) {
8890   MT_PROTECT(bool,  __yices_globals.lock, _o_unsat_core_check_assumptions(n, a));
8891 }
8892 
8893 /*
8894  * Check context with assumptions
8895  * - n = number of assumptions
8896  * - a[0] ... a[n-1] = n assumptions. All of them must be Boolean terms.
8897  */
yices_check_context_with_assumptions(context_t * ctx,const param_t * params,uint32_t n,const term_t a[])8898 EXPORTED smt_status_t yices_check_context_with_assumptions(context_t *ctx, const param_t *params, uint32_t n, const term_t a[]) {
8899   param_t default_params;
8900   ivector_t assumptions;
8901   smt_status_t stat;
8902   uint32_t i;
8903   literal_t l;
8904 
8905   if (!unsat_core_check_assumptions(n, a)) {
8906     return STATUS_ERROR; // Bad assumptions
8907   }
8908 
8909   // cleanup
8910   switch (context_status(ctx)) {
8911   case STATUS_UNKNOWN:
8912   case STATUS_SAT:
8913     if (! context_supports_multichecks(ctx)) {
8914       set_error_code(CTX_OPERATION_NOT_SUPPORTED);
8915       return STATUS_ERROR;
8916     }
8917     context_clear(ctx);
8918     break;
8919 
8920   case STATUS_IDLE:
8921     break;
8922 
8923   case STATUS_UNSAT:
8924     if (! context_supports_multichecks(ctx)) {
8925       set_error_code(CTX_OPERATION_NOT_SUPPORTED);
8926       return STATUS_ERROR;
8927     }
8928     // try to remove the previous assumptions if any
8929     context_clear_unsat(ctx);
8930     if (context_status(ctx) == STATUS_UNSAT) {
8931       return STATUS_UNSAT;
8932     }
8933     break;
8934 
8935   case STATUS_SEARCHING:
8936   case STATUS_INTERRUPTED:
8937     set_error_code(CTX_INVALID_OPERATION);
8938     return STATUS_ERROR;
8939 
8940   case STATUS_ERROR:
8941   default:
8942     set_error_code(INTERNAL_EXCEPTION);
8943     return STATUS_ERROR;
8944   }
8945 
8946   assert(context_status(ctx) == STATUS_IDLE);
8947 
8948   yices_obtain_mutex();
8949 
8950   // convert the assumptions to n literals
8951   init_ivector(&assumptions, n);
8952   for (i=0; i<n; i++) {
8953     l = context_add_assumption(ctx, a[i]);
8954     if (l < 0) {
8955       // error when converting a[i] to a literal
8956       convert_internalization_error(l);
8957       stat = STATUS_ERROR;
8958       yices_release_mutex();
8959       goto cleanup;
8960     }
8961     ivector_push(&assumptions, l);
8962   }
8963   assert(assumptions.size == n);
8964 
8965   yices_release_mutex();
8966 
8967   // set parameters
8968   if (params == NULL) {
8969     yices_default_params_for_context(ctx, &default_params);
8970     params = &default_params;
8971   }
8972 
8973   // call check
8974   stat = check_context_with_assumptions(ctx, params, n, assumptions.data);
8975   if (stat == STATUS_INTERRUPTED && context_supports_cleaninterrupt(ctx)) {
8976     context_cleanup(ctx);
8977   }
8978 
8979  cleanup:
8980   delete_ivector(&assumptions);
8981 
8982   return stat;
8983 }
8984 
8985 
8986 /*
8987  * Interrupt the search:
8988  * - this can be called from a signal handler to stop the search,
8989  *   after a call to yices_check_context to interrupt the solver.
8990  *
8991  * If ctx's status is SEARCHING, then the current search is
8992  * interrupted and ctx's status flag is updated to
8993  * INTERRUPTED. Otherwise, the function does nothing.
8994  */
yices_stop_search(context_t * ctx)8995 EXPORTED void yices_stop_search(context_t *ctx) {
8996   if (context_status(ctx) == STATUS_SEARCHING) {
8997     context_stop_search(ctx);
8998   }
8999 }
9000 
9001 
9002 
9003 /****************
9004  *  UNSAT CORE  *
9005  ***************/
9006 
9007 /*
9008  * Construct an unsat core: store the result in vector *v
9009  * - returns 0 if this works
9010  * - returns -1 if there's an error
9011  */
yices_get_unsat_core(context_t * ctx,term_vector_t * v)9012 EXPORTED int32_t yices_get_unsat_core(context_t *ctx, term_vector_t *v) {
9013   if (context_status(ctx) != STATUS_UNSAT) {
9014     set_error_code(CTX_INVALID_OPERATION);
9015     return -1;
9016   }
9017 
9018   yices_reset_term_vector(v);
9019   context_build_unsat_core(ctx, (ivector_t *) v);
9020   return 0;
9021 }
9022 
9023 
9024 /************
9025  *  MODELS  *
9026  ***********/
9027 
9028 /*
9029  * Build a model from ctx
9030  * - keep_subst indicates whether the model should include
9031  *   the eliminated variables:
9032  *   keep_subst = 0 means don't keep substitutions,
9033  *   keep_subst != 0 means keep them
9034  * - ctx status must be SAT or UNKNOWN
9035  *
9036  * The function returns NULL if the status isn't SAT or UNKNOWN and
9037  * sets an error report.
9038  *
9039  */
yices_get_model(context_t * ctx,int32_t keep_subst)9040 EXPORTED model_t *yices_get_model(context_t *ctx, int32_t keep_subst) {
9041   MT_PROTECT(model_t *,  __yices_globals.lock, _o_yices_get_model(ctx, keep_subst));
9042 }
9043 
_o_yices_get_model(context_t * ctx,int32_t keep_subst)9044 model_t *_o_yices_get_model(context_t *ctx, int32_t keep_subst) {
9045   model_t *mdl;
9046 
9047   assert(ctx != NULL);
9048 
9049   switch (context_status(ctx)) {
9050   case STATUS_UNKNOWN:
9051   case STATUS_SAT:
9052     mdl = alloc_model();
9053     init_model(mdl, __yices_globals.terms, (keep_subst != 0));
9054     context_build_model(mdl, ctx);
9055     break;
9056 
9057   default:
9058     set_error_code(CTX_INVALID_OPERATION);
9059     mdl = NULL;
9060     break;
9061   }
9062 
9063   return mdl;
9064 }
9065 
9066 
9067 /*
9068  * Return an empty model
9069  */
yices_new_model(bool keep_subst)9070 model_t *yices_new_model(bool keep_subst) {
9071   model_t *mdl;
9072 
9073   mdl = alloc_model();
9074   init_model(mdl, __yices_globals.terms, keep_subst);
9075 
9076   return mdl;
9077 }
9078 
9079 
9080 /*
9081  * Delete mdl
9082  */
yices_free_model(model_t * mdl)9083 EXPORTED void yices_free_model(model_t *mdl) {
9084   delete_model(mdl);
9085   free_model(mdl);
9086 }
9087 
9088 
9089 /*
9090  * Print model mdl on FILE f
9091  * - f must be open/writable
9092  */
yices_print_model(FILE * f,model_t * mdl)9093 EXPORTED void yices_print_model(FILE *f, model_t *mdl) {
9094   MT_PROTECT_VOID(__yices_globals.lock, _o_yices_print_model(f, mdl));
9095 }
9096 
_o_yices_print_model(FILE * f,model_t * mdl)9097 void _o_yices_print_model(FILE *f, model_t *mdl) {
9098   model_print_full(f, mdl);
9099 }
9100 
yices_print_model_fd(int fd,model_t * mdl)9101 EXPORTED int32_t yices_print_model_fd(int fd, model_t *mdl) {
9102   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_print_model_fd(fd, mdl));
9103 }
9104 
_o_yices_print_model_fd(int fd,model_t * mdl)9105 int32_t _o_yices_print_model_fd(int fd, model_t *mdl) {
9106   FILE *tmp_fp;
9107 
9108   tmp_fp = fd_2_tmp_fp(fd);
9109   if (tmp_fp == NULL) {
9110     file_output_error();
9111     return -1;
9112   }
9113   model_print_full(tmp_fp, mdl);
9114   fclose(tmp_fp);
9115 
9116   return 0;
9117 }
9118 
9119 
9120 /*
9121  * Pretty print mdl
9122  * - f = output file to use
9123  * - width, height, offset = print area
9124  */
yices_pp_model(FILE * f,model_t * mdl,uint32_t width,uint32_t height,uint32_t offset)9125 EXPORTED int32_t yices_pp_model(FILE *f, model_t *mdl, uint32_t width, uint32_t height, uint32_t offset) {
9126   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_pp_model(f, mdl, width, height, offset));
9127 }
9128 
_o_yices_pp_model(FILE * f,model_t * mdl,uint32_t width,uint32_t height,uint32_t offset)9129 int32_t _o_yices_pp_model(FILE *f, model_t *mdl, uint32_t width, uint32_t height, uint32_t offset) {
9130   yices_pp_t printer;
9131   pp_area_t area;
9132   int32_t code;
9133 
9134   if (width < 4) width = 4;
9135   if (height == 0) height = 1;
9136 
9137   area.width = width;
9138   area.height = height;
9139   area.offset = offset;
9140   area.stretch = false;
9141   area.truncate = true;
9142 
9143   init_default_yices_pp(&printer, f, &area);
9144   model_pp_full(&printer, mdl);
9145   flush_yices_pp(&printer);
9146 
9147   // check for error
9148   code = 0;
9149   if (yices_pp_print_failed(&printer)) {
9150     code = -1;
9151     errno = yices_pp_errno(&printer);
9152     file_output_error();
9153   }
9154   delete_yices_pp(&printer, false);
9155 
9156   return code;
9157 }
9158 
yices_pp_model_fd(int fd,model_t * mdl,uint32_t width,uint32_t height,uint32_t offset)9159 EXPORTED int32_t yices_pp_model_fd(int fd, model_t *mdl, uint32_t width, uint32_t height, uint32_t offset) {
9160   FILE *tmp_fp;
9161   int32_t retval;
9162 
9163   tmp_fp = fd_2_tmp_fp(fd);
9164   if (tmp_fp == NULL) {
9165     file_output_error();
9166     return -1;
9167   }
9168   retval = yices_pp_model(tmp_fp, mdl, width, height, offset);
9169   fclose(tmp_fp);
9170 
9171   return retval;
9172 }
9173 
9174 /*
9175  * Convert mdl to a string
9176  */
yices_model_to_string(model_t * mdl,uint32_t width,uint32_t height,uint32_t offset)9177 EXPORTED char *yices_model_to_string(model_t *mdl, uint32_t width, uint32_t height, uint32_t offset) {
9178   MT_PROTECT(char *,  __yices_globals.lock, _o_yices_model_to_string(mdl, width, height, offset));
9179 }
9180 
_o_yices_model_to_string(model_t * mdl,uint32_t width,uint32_t height,uint32_t offset)9181 char *_o_yices_model_to_string(model_t *mdl, uint32_t width, uint32_t height, uint32_t offset) {
9182   yices_pp_t printer;
9183   pp_area_t area;
9184   char *str;
9185   uint32_t len;
9186 
9187   if (width < 4) width = 4;
9188   if (height == 0) height = 1;
9189 
9190   area.width = width;
9191   area.height = height;
9192   area.offset = offset;
9193   area.stretch = false;
9194   area.truncate = true;
9195 
9196   init_default_yices_pp(&printer, NULL, &area);
9197   model_pp_full(&printer, mdl);
9198   flush_yices_pp(&printer);
9199 
9200   str = yices_pp_get_string(&printer, &len);
9201   delete_yices_pp(&printer, false);
9202 
9203   return str;
9204 }
9205 
9206 
9207 /*
9208  * Print the values of n terms in  a model
9209  * - f = output file
9210  * - mdl = model
9211  * - n = number of terms
9212  * - a - array of n terms
9213  *
9214  * The function returns -1 on error, 0 otherwise.
9215  *
9216  * Error report:
9217  * if a[i] is not a valid term:
9218  *   code = INVALID_TERM
9219  *   term1 = a[i]
9220  */
yices_print_term_values(FILE * f,model_t * mdl,uint32_t n,const term_t a[])9221 EXPORTED int32_t yices_print_term_values(FILE *f, model_t *mdl, uint32_t n, const term_t a[]) {
9222   MT_PROTECT(int32_t, __yices_globals.lock, _o_yices_print_term_values(f, mdl, n, a));
9223 }
9224 
_o_yices_print_term_values(FILE * f,model_t * mdl,uint32_t n,const term_t a[])9225 int32_t _o_yices_print_term_values(FILE *f, model_t *mdl, uint32_t n, const term_t a[]) {
9226   if (! check_good_terms(__yices_globals.manager, n, a)) {
9227     return -1;
9228   }
9229   model_print_eval_terms(f, mdl, a, n);
9230 
9231   return 0;
9232 }
9233 
9234 // Variant with a file descriptor
yices_print_term_values_fd(int fd,model_t * mdl,uint32_t n,const term_t a[])9235 EXPORTED int32_t yices_print_term_values_fd(int fd, model_t *mdl, uint32_t n, const term_t a[]) {
9236   FILE *tmp_fp;
9237   int32_t code;
9238 
9239   tmp_fp = fd_2_tmp_fp(fd);
9240   if (tmp_fp == NULL) {
9241     file_output_error();
9242     return -1;
9243   }
9244   code = yices_print_term_values(tmp_fp, mdl, n, a);
9245   fclose(tmp_fp);
9246 
9247   return code;
9248 }
9249 
9250 
9251 /*
9252  * Pretty print the values of n terms in  a model
9253  * - f = output file
9254  * - mdl = model
9255  * - n = number of terms
9256  * - a - array of n terms
9257  * - width, height, offset define the print area.
9258  *
9259  * This function is like yices_print_term_values except that is uses pretty printing.
9260  *
9261  * Return code: -1 on error, 0 otherwise
9262  *
9263  *
9264  * Error report:
9265  * if a[i] is not a valid term:
9266  *   code = INVALID_TERM
9267  *   term1 = a[i]
9268  * if writing to f fails,
9269  *   code = OUTPUT_ERROR
9270  *   in this case, errno, perror, etc. can be used for diagnostic.
9271  */
yices_pp_term_values(FILE * f,model_t * mdl,uint32_t n,const term_t a[],uint32_t width,uint32_t height,uint32_t offset)9272 EXPORTED int32_t yices_pp_term_values(FILE *f, model_t *mdl, uint32_t n, const term_t a[],
9273 				      uint32_t width, uint32_t height, uint32_t offset) {
9274   MT_PROTECT(int32_t, __yices_globals.lock, _o_yices_pp_term_values(f, mdl, n, a, width, height, offset));
9275 }
9276 
_o_yices_pp_term_values(FILE * f,model_t * mdl,uint32_t n,const term_t a[],uint32_t width,uint32_t height,uint32_t offset)9277 int32_t _o_yices_pp_term_values(FILE *f, model_t *mdl, uint32_t n, const term_t a[],
9278 				uint32_t width, uint32_t height, uint32_t offset) {
9279   yices_pp_t printer;
9280   pp_area_t area;
9281   int32_t code;
9282 
9283   if (! check_good_terms(__yices_globals.manager, n, a)) {
9284     return -1;
9285   }
9286 
9287   if (width < 4) width = 4;
9288   if (height == 0) height = 1;
9289 
9290   area.width = width;
9291   area.height = height;
9292   area.offset = offset;
9293   area.stretch = false;
9294   area.truncate = true;
9295 
9296   init_default_yices_pp(&printer, f, &area);
9297   model_pp_eval_terms(&printer, mdl, a, n);
9298   flush_yices_pp(&printer);
9299 
9300   // check for error
9301   code = 0;
9302   if (yices_pp_print_failed(&printer)) {
9303     code = -1;
9304     errno = yices_pp_errno(&printer);
9305     file_output_error();
9306   }
9307   delete_yices_pp(&printer, false);
9308 
9309   return code;
9310 }
9311 
9312 // Variant with a file descriptor
yices_pp_term_values_fd(int fd,model_t * mdl,uint32_t n,const term_t a[],uint32_t width,uint32_t height,uint32_t offset)9313 EXPORTED int32_t yices_pp_term_values_fd(int fd, model_t *mdl, uint32_t n, const term_t a[],
9314 					 uint32_t width, uint32_t height, uint32_t offset) {
9315   FILE *tmp_fp;
9316   int32_t code;
9317 
9318   tmp_fp = fd_2_tmp_fp(fd);
9319   if (tmp_fp == NULL) {
9320     file_output_error();
9321     return -1;
9322   }
9323   code = yices_pp_term_values(tmp_fp, mdl, n, a, width, height, offset);
9324   fclose(tmp_fp);
9325 
9326   return code;
9327 }
9328 
9329 
9330 
9331 
9332 /*
9333  * BUILD A MODEL FROM A MAP OF UNINTERPRETED TO CONSTANT TERMS
9334  */
9335 
9336 /*
9337  * Build a model from a term-to-term mapping:
9338  * - the mapping is defined by two arrays var[] and map[]
9339  * - every element of var must be an uninterpreted term
9340  *   every element of map must be a constant of primitive or tuple type
9341  *   map[i]'s type must be a subtype of var[i]
9342  * - there must not be duplicates in array var
9343  *
9344  * The function returns NULL and set up the error report if something
9345  * goes wrong. It allocates and create a new model otherwise. This
9346  * model must be deleted when no longer used via yices_free_model.
9347  *
9348  * Error report:
9349  * - code = INVALID_TERM if var[i] or map[i] is not valid
9350  * - code = TYPE_MISMATCH if map[i] doesn't have a type compatible (subtype of)
9351  *          var[i]'s type
9352  * - code = MDL_UNINT_REQUIRED if var[i] is not an uninterpreted term
9353  * - code = MDL_CONSTANT_REQUIRED if map[i] is not a constant
9354  * - code = MDL_DUPLICATE_VAR if var contains duplicate elements
9355  * - code = MDL_FTYPE_NOT_ALLOWED if one of var[i] has a function type
9356  * - code = MDL_CONSTRUCTION_FAILED: something else went wrong
9357  */
yices_model_from_map(uint32_t n,const term_t var[],const term_t map[])9358 EXPORTED model_t *yices_model_from_map(uint32_t n, const term_t var[], const term_t map[]) {
9359   MT_PROTECT(model_t *,  __yices_globals.lock, _o_yices_model_from_map(n, var, map));
9360 }
9361 
_o_yices_model_from_map(uint32_t n,const term_t var[],const term_t map[])9362 model_t *_o_yices_model_from_map(uint32_t n, const term_t var[], const term_t map[]) {
9363   model_t *mdl;
9364 
9365   if (! check_good_model_map(__yices_globals.manager, n, var, map)) {
9366     return NULL;
9367   }
9368 
9369   mdl = yices_new_model(true);
9370   build_model_from_map(mdl, n, var, map);
9371   return mdl;
9372 }
9373 
9374 
9375 /*
9376  * Export the list of uninterpreted terms that have a value in mdl.
9377  * - the variables are stored in term_vector v
9378  */
yices_model_collect_defined_terms(model_t * mdl,term_vector_t * v)9379 EXPORTED void yices_model_collect_defined_terms(model_t *mdl, term_vector_t *v) {
9380   MT_PROTECT_VOID(__yices_globals.lock, model_get_relevant_vars(mdl, (ivector_t *) v));
9381 }
9382 
9383 
9384 
9385 /*
9386  * Collect the support of term t in mdl:
9387  * - the support is a set of uninterpreted returned in *v
9388  */
yices_model_term_support(model_t * mdl,term_t t,term_vector_t * v)9389 EXPORTED int32_t yices_model_term_support(model_t *mdl, term_t t, term_vector_t *v) {
9390   MT_PROTECT(int32_t, __yices_globals.lock, _o_yices_model_term_support(mdl, t, v));
9391 }
9392 
_o_yices_model_term_support(model_t * mdl,term_t t,term_vector_t * v)9393 int32_t _o_yices_model_term_support(model_t *mdl, term_t t, term_vector_t *v) {
9394   if (! check_good_term(__yices_globals.manager, t)) {
9395     return -1;
9396   }
9397   model_get_term_support(mdl, t, (ivector_t *) v);
9398   return 0;
9399 }
9400 
9401 
9402 /*
9403  * Collect the support of terms a[0 ... n-1] in mdl:
9404  * - the support is a set of uninterpreted returned in *v
9405  */
yices_model_term_array_support(model_t * mdl,uint32_t n,const term_t a[],term_vector_t * v)9406 EXPORTED int32_t yices_model_term_array_support(model_t *mdl, uint32_t n, const term_t a[], term_vector_t *v) {
9407   MT_PROTECT(int32_t, __yices_globals.lock, _o_yices_model_term_array_support(mdl, n, a, v));
9408 }
9409 
_o_yices_model_term_array_support(model_t * mdl,uint32_t n,const term_t a[],term_vector_t * v)9410 int32_t _o_yices_model_term_array_support(model_t *mdl, uint32_t n, const term_t a[], term_vector_t *v) {
9411   if (! check_good_terms(__yices_globals.manager, n, a)) {
9412     return -1;
9413   }
9414   model_get_terms_support(mdl, n, a, (ivector_t *) v);
9415   return 0;
9416 }
9417 
9418 
9419 
9420 
9421 /******************************
9422  *  CHECK FORMULAS/DELEGATES  *
9423  *****************************/
9424 
9425 /*
9426  * Evaluate all terms in a[0 ... n-1] in a default model.
9427  * Return true if all terms evaluate to true in the model.
9428  * Return false otherwise.
9429  *
9430  * If model != NULL and the result is true, the default model is
9431  * returned in model.
9432  */
trivially_true_assertions(const term_t * a,uint32_t n,model_t ** model)9433 bool trivially_true_assertions(const term_t *a, uint32_t n, model_t **model) {
9434   model_t *mdl;
9435   evaluator_t evaluator;
9436   uint32_t i;
9437   bool result;
9438 
9439   yices_obtain_mutex();
9440 
9441   result = true;
9442   mdl = yices_new_model(true);
9443   init_evaluator(&evaluator, mdl);
9444   for (i=0; i<n; i++) {
9445     if (!eval_to_true_in_model(&evaluator, a[i])) {
9446       result = false;
9447       break;
9448     }
9449   }
9450 
9451   if (result && model != NULL) {
9452     eval_record_useful_terms(&evaluator);
9453     delete_evaluator(&evaluator);
9454     *model = mdl;
9455   } else {
9456     delete_evaluator(&evaluator);
9457     yices_free_model(mdl);
9458   }
9459 
9460   yices_release_mutex();
9461 
9462   return result;
9463 }
9464 
9465 
9466 /*
9467  * Check whether one of the terms a[0 .. n-1] is false.
9468  */
trivially_false_assertions(const term_t * a,uint32_t n)9469 static bool trivially_false_assertions(const term_t *a, uint32_t n) {
9470   uint32_t i;
9471 
9472   for (i=0; i<n; i++) {
9473     if (a[i] == false_term) return true;
9474   }
9475   return false;
9476 }
9477 
9478 
9479 /*
9480  * Check whether the given delegate is supported
9481  * - return 0 if it's not supported.
9482  * - return 1 if delegate is NULL or it's the name of a supported delegate
9483  *
9484  * Which delegate is supported depends on how this version of Yices was compiled.
9485  */
yices_has_delegate(const char * delegate)9486 EXPORTED int32_t yices_has_delegate(const char *delegate) {
9487   bool unknown;
9488   return delegate == NULL || supported_delegate(delegate, &unknown);
9489 }
9490 
9491 
9492 /*
9493  * Same thing but also set an error code.
9494  */
check_delegate(const char * delegate)9495 static bool check_delegate(const char *delegate) {
9496   bool unknown;
9497 
9498   assert(delegate != NULL);
9499   if (supported_delegate(delegate, &unknown)) {
9500     return true;
9501   }
9502   if (unknown) {
9503     set_error_code(CTX_UNKNOWN_DELEGATE);
9504   } else {
9505     set_error_code(CTX_DELEGATE_NOT_AVAILABLE);
9506   }
9507   return false;
9508 }
9509 
9510 
9511 /*
9512  * Check satisfiability of n formulas f[0 ... n-1]
9513  * - f[0 ... n-1] are known to be boolean terms
9514  */
yices_do_check_formulas(const term_t f[],uint32_t n,const char * logic_name,model_t ** result,const char * delegate)9515 static smt_status_t yices_do_check_formulas(const term_t f[], uint32_t n, const char *logic_name, model_t **result, const char *delegate) {
9516   context_t context;
9517   param_t default_params;
9518   model_t *model;
9519   smt_logic_t logic;
9520   context_arch_t arch;
9521   bool iflag, qflag;
9522   int32_t code;
9523   smt_status_t status;
9524 
9525   // check the logic first
9526   if (logic_name == NULL) {
9527     logic = SMT_UNKNOWN;
9528     arch = CTX_ARCH_EGFUNSPLXBV;
9529     iflag = true;
9530     qflag = false;
9531   } else {
9532     logic = smt_logic_code(logic_name);
9533     if (logic == SMT_UNKNOWN) {
9534       set_error_code(CTX_UNKNOWN_LOGIC);
9535       return STATUS_ERROR;
9536     }
9537     if (! logic_is_supported(logic) ||
9538 	(! yices_has_mcsat() && logic_requires_mcsat(logic))) {
9539       set_error_code(CTX_LOGIC_NOT_SUPPORTED);
9540       return STATUS_ERROR;
9541     }
9542 
9543     arch = arch_for_logic(logic);
9544     iflag = iflag_for_logic(logic);
9545     qflag = qflag_for_logic(logic);
9546   }
9547 
9548   // validate the delegate if given
9549   if (logic == QF_BV && delegate != NULL && !check_delegate(delegate)) {
9550     return STATUS_ERROR;
9551   }
9552 
9553   // check for trivial unsat then trivial sat
9554   if (trivially_false_assertions(f, n)) {
9555     return STATUS_UNSAT;
9556   }
9557 
9558   if (trivially_true_assertions(f, n, result)) {
9559     return STATUS_SAT;
9560   }
9561 
9562   // initialize the context and assert the formulas
9563   yices_obtain_mutex();
9564   init_context(&context, __yices_globals.terms, logic, CTX_MODE_ONECHECK, arch, qflag);
9565   context_set_default_options(&context, logic, arch, iflag, qflag);
9566   code = assert_formulas(&context, n, f);
9567   yices_release_mutex();
9568 
9569   if (code < 0) {
9570     // error in assert_formulas
9571     convert_internalization_error(code);
9572     status = STATUS_ERROR;
9573     goto cleanup;
9574   }
9575 
9576   // check satisfiability
9577   if (logic == QF_BV && delegate != NULL) {
9578     status = check_with_delegate(&context, delegate, 0);
9579   } else {
9580     yices_default_params_for_context(&context, &default_params);
9581     status = check_context(&context, &default_params);
9582   }
9583 
9584   // get the model
9585   if (status == STATUS_SAT && result != NULL) {
9586     // yices_get_model takes the lock so we don't
9587     // need to do it ourselves.
9588     model = yices_get_model(&context, true);
9589     assert(model != NULL);
9590     *result = model;
9591   }
9592 
9593  cleanup:
9594   delete_context(&context);
9595   return status;
9596 }
9597 
9598 
9599 
9600 /*
9601  * Check whether a formula is satisfiable
9602  * - f = formula
9603  * - logic = SMT name for a logic (or NULL)
9604  * - model = resulting model (or NULL if no model is needed)
9605  * - delegate = external solver to use or NULL
9606  *
9607  * This function first check whether f is trivially sat or trivially unsat.
9608  * If not, it construct a context configured for the specified logic, then
9609  * assert f in this context and check whether the context is satisfiable.
9610  *
9611  * The return value is
9612  *   STATUS_SAT if f is satisfiable,
9613  *   STATUS_UNSAT if f is not satisifiable
9614  *   STATUS_ERROR if something goes wrong
9615  *
9616  * If the formula is satisfiable and model != NULL, then a model of f is returned in *model.
9617  * That model must be deleted when no-longer needed by calling yices_free_model.
9618  *
9619  * The logic must be either NULL or the name of an SMT logic supported by Yices.
9620  * If the logic is NULL, the function uses a default context configuration.
9621  * Ohterwise, the function uses a context specialized for the logic.
9622  *
9623  * The delegate is an optional argument used only when logic is "QF_BV".
9624  * If is ignored otherwise.   It must be the name of a third-party SAT solver
9625  * to use after bit-blasting. Currently, the delegate can be either "cadical",
9626  * "cryptominisat",  "y2sat", or NULL.
9627  * If delegate is NULL, the default SAT solver is used.
9628  *
9629  * Support for "cadical" and "cryptominisat" must be enabled at compilation
9630  * time. The "y2sat" solver is always available. The function will return STATUS_ERROR
9631  * and store an error code if the requested delegate is not available.
9632  *
9633  * Error codes:
9634  *
9635  * if f is invalid
9636  *   code = INVALID_TERM
9637  *   term1 = f
9638  *
9639  * if f is not Boolean
9640  *   code = TYPE_MISMATCH
9641  *   term1 = t
9642  *   type1 = bool
9643  *
9644  * if logic is not a known logic name
9645  *   code = CTX_UNKNOWN_LOGIC
9646  *
9647  * if the logic is known but not supported by Yices
9648  *   code = CTX_LOGIC_NOT_SUPPORTED
9649  *
9650  * if delegate is not one of "cadical", "cryptominisat", "y2sat"
9651  *   code = CTX_UNKNOWN_DELEGATE
9652  *
9653  * if delegate is "cadical" or "cryptominisat" but support for these SAT solvers
9654  * was not implemented at compile time,
9655  *   code = CTX_DELEGATE_NOT_AVAILABLE
9656  *
9657  * other error codes are possible if the formula is not in the specified logic (cf, yices_assert_formula)
9658  */
yices_check_formula(term_t f,const char * logic,model_t ** model,const char * delegate)9659 EXPORTED smt_status_t yices_check_formula(term_t f, const char *logic, model_t **model, const char *delegate) {
9660   if (! yices_assert_formula_checks(f)) {
9661     return STATUS_ERROR;
9662   }
9663   return yices_do_check_formulas(&f, 1, logic, model, delegate);
9664 }
9665 
9666 /*
9667  * Check whether n formulas are satisfiable.
9668  * - f = array of n Boolean terms
9669  * - n = number of elements in f
9670  *
9671  * This is similar to yices_check_formula except that it checks whether
9672  * the conjunction of f[0] ... f[n-1] is satisfiable.
9673  */
yices_check_formulas(const term_t f[],uint32_t n,const char * logic,model_t ** model,const char * delegate)9674 EXPORTED smt_status_t yices_check_formulas(const term_t f[], uint32_t n, const char *logic, model_t **model, const char *delegate) {
9675   if (! yices_assert_formulas_checks(n, f)) {
9676     return STATUS_ERROR;
9677   }
9678   return yices_do_check_formulas(f, n, logic, model, delegate);
9679 }
9680 
9681 
9682 /************************************
9683  *  BIT-BLAST AND EXPORT TO DIMACS  *
9684  ***********************************/
9685 
9686 /*
9687  * Bit-blast f[0 ... n-1]
9688  * - filename = DIMACS file name
9689  * - simplify_cnf = whether to simplify after CNF conversion (using y2sat)
9690  * - status = returned status if the formulas are SAT or UNSAT
9691  */
yices_do_export_to_dimacs(const term_t f[],uint32_t n,const char * filename,bool simplify_cnf,smt_status_t * status)9692 static int32_t yices_do_export_to_dimacs(const term_t f[], uint32_t n, const char *filename, bool simplify_cnf, smt_status_t *status) {
9693   context_t context;
9694   context_arch_t arch;
9695   bool iflag, qflag;
9696   int32_t code;
9697 
9698   if (trivially_false_assertions(f, n)) {
9699     *status = STATUS_UNSAT;
9700     return 0;
9701   }
9702 
9703   if (trivially_true_assertions(f, n, NULL)) {
9704     *status = STATUS_SAT;
9705     return 0;
9706   }
9707 
9708   arch = arch_for_logic(QF_BV);
9709   iflag = iflag_for_logic(QF_BV);
9710   qflag = qflag_for_logic(QF_BV);
9711 
9712   yices_obtain_mutex();
9713   init_context(&context, __yices_globals.terms, QF_BV, CTX_MODE_ONECHECK, arch, qflag);
9714   context_set_default_options(&context, QF_BV, arch, iflag, qflag);
9715   code = assert_formulas(&context, n, f);
9716   yices_release_mutex();
9717 
9718   if (code < 0) {
9719     // error in assert_formulas
9720     convert_internalization_error(code);
9721     code = -1;
9722     goto done;
9723   }
9724 
9725   if (code == TRIVIALLY_UNSAT) {
9726     *status = STATUS_UNSAT;
9727     code = 0;
9728     goto done;
9729   }
9730 
9731   assert(code == CTX_NO_ERROR);
9732 
9733   if (simplify_cnf) {
9734     code = process_then_export_to_dimacs(&context, filename, status);
9735   } else {
9736     code = bitblast_then_export_to_dimacs(&context, filename, status);
9737   }
9738   if (code < 0) {
9739     // error in creating or writing to the file
9740     code = -1;
9741     file_output_error();
9742   }
9743 
9744  done:
9745   delete_context(&context);
9746   return code;
9747 }
9748 
9749 /*
9750  * Bit-blast then export the CNF to a file
9751  * - f = a Boolean formula (in the QF_BV theory)
9752  * - filename = name of the ouput file
9753  * - simplify_cnf = boolean flag
9754  * - stat = pointer to a variable that stores the formula's status
9755  *
9756  * Return code:
9757  *   1 if the DIMACS file was constructed
9758  *   0 if the formula is solved without CNF or after simplifying
9759  *  -1 if there's an error
9760  *
9761  * Error reports:
9762  */
yices_export_formula_to_dimacs(term_t f,const char * filename,int32_t simplify_cnf,smt_status_t * status)9763 EXPORTED int32_t yices_export_formula_to_dimacs(term_t f, const char *filename, int32_t simplify_cnf, smt_status_t *status) {
9764   if (! yices_assert_formula_checks(f)) {
9765     return -1;
9766   }
9767   return yices_do_export_to_dimacs(&f, 1, filename, simplify_cnf != 0, status);
9768 }
9769 
9770 /*
9771  * Bit-blast n formulas then export the CNF to a file
9772  * - f = array of n Boolean formula (in the QF_BV theory)
9773  * - n = number of formulas in f
9774  * - filename = name of the ouput file
9775  * - simplify_cnf = boolean flag
9776  * - stat = pointer to a variable that stores the formula's status
9777  *
9778  * Return code:
9779  *   1 if the DIMACS file was constructed
9780  *   0 if the formula is solved without CNF or after simplifying
9781  *  -1 if there's an error
9782  *
9783  * Error reports:
9784  */
yices_export_formulas_to_dimacs(const term_t f[],uint32_t n,const char * filename,int32_t simplify_cnf,smt_status_t * status)9785 EXPORTED int32_t yices_export_formulas_to_dimacs(const term_t f[], uint32_t n, const char *filename,
9786 						 int32_t simplify_cnf, smt_status_t *status) {
9787   if (! yices_assert_formulas_checks(n, f)) {
9788     return -1;
9789   }
9790   return yices_do_export_to_dimacs(f, n, filename, simplify_cnf != 0, status);
9791 }
9792 
9793 
9794 
9795 /************************
9796  *  VALUES IN A MODEL   *
9797  ***********************/
9798 
9799 /*
9800  * Convert a negative evaluation code v to
9801  * the corresponding yices error code.
9802  * - v is a code returned by eval_in_model or get_implicant
9803  */
9804 #define NUM_EVAL_ERROR_CODES ((-MDL_EVAL_FORMULA_FALSE) + 1)
9805 
9806 static const error_code_t eval_error2code[NUM_EVAL_ERROR_CODES] = {
9807   NO_ERROR,              // v = 0
9808   EVAL_FAILED,           // v = null_value (-1)
9809   INTERNAL_EXCEPTION,    // v = MDL_EVAL_INTERNAL_ERROR (-2)
9810   EVAL_UNKNOWN_TERM,     // v = MDL_EVAL_UNKNOWN_TERM (-3)
9811   EVAL_FREEVAR_IN_TERM,  // v = MDL_EVAL_FREEVAR_IN_TERM (4)
9812   EVAL_QUANTIFIER,       // v = MDL_EVAL_QUANTIFIER (-5)
9813   EVAL_LAMBDA,           // v = MDL_EVAL_LAMBDA (-6)
9814   EVAL_FAILED,           // v = MDL_EVAL_FAILED (-7)
9815   EVAL_NO_IMPLICANT,     // v = MDL_EVAL_FALSE (-8)
9816 };
9817 
yices_eval_error(int32_t v)9818 static inline error_code_t yices_eval_error(int32_t v) {
9819   assert(0 <= -v && -v <= NUM_EVAL_ERROR_CODES);
9820   return eval_error2code[-v];
9821 }
9822 
9823 
9824 /*
9825  * Value of boolean term t: returned as an integer val
9826  * - val = 0 means t is false in mdl
9827  * - val = 1 means t is true in mdl
9828  *
9829  * Error codes:
9830  * If t is not boolean
9831  *   code = TYPE_MISMATCH
9832  *   term1 = t
9833  *   type1 = bool (expected type)
9834  * + the other evaluation error codes above.
9835  */
yices_get_bool_value(model_t * mdl,term_t t,int32_t * val)9836 EXPORTED int32_t yices_get_bool_value(model_t *mdl, term_t t, int32_t *val) {
9837   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_bool_value(mdl, t, val));
9838 }
9839 
_o_yices_get_bool_value(model_t * mdl,term_t t,int32_t * val)9840 int32_t _o_yices_get_bool_value(model_t *mdl, term_t t, int32_t *val) {
9841   value_table_t *vtbl;
9842   value_t v;
9843 
9844   if (! check_good_term(__yices_globals.manager, t) ||
9845       ! check_boolean_term(__yices_globals.manager, t)) {
9846     return -1;
9847   }
9848 
9849   v = model_get_term_value(mdl, t);
9850   if (v < 0) {
9851     set_error_code(yices_eval_error(v));
9852     return -1;
9853   }
9854 
9855   vtbl = model_get_vtbl(mdl);
9856   if (! object_is_boolean(vtbl, v)) {
9857     set_error_code(INTERNAL_EXCEPTION);
9858     return -1;
9859   }
9860 
9861   *val = boolobj_value(vtbl, v);
9862 
9863   return 0;
9864 }
9865 
9866 
9867 /*
9868  * Value of arithmetic term t: it can be returned as an integer, a
9869  * rational (pair num/den), converted to a double, using the GMP
9870  * mpz_t and mpq_t representations, or as a libpoly algebraic number.
9871  *
9872  * Error codes:
9873  * If t is not an arithmetic term:
9874  *   code = ARITH_TERM_REQUIRED
9875  *   term1 = t
9876  * If t's value does not fit in the *val object
9877  *   code = EVAL_OVERFLOW
9878  */
9879 
9880 typedef enum arithval_tag {
9881   ARITHVAL_ERROR,
9882   ARITHVAL_RATIONAL,
9883   ARITHVAL_ALGEBRAIC,
9884 } arithval_tag_t;
9885 
9886 /*
9887  * Tagged union to represent pointers to either rational or algebraic numbers.
9888  * The flag can ERROR/RATIONAL/ALGEBRAIC
9889  */
9890 typedef struct arithval_struct_s {
9891   arithval_tag_t tag;
9892   union {
9893     rational_t *q;
9894     lp_algebraic_number_t *p;
9895   } val;
9896 } arithval_struct_t;
9897 
9898 
9899 
9900 /*
9901  * Auxiliary function: return the rational value of t
9902  * - store the result in *r
9903  * - if there's an error, set r->tag to ERROR and store an error report
9904  */
yices_get_arith_value(model_t * mdl,term_t t,arithval_struct_t * r)9905 static void yices_get_arith_value(model_t *mdl, term_t t, arithval_struct_t *r) {
9906   value_table_t *vtbl;
9907   value_t v;
9908 
9909   r->tag = ARITHVAL_ERROR;
9910   r->val.q = NULL;
9911 
9912   if (! check_good_term(__yices_globals.manager, t) ||
9913       ! check_arith_term(__yices_globals.manager, t)){
9914     return;
9915   }
9916 
9917   v = model_get_term_value(mdl, t);
9918   if (v < 0) {
9919     set_error_code(yices_eval_error(v));
9920     return;
9921   }
9922 
9923   vtbl = model_get_vtbl(mdl);
9924   if (object_is_rational(vtbl, v)) {
9925     r->tag = ARITHVAL_RATIONAL;
9926     r->val.q = vtbl_rational(vtbl, v);
9927   } else if (object_is_algebraic(vtbl, v)) {
9928     r->tag = ARITHVAL_ALGEBRAIC;
9929     r->val.p = vtbl_algebraic_number(vtbl, v);
9930   } else {
9931     // should not happen since t is an arithmetic term
9932     set_error_code(INTERNAL_EXCEPTION);
9933   }
9934 }
9935 
9936 /*
9937  * Check whether r->tag is RATIONAL, if not report an error: CONVERSION_FAILED
9938  */
arithval_is_rational(const arithval_struct_t * r)9939 static bool arithval_is_rational(const arithval_struct_t *r) {
9940   bool result;
9941 
9942   result = r->tag == ARITHVAL_RATIONAL;
9943   if (r->tag == ARITHVAL_ALGEBRAIC) {
9944     set_error_code(EVAL_CONVERSION_FAILED);
9945   }
9946   return result;
9947 }
9948 
9949 // return the value as a 32bit integer
yices_get_int32_value(model_t * mdl,term_t t,int32_t * val)9950 EXPORTED int32_t yices_get_int32_value(model_t *mdl, term_t t, int32_t *val) {
9951   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_int32_value(mdl, t, val));
9952 }
9953 
_o_yices_get_int32_value(model_t * mdl,term_t t,int32_t * val)9954 int32_t _o_yices_get_int32_value(model_t *mdl, term_t t, int32_t *val) {
9955   arithval_struct_t aux;
9956 
9957   yices_get_arith_value(mdl, t, &aux);
9958   if (! arithval_is_rational(&aux)) {
9959     return -1;
9960   }
9961 
9962   if (! q_get32(aux.val.q, val)) {
9963     set_error_code(EVAL_OVERFLOW);
9964     return -1;
9965   }
9966 
9967   return 0;
9968 }
9969 
9970 // return the value as a 64bit integer
yices_get_int64_value(model_t * mdl,term_t t,int64_t * val)9971 EXPORTED int32_t yices_get_int64_value(model_t *mdl, term_t t, int64_t *val) {
9972   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_int64_value(mdl, t, val));
9973 }
9974 
_o_yices_get_int64_value(model_t * mdl,term_t t,int64_t * val)9975 int32_t _o_yices_get_int64_value(model_t *mdl, term_t t, int64_t *val) {
9976   arithval_struct_t aux;
9977 
9978   yices_get_arith_value(mdl, t, &aux);
9979   if (! arithval_is_rational(&aux)) {
9980     return -1;
9981   }
9982 
9983   if (! q_get64(aux.val.q, val)) {
9984     set_error_code(EVAL_OVERFLOW);
9985     return -1;
9986   }
9987 
9988   return 0;
9989 }
9990 
9991 // return the value as a pair num/den (both 32bit integers)
yices_get_rational32_value(model_t * mdl,term_t t,int32_t * num,uint32_t * den)9992 EXPORTED int32_t yices_get_rational32_value(model_t *mdl, term_t t, int32_t *num, uint32_t *den) {
9993   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_rational32_value(mdl, t, num, den));
9994 }
9995 
_o_yices_get_rational32_value(model_t * mdl,term_t t,int32_t * num,uint32_t * den)9996 int32_t _o_yices_get_rational32_value(model_t *mdl, term_t t, int32_t *num, uint32_t *den) {
9997   arithval_struct_t aux;
9998 
9999   yices_get_arith_value(mdl, t, &aux);
10000   if (! arithval_is_rational(&aux)) {
10001     return -1;
10002   }
10003 
10004   if (! q_get_int32(aux.val.q, num, den)) {
10005     set_error_code(EVAL_OVERFLOW);
10006     return -1;
10007   }
10008 
10009   return 0;
10010 }
10011 
10012 // pair num/den (64bit integers)
yices_get_rational64_value(model_t * mdl,term_t t,int64_t * num,uint64_t * den)10013 EXPORTED int32_t yices_get_rational64_value(model_t *mdl, term_t t, int64_t *num, uint64_t *den) {
10014   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_rational64_value(mdl, t, num, den));
10015 }
10016 
_o_yices_get_rational64_value(model_t * mdl,term_t t,int64_t * num,uint64_t * den)10017 int32_t _o_yices_get_rational64_value(model_t *mdl, term_t t, int64_t *num, uint64_t *den) {
10018   arithval_struct_t aux;
10019 
10020   yices_get_arith_value(mdl, t, &aux);
10021   if (! arithval_is_rational(&aux)) {
10022     return -1;
10023   }
10024 
10025   if (! q_get_int64(aux.val.q, num, den)) {
10026     set_error_code(EVAL_OVERFLOW);
10027     return -1;
10028   }
10029 
10030   return 0;
10031 }
10032 
10033 // convert to a floating point number
yices_get_double_value(model_t * mdl,term_t t,double * val)10034 EXPORTED int32_t yices_get_double_value(model_t *mdl, term_t t, double *val) {
10035   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_double_value(mdl, t, val));
10036 }
10037 
_o_yices_get_double_value(model_t * mdl,term_t t,double * val)10038 int32_t _o_yices_get_double_value(model_t *mdl, term_t t, double *val) {
10039   arithval_struct_t aux;
10040 
10041   yices_get_arith_value(mdl, t, &aux);
10042   if (aux.tag == ARITHVAL_RATIONAL) {
10043     *val = q_get_double(aux.val.q);
10044     return 0;
10045   }
10046 
10047 #if HAVE_MCSAT
10048   if (aux.tag == ARITHVAL_ALGEBRAIC) {
10049     *val = lp_algebraic_number_to_double(aux.val.p);
10050     return 0;
10051   }
10052 #endif
10053 
10054   return -1;
10055 }
10056 
10057 
10058 // convert to a GMP integer
yices_get_mpz_value(model_t * mdl,term_t t,mpz_t val)10059 EXPORTED int32_t yices_get_mpz_value(model_t *mdl, term_t t, mpz_t val) {
10060   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_mpz_value(mdl, t, val));
10061 }
10062 
_o_yices_get_mpz_value(model_t * mdl,term_t t,mpz_t val)10063 int32_t _o_yices_get_mpz_value(model_t *mdl, term_t t, mpz_t val) {
10064   arithval_struct_t aux;
10065 
10066   yices_get_arith_value(mdl, t, &aux);
10067   if (! arithval_is_rational(&aux)) {
10068     return -1;
10069   }
10070 
10071   if (!q_get_mpz(aux.val.q, val)) {
10072     // the value is not an integer (maybe we should use a better error code
10073     // in this case?)
10074     set_error_code(EVAL_OVERFLOW);
10075     return -1;
10076   }
10077 
10078   return 0;
10079 }
10080 
10081 // convert to a GMP rational
yices_get_mpq_value(model_t * mdl,term_t t,mpq_t val)10082 EXPORTED int32_t yices_get_mpq_value(model_t *mdl, term_t t, mpq_t val) {
10083   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_mpq_value(mdl, t, val));
10084 }
10085 
_o_yices_get_mpq_value(model_t * mdl,term_t t,mpq_t val)10086 int32_t _o_yices_get_mpq_value(model_t *mdl, term_t t, mpq_t val) {
10087   arithval_struct_t aux;
10088 
10089   yices_get_arith_value(mdl, t, &aux);
10090   if (! arithval_is_rational(&aux)) {
10091     return -1;
10092   }
10093 
10094   q_get_mpq(aux.val.q, val);
10095 
10096   return 0;
10097 }
10098 
10099 
10100 /*
10101  * Algebraic number
10102  */
yices_get_algebraic_number_value(model_t * mdl,term_t t,lp_algebraic_number_t * a)10103 EXPORTED int32_t yices_get_algebraic_number_value(model_t *mdl, term_t t, lp_algebraic_number_t *a) {
10104   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_algebraic_number_value(mdl, t, a));
10105 }
10106 
_o_yices_get_algebraic_number_value(model_t * mdl,term_t t,lp_algebraic_number_t * a)10107 int32_t _o_yices_get_algebraic_number_value(model_t *mdl, term_t t, lp_algebraic_number_t *a) {
10108 #if HAVE_MCSAT
10109   arithval_struct_t aux;
10110 
10111   yices_get_arith_value(mdl, t, &aux);
10112   if (aux.tag == ARITHVAL_ALGEBRAIC) {
10113     lp_algebraic_number_construct_copy(a, aux.val.p);
10114     return 0;
10115   }
10116 
10117   // TODO: convert rational to algebraic (no direct way to do this in libpoly)
10118   if (aux.tag == ARITHVAL_RATIONAL) {
10119     set_error_code(EVAL_CONVERSION_FAILED);
10120     return -1;
10121   }
10122 
10123   return -1;
10124 
10125 #else
10126   // NO SUPPORT FOT MCSAT
10127   set_error_code(EVAL_NOT_SUPPORTED);
10128   return -1;
10129 #endif
10130 }
10131 
10132 /*
10133  * Value of bitvector term t in mdl
10134  * - the value is returned in array val
10135  * - val must be an integer array of sufficient size to store all bits of t
10136  * - bit i of t is stored in val[i] (val[i] is either 0 or 1)
10137  * - the value is returned using small-endian convention:
10138  *    val[0] is the low order bit
10139  *    ...
10140  *    val[n-1] is the high order bit
10141  *
10142  * If t is not a bitvector term
10143  *   code = BITVECTOR_REQUIRED
10144  *   term1 = t
10145  */
yices_get_bv_value(model_t * mdl,term_t t,int32_t val[])10146 EXPORTED int32_t yices_get_bv_value(model_t *mdl, term_t t, int32_t val[]) {
10147   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_bv_value(mdl, t, val));
10148 }
10149 
_o_yices_get_bv_value(model_t * mdl,term_t t,int32_t val[])10150 int32_t _o_yices_get_bv_value(model_t *mdl, term_t t, int32_t val[]) {
10151   value_table_t *vtbl;
10152   value_bv_t *bv;
10153   value_t v;
10154 
10155   if (! check_good_term(__yices_globals.manager, t) ||
10156       ! check_bitvector_term(__yices_globals.manager, t)) {
10157     return -1;
10158   }
10159 
10160   v = model_get_term_value(mdl, t);
10161   if (v < 0) {
10162     set_error_code(yices_eval_error(v));
10163     return -1;
10164   }
10165 
10166   vtbl = model_get_vtbl(mdl);
10167   if (! object_is_bitvector(vtbl, v)) {
10168     set_error_code(INTERNAL_EXCEPTION);
10169     return -1;
10170   }
10171 
10172   bv = vtbl_bitvector(vtbl, v);
10173   bvconst_get_array(bv->data, val, bv->nbits);
10174 
10175   return 0;
10176 }
10177 
10178 
10179 
10180 /*
10181  * Value of term t of uninterpreted or scalar type
10182  * - the value is returned as a constant index in *val
10183  *   (with the same meaning as in function yices_constant):
10184  * - if t has type tau and tau is a scalar type of size n then
10185  *   the function returns an index k between 0 and n-1
10186  * - if tau is an uninterpreted type, then the function returns an
10187  *   integer index k
10188  *
10189  * Error codes:
10190  * - if t does not have a scalar or uninterpreted type:
10191  *   code = SCALAR_TERM_REQUIRED
10192  *   term1 = t
10193  */
yices_get_scalar_value(model_t * mdl,term_t t,int32_t * val)10194 EXPORTED int32_t yices_get_scalar_value(model_t *mdl, term_t t, int32_t *val) {
10195   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_scalar_value(mdl, t, val));
10196 }
10197 
_o_yices_get_scalar_value(model_t * mdl,term_t t,int32_t * val)10198 int32_t _o_yices_get_scalar_value(model_t *mdl, term_t t, int32_t *val) {
10199   value_table_t *vtbl;
10200   value_unint_t *uv;
10201   value_t v;
10202 
10203   if (! check_good_term(__yices_globals.manager, t) ||
10204       ! check_scalar_term(__yices_globals.manager, t)) {
10205     return -1;
10206   }
10207 
10208   v = model_get_term_value(mdl, t);
10209   if (v < 0) {
10210     set_error_code(yices_eval_error(v));
10211     return -1;
10212   }
10213 
10214   vtbl = model_get_vtbl(mdl);
10215   if (! object_is_unint(vtbl, v)) {
10216     set_error_code(INTERNAL_EXCEPTION);
10217     return -1;
10218   }
10219 
10220   uv = vtbl_unint(vtbl, v);
10221   *val = uv->index;
10222 
10223   return 0;
10224 }
10225 
10226 
10227 /*
10228  * FULL MODEL: NODES AND VALUE DESCRIPTORS
10229  */
10230 
10231 /*
10232  * Vectors of node descriptors
10233  */
yices_init_yval_vector(yval_vector_t * v)10234 EXPORTED void yices_init_yval_vector(yval_vector_t *v) {
10235   init_yval_vector(v);
10236 }
10237 
yices_reset_yval_vector(yval_vector_t * v)10238 EXPORTED void yices_reset_yval_vector(yval_vector_t *v) {
10239   reset_yval_vector(v);
10240 }
10241 
yices_delete_yval_vector(yval_vector_t * v)10242 EXPORTED void yices_delete_yval_vector(yval_vector_t *v) {
10243   delete_yval_vector(v);
10244 }
10245 
10246 /*
10247  * Value of term t stored as a node descriptor in *val.
10248  *
10249  * The function returns 0 it t's value can be computed, -1 otherwise.
10250  *
10251  * Error codes are as in all evaluation functions.
10252  * If t is not valid:
10253  *   code = INVALID_TERM
10254  *   term1 = t
10255  * If t contains a subterm whose value is not known
10256  *   code = EVAL_UNKNOWN_TERM
10257  * If t contains free variables
10258  *   code = EVAL_FREEVAR_IN_TERM
10259  * If t contains quantifier(s)
10260  *   code = EVAL_QUANTIFIER
10261  * If t contains lambda terms
10262  *   code = EVAL_LAMBDA
10263  * If the evaluation fails for other reasons:
10264  *   code = EVAL_FAILED
10265  */
yices_get_value(model_t * mdl,term_t t,yval_t * val)10266 EXPORTED int32_t yices_get_value(model_t *mdl, term_t t, yval_t *val) {
10267   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_get_value(mdl, t, val));
10268 }
10269 
_o_yices_get_value(model_t * mdl,term_t t,yval_t * val)10270 int32_t _o_yices_get_value(model_t *mdl, term_t t, yval_t *val) {
10271   value_table_t *vtbl;
10272   value_t v;
10273 
10274   if (! check_good_term(__yices_globals.manager, t)) {
10275     return -1;
10276   }
10277 
10278   v = model_get_term_value(mdl, t);
10279   if (v < 0) {
10280     set_error_code(yices_eval_error(v));
10281     return -1;
10282   }
10283 
10284   vtbl = model_get_vtbl(mdl);
10285   get_yval(vtbl, v, val);
10286 
10287   return 0;
10288 }
10289 
10290 
10291 /*
10292  * Queries on the value of a rational node
10293  */
yices_val_is_int32(model_t * mdl,const yval_t * v)10294 EXPORTED int32_t yices_val_is_int32(model_t *mdl, const yval_t *v) {
10295   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_is_int32(mdl, v));
10296 }
10297 
_o_yices_val_is_int32(model_t * mdl,const yval_t * v)10298 int32_t _o_yices_val_is_int32(model_t *mdl, const yval_t *v) {
10299   value_table_t *vtbl;
10300   rational_t *q;
10301   value_t id;
10302   int32_t code;
10303 
10304   code = false;
10305   if (v->node_tag == YVAL_RATIONAL) {
10306     vtbl = model_get_vtbl(mdl);
10307     id = v->node_id;
10308     if (good_object(vtbl, id) && object_is_rational(vtbl, id)) {
10309       q = vtbl_rational(vtbl, id);
10310       code = q_is_int32(q);
10311     }
10312   }
10313 
10314   return code;
10315 }
10316 
yices_val_is_int64(model_t * mdl,const yval_t * v)10317 EXPORTED int32_t yices_val_is_int64(model_t *mdl, const yval_t *v) {
10318   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_is_int64(mdl, v));
10319 }
10320 
_o_yices_val_is_int64(model_t * mdl,const yval_t * v)10321 int32_t _o_yices_val_is_int64(model_t *mdl, const yval_t *v) {
10322   value_table_t *vtbl;
10323   rational_t *q;
10324   value_t id;
10325   int32_t code;
10326 
10327   code = false;
10328   if (v->node_tag == YVAL_RATIONAL) {
10329     vtbl = model_get_vtbl(mdl);
10330     id = v->node_id;
10331     if (good_object(vtbl, id) && object_is_rational(vtbl, id)) {
10332       q = vtbl_rational(vtbl, id);
10333       code = q_is_int64(q);
10334     }
10335   }
10336 
10337   return code;
10338 }
10339 
yices_val_is_rational32(model_t * mdl,const yval_t * v)10340 EXPORTED int32_t yices_val_is_rational32(model_t *mdl, const yval_t *v) {
10341   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_is_rational32(mdl, v));
10342 }
10343 
_o_yices_val_is_rational32(model_t * mdl,const yval_t * v)10344 int32_t _o_yices_val_is_rational32(model_t *mdl, const yval_t *v) {
10345   value_table_t *vtbl;
10346   rational_t *q;
10347   value_t id;
10348   int32_t code;
10349 
10350   code = false;
10351   if (v->node_tag == YVAL_RATIONAL) {
10352     vtbl = model_get_vtbl(mdl);
10353     id = v->node_id;
10354     if (good_object(vtbl, id) && object_is_rational(vtbl, id)) {
10355       q = vtbl_rational(vtbl, id);
10356       code = q_fits_int32(q);
10357     }
10358   }
10359 
10360   return code;
10361 }
10362 
yices_val_is_rational64(model_t * mdl,const yval_t * v)10363 EXPORTED int32_t yices_val_is_rational64(model_t *mdl, const yval_t *v) {
10364   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_is_rational64(mdl, v));
10365 }
10366 
_o_yices_val_is_rational64(model_t * mdl,const yval_t * v)10367 int32_t _o_yices_val_is_rational64(model_t *mdl, const yval_t *v) {
10368   value_table_t *vtbl;
10369   rational_t *q;
10370   value_t id;
10371   int32_t code;
10372 
10373   code = false;
10374   if (v->node_tag == YVAL_RATIONAL) {
10375     vtbl = model_get_vtbl(mdl);
10376     id = v->node_id;
10377     if (good_object(vtbl, id) && object_is_rational(vtbl, id)) {
10378       q = vtbl_rational(vtbl, id);
10379       code = q_fits_int64(q);
10380     }
10381   }
10382 
10383   return code;
10384 }
10385 
yices_val_is_integer(model_t * mdl,const yval_t * v)10386 EXPORTED int32_t yices_val_is_integer(model_t *mdl, const yval_t *v) {
10387   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_is_integer(mdl, v));
10388 }
10389 
_o_yices_val_is_integer(model_t * mdl,const yval_t * v)10390 int32_t _o_yices_val_is_integer(model_t *mdl, const yval_t *v) {
10391   value_table_t *vtbl;
10392   rational_t *q;
10393   value_t id;
10394   int32_t code;
10395 
10396   code = false;
10397   if (v->node_tag == YVAL_RATIONAL) {
10398     vtbl = model_get_vtbl(mdl);
10399     id = v->node_id;
10400     if (good_object(vtbl, id) && object_is_rational(vtbl, id)) {
10401       q = vtbl_rational(vtbl, id);
10402       code = q_is_integer(q);
10403     }
10404   }
10405 
10406   return code;
10407 }
10408 
10409 /*
10410  * Number of bits in a bitvector constant
10411  */
yices_val_bitsize(model_t * mdl,const yval_t * v)10412 EXPORTED uint32_t yices_val_bitsize(model_t *mdl, const yval_t *v) {
10413   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_val_bitsize(mdl, v));
10414 }
10415 
_o_yices_val_bitsize(model_t * mdl,const yval_t * v)10416 uint32_t _o_yices_val_bitsize(model_t *mdl, const yval_t *v) {
10417   value_table_t *vtbl;
10418   value_bv_t *bv;
10419   value_t id;
10420   uint32_t n;
10421 
10422   n = 0;
10423   if (v->node_tag == YVAL_BV) {
10424     vtbl = model_get_vtbl(mdl);
10425     id = v->node_id;
10426     if (good_object(vtbl, id) && object_is_bitvector(vtbl, id)) {
10427       bv = vtbl_bitvector(vtbl, id);
10428       n = bv->nbits;
10429     }
10430   }
10431 
10432   return n;
10433 }
10434 
10435 
10436 /*
10437  * Number of components in a tuple
10438  */
yices_val_tuple_arity(model_t * mdl,const yval_t * v)10439 EXPORTED uint32_t yices_val_tuple_arity(model_t *mdl, const yval_t *v) {
10440   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_val_tuple_arity(mdl, v));
10441 }
10442 
_o_yices_val_tuple_arity(model_t * mdl,const yval_t * v)10443 uint32_t _o_yices_val_tuple_arity(model_t *mdl, const yval_t *v) {
10444   value_table_t *vtbl;
10445   value_tuple_t *tuple;
10446   value_t id;
10447   uint32_t n;
10448 
10449   n = 0;
10450   if (v->node_tag == YVAL_TUPLE) {
10451     vtbl = model_get_vtbl(mdl);
10452     id = v->node_id;
10453     if (good_object(vtbl, id) && object_is_tuple(vtbl, id)) {
10454       tuple = vtbl_tuple(vtbl, id);
10455       n = tuple->nelems;
10456     }
10457   }
10458 
10459   return n;
10460 }
10461 
10462 
10463 /*
10464  * Arity of a mapping object
10465  */
yices_val_mapping_arity(model_t * mdl,const yval_t * v)10466 EXPORTED uint32_t yices_val_mapping_arity(model_t *mdl, const yval_t *v) {
10467   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_val_mapping_arity(mdl, v));
10468 }
10469 
_o_yices_val_mapping_arity(model_t * mdl,const yval_t * v)10470 uint32_t _o_yices_val_mapping_arity(model_t *mdl, const yval_t *v) {
10471   value_table_t *vtbl;
10472   value_map_t *map;
10473   value_t id;
10474   uint32_t n;
10475 
10476   n = 0;
10477   if (v->node_tag == YVAL_MAPPING) {
10478     vtbl = model_get_vtbl(mdl);
10479     id = v->node_id;
10480     if (good_object(vtbl, id) && object_is_map(vtbl, id)) {
10481       map = vtbl_map(vtbl, id);
10482       n = map->arity;
10483     }
10484   }
10485 
10486   return n;
10487 }
10488 
10489 /*
10490  * Arity of a function node
10491  */
yices_val_function_arity(model_t * mdl,const yval_t * v)10492 EXPORTED uint32_t yices_val_function_arity(model_t *mdl, const yval_t *v) {
10493   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_val_function_arity(mdl, v));
10494 }
10495 
_o_yices_val_function_arity(model_t * mdl,const yval_t * v)10496 uint32_t _o_yices_val_function_arity(model_t *mdl, const yval_t *v) {
10497   value_table_t *vtbl;
10498   value_t id;
10499   uint32_t n;
10500 
10501   n = 0;
10502   if (v->node_tag == YVAL_FUNCTION) {
10503     vtbl = model_get_vtbl(mdl);
10504     id = v->node_id;
10505     if (good_object(vtbl, id)) {
10506       if (object_is_function(vtbl, id)) {
10507 	n = vtbl_function(vtbl, id)->arity;
10508       } else if (object_is_update(vtbl, id)) {
10509 	n = vtbl_update(vtbl, id)->arity;
10510       }
10511     }
10512   }
10513 
10514   return n;
10515 }
10516 
10517 /*
10518  * Type of a function node
10519  */
yices_val_function_type(model_t * mdl,const yval_t * v)10520 EXPORTED type_t yices_val_function_type(model_t *mdl, const yval_t *v) {
10521   MT_PROTECT(type_t,  __yices_globals.lock, _o_yices_val_function_type(mdl, v));
10522 }
10523 
_o_yices_val_function_type(model_t * mdl,const yval_t * v)10524 type_t _o_yices_val_function_type(model_t *mdl, const yval_t *v) {
10525   value_table_t *vtbl;
10526   value_t id;
10527 
10528   if (v->node_tag == YVAL_FUNCTION) {
10529     vtbl = model_get_vtbl(mdl);
10530     id = v->node_id;
10531     if (good_object(vtbl, id) &&
10532 	(object_is_function(vtbl, id) || object_is_update(vtbl, id))) {
10533       return vtbl_function_type(vtbl, id);
10534     }
10535   } else {
10536     set_error_code(YVAL_INVALID_OP);
10537   }
10538   return NULL_TYPE;
10539 }
10540 
10541 /*
10542  * Extract value of a leaf node
10543  */
yices_val_get_bool(model_t * mdl,const yval_t * v,int32_t * val)10544 EXPORTED int32_t yices_val_get_bool(model_t *mdl, const yval_t *v, int32_t *val) {
10545   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_bool(mdl, v, val));
10546 }
10547 
_o_yices_val_get_bool(model_t * mdl,const yval_t * v,int32_t * val)10548 int32_t _o_yices_val_get_bool(model_t *mdl, const yval_t *v, int32_t *val) {
10549   value_table_t *vtbl;
10550   value_t id;
10551 
10552   if (v->node_tag == YVAL_BOOL) {
10553     vtbl = model_get_vtbl(mdl);
10554     id = v->node_id;
10555     if (good_object(vtbl, id) && object_is_boolean(vtbl, id)) {
10556       *val = boolobj_value(vtbl, id);
10557       return 0;
10558     }
10559   } else {
10560     set_error_code(YVAL_INVALID_OP);
10561   }
10562   return -1;
10563 }
10564 
10565 
10566 /*
10567  * Auxiliary function: return the rational value of v
10568  * - return NULL and set error code to YVAL_INVALID_OP if v does not refer to a rational object
10569  */
yices_val_get_rational(model_t * mdl,const yval_t * v)10570 static rational_t *yices_val_get_rational(model_t *mdl, const yval_t *v) {
10571   value_table_t *vtbl;
10572   value_t id;
10573 
10574   if (v->node_tag == YVAL_RATIONAL) {
10575     vtbl = model_get_vtbl(mdl);
10576     id = v->node_id;
10577     if (good_object(vtbl, id) && object_is_rational(vtbl, id)) {
10578       return vtbl_rational(vtbl, id);
10579     }
10580   } else {
10581     set_error_code(YVAL_INVALID_OP);
10582   }
10583   return NULL;
10584 }
10585 
yices_val_get_int32(model_t * mdl,const yval_t * v,int32_t * val)10586 EXPORTED int32_t yices_val_get_int32(model_t *mdl, const yval_t *v, int32_t *val) {
10587   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_int32(mdl, v, val));
10588 }
10589 
_o_yices_val_get_int32(model_t * mdl,const yval_t * v,int32_t * val)10590 int32_t _o_yices_val_get_int32(model_t *mdl, const yval_t *v, int32_t *val) {
10591   rational_t *q;
10592 
10593   q = yices_val_get_rational(mdl, v);
10594   if (q == NULL) {
10595     return -1;
10596   }
10597 
10598   if (! q_get32(q, val)) {
10599     set_error_code(YVAL_OVERFLOW);
10600     return -1;
10601   }
10602 
10603   return 0;
10604 }
10605 
yices_val_get_int64(model_t * mdl,const yval_t * v,int64_t * val)10606 EXPORTED int32_t yices_val_get_int64(model_t *mdl, const yval_t *v, int64_t *val) {
10607   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_int64(mdl, v, val));
10608 }
10609 
_o_yices_val_get_int64(model_t * mdl,const yval_t * v,int64_t * val)10610 int32_t _o_yices_val_get_int64(model_t *mdl, const yval_t *v, int64_t *val) {
10611   rational_t *q;
10612 
10613   q = yices_val_get_rational(mdl, v);
10614   if (q == NULL) {
10615     return -1;
10616   }
10617 
10618   if (! q_get64(q, val)) {
10619     set_error_code(YVAL_OVERFLOW);
10620     return -1;
10621   }
10622 
10623   return 0;
10624 }
10625 
yices_val_get_rational32(model_t * mdl,const yval_t * v,int32_t * num,uint32_t * den)10626 EXPORTED int32_t yices_val_get_rational32(model_t *mdl, const yval_t *v, int32_t *num, uint32_t *den) {
10627   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_rational32(mdl, v, num, den));
10628 }
10629 
_o_yices_val_get_rational32(model_t * mdl,const yval_t * v,int32_t * num,uint32_t * den)10630 int32_t _o_yices_val_get_rational32(model_t *mdl, const yval_t *v, int32_t *num, uint32_t *den) {
10631   rational_t *q;
10632 
10633   q = yices_val_get_rational(mdl, v);
10634   if (q == NULL) {
10635     return -1;
10636   }
10637 
10638   if (! q_get_int32(q, num, den)) {
10639     set_error_code(YVAL_OVERFLOW);
10640     return -1;
10641   }
10642 
10643   return 0;
10644 }
10645 
yices_val_get_rational64(model_t * mdl,const yval_t * v,int64_t * num,uint64_t * den)10646 EXPORTED int32_t yices_val_get_rational64(model_t *mdl, const yval_t *v, int64_t *num, uint64_t *den) {
10647   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_rational64(mdl, v, num, den));
10648 }
10649 
_o_yices_val_get_rational64(model_t * mdl,const yval_t * v,int64_t * num,uint64_t * den)10650 int32_t _o_yices_val_get_rational64(model_t *mdl, const yval_t *v, int64_t *num, uint64_t *den) {
10651   rational_t *q;
10652 
10653   q = yices_val_get_rational(mdl, v);
10654   if (q == NULL) {
10655     return -1;
10656   }
10657 
10658   if (! q_get_int64(q, num, den)) {
10659     set_error_code(YVAL_OVERFLOW);
10660     return -1;
10661   }
10662 
10663   return 0;
10664 }
10665 
yices_val_get_mpz(model_t * mdl,const yval_t * v,mpz_t val)10666 EXPORTED int32_t yices_val_get_mpz(model_t *mdl, const yval_t *v, mpz_t val) {
10667   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_mpz(mdl, v, val));
10668 }
10669 
_o_yices_val_get_mpz(model_t * mdl,const yval_t * v,mpz_t val)10670 int32_t _o_yices_val_get_mpz(model_t *mdl, const yval_t *v, mpz_t val) {
10671   rational_t *q;
10672 
10673   q = yices_val_get_rational(mdl, v);
10674   if (q == NULL) {
10675     return -1;
10676   }
10677 
10678   if (!q_get_mpz(q, val)) {
10679     set_error_code(EVAL_OVERFLOW);
10680     return -1;
10681   }
10682 
10683   return 0;
10684 }
10685 
yices_val_get_mpq(model_t * mdl,const yval_t * v,mpq_t val)10686 EXPORTED int32_t yices_val_get_mpq(model_t *mdl, const yval_t *v, mpq_t val) {
10687   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_mpq(mdl, v, val));
10688 }
10689 
_o_yices_val_get_mpq(model_t * mdl,const yval_t * v,mpq_t val)10690 int32_t _o_yices_val_get_mpq(model_t *mdl, const yval_t *v, mpq_t val) {
10691   rational_t *q;
10692 
10693   q = yices_val_get_rational(mdl, v);
10694   if (q == NULL) {
10695     return -1;
10696   }
10697   q_get_mpq(q, val);
10698 
10699   return 0;
10700 }
10701 
10702 
10703 // Conversion to double
yices_val_get_double(model_t * mdl,const yval_t * v,double * val)10704 EXPORTED int32_t yices_val_get_double(model_t *mdl, const yval_t *v, double *val) {
10705   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_double(mdl, v, val));
10706 }
10707 
_o_yices_val_get_double(model_t * mdl,const yval_t * v,double * val)10708 int32_t _o_yices_val_get_double(model_t *mdl, const yval_t *v, double *val) {
10709   value_table_t *vtbl;
10710   value_t id;
10711 
10712   vtbl = model_get_vtbl(mdl);
10713   id = v->node_id;
10714 
10715   if (v->node_tag == YVAL_RATIONAL) {
10716     if (good_object(vtbl, id) && object_is_rational(vtbl, id)) {
10717       *val = q_get_double(vtbl_rational(vtbl, id));
10718       return 0;
10719     }
10720   }
10721 
10722 #if HAVE_MCSAT
10723   if (v->node_tag == YVAL_ALGEBRAIC) {
10724     if (good_object(vtbl, id) && object_is_algebraic(vtbl, id)) {
10725       *val = lp_algebraic_number_to_double(vtbl_algebraic_number(vtbl, id));
10726       return 0;
10727     }
10728   }
10729 #endif
10730 
10731   set_error_code(YVAL_INVALID_OP);
10732   return -1;
10733 }
10734 
10735 /*
10736  * Value of a bitvector node
10737  */
yices_val_get_bv(model_t * mdl,const yval_t * v,int32_t val[])10738 EXPORTED int32_t yices_val_get_bv(model_t *mdl, const yval_t *v, int32_t val[]) {
10739   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_bv(mdl, v, val));
10740 }
10741 
_o_yices_val_get_bv(model_t * mdl,const yval_t * v,int32_t val[])10742 int32_t _o_yices_val_get_bv(model_t *mdl, const yval_t *v, int32_t val[]) {
10743   value_table_t *vtbl;
10744   value_bv_t *bv;
10745   value_t id;
10746 
10747   if (v->node_tag == YVAL_BV) {
10748     vtbl = model_get_vtbl(mdl);
10749     id = v->node_id;
10750     if (good_object(vtbl, id) && object_is_bitvector(vtbl, id)) {
10751       bv = vtbl_bitvector(vtbl, id);
10752       bvconst_get_array(bv->data, val, bv->nbits);
10753       return 0;
10754     }
10755   } else {
10756     set_error_code(YVAL_INVALID_OP);
10757   }
10758   return -1;
10759 }
10760 
10761 /*
10762  * Algebraic number
10763  */
yices_val_get_algebraic_number(model_t * mdl,const yval_t * v,lp_algebraic_number_t * a)10764 EXPORTED int32_t yices_val_get_algebraic_number(model_t *mdl, const yval_t *v, lp_algebraic_number_t *a) {
10765   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_algebraic_number(mdl, v, a));
10766 }
10767 
_o_yices_val_get_algebraic_number(model_t * mdl,const yval_t * v,lp_algebraic_number_t * a)10768 int32_t _o_yices_val_get_algebraic_number(model_t *mdl, const yval_t *v, lp_algebraic_number_t *a) {
10769 #if HAVE_MCSAT
10770   value_table_t *vtbl;
10771   value_t id;
10772 
10773   if (v->node_tag == YVAL_ALGEBRAIC) {
10774     vtbl = model_get_vtbl(mdl);
10775     id = v->node_id;
10776     if (good_object(vtbl, id) && object_is_algebraic(vtbl, id)) {
10777       lp_algebraic_number_construct_copy(a, vtbl_algebraic_number(vtbl, id));
10778       return 0;
10779     }
10780   } else {
10781     set_error_code(YVAL_INVALID_OP);
10782   }
10783 
10784 #else
10785   set_error_code(YVAL_NOT_SUPPORTED);
10786 #endif
10787 
10788   return -1;
10789 }
10790 
10791 
10792 
10793 /*
10794  * Value of a scalar/uninterpreted constant
10795  */
yices_val_get_scalar(model_t * mdl,const yval_t * v,int32_t * val,type_t * tau)10796 EXPORTED int32_t yices_val_get_scalar(model_t *mdl, const yval_t *v, int32_t *val, type_t *tau) {
10797   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_get_scalar(mdl, v, val, tau));
10798 }
10799 
_o_yices_val_get_scalar(model_t * mdl,const yval_t * v,int32_t * val,type_t * tau)10800 int32_t _o_yices_val_get_scalar(model_t *mdl, const yval_t *v, int32_t *val, type_t *tau) {
10801   value_table_t *vtbl;
10802   value_unint_t *u;
10803   value_t id;
10804 
10805   if (v->node_tag == YVAL_SCALAR) {
10806     vtbl = model_get_vtbl(mdl);
10807     id = v->node_id;
10808     if (good_object(vtbl, id) && object_is_unint(vtbl, id)) {
10809       u = vtbl_unint(vtbl, id);
10810       *tau = u->type;
10811       *val = u->index;
10812       return 0;
10813     }
10814   } else {
10815     set_error_code(YVAL_INVALID_OP);
10816   }
10817   return -1;
10818 }
10819 
10820 
10821 /*
10822  * Expand a tuple node
10823  */
yices_val_expand_tuple(model_t * mdl,const yval_t * v,yval_t child[])10824 EXPORTED int32_t yices_val_expand_tuple(model_t *mdl, const yval_t *v, yval_t child[]) {
10825   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_expand_tuple(mdl, v, child));
10826 }
10827 
10828 
_o_yices_val_expand_tuple(model_t * mdl,const yval_t * v,yval_t child[])10829 int32_t _o_yices_val_expand_tuple(model_t *mdl, const yval_t *v, yval_t child[]) {
10830   value_table_t *vtbl;
10831   value_t id;
10832 
10833   if (v->node_tag == YVAL_TUPLE) {
10834     vtbl = model_get_vtbl(mdl);
10835     id = v->node_id;
10836     if (good_object(vtbl, id) && object_is_tuple(vtbl, id)) {
10837       yval_expand_tuple(vtbl, id, child);
10838       return 0;
10839     }
10840   } else {
10841     set_error_code(YVAL_INVALID_OP);
10842   }
10843   return -1;
10844 }
10845 
10846 
10847 /*
10848  * Expand a mapping node
10849  */
yices_val_expand_mapping(model_t * mdl,const yval_t * v,yval_t tup[],yval_t * val)10850 EXPORTED int32_t yices_val_expand_mapping(model_t *mdl, const yval_t *v, yval_t tup[], yval_t *val) {
10851   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_expand_mapping(mdl, v, tup, val));
10852 }
10853 
_o_yices_val_expand_mapping(model_t * mdl,const yval_t * v,yval_t tup[],yval_t * val)10854 int32_t _o_yices_val_expand_mapping(model_t *mdl, const yval_t *v, yval_t tup[], yval_t *val) {
10855   value_table_t *vtbl;
10856   value_t id;
10857 
10858   if (v->node_tag == YVAL_MAPPING) {
10859     vtbl = model_get_vtbl(mdl);
10860     id = v->node_id;
10861     if (good_object(vtbl, id) && object_is_map(vtbl, id)) {
10862       yval_expand_mapping(vtbl, id, tup, val);
10863       return 0;
10864     }
10865   } else {
10866     set_error_code(YVAL_INVALID_OP);
10867   }
10868   return -1;
10869 }
10870 
10871 
10872 /*
10873  * Expand a function node
10874  */
yices_val_expand_function(model_t * mdl,const yval_t * f,yval_t * def,yval_vector_t * v)10875 EXPORTED int32_t yices_val_expand_function(model_t *mdl, const yval_t *f, yval_t *def, yval_vector_t *v) {
10876   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_val_expand_function(mdl, f, def, v));
10877 }
10878 
_o_yices_val_expand_function(model_t * mdl,const yval_t * f,yval_t * def,yval_vector_t * v)10879 int32_t _o_yices_val_expand_function(model_t *mdl, const yval_t *f, yval_t *def, yval_vector_t *v) {
10880   value_table_t *vtbl;
10881   value_t id;
10882 
10883   if (f->node_tag == YVAL_FUNCTION) {
10884     vtbl = model_get_vtbl(mdl);
10885     id = f->node_id;
10886     if (good_object(vtbl, id)) {
10887       if (object_is_function(vtbl, id)) {
10888 	yval_expand_function(vtbl, id, v, def);
10889 	return 0;
10890       }
10891       if (object_is_update(vtbl, id)) {
10892 	yval_expand_update(vtbl, id, v, def);
10893 	return 0;
10894       }
10895     }
10896   } else {
10897     set_error_code(YVAL_INVALID_OP);
10898   }
10899   return -1;
10900 }
10901 
10902 
10903 /*
10904  * VALUES AS CONSTANT TERMS
10905  */
10906 
10907 /*
10908  * Value of term t converted to a constant term val.
10909  */
yices_get_value_as_term(model_t * mdl,term_t t)10910 EXPORTED term_t yices_get_value_as_term(model_t *mdl, term_t t) {
10911   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_get_value_as_term(mdl, t));
10912 }
10913 
_o_yices_get_value_as_term(model_t * mdl,term_t t)10914 term_t _o_yices_get_value_as_term(model_t *mdl, term_t t) {
10915   value_table_t *vtbl;
10916   value_t v;
10917   term_t a;
10918 
10919   if (! check_good_term(__yices_globals.manager, t)) {
10920     return NULL_TERM;
10921   }
10922 
10923   v = model_get_term_value(mdl, t);
10924   if (v < 0) {
10925     set_error_code(yices_eval_error(v));
10926     return NULL_TERM;
10927   }
10928 
10929   vtbl = model_get_vtbl(mdl);
10930   a = convert_value_to_term(__yices_globals.terms, vtbl, v);
10931   if (a < 0) {
10932     set_error_code(EVAL_CONVERSION_FAILED);
10933     return NULL_TERM;
10934   }
10935 
10936   return a;
10937 }
10938 
10939 
10940 
10941 /*
10942  * TEST TRUTH-VALUE OF BOOLEAN TERMS
10943  */
10944 
10945 /*
10946  * Check whether f is true in mdl
10947  * - the returned value is
10948  *     1 if f is true in mdl,
10949  *     0 if f is false in mdl,
10950  *    -1 if f's value can't be evaluated
10951  *
10952  * Error codes:
10953  * - same as get_bool_val
10954  */
yices_formula_true_in_model(model_t * mdl,term_t f)10955 EXPORTED int32_t yices_formula_true_in_model(model_t *mdl, term_t f) {
10956   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_formula_true_in_model(mdl, f));
10957 }
10958 
_o_yices_formula_true_in_model(model_t * mdl,term_t f)10959 int32_t _o_yices_formula_true_in_model(model_t *mdl, term_t f) {
10960   int32_t code;
10961 
10962   if (! check_good_term(__yices_globals.manager, f) ||
10963       ! check_boolean_term(__yices_globals.manager, f)) {
10964     return -1;
10965   }
10966 
10967   if (formula_holds_in_model(mdl, f, &code)) {
10968     assert(code >= 0);
10969     return 1; // true
10970   } else if (code >= 0) {
10971     return 0; // false
10972   } else {
10973     // code < 0: contains the evaluation error
10974     set_error_code(yices_eval_error(code));
10975     return -1;
10976   }
10977 }
10978 
10979 
10980 /*
10981  * Check whether formulas f[0 ... n-1] are all true in mdl
10982  * - the returned value is as in the previous function:
10983  *     1 if all f[i] are true
10984  *     0 if one f[i] is false (and f[0 ... i-1] are all true)
10985  *    -1 if one f[i] can't be evaluated
10986  * Error code:
10987  * - same as yices_get_bool_val
10988  */
yices_formulas_true_in_model(model_t * mdl,uint32_t n,const term_t f[])10989 EXPORTED int32_t yices_formulas_true_in_model(model_t *mdl, uint32_t n, const term_t f[]) {
10990   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_formulas_true_in_model(mdl, n, f));
10991 }
10992 
_o_yices_formulas_true_in_model(model_t * mdl,uint32_t n,const term_t f[])10993 int32_t _o_yices_formulas_true_in_model(model_t *mdl, uint32_t n, const term_t f[]) {
10994   int32_t code;
10995 
10996   if (! check_good_terms(__yices_globals.manager, n, f) ||
10997       ! check_boolean_args(__yices_globals.manager, n, f)) {
10998     return -1;
10999   }
11000 
11001   if (formulas_hold_in_model(mdl, n, f, &code)) {
11002     assert(code >= 0);
11003     return 1; // all true
11004   } else if (code >= 0) {
11005     return 0; // at least one false
11006   } else {
11007     // error in evaluation: code contains the eval code
11008     set_error_code(yices_eval_error(code));
11009     return -1;
11010   }
11011 }
11012 
11013 
11014 
11015 
11016 /*
11017  * ARRAYS
11018  */
11019 
11020 /*
11021  * Values of terms a[0 ... n-1] all converted to terms
11022  */
yices_term_array_value(model_t * mdl,uint32_t n,const term_t a[],term_t b[])11023 EXPORTED int32_t yices_term_array_value(model_t *mdl, uint32_t n, const term_t a[], term_t b[]) {
11024   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_term_array_value(mdl, n, a, b));
11025 }
11026 
_o_yices_term_array_value(model_t * mdl,uint32_t n,const term_t a[],term_t b[])11027 int32_t _o_yices_term_array_value(model_t *mdl, uint32_t n, const term_t a[], term_t b[]) {
11028   int32_t eval_code;
11029   uint32_t count;
11030 
11031   if (! check_good_terms(__yices_globals.manager, n, a)) {
11032     return -1;
11033   }
11034 
11035   eval_code = evaluate_term_array(mdl, n, a, b);
11036   if (eval_code < 0) {
11037     set_error_code(yices_eval_error(eval_code));
11038     return -1;
11039   }
11040 
11041   count = convert_value_array(__yices_globals.terms, model_get_vtbl(mdl), n, b);
11042   if (count < n) {
11043     set_error_code(EVAL_CONVERSION_FAILED);
11044     return -1;
11045   }
11046 
11047   return 0;
11048 }
11049 
11050 
11051 
11052 
11053 
11054 /*
11055  * IMPLICANTS
11056  */
11057 
11058 /*
11059  * Given a model mdl and a Boolean term t that is true in mdl, return an implicant for t
11060  * - the implicant is a list of literals a[0 ... n-1] such that
11061  *   every a[i] is true in mdl
11062  *   the conjunction a[0] /\ a[1] /\ ... /\ a[n-1] implies t
11063  *
11064  * The function returns a[0 ... n-1] in a term_vector v that must be initialized (by
11065  * yices_init_term_vector).
11066  *
11067  * The function returns 0 if all goes well or -1 if there's an error
11068  *
11069  * Error codes:
11070  * - INVALID_TERM         if t is not valid
11071  * - TYPE_MISMATCH        if t is not a Boolean term
11072  * - EVAL_FREEVAR_IN_TERM if t contains free variables
11073  * - EVAL_QUANTIFIER     if t contains quantifiers
11074  * - EVAL_LAMBDA          if t contains a lambda
11075  * - EVAL_NO_IMPLICANT    if t is false in  mdl
11076  * - EVAL_FAILED          if the function fails for some other reason
11077  */
yices_implicant_for_formula(model_t * mdl,term_t t,term_vector_t * v)11078 EXPORTED int32_t yices_implicant_for_formula(model_t *mdl, term_t t, term_vector_t *v) {
11079   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_implicant_for_formula(mdl, t, v));
11080 }
11081 
_o_yices_implicant_for_formula(model_t * mdl,term_t t,term_vector_t * v)11082 int32_t _o_yices_implicant_for_formula(model_t *mdl, term_t t, term_vector_t *v) {
11083   int32_t code;
11084 
11085   if (! check_good_term(__yices_globals.manager, t) ||
11086       ! check_boolean_term(__yices_globals.manager, t)) {
11087     return -1;
11088   }
11089 
11090   v->size = 0;
11091   code = get_implicant(mdl, __yices_globals.manager, LIT_COLLECTOR_ALL_OPTIONS, 1, &t, (ivector_t *) v);
11092   if (code < 0) {
11093     set_error_code(yices_eval_error(code));
11094     return -1;
11095   }
11096 
11097   return 0;
11098 }
11099 
11100 
11101 /*
11102  * Same thing for an array of formulas a[0 ... n-1]
11103  */
yices_implicant_for_formulas(model_t * mdl,uint32_t n,const term_t a[],term_vector_t * v)11104 EXPORTED int32_t yices_implicant_for_formulas(model_t *mdl, uint32_t n, const term_t a[], term_vector_t *v) {
11105   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_implicant_for_formulas(mdl, n, a, v));
11106 }
11107 
_o_yices_implicant_for_formulas(model_t * mdl,uint32_t n,const term_t a[],term_vector_t * v)11108 int32_t _o_yices_implicant_for_formulas(model_t *mdl, uint32_t n, const term_t a[], term_vector_t *v) {
11109   int32_t code;
11110 
11111   if (! check_good_terms(__yices_globals.manager, n, a) ||
11112       ! check_boolean_args(__yices_globals.manager, n, a)) {
11113     return -1;
11114   }
11115 
11116   v->size = 0;
11117   code = get_implicant(mdl, __yices_globals.manager, LIT_COLLECTOR_ALL_OPTIONS, n, a, (ivector_t *) v);
11118   if (code < 0) {
11119     set_error_code(yices_eval_error(code));
11120     return -1;
11121   }
11122 
11123   return 0;
11124 }
11125 
11126 
11127 
11128 /*
11129  * MODEL GENERALIZATION
11130  */
11131 
11132 /*
11133  * Convert a negative error code v from generalization.h into the
11134  * corresponding yices error code.
11135  */
11136 #define NUM_GEN_ERROR_CODES ((-GEN_PROJ_ERROR_BAD_ARITH_LITERAL)+1)
11137 
11138 static const error_code_t gen_error2code[NUM_GEN_ERROR_CODES] = {
11139   NO_ERROR,                  // 0
11140   MDL_GEN_FAILED,            // NULL_TERM,
11141   INTERNAL_EXCEPTION,        // GEN_EVAL_INTERNAL_ERROR
11142   EVAL_UNKNOWN_TERM,         // GEN_EVAL_UNKNOWN_TERM
11143   EVAL_FREEVAR_IN_TERM,      // GEN_EVAL_FREEVAR_IN_TERM
11144   EVAL_QUANTIFIER,           // GEN_EVAL_QUANTIFIER
11145   EVAL_LAMBDA,               // GEN_EVAL_LAMBDA
11146   MDL_GEN_FAILED,            // GEN_EVAL_FAILED
11147   EVAL_NO_IMPLICANT,         // GEN_EVAL_FORMULA_FALSE
11148   MDL_GEN_FAILED,            // GEN_CONV_INTERNAL_ERROR
11149   EVAL_CONVERSION_FAILED,    // GEN_CONV_UNKNOWN_VALUE
11150   EVAL_CONVERSION_FAILED,    // GEN_CONV_NOT_PRIMITIVE
11151   EVAL_CONVERSION_FAILED,    // GEN_CONV_FUNCTION
11152   EVAL_CONVERSION_FAILED,    // GEN_CONV_FAILED
11153   MDL_GEN_NONLINEAR,         // GEN_PROJ_ERROR_NON_LINEAR
11154   MDL_GEN_FAILED,            // GEN_PROJ_ERROR_IN_EVAL
11155   MDL_GEN_FAILED,            // GEN_PROJ_ERROR_IN_CONVERT
11156   MDL_GEN_FAILED,            // GEN_PROJ_ERROR_IN_SUBST
11157   MDL_GEN_FAILED,            // GEN_PROJ_ERROR_BAD_ARITH_LITERAL
11158 };
11159 
yices_gen_error(int32_t v)11160 static inline error_code_t yices_gen_error(int32_t v) {
11161   assert(0 <= -v && v < NUM_GEN_ERROR_CODES);
11162   return gen_error2code[-v];
11163 }
11164 
11165 
11166 /*
11167  * Given a model mdl for a formula F(X, Y). The following generalization functions
11168  * eliminate variables Y from F(X, Y) in a way that is guided by the model.
11169  *
11170  * - nelims = number of variables to eliminate
11171  * - elim = variables to eliminate
11172  * - each term in elim[i] must be an uninterpreted term (as returned by yices_new_uninterpreted_term)
11173  *   of one of the following types: Boolean, (bitvector k), or Real
11174  * - mode defines the generalization algorithm
11175  * - v: term_vector to return the result
11176  *
11177  */
yices_generalize_model(model_t * mdl,term_t t,uint32_t nelims,const term_t elim[],yices_gen_mode_t mode,term_vector_t * v)11178 EXPORTED int32_t yices_generalize_model(model_t *mdl, term_t t, uint32_t nelims, const term_t elim[],
11179 					yices_gen_mode_t mode, term_vector_t *v) {
11180   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_generalize_model(mdl, t, nelims, elim, mode, v));
11181 }
11182 
_o_yices_generalize_model(model_t * mdl,term_t t,uint32_t nelims,const term_t elim[],yices_gen_mode_t mode,term_vector_t * v)11183 int32_t _o_yices_generalize_model(model_t *mdl, term_t t, uint32_t nelims, const term_t elim[],
11184 					yices_gen_mode_t mode, term_vector_t *v) {
11185   int32_t code;
11186 
11187   if (! check_good_term(__yices_globals.manager, t) ||
11188       ! check_boolean_term(__yices_globals.manager, t) ||
11189       ! check_elim_vars(__yices_globals.manager, nelims, elim)) {
11190     return -1;
11191   }
11192 
11193   v->size = 0;
11194   switch (mode) {
11195   case YICES_GEN_BY_SUBST:
11196     code = gen_model_by_substitution(mdl, __yices_globals.manager, 1, &t, nelims, elim, (ivector_t *) v);
11197     break;
11198 
11199   case YICES_GEN_BY_PROJ:
11200     code = gen_model_by_projection(mdl, __yices_globals.manager, 1, &t, nelims, elim, (ivector_t *) v);
11201     break;
11202 
11203   default:
11204     code = generalize_model(mdl, __yices_globals.manager, 1, &t, nelims, elim, (ivector_t *) v);
11205     break;
11206   }
11207 
11208   if (code < 0) {
11209     set_error_code(yices_gen_error(code));
11210     return -1;
11211   }
11212 
11213   return 0;
11214 }
11215 
11216 
11217 /*
11218  * Same thing for a conjunction of formulas a[0 ... n-1]
11219  */
yices_generalize_model_array(model_t * mdl,uint32_t n,const term_t a[],uint32_t nelims,const term_t elim[],yices_gen_mode_t mode,term_vector_t * v)11220 EXPORTED term_t yices_generalize_model_array(model_t *mdl, uint32_t n, const term_t a[], uint32_t nelims, const term_t elim[],
11221 					     yices_gen_mode_t mode, term_vector_t *v) {
11222   MT_PROTECT(term_t,  __yices_globals.lock, _o_yices_generalize_model_array(mdl, n, a, nelims, elim, mode, v));
11223 }
11224 
_o_yices_generalize_model_array(model_t * mdl,uint32_t n,const term_t a[],uint32_t nelims,const term_t elim[],yices_gen_mode_t mode,term_vector_t * v)11225 term_t _o_yices_generalize_model_array(model_t *mdl, uint32_t n, const term_t a[], uint32_t nelims, const term_t elim[],
11226 					     yices_gen_mode_t mode, term_vector_t *v) {
11227   int32_t code;
11228 
11229   if (! check_good_terms(__yices_globals.manager, n, a) ||
11230       ! check_boolean_args(__yices_globals.manager, n, a) ||
11231       ! check_elim_vars(__yices_globals.manager, nelims, elim)) {
11232     return NULL_TERM;
11233   }
11234 
11235   v->size = 0;
11236   switch (mode) {
11237   case YICES_GEN_BY_SUBST:
11238     code = gen_model_by_substitution(mdl, __yices_globals.manager, n, a, nelims, elim, (ivector_t *) v);
11239     break;
11240 
11241   case YICES_GEN_BY_PROJ:
11242     code = gen_model_by_projection(mdl, __yices_globals.manager, n, a, nelims, elim, (ivector_t *) v);
11243     break;
11244 
11245   default:
11246     code = generalize_model(mdl, __yices_globals.manager, n, a, nelims, elim, (ivector_t *) v);
11247     break;
11248   }
11249 
11250   if (code < 0) {
11251     set_error_code(yices_gen_error(code));
11252     return -1;
11253   }
11254 
11255   return 0;
11256 }
11257 
11258 
11259 
11260 
11261 
11262 /*************************
11263  *  GARBAGE COLLECTION   *
11264  ************************/
11265 
11266 /*
11267  * Allocate and initialize the registry tables
11268  */
get_root_terms(void)11269 static sparse_array_t *get_root_terms(void) {
11270   if (root_terms == NULL) {
11271     init_sparse_array(&the_root_terms, 0);
11272     root_terms = &the_root_terms;
11273   }
11274   return root_terms;
11275 }
11276 
get_root_types(void)11277 static sparse_array_t *get_root_types(void) {
11278   if (root_types == NULL) {
11279     init_sparse_array(&the_root_types, 0);
11280     root_types = &the_root_types;
11281   }
11282   return root_types;
11283 }
11284 
11285 
11286 /*
11287  * Increment/decrement the reference counters
11288  */
yices_incref_term(term_t t)11289 EXPORTED int32_t yices_incref_term(term_t t) {
11290   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_incref_term(t));
11291 }
11292 
_o_yices_incref_term(term_t t)11293 int32_t _o_yices_incref_term(term_t t) {
11294   sparse_array_t *roots;
11295 
11296   if (!check_good_term(__yices_globals.manager, t)) {
11297     return -1;
11298   }
11299 
11300   // we keep the ref count on the term index
11301   // (i.e., we ignore t's polarity)
11302   roots = get_root_terms();
11303   sparse_array_incr(roots, index_of(t));
11304 
11305   return 0;
11306 }
11307 
yices_incref_type(type_t tau)11308 EXPORTED int32_t yices_incref_type(type_t tau) {
11309   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_incref_type(tau));
11310 }
11311 
_o_yices_incref_type(type_t tau)11312 int32_t _o_yices_incref_type(type_t tau) {
11313   sparse_array_t *roots;
11314 
11315   if (!check_good_type(__yices_globals.types, tau)) {
11316     return -1;
11317   }
11318 
11319   roots = get_root_types();
11320   sparse_array_incr(roots, tau);
11321 
11322   return 0;
11323 }
11324 
yices_decref_term(term_t t)11325 EXPORTED int32_t yices_decref_term(term_t t) {
11326   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_decref_term(t));
11327 }
11328 
_o_yices_decref_term(term_t t)11329 int32_t _o_yices_decref_term(term_t t) {
11330   if (!check_good_term(__yices_globals.manager, t)) {
11331     return -1;
11332   }
11333 
11334   if (root_terms == NULL || sparse_array_read(root_terms, index_of(t)) == 0) {
11335     error_report_t *error = get_yices_error();
11336     error->code = BAD_TERM_DECREF;
11337     error->term1 = t;
11338     return -1;
11339   }
11340 
11341   sparse_array_decr(root_terms, index_of(t));
11342 
11343   return 0;
11344 }
11345 
yices_decref_type(type_t tau)11346 EXPORTED int32_t yices_decref_type(type_t tau) {
11347   MT_PROTECT(int32_t,  __yices_globals.lock, _o_yices_decref_type(tau));
11348 }
11349 
_o_yices_decref_type(type_t tau)11350 int32_t _o_yices_decref_type(type_t tau) {
11351   if (! check_good_type(__yices_globals.types, tau)) {
11352     return -1;
11353   }
11354 
11355   if (root_types == NULL || sparse_array_read(root_types, tau) == 0) {
11356     error_report_t *error = get_yices_error();
11357     error->code = BAD_TYPE_DECREF;
11358     error->type1 = tau;
11359     return -1;
11360   }
11361 
11362   sparse_array_decr(root_types, tau);
11363 
11364   return 0;
11365 }
11366 
11367 
11368 /*
11369  * Number of live terms and types
11370  */
yices_num_terms(void)11371 EXPORTED uint32_t yices_num_terms(void) {
11372   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_num_terms());
11373 }
11374 
_o_yices_num_terms(void)11375 uint32_t _o_yices_num_terms(void) {
11376   return __yices_globals.terms->live_terms;
11377 }
11378 
yices_num_types(void)11379 EXPORTED uint32_t yices_num_types(void) {
11380   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_num_types());
11381 }
11382 
_o_yices_num_types(void)11383 uint32_t _o_yices_num_types(void) {
11384   return __yices_globals.types->live_types;
11385 }
11386 
11387 
11388 /*
11389  * Number of terms/types with a positive reference count
11390  */
yices_num_posref_terms(void)11391 EXPORTED uint32_t yices_num_posref_terms(void) {
11392   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_num_posref_terms());
11393 }
11394 
_o_yices_num_posref_terms(void)11395 uint32_t _o_yices_num_posref_terms(void) {
11396   uint32_t n;
11397 
11398   n = 0;
11399   if (root_terms != NULL) {
11400     n = root_terms->nelems;
11401   }
11402   return n;
11403 }
11404 
yices_num_posref_types(void)11405 EXPORTED uint32_t yices_num_posref_types(void) {
11406   MT_PROTECT(uint32_t,  __yices_globals.lock, _o_yices_num_posref_types());
11407 }
11408 
_o_yices_num_posref_types(void)11409 uint32_t _o_yices_num_posref_types(void) {
11410   uint32_t n;
11411 
11412   n = 0;
11413   if (root_types != NULL) {
11414     n = root_types->nelems;
11415   }
11416   return n;
11417 }
11418 
11419 
11420 
11421 /*
11422  * GC: mark roots
11423  */
11424 
11425 // iterator for the root_terms array
term_idx_marker(void * aux,uint32_t i)11426 static void term_idx_marker(void *aux, uint32_t i) {
11427   assert(aux == __yices_globals.terms);
11428   if (good_term_idx(aux, i)) {
11429     term_table_set_gc_mark(aux, i);
11430   }
11431 }
11432 
11433 // iterator for the root_types array
type_marker(void * aux,uint32_t i)11434 static void type_marker(void *aux, uint32_t i) {
11435   assert(aux == __yices_globals.types);
11436   if (good_type(aux, i)) {
11437     type_table_set_gc_mark(aux, i);
11438   }
11439 }
11440 
11441 // scan the list of contexts and mark
context_list_gc_mark(void)11442 static void context_list_gc_mark(void) {
11443   dl_list_t *elem;
11444 
11445   elem = context_list.next;
11446   while (elem != &context_list) {
11447     context_gc_mark(context_of_header(elem));
11448     elem = elem->next;
11449   }
11450 }
11451 
11452 // scan the list of models and call the mark procedure
model_list_gc_mark(void)11453 static void model_list_gc_mark(void) {
11454   dl_list_t *elem;
11455 
11456   elem = model_list.next;
11457   while (elem != &model_list) {
11458     model_gc_mark(model_of_header(elem));
11459     elem = elem->next;
11460   }
11461 }
11462 
11463 // mark all terms in array a, n = size of a
mark_term_array(term_table_t * tbl,const term_t * a,uint32_t n)11464 static void mark_term_array(term_table_t *tbl, const term_t *a, uint32_t n) {
11465   uint32_t i;
11466   int32_t idx;
11467 
11468   for (i=0; i<n; i++) {
11469     idx = index_of(a[i]);
11470     if (good_term_idx(tbl, idx)) {
11471       term_table_set_gc_mark(tbl, idx);
11472     }
11473   }
11474 }
11475 
11476 // mark all types in array a
mark_type_array(type_table_t * tbl,const type_t * a,uint32_t n)11477 static void mark_type_array(type_table_t *tbl, const type_t *a, uint32_t n) {
11478   uint32_t i;
11479   type_t tau;
11480 
11481   for (i=0; i<n; i++) {
11482     tau = a[i];
11483     if (good_type(tbl, tau)) {
11484       type_table_set_gc_mark(tbl, tau);
11485     }
11486   }
11487 }
11488 
11489 
11490 /*
11491  * Call the garbage collector
11492  * - t = optional array of terms
11493  * - nt = size of t
11494  * - tau = optional array of types
11495  * - ntau = size of tau
11496  * - keep_named specifies whether the named terms and types should
11497  *   all be preserved
11498  */
yices_garbage_collect(const term_t t[],uint32_t nt,const type_t tau[],uint32_t ntau,int32_t keep_named)11499 EXPORTED void yices_garbage_collect(const term_t t[], uint32_t nt,
11500 				    const type_t tau[], uint32_t ntau,
11501 				    int32_t keep_named) {
11502   MT_PROTECT_VOID(__yices_globals.lock, _o_yices_garbage_collect(t, nt, tau, ntau, keep_named));
11503 }
11504 
_o_yices_garbage_collect(const term_t t[],uint32_t nt,const type_t tau[],uint32_t ntau,int32_t keep_named)11505 void _o_yices_garbage_collect(const term_t t[], uint32_t nt,
11506                               const type_t tau[], uint32_t ntau,
11507                               int32_t keep_named) {
11508   bool keep;
11509 
11510 
11511   get_list_locks();
11512 
11513   /*
11514    * Default roots: all terms and types in all live models and context
11515    */
11516   context_list_gc_mark();
11517   model_list_gc_mark();
11518 
11519   /*
11520    * Add roots from t and tau
11521    */
11522   if (t != NULL) mark_term_array(__yices_globals.terms, t, nt);
11523   if (tau != NULL) mark_type_array(__yices_globals.types, tau, ntau);
11524 
11525   /*
11526    * Roots from the reference counting
11527    */
11528   if (root_terms != NULL) {
11529     sparse_array_iterate(root_terms, __yices_globals.terms, term_idx_marker);
11530   }
11531   if (root_types != NULL) {
11532     sparse_array_iterate(root_types, __yices_globals.types, type_marker);
11533   }
11534 
11535   /*
11536    * Call the garbage collector
11537    */
11538   keep = (keep_named != 0);
11539   term_table_gc(__yices_globals.terms, keep);
11540 
11541   /*
11542    * Cleanup the fvars structure if it exists
11543    */
11544   if (__yices_globals.fvars != NULL) {
11545     cleanup_fvar_collector(__yices_globals.fvars);
11546   }
11547 
11548   release_list_locks();
11549 
11550 }
11551