/* * Reset to the empty table */ void reset_intern_tbl(intern_tbl_t *tbl) { reset_int32_array(&tbl->map); reset_int32_array(&tbl->type); reset_uint8_array(&tbl->rank); if (tbl->cache != NULL) { int_hset_reset(tbl->cache); } if (tbl->queue != NULL) { int_queue_reset(tbl->queue); } }
/* * Reset queue/cache and vector */ void reset_flattener(flattener_t *flat) { int_queue_reset(&flat->queue); int_hset_reset(&flat->cache); ivector_reset(&flat->resu); }
/* * Check whether t occurs in v * - t must be a free root * - v must be a valid term */ static bool bfs_occurs_check(intern_tbl_t *tbl, term_t t, term_t v) { term_table_t *terms; int_queue_t *queue; int_hset_t *cache; int32_t x; bool found; assert(intern_tbl_root_is_free(tbl, t)); assert(is_pos_term(t) && term_kind(tbl->terms, t) == UNINTERPRETED_TERM); terms = tbl->terms; queue = intern_tbl_get_queue(tbl); cache = intern_tbl_get_cache(tbl); assert(int_queue_is_empty(queue) && int_hset_is_empty(cache)); bfs_visit_term(tbl, v); found = false; do { x = int_queue_pop(queue); switch (kind_for_idx(terms, x)) { case CONSTANT_TERM: case ARITH_CONSTANT: case BV64_CONSTANT: case BV_CONSTANT: case VARIABLE: break; case UNINTERPRETED_TERM: if (x == index_of(t)) { // found a cycle found = true; goto done; } break; case ARITH_EQ_ATOM: case ARITH_GE_ATOM: bfs_visit_term(tbl, integer_value_for_idx(terms, x)); break; case ITE_TERM: case ITE_SPECIAL: case APP_TERM: case UPDATE_TERM: case TUPLE_TERM: case EQ_TERM: case DISTINCT_TERM: case FORALL_TERM: case LAMBDA_TERM: case OR_TERM: case XOR_TERM: case ARITH_BINEQ_ATOM: case BV_ARRAY: case BV_DIV: case BV_REM: case BV_SDIV: case BV_SREM: case BV_SMOD: case BV_SHL: case BV_LSHR: case BV_ASHR: case BV_EQ_ATOM: case BV_GE_ATOM: case BV_SGE_ATOM: bfs_visit_composite(tbl, composite_for_idx(terms, x)); break; case BIT_TERM: case SELECT_TERM: bfs_visit_term(tbl, select_for_idx(terms, x)->arg); break; case POWER_PRODUCT: bfs_visit_pprod(tbl, pprod_for_idx(terms, x)); break; case ARITH_POLY: bfs_visit_poly(tbl, polynomial_for_idx(terms, x)); break; case BV64_POLY: bfs_visit_bvpoly64(tbl, bvpoly64_for_idx(terms, x)); break; case BV_POLY: bfs_visit_bvpoly(tbl, bvpoly_for_idx(terms, x)); break; default: assert(false); abort(); break; } } while (! int_queue_is_empty(queue)); done: int_hset_reset(cache); int_queue_reset(queue); return found; }
/* * Check whether f is a range constraint * - if so return a term t and fill in vector v with the formula's constants * - otherwise, return NULL_TERM * * Side effect: use queue and cache. * v may be modified even if the function returns NULL_TERM. */ static term_t formula_is_range_constraint(sym_breaker_t *breaker, term_t f, ivector_t *v) { int_queue_t *queue; int_hset_t *cache; term_table_t *terms; intern_tbl_t *intern; term_t r, t; term_t x, a, y, b; uint32_t neqs; queue = &breaker->queue; cache = &breaker->cache; terms = breaker->terms; intern = &breaker->ctx->intern; assert(int_queue_is_empty(queue) && int_hset_is_empty(cache)); push_term(queue, cache, f); neqs = 0; t = NULL_TERM; y = NULL_TERM; // prevent GCC warning b = NULL_TERM; // prevent GCC warning /* * Invariants: * - neqs = number of equality atoms seen so far * - if neq == 1, then the first equality is stored as (y == b) where b is a constant * - if neq >= 2, then all equalities seen so far were of the form (x == constant) */ do { // r := root of the first term in the queue r = intern_tbl_get_root(intern, int_queue_pop(queue)); switch (match_term(breaker->ctx, r, &a, &x)) { case MATCH_FALSE: // skip false terms break; case MATCH_OR: push_children(queue, cache, or_term_desc(terms, r)); break; case MATCH_EQ: assert(term_is_constant(terms, a)); if (neqs == 0) { y = x; b = a; } else if (neqs == 1) { /* * First equality: (y == b). Second equality: (x == a) */ if (y == x) { // y is the common term, a and b are constant ivector_push(v, b); ivector_push(v, a); } else if (y == a && term_is_uconst(terms, x)) { // y is the common term, b and x are constant ivector_push(v, b); ivector_push(v, a); } else if (x == b && term_is_uconst(terms, y)) { // b is the common term, y and a are constant ivector_push(v, y); ivector_push(v, a); y = b; } else if (a == b && term_is_uconst(terms, y) && term_is_uconst(terms, x)) { // b is the common term, y and x are constant ivector_push(v, y); ivector_push(v, x); y = b; } else { // abort goto done; } } else { /* * All equalities so far have the form (y == constant) * - the current equality is (x == a) */ if (y == x) { ivector_push(v, a); // match } else if (y == a && term_is_constant(terms, x)) { ivector_push(v, x); // swap a and x } else { // no match goto done; } } neqs ++; break; case MATCH_IFF: /* * the returned term x is equivalent to t */ push_term(queue, cache, x); break; default: // abort goto done; } } while (! int_queue_is_empty(queue)); assert(y != NULL_TERM && t == NULL_TERM); if (neqs >= 2) { assert(v->size == neqs); t = y; } done: int_queue_reset(queue); int_hset_reset(cache); return t; }