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

SRI-CSL / yices2 / 26234961786

21 May 2026 03:14PM UTC coverage: 67.559% (+0.1%) from 67.453%
26234961786

Pull #611

github

disteph
Serialize supplemental MCSAT satellite entry points

Supported by Codex/GPT5.5 and Windsurf/Opus4.7
Pull Request #611: Wrap MCSAT as a Nelson-Oppen theory solver in CDCL(T) architecture

903 of 1349 new or added lines in 17 files covered. (66.94%)

2 existing lines in 2 files now uncovered.

86771 of 128437 relevant lines covered (67.56%)

1608322.57 hits per line

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

56.43
/src/api/context_config.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
/*
20
 * OBJECT TO STORE CONTEXT CONFIGURATIONS
21
 */
22

23
#include <stdbool.h>
24
#include <assert.h>
25

26
#include "api/context_config.h"
27
#include "api/search_parameters.h"
28
#include "utils/memalloc.h"
29
#include "utils/string_utils.h"
30

31

32
/*
33
 * Mapping from strings to context modes (cf. string_utils.h)
34
 */
35
static const char * const mode_names[NUM_MODES] = {
36
  "interactive",
37
  "multi-checks",
38
  "one-shot",
39
  "push-pop",
40
};
41

42
static const int32_t mode[NUM_MODES] = {
43
  CTX_MODE_INTERACTIVE,
44
  CTX_MODE_MULTICHECKS,
45
  CTX_MODE_ONECHECK,
46
  CTX_MODE_PUSHPOP,
47
};
48

49
static const char * const solver_type_names[NUM_SOLVER_TYPES] = {
50
  "dpllt",
51
  "mcsat"
52
};
53

54
static const int32_t solver_type[NUM_SOLVER_TYPES] = {
55
  CTX_SOLVER_TYPE_DPLLT,
56
  CTX_SOLVER_TYPE_MCSAT
57
};
58

59
/*
60
 * Solver codes
61
 */
62
static const char * const solver_code_names[NUM_SOLVER_CODES] = {
63
  "auto",
64
  "default",
65
  "ifw",
66
  "none",
67
  "rfw",
68
  "simplex",
69
};
70

71
static const int32_t solver_code[NUM_SOLVER_CODES] = {
72
  CTX_CONFIG_AUTO,
73
  CTX_CONFIG_DEFAULT,
74
  CTX_CONFIG_ARITH_IFW,
75
  CTX_CONFIG_NONE,
76
  CTX_CONFIG_ARITH_RFW,
77
  CTX_CONFIG_ARITH_SIMPLEX,
78
};
79

80

81
/*
82
 * Descriptor fields (other than "logic")
83
 */
84
typedef enum ctx_config_key {
85
  CTX_CONFIG_KEY_MODE,
86
  CTX_CONFIG_KEY_SOLVER_TYPE,
87
  CTX_CONFIG_KEY_TRACE_TAGS,
88
  CTX_CONFIG_KEY_ARITH_FRAGMENT,
89
  CTX_CONFIG_KEY_UF_SOLVER,
90
  CTX_CONFIG_KEY_ARRAY_SOLVER,
91
  CTX_CONFIG_KEY_BV_SOLVER,
92
  CTX_CONFIG_KEY_ARITH_SOLVER,
93
  CTX_CONFIG_KEY_MCSAT_SUPPLEMENT,
94
  CTX_CONFIG_KEY_MODEL_INTERPOLATION,
95
  CTX_CONFIG_KEY_SAT_DELEGATE,
96
  CTX_CONFIG_KEY_SAT_DELEGATE_INCREMENTAL_MODE,
97
} ctx_config_key_t;
98

99
#define NUM_CONFIG_KEYS (CTX_CONFIG_KEY_SAT_DELEGATE_INCREMENTAL_MODE+1)
100

101

102
static const char *const config_key_names[NUM_CONFIG_KEYS] = {
103
  "arith-fragment",
104
  "arith-solver",
105
  "array-solver",
106
  "bv-solver",
107
  "mcsat-supplement",
108
  "mode",
109
  "model-interpolation",
110
  "sat-delegate",
111
  "sat-delegate-incremental-mode",
112
  "solver-type",
113
  "trace",
114
  "uf-solver",
115
};
116

117
static const int32_t config_key[NUM_CONFIG_KEYS] = {
118
  CTX_CONFIG_KEY_ARITH_FRAGMENT,
119
  CTX_CONFIG_KEY_ARITH_SOLVER,
120
  CTX_CONFIG_KEY_ARRAY_SOLVER,
121
  CTX_CONFIG_KEY_BV_SOLVER,
122
  CTX_CONFIG_KEY_MCSAT_SUPPLEMENT,
123
  CTX_CONFIG_KEY_MODE,
124
  CTX_CONFIG_KEY_MODEL_INTERPOLATION,
125
  CTX_CONFIG_KEY_SAT_DELEGATE,
126
  CTX_CONFIG_KEY_SAT_DELEGATE_INCREMENTAL_MODE,
127
  CTX_CONFIG_KEY_SOLVER_TYPE,
128
  CTX_CONFIG_KEY_TRACE_TAGS,
129
  CTX_CONFIG_KEY_UF_SOLVER,
130
};
131

132
/*
133
 * CONTEXT SETTING FOR A GIVEN LOGIC CODE
134
 */
135

136
/*
137
 * Conversion of SMT logic code to a default architecture code
138
 * -1 means not supported
139
 *
140
 * We don't use AUTO_IDL, AUTO_RDL, IFW or RFW here since
141
 * the Floyd-Warshall solvers don't support all use modes.
142
 *
143
 * IMPORTANT: this array is used by the API in config_for_logic.
144
 */
145
static const int32_t logic2arch[NUM_SMT_LOGICS] = {
146
  CTX_ARCH_NOSOLVERS,  // NONE
147

148
  -1,                  // AX
149
  -1,                  // BV  (supported by EF)
150
  -1,                  // FFA
151
  -1,                  // IDL (supported by EF)
152
  -1,                  // LIA (supported by EF)
153
  -1,                  // LRA (supported by EF)
154
  -1,                  // LIRA
155
  -1,                  // NIA
156
  -1,                  // NRA
157
  -1,                  // NIRA
158
  -1,                  // RDL
159
  -1,                  // UF
160
  -1,                  // ABV
161
  -1,                  // ALIA
162
  -1,                  // ALRA
163
  -1,                  // ALIRA
164
  -1,                  // ANIA
165
  -1,                  // ANRA
166
  -1,                  // ANIRA
167
  -1,                  // AUF
168
  -1,                  // BVLRA
169
  -1,                  // UFBV
170
  -1,                  // UFBVLIA
171
  -1,                  // UFIDL
172
  -1,                  // UFLIA
173
  -1,                  // UFLRA
174
  -1,                  // UFLIRA
175
  -1,                  // UFNIA
176
  -1,                  // UFNRA
177
  -1,                  // UFNIRA
178
  -1,                  // UFRDL
179
  -1,                  // AUFBV
180
  -1,                  // AUFBVLIA
181
  -1,                  // AUFBVNIA
182
  -1,                  // AUFLIA
183
  -1,                  // AUFLRA
184
  -1,                  // AUFLIRA
185
  -1,                  // AUFNIA
186
  -1,                  // AUFNRA
187
  -1,                  // AUFNIRA
188

189
  CTX_ARCH_EGFUN,      // QF_AX
190
  CTX_ARCH_BV,         // QF_BV
191
  CTX_ARCH_MCSAT,      // QF_FFA
192
  CTX_ARCH_SPLX,       // QF_IDL
193
  CTX_ARCH_SPLX,       // QF_LIA
194
  CTX_ARCH_SPLX,       // QF_LRA
195
  CTX_ARCH_SPLX,       // QF_LIRA
196
  CTX_ARCH_MCSAT,      // QF_NIA
197
  CTX_ARCH_MCSAT,      // QF_NRA
198
  CTX_ARCH_MCSAT,      // QF_NIRA
199
  CTX_ARCH_SPLX,       // QF_RDL
200
  CTX_ARCH_EG,         // QF_UF
201
  CTX_ARCH_EGFUNBV,    // QF_ABV
202
  CTX_ARCH_EGFUNSPLX,  // QF_ALIA
203
  CTX_ARCH_EGFUNSPLX,  // QF_ALRA
204
  CTX_ARCH_EGFUNSPLX,  // QF_ALIRA
205
  CTX_ARCH_MCSAT,      // QF_ANIA
206
  CTX_ARCH_MCSAT,      // QF_ANRA
207
  CTX_ARCH_MCSAT,      // QF_ANIRA
208
  CTX_ARCH_EGFUN,      // QF_AUF
209
  CTX_ARCH_EGSPLXBV,   // QF_BVLRA
210
  CTX_ARCH_EGBV,       // QF_UFBV
211
  CTX_ARCH_EGSPLXBV,   // QF_UFBVLIA
212

213
  CTX_ARCH_EGSPLX,     // QF_UFIDL
214
  CTX_ARCH_EGSPLX,     // QF_UFLIA
215
  CTX_ARCH_EGSPLX,     // QF_UFLRA
216
  CTX_ARCH_EGSPLX,     // QF_UFLIRA
217
  CTX_ARCH_MCSAT,      // QF_UFNIA
218
  CTX_ARCH_MCSAT,      // QF_UFNRA
219
  CTX_ARCH_MCSAT,      // QF_UFNIRA
220
  CTX_ARCH_EGSPLX,     // QF_UFRDL
221
  CTX_ARCH_EGFUNBV,    // QF_AUFBV
222
  CTX_ARCH_EGFUNSPLXBV, // QF_AUFBVLIA
223
  CTX_ARCH_MCSAT,      // QF_AUFBVNIA
224
  CTX_ARCH_EGFUNSPLX,  // QF_AUFLIA
225
  CTX_ARCH_EGFUNSPLX,  // QF_AUFLRA
226
  CTX_ARCH_EGFUNSPLX,  // QF_AUFLIRA
227
  CTX_ARCH_MCSAT,      // QF_AUFNIA
228
  CTX_ARCH_MCSAT,      // QF_AUFNRA
229
  CTX_ARCH_MCSAT,      // QF_AUFNIRA
230

231
  CTX_ARCH_EGFUNSPLXBV,  // ALL interpreted as QF_AUFLIRA + QF_BV
232
};
233

234

235

236
/*
237
 * WHICH ARITHMETIC FRAGMENTS REQUIRE THE DIOPHANTINE SUBSOLVER
238
 */
239
static const bool fragment2iflag[NUM_ARITH_FRAGMENTS+1] = {
240
  false,  // IDL
241
  false,  // RDL
242
  true,   // LIA
243
  false,  // LRA
244
  true,   // LIRA
245
  true,   // NIA
246
  false,  // NRA
247
  true,   // NIRA
248
  false,  // FFA
249
  false,  // no arithmetic
250
};
251

252

253
/*
254
 * Default configuration:
255
 * - enable PUSH/POP
256
 * - solver type = DPLL(T)
257
 * - no logic specified
258
 * - arith fragment = LIRA
259
 * - all solvers set to defaults
260
 */
261
static const ctx_config_t default_config = {
262
  CTX_MODE_PUSHPOP,       // mode
263
  CTX_SOLVER_TYPE_DPLLT,  // DPLLT solver
264
  false,                  // solver type set by user
265
  SMT_UNKNOWN,            // logic
266
  CTX_CONFIG_DEFAULT,     // uf
267
  CTX_CONFIG_DEFAULT,     // array
268
  CTX_CONFIG_DEFAULT,     // bv
269
  CTX_CONFIG_DEFAULT,     // arith
270
  ARITH_LIRA,             // fragment
271
  false,                  // mcsat supplement
272
  false,                  // model interpolation
273
  SAT_DELEGATE_NONE,      // sat delegate
274
  SAT_DELEGATE_MODE_REBUILD, // sat delegate incremental mode (unused unless explicitly set)
275
  false,                  // sat delegate incremental mode set by user
276
  NULL,                   // trace tags
277
  false,                  // mcsat supplement set by user
278
};
279

280

281

282

283

284
/*
285
 * DIRECT CONFIGURATION
286
 */
287
int32_t arch_for_logic(smt_logic_t code) {
5,513✔
288
  assert(code != SMT_UNKNOWN);
289
  return logic2arch[code];
5,513✔
290
}
291

292
bool iflag_for_logic(smt_logic_t code) {
2,809✔
293
  assert(code != SMT_UNKNOWN);
294
  return fragment2iflag[arith_fragment(code)];
2,809✔
295
}
296

297

298

299
/*
300
 * CONFIG OBJECT
301
 */
302

303
/*
304
 * Initialize config to the default configuration
305
 */
306
void init_config_to_defaults(ctx_config_t *config) {
132✔
307
  *config = default_config;
132✔
308
}
132✔
309

310

311

312
/*
313
 * Set a default configuration to support the given logic
314
 * - return -1 if the logic name is not recognized
315
 * - return -2 if we don't support the logic yet
316
 * - return 0 otherwise
317
 *
318
 * If the function returns 0, the logic field is updated.
319
 * All other fields are left unchanged.
320
 */
321
int32_t config_set_logic(ctx_config_t *config, const char *logic) {
64✔
322
  smt_logic_t code;
323
  int32_t r;
324

325
  code = smt_logic_code(logic);
64✔
326
  if (code == SMT_UNKNOWN) {
64✔
327
    r = -1;
×
328
  } else if (logic2arch[code] < 0) {
64✔
329
    r = -2;
×
330
  } else {
331
    config->logic = (smt_logic_t) code;
64✔
332
    r = 0;
64✔
333
  }
334

335
  return r;
64✔
336
}
337

338

339
/*
340
 * Convert value to a solver
341
 */
342
static int32_t set_solver_code(const char *value, solver_code_t *dest) {
×
343
  int32_t v, r;
344

345
  v = parse_as_keyword(value, solver_code_names, solver_code, NUM_SOLVER_CODES);
×
346
  if (v < 0) {
×
347
    r = -2;
×
348
  } else if (v >= CTX_CONFIG_AUTO) {
×
349
    r = -3;
×
350
  } else {
351
    assert(v == CTX_CONFIG_DEFAULT || v == CTX_CONFIG_NONE);
352
    *dest = (solver_code_t) v;
×
353
    r = 0;
×
354
  }
355

356
  return r;
×
357
}
358

359

360
/*
361
 * Set an individual field in config
362
 * - key = field name
363
 * - value = value for that field
364
 *
365
 * Return code:
366
 *   -1 if the key is not recognized
367
 *   -2 if the value is not recognized
368
 *   -3 if the value is not valid for the key
369
 *    0 otherwise
370
 */
371
int32_t config_set_field(ctx_config_t *config, const char *key, const char *value) {
201✔
372
  int32_t k, v, r;
373
  arith_fragment_t arith;
374

375
  r = 0; // return code
201✔
376

377
  k = parse_as_keyword(key, config_key_names, config_key, NUM_CONFIG_KEYS);
201✔
378
  switch (k) {
201✔
379
  case CTX_CONFIG_KEY_MODE:
72✔
380
    v = parse_as_keyword(value, mode_names, mode, NUM_MODES);
72✔
381
    if (v < 0) {
72✔
382
      r = -2;
×
383
    } else {
384
      config->mode = v;
72✔
385
    }
386
    break;
72✔
387

388
  case CTX_CONFIG_KEY_SOLVER_TYPE:
75✔
389
    v = parse_as_keyword(value, solver_type_names, solver_type, NUM_SOLVER_TYPES);
75✔
390
    if (v < 0) {
75✔
391
      r = -2;
×
392
    } else {
393
      config->solver_type = v;
75✔
394
      config->solver_type_set = true;
75✔
395
    }
396
    break;
75✔
397

398
  case CTX_CONFIG_KEY_TRACE_TAGS:
2✔
399
    config->trace_tags = safe_strdup(value);
2✔
400
    break;
2✔
401

402
  case CTX_CONFIG_KEY_ARITH_FRAGMENT:
×
403
    arith = arith_fragment_code(value);
×
404
    if (arith == ARITH_NONE) {
×
405
      r = -2;
×
406
    } else {
407
      config->arith_fragment = arith;
×
408
    }
409
    break;
×
410

411
  case CTX_CONFIG_KEY_UF_SOLVER:
×
412
    r = set_solver_code(value, &config->uf_config);
×
413
    break;
×
414

415
  case CTX_CONFIG_KEY_ARRAY_SOLVER:
×
416
    r = set_solver_code(value, &config->array_config);
×
417
    break;
×
418

419
  case CTX_CONFIG_KEY_BV_SOLVER:
×
420
    r = set_solver_code(value, &config->bv_config);
×
421
    break;
×
422

423
  case CTX_CONFIG_KEY_ARITH_SOLVER:
×
424
    v = parse_as_keyword(value, solver_code_names, solver_code, NUM_SOLVER_CODES);
×
425
    if (v < 0) {
×
426
      r = -2;
×
427
    } else {
428
      assert(0 <= v && v <= NUM_SOLVER_CODES);
429
      config->arith_config = v;
×
430
    }
431
    break;
×
432
  case CTX_CONFIG_KEY_MCSAT_SUPPLEMENT:
8✔
433
    v = parse_as_boolean(value, &config->mcsat_supplement);
8✔
434
    if (v < 0) {
8✔
NEW
435
      r = -2;
×
436
    } else {
437
      config->mcsat_supplement_set = true;
8✔
438
    }
439
    break;
8✔
440
  case CTX_CONFIG_KEY_MODEL_INTERPOLATION:
9✔
441
    v = parse_as_boolean(value, &config->model_interpolation);
9✔
442
    if (v < 0) {
9✔
443
      r = -2;
×
444
    }
445
    break;
9✔
446
  case CTX_CONFIG_KEY_SAT_DELEGATE:
20✔
447
    if (parse_sat_delegate(value, &config->sat_delegate) < 0) {
20✔
448
      r = -2;
×
449
    }
450
    break;
20✔
451
  case CTX_CONFIG_KEY_SAT_DELEGATE_INCREMENTAL_MODE:
14✔
452
    if (parse_sat_delegate_incremental_mode(value, &config->sat_delegate_incremental_mode) < 0) {
14✔
453
      r = -2;
×
454
    } else {
455
      config->sat_delegate_incremental_mode_set = true;
14✔
456
    }
457
    break;
14✔
458
  default:
1✔
459
    assert(k == -1);
460
    r = -1;
1✔
461
    break;
1✔
462
  }
463

464
  return r;
201✔
465
}
466

467

468

469
/*
470
 * Auxiliary functions to build architecture codes incrementally
471
 * - each function takes an integer a: a is either a valid architecture
472
 *   code or -1
473
 * - then the function adds a new solver component to a: this results
474
 *   in either a new valid code or -1 if the new component is not compatible with a.
475
 *
476
 * Important: we assume that the components are added in the following
477
 * order: egraph, array solver, bitvector solver, arithmetic solver
478
 */
479
static inline int32_t arch_add_egraph(int32_t a) {
5✔
480
  if (a == CTX_ARCH_NOSOLVERS) {
5✔
481
    a = CTX_ARCH_EG;
5✔
482
  } else {
483
    a = -1;
×
484
  }
485
  return a;
5✔
486
}
487

488
static int32_t arch_add_array(int32_t a) {
5✔
489
  if (a == CTX_ARCH_EG || a == CTX_ARCH_NOSOLVERS) {
5✔
490
    a = CTX_ARCH_EGFUN; // array requires egraph so we add both implicitly
5✔
491
  } else {
492
    a = -1;
×
493
  }
494
  return a;
5✔
495
}
496

497
static int32_t arch_add_bv(int32_t a) {
5✔
498
  switch (a) {
5✔
499
  case CTX_ARCH_NOSOLVERS:
×
500
    a = CTX_ARCH_BV;
×
501
    break;
×
502

503
  case CTX_ARCH_EG:
×
504
    a = CTX_ARCH_EGBV;
×
505
    break;
×
506

507
  case CTX_ARCH_EGFUN:
5✔
508
    a = CTX_ARCH_EGFUNBV;
5✔
509
    break;
5✔
510

511
  case CTX_ARCH_SPLX:
×
512
    a = CTX_ARCH_EGSPLXBV;
×
513
    break;
×
514

515
  default:
×
516
    a = -1;
×
517
    break;
×
518
  }
519

520
  return a;
5✔
521
}
522

523
// add the simplex solver
524
static int32_t arch_add_simplex(int32_t a) {
5✔
525
  switch (a) {
5✔
526
  case CTX_ARCH_NOSOLVERS:
×
527
    a = CTX_ARCH_SPLX;
×
528
    break;
×
529

530
  case CTX_ARCH_BV:
×
531
    a = CTX_ARCH_EGSPLXBV;
×
532
    break;
×
533

534
  case CTX_ARCH_EG:
×
535
    a = CTX_ARCH_EGSPLX;
×
536
    break;
×
537

538
  case CTX_ARCH_EGFUN:
×
539
    a = CTX_ARCH_EGFUNSPLX;
×
540
    break;
×
541

542
  case CTX_ARCH_EGBV:
×
543
    a = CTX_ARCH_EGSPLXBV;
×
544
    break;
×
545

546
  case CTX_ARCH_EGFUNBV:
5✔
547
    a = CTX_ARCH_EGFUNSPLXBV;
5✔
548
    break;
5✔
549

550
  default:
×
551
    a = -1;
×
552
    break;
×
553
  }
554

555
  return a;
5✔
556
}
557

558
// add a Floyd-Warshall solver
559
static int32_t arch_add_ifw(int32_t a) {
×
560
  if (a == CTX_ARCH_NOSOLVERS) {
×
561
    a = CTX_ARCH_IFW;
×
562
  } else {
563
    a = -1;
×
564
  }
565
  return a;
×
566
}
567

568
static int32_t arch_add_rfw(int32_t a) {
×
569
  if (a == CTX_ARCH_NOSOLVERS) {
×
570
    a = CTX_ARCH_RFW;
×
571
  } else {
572
    a = -1;
×
573
  }
574
  return a;
×
575
}
576

577

578
// add solver identified by code c to a
579
static int32_t arch_add_arith(int32_t a, solver_code_t c) {
5✔
580
  switch (c) {
5✔
581
  case CTX_CONFIG_NONE:  // no arithmetic solver
×
582
    break;
×
583

584
  case CTX_CONFIG_DEFAULT:  // simplex is the default
5✔
585
  case CTX_CONFIG_AUTO:     // auto = simplex here too
586
  case CTX_CONFIG_ARITH_SIMPLEX:
587
    a = arch_add_simplex(a);
5✔
588
    break;
5✔
589

590
  case CTX_CONFIG_ARITH_IFW:
×
591
    a = arch_add_ifw(a);
×
592
    break;
×
593

594
  case CTX_CONFIG_ARITH_RFW:
×
595
    a = arch_add_rfw(a);
×
596
    break;
×
597
  }
598
  return a;
5✔
599
}
600

601

602
/*
603
 * Check whether the architecture code a is compatible with mode
604
 * - current restriction: IFW and RFW don't support PUSH/POP or MULTIPLE CHECKS
605
 */
606
static bool arch_supports_mode(context_arch_t a, context_mode_t mode) {
5✔
607
  return (a != CTX_ARCH_IFW && a != CTX_ARCH_RFW) || mode == CTX_MODE_ONECHECK;
5✔
608
}
609

610

611
/*
612
 * Check whether the architecture is supported.
613
 */
614
static bool arch_is_supported(context_arch_t a) {
127✔
615
#if HAVE_MCSAT
616
  return true; // all architectures are supported
127✔
617
#else
618
  return a != CTX_ARCH_MCSAT;
619
#endif
620
}
621

622
/*
623
 * Check whether architecture a has an E-graph coordinator.
624
 */
625
static bool arch_has_egraph(context_arch_t a) {
7✔
626
  switch (a) {
7✔
627
  case CTX_ARCH_EG:
7✔
628
  case CTX_ARCH_EGFUN:
629
  case CTX_ARCH_EGSPLX:
630
  case CTX_ARCH_EGBV:
631
  case CTX_ARCH_EGFUNSPLX:
632
  case CTX_ARCH_EGFUNBV:
633
  case CTX_ARCH_EGSPLXBV:
634
  case CTX_ARCH_EGFUNSPLXBV:
635
    return true;
7✔
NEW
636
  default:
×
NEW
637
    return false;
×
638
  }
639
}
640

641
/*
642
 * CDCL(T) architecture to use when a logic's default backend is MCSAT
643
 * but the configuration requests a DPLL(T) top-level solver.
644
 */
NEW
645
static inline context_arch_t mcsat_supplement_arch_for_logic(smt_logic_t logic) {
×
646
  (void) logic;
NEW
647
  return CTX_ARCH_EGFUNSPLXBV;
×
648
}
649

650
static bool mcsat_supplement_is_supported(void) {
7✔
651
#if HAVE_MCSAT
652
  return true;
7✔
653
#else
654
  return false;
655
#endif
656
}
657

658
static bool logic_supported_by_mcsat_config(smt_logic_t code) {
2✔
659
  return code == SMT_ALL || !logic_has_quantifiers(code);
2✔
660
}
661

662

663
/*
664
 * Check whether config is valid (and supported by this version of Yices)
665
 * and convert it to a tuple (arch, mode, iflag, qflag)
666
 * - arch = architecture code as defined in context.h
667
 * - mode = one of the context's modes
668
 * - iflag = true if the integer solver (in simplex) is required
669
 * - qflag = true if support for quantifiers is required
670
 *
671
 * Return code:
672
 *   0 if the config is valid and supported
673
 *  -1 if the config is invalid
674
 *  -2 if the config is valid but not currently supported
675
 *  -3 if the solver combination is valid but does not support the specified mode
676
 */
677
int32_t decode_config(const ctx_config_t *config, smt_logic_t *logic, context_arch_t *arch, context_mode_t *mode, bool *iflag, bool *qflag, bool *mcsat_supplement) {
131✔
678
  smt_logic_t logic_code;
679
  int32_t a, r;
680

681
  r = 0; // default return code
131✔
682
  *mcsat_supplement = false;
131✔
683

684
  logic_code = config->logic;
131✔
685
  if (logic_code != SMT_UNKNOWN) {
131✔
686
    /*
687
     * The intended logic is specified
688
     */
689
    assert(0 <= logic_code && logic_code < NUM_SMT_LOGICS);
690

691
    /*
692
     * Special case: difference logic + mode = ONECHECK + arith_config == AUTO
693
     */
694
    if (config->arith_config == CTX_CONFIG_AUTO && config->mode == CTX_MODE_ONECHECK) {
64✔
695
      if (logic_code == QF_IDL) {
×
696
        *logic = QF_IDL;
×
697
        *arch = CTX_ARCH_AUTO_IDL;
×
698
        *mode = CTX_MODE_ONECHECK;
×
699
        *iflag = false;
×
700
        *qflag = false;
×
701
        goto done;
×
702
      }
703

704
      if (logic_code == QF_RDL) {
×
705
        *logic = QF_RDL;
×
706
        *arch = CTX_ARCH_AUTO_RDL;
×
707
        *mode = CTX_MODE_ONECHECK;
×
708
        *iflag = false;
×
709
        *qflag = false;
×
710
        goto done;
×
711
      }
712
    }
713

714
    if (config->solver_type_set && config->solver_type == CTX_SOLVER_TYPE_MCSAT) {
64✔
715
      if (!arch_is_supported(CTX_ARCH_MCSAT) || !logic_supported_by_mcsat_config(logic_code)) {
2✔
NEW
716
        r = -2;
×
NEW
717
        goto done;
×
718
      }
719
      a = CTX_ARCH_MCSAT;
2✔
720
    } else {
721
      a = logic2arch[logic_code];
62✔
722
    }
723

724
    if (config->solver_type_set && config->solver_type == CTX_SOLVER_TYPE_DPLLT && a == CTX_ARCH_MCSAT) {
64✔
725
      if (config->mcsat_supplement_set && !config->mcsat_supplement) {
1✔
726
        r = -1;
1✔
727
        goto done;
1✔
728
      }
NEW
729
      a = mcsat_supplement_arch_for_logic(logic_code);
×
NEW
730
      *mcsat_supplement = true;
×
731
    } else if (config->mcsat_supplement) {
63✔
732
      *mcsat_supplement = true;
6✔
733
    }
734
    if (a < 0 || !arch_is_supported(a)) {
63✔
735
      // not supported
736
      r = -2;
×
737
    } else {
738
      // good configuration
739
      *logic = logic_code;
63✔
740
      *arch = (context_arch_t) a;
63✔
741
      *iflag = iflag_for_logic(logic_code);
63✔
742
      *qflag = qflag_for_logic(logic_code);
63✔
743
      *mode = config->mode;
63✔
744
    }
745

746
  } else if (config->solver_type_set && config->solver_type == CTX_SOLVER_TYPE_MCSAT) {
67✔
747
    if (config->mcsat_supplement) {
62✔
NEW
748
      r = -1;
×
NEW
749
      goto done;
×
750
    }
751
    if (arch_is_supported(CTX_ARCH_MCSAT)) {
124✔
752
      /*
753
       * MCSAT solver/no logic specified
754
       */
755
      *logic = SMT_UNKNOWN;
62✔
756
      *arch = CTX_ARCH_MCSAT;
62✔
757
      *mode = CTX_MODE_PUSHPOP;
62✔
758
      *iflag = false;
62✔
759
      *qflag = false;
62✔
760
    } else {
761
      // not compiled with MCSAT support so this is not supported
762
      r = -2;
×
763
    }
764

765
  } else {
766
    /*
767
     * No logic specified.
768
     */
769

770
    a = CTX_ARCH_NOSOLVERS;
5✔
771
    if (config->uf_config == CTX_CONFIG_DEFAULT) {
5✔
772
      a = arch_add_egraph(a);
5✔
773
    }
774
    if (config->array_config == CTX_CONFIG_DEFAULT) {
5✔
775
      a = arch_add_array(a);
5✔
776
    }
777
    if (config->bv_config == CTX_CONFIG_DEFAULT) {
5✔
778
      a = arch_add_bv(a);
5✔
779
    }
780
    a = arch_add_arith(a, config->arith_config);
5✔
781
    *mcsat_supplement = config->mcsat_supplement;
5✔
782

783
    // a is either -1 or an architecture code
784
    if (a < 0) {
5✔
785
      r = -1; // invalid combination of solvers
×
786
    } else if (arch_supports_mode(a, config->mode)) {
5✔
787
      // good configuration
788
      *logic = SMT_UNKNOWN;
5✔
789
      *arch = (context_arch_t) a;
5✔
790
      *iflag = fragment2iflag[config->arith_fragment];
5✔
791
      *qflag = false;
5✔
792
      *mode = config->mode;
5✔
793
    } else {
794
      // mode is not supported by the solvers
795
      r = -3;
×
796
    }
797
  }
798

799
  if (r == 0 && *mcsat_supplement) {
130✔
800
    if (!mcsat_supplement_is_supported()) {
7✔
NEW
801
      r = -2;
×
802
    } else if (*arch == CTX_ARCH_MCSAT || !arch_has_egraph(*arch)) {
7✔
NEW
803
      r = -1;
×
804
    }
805
  }
806

807
 done:
130✔
808
  return r;
131✔
809
}
810

811

812
/*
813
 * Cleanup a configutation descriptor
814
 */
815
void delete_config(ctx_config_t *config) {
131✔
816
  safe_free(config->trace_tags);
131✔
817
}
131✔
818

819

820
/*
821
 * Check whether a logic is supported by the MCSAT solver
822
 */
823
bool logic_is_supported_by_mcsat(smt_logic_t code) {
512✔
824
  return code == SMT_ALL || !logic_has_quantifiers(code);
512✔
825
}
826

827
/*
828
 * Check whether a logic requires the MCSAT solver
829
 */
830
bool logic_requires_mcsat(smt_logic_t code) {
1,644✔
831
  return arch_for_logic(code) == CTX_ARCH_MCSAT;
1,644✔
832
}
833

834
/*
835
 * Check whether a logic is supported by the exists/forall solver
836
 * - logics with quantifiers and BV or linear arithmetic are supported
837
 * - logic "NONE" == purely Boolean is supported too
838
 */
839
bool logic_is_supported_by_ef(smt_logic_t code) {
1,644✔
840
  return code == NONE || code == BV || code == IDL || code == LRA || code == RDL || code == LIA || code == UF;
1,644✔
841
}
842

843

844
/*
845
 * Context architecture for a logic supported by EF
846
 */
847
int32_t ef_arch_for_logic(smt_logic_t code) {
694✔
848
  switch (code) {
694✔
849
  case NONE:
×
850
    return CTX_ARCH_NOSOLVERS;
×
851

852
  case UF:
114✔
853
    return CTX_ARCH_EG;
114✔
854

855
  case BV:
24✔
856
    return CTX_ARCH_BV;
24✔
857

858
  case IDL:
556✔
859
  case LRA:
860
  case RDL:
861
  case LIA:
862
    return CTX_ARCH_SPLX;
556✔
863

864
  default:
×
865
    return -1;
×
866
  }
867
}
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