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