• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SRI-CSL / yices2 / 25301905438

04 May 2026 04:59AM UTC coverage: 66.687% (+0.002%) from 66.685%
25301905438

Pull #590

github

disteph
coverage: mark fail-closed defensive branches LCOV_EXCL

The four review-driven commits earlier in this PR added defensive
fail-closed branches that are unreachable on supported inputs:

  - src/mcsat/uf/uf_plugin.c
      * uf_plugin_get_function_id_from_trail's q_get32 failure path
      * uf_plugin_build_app_model_compare's both-ids-failed fallback
      * uf_model_builder_remember_function_term's early return
      * uf_model_builder_get_function_value's early return on id lookup
      * uf_model_builder_get_function_value's make_fresh_function ==
        null_value branch (rejected by the preprocessor guard)
      * uf_model_builder_prepare's continue on id lookup

  - src/context/context.c
      * two internalize_to_eterm consistency assert()s that fire only
        when root was already mapped during recursive internalization

All of these are never taken in the gcov regression run (either
guarded out by term_needs_function_diseq_guard in preprocessor.c, or
structurally impossible because function ids are allocated as small
non-negative integers by uf_plugin_decide), so they show up as
uncovered lines and regress PR 590's coveralls score.

Wrap each with LCOV_EXCL_LINE (single-line branches) or
LCOV_EXCL_START / LCOV_EXCL_STOP (multi-line blocks). The hardening
itself is preserved; the markers only tell lcov not to count these
deliberately unreachable lines against the coverage metric.

No behavior change.

Refs: PR #590, coveralls build 79245430.
Pull Request #590: fixes #414

65 of 80 new or added lines in 6 files covered. (81.25%)

37 existing lines in 8 files now uncovered.

83456 of 125146 relevant lines covered (66.69%)

1655176.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.45
/src/mcsat/preprocessor.c
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
#if defined(CYGWIN) || defined(MINGW)
20
#ifndef __YICES_DLLSPEC__
21
#define __YICES_DLLSPEC__ __declspec(dllexport)
22
#endif
23
#endif
24

25
#include "mcsat/preprocessor.h"
26
#include "mcsat/tracing.h"
27

28
#include "terms/term_explorer.h"
29
#include "terms/bvarith64_buffer_terms.h"
30
#include "terms/bvarith_buffer_terms.h"
31

32
#include "model/models.h"
33

34
#include "context/context_types.h"
35

36
#include "yices.h"
37
#include "api/yices_api_lock_free.h"
38

39
void preprocessor_construct(preprocessor_t* pre, term_table_t* terms, jmp_buf* handler, const mcsat_options_t* options) {
687✔
40
  pre->terms = terms;
687✔
41
  init_term_manager(&pre->tm, terms);
687✔
42
  init_int_hmap(&pre->preprocess_map, 0);
687✔
43
  init_ivector(&pre->preprocess_map_list, 0);
687✔
44
  init_int_hmap(&pre->purification_map, 0);
687✔
45
  init_ivector(&pre->purification_map_list, 0);
687✔
46
  init_ivector(&pre->preprocessing_stack, 0);
687✔
47
  init_int_hmap(&pre->equalities, 0);
687✔
48
  init_ivector(&pre->equalities_list, 0);
687✔
49
  pre->tracer = NULL;
687✔
50
  pre->exception = handler;
687✔
51
  pre->options = options;
687✔
52
  scope_holder_construct(&pre->scope);
687✔
53
}
687✔
54

55
void preprocessor_set_tracer(preprocessor_t* pre, tracer_t* tracer) {
284✔
56
  pre->tracer = tracer;
284✔
57
}
284✔
58

59
void preprocessor_destruct(preprocessor_t* pre) {
687✔
60
  delete_int_hmap(&pre->purification_map);
687✔
61
  delete_ivector(&pre->purification_map_list);
687✔
62
  delete_int_hmap(&pre->preprocess_map);
687✔
63
  delete_ivector(&pre->preprocess_map_list);
687✔
64
  delete_ivector(&pre->preprocessing_stack);
687✔
65
  delete_int_hmap(&pre->equalities);
687✔
66
  delete_ivector(&pre->equalities_list);
687✔
67
  delete_term_manager(&pre->tm);
687✔
68
  scope_holder_destruct(&pre->scope);
687✔
69
}
687✔
70

71
static
72
term_t preprocessor_get(preprocessor_t* pre, term_t t) {
1,601,101✔
73
  int_hmap_pair_t* find = int_hmap_find(&pre->preprocess_map, t);
1,601,101✔
74
  if (find == NULL) {
1,601,101✔
75
    return NULL_TERM;
867,873✔
76
  } else {
77
    return find->val;
733,228✔
78
  }
79
}
80

81
static
82
void preprocessor_set(preprocessor_t* pre, term_t t, term_t t_pre) {
336,180✔
83
  assert(preprocessor_get(pre, t) == NULL_TERM);
84
  int_hmap_add(&pre->preprocess_map, t, t_pre);
336,180✔
85
  ivector_push(&pre->preprocess_map_list, t);
336,180✔
86
}
336,180✔
87

88
typedef struct composite_term1_s {
89
  uint32_t arity;  // number of subterms
90
  term_t arg[1];  // real size = arity
91
} composite_term1_t;
92

93
static
94
composite_term1_t composite_for_noncomposite;
95

96
static
97
composite_term_t* get_composite(term_table_t* terms, term_kind_t kind, term_t t) {
207,492✔
98
  assert(term_is_composite(terms, t));
99
  assert(term_kind(terms, t) == kind);
100
  assert(is_pos_term(t));
101

102
  switch (kind) {
207,492✔
103
  case ITE_TERM:           // if-then-else
20,872✔
104
  case ITE_SPECIAL:        // special if-then-else term (NEW: EXPERIMENTAL)
105
    return ite_term_desc(terms, t);
20,872✔
106
  case EQ_TERM:            // equality
20,736✔
107
    return eq_term_desc(terms, t);
20,736✔
108
  case OR_TERM:            // n-ary OR
62,177✔
109
    return or_term_desc(terms, t);
62,177✔
110
  case XOR_TERM:           // n-ary XOR
30✔
111
    return xor_term_desc(terms, t);
30✔
112
  case ARITH_BINEQ_ATOM:   // equality: (t1 == t2)  (between two arithmetic terms)
4,082✔
113
    return arith_bineq_atom_desc(terms, t);
4,082✔
114
  case ARITH_EQ_ATOM: {
3,750✔
115
    composite_for_noncomposite.arity = 1;
3,750✔
116
    composite_for_noncomposite.arg[0] = arith_eq_arg(terms, t);
3,750✔
117
    return (composite_term_t*)&composite_for_noncomposite;
3,750✔
118
  }
119
  case ARITH_GE_ATOM: {
8,257✔
120
    composite_for_noncomposite.arity = 1;
8,257✔
121
    composite_for_noncomposite.arg[0] = arith_ge_arg(terms, t);
8,257✔
122
    return (composite_term_t*)&composite_for_noncomposite;
8,257✔
123
  }
124
  case ARITH_FF_BINEQ_ATOM:
12✔
125
    return arith_ff_bineq_atom_desc(terms, t);
12✔
126
  case ARITH_FF_EQ_ATOM: {
155✔
127
    composite_for_noncomposite.arity = 1;
155✔
128
    composite_for_noncomposite.arg[0] = arith_ff_eq_arg(terms, t);
155✔
129
    return (composite_term_t*)&composite_for_noncomposite;
155✔
130
  }
131
  case APP_TERM:           // application of an uninterpreted function
5,793✔
132
    return app_term_desc(terms, t);
5,793✔
133
  case ARITH_RDIV:          // division: (/ x y)
58✔
134
    return arith_rdiv_term_desc(terms, t);
58✔
135
  case ARITH_IDIV:          // division: (div x y) as defined in SMT-LIB 2
106✔
136
    return arith_idiv_term_desc(terms, t);
106✔
137
  case ARITH_MOD:          // remainder: (mod x y) is y - x * (div x y)
160✔
138
    return arith_mod_term_desc(terms, t);
160✔
139
  case UPDATE_TERM:
2,501✔
140
    return update_term_desc(terms, t);
2,501✔
141
  case DISTINCT_TERM:
27✔
142
    return distinct_term_desc(terms, t);
27✔
143
  case BV_ARRAY:
17,517✔
144
    return bvarray_term_desc(terms, t);
17,517✔
145
  case BV_DIV:
93✔
146
    return bvdiv_term_desc(terms, t);
93✔
147
  case BV_REM:
212✔
148
    return bvrem_term_desc(terms, t);
212✔
149
  case BV_SDIV:
20✔
150
    return bvsdiv_term_desc(terms, t);
20✔
151
  case BV_SREM:
21✔
152
    return bvsrem_term_desc(terms, t);
21✔
153
  case BV_SMOD:
6✔
154
    return bvsmod_term_desc(terms, t);
6✔
155
  case BV_SHL:
143✔
156
    return bvshl_term_desc(terms, t);
143✔
157
  case BV_LSHR:
279✔
158
    return bvlshr_term_desc(terms, t);
279✔
159
  case BV_ASHR:
21✔
160
    return bvashr_term_desc(terms, t);
21✔
161
  case BV_EQ_ATOM:
57,047✔
162
    return bveq_atom_desc(terms, t);
57,047✔
163
  case BV_GE_ATOM:
2,775✔
164
    return bvge_atom_desc(terms, t);
2,775✔
165
  case BV_SGE_ATOM:
642✔
166
    return bvsge_atom_desc(terms, t);
642✔
167
  default:
×
168
    assert(false);
169
    return NULL;
×
170
  }
171
}
172

173
static bool type_needs_function_diseq_guard(type_table_t* types, type_t tau) {
24,765✔
174
  uint32_t i, n;
175

176
  switch (type_kind(types, tau)) {
24,765✔
177
  case FUNCTION_TYPE:
1,973✔
178
    if (type_has_finite_domain(types, tau) ||
3,936✔
179
        is_unit_type(types, function_type_range(types, tau))) {
1,963✔
180
      return true;
11✔
181
    }
182

183
    n = function_type_arity(types, tau);
1,962✔
184
    for (i = 0; i < n; ++ i) {
3,928✔
185
      if (type_needs_function_diseq_guard(types, function_type_domain(types, tau, i))) {
1,968✔
186
        return true;
2✔
187
      }
188
    }
189

190
    return type_needs_function_diseq_guard(types, function_type_range(types, tau));
1,960✔
191

NEW
192
  case TUPLE_TYPE:
×
NEW
193
    n = tuple_type_arity(types, tau);
×
NEW
194
    for (i = 0; i < n; ++ i) {
×
NEW
195
      if (type_needs_function_diseq_guard(types, tuple_type_component(types, tau, i))) {
×
NEW
196
        return true;
×
197
      }
198
    }
NEW
199
    return false;
×
200

NEW
201
  case INSTANCE_TYPE:
×
NEW
202
    n = instance_type_arity(types, tau);
×
NEW
203
    for (i = 0; i < n; ++ i) {
×
NEW
204
      if (type_needs_function_diseq_guard(types, instance_type_param(types, tau, i))) {
×
NEW
205
        return true;
×
206
      }
207
    }
NEW
208
    return false;
×
209

210
  default:
22,792✔
211
    return false;
22,792✔
212
  }
213
}
214

215
static bool term_needs_function_diseq_guard(term_table_t* terms, term_t t) {
20,837✔
216
  return type_needs_function_diseq_guard(terms->types, term_type(terms, t));
20,837✔
217
}
218

219
static
220
term_t mk_composite(preprocessor_t* pre, term_kind_t kind, uint32_t n, term_t* children) {
46,532✔
221
  term_manager_t* tm = &pre->tm;
46,532✔
222
  term_table_t* terms = pre->terms;
46,532✔
223

224
  switch (kind) {
46,532✔
225
  case ITE_TERM:           // if-then-else
12,893✔
226
  case ITE_SPECIAL:        // special if-then-else term (NEW: EXPERIMENTAL)
227
  {
228
    assert(n == 3);
229
    term_t type = super_type(pre->terms->types, term_type(terms, children[1]), term_type(terms, children[2]));
12,893✔
230
    assert(type != NULL_TYPE);
231
    return mk_ite(tm, children[0], children[1], children[2], type);
12,893✔
232
  }
233
  case EQ_TERM:            // equality
3,577✔
234
    assert(n == 2);
235
    return mk_eq(tm, children[0], children[1]);
3,577✔
236
  case OR_TERM:            // n-ary OR
12,110✔
237
    assert(n > 1);
238
    return mk_or(tm, n, children);
12,110✔
239
  case XOR_TERM:           // n-ary XOR
3✔
240
    return mk_xor(tm, n, children);
3✔
241
  case ARITH_EQ_ATOM:
63✔
242
    assert(n == 1);
243
    return mk_arith_eq(tm, children[0], zero_term);
63✔
244
  case ARITH_GE_ATOM:
414✔
245
    assert(n == 1);
246
    return mk_arith_geq(tm, children[0], zero_term);
414✔
247
  case ARITH_BINEQ_ATOM:   // equality: (t1 == t2)  (between two arithmetic terms)
214✔
248
    assert(n == 2);
249
    return mk_arith_eq(tm, children[0], children[1]);
214✔
250
  case APP_TERM:           // application of an uninterpreted function
861✔
251
    assert(n > 1);
252
    return mk_application(tm, children[0], n-1, children + 1);
861✔
253
  case ARITH_RDIV:
21✔
254
    assert(n == 2);
255
    return mk_arith_rdiv(tm, children[0], children[1]);
21✔
256
  case ARITH_IDIV:          // division: (div x y) as defined in SMT-LIB 2
19✔
257
    assert(n == 2);
258
    return mk_arith_idiv(tm, children[0], children[1]);
19✔
259
  case ARITH_MOD:          // remainder: (mod x y) is y - x * (div x y)
21✔
260
    assert(n == 2);
261
    return mk_arith_mod(tm, children[0], children[1]);
21✔
262
  case UPDATE_TERM:
497✔
263
    assert(n > 2);
264
    return mk_update(tm, children[0], n-2, children + 1, children[n-1]);
497✔
265
  case BV_ARRAY:
6,955✔
266
    assert(n >= 1);
267
    return mk_bvarray(tm, n, children);
6,955✔
268
  case BV_DIV:
63✔
269
    assert(n == 2);
270
    return mk_bvdiv(tm, children[0], children[1]);
63✔
271
  case BV_REM:
18✔
272
    assert(n == 2);
273
    return mk_bvrem(tm, children[0], children[1]);
18✔
274
  case BV_SDIV:
×
275
    assert(n == 2);
276
    return mk_bvsdiv(tm, children[0], children[1]);
×
277
  case BV_SREM:
×
278
    assert(n == 2);
279
    return mk_bvsrem(tm, children[0], children[1]);
×
280
  case BV_SMOD:
2✔
281
    assert(n == 2);
282
    return mk_bvsmod(tm, children[0], children[1]);
2✔
283
  case BV_SHL:
108✔
284
    assert(n == 2);
285
    return mk_bvshl(tm, children[0], children[1]);
108✔
286
  case BV_LSHR:
135✔
287
    assert(n == 2);
288
    return mk_bvlshr(tm, children[0], children[1]);
135✔
289
  case BV_ASHR:
3✔
290
    assert(n == 2);
291
    return mk_bvashr(tm, children[0], children[1]);
3✔
292
  case BV_EQ_ATOM:
6,477✔
293
    assert(n == 2);
294
    return mk_bveq(tm, children[0], children[1]);
6,477✔
295
  case BV_GE_ATOM:
1,797✔
296
    assert(n == 2);
297
    return mk_bvge(tm, children[0], children[1]);
1,797✔
298
  case BV_SGE_ATOM:
281✔
299
    assert(n == 2);
300
    return mk_bvsge(tm, children[0], children[1]);
281✔
301
  default:
×
302
    assert(false);
303
    return NULL_TERM;
×
304
  }
305
}
306

307
/**
308
 * Returns purified version of t if we should purify t as an argument of a function.
309
 * Any new equalities are added to output.
310
 */
311
static inline
312
term_t preprocessor_purify(preprocessor_t* pre, term_t t, ivector_t* out) {
52,754✔
313

314
  term_table_t* terms = pre->terms;
52,754✔
315

316
  // Negated terms must be purified
317
  if (is_pos_term(t)) {
52,754✔
318
    // We don't purify variables
319
    switch (term_kind(terms, t)) {
17,000✔
320
    case UNINTERPRETED_TERM:
10,785✔
321
      // Variables are already pure
322
      return t;
10,785✔
323
    case CONSTANT_TERM:
15✔
324
      return t;
15✔
325
    case ARITH_CONSTANT:
1,669✔
326
    case ARITH_FF_CONSTANT:
327
    case BV64_CONSTANT:
328
    case BV_CONSTANT:
329
      // Constants are also pure (except for false)
330
      return t;
1,669✔
331
    case APP_TERM:
1,685✔
332
      // Uninterpreted functions are also already purified
333
      return t;
1,685✔
334
    case UPDATE_TERM:
1,680✔
335
      return t;
1,680✔
336
    default:
1,166✔
337
      break;
1,166✔
338
    }
339
  }
340

341
  // Everything else gets purified. Check if in the cache
342
  int_hmap_pair_t* find = int_hmap_find(&pre->purification_map, t);
36,920✔
343
  if (find != NULL) {
36,920✔
344
    return find->val;
36,362✔
345
  } else {
346
    // Make the variable
347
    type_t t_type = term_type(terms, t);
558✔
348
    term_t x = new_uninterpreted_term(terms, t_type);
558✔
349
    // Remember for later
350
    int_hmap_add(&pre->purification_map, t, x);
558✔
351
    ivector_push(&pre->purification_map_list, t);
558✔
352
    // Also add the variable to the pre-processor
353
    preprocessor_set(pre, x, x);
558✔
354
    // Add equality to output
355
    term_t eq = mk_eq(&pre->tm, x, t);
558✔
356
    ivector_push(out, eq);
558✔
357

358
    if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
558✔
359
      mcsat_trace_printf(pre->tracer, "adding lemma = ");
×
360
      trace_term_ln(pre->tracer, terms, eq);
×
361
    }
362

363
    // Return the purified version
364
    return x;
558✔
365
  }
366
}
367

368
static inline
369
term_t mk_bvneg(term_manager_t* tm, term_t t) {
92✔
370
  term_table_t* terms = tm->terms;
92✔
371
  if (term_bitsize(terms,t) <= 64) {
92✔
372
    bvarith64_buffer_t *buffer = term_manager_get_bvarith64_buffer(tm);
76✔
373
    bvarith64_buffer_set_term(buffer, terms, t);
76✔
374
    bvarith64_buffer_negate(buffer);
76✔
375
    return mk_bvarith64_term(tm, buffer);
76✔
376
  } else {
377
    bvarith_buffer_t *buffer = term_manager_get_bvarith_buffer(tm);
16✔
378
    bvarith_buffer_set_term(buffer, terms, t);
16✔
379
    bvarith_buffer_negate(buffer);
16✔
380
    return mk_bvarith_term(tm, buffer);
16✔
381
  }
382
}
383

384
// Mark equality eq: (var = t) for solving
385
static
386
void preprocessor_mark_eq(preprocessor_t* pre, term_t eq, term_t var) {
24,843✔
387
  assert(is_pos_term(eq));
388
  assert(is_pos_term(var));
389
  assert(term_kind(pre->terms, var) == UNINTERPRETED_TERM);
390

391
  // Mark the equality
392
  int_hmap_pair_t* find = int_hmap_get(&pre->equalities, eq);
24,843✔
393
  assert(find->val == -1);
394
  find->val = var;
24,843✔
395
  ivector_push(&pre->equalities_list, eq);
24,843✔
396
}
24,843✔
397

398
static
399
term_t preprocessor_get_eq_solved_var(const preprocessor_t* pre, term_t eq) {
47,613✔
400
  assert(is_pos_term(eq));
401
  int_hmap_pair_t* find = int_hmap_find((int_hmap_t*) &pre->equalities, eq);
47,613✔
402
  if (find != NULL) {
47,613✔
403
    return find->val;
19,964✔
404
  } else {
405
    return NULL_TERM;
27,649✔
406
  }
407
}
408

409
term_t preprocessor_apply(preprocessor_t* pre, term_t t, ivector_t* out, bool is_assertion) {
39,747✔
410

411
  term_table_t* terms = pre->terms;
39,747✔
412
  term_manager_t* tm = &pre->tm;
39,747✔
413

414
  uint32_t i, j, n;
415

416
  // Check if already preprocessed;
417
  term_t t_pre = preprocessor_get(pre, t);
39,747✔
418
  if (t_pre != NULL_TERM) {
39,747✔
419
    return t_pre;
1,636✔
420
  }
421

422
// Note: negative affect on general performance due to solved/substituted
423
//       terms being to complex for explainers.
424
//
425
//  // First, if the assertion is a conjunction, just expand
426
//  if (is_assertion && is_neg_term(t) && term_kind(terms, t) == OR_TERM) {
427
//    // !(or t1 ... tn) -> !t1 && ... && !tn
428
//    composite_term_t* t_desc = composite_term_desc(terms, t);
429
//    for (i = 0; i < t_desc->arity; ++ i) {
430
//      ivector_push(out, opposite_term(t_desc->arg[i]));
431
//    }
432
//    return true_term;
433
//  }
434
//
435
  // Start
436
  ivector_t* pre_stack = &pre->preprocessing_stack;
38,111✔
437
  ivector_reset(pre_stack);
38,111✔
438
  ivector_push(pre_stack, t);
38,111✔
439

440
  // Preprocess
441
  while (pre_stack->size) {
505,617✔
442
    // Current term
443
    term_t current = ivector_last(pre_stack);
467,517✔
444

445
    if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
467,517✔
446
      mcsat_trace_printf(pre->tracer, "current = ");
×
447
      trace_term_ln(pre->tracer, terms, current);
×
448
    }
449

450
    // If preprocessed already, done
451
    term_t current_pre = preprocessor_get(pre, current);
467,517✔
452
    if (current_pre != NULL_TERM) {
467,517✔
453
      ivector_pop(pre_stack);
31,304✔
454
      continue;
31,304✔
455
    }
456

457
    // Negation
458
    if (is_neg_term(current)) {
436,213✔
459
      term_t child = unsigned_term(current);
88,828✔
460
      term_t child_pre = preprocessor_get(pre, child);
88,828✔
461
      if (child_pre == NULL_TERM) {
88,828✔
462
        ivector_push(pre_stack, child);
41,949✔
463
        continue;
41,949✔
464
      } else {
465
        ivector_pop(pre_stack);
46,879✔
466
        current_pre = opposite_term(child_pre);
46,879✔
467
        preprocessor_set(pre, current, current_pre);
46,879✔
468
        continue;
46,879✔
469
      }
470
    }
471

472
    // Check for supported types
473
    type_kind_t type = term_type_kind(terms, current);
347,385✔
474
    switch (type) {
347,385✔
475
    case BOOL_TYPE:
347,385✔
476
    case INT_TYPE:
477
    case REAL_TYPE:
478
    case FF_TYPE:
479
    case UNINTERPRETED_TYPE:
480
    case FUNCTION_TYPE:
481
    case BITVECTOR_TYPE:
482
    case SCALAR_TYPE:
483
      break;
347,385✔
484
    default:
×
485
      longjmp(*pre->exception, MCSAT_EXCEPTION_UNSUPPORTED_THEORY);
×
486
    }
487

488
    // Kind of term
489
    term_kind_t current_kind = term_kind(terms, current);
347,385✔
490

491
    switch(current_kind) {
347,385✔
492
    case CONSTANT_TERM:    // constant of uninterpreted/scalar/boolean types
1,782✔
493
    case BV64_CONSTANT:    // compact bitvector constant (64 bits at most)
494
    case BV_CONSTANT:      // generic bitvector constant (more than 64 bits)
495
    case ARITH_CONSTANT:   // rational constant
496
    case ARITH_FF_CONSTANT:   // finite field constant
497
      current_pre = current;
1,782✔
498
      break;
1,782✔
499

500
    case UNINTERPRETED_TERM:  // (i.e., global variables, can't be bound).
14,005✔
501
      current_pre = current;
14,005✔
502
      // Unless we want special slicing
503
      if (type == BITVECTOR_TYPE) {
14,005✔
504
        if (pre->options->bv_var_size > 0) {
4,236✔
505
          uint32_t size = term_bitsize(terms, current);
23✔
506
          uint32_t var_size = pre->options->bv_var_size;
23✔
507
          if (size > var_size) {
23✔
508
            uint32_t n_vars = (size - 1) / var_size + 1;
2✔
509
            term_t vars[n_vars];
2✔
510
            for (i = n_vars - 1; size > 0; i--) {
8✔
511
              if (size >= var_size) {
6✔
512
                vars[i] = new_uninterpreted_term(terms, bv_type(terms->types, var_size));
4✔
513
                size -= var_size;
4✔
514
              } else {
515
                vars[i] = new_uninterpreted_term(terms, bv_type(terms->types, size));
2✔
516
                size = 0;
2✔
517
              }
518
            }
519
            current_pre = _o_yices_bvconcat(n_vars, vars);
2✔
520
            term_t eq = _o_yices_eq(current, current_pre);
2✔
521
            preprocessor_mark_eq(pre, eq, current);
2✔
522
          }
523
        }
524
      }
525
      break;
14,005✔
526

527
    case ITE_TERM:           // if-then-else
181,286✔
528
    case ITE_SPECIAL:        // special if-then-else term (NEW: EXPERIMENTAL)
529
    case EQ_TERM:            // equality
530
    case OR_TERM:            // n-ary OR
531
    case XOR_TERM:           // n-ary XOR
532
    case ARITH_EQ_ATOM:      // equality (t == 0)
533
    case ARITH_BINEQ_ATOM:   // equality (t1 == t2)  (between two arithmetic terms)
534
    case ARITH_GE_ATOM:      // inequality (t >= 0)
535
    case ARITH_FF_EQ_ATOM:   // finite field equality (t == 0)
536
    case ARITH_FF_BINEQ_ATOM: // finite field equality (t1 == t2)  (between two arithmetic terms)
537
    case BV_DIV:
538
    case BV_REM:
539
    case BV_SMOD:
540
    case BV_SHL:
541
    case BV_LSHR:
542
    case BV_ASHR:
543
    case BV_EQ_ATOM:
544
    case BV_GE_ATOM:
545
    case BV_SGE_ATOM:
546
    {
547
      composite_term_t* desc = get_composite(terms, current_kind, current);
181,286✔
548
      bool children_done = true;
181,286✔
549
      bool children_same = true;
181,286✔
550

551
      n = desc->arity;
181,286✔
552

553
      // MCSAT does not yet enforce all extensionality/cardinality constraints
554
      // for function-sort disequalities. Reject equality atoms whose type needs
555
      // that monitoring; the Boolean abstraction may assert them either way.
556
      if (current_kind == EQ_TERM && term_needs_function_diseq_guard(terms, desc->arg[0])) {
181,286✔
557
        longjmp(*pre->exception, MCSAT_EXCEPTION_UNSUPPORTED_THEORY);
8✔
558
      }
559

560
      // Is this a top-level equality assertion
561
      bool is_equality =
181,278✔
562
          current_kind == EQ_TERM ||
160,550✔
563
          current_kind == BV_EQ_ATOM ||
103,503✔
564
          current_kind == ARITH_EQ_ATOM ||
99,755✔
565
          current_kind == ARITH_BINEQ_ATOM ||
95,674✔
566
          current_kind == ARITH_FF_EQ_ATOM ||
341,828✔
567
          current_kind == ARITH_FF_BINEQ_ATOM;
568
      // don't rewrite if the equality is between Boolean terms
569
      bool is_boolean = is_boolean_type(term_type(pre->terms, desc->arg[0]));
181,278✔
570

571
      term_t eq_solve_var = NULL_TERM;
181,278✔
572
      if (is_assertion && is_equality && !is_boolean) {
181,278✔
573
        bool is_lhs_rhs_mixed = desc->arity > 1 &&
139,355✔
574
          term_type_kind(pre->terms, desc->arg[0]) != term_type_kind(pre->terms, desc->arg[1]);
67,726✔
575
        // don't rewrite if equality is between mixed terms, e.g. between int and real terms
576
        if (!is_lhs_rhs_mixed && current == t) {
71,629✔
577
          eq_solve_var = preprocessor_get_eq_solved_var(pre, t);
47,610✔
578
          if (eq_solve_var == NULL_TERM) {
47,610✔
579
            term_t lhs = desc->arg[0];
27,649✔
580
            term_kind_t lhs_kind = term_kind(terms, lhs);
27,649✔
581
            // If lhs/rhs is a first-time seen variable, we can solve it
582
            bool lhs_is_var = lhs_kind == UNINTERPRETED_TERM && is_pos_term(lhs);
27,649✔
583
            if (lhs_is_var && preprocessor_get(pre, lhs) == NULL_TERM) {
27,649✔
584
              // First time variable, let's solve
585
              preprocessor_mark_eq(pre, t, lhs);
24,586✔
586
              eq_solve_var = lhs;
24,586✔
587
            } else if (desc->arity > 1) {
3,063✔
588
              term_t rhs = desc->arg[1];
2,303✔
589
              term_kind_t rhs_kind = term_kind(terms, rhs);
2,303✔
590
              bool rhs_is_var = rhs_kind == UNINTERPRETED_TERM && is_pos_term(rhs);
2,303✔
591
              if (rhs_is_var && preprocessor_get(pre, rhs) == NULL_TERM) {
2,303✔
592
                // First time variable, let's solve
593
                preprocessor_mark_eq(pre, t, rhs);
255✔
594
                eq_solve_var = rhs;
255✔
595
              }
596
            }
597
          } else {
598
            // Check that we it's not there already
599
            if (preprocessor_get(pre, eq_solve_var) != NULL_TERM) {
19,961✔
600
              eq_solve_var = NULL_TERM;
51✔
601
            }
602
          }
603
        }
604
      }
605

606
      ivector_t children;
607
      init_ivector(&children, n);
181,278✔
608

609
      for (i = 0; i < n; ++ i) {
604,692✔
610
        term_t child = desc->arg[i];
423,414✔
611
        if (child != eq_solve_var) {
423,414✔
612
          term_t child_pre = preprocessor_get(pre, child);
378,663✔
613
          if (child_pre == NULL_TERM) {
378,663✔
614
            children_done = false;
108,498✔
615
            ivector_push(pre_stack, child);
108,498✔
616
          } else if (child_pre != child) {
270,165✔
617
            children_same = false;
106,029✔
618
          }
619
          if (children_done) {
378,663✔
620
            ivector_push(&children, child_pre);
256,322✔
621
          }
622
        }
623
      }
624

625
      if (eq_solve_var != NULL_TERM) {
181,278✔
626
        // Check again to make sure we don't have something like x = x + 1
627
        if (preprocessor_get(pre, eq_solve_var) != NULL_TERM) {
44,751✔
628
          // Do it again
629
          children_done = false;
×
630
        }
631
      }
632

633
      if (children_done) {
181,278✔
634
        if (eq_solve_var != NULL_TERM) {
113,384✔
635
          term_t eq_solve_term = zero_term;
24,790✔
636
          if (children.size > 0) {
24,790✔
637
            eq_solve_term = children.data[0];
24,752✔
638
          }
639
          preprocessor_set(pre, eq_solve_var, eq_solve_term);
24,790✔
640
          current_pre = true_term;
24,790✔
641
        } else {
642
          if (children_same) {
88,594✔
643
            current_pre = current;
50,436✔
644
          } else {
645
            current_pre = mk_composite(pre, current_kind, n, children.data);
38,158✔
646
          }
647
        }
648
      }
649

650
      delete_ivector(&children);
181,278✔
651

652
      break;
181,278✔
653
    }
654

655
    case BV_ARRAY:
17,517✔
656
    {
657
      composite_term_t* desc = get_composite(terms, current_kind, current);
17,517✔
658
      bool children_done = true;
17,517✔
659
      bool children_same = true;
17,517✔
660

661
      n = desc->arity;
17,517✔
662

663
      ivector_t children;
664
      init_ivector(&children, n);
17,517✔
665

666
      for (i = 0; i < n; ++ i) {
353,534✔
667
        term_t child = desc->arg[i];
336,017✔
668
        term_t child_pre = preprocessor_get(pre, child);
336,017✔
669
        if (child_pre == NULL_TERM) {
336,017✔
670
          children_done = false;
143,211✔
671
          ivector_push(pre_stack, child);
143,211✔
672
        } else {
673
          if (is_arithmetic_literal(terms, child_pre) || child_pre == false_term) {
192,806✔
674
            // purify if arithmetic literal, i.e. a = 0 where a is of integer type
675
            child_pre = preprocessor_purify(pre, child_pre, out);
35,723✔
676
          }
677
          if (child_pre != child) {
192,806✔
678
            children_same = false;
110,041✔
679
          }
680
        }
681
        if (children_done) {
336,017✔
682
          ivector_push(&children, child_pre);
179,684✔
683
        }
684
      }
685

686
      if (children_done) {
17,517✔
687
        if (children_same) {
9,165✔
688
          current_pre = current;
2,210✔
689
        } else {
690
          current_pre = mk_composite(pre, current_kind, n, children.data);
6,955✔
691
        }
692
      }
693

694
      delete_ivector(&children);
17,517✔
695

696
      break;
17,517✔
697
    }
698

699
    case ARITH_ABS:
8✔
700
    {
701
      term_t arg = arith_abs_arg(terms, current);
8✔
702
      term_t arg_pre = preprocessor_get(pre, arg);
8✔
703
      if (arg_pre == NULL_TERM) {
8✔
704
        ivector_push(pre_stack, arg);
3✔
705
      } else {
706
        type_t arg_pre_type = term_type(pre->terms, arg_pre);
5✔
707
        term_t arg_pre_is_positive = mk_arith_term_geq0(&pre->tm, arg_pre);
5✔
708
        term_t arg_negative = _o_yices_neg(arg_pre);
5✔
709
        current_pre = mk_ite(&pre->tm, arg_pre_is_positive, arg_pre, arg_negative, arg_pre_type);
5✔
710
      }
711
      break;
8✔
712
    }
713

714
    case BV_SDIV:
20✔
715
    {
716
      composite_term_t* desc = get_composite(terms, current_kind, current);
20✔
717
      assert(desc->arity == 2);
718
      term_t s = desc->arg[0];
20✔
719
      term_t s_pre = preprocessor_get(pre, s);
20✔
720
      if (s_pre == NULL_TERM) {
20✔
721
        ivector_push(pre_stack, s);
7✔
722
      }
723
      term_t t = desc->arg[1];
20✔
724
      term_t t_pre = preprocessor_get(pre, t);
20✔
725
      if (t_pre == NULL_TERM) {
20✔
726
        ivector_push(pre_stack, t);
5✔
727
      }
728
      if (s_pre != NULL_TERM && t_pre != NULL_TERM) {
20✔
729
        type_t tau = term_type(terms, s_pre);
11✔
730
        uint32_t n = term_bitsize(terms, s_pre);
11✔
731
        term_t msb_s = mk_bitextract(tm, s_pre, n-1);
11✔
732
        term_t msb_t = mk_bitextract(tm, t_pre, n-1);
11✔
733
        // if (msb_s) {
734
        //   if (msb_t) {
735
        //     t1: udiv(-s, -t)
736
        //   } else {
737
        //     t2: -udiv(-s, t)
738
        //   }
739
        // } else {
740
        //   if (msb_t) {
741
        //     t3: -udiv(s, -t)
742
        //   } else {
743
        //     t4: udiv(s, t)
744
        //   }
745
        // }
746
        term_t neg_s = mk_bvneg(tm, s_pre);
11✔
747
        term_t neg_t = mk_bvneg(tm, t_pre);
11✔
748

749
        term_t t1 = mk_bvdiv(tm, neg_s, neg_t);
11✔
750
        term_t t2 = mk_bvdiv(tm, neg_s, t_pre);
11✔
751
        t2 = mk_bvneg(&pre->tm, t2);
11✔
752
        term_t t3 = mk_bvdiv(tm, s_pre, neg_t);
11✔
753
        t3 = mk_bvneg(&pre->tm, t3);
11✔
754
        term_t t4 = mk_bvdiv(tm, s_pre, t_pre);
11✔
755

756
        term_t b1 = mk_ite(tm, msb_t, t1, t2, tau);
11✔
757
        term_t b2 = mk_ite(tm, msb_t, t3, t4, tau);
11✔
758

759
        current_pre = mk_ite(tm, msb_s, b1, b2, tau);
11✔
760
      }
761
      break;
20✔
762
    }
763
    case BV_SREM:
21✔
764
    {
765
      composite_term_t* desc = get_composite(terms, current_kind, current);
21✔
766
      assert(desc->arity == 2);
767
      term_t s = desc->arg[0];
21✔
768
      term_t s_pre = preprocessor_get(pre, s);
21✔
769
      if (s_pre == NULL_TERM) {
21✔
770
        ivector_push(pre_stack, s);
8✔
771
      }
772
      term_t t = desc->arg[1];
21✔
773
      term_t t_pre = preprocessor_get(pre, t);
21✔
774
      if (t_pre == NULL_TERM) {
21✔
775
        ivector_push(pre_stack, t);
3✔
776
      }
777
      if (s_pre != NULL_TERM && t_pre != NULL_TERM) {
21✔
778
        type_t tau = term_type(terms, s_pre);
12✔
779
        uint32_t n = term_bitsize(terms, s_pre);
12✔
780
        term_t msb_s = mk_bitextract(tm, s_pre, n-1);
12✔
781
        term_t msb_t = mk_bitextract(tm, t_pre, n-1);
12✔
782
        // if (msb_s) {
783
        //   if (msb_t) {
784
        //     t1: -urem(-s, -t)
785
        //   } else {
786
        //     t2: -urem(-s, t)
787
        //   }
788
        // } else {
789
        //   if (msb_t) {
790
        //     t3: -urem(s, -t)
791
        //   } else {
792
        //     t4: urem(s, t)
793
        //   }
794
        // }
795
        term_t neg_s = mk_bvneg(tm, s_pre);
12✔
796
        term_t neg_t = mk_bvneg(tm, t_pre);
12✔
797

798
        term_t t1 = mk_bvrem(tm, neg_s, neg_t);
12✔
799
        t1 = mk_bvneg(tm, t1);
12✔
800
        term_t t2 = mk_bvrem(tm, neg_s, t_pre);
12✔
801
        t2 = mk_bvneg(tm, t2);
12✔
802
        term_t t3 = mk_bvrem(tm, s_pre, neg_t);
12✔
803
        term_t t4 = mk_bvrem(tm, s_pre, t_pre);
12✔
804

805
        term_t b1 = mk_ite(tm, msb_t, t1, t2, tau);
12✔
806
        term_t b2 = mk_ite(tm, msb_t, t3, t4, tau);
12✔
807

808
        current_pre = mk_ite(tm, msb_s, b1, b2, tau);
12✔
809
      }
810
      break;
21✔
811
    }
812
    case BIT_TERM: // bit-select current = child[i]
112,741✔
813
    {
814
      uint32_t index = bit_term_index(terms, current);
112,741✔
815
      term_t arg = bit_term_arg(terms, current);
112,741✔
816
      term_t arg_pre = preprocessor_get(pre, arg);
112,741✔
817
      if (arg_pre == NULL_TERM) {
112,741✔
818
        ivector_push(pre_stack, arg);
1,584✔
819
      } else {
820
        if (arg_pre == arg) {
111,157✔
821
          current_pre = current;
73,115✔
822
        } else {
823
          if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
38,042✔
824
            mcsat_trace_printf(pre->tracer, "arg_pre = ");
×
825
            trace_term_ln(pre->tracer, terms, arg_pre);
×
826
          }
827
          // For simplification purposes use API
828
          current_pre = _o_yices_bitextract(arg_pre, index);
38,042✔
829
          assert(current_pre != NULL_TERM);
830
        }
831
      }
832
      break;
112,741✔
833
    }
834
    case BV_POLY:  // polynomial with generic bitvector coefficients
33✔
835
    {
836
      bvpoly_t* p = bvpoly_term_desc(terms, current);
33✔
837

838
      bool children_done = true;
33✔
839
      bool children_same = true;
33✔
840

841
      n = p->nterms;
33✔
842

843
      ivector_t children;
844
      init_ivector(&children, n);
33✔
845

846
      for (i = 0; i < n; ++ i) {
84✔
847
        term_t x = p->mono[i].var;
51✔
848
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
51✔
849

850
        if (x_pre != const_idx) {
51✔
851
          if (x_pre == NULL_TERM) {
47✔
852
            children_done = false;
10✔
853
            ivector_push(pre_stack, x);
10✔
854
          } else if (x_pre != x) {
37✔
855
            children_same = false;
23✔
856
          }
857
        }
858

859
        if (children_done) { ivector_push(&children, x_pre); }
51✔
860
      }
861

862
      if (children_done) {
33✔
863
        if (children_same) {
26✔
864
          current_pre = current;
11✔
865
        } else {
866
          current_pre = mk_bvarith_poly(tm, p, n, children.data);
15✔
867
        }
868
      }
869

870
      delete_ivector(&children);
33✔
871

872
      break;
33✔
873
    }
874
    case BV64_POLY: // polynomial with 64bit coefficients
2,571✔
875
    {
876
      bvpoly64_t* p = bvpoly64_term_desc(terms, current);
2,571✔
877

878
      bool children_done = true;
2,571✔
879
      bool children_same = true;
2,571✔
880

881
      n = p->nterms;
2,571✔
882

883
      ivector_t children;
884
      init_ivector(&children, n);
2,571✔
885

886
      for (i = 0; i < n; ++ i) {
9,821✔
887
        term_t x = p->mono[i].var;
7,250✔
888
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
7,250✔
889

890
        if (x_pre != const_idx) {
7,250✔
891
          if (x_pre == NULL_TERM) {
5,578✔
892
            children_done = false;
1,308✔
893
            ivector_push(pre_stack, x);
1,308✔
894
          } else if (x_pre != x) {
4,270✔
895
            children_same = false;
3,566✔
896
          }
897
        }
898

899
        if (children_done) { ivector_push(&children, x_pre); }
7,250✔
900
      }
901

902
      if (children_done) {
2,571✔
903
        if (children_same) {
1,870✔
904
          current_pre = current;
279✔
905
        } else {
906
          current_pre = mk_bvarith64_poly(tm, p, n, children.data);
1,591✔
907
        }
908
      }
909

910
      delete_ivector(&children);
2,571✔
911

912
      break;
2,571✔
913
    }
914

915
    case POWER_PRODUCT:    // power products: (t1^d1 * ... * t_n^d_n)
1,673✔
916
    {
917
      pprod_t* pp = pprod_term_desc(terms, current);
1,673✔
918
      bool children_done = true;
1,673✔
919
      bool children_same = true;
1,673✔
920

921
      n = pp->len;
1,673✔
922

923
      ivector_t children;
924
      init_ivector(&children, n);
1,673✔
925

926
      for (i = 0; i < n; ++ i) {
5,310✔
927
        term_t x = pp->prod[i].var;
3,637✔
928
        term_t x_pre = preprocessor_get(pre, x);
3,637✔
929

930
        if (x_pre == NULL_TERM) {
3,637✔
931
          children_done = false;
452✔
932
          ivector_push(pre_stack, x);
452✔
933
        } else if (x_pre != x) {
3,185✔
934
          children_same = false;
92✔
935
        }
936

937
        if (children_done) { ivector_push(&children, x_pre); }
3,637✔
938
      }
939

940
      if (children_done) {
1,673✔
941
        if (children_same) {
1,337✔
942
          current_pre = current;
1,281✔
943
        } else {
944
          // NOTE: it doens't change pp, it just uses it as a frame
945
          current_pre = mk_pprod(tm, pp, n, children.data);
56✔
946
        }
947
      }
948

949
      delete_ivector(&children);
1,673✔
950

951
      break;
1,673✔
952
    }
953

954
    case ARITH_POLY:       // polynomial with rational coefficients
6,926✔
955
    {
956
      polynomial_t* p = poly_term_desc(terms, current);
6,926✔
957

958
      bool children_done = true;
6,926✔
959
      bool children_same = true;
6,926✔
960

961
      n = p->nterms;
6,926✔
962

963
      ivector_t children;
964
      init_ivector(&children, n);
6,926✔
965

966
      for (i = 0; i < n; ++ i) {
26,821✔
967
        term_t x = p->mono[i].var;
19,895✔
968
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
19,895✔
969

970
        if (x_pre != const_idx) {
19,895✔
971
          if (x_pre == NULL_TERM) {
16,879✔
972
            children_done = false;
2,566✔
973
            ivector_push(pre_stack, x);
2,566✔
974
          } else if (x_pre != x) {
14,313✔
975
            children_same = false;
933✔
976
          }
977
        }
978

979
        if (children_done) { ivector_push(&children, x_pre); }
19,895✔
980
      }
981

982
      if (children_done) {
6,926✔
983
        if (children_same) {
5,476✔
984
          current_pre = current;
4,884✔
985
        } else {
986
          current_pre = mk_arith_poly(tm, p, n, children.data);
592✔
987
        }
988
      }
989

990
      delete_ivector(&children);
6,926✔
991

992
      break;
6,926✔
993
    }
994

995
    case ARITH_FF_POLY:    // polynomial with finite field coefficients
150✔
996
    {
997
      polynomial_t* p = finitefield_poly_term_desc(terms, current);
150✔
998
      const rational_t *mod = finitefield_term_order(terms, current);
150✔
999

1000
      bool children_done = true;
150✔
1001
      bool children_same = true;
150✔
1002

1003
      n = p->nterms;
150✔
1004

1005
      ivector_t children;
1006
      init_ivector(&children, n);
150✔
1007

1008
      for (i = 0; i < n; ++ i) {
1,068✔
1009
        term_t x = p->mono[i].var;
918✔
1010
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
918✔
1011

1012
        if (x_pre != const_idx) {
918✔
1013
          if (x_pre == NULL_TERM) {
864✔
1014
            children_done = false;
380✔
1015
            ivector_push(pre_stack, x);
380✔
1016
          } else if (x_pre != x) {
484✔
1017
            children_same = false;
×
1018
          }
1019
        }
1020

1021
        if (children_done) { ivector_push(&children, x_pre); }
918✔
1022
      }
1023

1024
      if (children_done) {
150✔
1025
        if (children_same) {
75✔
1026
          current_pre = current;
75✔
1027
        } else {
1028
          current_pre = mk_arith_ff_poly(tm, p, n, children.data, mod);
×
1029
        }
1030
      }
1031

1032
      delete_ivector(&children);
150✔
1033

1034
      break;
150✔
1035
    }
1036

1037
    // FOLLOWING ARE UNINTEPRETED, SO WE PURIFY THE ARGUMENTS
1038

1039
    case APP_TERM:           // application of an uninterpreted function
8,618✔
1040
    case ARITH_RDIV:         // regular division (/ x y)
1041
    case ARITH_IDIV:         // division: (div x y) as defined in SMT-LIB 2
1042
    case ARITH_MOD:          // remainder: (mod x y) is y - x * (div x y)
1043
    case UPDATE_TERM:        // update array
1044
    {
1045
      composite_term_t* desc = get_composite(terms, current_kind, current);
8,618✔
1046
      bool children_done = true;
8,618✔
1047
      bool children_same = true;
8,618✔
1048

1049
      n = desc->arity;
8,618✔
1050

1051
      ivector_t children;
1052
      init_ivector(&children, n);
8,618✔
1053

1054
      for (i = 0; i < n; ++ i) {
29,665✔
1055
        term_t child = desc->arg[i];
21,047✔
1056
        term_t child_pre = preprocessor_get(pre, child);
21,047✔
1057

1058
        if (child_pre == NULL_TERM) {
21,047✔
1059
          children_done = false;
4,019✔
1060
          ivector_push(pre_stack, child);
4,019✔
1061
        } else {
1062
          // Purify if needed
1063
          child_pre = preprocessor_purify(pre, child_pre, out);
17,028✔
1064
          // If interpreted terms, we need to purify non-variables
1065
          if (child_pre != child) { children_same = false; }
17,028✔
1066
        }
1067

1068
        if (children_done) { ivector_push(&children, child_pre); }
21,047✔
1069
      }
1070

1071
      if (children_done) {
8,618✔
1072
        if (children_same) {
5,630✔
1073
          current_pre = current;
4,211✔
1074
        } else {
1075
          current_pre = mk_composite(pre, current_kind, n, children.data);
1,419✔
1076
        }
1077
      }
1078

1079
      delete_ivector(&children);
8,618✔
1080

1081
      break;
8,618✔
1082
    }
1083

1084
    case ARITH_IS_INT_ATOM:
×
1085
    {
1086
      // replace with t <= floor(t)
1087
      term_t child = arith_is_int_arg(terms, current);
×
1088
      term_t child_pre = preprocessor_get(pre, child);
×
1089
      if (child_pre != NULL_TERM) {
×
1090
        child_pre = preprocessor_purify(pre, child_pre, out);
×
1091
        current_pre = arith_floor(terms, child_pre);
×
1092
        current_pre = mk_arith_leq(tm, child_pre, current_pre);
×
1093
      } else {
1094
        ivector_push(pre_stack, child);
×
1095
      }
1096
      break;
×
1097
    }
1098

1099
    case ARITH_FLOOR:        // floor: purify, but its interpreted
7✔
1100
    {
1101
      term_t child = arith_floor_arg(terms, current);
7✔
1102
      term_t child_pre = preprocessor_get(pre, child);
7✔
1103

1104
      if (child_pre != NULL_TERM) {
7✔
1105
        if (term_kind(terms, child_pre) == ARITH_CONSTANT) {
4✔
1106
          rational_t floor;
1107
          q_init(&floor);
1✔
1108
          q_set(&floor, rational_term_desc(terms, child_pre));
1✔
1109
          q_floor(&floor);
1✔
1110
          current_pre = arith_constant(terms, &floor);
1✔
1111
          q_clear(&floor);
1✔
1112
        } else {
1113
          child_pre = preprocessor_purify(pre, child_pre, out);
3✔
1114
          if (child_pre != child) {
3✔
1115
            current_pre = arith_floor(terms, child_pre);
1✔
1116
          } else {
1117
            current_pre = current;
2✔
1118
          }
1119
        }
1120
      } else {
1121
        ivector_push(pre_stack, child);
3✔
1122
      }
1123

1124
      break;
7✔
1125
    }
1126

1127
    case ARITH_CEIL:        // floor: purify, but its interpreted
×
1128
    {
1129
      term_t child = arith_ceil_arg(terms, current);
×
1130
      term_t child_pre = preprocessor_get(pre, child);
×
1131

1132
      if (child_pre != NULL_TERM) {
×
1133
        child_pre = preprocessor_purify(pre, child_pre, out);
×
1134
        if (child_pre != child) {
×
1135
          current_pre = arith_floor(terms, child_pre);
×
1136
        } else {
1137
          current_pre = current;
×
1138
        }
1139
      } else {
1140
        ivector_push(pre_stack, child);
×
1141
      }
1142

1143
      break;
×
1144
    }
1145

1146
    case DISTINCT_TERM:
27✔
1147
    {
1148
      composite_term_t* desc = get_composite(terms, current_kind, current);
27✔
1149

1150
      bool children_done = true;
27✔
1151
      n = desc->arity;
27✔
1152

1153
      // DISTINCT_TERM is lowered below into pairwise disequalities. Apply the
1154
      // same function-sort guard before that expansion.
1155
      for (i = 0; i < n; ++ i) {
125✔
1156
        if (term_needs_function_diseq_guard(terms, desc->arg[i])) {
101✔
1157
          longjmp(*pre->exception, MCSAT_EXCEPTION_UNSUPPORTED_THEORY);
3✔
1158
        }
1159
      }
1160

1161
      ivector_t children;
1162
      init_ivector(&children, n);
24✔
1163

1164
      for (i = 0; i < n; ++ i) {
122✔
1165
        term_t child = desc->arg[i];
98✔
1166
        term_t child_pre = preprocessor_get(pre, child);
98✔
1167

1168
        if (child_pre == NULL_TERM) {
98✔
1169
          children_done = false;
41✔
1170
          ivector_push(pre_stack, child);
41✔
1171
        }
1172

1173
        if (children_done) { ivector_push(&children, child_pre); }
98✔
1174
      }
1175

1176
      if (children_done) {
24✔
1177
        ivector_t distinct;
1178
        init_ivector(&distinct, 0);
14✔
1179

1180
        for (i = 0; i < n; ++ i) {
70✔
1181
          for (j = i + 1; j < n; ++ j) {
148✔
1182
            term_t neq = mk_eq(&pre->tm, children.data[i], children.data[j]);
92✔
1183
            neq = opposite_term(neq);
92✔
1184
            ivector_push(&distinct, neq);
92✔
1185
          }
1186
        }
1187
        current_pre = mk_and(&pre->tm, distinct.size, distinct.data);
14✔
1188

1189
        delete_ivector(&distinct);
14✔
1190
      }
1191

1192
      delete_ivector(&children);
24✔
1193

1194
      break;
24✔
1195
    }
1196

1197
    case LAMBDA_TERM:
×
1198
      longjmp(*pre->exception, LAMBDAS_NOT_SUPPORTED);
×
1199
      break;
1200

1201
    default:
×
1202
      // UNSUPPORTED TERM/THEORY
1203
      longjmp(*pre->exception, MCSAT_EXCEPTION_UNSUPPORTED_THEORY);
×
1204
      break;
1205
    }
1206

1207
    if (current_pre != NULL_TERM) {
347,374✔
1208
      preprocessor_set(pre, current, current_pre);
263,953✔
1209
      ivector_pop(pre_stack);
263,953✔
1210
      if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
263,953✔
1211
        mcsat_trace_printf(pre->tracer, "current_pre = ");
×
1212
        trace_term_ln(pre->tracer, terms, current_pre);
×
1213
      }
1214
    }
1215

1216
  }
1217

1218
  // Return the result
1219
  t_pre = preprocessor_get(pre, t);
38,100✔
1220
  if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
38,100✔
1221
    mcsat_trace_printf(pre->tracer, "t_pre = ");
×
1222
    trace_term_ln(pre->tracer, terms, t_pre);
×
1223
  }
1224

1225
  ivector_reset(pre_stack);
38,100✔
1226

1227
  assert(t_pre != NULL_TERM);
1228
  return t_pre;
38,100✔
1229
}
1230

1231
void preprocessor_set_exception_handler(preprocessor_t* pre, jmp_buf* handler) {
×
1232
  pre->exception = handler;
×
1233
}
×
1234

1235
void preprocessor_push(preprocessor_t* pre) {
523✔
1236
  scope_holder_push(&pre->scope,
523✔
1237
      &pre->preprocess_map_list.size,
1238
      &pre->purification_map_list.size,
1239
      &pre->equalities_list.size,
1240
      NULL);
1241
}
523✔
1242

1243
void preprocessor_pop(preprocessor_t* pre) {
449✔
1244

1245
  uint32_t preprocess_map_list_size = 0;
449✔
1246
  uint32_t purification_map_list_size = 0;
449✔
1247
  uint32_t equalities_list_size = 0;
449✔
1248

1249
  scope_holder_pop(&pre->scope,
449✔
1250
      &preprocess_map_list_size,
1251
      &purification_map_list_size,
1252
      &equalities_list_size,
1253
      NULL);
1254

1255
  while (pre->preprocess_map_list.size > preprocess_map_list_size) {
11,925✔
1256
    term_t t = ivector_last(&pre->preprocess_map_list);
11,476✔
1257
    ivector_pop(&pre->preprocess_map_list);
11,476✔
1258
    int_hmap_pair_t* find = int_hmap_find(&pre->preprocess_map, t);
11,476✔
1259
    assert(find != NULL);
1260
    int_hmap_erase(&pre->preprocess_map, find);
11,476✔
1261
  }
1262

1263
  while (pre->purification_map_list.size > purification_map_list_size) {
584✔
1264
    term_t t = ivector_last(&pre->purification_map_list);
135✔
1265
    ivector_pop(&pre->purification_map_list);
135✔
1266
    int_hmap_pair_t* find = int_hmap_find(&pre->purification_map, t);
135✔
1267
    assert(find != NULL);
1268
    int_hmap_erase(&pre->purification_map, find);
135✔
1269
  }
1270

1271
  while (pre->equalities_list.size > equalities_list_size) {
499✔
1272
    term_t eq = ivector_last(&pre->equalities_list);
50✔
1273
    ivector_pop(&pre->equalities_list);
50✔
1274
    int_hmap_pair_t* find = int_hmap_find(&pre->equalities, eq);
50✔
1275
    assert(find != NULL);
1276
    int_hmap_erase(&pre->equalities, find);
50✔
1277
  }
1278
}
449✔
1279

1280
void preprocessor_build_model(preprocessor_t* pre, model_t* model) {
33✔
1281
  uint32_t i = 0;
33✔
1282
  for (i = 0; i < pre->equalities_list.size; ++ i) {
36✔
1283
    term_t eq = pre->equalities_list.data[i];
3✔
1284
    term_t eq_var = preprocessor_get_eq_solved_var(pre, eq);
3✔
1285
    if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
3✔
1286
      mcsat_trace_printf(pre->tracer, "eq = ");
×
1287
      trace_term_ln(pre->tracer, pre->terms, eq);
×
1288
      mcsat_trace_printf(pre->tracer, "\neq_var = ");
×
1289
      trace_term_ln(pre->tracer, pre->terms, eq_var);
×
1290
      mcsat_trace_printf(pre->tracer, "\n");
×
1291
    }
1292
    // Some equalities are solved, but then reasserted in the solver
1293
    // these already have a model
1294
    if (model_find_term_value(model, eq_var) != null_value) {
3✔
1295
      continue;
×
1296
    }
1297
    // Some equalities are marked, but not solved. These we skip as they
1298
    // are already set in the model
1299
    if (preprocessor_get(pre, eq_var) == eq_var) {
3✔
1300
      continue;
×
1301
    }
1302
    term_kind_t eq_kind = term_kind(pre->terms, eq);
3✔
1303
    composite_term_t* eq_desc = get_composite(pre->terms, eq_kind, eq);
3✔
1304
    if (eq_desc->arity > 1) {
3✔
1305
      term_t eq_subst = eq_desc->arg[0] == eq_var ? eq_desc->arg[1] : eq_desc->arg[0];
1✔
1306
      model_add_substitution(model, eq_var, eq_subst);
1✔
1307
    } else {
1308
      model_add_substitution(model, eq_var, zero_term);
2✔
1309
    }
1310
  }
1311
}
33✔
1312

1313

1314
static inline
1315
void preprocessor_gc_mark_term(preprocessor_t* pre, term_t t) {
1,000✔
1316
  term_table_set_gc_mark(pre->terms, index_of(t));
1,000✔
1317
  type_table_set_gc_mark(pre->terms->types, term_type(pre->terms, t));
1,000✔
1318
}
1,000✔
1319

1320
void preprocessor_gc_mark(preprocessor_t* pre) {
5✔
1321
  uint32_t i;
1322

1323
  for (i = 0; i < pre->preprocess_map_list.size; ++ i) {
486✔
1324
    term_t t = pre->preprocess_map_list.data[i];
481✔
1325
    preprocessor_gc_mark_term(pre, t);
481✔
1326
    term_t t_pre = preprocessor_get(pre, t);
481✔
1327
    preprocessor_gc_mark_term(pre, t_pre);
481✔
1328
  }
1329

1330
  for (i = 0; i < pre->equalities_list.size; ++ i) {
5✔
UNCOV
1331
    term_t t = pre->equalities_list.data[i];
×
UNCOV
1332
    preprocessor_gc_mark_term(pre, t);
×
1333
  }
1334

1335
  for (i = 0; i < pre->purification_map_list.size; ++ i) {
24✔
1336
    term_t t = pre->purification_map_list.data[i];
19✔
1337
    preprocessor_gc_mark_term(pre, t);
19✔
1338
    term_t t_pure = int_hmap_find(&pre->purification_map, t)->val;
19✔
1339
    preprocessor_gc_mark_term(pre, t_pure);
19✔
1340
  }
1341
}
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc