GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/api/cpp/cvc5.cpp Lines: 2530 3366 75.2 %
Date: 2021-11-07 Branches: 6830 25352 26.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Aina Niemetz, Andrew Reynolds, Andres Noetzli
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * The cvc5 C++ API.
14
 *
15
 * A brief note on how to guard API functions:
16
 *
17
 * In general, we think of API guards as a fence -- they are supposed to make
18
 * sure that no invalid arguments get passed into internal realms of cvc5.
19
 * Thus we always want to catch such cases on the API level (and can then
20
 * assert internally that no invalid argument is passed in).
21
 *
22
 * The only special case is when we use 3rd party back-ends we have no control
23
 * over, and which throw (invalid_argument) exceptions anyways. In this case,
24
 * we do not replicate argument checks but delegate them to the back-end,
25
 * catch thrown exceptions, and raise a CVC5ApiException.
26
 *
27
 * Our Integer implementation, e.g., is such a special case since we support
28
 * two different back end implementations (GMP, CLN). Be aware that they do
29
 * not fully agree on what is (in)valid input, which requires extra checks for
30
 * consistent behavior (see Solver::mkRealFromStrHelper for an example).
31
 */
32
33
#include "api/cpp/cvc5.h"
34
35
#include <cstring>
36
#include <sstream>
37
38
#include "api/cpp/cvc5_checks.h"
39
#include "base/check.h"
40
#include "base/configuration.h"
41
#include "base/modal_exception.h"
42
#include "expr/array_store_all.h"
43
#include "expr/ascription_type.h"
44
#include "expr/cardinality_constraint.h"
45
#include "expr/dtype.h"
46
#include "expr/dtype_cons.h"
47
#include "expr/dtype_selector.h"
48
#include "expr/emptybag.h"
49
#include "expr/emptyset.h"
50
#include "expr/kind.h"
51
#include "expr/metakind.h"
52
#include "expr/node.h"
53
#include "expr/node_algorithm.h"
54
#include "expr/node_builder.h"
55
#include "expr/node_manager.h"
56
#include "expr/sequence.h"
57
#include "expr/type_node.h"
58
#include "expr/uninterpreted_constant.h"
59
#include "options/base_options.h"
60
#include "options/main_options.h"
61
#include "options/option_exception.h"
62
#include "options/options.h"
63
#include "options/options_public.h"
64
#include "options/smt_options.h"
65
#include "proof/unsat_core.h"
66
#include "smt/env.h"
67
#include "smt/model.h"
68
#include "smt/smt_mode.h"
69
#include "smt/solver_engine.h"
70
#include "theory/datatypes/tuple_project_op.h"
71
#include "theory/logic_info.h"
72
#include "theory/theory_model.h"
73
#include "util/abstract_value.h"
74
#include "util/bitvector.h"
75
#include "util/divisible.h"
76
#include "util/floatingpoint.h"
77
#include "util/iand.h"
78
#include "util/random.h"
79
#include "util/regexp.h"
80
#include "util/result.h"
81
#include "util/roundingmode.h"
82
#include "util/statistics_registry.h"
83
#include "util/statistics_stats.h"
84
#include "util/statistics_value.h"
85
#include "util/string.h"
86
#include "util/utility.h"
87
88
namespace cvc5 {
89
namespace api {
90
91
/* -------------------------------------------------------------------------- */
92
/* APIStatistics                                                              */
93
/* -------------------------------------------------------------------------- */
94
95
struct APIStatistics
96
{
97
  HistogramStat<TypeConstant> d_consts;
98
  HistogramStat<TypeConstant> d_vars;
99
  HistogramStat<Kind> d_terms;
100
};
101
102
/* -------------------------------------------------------------------------- */
103
/* Kind                                                                       */
104
/* -------------------------------------------------------------------------- */
105
106
/* Mapping from external (API) kind to internal kind. */
107
10379
const static std::unordered_map<Kind, cvc5::Kind> s_kinds{
108
    {INTERNAL_KIND, cvc5::Kind::UNDEFINED_KIND},
109
    {UNDEFINED_KIND, cvc5::Kind::UNDEFINED_KIND},
110
    {NULL_EXPR, cvc5::Kind::NULL_EXPR},
111
    /* Builtin ------------------------------------------------------------- */
112
    {UNINTERPRETED_CONSTANT, cvc5::Kind::UNINTERPRETED_CONSTANT},
113
    {ABSTRACT_VALUE, cvc5::Kind::ABSTRACT_VALUE},
114
    {EQUAL, cvc5::Kind::EQUAL},
115
    {DISTINCT, cvc5::Kind::DISTINCT},
116
    {CONSTANT, cvc5::Kind::VARIABLE},
117
    {VARIABLE, cvc5::Kind::BOUND_VARIABLE},
118
    {SEXPR, cvc5::Kind::SEXPR},
119
    {LAMBDA, cvc5::Kind::LAMBDA},
120
    {WITNESS, cvc5::Kind::WITNESS},
121
    /* Boolean ------------------------------------------------------------- */
122
    {CONST_BOOLEAN, cvc5::Kind::CONST_BOOLEAN},
123
    {NOT, cvc5::Kind::NOT},
124
    {AND, cvc5::Kind::AND},
125
    {IMPLIES, cvc5::Kind::IMPLIES},
126
    {OR, cvc5::Kind::OR},
127
    {XOR, cvc5::Kind::XOR},
128
    {ITE, cvc5::Kind::ITE},
129
    {MATCH, cvc5::Kind::MATCH},
130
    {MATCH_CASE, cvc5::Kind::MATCH_CASE},
131
    {MATCH_BIND_CASE, cvc5::Kind::MATCH_BIND_CASE},
132
    /* UF ------------------------------------------------------------------ */
133
    {APPLY_UF, cvc5::Kind::APPLY_UF},
134
    {CARDINALITY_CONSTRAINT, cvc5::Kind::CARDINALITY_CONSTRAINT},
135
    {HO_APPLY, cvc5::Kind::HO_APPLY},
136
    /* Arithmetic ---------------------------------------------------------- */
137
    {PLUS, cvc5::Kind::PLUS},
138
    {MULT, cvc5::Kind::MULT},
139
    {IAND, cvc5::Kind::IAND},
140
    {POW2, cvc5::Kind::POW2},
141
    {MINUS, cvc5::Kind::MINUS},
142
    {UMINUS, cvc5::Kind::UMINUS},
143
    {DIVISION, cvc5::Kind::DIVISION},
144
    {INTS_DIVISION, cvc5::Kind::INTS_DIVISION},
145
    {INTS_MODULUS, cvc5::Kind::INTS_MODULUS},
146
    {ABS, cvc5::Kind::ABS},
147
    {DIVISIBLE, cvc5::Kind::DIVISIBLE},
148
    {POW, cvc5::Kind::POW},
149
    {EXPONENTIAL, cvc5::Kind::EXPONENTIAL},
150
    {SINE, cvc5::Kind::SINE},
151
    {COSINE, cvc5::Kind::COSINE},
152
    {TANGENT, cvc5::Kind::TANGENT},
153
    {COSECANT, cvc5::Kind::COSECANT},
154
    {SECANT, cvc5::Kind::SECANT},
155
    {COTANGENT, cvc5::Kind::COTANGENT},
156
    {ARCSINE, cvc5::Kind::ARCSINE},
157
    {ARCCOSINE, cvc5::Kind::ARCCOSINE},
158
    {ARCTANGENT, cvc5::Kind::ARCTANGENT},
159
    {ARCCOSECANT, cvc5::Kind::ARCCOSECANT},
160
    {ARCSECANT, cvc5::Kind::ARCSECANT},
161
    {ARCCOTANGENT, cvc5::Kind::ARCCOTANGENT},
162
    {SQRT, cvc5::Kind::SQRT},
163
    {CONST_RATIONAL, cvc5::Kind::CONST_RATIONAL},
164
    {LT, cvc5::Kind::LT},
165
    {LEQ, cvc5::Kind::LEQ},
166
    {GT, cvc5::Kind::GT},
167
    {GEQ, cvc5::Kind::GEQ},
168
    {IS_INTEGER, cvc5::Kind::IS_INTEGER},
169
    {TO_INTEGER, cvc5::Kind::TO_INTEGER},
170
    {TO_REAL, cvc5::Kind::TO_REAL},
171
    {PI, cvc5::Kind::PI},
172
    /* BV ------------------------------------------------------------------ */
173
    {CONST_BITVECTOR, cvc5::Kind::CONST_BITVECTOR},
174
    {BITVECTOR_CONCAT, cvc5::Kind::BITVECTOR_CONCAT},
175
    {BITVECTOR_AND, cvc5::Kind::BITVECTOR_AND},
176
    {BITVECTOR_OR, cvc5::Kind::BITVECTOR_OR},
177
    {BITVECTOR_XOR, cvc5::Kind::BITVECTOR_XOR},
178
    {BITVECTOR_NOT, cvc5::Kind::BITVECTOR_NOT},
179
    {BITVECTOR_NAND, cvc5::Kind::BITVECTOR_NAND},
180
    {BITVECTOR_NOR, cvc5::Kind::BITVECTOR_NOR},
181
    {BITVECTOR_XNOR, cvc5::Kind::BITVECTOR_XNOR},
182
    {BITVECTOR_COMP, cvc5::Kind::BITVECTOR_COMP},
183
    {BITVECTOR_MULT, cvc5::Kind::BITVECTOR_MULT},
184
    {BITVECTOR_ADD, cvc5::Kind::BITVECTOR_ADD},
185
    {BITVECTOR_SUB, cvc5::Kind::BITVECTOR_SUB},
186
    {BITVECTOR_NEG, cvc5::Kind::BITVECTOR_NEG},
187
    {BITVECTOR_UDIV, cvc5::Kind::BITVECTOR_UDIV},
188
    {BITVECTOR_UREM, cvc5::Kind::BITVECTOR_UREM},
189
    {BITVECTOR_SDIV, cvc5::Kind::BITVECTOR_SDIV},
190
    {BITVECTOR_SREM, cvc5::Kind::BITVECTOR_SREM},
191
    {BITVECTOR_SMOD, cvc5::Kind::BITVECTOR_SMOD},
192
    {BITVECTOR_SHL, cvc5::Kind::BITVECTOR_SHL},
193
    {BITVECTOR_LSHR, cvc5::Kind::BITVECTOR_LSHR},
194
    {BITVECTOR_ASHR, cvc5::Kind::BITVECTOR_ASHR},
195
    {BITVECTOR_ULT, cvc5::Kind::BITVECTOR_ULT},
196
    {BITVECTOR_ULE, cvc5::Kind::BITVECTOR_ULE},
197
    {BITVECTOR_UGT, cvc5::Kind::BITVECTOR_UGT},
198
    {BITVECTOR_UGE, cvc5::Kind::BITVECTOR_UGE},
199
    {BITVECTOR_SLT, cvc5::Kind::BITVECTOR_SLT},
200
    {BITVECTOR_SLE, cvc5::Kind::BITVECTOR_SLE},
201
    {BITVECTOR_SGT, cvc5::Kind::BITVECTOR_SGT},
202
    {BITVECTOR_SGE, cvc5::Kind::BITVECTOR_SGE},
203
    {BITVECTOR_ULTBV, cvc5::Kind::BITVECTOR_ULTBV},
204
    {BITVECTOR_SLTBV, cvc5::Kind::BITVECTOR_SLTBV},
205
    {BITVECTOR_ITE, cvc5::Kind::BITVECTOR_ITE},
206
    {BITVECTOR_REDOR, cvc5::Kind::BITVECTOR_REDOR},
207
    {BITVECTOR_REDAND, cvc5::Kind::BITVECTOR_REDAND},
208
    {BITVECTOR_EXTRACT, cvc5::Kind::BITVECTOR_EXTRACT},
209
    {BITVECTOR_REPEAT, cvc5::Kind::BITVECTOR_REPEAT},
210
    {BITVECTOR_ZERO_EXTEND, cvc5::Kind::BITVECTOR_ZERO_EXTEND},
211
    {BITVECTOR_SIGN_EXTEND, cvc5::Kind::BITVECTOR_SIGN_EXTEND},
212
    {BITVECTOR_ROTATE_LEFT, cvc5::Kind::BITVECTOR_ROTATE_LEFT},
213
    {BITVECTOR_ROTATE_RIGHT, cvc5::Kind::BITVECTOR_ROTATE_RIGHT},
214
    {INT_TO_BITVECTOR, cvc5::Kind::INT_TO_BITVECTOR},
215
    {BITVECTOR_TO_NAT, cvc5::Kind::BITVECTOR_TO_NAT},
216
    /* FP ------------------------------------------------------------------ */
217
    {CONST_FLOATINGPOINT, cvc5::Kind::CONST_FLOATINGPOINT},
218
    {CONST_ROUNDINGMODE, cvc5::Kind::CONST_ROUNDINGMODE},
219
    {FLOATINGPOINT_FP, cvc5::Kind::FLOATINGPOINT_FP},
220
    {FLOATINGPOINT_EQ, cvc5::Kind::FLOATINGPOINT_EQ},
221
    {FLOATINGPOINT_ABS, cvc5::Kind::FLOATINGPOINT_ABS},
222
    {FLOATINGPOINT_NEG, cvc5::Kind::FLOATINGPOINT_NEG},
223
    {FLOATINGPOINT_ADD, cvc5::Kind::FLOATINGPOINT_ADD},
224
    {FLOATINGPOINT_SUB, cvc5::Kind::FLOATINGPOINT_SUB},
225
    {FLOATINGPOINT_MULT, cvc5::Kind::FLOATINGPOINT_MULT},
226
    {FLOATINGPOINT_DIV, cvc5::Kind::FLOATINGPOINT_DIV},
227
    {FLOATINGPOINT_FMA, cvc5::Kind::FLOATINGPOINT_FMA},
228
    {FLOATINGPOINT_SQRT, cvc5::Kind::FLOATINGPOINT_SQRT},
229
    {FLOATINGPOINT_REM, cvc5::Kind::FLOATINGPOINT_REM},
230
    {FLOATINGPOINT_RTI, cvc5::Kind::FLOATINGPOINT_RTI},
231
    {FLOATINGPOINT_MIN, cvc5::Kind::FLOATINGPOINT_MIN},
232
    {FLOATINGPOINT_MAX, cvc5::Kind::FLOATINGPOINT_MAX},
233
    {FLOATINGPOINT_LEQ, cvc5::Kind::FLOATINGPOINT_LEQ},
234
    {FLOATINGPOINT_LT, cvc5::Kind::FLOATINGPOINT_LT},
235
    {FLOATINGPOINT_GEQ, cvc5::Kind::FLOATINGPOINT_GEQ},
236
    {FLOATINGPOINT_GT, cvc5::Kind::FLOATINGPOINT_GT},
237
    {FLOATINGPOINT_ISN, cvc5::Kind::FLOATINGPOINT_ISN},
238
    {FLOATINGPOINT_ISSN, cvc5::Kind::FLOATINGPOINT_ISSN},
239
    {FLOATINGPOINT_ISZ, cvc5::Kind::FLOATINGPOINT_ISZ},
240
    {FLOATINGPOINT_ISINF, cvc5::Kind::FLOATINGPOINT_ISINF},
241
    {FLOATINGPOINT_ISNAN, cvc5::Kind::FLOATINGPOINT_ISNAN},
242
    {FLOATINGPOINT_ISNEG, cvc5::Kind::FLOATINGPOINT_ISNEG},
243
    {FLOATINGPOINT_ISPOS, cvc5::Kind::FLOATINGPOINT_ISPOS},
244
    {FLOATINGPOINT_TO_FP_FLOATINGPOINT,
245
     cvc5::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT},
246
    {FLOATINGPOINT_TO_FP_IEEE_BITVECTOR,
247
     cvc5::Kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR},
248
    {FLOATINGPOINT_TO_FP_REAL, cvc5::Kind::FLOATINGPOINT_TO_FP_REAL},
249
    {FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR,
250
     cvc5::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR},
251
    {FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR,
252
     cvc5::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR},
253
    {FLOATINGPOINT_TO_FP_GENERIC, cvc5::Kind::FLOATINGPOINT_TO_FP_GENERIC},
254
    {FLOATINGPOINT_TO_UBV, cvc5::Kind::FLOATINGPOINT_TO_UBV},
255
    {FLOATINGPOINT_TO_SBV, cvc5::Kind::FLOATINGPOINT_TO_SBV},
256
    {FLOATINGPOINT_TO_REAL, cvc5::Kind::FLOATINGPOINT_TO_REAL},
257
    /* Arrays -------------------------------------------------------------- */
258
    {SELECT, cvc5::Kind::SELECT},
259
    {STORE, cvc5::Kind::STORE},
260
    {CONST_ARRAY, cvc5::Kind::STORE_ALL},
261
    {EQ_RANGE, cvc5::Kind::EQ_RANGE},
262
    /* Datatypes ----------------------------------------------------------- */
263
    {APPLY_SELECTOR, cvc5::Kind::APPLY_SELECTOR},
264
    {APPLY_CONSTRUCTOR, cvc5::Kind::APPLY_CONSTRUCTOR},
265
    {APPLY_TESTER, cvc5::Kind::APPLY_TESTER},
266
    {APPLY_UPDATER, cvc5::Kind::APPLY_UPDATER},
267
    {DT_SIZE, cvc5::Kind::DT_SIZE},
268
    {TUPLE_PROJECT, cvc5::Kind::TUPLE_PROJECT},
269
    /* Separation Logic ---------------------------------------------------- */
270
    {SEP_NIL, cvc5::Kind::SEP_NIL},
271
    {SEP_EMP, cvc5::Kind::SEP_EMP},
272
    {SEP_PTO, cvc5::Kind::SEP_PTO},
273
    {SEP_STAR, cvc5::Kind::SEP_STAR},
274
    {SEP_WAND, cvc5::Kind::SEP_WAND},
275
    /* Sets ---------------------------------------------------------------- */
276
    {EMPTYSET, cvc5::Kind::EMPTYSET},
277
    {UNION, cvc5::Kind::UNION},
278
    {INTERSECTION, cvc5::Kind::INTERSECTION},
279
    {SETMINUS, cvc5::Kind::SETMINUS},
280
    {SUBSET, cvc5::Kind::SUBSET},
281
    {MEMBER, cvc5::Kind::MEMBER},
282
    {SINGLETON, cvc5::Kind::SINGLETON},
283
    {INSERT, cvc5::Kind::INSERT},
284
    {CARD, cvc5::Kind::CARD},
285
    {COMPLEMENT, cvc5::Kind::COMPLEMENT},
286
    {UNIVERSE_SET, cvc5::Kind::UNIVERSE_SET},
287
    {JOIN, cvc5::Kind::JOIN},
288
    {PRODUCT, cvc5::Kind::PRODUCT},
289
    {TRANSPOSE, cvc5::Kind::TRANSPOSE},
290
    {TCLOSURE, cvc5::Kind::TCLOSURE},
291
    {JOIN_IMAGE, cvc5::Kind::JOIN_IMAGE},
292
    {IDEN, cvc5::Kind::IDEN},
293
    {COMPREHENSION, cvc5::Kind::COMPREHENSION},
294
    {CHOOSE, cvc5::Kind::CHOOSE},
295
    {IS_SINGLETON, cvc5::Kind::IS_SINGLETON},
296
    /* Bags ---------------------------------------------------------------- */
297
    {UNION_MAX, cvc5::Kind::UNION_MAX},
298
    {UNION_DISJOINT, cvc5::Kind::UNION_DISJOINT},
299
    {INTERSECTION_MIN, cvc5::Kind::INTERSECTION_MIN},
300
    {DIFFERENCE_SUBTRACT, cvc5::Kind::DIFFERENCE_SUBTRACT},
301
    {DIFFERENCE_REMOVE, cvc5::Kind::DIFFERENCE_REMOVE},
302
    {SUBBAG, cvc5::Kind::SUBBAG},
303
    {BAG_COUNT, cvc5::Kind::BAG_COUNT},
304
    {DUPLICATE_REMOVAL, cvc5::Kind::DUPLICATE_REMOVAL},
305
    {MK_BAG, cvc5::Kind::MK_BAG},
306
    {EMPTYBAG, cvc5::Kind::EMPTYBAG},
307
    {BAG_CARD, cvc5::Kind::BAG_CARD},
308
    {BAG_CHOOSE, cvc5::Kind::BAG_CHOOSE},
309
    {BAG_IS_SINGLETON, cvc5::Kind::BAG_IS_SINGLETON},
310
    {BAG_FROM_SET, cvc5::Kind::BAG_FROM_SET},
311
    {BAG_TO_SET, cvc5::Kind::BAG_TO_SET},
312
    {BAG_MAP, cvc5::Kind::BAG_MAP},
313
    /* Strings ------------------------------------------------------------- */
314
    {STRING_CONCAT, cvc5::Kind::STRING_CONCAT},
315
    {STRING_IN_REGEXP, cvc5::Kind::STRING_IN_REGEXP},
316
    {STRING_LENGTH, cvc5::Kind::STRING_LENGTH},
317
    {STRING_SUBSTR, cvc5::Kind::STRING_SUBSTR},
318
    {STRING_UPDATE, cvc5::Kind::STRING_UPDATE},
319
    {STRING_CHARAT, cvc5::Kind::STRING_CHARAT},
320
    {STRING_CONTAINS, cvc5::Kind::STRING_CONTAINS},
321
    {STRING_INDEXOF, cvc5::Kind::STRING_INDEXOF},
322
    {STRING_INDEXOF_RE, cvc5::Kind::STRING_INDEXOF_RE},
323
    {STRING_REPLACE, cvc5::Kind::STRING_REPLACE},
324
    {STRING_REPLACE_ALL, cvc5::Kind::STRING_REPLACE_ALL},
325
    {STRING_REPLACE_RE, cvc5::Kind::STRING_REPLACE_RE},
326
    {STRING_REPLACE_RE_ALL, cvc5::Kind::STRING_REPLACE_RE_ALL},
327
    {STRING_TOLOWER, cvc5::Kind::STRING_TOLOWER},
328
    {STRING_TOUPPER, cvc5::Kind::STRING_TOUPPER},
329
    {STRING_REV, cvc5::Kind::STRING_REV},
330
    {STRING_FROM_CODE, cvc5::Kind::STRING_FROM_CODE},
331
    {STRING_TO_CODE, cvc5::Kind::STRING_TO_CODE},
332
    {STRING_LT, cvc5::Kind::STRING_LT},
333
    {STRING_LEQ, cvc5::Kind::STRING_LEQ},
334
    {STRING_PREFIX, cvc5::Kind::STRING_PREFIX},
335
    {STRING_SUFFIX, cvc5::Kind::STRING_SUFFIX},
336
    {STRING_IS_DIGIT, cvc5::Kind::STRING_IS_DIGIT},
337
    {STRING_FROM_INT, cvc5::Kind::STRING_ITOS},
338
    {STRING_TO_INT, cvc5::Kind::STRING_STOI},
339
    {CONST_STRING, cvc5::Kind::CONST_STRING},
340
    {STRING_TO_REGEXP, cvc5::Kind::STRING_TO_REGEXP},
341
    {REGEXP_CONCAT, cvc5::Kind::REGEXP_CONCAT},
342
    {REGEXP_UNION, cvc5::Kind::REGEXP_UNION},
343
    {REGEXP_INTER, cvc5::Kind::REGEXP_INTER},
344
    {REGEXP_DIFF, cvc5::Kind::REGEXP_DIFF},
345
    {REGEXP_STAR, cvc5::Kind::REGEXP_STAR},
346
    {REGEXP_PLUS, cvc5::Kind::REGEXP_PLUS},
347
    {REGEXP_OPT, cvc5::Kind::REGEXP_OPT},
348
    {REGEXP_RANGE, cvc5::Kind::REGEXP_RANGE},
349
    {REGEXP_REPEAT, cvc5::Kind::REGEXP_REPEAT},
350
    {REGEXP_LOOP, cvc5::Kind::REGEXP_LOOP},
351
    {REGEXP_EMPTY, cvc5::Kind::REGEXP_EMPTY},
352
    {REGEXP_SIGMA, cvc5::Kind::REGEXP_SIGMA},
353
    {REGEXP_COMPLEMENT, cvc5::Kind::REGEXP_COMPLEMENT},
354
    // maps to the same kind as the string versions
355
    {SEQ_CONCAT, cvc5::Kind::STRING_CONCAT},
356
    {SEQ_LENGTH, cvc5::Kind::STRING_LENGTH},
357
    {SEQ_EXTRACT, cvc5::Kind::STRING_SUBSTR},
358
    {SEQ_UPDATE, cvc5::Kind::STRING_UPDATE},
359
    {SEQ_AT, cvc5::Kind::STRING_CHARAT},
360
    {SEQ_CONTAINS, cvc5::Kind::STRING_CONTAINS},
361
    {SEQ_INDEXOF, cvc5::Kind::STRING_INDEXOF},
362
    {SEQ_REPLACE, cvc5::Kind::STRING_REPLACE},
363
    {SEQ_REPLACE_ALL, cvc5::Kind::STRING_REPLACE_ALL},
364
    {SEQ_REV, cvc5::Kind::STRING_REV},
365
    {SEQ_PREFIX, cvc5::Kind::STRING_PREFIX},
366
    {SEQ_SUFFIX, cvc5::Kind::STRING_SUFFIX},
367
    {CONST_SEQUENCE, cvc5::Kind::CONST_SEQUENCE},
368
    {SEQ_UNIT, cvc5::Kind::SEQ_UNIT},
369
    {SEQ_NTH, cvc5::Kind::SEQ_NTH},
370
    /* Quantifiers --------------------------------------------------------- */
371
    {FORALL, cvc5::Kind::FORALL},
372
    {EXISTS, cvc5::Kind::EXISTS},
373
    {BOUND_VAR_LIST, cvc5::Kind::BOUND_VAR_LIST},
374
    {INST_PATTERN, cvc5::Kind::INST_PATTERN},
375
    {INST_NO_PATTERN, cvc5::Kind::INST_NO_PATTERN},
376
    {INST_POOL, cvc5::Kind::INST_POOL},
377
    {INST_ADD_TO_POOL, cvc5::Kind::INST_ADD_TO_POOL},
378
    {SKOLEM_ADD_TO_POOL, cvc5::Kind::SKOLEM_ADD_TO_POOL},
379
    {INST_ATTRIBUTE, cvc5::Kind::INST_ATTRIBUTE},
380
    {INST_PATTERN_LIST, cvc5::Kind::INST_PATTERN_LIST},
381
    {LAST_KIND, cvc5::Kind::LAST_KIND},
382
};
383
384
/* Mapping from internal kind to external (API) kind. */
385
const static std::unordered_map<cvc5::Kind, Kind, cvc5::kind::KindHashFunction>
386
10379
    s_kinds_internal{
387
        {cvc5::Kind::UNDEFINED_KIND, UNDEFINED_KIND},
388
        {cvc5::Kind::NULL_EXPR, NULL_EXPR},
389
        /* Builtin --------------------------------------------------------- */
390
        {cvc5::Kind::UNINTERPRETED_CONSTANT, UNINTERPRETED_CONSTANT},
391
        {cvc5::Kind::ABSTRACT_VALUE, ABSTRACT_VALUE},
392
        {cvc5::Kind::EQUAL, EQUAL},
393
        {cvc5::Kind::DISTINCT, DISTINCT},
394
        {cvc5::Kind::VARIABLE, CONSTANT},
395
        {cvc5::Kind::BOUND_VARIABLE, VARIABLE},
396
        {cvc5::Kind::SEXPR, SEXPR},
397
        {cvc5::Kind::LAMBDA, LAMBDA},
398
        {cvc5::Kind::WITNESS, WITNESS},
399
        /* Boolean --------------------------------------------------------- */
400
        {cvc5::Kind::CONST_BOOLEAN, CONST_BOOLEAN},
401
        {cvc5::Kind::NOT, NOT},
402
        {cvc5::Kind::AND, AND},
403
        {cvc5::Kind::IMPLIES, IMPLIES},
404
        {cvc5::Kind::OR, OR},
405
        {cvc5::Kind::XOR, XOR},
406
        {cvc5::Kind::ITE, ITE},
407
        {cvc5::Kind::MATCH, MATCH},
408
        {cvc5::Kind::MATCH_CASE, MATCH_CASE},
409
        {cvc5::Kind::MATCH_BIND_CASE, MATCH_BIND_CASE},
410
        /* UF -------------------------------------------------------------- */
411
        {cvc5::Kind::APPLY_UF, APPLY_UF},
412
        {cvc5::Kind::CARDINALITY_CONSTRAINT, CARDINALITY_CONSTRAINT},
413
        {cvc5::Kind::HO_APPLY, HO_APPLY},
414
        /* Arithmetic ------------------------------------------------------ */
415
        {cvc5::Kind::PLUS, PLUS},
416
        {cvc5::Kind::MULT, MULT},
417
        {cvc5::Kind::IAND, IAND},
418
        {cvc5::Kind::POW2, POW2},
419
        {cvc5::Kind::MINUS, MINUS},
420
        {cvc5::Kind::UMINUS, UMINUS},
421
        {cvc5::Kind::DIVISION, DIVISION},
422
        {cvc5::Kind::DIVISION_TOTAL, INTERNAL_KIND},
423
        {cvc5::Kind::INTS_DIVISION, INTS_DIVISION},
424
        {cvc5::Kind::INTS_DIVISION_TOTAL, INTERNAL_KIND},
425
        {cvc5::Kind::INTS_MODULUS, INTS_MODULUS},
426
        {cvc5::Kind::INTS_MODULUS_TOTAL, INTERNAL_KIND},
427
        {cvc5::Kind::ABS, ABS},
428
        {cvc5::Kind::DIVISIBLE, DIVISIBLE},
429
        {cvc5::Kind::POW, POW},
430
        {cvc5::Kind::EXPONENTIAL, EXPONENTIAL},
431
        {cvc5::Kind::SINE, SINE},
432
        {cvc5::Kind::COSINE, COSINE},
433
        {cvc5::Kind::TANGENT, TANGENT},
434
        {cvc5::Kind::COSECANT, COSECANT},
435
        {cvc5::Kind::SECANT, SECANT},
436
        {cvc5::Kind::COTANGENT, COTANGENT},
437
        {cvc5::Kind::ARCSINE, ARCSINE},
438
        {cvc5::Kind::ARCCOSINE, ARCCOSINE},
439
        {cvc5::Kind::ARCTANGENT, ARCTANGENT},
440
        {cvc5::Kind::ARCCOSECANT, ARCCOSECANT},
441
        {cvc5::Kind::ARCSECANT, ARCSECANT},
442
        {cvc5::Kind::ARCCOTANGENT, ARCCOTANGENT},
443
        {cvc5::Kind::SQRT, SQRT},
444
        {cvc5::Kind::DIVISIBLE_OP, DIVISIBLE},
445
        {cvc5::Kind::CONST_RATIONAL, CONST_RATIONAL},
446
        {cvc5::Kind::LT, LT},
447
        {cvc5::Kind::LEQ, LEQ},
448
        {cvc5::Kind::GT, GT},
449
        {cvc5::Kind::GEQ, GEQ},
450
        {cvc5::Kind::IS_INTEGER, IS_INTEGER},
451
        {cvc5::Kind::TO_INTEGER, TO_INTEGER},
452
        {cvc5::Kind::TO_REAL, TO_REAL},
453
        {cvc5::Kind::PI, PI},
454
        {cvc5::Kind::IAND_OP, IAND},
455
        /* BV -------------------------------------------------------------- */
456
        {cvc5::Kind::CONST_BITVECTOR, CONST_BITVECTOR},
457
        {cvc5::Kind::BITVECTOR_CONCAT, BITVECTOR_CONCAT},
458
        {cvc5::Kind::BITVECTOR_AND, BITVECTOR_AND},
459
        {cvc5::Kind::BITVECTOR_OR, BITVECTOR_OR},
460
        {cvc5::Kind::BITVECTOR_XOR, BITVECTOR_XOR},
461
        {cvc5::Kind::BITVECTOR_NOT, BITVECTOR_NOT},
462
        {cvc5::Kind::BITVECTOR_NAND, BITVECTOR_NAND},
463
        {cvc5::Kind::BITVECTOR_NOR, BITVECTOR_NOR},
464
        {cvc5::Kind::BITVECTOR_XNOR, BITVECTOR_XNOR},
465
        {cvc5::Kind::BITVECTOR_COMP, BITVECTOR_COMP},
466
        {cvc5::Kind::BITVECTOR_MULT, BITVECTOR_MULT},
467
        {cvc5::Kind::BITVECTOR_ADD, BITVECTOR_ADD},
468
        {cvc5::Kind::BITVECTOR_SUB, BITVECTOR_SUB},
469
        {cvc5::Kind::BITVECTOR_NEG, BITVECTOR_NEG},
470
        {cvc5::Kind::BITVECTOR_UDIV, BITVECTOR_UDIV},
471
        {cvc5::Kind::BITVECTOR_UREM, BITVECTOR_UREM},
472
        {cvc5::Kind::BITVECTOR_SDIV, BITVECTOR_SDIV},
473
        {cvc5::Kind::BITVECTOR_SREM, BITVECTOR_SREM},
474
        {cvc5::Kind::BITVECTOR_SMOD, BITVECTOR_SMOD},
475
        {cvc5::Kind::BITVECTOR_SHL, BITVECTOR_SHL},
476
        {cvc5::Kind::BITVECTOR_LSHR, BITVECTOR_LSHR},
477
        {cvc5::Kind::BITVECTOR_ASHR, BITVECTOR_ASHR},
478
        {cvc5::Kind::BITVECTOR_ULT, BITVECTOR_ULT},
479
        {cvc5::Kind::BITVECTOR_ULE, BITVECTOR_ULE},
480
        {cvc5::Kind::BITVECTOR_UGT, BITVECTOR_UGT},
481
        {cvc5::Kind::BITVECTOR_UGE, BITVECTOR_UGE},
482
        {cvc5::Kind::BITVECTOR_SLT, BITVECTOR_SLT},
483
        {cvc5::Kind::BITVECTOR_SLE, BITVECTOR_SLE},
484
        {cvc5::Kind::BITVECTOR_SGT, BITVECTOR_SGT},
485
        {cvc5::Kind::BITVECTOR_SGE, BITVECTOR_SGE},
486
        {cvc5::Kind::BITVECTOR_ULTBV, BITVECTOR_ULTBV},
487
        {cvc5::Kind::BITVECTOR_SLTBV, BITVECTOR_SLTBV},
488
        {cvc5::Kind::BITVECTOR_ITE, BITVECTOR_ITE},
489
        {cvc5::Kind::BITVECTOR_REDOR, BITVECTOR_REDOR},
490
        {cvc5::Kind::BITVECTOR_REDAND, BITVECTOR_REDAND},
491
        {cvc5::Kind::BITVECTOR_EXTRACT_OP, BITVECTOR_EXTRACT},
492
        {cvc5::Kind::BITVECTOR_REPEAT_OP, BITVECTOR_REPEAT},
493
        {cvc5::Kind::BITVECTOR_ZERO_EXTEND_OP, BITVECTOR_ZERO_EXTEND},
494
        {cvc5::Kind::BITVECTOR_SIGN_EXTEND_OP, BITVECTOR_SIGN_EXTEND},
495
        {cvc5::Kind::BITVECTOR_ROTATE_LEFT_OP, BITVECTOR_ROTATE_LEFT},
496
        {cvc5::Kind::BITVECTOR_ROTATE_RIGHT_OP, BITVECTOR_ROTATE_RIGHT},
497
        {cvc5::Kind::BITVECTOR_EXTRACT, BITVECTOR_EXTRACT},
498
        {cvc5::Kind::BITVECTOR_REPEAT, BITVECTOR_REPEAT},
499
        {cvc5::Kind::BITVECTOR_ZERO_EXTEND, BITVECTOR_ZERO_EXTEND},
500
        {cvc5::Kind::BITVECTOR_SIGN_EXTEND, BITVECTOR_SIGN_EXTEND},
501
        {cvc5::Kind::BITVECTOR_ROTATE_LEFT, BITVECTOR_ROTATE_LEFT},
502
        {cvc5::Kind::BITVECTOR_ROTATE_RIGHT, BITVECTOR_ROTATE_RIGHT},
503
        {cvc5::Kind::INT_TO_BITVECTOR_OP, INT_TO_BITVECTOR},
504
        {cvc5::Kind::INT_TO_BITVECTOR, INT_TO_BITVECTOR},
505
        {cvc5::Kind::BITVECTOR_TO_NAT, BITVECTOR_TO_NAT},
506
        /* FP -------------------------------------------------------------- */
507
        {cvc5::Kind::CONST_FLOATINGPOINT, CONST_FLOATINGPOINT},
508
        {cvc5::Kind::CONST_ROUNDINGMODE, CONST_ROUNDINGMODE},
509
        {cvc5::Kind::FLOATINGPOINT_FP, FLOATINGPOINT_FP},
510
        {cvc5::Kind::FLOATINGPOINT_EQ, FLOATINGPOINT_EQ},
511
        {cvc5::Kind::FLOATINGPOINT_ABS, FLOATINGPOINT_ABS},
512
        {cvc5::Kind::FLOATINGPOINT_NEG, FLOATINGPOINT_NEG},
513
        {cvc5::Kind::FLOATINGPOINT_ADD, FLOATINGPOINT_ADD},
514
        {cvc5::Kind::FLOATINGPOINT_SUB, FLOATINGPOINT_SUB},
515
        {cvc5::Kind::FLOATINGPOINT_MULT, FLOATINGPOINT_MULT},
516
        {cvc5::Kind::FLOATINGPOINT_DIV, FLOATINGPOINT_DIV},
517
        {cvc5::Kind::FLOATINGPOINT_FMA, FLOATINGPOINT_FMA},
518
        {cvc5::Kind::FLOATINGPOINT_SQRT, FLOATINGPOINT_SQRT},
519
        {cvc5::Kind::FLOATINGPOINT_REM, FLOATINGPOINT_REM},
520
        {cvc5::Kind::FLOATINGPOINT_RTI, FLOATINGPOINT_RTI},
521
        {cvc5::Kind::FLOATINGPOINT_MIN, FLOATINGPOINT_MIN},
522
        {cvc5::Kind::FLOATINGPOINT_MAX, FLOATINGPOINT_MAX},
523
        {cvc5::Kind::FLOATINGPOINT_LEQ, FLOATINGPOINT_LEQ},
524
        {cvc5::Kind::FLOATINGPOINT_LT, FLOATINGPOINT_LT},
525
        {cvc5::Kind::FLOATINGPOINT_GEQ, FLOATINGPOINT_GEQ},
526
        {cvc5::Kind::FLOATINGPOINT_GT, FLOATINGPOINT_GT},
527
        {cvc5::Kind::FLOATINGPOINT_ISN, FLOATINGPOINT_ISN},
528
        {cvc5::Kind::FLOATINGPOINT_ISSN, FLOATINGPOINT_ISSN},
529
        {cvc5::Kind::FLOATINGPOINT_ISZ, FLOATINGPOINT_ISZ},
530
        {cvc5::Kind::FLOATINGPOINT_ISINF, FLOATINGPOINT_ISINF},
531
        {cvc5::Kind::FLOATINGPOINT_ISNAN, FLOATINGPOINT_ISNAN},
532
        {cvc5::Kind::FLOATINGPOINT_ISNEG, FLOATINGPOINT_ISNEG},
533
        {cvc5::Kind::FLOATINGPOINT_ISPOS, FLOATINGPOINT_ISPOS},
534
        {cvc5::Kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR_OP,
535
         FLOATINGPOINT_TO_FP_IEEE_BITVECTOR},
536
        {cvc5::Kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR,
537
         FLOATINGPOINT_TO_FP_IEEE_BITVECTOR},
538
        {cvc5::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT_OP,
539
         FLOATINGPOINT_TO_FP_FLOATINGPOINT},
540
        {cvc5::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT,
541
         FLOATINGPOINT_TO_FP_FLOATINGPOINT},
542
        {cvc5::Kind::FLOATINGPOINT_TO_FP_REAL_OP, FLOATINGPOINT_TO_FP_REAL},
543
        {cvc5::Kind::FLOATINGPOINT_TO_FP_REAL, FLOATINGPOINT_TO_FP_REAL},
544
        {cvc5::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR_OP,
545
         FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR},
546
        {cvc5::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR,
547
         FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR},
548
        {cvc5::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR_OP,
549
         FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR},
550
        {cvc5::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR,
551
         FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR},
552
        {cvc5::Kind::FLOATINGPOINT_TO_FP_GENERIC_OP,
553
         FLOATINGPOINT_TO_FP_GENERIC},
554
        {cvc5::Kind::FLOATINGPOINT_TO_FP_GENERIC, FLOATINGPOINT_TO_FP_GENERIC},
555
        {cvc5::Kind::FLOATINGPOINT_TO_UBV_OP, FLOATINGPOINT_TO_UBV},
556
        {cvc5::Kind::FLOATINGPOINT_TO_UBV, FLOATINGPOINT_TO_UBV},
557
        {cvc5::Kind::FLOATINGPOINT_TO_UBV_TOTAL_OP, INTERNAL_KIND},
558
        {cvc5::Kind::FLOATINGPOINT_TO_UBV_TOTAL, INTERNAL_KIND},
559
        {cvc5::Kind::FLOATINGPOINT_TO_SBV_OP, FLOATINGPOINT_TO_SBV},
560
        {cvc5::Kind::FLOATINGPOINT_TO_SBV, FLOATINGPOINT_TO_SBV},
561
        {cvc5::Kind::FLOATINGPOINT_TO_SBV_TOTAL_OP, INTERNAL_KIND},
562
        {cvc5::Kind::FLOATINGPOINT_TO_SBV_TOTAL, INTERNAL_KIND},
563
        {cvc5::Kind::FLOATINGPOINT_TO_REAL, FLOATINGPOINT_TO_REAL},
564
        {cvc5::Kind::FLOATINGPOINT_TO_REAL_TOTAL, INTERNAL_KIND},
565
        /* Arrays ---------------------------------------------------------- */
566
        {cvc5::Kind::SELECT, SELECT},
567
        {cvc5::Kind::STORE, STORE},
568
        {cvc5::Kind::STORE_ALL, CONST_ARRAY},
569
        /* Datatypes ------------------------------------------------------- */
570
        {cvc5::Kind::APPLY_SELECTOR, APPLY_SELECTOR},
571
        {cvc5::Kind::APPLY_CONSTRUCTOR, APPLY_CONSTRUCTOR},
572
        {cvc5::Kind::APPLY_SELECTOR_TOTAL, INTERNAL_KIND},
573
        {cvc5::Kind::APPLY_TESTER, APPLY_TESTER},
574
        {cvc5::Kind::APPLY_UPDATER, APPLY_UPDATER},
575
        {cvc5::Kind::DT_SIZE, DT_SIZE},
576
        {cvc5::Kind::TUPLE_PROJECT, TUPLE_PROJECT},
577
        {cvc5::Kind::TUPLE_PROJECT_OP, TUPLE_PROJECT},
578
        /* Separation Logic ------------------------------------------------ */
579
        {cvc5::Kind::SEP_NIL, SEP_NIL},
580
        {cvc5::Kind::SEP_EMP, SEP_EMP},
581
        {cvc5::Kind::SEP_PTO, SEP_PTO},
582
        {cvc5::Kind::SEP_STAR, SEP_STAR},
583
        {cvc5::Kind::SEP_WAND, SEP_WAND},
584
        /* Sets ------------------------------------------------------------ */
585
        {cvc5::Kind::EMPTYSET, EMPTYSET},
586
        {cvc5::Kind::UNION, UNION},
587
        {cvc5::Kind::INTERSECTION, INTERSECTION},
588
        {cvc5::Kind::SETMINUS, SETMINUS},
589
        {cvc5::Kind::SUBSET, SUBSET},
590
        {cvc5::Kind::MEMBER, MEMBER},
591
        {cvc5::Kind::SINGLETON, SINGLETON},
592
        {cvc5::Kind::INSERT, INSERT},
593
        {cvc5::Kind::CARD, CARD},
594
        {cvc5::Kind::COMPLEMENT, COMPLEMENT},
595
        {cvc5::Kind::UNIVERSE_SET, UNIVERSE_SET},
596
        {cvc5::Kind::JOIN, JOIN},
597
        {cvc5::Kind::PRODUCT, PRODUCT},
598
        {cvc5::Kind::TRANSPOSE, TRANSPOSE},
599
        {cvc5::Kind::TCLOSURE, TCLOSURE},
600
        {cvc5::Kind::JOIN_IMAGE, JOIN_IMAGE},
601
        {cvc5::Kind::IDEN, IDEN},
602
        {cvc5::Kind::COMPREHENSION, COMPREHENSION},
603
        {cvc5::Kind::CHOOSE, CHOOSE},
604
        {cvc5::Kind::IS_SINGLETON, IS_SINGLETON},
605
        /* Bags ------------------------------------------------------------ */
606
        {cvc5::Kind::UNION_MAX, UNION_MAX},
607
        {cvc5::Kind::UNION_DISJOINT, UNION_DISJOINT},
608
        {cvc5::Kind::INTERSECTION_MIN, INTERSECTION_MIN},
609
        {cvc5::Kind::DIFFERENCE_SUBTRACT, DIFFERENCE_SUBTRACT},
610
        {cvc5::Kind::DIFFERENCE_REMOVE, DIFFERENCE_REMOVE},
611
        {cvc5::Kind::SUBBAG, SUBBAG},
612
        {cvc5::Kind::BAG_COUNT, BAG_COUNT},
613
        {cvc5::Kind::DUPLICATE_REMOVAL, DUPLICATE_REMOVAL},
614
        {cvc5::Kind::MK_BAG, MK_BAG},
615
        {cvc5::Kind::EMPTYBAG, EMPTYBAG},
616
        {cvc5::Kind::BAG_CARD, BAG_CARD},
617
        {cvc5::Kind::BAG_CHOOSE, BAG_CHOOSE},
618
        {cvc5::Kind::BAG_IS_SINGLETON, BAG_IS_SINGLETON},
619
        {cvc5::Kind::BAG_FROM_SET, BAG_FROM_SET},
620
        {cvc5::Kind::BAG_TO_SET, BAG_TO_SET},
621
        {cvc5::Kind::BAG_MAP,BAG_MAP},
622
        /* Strings --------------------------------------------------------- */
623
        {cvc5::Kind::STRING_CONCAT, STRING_CONCAT},
624
        {cvc5::Kind::STRING_IN_REGEXP, STRING_IN_REGEXP},
625
        {cvc5::Kind::STRING_LENGTH, STRING_LENGTH},
626
        {cvc5::Kind::STRING_SUBSTR, STRING_SUBSTR},
627
        {cvc5::Kind::STRING_UPDATE, STRING_UPDATE},
628
        {cvc5::Kind::STRING_CHARAT, STRING_CHARAT},
629
        {cvc5::Kind::STRING_CONTAINS, STRING_CONTAINS},
630
        {cvc5::Kind::STRING_INDEXOF, STRING_INDEXOF},
631
        {cvc5::Kind::STRING_INDEXOF_RE, STRING_INDEXOF_RE},
632
        {cvc5::Kind::STRING_REPLACE, STRING_REPLACE},
633
        {cvc5::Kind::STRING_REPLACE_ALL, STRING_REPLACE_ALL},
634
        {cvc5::Kind::STRING_REPLACE_RE, STRING_REPLACE_RE},
635
        {cvc5::Kind::STRING_REPLACE_RE_ALL, STRING_REPLACE_RE_ALL},
636
        {cvc5::Kind::STRING_TOLOWER, STRING_TOLOWER},
637
        {cvc5::Kind::STRING_TOUPPER, STRING_TOUPPER},
638
        {cvc5::Kind::STRING_REV, STRING_REV},
639
        {cvc5::Kind::STRING_FROM_CODE, STRING_FROM_CODE},
640
        {cvc5::Kind::STRING_TO_CODE, STRING_TO_CODE},
641
        {cvc5::Kind::STRING_LT, STRING_LT},
642
        {cvc5::Kind::STRING_LEQ, STRING_LEQ},
643
        {cvc5::Kind::STRING_PREFIX, STRING_PREFIX},
644
        {cvc5::Kind::STRING_SUFFIX, STRING_SUFFIX},
645
        {cvc5::Kind::STRING_IS_DIGIT, STRING_IS_DIGIT},
646
        {cvc5::Kind::STRING_ITOS, STRING_FROM_INT},
647
        {cvc5::Kind::STRING_STOI, STRING_TO_INT},
648
        {cvc5::Kind::CONST_STRING, CONST_STRING},
649
        {cvc5::Kind::STRING_TO_REGEXP, STRING_TO_REGEXP},
650
        {cvc5::Kind::REGEXP_CONCAT, REGEXP_CONCAT},
651
        {cvc5::Kind::REGEXP_UNION, REGEXP_UNION},
652
        {cvc5::Kind::REGEXP_INTER, REGEXP_INTER},
653
        {cvc5::Kind::REGEXP_DIFF, REGEXP_DIFF},
654
        {cvc5::Kind::REGEXP_STAR, REGEXP_STAR},
655
        {cvc5::Kind::REGEXP_PLUS, REGEXP_PLUS},
656
        {cvc5::Kind::REGEXP_OPT, REGEXP_OPT},
657
        {cvc5::Kind::REGEXP_RANGE, REGEXP_RANGE},
658
        {cvc5::Kind::REGEXP_REPEAT, REGEXP_REPEAT},
659
        {cvc5::Kind::REGEXP_REPEAT_OP, REGEXP_REPEAT},
660
        {cvc5::Kind::REGEXP_LOOP, REGEXP_LOOP},
661
        {cvc5::Kind::REGEXP_LOOP_OP, REGEXP_LOOP},
662
        {cvc5::Kind::REGEXP_EMPTY, REGEXP_EMPTY},
663
        {cvc5::Kind::REGEXP_SIGMA, REGEXP_SIGMA},
664
        {cvc5::Kind::REGEXP_COMPLEMENT, REGEXP_COMPLEMENT},
665
        {cvc5::Kind::CONST_SEQUENCE, CONST_SEQUENCE},
666
        {cvc5::Kind::SEQ_UNIT, SEQ_UNIT},
667
        {cvc5::Kind::SEQ_NTH, SEQ_NTH},
668
        /* Quantifiers ----------------------------------------------------- */
669
        {cvc5::Kind::FORALL, FORALL},
670
        {cvc5::Kind::EXISTS, EXISTS},
671
        {cvc5::Kind::BOUND_VAR_LIST, BOUND_VAR_LIST},
672
        {cvc5::Kind::INST_PATTERN, INST_PATTERN},
673
        {cvc5::Kind::INST_NO_PATTERN, INST_NO_PATTERN},
674
        {cvc5::Kind::INST_POOL, INST_POOL},
675
        {cvc5::Kind::INST_ADD_TO_POOL, INST_ADD_TO_POOL},
676
        {cvc5::Kind::SKOLEM_ADD_TO_POOL, SKOLEM_ADD_TO_POOL},
677
        {cvc5::Kind::INST_ATTRIBUTE, INST_ATTRIBUTE},
678
        {cvc5::Kind::INST_PATTERN_LIST, INST_PATTERN_LIST},
679
        /* ----------------------------------------------------------------- */
680
        {cvc5::Kind::LAST_KIND, LAST_KIND},
681
    };
682
683
/* Set of kinds for indexed operators */
684
10379
const static std::unordered_set<Kind> s_indexed_kinds(
685
    {DIVISIBLE,
686
     IAND,
687
     BITVECTOR_REPEAT,
688
     BITVECTOR_ZERO_EXTEND,
689
     BITVECTOR_SIGN_EXTEND,
690
     BITVECTOR_ROTATE_LEFT,
691
     BITVECTOR_ROTATE_RIGHT,
692
     INT_TO_BITVECTOR,
693
     FLOATINGPOINT_TO_UBV,
694
     FLOATINGPOINT_TO_SBV,
695
     BITVECTOR_EXTRACT,
696
     FLOATINGPOINT_TO_FP_IEEE_BITVECTOR,
697
     FLOATINGPOINT_TO_FP_FLOATINGPOINT,
698
     FLOATINGPOINT_TO_FP_REAL,
699
     FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR,
700
     FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR,
701
     FLOATINGPOINT_TO_FP_GENERIC});
702
703
namespace {
704
705
/** Convert a cvc5::Kind (internal) to a cvc5::api::Kind (external). */
706
5633
cvc5::api::Kind intToExtKind(cvc5::Kind k)
707
{
708
5633
  auto it = api::s_kinds_internal.find(k);
709
5633
  if (it == api::s_kinds_internal.end())
710
  {
711
1302
    return api::INTERNAL_KIND;
712
  }
713
4331
  return it->second;
714
}
715
716
/** Convert a cvc5::api::Kind (external) to a cvc5::Kind (internal). */
717
17255258
cvc5::Kind extToIntKind(cvc5::api::Kind k)
718
{
719
17255258
  auto it = api::s_kinds.find(k);
720
17255258
  if (it == api::s_kinds.end())
721
  {
722
    return cvc5::Kind::UNDEFINED_KIND;
723
  }
724
17255258
  return it->second;
725
}
726
727
/** Return true if given kind is a defined external kind. */
728
8050662
bool isDefinedKind(Kind k) { return k > UNDEFINED_KIND && k < LAST_KIND; }
729
730
/**
731
 * Return true if the internal kind is one where the API term structure
732
 * differs from internal structure. This happens for APPLY_* kinds.
733
 * The API takes a "higher-order" perspective and treats functions as well
734
 * as datatype constructors/selectors/testers as terms
735
 * but interally they are not
736
 */
737
3682247
bool isApplyKind(cvc5::Kind k)
738
{
739
3055053
  return (k == cvc5::Kind::APPLY_UF || k == cvc5::Kind::APPLY_CONSTRUCTOR
740
3037115
          || k == cvc5::Kind::APPLY_SELECTOR || k == cvc5::Kind::APPLY_TESTER
741
6694520
          || k == cvc5::Kind::APPLY_UPDATER);
742
}
743
744
#ifdef CVC5_ASSERTIONS
745
/** Return true if given kind is a defined internal kind. */
746
5520091
bool isDefinedIntKind(cvc5::Kind k)
747
{
748
5520091
  return k != cvc5::Kind::UNDEFINED_KIND && k != cvc5::Kind::LAST_KIND;
749
}
750
#endif
751
752
/** Return the minimum arity of given kind. */
753
1840041
uint32_t minArity(Kind k)
754
{
755
1840041
  Assert(isDefinedKind(k));
756
1840041
  Assert(isDefinedIntKind(extToIntKind(k)));
757
1840041
  uint32_t min = cvc5::kind::metakind::getMinArityForKind(extToIntKind(k));
758
759
  // At the API level, we treat functions/constructors/selectors/testers as
760
  // normal terms instead of making them part of the operator
761
1840041
  if (isApplyKind(extToIntKind(k)))
762
  {
763
334084
    min++;
764
  }
765
1840041
  return min;
766
}
767
768
/** Return the maximum arity of given kind. */
769
1840027
uint32_t maxArity(Kind k)
770
{
771
1840027
  Assert(isDefinedKind(k));
772
1840027
  Assert(isDefinedIntKind(extToIntKind(k)));
773
1840027
  uint32_t max = cvc5::kind::metakind::getMaxArityForKind(extToIntKind(k));
774
775
  // At the API level, we treat functions/constructors/selectors/testers as
776
  // normal terms instead of making them part of the operator
777
3680054
  if (isApplyKind(extToIntKind(k))
778
1840027
      && max != std::numeric_limits<uint32_t>::max())  // be careful not to
779
                                                       // overflow
780
  {
781
334078
    max++;
782
  }
783
1840027
  return max;
784
}
785
786
}  // namespace
787
788
60
std::string kindToString(Kind k)
789
{
790
  return k == INTERNAL_KIND ? "INTERNAL_KIND"
791
60
                            : cvc5::kind::kindToString(extToIntKind(k));
792
}
793
794
const char* toString(Kind k)
795
{
796
  return k == INTERNAL_KIND ? "INTERNAL_KIND"
797
                            : cvc5::kind::toString(extToIntKind(k));
798
}
799
800
2726
std::ostream& operator<<(std::ostream& out, Kind k)
801
{
802
2726
  switch (k)
803
  {
804
    case INTERNAL_KIND: out << "INTERNAL_KIND"; break;
805
2726
    default: out << extToIntKind(k);
806
  }
807
2726
  return out;
808
}
809
810
/* -------------------------------------------------------------------------- */
811
/* API guard helpers                                                          */
812
/* -------------------------------------------------------------------------- */
813
814
namespace {
815
816
class CVC5ApiExceptionStream
817
{
818
 public:
819
775
  CVC5ApiExceptionStream() {}
820
  /* Note: This needs to be explicitly set to 'noexcept(false)' since it is
821
   * a destructor that throws an exception and in C++11 all destructors
822
   * default to noexcept(true) (else this triggers a call to std::terminate). */
823
775
  ~CVC5ApiExceptionStream() noexcept(false)
824
775
  {
825
775
    if (std::uncaught_exceptions() == 0)
826
    {
827
775
      throw CVC5ApiException(d_stream.str());
828
    }
829
  }
830
831
775
  std::ostream& ostream() { return d_stream; }
832
833
 private:
834
  std::stringstream d_stream;
835
};
836
837
class CVC5ApiRecoverableExceptionStream
838
{
839
 public:
840
41
  CVC5ApiRecoverableExceptionStream() {}
841
  /* Note: This needs to be explicitly set to 'noexcept(false)' since it is
842
   * a destructor that throws an exception and in C++11 all destructors
843
   * default to noexcept(true) (else this triggers a call to std::terminate). */
844
41
  ~CVC5ApiRecoverableExceptionStream() noexcept(false)
845
41
  {
846
41
    if (std::uncaught_exceptions() == 0)
847
    {
848
41
      throw CVC5ApiRecoverableException(d_stream.str());
849
    }
850
  }
851
852
41
  std::ostream& ostream() { return d_stream; }
853
854
 private:
855
  std::stringstream d_stream;
856
};
857
858
class CVC5ApiUnsupportedExceptionStream
859
{
860
 public:
861
24
  CVC5ApiUnsupportedExceptionStream() {}
862
  /* Note: This needs to be explicitly set to 'noexcept(false)' since it is
863
   * a destructor that throws an exception and in C++11 all destructors
864
   * default to noexcept(true) (else this triggers a call to std::terminate). */
865
24
  ~CVC5ApiUnsupportedExceptionStream() noexcept(false)
866
24
  {
867
24
    if (std::uncaught_exceptions() == 0)
868
    {
869
24
      throw CVC5ApiUnsupportedException(d_stream.str());
870
    }
871
  }
872
873
24
  std::ostream& ostream() { return d_stream; }
874
875
 private:
876
  std::stringstream d_stream;
877
};
878
879
#define CVC5_API_TRY_CATCH_BEGIN \
880
  try                            \
881
  {
882
#define CVC5_API_TRY_CATCH_END                                                 \
883
  }                                                                            \
884
  catch (const OptionException& e)                                             \
885
  {                                                                            \
886
    throw CVC5ApiOptionException(e.getMessage());                              \
887
  }                                                                            \
888
  catch (const cvc5::RecoverableModalException& e)                             \
889
  {                                                                            \
890
    throw CVC5ApiRecoverableException(e.getMessage());                         \
891
  }                                                                            \
892
  catch (const cvc5::Exception& e) { throw CVC5ApiException(e.getMessage()); } \
893
  catch (const std::invalid_argument& e) { throw CVC5ApiException(e.what()); }
894
895
}  // namespace
896
897
/* -------------------------------------------------------------------------- */
898
/* Result                                                                     */
899
/* -------------------------------------------------------------------------- */
900
901
11512
Result::Result(const cvc5::Result& r) : d_result(new cvc5::Result(r)) {}
902
903
269718
Result::Result() : d_result(new cvc5::Result()) {}
904
905
4
bool Result::isNull() const
906
{
907
4
  return d_result->getType() == cvc5::Result::TYPE_NONE;
908
}
909
910
242585
bool Result::isSat(void) const
911
{
912
242585
  return d_result->getType() == cvc5::Result::TYPE_SAT
913
242585
         && d_result->isSat() == cvc5::Result::SAT;
914
}
915
916
243323
bool Result::isUnsat(void) const
917
{
918
243323
  return d_result->getType() == cvc5::Result::TYPE_SAT
919
243323
         && d_result->isSat() == cvc5::Result::UNSAT;
920
}
921
922
189
bool Result::isSatUnknown(void) const
923
{
924
189
  return d_result->getType() == cvc5::Result::TYPE_SAT
925
189
         && d_result->isSat() == cvc5::Result::SAT_UNKNOWN;
926
}
927
928
237998
bool Result::isEntailed(void) const
929
{
930
237998
  return d_result->getType() == cvc5::Result::TYPE_ENTAILMENT
931
237998
         && d_result->isEntailed() == cvc5::Result::ENTAILED;
932
}
933
934
236084
bool Result::isNotEntailed(void) const
935
{
936
236084
  return d_result->getType() == cvc5::Result::TYPE_ENTAILMENT
937
236084
         && d_result->isEntailed() == cvc5::Result::NOT_ENTAILED;
938
}
939
940
8
bool Result::isEntailmentUnknown(void) const
941
{
942
8
  return d_result->getType() == cvc5::Result::TYPE_ENTAILMENT
943
8
         && d_result->isEntailed() == cvc5::Result::ENTAILMENT_UNKNOWN;
944
}
945
946
4
bool Result::operator==(const Result& r) const
947
{
948
4
  return *d_result == *r.d_result;
949
}
950
951
bool Result::operator!=(const Result& r) const
952
{
953
  return *d_result != *r.d_result;
954
}
955
956
2
Result::UnknownExplanation Result::getUnknownExplanation(void) const
957
{
958
2
  cvc5::Result::UnknownExplanation expl = d_result->whyUnknown();
959
2
  switch (expl)
960
  {
961
    case cvc5::Result::REQUIRES_FULL_CHECK: return REQUIRES_FULL_CHECK;
962
    case cvc5::Result::INCOMPLETE: return INCOMPLETE;
963
    case cvc5::Result::TIMEOUT: return TIMEOUT;
964
    case cvc5::Result::RESOURCEOUT: return RESOURCEOUT;
965
    case cvc5::Result::MEMOUT: return MEMOUT;
966
    case cvc5::Result::INTERRUPTED: return INTERRUPTED;
967
    case cvc5::Result::NO_STATUS: return NO_STATUS;
968
    case cvc5::Result::UNSUPPORTED: return UNSUPPORTED;
969
    case cvc5::Result::OTHER: return OTHER;
970
2
    default: return UNKNOWN_REASON;
971
  }
972
  return UNKNOWN_REASON;
973
}
974
975
11362
std::string Result::toString(void) const { return d_result->toString(); }
976
977
11362
std::ostream& operator<<(std::ostream& out, const Result& r)
978
{
979
11362
  out << r.toString();
980
11362
  return out;
981
}
982
983
std::ostream& operator<<(std::ostream& out, enum Result::UnknownExplanation e)
984
{
985
  switch (e)
986
  {
987
    case Result::REQUIRES_FULL_CHECK: out << "REQUIRES_FULL_CHECK"; break;
988
    case Result::INCOMPLETE: out << "INCOMPLETE"; break;
989
    case Result::TIMEOUT: out << "TIMEOUT"; break;
990
    case Result::RESOURCEOUT: out << "RESOURCEOUT"; break;
991
    case Result::MEMOUT: out << "MEMOUT"; break;
992
    case Result::INTERRUPTED: out << "INTERRUPTED"; break;
993
    case Result::NO_STATUS: out << "NO_STATUS"; break;
994
    case Result::UNSUPPORTED: out << "UNSUPPORTED"; break;
995
    case Result::OTHER: out << "OTHER"; break;
996
    case Result::UNKNOWN_REASON: out << "UNKNOWN_REASON"; break;
997
    default: Unhandled() << e;
998
  }
999
  return out;
1000
}
1001
1002
/* -------------------------------------------------------------------------- */
1003
/* Sort                                                                       */
1004
/* -------------------------------------------------------------------------- */
1005
1006
5261760
Sort::Sort(const Solver* slv, const cvc5::TypeNode& t)
1007
5261760
    : d_solver(slv), d_type(new cvc5::TypeNode(t))
1008
{
1009
5261760
}
1010
1011
28674447
Sort::Sort() : d_solver(nullptr), d_type(new cvc5::TypeNode()) {}
1012
1013
80435816
Sort::~Sort()
1014
{
1015
40217908
  if (d_solver != nullptr)
1016
  {
1017
6664764
    d_type.reset();
1018
  }
1019
40217908
}
1020
1021
1186
std::set<TypeNode> Sort::sortSetToTypeNodes(const std::set<Sort>& sorts)
1022
{
1023
1186
  std::set<TypeNode> types;
1024
2738
  for (const Sort& s : sorts)
1025
  {
1026
1552
    types.insert(s.getTypeNode());
1027
  }
1028
1186
  return types;
1029
}
1030
1031
32635
std::vector<TypeNode> Sort::sortVectorToTypeNodes(
1032
    const std::vector<Sort>& sorts)
1033
{
1034
32635
  std::vector<TypeNode> typeNodes;
1035
113345
  for (const Sort& sort : sorts)
1036
  {
1037
80710
    typeNodes.push_back(sort.getTypeNode());
1038
  }
1039
32635
  return typeNodes;
1040
}
1041
1042
1691
std::vector<Sort> Sort::typeNodeVectorToSorts(
1043
    const Solver* slv, const std::vector<TypeNode>& types)
1044
{
1045
1691
  std::vector<Sort> sorts;
1046
3975
  for (size_t i = 0, tsize = types.size(); i < tsize; i++)
1047
  {
1048
2284
    sorts.push_back(Sort(slv, types[i]));
1049
  }
1050
1691
  return sorts;
1051
}
1052
1053
565136
bool Sort::operator==(const Sort& s) const
1054
{
1055
  CVC5_API_TRY_CATCH_BEGIN;
1056
  //////// all checks before this line
1057
565136
  return *d_type == *s.d_type;
1058
  ////////
1059
  CVC5_API_TRY_CATCH_END;
1060
}
1061
1062
1060
bool Sort::operator!=(const Sort& s) const
1063
{
1064
  CVC5_API_TRY_CATCH_BEGIN;
1065
  //////// all checks before this line
1066
1060
  return *d_type != *s.d_type;
1067
  ////////
1068
  CVC5_API_TRY_CATCH_END;
1069
}
1070
1071
2217
bool Sort::operator<(const Sort& s) const
1072
{
1073
  CVC5_API_TRY_CATCH_BEGIN;
1074
  //////// all checks before this line
1075
2217
  return *d_type < *s.d_type;
1076
  ////////
1077
  CVC5_API_TRY_CATCH_END;
1078
}
1079
1080
6
bool Sort::operator>(const Sort& s) const
1081
{
1082
  CVC5_API_TRY_CATCH_BEGIN;
1083
  //////// all checks before this line
1084
6
  return *d_type > *s.d_type;
1085
  ////////
1086
  CVC5_API_TRY_CATCH_END;
1087
}
1088
1089
4
bool Sort::operator<=(const Sort& s) const
1090
{
1091
  CVC5_API_TRY_CATCH_BEGIN;
1092
  //////// all checks before this line
1093
4
  return *d_type <= *s.d_type;
1094
  ////////
1095
  CVC5_API_TRY_CATCH_END;
1096
}
1097
1098
6
bool Sort::operator>=(const Sort& s) const
1099
{
1100
  CVC5_API_TRY_CATCH_BEGIN;
1101
  //////// all checks before this line
1102
6
  return *d_type >= *s.d_type;
1103
  ////////
1104
  CVC5_API_TRY_CATCH_END;
1105
}
1106
1107
2864433
bool Sort::isNull() const
1108
{
1109
  CVC5_API_TRY_CATCH_BEGIN;
1110
  //////// all checks before this line
1111
2864433
  return isNullHelper();
1112
  ////////
1113
  CVC5_API_TRY_CATCH_END;
1114
}
1115
1116
10
bool Sort::isBoolean() const
1117
{
1118
  CVC5_API_TRY_CATCH_BEGIN;
1119
  //////// all checks before this line
1120
10
  return d_type->isBoolean();
1121
  ////////
1122
  CVC5_API_TRY_CATCH_END;
1123
}
1124
1125
14
bool Sort::isInteger() const
1126
{
1127
  CVC5_API_TRY_CATCH_BEGIN;
1128
  //////// all checks before this line
1129
14
  return d_type->isInteger();
1130
  ////////
1131
  CVC5_API_TRY_CATCH_END;
1132
}
1133
1134
724
bool Sort::isReal() const
1135
{
1136
  CVC5_API_TRY_CATCH_BEGIN;
1137
  //////// all checks before this line
1138
  // notice that we do not expose internal subtyping to the user
1139
724
  return d_type->isReal() && !d_type->isInteger();
1140
  ////////
1141
  CVC5_API_TRY_CATCH_END;
1142
}
1143
1144
4
bool Sort::isString() const
1145
{
1146
  CVC5_API_TRY_CATCH_BEGIN;
1147
  //////// all checks before this line
1148
4
  return d_type->isString();
1149
  ////////
1150
  CVC5_API_TRY_CATCH_END;
1151
}
1152
1153
4
bool Sort::isRegExp() const
1154
{
1155
  CVC5_API_TRY_CATCH_BEGIN;
1156
  //////// all checks before this line
1157
4
  return d_type->isRegExp();
1158
  ////////
1159
  CVC5_API_TRY_CATCH_END;
1160
}
1161
1162
4
bool Sort::isRoundingMode() const
1163
{
1164
  CVC5_API_TRY_CATCH_BEGIN;
1165
  //////// all checks before this line
1166
4
  return d_type->isRoundingMode();
1167
  ////////
1168
  CVC5_API_TRY_CATCH_END;
1169
}
1170
1171
9
bool Sort::isBitVector() const
1172
{
1173
  CVC5_API_TRY_CATCH_BEGIN;
1174
  //////// all checks before this line
1175
9
  return d_type->isBitVector();
1176
  ////////
1177
  CVC5_API_TRY_CATCH_END;
1178
}
1179
1180
12
bool Sort::isFloatingPoint() const
1181
{
1182
  CVC5_API_TRY_CATCH_BEGIN;
1183
  //////// all checks before this line
1184
12
  return d_type->isFloatingPoint();
1185
  ////////
1186
  CVC5_API_TRY_CATCH_END;
1187
}
1188
1189
7450
bool Sort::isDatatype() const
1190
{
1191
  CVC5_API_TRY_CATCH_BEGIN;
1192
  //////// all checks before this line
1193
7450
  return d_type->isDatatype();
1194
  ////////
1195
  CVC5_API_TRY_CATCH_END;
1196
}
1197
1198
2427
bool Sort::isParametricDatatype() const
1199
{
1200
  CVC5_API_TRY_CATCH_BEGIN;
1201
  //////// all checks before this line
1202
2427
  if (!d_type->isDatatype()) return false;
1203
1999
  return d_type->isParametricDatatype();
1204
  ////////
1205
  CVC5_API_TRY_CATCH_END;
1206
}
1207
1208
2555706
bool Sort::isConstructor() const
1209
{
1210
  CVC5_API_TRY_CATCH_BEGIN;
1211
  //////// all checks before this line
1212
2555706
  return d_type->isConstructor();
1213
  ////////
1214
  CVC5_API_TRY_CATCH_END;
1215
}
1216
1217
23155
bool Sort::isSelector() const
1218
{
1219
  CVC5_API_TRY_CATCH_BEGIN;
1220
  //////// all checks before this line
1221
23155
  return d_type->isSelector();
1222
  ////////
1223
  CVC5_API_TRY_CATCH_END;
1224
}
1225
1226
12601
bool Sort::isTester() const
1227
{
1228
  CVC5_API_TRY_CATCH_BEGIN;
1229
  //////// all checks before this line
1230
12601
  return d_type->isTester();
1231
  ////////
1232
  CVC5_API_TRY_CATCH_END;
1233
}
1234
1235
35
bool Sort::isUpdater() const
1236
{
1237
  CVC5_API_TRY_CATCH_BEGIN;
1238
  //////// all checks before this line
1239
35
  return d_type->isUpdater();
1240
  ////////
1241
  CVC5_API_TRY_CATCH_END;
1242
}
1243
1244
1957657
bool Sort::isFunction() const
1245
{
1246
  CVC5_API_TRY_CATCH_BEGIN;
1247
  //////// all checks before this line
1248
1957657
  return d_type->isFunction();
1249
  ////////
1250
  CVC5_API_TRY_CATCH_END;
1251
}
1252
1253
4
bool Sort::isPredicate() const
1254
{
1255
  CVC5_API_TRY_CATCH_BEGIN;
1256
  //////// all checks before this line
1257
4
  return d_type->isPredicate();
1258
  ////////
1259
  CVC5_API_TRY_CATCH_END;
1260
}
1261
1262
122
bool Sort::isTuple() const
1263
{
1264
  CVC5_API_TRY_CATCH_BEGIN;
1265
  //////// all checks before this line
1266
122
  return d_type->isTuple();
1267
  ////////
1268
  CVC5_API_TRY_CATCH_END;
1269
}
1270
1271
4
bool Sort::isRecord() const
1272
{
1273
  CVC5_API_TRY_CATCH_BEGIN;
1274
  //////// all checks before this line
1275
4
  return d_type->isRecord();
1276
  ////////
1277
  CVC5_API_TRY_CATCH_END;
1278
}
1279
1280
346
bool Sort::isArray() const
1281
{
1282
  CVC5_API_TRY_CATCH_BEGIN;
1283
  //////// all checks before this line
1284
346
  return d_type->isArray();
1285
  ////////
1286
  CVC5_API_TRY_CATCH_END;
1287
}
1288
1289
182
bool Sort::isSet() const
1290
{
1291
  CVC5_API_TRY_CATCH_BEGIN;
1292
  //////// all checks before this line
1293
182
  return d_type->isSet();
1294
  ////////
1295
  CVC5_API_TRY_CATCH_END;
1296
}
1297
1298
35
bool Sort::isBag() const
1299
{
1300
  CVC5_API_TRY_CATCH_BEGIN;
1301
  //////// all checks before this line
1302
35
  return d_type->isBag();
1303
  ////////
1304
  CVC5_API_TRY_CATCH_END;
1305
}
1306
1307
34
bool Sort::isSequence() const
1308
{
1309
  CVC5_API_TRY_CATCH_BEGIN;
1310
  //////// all checks before this line
1311
34
  return d_type->isSequence();
1312
  ////////
1313
  CVC5_API_TRY_CATCH_END;
1314
}
1315
1316
86
bool Sort::isUninterpretedSort() const
1317
{
1318
  CVC5_API_TRY_CATCH_BEGIN;
1319
  //////// all checks before this line
1320
86
  return d_type->isSort();
1321
  ////////
1322
  CVC5_API_TRY_CATCH_END;
1323
}
1324
1325
858
bool Sort::isSortConstructor() const
1326
{
1327
  CVC5_API_TRY_CATCH_BEGIN;
1328
  //////// all checks before this line
1329
858
  return d_type->isSortConstructor();
1330
  ////////
1331
  CVC5_API_TRY_CATCH_END;
1332
}
1333
1334
70179
bool Sort::isFirstClass() const
1335
{
1336
  CVC5_API_TRY_CATCH_BEGIN;
1337
  //////// all checks before this line
1338
70179
  return d_type->isFirstClass();
1339
  ////////
1340
  CVC5_API_TRY_CATCH_END;
1341
}
1342
1343
4096
bool Sort::isFunctionLike() const
1344
{
1345
  CVC5_API_TRY_CATCH_BEGIN;
1346
  //////// all checks before this line
1347
4096
  return d_type->isFunctionLike();
1348
  ////////
1349
  CVC5_API_TRY_CATCH_END;
1350
}
1351
1352
7623
bool Sort::isSubsortOf(const Sort& s) const
1353
{
1354
  CVC5_API_TRY_CATCH_BEGIN;
1355
7623
  CVC5_API_ARG_CHECK_SOLVER("sort", s);
1356
  //////// all checks before this line
1357
7623
  return d_type->isSubtypeOf(*s.d_type);
1358
  ////////
1359
  CVC5_API_TRY_CATCH_END;
1360
}
1361
1362
149
bool Sort::isComparableTo(const Sort& s) const
1363
{
1364
  CVC5_API_TRY_CATCH_BEGIN;
1365
149
  CVC5_API_ARG_CHECK_SOLVER("sort", s);
1366
  //////// all checks before this line
1367
149
  return d_type->isComparableTo(*s.d_type);
1368
  ////////
1369
  CVC5_API_TRY_CATCH_END;
1370
}
1371
1372
6784
Datatype Sort::getDatatype() const
1373
{
1374
  CVC5_API_TRY_CATCH_BEGIN;
1375
6784
  CVC5_API_CHECK_NOT_NULL;
1376
6784
  CVC5_API_CHECK(isDatatype()) << "Expected datatype sort.";
1377
  //////// all checks before this line
1378
6782
  return Datatype(d_solver, d_type->getDType());
1379
  ////////
1380
  CVC5_API_TRY_CATCH_END;
1381
}
1382
1383
620
Sort Sort::instantiate(const std::vector<Sort>& params) const
1384
{
1385
  CVC5_API_TRY_CATCH_BEGIN;
1386
620
  CVC5_API_CHECK_NOT_NULL;
1387
620
  CVC5_API_CHECK_SORTS(params);
1388
622
  CVC5_API_CHECK(isParametricDatatype() || isSortConstructor())
1389
2
      << "Expected parametric datatype or sort constructor sort.";
1390
  //////// all checks before this line
1391
1236
  std::vector<cvc5::TypeNode> tparams = sortVectorToTypeNodes(params);
1392
618
  if (d_type->isDatatype())
1393
  {
1394
192
    return Sort(d_solver, d_type->instantiateParametricDatatype(tparams));
1395
  }
1396
426
  Assert(d_type->isSortConstructor());
1397
426
  return Sort(d_solver, d_solver->getNodeManager()->mkSort(*d_type, tparams));
1398
  ////////
1399
  CVC5_API_TRY_CATCH_END;
1400
}
1401
1402
2
Sort Sort::substitute(const Sort& sort, const Sort& replacement) const
1403
{
1404
  CVC5_API_TRY_CATCH_BEGIN;
1405
2
  CVC5_API_CHECK_NOT_NULL;
1406
2
  CVC5_API_CHECK_SORT(sort);
1407
2
  CVC5_API_CHECK_SORT(replacement);
1408
  //////// all checks before this line
1409
  return Sort(
1410
2
      d_solver,
1411
4
      d_type->substitute(sort.getTypeNode(), replacement.getTypeNode()));
1412
  ////////
1413
  CVC5_API_TRY_CATCH_END;
1414
}
1415
1416
4
Sort Sort::substitute(const std::vector<Sort>& sorts,
1417
                      const std::vector<Sort>& replacements) const
1418
{
1419
  CVC5_API_TRY_CATCH_BEGIN;
1420
4
  CVC5_API_CHECK_NOT_NULL;
1421
4
  CVC5_API_CHECK_SORTS(sorts);
1422
4
  CVC5_API_CHECK_SORTS(replacements);
1423
  //////// all checks before this line
1424
1425
8
  std::vector<cvc5::TypeNode> tSorts = sortVectorToTypeNodes(sorts),
1426
                              tReplacements =
1427
8
                                  sortVectorToTypeNodes(replacements);
1428
4
  return Sort(d_solver,
1429
8
              d_type->substitute(tSorts.begin(),
1430
                                 tSorts.end(),
1431
                                 tReplacements.begin(),
1432
8
                                 tReplacements.end()));
1433
  ////////
1434
  CVC5_API_TRY_CATCH_END;
1435
}
1436
1437
68
std::string Sort::toString() const
1438
{
1439
  CVC5_API_TRY_CATCH_BEGIN;
1440
  //////// all checks before this line
1441
68
  if (d_solver != nullptr)
1442
  {
1443
68
    return d_type->toString();
1444
  }
1445
  return d_type->toString();
1446
  ////////
1447
  CVC5_API_TRY_CATCH_END;
1448
}
1449
1450
257733
const cvc5::TypeNode& Sort::getTypeNode(void) const { return *d_type; }
1451
1452
/* Constructor sort ------------------------------------------------------- */
1453
1454
3943
size_t Sort::getConstructorArity() const
1455
{
1456
  CVC5_API_TRY_CATCH_BEGIN;
1457
3943
  CVC5_API_CHECK_NOT_NULL;
1458
3943
  CVC5_API_CHECK(isConstructor()) << "Not a constructor sort: " << (*this);
1459
  //////// all checks before this line
1460
3941
  return d_type->getNumChildren() - 1;
1461
  ////////
1462
  CVC5_API_TRY_CATCH_END;
1463
}
1464
1465
90
std::vector<Sort> Sort::getConstructorDomainSorts() const
1466
{
1467
  CVC5_API_TRY_CATCH_BEGIN;
1468
90
  CVC5_API_CHECK_NOT_NULL;
1469
90
  CVC5_API_CHECK(isConstructor()) << "Not a constructor sort: " << (*this);
1470
  //////// all checks before this line
1471
88
  return typeNodeVectorToSorts(d_solver, d_type->getArgTypes());
1472
  ////////
1473
  CVC5_API_TRY_CATCH_END;
1474
}
1475
1476
1826
Sort Sort::getConstructorCodomainSort() const
1477
{
1478
  CVC5_API_TRY_CATCH_BEGIN;
1479
1826
  CVC5_API_CHECK_NOT_NULL;
1480
1826
  CVC5_API_CHECK(isConstructor()) << "Not a constructor sort: " << (*this);
1481
  //////// all checks before this line
1482
1824
  return Sort(d_solver, d_type->getConstructorRangeType());
1483
  ////////
1484
  CVC5_API_TRY_CATCH_END;
1485
}
1486
1487
/* Selector sort ------------------------------------------------------- */
1488
1489
83
Sort Sort::getSelectorDomainSort() const
1490
{
1491
  CVC5_API_TRY_CATCH_BEGIN;
1492
83
  CVC5_API_CHECK_NOT_NULL;
1493
83
  CVC5_API_CHECK(isSelector()) << "Not a selector sort: " << (*this);
1494
  //////// all checks before this line
1495
81
  return Sort(d_solver, d_type->getSelectorDomainType());
1496
  ////////
1497
  CVC5_API_TRY_CATCH_END;
1498
}
1499
1500
52
Sort Sort::getSelectorCodomainSort() const
1501
{
1502
  CVC5_API_TRY_CATCH_BEGIN;
1503
52
  CVC5_API_CHECK_NOT_NULL;
1504
52
  CVC5_API_CHECK(isSelector()) << "Not a selector sort: " << (*this);
1505
  //////// all checks before this line
1506
50
  return Sort(d_solver, d_type->getSelectorRangeType());
1507
  ////////
1508
  CVC5_API_TRY_CATCH_END;
1509
}
1510
1511
/* Tester sort ------------------------------------------------------- */
1512
1513
42
Sort Sort::getTesterDomainSort() const
1514
{
1515
  CVC5_API_TRY_CATCH_BEGIN;
1516
42
  CVC5_API_CHECK_NOT_NULL;
1517
42
  CVC5_API_CHECK(isTester()) << "Not a tester sort: " << (*this);
1518
  //////// all checks before this line
1519
40
  return Sort(d_solver, d_type->getTesterDomainType());
1520
  ////////
1521
  CVC5_API_TRY_CATCH_END;
1522
}
1523
1524
42
Sort Sort::getTesterCodomainSort() const
1525
{
1526
  CVC5_API_TRY_CATCH_BEGIN;
1527
42
  CVC5_API_CHECK_NOT_NULL;
1528
42
  CVC5_API_CHECK(isTester()) << "Not a tester sort: " << (*this);
1529
  //////// all checks before this line
1530
40
  return d_solver->getBooleanSort();
1531
  ////////
1532
  CVC5_API_TRY_CATCH_END;
1533
}
1534
1535
/* Function sort ------------------------------------------------------- */
1536
1537
313671
size_t Sort::getFunctionArity() const
1538
{
1539
  CVC5_API_TRY_CATCH_BEGIN;
1540
313671
  CVC5_API_CHECK_NOT_NULL;
1541
313671
  CVC5_API_CHECK(isFunction()) << "Not a function sort: " << (*this);
1542
  //////// all checks before this line
1543
313669
  return d_type->getNumChildren() - 1;
1544
  ////////
1545
  CVC5_API_TRY_CATCH_END;
1546
}
1547
1548
354
std::vector<Sort> Sort::getFunctionDomainSorts() const
1549
{
1550
  CVC5_API_TRY_CATCH_BEGIN;
1551
354
  CVC5_API_CHECK_NOT_NULL;
1552
354
  CVC5_API_CHECK(isFunction()) << "Not a function sort: " << (*this);
1553
  //////// all checks before this line
1554
352
  return typeNodeVectorToSorts(d_solver, d_type->getArgTypes());
1555
  ////////
1556
  CVC5_API_TRY_CATCH_END;
1557
}
1558
1559
1791
Sort Sort::getFunctionCodomainSort() const
1560
{
1561
  CVC5_API_TRY_CATCH_BEGIN;
1562
1791
  CVC5_API_CHECK_NOT_NULL;
1563
1791
  CVC5_API_CHECK(isFunction()) << "Not a function sort" << (*this);
1564
  //////// all checks before this line
1565
1789
  return Sort(d_solver, d_type->getRangeType());
1566
  ////////
1567
  CVC5_API_TRY_CATCH_END;
1568
}
1569
1570
/* Array sort ---------------------------------------------------------- */
1571
1572
4
Sort Sort::getArrayIndexSort() const
1573
{
1574
  CVC5_API_TRY_CATCH_BEGIN;
1575
4
  CVC5_API_CHECK_NOT_NULL;
1576
4
  CVC5_API_CHECK(isArray()) << "Not an array sort.";
1577
  //////// all checks before this line
1578
2
  return Sort(d_solver, d_type->getArrayIndexType());
1579
  ////////
1580
  CVC5_API_TRY_CATCH_END;
1581
}
1582
1583
170
Sort Sort::getArrayElementSort() const
1584
{
1585
  CVC5_API_TRY_CATCH_BEGIN;
1586
170
  CVC5_API_CHECK_NOT_NULL;
1587
170
  CVC5_API_CHECK(isArray()) << "Not an array sort.";
1588
  //////// all checks before this line
1589
168
  return Sort(d_solver, d_type->getArrayConstituentType());
1590
  ////////
1591
  CVC5_API_TRY_CATCH_END;
1592
}
1593
1594
/* Set sort ------------------------------------------------------------ */
1595
1596
6
Sort Sort::getSetElementSort() const
1597
{
1598
  CVC5_API_TRY_CATCH_BEGIN;
1599
6
  CVC5_API_CHECK_NOT_NULL;
1600
6
  CVC5_API_CHECK(isSet()) << "Not a set sort.";
1601
  //////// all checks before this line
1602
4
  return Sort(d_solver, d_type->getSetElementType());
1603
  ////////
1604
  CVC5_API_TRY_CATCH_END;
1605
}
1606
1607
/* Bag sort ------------------------------------------------------------ */
1608
1609
6
Sort Sort::getBagElementSort() const
1610
{
1611
  CVC5_API_TRY_CATCH_BEGIN;
1612
6
  CVC5_API_CHECK_NOT_NULL;
1613
6
  CVC5_API_CHECK(isBag()) << "Not a bag sort.";
1614
  //////// all checks before this line
1615
4
  return Sort(d_solver, d_type->getBagElementType());
1616
  ////////
1617
  CVC5_API_TRY_CATCH_END;
1618
}
1619
1620
/* Sequence sort ------------------------------------------------------- */
1621
1622
15
Sort Sort::getSequenceElementSort() const
1623
{
1624
  CVC5_API_TRY_CATCH_BEGIN;
1625
15
  CVC5_API_CHECK_NOT_NULL;
1626
15
  CVC5_API_CHECK(isSequence()) << "Not a sequence sort.";
1627
  //////// all checks before this line
1628
13
  return Sort(d_solver, d_type->getSequenceElementType());
1629
  ////////
1630
  CVC5_API_TRY_CATCH_END;
1631
}
1632
1633
/* Uninterpreted sort -------------------------------------------------- */
1634
1635
4
std::string Sort::getUninterpretedSortName() const
1636
{
1637
  CVC5_API_TRY_CATCH_BEGIN;
1638
4
  CVC5_API_CHECK_NOT_NULL;
1639
4
  CVC5_API_CHECK(isUninterpretedSort()) << "Not an uninterpreted sort.";
1640
  //////// all checks before this line
1641
2
  return d_type->getName();
1642
  ////////
1643
  CVC5_API_TRY_CATCH_END;
1644
}
1645
1646
6
bool Sort::isUninterpretedSortParameterized() const
1647
{
1648
  CVC5_API_TRY_CATCH_BEGIN;
1649
6
  CVC5_API_CHECK_NOT_NULL;
1650
6
  CVC5_API_CHECK(isUninterpretedSort()) << "Not an uninterpreted sort.";
1651
  //////// all checks before this line
1652
1653
  /* This method is not implemented in the NodeManager, since whether a
1654
   * uninterpreted sort is parameterized is irrelevant for solving. */
1655
4
  return d_type->getNumChildren() > 0;
1656
  ////////
1657
  CVC5_API_TRY_CATCH_END;
1658
}
1659
1660
6
std::vector<Sort> Sort::getUninterpretedSortParamSorts() const
1661
{
1662
  CVC5_API_TRY_CATCH_BEGIN;
1663
6
  CVC5_API_CHECK_NOT_NULL;
1664
6
  CVC5_API_CHECK(isUninterpretedSort()) << "Not an uninterpreted sort.";
1665
  //////// all checks before this line
1666
1667
  /* This method is not implemented in the NodeManager, since whether a
1668
   * uninterpreted sort is parameterized is irrelevant for solving. */
1669
8
  std::vector<TypeNode> params;
1670
8
  for (size_t i = 0, nchildren = d_type->getNumChildren(); i < nchildren; i++)
1671
  {
1672
4
    params.push_back((*d_type)[i]);
1673
  }
1674
8
  return typeNodeVectorToSorts(d_solver, params);
1675
  ////////
1676
  CVC5_API_TRY_CATCH_END;
1677
}
1678
1679
/* Sort constructor sort ----------------------------------------------- */
1680
1681
4
std::string Sort::getSortConstructorName() const
1682
{
1683
  CVC5_API_TRY_CATCH_BEGIN;
1684
4
  CVC5_API_CHECK_NOT_NULL;
1685
4
  CVC5_API_CHECK(isSortConstructor()) << "Not a sort constructor sort.";
1686
  //////// all checks before this line
1687
2
  return d_type->getName();
1688
  ////////
1689
  CVC5_API_TRY_CATCH_END;
1690
}
1691
1692
4
size_t Sort::getSortConstructorArity() const
1693
{
1694
  CVC5_API_TRY_CATCH_BEGIN;
1695
4
  CVC5_API_CHECK_NOT_NULL;
1696
4
  CVC5_API_CHECK(isSortConstructor()) << "Not a sort constructor sort.";
1697
  //////// all checks before this line
1698
2
  return d_type->getSortConstructorArity();
1699
  ////////
1700
  CVC5_API_TRY_CATCH_END;
1701
}
1702
1703
/* Bit-vector sort ----------------------------------------------------- */
1704
1705
5
uint32_t Sort::getBitVectorSize() const
1706
{
1707
  CVC5_API_TRY_CATCH_BEGIN;
1708
5
  CVC5_API_CHECK_NOT_NULL;
1709
5
  CVC5_API_CHECK(isBitVector()) << "Not a bit-vector sort.";
1710
  //////// all checks before this line
1711
3
  return d_type->getBitVectorSize();
1712
  ////////
1713
  CVC5_API_TRY_CATCH_END;
1714
}
1715
1716
/* Floating-point sort ------------------------------------------------- */
1717
1718
4
uint32_t Sort::getFloatingPointExponentSize() const
1719
{
1720
  CVC5_API_TRY_CATCH_BEGIN;
1721
4
  CVC5_API_CHECK_NOT_NULL;
1722
4
  CVC5_API_CHECK(isFloatingPoint()) << "Not a floating-point sort.";
1723
  //////// all checks before this line
1724
2
  return d_type->getFloatingPointExponentSize();
1725
  ////////
1726
  CVC5_API_TRY_CATCH_END;
1727
}
1728
1729
4
uint32_t Sort::getFloatingPointSignificandSize() const
1730
{
1731
  CVC5_API_TRY_CATCH_BEGIN;
1732
4
  CVC5_API_CHECK_NOT_NULL;
1733
4
  CVC5_API_CHECK(isFloatingPoint()) << "Not a floating-point sort.";
1734
  //////// all checks before this line
1735
2
  return d_type->getFloatingPointSignificandSize();
1736
  ////////
1737
  CVC5_API_TRY_CATCH_END;
1738
}
1739
1740
/* Datatype sort ------------------------------------------------------- */
1741
1742
61
std::vector<Sort> Sort::getDatatypeParamSorts() const
1743
{
1744
  CVC5_API_TRY_CATCH_BEGIN;
1745
61
  CVC5_API_CHECK_NOT_NULL;
1746
61
  CVC5_API_CHECK(isParametricDatatype()) << "Not a parametric datatype sort.";
1747
  //////// all checks before this line
1748
59
  return typeNodeVectorToSorts(d_solver, d_type->getParamTypes());
1749
  ////////
1750
  CVC5_API_TRY_CATCH_END;
1751
}
1752
1753
4
size_t Sort::getDatatypeArity() const
1754
{
1755
  CVC5_API_TRY_CATCH_BEGIN;
1756
4
  CVC5_API_CHECK_NOT_NULL;
1757
4
  CVC5_API_CHECK(isDatatype()) << "Not a datatype sort.";
1758
  //////// all checks before this line
1759
2
  return d_type->getNumChildren() - 1;
1760
  ////////
1761
  CVC5_API_TRY_CATCH_END;
1762
}
1763
1764
/* Tuple sort ---------------------------------------------------------- */
1765
1766
59
size_t Sort::getTupleLength() const
1767
{
1768
  CVC5_API_TRY_CATCH_BEGIN;
1769
59
  CVC5_API_CHECK_NOT_NULL;
1770
59
  CVC5_API_CHECK(isTuple()) << "Not a tuple sort.";
1771
  //////// all checks before this line
1772
57
  return d_type->getTupleLength();
1773
  ////////
1774
  CVC5_API_TRY_CATCH_END;
1775
}
1776
1777
4
std::vector<Sort> Sort::getTupleSorts() const
1778
{
1779
  CVC5_API_TRY_CATCH_BEGIN;
1780
4
  CVC5_API_CHECK_NOT_NULL;
1781
4
  CVC5_API_CHECK(isTuple()) << "Not a tuple sort.";
1782
  //////// all checks before this line
1783
2
  return typeNodeVectorToSorts(d_solver, d_type->getTupleTypes());
1784
  ////////
1785
  CVC5_API_TRY_CATCH_END;
1786
}
1787
1788
/* --------------------------------------------------------------------- */
1789
1790
60
std::ostream& operator<<(std::ostream& out, const Sort& s)
1791
{
1792
60
  out << s.toString();
1793
60
  return out;
1794
}
1795
1796
/* Helpers                                                                    */
1797
/* -------------------------------------------------------------------------- */
1798
1799
/* Split out to avoid nested API calls (problematic with API tracing).        */
1800
/* .......................................................................... */
1801
1802
3194103
bool Sort::isNullHelper() const { return d_type->isNull(); }
1803
1804
/* -------------------------------------------------------------------------- */
1805
/* Op                                                                     */
1806
/* -------------------------------------------------------------------------- */
1807
1808
11177002
Op::Op() : d_solver(nullptr), d_kind(NULL_EXPR), d_node(new cvc5::Node()) {}
1809
1810
58
Op::Op(const Solver* slv, const Kind k)
1811
58
    : d_solver(slv), d_kind(k), d_node(new cvc5::Node())
1812
{
1813
58
}
1814
1815
76755
Op::Op(const Solver* slv, const Kind k, const cvc5::Node& n)
1816
76755
    : d_solver(slv), d_kind(k), d_node(new cvc5::Node(n))
1817
{
1818
76755
}
1819
1820
22700182
Op::~Op()
1821
{
1822
11350091
  if (d_solver != nullptr)
1823
  {
1824
    // Ensure that the correct node manager is in scope when the type node is
1825
    // destroyed.
1826
383515
    d_node.reset();
1827
  }
1828
11350091
}
1829
1830
/* Public methods                                                             */
1831
26
bool Op::operator==(const Op& t) const
1832
{
1833
  CVC5_API_TRY_CATCH_BEGIN;
1834
  //////// all checks before this line
1835
26
  if (d_node->isNull() && t.d_node->isNull())
1836
  {
1837
22
    return (d_kind == t.d_kind);
1838
  }
1839
4
  else if (d_node->isNull() || t.d_node->isNull())
1840
  {
1841
    return false;
1842
  }
1843
4
  return (d_kind == t.d_kind) && (*d_node == *t.d_node);
1844
  ////////
1845
  CVC5_API_TRY_CATCH_END;
1846
}
1847
1848
bool Op::operator!=(const Op& t) const
1849
{
1850
  CVC5_API_TRY_CATCH_BEGIN;
1851
  //////// all checks before this line
1852
  return !(*this == t);
1853
  ////////
1854
  CVC5_API_TRY_CATCH_END;
1855
}
1856
1857
2
Kind Op::getKind() const
1858
{
1859
2
  CVC5_API_CHECK(d_kind != NULL_EXPR) << "Expecting a non-null Kind";
1860
  //////// all checks before this line
1861
2
  return d_kind;
1862
}
1863
1864
3004375
bool Op::isNull() const
1865
{
1866
  CVC5_API_TRY_CATCH_BEGIN;
1867
  //////// all checks before this line
1868
3004375
  return isNullHelper();
1869
  ////////
1870
  CVC5_API_TRY_CATCH_END;
1871
}
1872
1873
14
bool Op::isIndexed() const
1874
{
1875
  CVC5_API_TRY_CATCH_BEGIN;
1876
  //////// all checks before this line
1877
14
  return isIndexedHelper();
1878
  ////////
1879
  CVC5_API_TRY_CATCH_END;
1880
}
1881
1882
38
size_t Op::getNumIndices() const
1883
{
1884
  CVC5_API_TRY_CATCH_BEGIN;
1885
38
  CVC5_API_CHECK_NOT_NULL;
1886
  //////// all checks before this line
1887
38
  return getNumIndicesHelper();
1888
  ////////
1889
  CVC5_API_TRY_CATCH_END;
1890
}
1891
1892
98
size_t Op::getNumIndicesHelper() const
1893
{
1894
98
  if (!isIndexedHelper())
1895
  {
1896
2
    return 0;
1897
  }
1898
1899
96
  Kind k = intToExtKind(d_node->getKind());
1900
96
  size_t size = 0;
1901
96
  switch (k)
1902
  {
1903
4
    case DIVISIBLE: size = 1; break;
1904
4
    case BITVECTOR_REPEAT: size = 1; break;
1905
4
    case BITVECTOR_ZERO_EXTEND: size = 1; break;
1906
4
    case BITVECTOR_SIGN_EXTEND: size = 1; break;
1907
4
    case BITVECTOR_ROTATE_LEFT: size = 1; break;
1908
4
    case BITVECTOR_ROTATE_RIGHT: size = 1; break;
1909
4
    case INT_TO_BITVECTOR: size = 1; break;
1910
4
    case IAND: size = 1; break;
1911
4
    case FLOATINGPOINT_TO_UBV: size = 1; break;
1912
4
    case FLOATINGPOINT_TO_SBV: size = 1; break;
1913
    case REGEXP_REPEAT: size = 1; break;
1914
    case BITVECTOR_EXTRACT: size = 2; break;
1915
4
    case FLOATINGPOINT_TO_FP_IEEE_BITVECTOR: size = 2; break;
1916
4
    case FLOATINGPOINT_TO_FP_FLOATINGPOINT: size = 2; break;
1917
4
    case FLOATINGPOINT_TO_FP_REAL: size = 2; break;
1918
4
    case FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR: size = 2; break;
1919
4
    case FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR: size = 2; break;
1920
4
    case FLOATINGPOINT_TO_FP_GENERIC: size = 2; break;
1921
4
    case REGEXP_LOOP: size = 2; break;
1922
28
    case TUPLE_PROJECT:
1923
28
      size = d_node->getConst<TupleProjectOp>().getIndices().size();
1924
28
      break;
1925
    default: CVC5_API_CHECK(false) << "Unhandled kind " << kindToString(k);
1926
  }
1927
96
  return size;
1928
}
1929
1930
48
Term Op::operator[](size_t index) const
1931
{
1932
48
  return getIndexHelper(index);
1933
}
1934
1935
60
Term Op::getIndexHelper(size_t index) const
1936
{
1937
  CVC5_API_TRY_CATCH_BEGIN;
1938
60
  CVC5_API_CHECK_NOT_NULL;
1939
62
  CVC5_API_CHECK(!d_node->isNull())
1940
2
      << "Expecting a non-null internal expression. This Op is not indexed.";
1941
58
  CVC5_API_CHECK(index < getNumIndicesHelper()) << "index out of bound";
1942
58
  Kind k = intToExtKind(d_node->getKind());
1943
116
  Term t;
1944
58
  switch (k)
1945
  {
1946
2
    case DIVISIBLE:
1947
    {
1948
4
      t = d_solver->mkValHelper<Rational>(
1949
4
          Rational(d_node->getConst<Divisible>().k));
1950
2
      break;
1951
    }
1952
2
    case BITVECTOR_REPEAT:
1953
    {
1954
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1955
2
          d_node->getConst<BitVectorRepeat>().d_repeatAmount);
1956
2
      break;
1957
    }
1958
2
    case BITVECTOR_ZERO_EXTEND:
1959
    {
1960
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1961
2
          d_node->getConst<BitVectorZeroExtend>().d_zeroExtendAmount);
1962
2
      break;
1963
    }
1964
2
    case BITVECTOR_SIGN_EXTEND:
1965
    {
1966
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1967
2
          d_node->getConst<BitVectorSignExtend>().d_signExtendAmount);
1968
2
      break;
1969
    }
1970
2
    case BITVECTOR_ROTATE_LEFT:
1971
    {
1972
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1973
2
          d_node->getConst<BitVectorRotateLeft>().d_rotateLeftAmount);
1974
2
      break;
1975
    }
1976
2
    case BITVECTOR_ROTATE_RIGHT:
1977
    {
1978
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1979
2
          d_node->getConst<BitVectorRotateRight>().d_rotateRightAmount);
1980
2
      break;
1981
    }
1982
2
    case INT_TO_BITVECTOR:
1983
    {
1984
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1985
2
          d_node->getConst<IntToBitVector>().d_size);
1986
2
      break;
1987
    }
1988
2
    case IAND:
1989
    {
1990
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1991
2
          d_node->getConst<IntAnd>().d_size);
1992
2
      break;
1993
    }
1994
2
    case FLOATINGPOINT_TO_UBV:
1995
    {
1996
4
      t = d_solver->mkValHelper<cvc5::Rational>(
1997
2
          d_node->getConst<FloatingPointToUBV>().d_bv_size.d_size);
1998
2
      break;
1999
    }
2000
2
    case FLOATINGPOINT_TO_SBV:
2001
    {
2002
4
      t = d_solver->mkValHelper<cvc5::Rational>(
2003
2
          d_node->getConst<FloatingPointToSBV>().d_bv_size.d_size);
2004
2
      break;
2005
    }
2006
    case REGEXP_REPEAT:
2007
    {
2008
      t = d_solver->mkValHelper<cvc5::Rational>(
2009
          d_node->getConst<RegExpRepeat>().d_repeatAmount);
2010
      break;
2011
    }
2012
    case BITVECTOR_EXTRACT:
2013
    {
2014
      cvc5::BitVectorExtract ext = d_node->getConst<BitVectorExtract>();
2015
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(ext.d_high)
2016
                     : d_solver->mkValHelper<cvc5::Rational>(ext.d_low);
2017
      break;
2018
    }
2019
2
    case FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
2020
    {
2021
      cvc5::FloatingPointToFPIEEEBitVector ext =
2022
2
          d_node->getConst<FloatingPointToFPIEEEBitVector>();
2023
2024
6
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(
2025
4
              ext.getSize().exponentWidth())
2026
                     : d_solver->mkValHelper<cvc5::Rational>(
2027
2
                         ext.getSize().significandWidth());
2028
2
      break;
2029
    }
2030
2
    case FLOATINGPOINT_TO_FP_FLOATINGPOINT:
2031
    {
2032
      cvc5::FloatingPointToFPFloatingPoint ext =
2033
2
          d_node->getConst<FloatingPointToFPFloatingPoint>();
2034
6
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(
2035
4
              ext.getSize().exponentWidth())
2036
                     : d_solver->mkValHelper<cvc5::Rational>(
2037
2
                         ext.getSize().significandWidth());
2038
2
      break;
2039
    }
2040
2
    case FLOATINGPOINT_TO_FP_REAL:
2041
    {
2042
      cvc5::FloatingPointToFPReal ext =
2043
2
          d_node->getConst<FloatingPointToFPReal>();
2044
2045
6
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(
2046
4
              ext.getSize().exponentWidth())
2047
                     : d_solver->mkValHelper<cvc5::Rational>(
2048
2
                         ext.getSize().significandWidth());
2049
2
      break;
2050
    }
2051
2
    case FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
2052
    {
2053
      cvc5::FloatingPointToFPSignedBitVector ext =
2054
2
          d_node->getConst<FloatingPointToFPSignedBitVector>();
2055
6
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(
2056
4
              ext.getSize().exponentWidth())
2057
                     : d_solver->mkValHelper<cvc5::Rational>(
2058
2
                         ext.getSize().significandWidth());
2059
2
      break;
2060
    }
2061
2
    case FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
2062
    {
2063
      cvc5::FloatingPointToFPUnsignedBitVector ext =
2064
2
          d_node->getConst<FloatingPointToFPUnsignedBitVector>();
2065
6
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(
2066
4
              ext.getSize().exponentWidth())
2067
                     : d_solver->mkValHelper<cvc5::Rational>(
2068
2
                         ext.getSize().significandWidth());
2069
2
      break;
2070
    }
2071
2
    case FLOATINGPOINT_TO_FP_GENERIC:
2072
    {
2073
      cvc5::FloatingPointToFPGeneric ext =
2074
2
          d_node->getConst<FloatingPointToFPGeneric>();
2075
6
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(
2076
4
              ext.getSize().exponentWidth())
2077
                     : d_solver->mkValHelper<cvc5::Rational>(
2078
2
                         ext.getSize().significandWidth());
2079
2
      break;
2080
    }
2081
2
    case REGEXP_LOOP:
2082
    {
2083
2
      cvc5::RegExpLoop ext = d_node->getConst<RegExpLoop>();
2084
2
      t = index == 0 ? d_solver->mkValHelper<cvc5::Rational>(ext.d_loopMinOcc)
2085
                     : d_solver->mkValHelper<cvc5::Rational>(ext.d_loopMaxOcc);
2086
2087
2
      break;
2088
    }
2089
2090
24
    case TUPLE_PROJECT:
2091
    {
2092
      const std::vector<uint32_t>& projectionIndices =
2093
24
          d_node->getConst<TupleProjectOp>().getIndices();
2094
24
      t = d_solver->mkValHelper<cvc5::Rational>(projectionIndices[index]);
2095
24
      break;
2096
    }
2097
    default:
2098
    {
2099
      CVC5_API_CHECK(false) << "Unhandled kind " << kindToString(k);
2100
      break;
2101
    }
2102
  }
2103
2104
  //////// all checks before this line
2105
116
  return t;
2106
  ////////
2107
  CVC5_API_TRY_CATCH_END;
2108
}
2109
2110
template <>
2111
8
std::string Op::getIndices() const
2112
{
2113
  CVC5_API_TRY_CATCH_BEGIN;
2114
8
  CVC5_API_CHECK_NOT_NULL;
2115
6
  CVC5_API_CHECK(!d_node->isNull())
2116
      << "Expecting a non-null internal expression. This Op is not indexed.";
2117
6
  Kind k = intToExtKind(d_node->getKind());
2118
20
  CVC5_API_CHECK(k == DIVISIBLE) << "Can't get string index from"
2119
14
                                 << " kind " << kindToString(k);
2120
  //////// all checks before this line
2121
2
  return d_node->getConst<Divisible>().k.toString();
2122
  ////////
2123
  CVC5_API_TRY_CATCH_END;
2124
}
2125
2126
template <>
2127
18
uint32_t Op::getIndices() const
2128
{
2129
  CVC5_API_TRY_CATCH_BEGIN;
2130
18
  CVC5_API_CHECK_NOT_NULL;
2131
20
  CVC5_API_CHECK(!d_node->isNull())
2132
2
      << "Expecting a non-null internal expression. This Op is not indexed.";
2133
  //////// all checks before this line
2134
2135
16
  uint32_t i = 0;
2136
16
  Kind k = intToExtKind(d_node->getKind());
2137
16
  switch (k)
2138
  {
2139
2
    case BITVECTOR_REPEAT:
2140
2
      i = d_node->getConst<BitVectorRepeat>().d_repeatAmount;
2141
2
      break;
2142
2
    case BITVECTOR_ZERO_EXTEND:
2143
2
      i = d_node->getConst<BitVectorZeroExtend>().d_zeroExtendAmount;
2144
2
      break;
2145
2
    case BITVECTOR_SIGN_EXTEND:
2146
2
      i = d_node->getConst<BitVectorSignExtend>().d_signExtendAmount;
2147
2
      break;
2148
2
    case BITVECTOR_ROTATE_LEFT:
2149
2
      i = d_node->getConst<BitVectorRotateLeft>().d_rotateLeftAmount;
2150
2
      break;
2151
2
    case BITVECTOR_ROTATE_RIGHT:
2152
2
      i = d_node->getConst<BitVectorRotateRight>().d_rotateRightAmount;
2153
2
      break;
2154
2
    case INT_TO_BITVECTOR: i = d_node->getConst<IntToBitVector>().d_size; break;
2155
    case IAND: i = d_node->getConst<IntAnd>().d_size; break;
2156
2
    case FLOATINGPOINT_TO_UBV:
2157
2
      i = d_node->getConst<FloatingPointToUBV>().d_bv_size.d_size;
2158
2
      break;
2159
2
    case FLOATINGPOINT_TO_SBV:
2160
2
      i = d_node->getConst<FloatingPointToSBV>().d_bv_size.d_size;
2161
2
      break;
2162
    case REGEXP_REPEAT:
2163
      i = d_node->getConst<RegExpRepeat>().d_repeatAmount;
2164
      break;
2165
    default:
2166
      CVC5_API_CHECK(false) << "Can't get uint32_t index from"
2167
                            << " kind " << kindToString(k);
2168
  }
2169
16
  return i;
2170
  ////////
2171
  CVC5_API_TRY_CATCH_END;
2172
}
2173
2174
template <>
2175
16
std::pair<uint32_t, uint32_t> Op::getIndices() const
2176
{
2177
  CVC5_API_TRY_CATCH_BEGIN;
2178
16
  CVC5_API_CHECK_NOT_NULL;
2179
16
  CVC5_API_CHECK(!d_node->isNull())
2180
      << "Expecting a non-null internal expression. This Op is not indexed.";
2181
  //////// all checks before this line
2182
2183
16
  std::pair<uint32_t, uint32_t> indices;
2184
16
  Kind k = intToExtKind(d_node->getKind());
2185
2186
  // using if/else instead of case statement because want local variables
2187
16
  if (k == BITVECTOR_EXTRACT)
2188
  {
2189
2
    cvc5::BitVectorExtract ext = d_node->getConst<BitVectorExtract>();
2190
4
    indices = std::make_pair(ext.d_high, ext.d_low);
2191
  }
2192
14
  else if (k == FLOATINGPOINT_TO_FP_IEEE_BITVECTOR)
2193
  {
2194
    cvc5::FloatingPointToFPIEEEBitVector ext =
2195
2
        d_node->getConst<FloatingPointToFPIEEEBitVector>();
2196
2
    indices = std::make_pair(ext.getSize().exponentWidth(),
2197
4
                             ext.getSize().significandWidth());
2198
  }
2199
12
  else if (k == FLOATINGPOINT_TO_FP_FLOATINGPOINT)
2200
  {
2201
    cvc5::FloatingPointToFPFloatingPoint ext =
2202
2
        d_node->getConst<FloatingPointToFPFloatingPoint>();
2203
2
    indices = std::make_pair(ext.getSize().exponentWidth(),
2204
4
                             ext.getSize().significandWidth());
2205
  }
2206
10
  else if (k == FLOATINGPOINT_TO_FP_REAL)
2207
  {
2208
2
    cvc5::FloatingPointToFPReal ext = d_node->getConst<FloatingPointToFPReal>();
2209
2
    indices = std::make_pair(ext.getSize().exponentWidth(),
2210
4
                             ext.getSize().significandWidth());
2211
  }
2212
8
  else if (k == FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR)
2213
  {
2214
    cvc5::FloatingPointToFPSignedBitVector ext =
2215
2
        d_node->getConst<FloatingPointToFPSignedBitVector>();
2216
2
    indices = std::make_pair(ext.getSize().exponentWidth(),
2217
4
                             ext.getSize().significandWidth());
2218
  }
2219
6
  else if (k == FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR)
2220
  {
2221
    cvc5::FloatingPointToFPUnsignedBitVector ext =
2222
2
        d_node->getConst<FloatingPointToFPUnsignedBitVector>();
2223
2
    indices = std::make_pair(ext.getSize().exponentWidth(),
2224
4
                             ext.getSize().significandWidth());
2225
  }
2226
4
  else if (k == FLOATINGPOINT_TO_FP_GENERIC)
2227
  {
2228
    cvc5::FloatingPointToFPGeneric ext =
2229
2
        d_node->getConst<FloatingPointToFPGeneric>();
2230
2
    indices = std::make_pair(ext.getSize().exponentWidth(),
2231
4
                             ext.getSize().significandWidth());
2232
  }
2233
2
  else if (k == REGEXP_LOOP)
2234
  {
2235
    cvc5::RegExpLoop ext = d_node->getConst<RegExpLoop>();
2236
    indices = std::make_pair(ext.d_loopMinOcc, ext.d_loopMaxOcc);
2237
  }
2238
  else
2239
  {
2240
8
    CVC5_API_CHECK(false) << "Can't get pair<uint32_t, uint32_t> indices from"
2241
6
                          << " kind " << kindToString(k);
2242
  }
2243
14
  return indices;
2244
  ////////
2245
  CVC5_API_TRY_CATCH_END;
2246
}
2247
2248
template <>
2249
2
std::vector<api::Term> Op::getIndices() const
2250
{
2251
  CVC5_API_TRY_CATCH_BEGIN;
2252
2
  CVC5_API_CHECK_NOT_NULL;
2253
2
  CVC5_API_CHECK(!d_node->isNull())
2254
      << "Expecting a non-null internal expression. This Op is not indexed.";
2255
2
  size_t size = getNumIndicesHelper();
2256
4
  std::vector<Term> terms(getNumIndices());
2257
14
  for (size_t i = 0; i < size; i++)
2258
  {
2259
12
    terms[i] = getIndexHelper(i);
2260
  }
2261
  //////// all checks before this line
2262
4
  return terms;
2263
  ////////
2264
  CVC5_API_TRY_CATCH_END;
2265
}
2266
2267
4
std::string Op::toString() const
2268
{
2269
  CVC5_API_TRY_CATCH_BEGIN;
2270
  //////// all checks before this line
2271
4
  if (d_node->isNull())
2272
  {
2273
    return kindToString(d_kind);
2274
  }
2275
  else
2276
  {
2277
4
    CVC5_API_CHECK(!d_node->isNull())
2278
        << "Expecting a non-null internal expression";
2279
4
    if (d_solver != nullptr)
2280
    {
2281
4
      return d_node->toString();
2282
    }
2283
    return d_node->toString();
2284
  }
2285
  ////////
2286
  CVC5_API_TRY_CATCH_END;
2287
}
2288
2289
std::ostream& operator<<(std::ostream& out, const Op& t)
2290
{
2291
  out << t.toString();
2292
  return out;
2293
}
2294
2295
/* Helpers                                                                    */
2296
/* -------------------------------------------------------------------------- */
2297
2298
/* Split out to avoid nested API calls (problematic with API tracing).        */
2299
/* .......................................................................... */
2300
2301
3004517
bool Op::isNullHelper() const
2302
{
2303
3004517
  return (d_node->isNull() && (d_kind == NULL_EXPR));
2304
}
2305
2306
76749
bool Op::isIndexedHelper() const { return !d_node->isNull(); }
2307
2308
/* -------------------------------------------------------------------------- */
2309
/* Term                                                                       */
2310
/* -------------------------------------------------------------------------- */
2311
2312
53023128
Term::Term() : d_solver(nullptr), d_node(new cvc5::Node()) {}
2313
2314
3410109
Term::Term(const Solver* slv, const cvc5::Node& n) : d_solver(slv)
2315
{
2316
3410109
  d_node.reset(new cvc5::Node(n));
2317
3410109
}
2318
2319
168740636
Term::~Term()
2320
{
2321
84370318
  if (d_solver != nullptr)
2322
  {
2323
34380206
    d_node.reset();
2324
  }
2325
84370318
}
2326
2327
119712
bool Term::operator==(const Term& t) const
2328
{
2329
  CVC5_API_TRY_CATCH_BEGIN;
2330
  //////// all checks before this line
2331
119712
  return *d_node == *t.d_node;
2332
  ////////
2333
  CVC5_API_TRY_CATCH_END;
2334
}
2335
2336
99
bool Term::operator!=(const Term& t) const
2337
{
2338
  CVC5_API_TRY_CATCH_BEGIN;
2339
  //////// all checks before this line
2340
99
  return *d_node != *t.d_node;
2341
  ////////
2342
  CVC5_API_TRY_CATCH_END;
2343
}
2344
2345
51
bool Term::operator<(const Term& t) const
2346
{
2347
  CVC5_API_TRY_CATCH_BEGIN;
2348
  //////// all checks before this line
2349
51
  return *d_node < *t.d_node;
2350
  ////////
2351
  CVC5_API_TRY_CATCH_END;
2352
}
2353
2354
4
bool Term::operator>(const Term& t) const
2355
{
2356
  CVC5_API_TRY_CATCH_BEGIN;
2357
  //////// all checks before this line
2358
4
  return *d_node > *t.d_node;
2359
  ////////
2360
  CVC5_API_TRY_CATCH_END;
2361
}
2362
2363
2
bool Term::operator<=(const Term& t) const
2364
{
2365
  CVC5_API_TRY_CATCH_BEGIN;
2366
  //////// all checks before this line
2367
2
  return *d_node <= *t.d_node;
2368
  ////////
2369
  CVC5_API_TRY_CATCH_END;
2370
}
2371
2372
4
bool Term::operator>=(const Term& t) const
2373
{
2374
  CVC5_API_TRY_CATCH_BEGIN;
2375
  //////// all checks before this line
2376
4
  return *d_node >= *t.d_node;
2377
  ////////
2378
  CVC5_API_TRY_CATCH_END;
2379
}
2380
2381
947
size_t Term::getNumChildren() const
2382
{
2383
  CVC5_API_TRY_CATCH_BEGIN;
2384
947
  CVC5_API_CHECK_NOT_NULL;
2385
  //////// all checks before this line
2386
2387
  // special case for apply kinds
2388
945
  if (isApplyKind(d_node->getKind()))
2389
  {
2390
881
    return d_node->getNumChildren() + 1;
2391
  }
2392
64
  if (isCastedReal())
2393
  {
2394
    return 0;
2395
  }
2396
64
  return d_node->getNumChildren();
2397
  ////////
2398
  CVC5_API_TRY_CATCH_END;
2399
}
2400
2401
489
Term Term::operator[](size_t index) const
2402
{
2403
  CVC5_API_TRY_CATCH_BEGIN;
2404
489
  CVC5_API_CHECK_NOT_NULL;
2405
487
  CVC5_API_CHECK(index < getNumChildren()) << "index out of bound";
2406
487
  CVC5_API_CHECK(!isApplyKind(d_node->getKind()) || d_node->hasOperator())
2407
      << "Expected apply kind to have operator when accessing child of Term";
2408
  //////// all checks before this line
2409
2410
  // special cases for apply kinds
2411
487
  if (isApplyKind(d_node->getKind()))
2412
  {
2413
443
    if (index == 0)
2414
    {
2415
      // return the operator
2416
441
      return Term(d_solver, d_node->getOperator());
2417
    }
2418
    else
2419
    {
2420
2
      index -= 1;
2421
    }
2422
  }
2423
  // otherwise we are looking up child at (index-1)
2424
46
  return Term(d_solver, (*d_node)[index]);
2425
  ////////
2426
  CVC5_API_TRY_CATCH_END;
2427
}
2428
2429
12
uint64_t Term::getId() const
2430
{
2431
  CVC5_API_TRY_CATCH_BEGIN;
2432
12
  CVC5_API_CHECK_NOT_NULL;
2433
  //////// all checks before this line
2434
10
  return d_node->getId();
2435
  ////////
2436
  CVC5_API_TRY_CATCH_END;
2437
}
2438
2439
5413
Kind Term::getKind() const
2440
{
2441
  CVC5_API_TRY_CATCH_BEGIN;
2442
5413
  CVC5_API_CHECK_NOT_NULL;
2443
  //////// all checks before this line
2444
5411
  return getKindHelper();
2445
  ////////
2446
  CVC5_API_TRY_CATCH_END;
2447
}
2448
2449
4618432
Sort Term::getSort() const
2450
{
2451
  CVC5_API_TRY_CATCH_BEGIN;
2452
4618432
  CVC5_API_CHECK_NOT_NULL;
2453
  //////// all checks before this line
2454
4618430
  return Sort(d_solver, d_node->getType());
2455
  ////////
2456
  CVC5_API_TRY_CATCH_END;
2457
}
2458
2459
15
Term Term::substitute(const Term& term, const Term& replacement) const
2460
{
2461
  CVC5_API_TRY_CATCH_BEGIN;
2462
15
  CVC5_API_CHECK_NOT_NULL;
2463
13
  CVC5_API_CHECK_TERM(term);
2464
11
  CVC5_API_CHECK_TERM(replacement);
2465
11
  CVC5_API_CHECK(term.getSort().isComparableTo(replacement.getSort()))
2466
2
      << "Expecting terms of comparable sort in substitute";
2467
  //////// all checks before this line
2468
  return Term(
2469
7
      d_solver,
2470
14
      d_node->substitute(TNode(*term.d_node), TNode(*replacement.d_node)));
2471
  ////////
2472
  CVC5_API_TRY_CATCH_END;
2473
}
2474
2475
12
Term Term::substitute(const std::vector<Term>& terms,
2476
                      const std::vector<Term>& replacements) const
2477
{
2478
  CVC5_API_TRY_CATCH_BEGIN;
2479
12
  CVC5_API_CHECK_NOT_NULL;
2480
12
  CVC5_API_CHECK(terms.size() == replacements.size())
2481
2
      << "Expecting vectors of the same arity in substitute";
2482
8
  CVC5_API_TERM_CHECK_TERMS_WITH_TERMS_COMPARABLE_TO(terms, replacements);
2483
  //////// all checks before this line
2484
4
  std::vector<Node> nodes = Term::termVectorToNodes(terms);
2485
4
  std::vector<Node> nodeReplacements = Term::termVectorToNodes(replacements);
2486
2
  return Term(d_solver,
2487
4
              d_node->substitute(nodes.begin(),
2488
                                 nodes.end(),
2489
                                 nodeReplacements.begin(),
2490
4
                                 nodeReplacements.end()));
2491
  ////////
2492
  CVC5_API_TRY_CATCH_END;
2493
}
2494
2495
36
bool Term::hasOp() const
2496
{
2497
  CVC5_API_TRY_CATCH_BEGIN;
2498
36
  CVC5_API_CHECK_NOT_NULL;
2499
  //////// all checks before this line
2500
36
  return d_node->hasOperator();
2501
  ////////
2502
  CVC5_API_TRY_CATCH_END;
2503
}
2504
2505
40
Op Term::getOp() const
2506
{
2507
  CVC5_API_TRY_CATCH_BEGIN;
2508
40
  CVC5_API_CHECK_NOT_NULL;
2509
46
  CVC5_API_CHECK(d_node->hasOperator())
2510
6
      << "Expecting Term to have an Op when calling getOp()";
2511
  //////// all checks before this line
2512
2513
  // special cases for parameterized operators that are not indexed operators
2514
  // the API level differs from the internal structure
2515
  // indexed operators are stored in Ops
2516
  // whereas functions and datatype operators are terms, and the Op
2517
  // is one of the APPLY_* kinds
2518
34
  if (isApplyKind(d_node->getKind()))
2519
  {
2520
20
    return Op(d_solver, intToExtKind(d_node->getKind()));
2521
  }
2522
14
  else if (d_node->getMetaKind() == kind::metakind::PARAMETERIZED)
2523
  {
2524
    // it's an indexed operator
2525
    // so we should return the indexed op
2526
12
    cvc5::Node op = d_node->getOperator();
2527
6
    return Op(d_solver, intToExtKind(d_node->getKind()), op);
2528
  }
2529
  // Notice this is the only case where getKindHelper is used, since the
2530
  // cases above do not have special cases for intToExtKind.
2531
8
  return Op(d_solver, getKindHelper());
2532
  ////////
2533
  CVC5_API_TRY_CATCH_END;
2534
}
2535
2536
19576213
bool Term::isNull() const
2537
{
2538
  CVC5_API_TRY_CATCH_BEGIN;
2539
  //////// all checks before this line
2540
19576213
  return isNullHelper();
2541
  ////////
2542
  CVC5_API_TRY_CATCH_END;
2543
}
2544
2545
58
Term Term::notTerm() const
2546
{
2547
  CVC5_API_TRY_CATCH_BEGIN;
2548
58
  CVC5_API_CHECK_NOT_NULL;
2549
  //////// all checks before this line
2550
100
  Node res = d_node->notNode();
2551
44
  (void)res.getType(true); /* kick off type checking */
2552
88
  return Term(d_solver, res);
2553
  ////////
2554
  CVC5_API_TRY_CATCH_END;
2555
}
2556
2557
94
Term Term::andTerm(const Term& t) const
2558
{
2559
  CVC5_API_TRY_CATCH_BEGIN;
2560
94
  CVC5_API_CHECK_NOT_NULL;
2561
92
  CVC5_API_CHECK_TERM(t);
2562
  //////// all checks before this line
2563
102
  Node res = d_node->andNode(*t.d_node);
2564
12
  (void)res.getType(true); /* kick off type checking */
2565
24
  return Term(d_solver, res);
2566
  ////////
2567
  CVC5_API_TRY_CATCH_END;
2568
}
2569
2570
94
Term Term::orTerm(const Term& t) const
2571
{
2572
  CVC5_API_TRY_CATCH_BEGIN;
2573
94
  CVC5_API_CHECK_NOT_NULL;
2574
92
  CVC5_API_CHECK_TERM(t);
2575
  //////// all checks before this line
2576
102
  Node res = d_node->orNode(*t.d_node);
2577
12
  (void)res.getType(true); /* kick off type checking */
2578
24
  return Term(d_solver, res);
2579
  ////////
2580
  CVC5_API_TRY_CATCH_END;
2581
}
2582
2583
94
Term Term::xorTerm(const Term& t) const
2584
{
2585
  CVC5_API_TRY_CATCH_BEGIN;
2586
94
  CVC5_API_CHECK_NOT_NULL;
2587
92
  CVC5_API_CHECK_TERM(t);
2588
  //////// all checks before this line
2589
102
  Node res = d_node->xorNode(*t.d_node);
2590
12
  (void)res.getType(true); /* kick off type checking */
2591
24
  return Term(d_solver, res);
2592
  ////////
2593
  CVC5_API_TRY_CATCH_END;
2594
}
2595
2596
140
Term Term::eqTerm(const Term& t) const
2597
{
2598
  CVC5_API_TRY_CATCH_BEGIN;
2599
140
  CVC5_API_CHECK_NOT_NULL;
2600
138
  CVC5_API_CHECK_TERM(t);
2601
  //////// all checks before this line
2602
212
  Node res = d_node->eqNode(*t.d_node);
2603
76
  (void)res.getType(true); /* kick off type checking */
2604
152
  return Term(d_solver, res);
2605
  ////////
2606
  CVC5_API_TRY_CATCH_END;
2607
}
2608
2609
94
Term Term::impTerm(const Term& t) const
2610
{
2611
  CVC5_API_TRY_CATCH_BEGIN;
2612
94
  CVC5_API_CHECK_NOT_NULL;
2613
92
  CVC5_API_CHECK_TERM(t);
2614
  //////// all checks before this line
2615
102
  Node res = d_node->impNode(*t.d_node);
2616
12
  (void)res.getType(true); /* kick off type checking */
2617
24
  return Term(d_solver, res);
2618
  ////////
2619
  CVC5_API_TRY_CATCH_END;
2620
}
2621
2622
50
Term Term::iteTerm(const Term& then_t, const Term& else_t) const
2623
{
2624
  CVC5_API_TRY_CATCH_BEGIN;
2625
50
  CVC5_API_CHECK_NOT_NULL;
2626
48
  CVC5_API_CHECK_TERM(then_t);
2627
46
  CVC5_API_CHECK_TERM(else_t);
2628
  //////// all checks before this line
2629
58
  Node res = d_node->iteNode(*then_t.d_node, *else_t.d_node);
2630
14
  (void)res.getType(true); /* kick off type checking */
2631
28
  return Term(d_solver, res);
2632
  ////////
2633
  CVC5_API_TRY_CATCH_END;
2634
}
2635
2636
13749
std::string Term::toString() const
2637
{
2638
  CVC5_API_TRY_CATCH_BEGIN;
2639
  //////// all checks before this line
2640
13749
  if (d_solver != nullptr)
2641
  {
2642
13749
    return d_node->toString();
2643
  }
2644
  return d_node->toString();
2645
  ////////
2646
  CVC5_API_TRY_CATCH_END;
2647
}
2648
2649
Term::const_iterator::const_iterator()
2650
    : d_solver(nullptr), d_origNode(nullptr), d_pos(0)
2651
{
2652
}
2653
2654
176
Term::const_iterator::const_iterator(const Solver* slv,
2655
                                     const std::shared_ptr<cvc5::Node>& n,
2656
176
                                     uint32_t p)
2657
176
    : d_solver(slv), d_origNode(n), d_pos(p)
2658
{
2659
176
}
2660
2661
721
Term::const_iterator::const_iterator(const const_iterator& it)
2662
721
    : d_solver(nullptr), d_origNode(nullptr)
2663
{
2664
721
  if (it.d_origNode != nullptr)
2665
  {
2666
721
    d_solver = it.d_solver;
2667
721
    d_origNode = it.d_origNode;
2668
721
    d_pos = it.d_pos;
2669
  }
2670
721
}
2671
2672
Term::const_iterator& Term::const_iterator::operator=(const const_iterator& it)
2673
{
2674
  d_solver = it.d_solver;
2675
  d_origNode = it.d_origNode;
2676
  d_pos = it.d_pos;
2677
  return *this;
2678
}
2679
2680
301
bool Term::const_iterator::operator==(const const_iterator& it) const
2681
{
2682
301
  if (d_origNode == nullptr || it.d_origNode == nullptr)
2683
  {
2684
    return false;
2685
  }
2686
602
  return (d_solver == it.d_solver && *d_origNode == *it.d_origNode)
2687
602
         && (d_pos == it.d_pos);
2688
}
2689
2690
301
bool Term::const_iterator::operator!=(const const_iterator& it) const
2691
{
2692
301
  return !(*this == it);
2693
}
2694
2695
188
Term::const_iterator& Term::const_iterator::operator++()
2696
{
2697
188
  Assert(d_origNode != nullptr);
2698
188
  ++d_pos;
2699
188
  return *this;
2700
}
2701
2702
Term::const_iterator Term::const_iterator::operator++(int)
2703
{
2704
  Assert(d_origNode != nullptr);
2705
  const_iterator it = *this;
2706
  ++d_pos;
2707
  return it;
2708
}
2709
2710
124
Term Term::const_iterator::operator*() const
2711
{
2712
124
  Assert(d_origNode != nullptr);
2713
  // this term has an extra child (mismatch between API and internal structure)
2714
  // the extra child will be the first child
2715
124
  bool extra_child = isApplyKind(d_origNode->getKind());
2716
2717
124
  if (!d_pos && extra_child)
2718
  {
2719
43
    return Term(d_solver, d_origNode->getOperator());
2720
  }
2721
  else
2722
  {
2723
81
    uint32_t idx = d_pos;
2724
81
    if (extra_child)
2725
    {
2726
18
      Assert(idx > 0);
2727
18
      --idx;
2728
    }
2729
81
    Assert(idx >= 0);
2730
81
    return Term(d_solver, (*d_origNode)[idx]);
2731
  }
2732
}
2733
2734
74
Term::const_iterator Term::begin() const
2735
{
2736
74
  return Term::const_iterator(d_solver, d_node, 0);
2737
}
2738
2739
102
Term::const_iterator Term::end() const
2740
{
2741
102
  int endpos = d_node->getNumChildren();
2742
  // special cases for APPLY_*
2743
  // the API differs from the internal structure
2744
  // the API takes a "higher-order" perspective and the applied
2745
  //   function or datatype constructor/selector/tester is a Term
2746
  // which means it needs to be one of the children, even though
2747
  //   internally it is not
2748
102
  if (isApplyKind(d_node->getKind()))
2749
  {
2750
    // one more child if this is a UF application (count the UF as a child)
2751
46
    ++endpos;
2752
  }
2753
102
  return Term::const_iterator(d_solver, d_node, endpos);
2754
}
2755
2756
5778090
const cvc5::Node& Term::getNode(void) const { return *d_node; }
2757
2758
namespace detail {
2759
92
const Rational& getRational(const cvc5::Node& node)
2760
{
2761
92
  switch (node.getKind())
2762
  {
2763
52
    case cvc5::Kind::CAST_TO_REAL: return node[0].getConst<Rational>();
2764
40
    case cvc5::Kind::CONST_RATIONAL: return node.getConst<Rational>();
2765
    default:
2766
      CVC5_API_CHECK(false) << "Node is not a rational.";
2767
      return node.getConst<Rational>();
2768
  }
2769
}
2770
463
Integer getInteger(const cvc5::Node& node)
2771
{
2772
463
  return node.getConst<Rational>().getNumerator();
2773
}
2774
template <typename T>
2775
388
bool checkIntegerBounds(const Integer& i)
2776
{
2777
1164
  return i >= std::numeric_limits<T>::min()
2778
1552
         && i <= std::numeric_limits<T>::max();
2779
}
2780
20
bool checkReal32Bounds(const Rational& r)
2781
{
2782
60
  return checkIntegerBounds<std::int32_t>(r.getNumerator())
2783
80
         && checkIntegerBounds<std::uint32_t>(r.getDenominator());
2784
}
2785
28
bool checkReal64Bounds(const Rational& r)
2786
{
2787
84
  return checkIntegerBounds<std::int64_t>(r.getNumerator())
2788
112
         && checkIntegerBounds<std::uint64_t>(r.getDenominator());
2789
}
2790
2791
88
bool isReal(const Node& node)
2792
{
2793
88
  return node.getKind() == cvc5::Kind::CONST_RATIONAL
2794
88
         || node.getKind() == cvc5::Kind::CAST_TO_REAL;
2795
}
2796
20
bool isReal32(const Node& node)
2797
{
2798
20
  return isReal(node) && checkReal32Bounds(getRational(node));
2799
}
2800
28
bool isReal64(const Node& node)
2801
{
2802
28
  return isReal(node) && checkReal64Bounds(getRational(node));
2803
}
2804
2805
336
bool isInteger(const Node& node)
2806
{
2807
336
  return node.getKind() == cvc5::Kind::CONST_RATIONAL
2808
336
         && node.getConst<Rational>().isIntegral();
2809
}
2810
28
bool isInt32(const Node& node)
2811
{
2812
28
  return isInteger(node) && checkIntegerBounds<std::int32_t>(getInteger(node));
2813
}
2814
86
bool isUInt32(const Node& node)
2815
{
2816
86
  return isInteger(node) && checkIntegerBounds<std::uint32_t>(getInteger(node));
2817
}
2818
36
bool isInt64(const Node& node)
2819
{
2820
36
  return isInteger(node) && checkIntegerBounds<std::int64_t>(getInteger(node));
2821
}
2822
142
bool isUInt64(const Node& node)
2823
{
2824
142
  return isInteger(node) && checkIntegerBounds<std::uint64_t>(getInteger(node));
2825
}
2826
}  // namespace detail
2827
2828
22
bool Term::isInt32Value() const
2829
{
2830
  CVC5_API_TRY_CATCH_BEGIN;
2831
22
  CVC5_API_CHECK_NOT_NULL;
2832
  //////// all checks before this line
2833
22
  return detail::isInt32(*d_node);
2834
  ////////
2835
  CVC5_API_TRY_CATCH_END;
2836
}
2837
2838
6
std::int32_t Term::getInt32Value() const
2839
{
2840
  CVC5_API_TRY_CATCH_BEGIN;
2841
6
  CVC5_API_CHECK_NOT_NULL;
2842
6
  CVC5_API_ARG_CHECK_EXPECTED(detail::isInt32(*d_node), *d_node)
2843
      << "Term to be a 32-bit integer value when calling getInt32Value()";
2844
  //////// all checks before this line
2845
6
  return detail::getInteger(*d_node).getSignedInt();
2846
  ////////
2847
  CVC5_API_TRY_CATCH_END;
2848
}
2849
2850
22
bool Term::isUInt32Value() const
2851
{
2852
  CVC5_API_TRY_CATCH_BEGIN;
2853
22
  CVC5_API_CHECK_NOT_NULL;
2854
  //////// all checks before this line
2855
22
  return detail::isUInt32(*d_node);
2856
  ////////
2857
  CVC5_API_TRY_CATCH_END;
2858
}
2859
64
std::uint32_t Term::getUInt32Value() const
2860
{
2861
  CVC5_API_TRY_CATCH_BEGIN;
2862
64
  CVC5_API_CHECK_NOT_NULL;
2863
64
  CVC5_API_ARG_CHECK_EXPECTED(detail::isUInt32(*d_node), *d_node)
2864
      << "Term to be a unsigned 32-bit integer value when calling "
2865
         "getUInt32Value()";
2866
  //////// all checks before this line
2867
64
  return detail::getInteger(*d_node).getUnsignedInt();
2868
  ////////
2869
  CVC5_API_TRY_CATCH_END;
2870
}
2871
2872
22
bool Term::isInt64Value() const
2873
{
2874
  CVC5_API_TRY_CATCH_BEGIN;
2875
22
  CVC5_API_CHECK_NOT_NULL;
2876
  //////// all checks before this line
2877
22
  return detail::isInt64(*d_node);
2878
  ////////
2879
  CVC5_API_TRY_CATCH_END;
2880
}
2881
14
std::int64_t Term::getInt64Value() const
2882
{
2883
  CVC5_API_TRY_CATCH_BEGIN;
2884
14
  CVC5_API_CHECK_NOT_NULL;
2885
14
  CVC5_API_ARG_CHECK_EXPECTED(detail::isInt64(*d_node), *d_node)
2886
      << "Term to be a 64-bit integer value when calling getInt64Value()";
2887
  //////// all checks before this line
2888
14
  return detail::getInteger(*d_node).getLong();
2889
  ////////
2890
  CVC5_API_TRY_CATCH_END;
2891
}
2892
2893
77
bool Term::isUInt64Value() const
2894
{
2895
  CVC5_API_TRY_CATCH_BEGIN;
2896
77
  CVC5_API_CHECK_NOT_NULL;
2897
  //////// all checks before this line
2898
77
  return detail::isUInt64(*d_node);
2899
  ////////
2900
  CVC5_API_TRY_CATCH_END;
2901
}
2902
2903
65
std::uint64_t Term::getUInt64Value() const
2904
{
2905
  CVC5_API_TRY_CATCH_BEGIN;
2906
65
  CVC5_API_CHECK_NOT_NULL;
2907
65
  CVC5_API_ARG_CHECK_EXPECTED(detail::isUInt64(*d_node), *d_node)
2908
      << "Term to be a unsigned 64-bit integer value when calling "
2909
         "getUInt64Value()";
2910
  //////// all checks before this line
2911
65
  return detail::getInteger(*d_node).getUnsignedLong();
2912
  ////////
2913
  CVC5_API_TRY_CATCH_END;
2914
}
2915
2916
22
bool Term::isIntegerValue() const
2917
{
2918
  CVC5_API_TRY_CATCH_BEGIN;
2919
22
  CVC5_API_CHECK_NOT_NULL;
2920
  //////// all checks before this line
2921
22
  return detail::isInteger(*d_node);
2922
  ////////
2923
  CVC5_API_TRY_CATCH_END;
2924
}
2925
22
std::string Term::getIntegerValue() const
2926
{
2927
  CVC5_API_TRY_CATCH_BEGIN;
2928
22
  CVC5_API_CHECK_NOT_NULL;
2929
22
  CVC5_API_ARG_CHECK_EXPECTED(detail::isInteger(*d_node), *d_node)
2930
      << "Term to be an integer value when calling getIntegerValue()";
2931
  //////// all checks before this line
2932
22
  return detail::getInteger(*d_node).toString();
2933
  ////////
2934
  CVC5_API_TRY_CATCH_END;
2935
}
2936
2937
8666
bool Term::isStringValue() const
2938
{
2939
  CVC5_API_TRY_CATCH_BEGIN;
2940
8666
  CVC5_API_CHECK_NOT_NULL;
2941
  //////// all checks before this line
2942
8666
  return d_node->getKind() == cvc5::Kind::CONST_STRING;
2943
  ////////
2944
  CVC5_API_TRY_CATCH_END;
2945
}
2946
2947
8647
std::wstring Term::getStringValue() const
2948
{
2949
  CVC5_API_TRY_CATCH_BEGIN;
2950
8647
  CVC5_API_CHECK_NOT_NULL;
2951
8647
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getKind() == cvc5::Kind::CONST_STRING,
2952
                              *d_node)
2953
      << "Term to be a string value when calling getStringValue()";
2954
  //////// all checks before this line
2955
8647
  return d_node->getConst<cvc5::String>().toWString();
2956
  ////////
2957
  CVC5_API_TRY_CATCH_END;
2958
}
2959
2960
2543934
std::vector<Node> Term::termVectorToNodes(const std::vector<Term>& terms)
2961
{
2962
2543934
  std::vector<Node> res;
2963
8321856
  for (const Term& t : terms)
2964
  {
2965
5777922
    res.push_back(t.getNode());
2966
  }
2967
2543934
  return res;
2968
}
2969
2970
10
bool Term::isReal32Value() const
2971
{
2972
  CVC5_API_TRY_CATCH_BEGIN;
2973
10
  CVC5_API_CHECK_NOT_NULL;
2974
  //////// all checks before this line
2975
10
  return detail::isReal32(*d_node);
2976
  ////////
2977
  CVC5_API_TRY_CATCH_END;
2978
}
2979
10
std::pair<std::int32_t, std::uint32_t> Term::getReal32Value() const
2980
{
2981
  CVC5_API_TRY_CATCH_BEGIN;
2982
10
  CVC5_API_CHECK_NOT_NULL;
2983
10
  CVC5_API_ARG_CHECK_EXPECTED(detail::isReal32(*d_node), *d_node)
2984
      << "Term to be a 32-bit rational value when calling getReal32Value()";
2985
  //////// all checks before this line
2986
10
  const Rational& r = detail::getRational(*d_node);
2987
20
  return std::make_pair(r.getNumerator().getSignedInt(),
2988
30
                        r.getDenominator().getUnsignedInt());
2989
  ////////
2990
  CVC5_API_TRY_CATCH_END;
2991
}
2992
14
bool Term::isReal64Value() const
2993
{
2994
  CVC5_API_TRY_CATCH_BEGIN;
2995
14
  CVC5_API_CHECK_NOT_NULL;
2996
  //////// all checks before this line
2997
14
  return detail::isReal64(*d_node);
2998
  ////////
2999
  CVC5_API_TRY_CATCH_END;
3000
}
3001
14
std::pair<std::int64_t, std::uint64_t> Term::getReal64Value() const
3002
{
3003
  CVC5_API_TRY_CATCH_BEGIN;
3004
14
  CVC5_API_CHECK_NOT_NULL;
3005
14
  CVC5_API_ARG_CHECK_EXPECTED(detail::isReal64(*d_node), *d_node)
3006
      << "Term to be a 64-bit rational value when calling getReal64Value()";
3007
  //////// all checks before this line
3008
14
  const Rational& r = detail::getRational(*d_node);
3009
28
  return std::make_pair(r.getNumerator().getLong(),
3010
42
                        r.getDenominator().getUnsignedLong());
3011
  ////////
3012
  CVC5_API_TRY_CATCH_END;
3013
}
3014
20
bool Term::isRealValue() const
3015
{
3016
  CVC5_API_TRY_CATCH_BEGIN;
3017
20
  CVC5_API_CHECK_NOT_NULL;
3018
  //////// all checks before this line
3019
20
  return detail::isReal(*d_node);
3020
  ////////
3021
  CVC5_API_TRY_CATCH_END;
3022
}
3023
20
std::string Term::getRealValue() const
3024
{
3025
  CVC5_API_TRY_CATCH_BEGIN;
3026
20
  CVC5_API_CHECK_NOT_NULL;
3027
20
  CVC5_API_ARG_CHECK_EXPECTED(detail::isReal(*d_node), *d_node)
3028
      << "Term to be a rational value when calling getRealValue()";
3029
  //////// all checks before this line
3030
20
  const Rational& rat = detail::getRational(*d_node);
3031
40
  std::string res = rat.toString();
3032
20
  if (rat.isIntegral())
3033
  {
3034
10
    return res + "/1";
3035
  }
3036
10
  return res;
3037
  ////////
3038
  CVC5_API_TRY_CATCH_END;
3039
}
3040
3041
2
bool Term::isConstArray() const
3042
{
3043
  CVC5_API_TRY_CATCH_BEGIN;
3044
2
  CVC5_API_CHECK_NOT_NULL;
3045
  //////// all checks before this line
3046
2
  return d_node->getKind() == cvc5::Kind::STORE_ALL;
3047
  ////////
3048
  CVC5_API_TRY_CATCH_END;
3049
}
3050
6
Term Term::getConstArrayBase() const
3051
{
3052
  CVC5_API_TRY_CATCH_BEGIN;
3053
6
  CVC5_API_CHECK_NOT_NULL;
3054
8
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getKind() == cvc5::Kind::STORE_ALL,
3055
                              *d_node)
3056
2
      << "Term to be a constant array when calling getConstArrayBase()";
3057
  //////// all checks before this line
3058
4
  const auto& ar = d_node->getConst<ArrayStoreAll>();
3059
4
  return Term(d_solver, ar.getValue());
3060
  ////////
3061
  CVC5_API_TRY_CATCH_END;
3062
}
3063
3064
4
bool Term::isBooleanValue() const
3065
{
3066
  CVC5_API_TRY_CATCH_BEGIN;
3067
4
  CVC5_API_CHECK_NOT_NULL;
3068
  //////// all checks before this line
3069
4
  return d_node->getKind() == cvc5::Kind::CONST_BOOLEAN;
3070
  ////////
3071
  CVC5_API_TRY_CATCH_END;
3072
}
3073
4
bool Term::getBooleanValue() const
3074
{
3075
  CVC5_API_TRY_CATCH_BEGIN;
3076
4
  CVC5_API_CHECK_NOT_NULL;
3077
4
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getKind() == cvc5::Kind::CONST_BOOLEAN,
3078
                              *d_node)
3079
      << "Term to be a Boolean value when calling getBooleanValue()";
3080
  //////// all checks before this line
3081
4
  return d_node->getConst<bool>();
3082
  ////////
3083
  CVC5_API_TRY_CATCH_END;
3084
}
3085
3086
14
bool Term::isBitVectorValue() const
3087
{
3088
  CVC5_API_TRY_CATCH_BEGIN;
3089
14
  CVC5_API_CHECK_NOT_NULL;
3090
  //////// all checks before this line
3091
14
  return d_node->getKind() == cvc5::Kind::CONST_BITVECTOR;
3092
  ////////
3093
  CVC5_API_TRY_CATCH_END;
3094
}
3095
42
std::string Term::getBitVectorValue(std::uint32_t base) const
3096
{
3097
  CVC5_API_TRY_CATCH_BEGIN;
3098
42
  CVC5_API_CHECK_NOT_NULL;
3099
42
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getKind() == cvc5::Kind::CONST_BITVECTOR,
3100
                              *d_node)
3101
      << "Term to be a bit-vector value when calling getBitVectorValue()";
3102
  //////// all checks before this line
3103
42
  return d_node->getConst<BitVector>().toString(base);
3104
  ////////
3105
  CVC5_API_TRY_CATCH_END;
3106
}
3107
3108
6
bool Term::isAbstractValue() const
3109
{
3110
  CVC5_API_TRY_CATCH_BEGIN;
3111
6
  CVC5_API_CHECK_NOT_NULL;
3112
  //////// all checks before this line
3113
6
  return d_node->getKind() == cvc5::Kind::ABSTRACT_VALUE;
3114
  ////////
3115
  CVC5_API_TRY_CATCH_END;
3116
}
3117
6
std::string Term::getAbstractValue() const
3118
{
3119
  CVC5_API_TRY_CATCH_BEGIN;
3120
6
  CVC5_API_CHECK_NOT_NULL;
3121
6
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getKind() == cvc5::Kind::ABSTRACT_VALUE,
3122
                              *d_node)
3123
      << "Term to be an abstract value when calling "
3124
         "getAbstractValue()";
3125
  //////// all checks before this line
3126
6
  return d_node->getConst<AbstractValue>().getIndex().toString();
3127
  ////////
3128
  CVC5_API_TRY_CATCH_END;
3129
}
3130
3131
2
bool Term::isTupleValue() const
3132
{
3133
  CVC5_API_TRY_CATCH_BEGIN;
3134
2
  CVC5_API_CHECK_NOT_NULL;
3135
  //////// all checks before this line
3136
4
  return d_node->getKind() == cvc5::Kind::APPLY_CONSTRUCTOR && d_node->isConst()
3137
6
         && d_node->getType().getDType().isTuple();
3138
  ////////
3139
  CVC5_API_TRY_CATCH_END;
3140
}
3141
2
std::vector<Term> Term::getTupleValue() const
3142
{
3143
  CVC5_API_TRY_CATCH_BEGIN;
3144
2
  CVC5_API_CHECK_NOT_NULL;
3145
2
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getKind() == cvc5::Kind::APPLY_CONSTRUCTOR
3146
                                  && d_node->isConst()
3147
                                  && d_node->getType().getDType().isTuple(),
3148
                              *d_node)
3149
      << "Term to be a tuple value when calling getTupleValue()";
3150
  //////// all checks before this line
3151
4
  std::vector<Term> res;
3152
8
  for (size_t i = 0, n = d_node->getNumChildren(); i < n; ++i)
3153
  {
3154
6
    res.emplace_back(Term(d_solver, (*d_node)[i]));
3155
  }
3156
4
  return res;
3157
  ////////
3158
  CVC5_API_TRY_CATCH_END;
3159
}
3160
3161
4
bool Term::isFloatingPointPosZero() const
3162
{
3163
  CVC5_API_TRY_CATCH_BEGIN;
3164
4
  CVC5_API_CHECK_NOT_NULL;
3165
  //////// all checks before this line
3166
4
  if (d_node->getKind() == cvc5::Kind::CONST_FLOATINGPOINT)
3167
  {
3168
4
    const auto& fp = d_node->getConst<FloatingPoint>();
3169
4
    return fp.isZero() && fp.isPositive();
3170
  }
3171
  return false;
3172
  ////////
3173
  CVC5_API_TRY_CATCH_END;
3174
}
3175
4
bool Term::isFloatingPointNegZero() const
3176
{
3177
  CVC5_API_TRY_CATCH_BEGIN;
3178
4
  CVC5_API_CHECK_NOT_NULL;
3179
  //////// all checks before this line
3180
4
  if (d_node->getKind() == cvc5::Kind::CONST_FLOATINGPOINT)
3181
  {
3182
4
    const auto& fp = d_node->getConst<FloatingPoint>();
3183
4
    return fp.isZero() && fp.isNegative();
3184
  }
3185
  return false;
3186
  ////////
3187
  CVC5_API_TRY_CATCH_END;
3188
}
3189
4
bool Term::isFloatingPointPosInf() const
3190
{
3191
  CVC5_API_TRY_CATCH_BEGIN;
3192
4
  CVC5_API_CHECK_NOT_NULL;
3193
  //////// all checks before this line
3194
4
  if (d_node->getKind() == cvc5::Kind::CONST_FLOATINGPOINT)
3195
  {
3196
4
    const auto& fp = d_node->getConst<FloatingPoint>();
3197
4
    return fp.isInfinite() && fp.isPositive();
3198
  }
3199
  return false;
3200
  ////////
3201
  CVC5_API_TRY_CATCH_END;
3202
}
3203
4
bool Term::isFloatingPointNegInf() const
3204
{
3205
  CVC5_API_TRY_CATCH_BEGIN;
3206
4
  CVC5_API_CHECK_NOT_NULL;
3207
  //////// all checks before this line
3208
4
  if (d_node->getKind() == cvc5::Kind::CONST_FLOATINGPOINT)
3209
  {
3210
4
    const auto& fp = d_node->getConst<FloatingPoint>();
3211
4
    return fp.isInfinite() && fp.isNegative();
3212
  }
3213
  return false;
3214
  ////////
3215
  CVC5_API_TRY_CATCH_END;
3216
}
3217
4
bool Term::isFloatingPointNaN() const
3218
{
3219
  CVC5_API_TRY_CATCH_BEGIN;
3220
4
  CVC5_API_CHECK_NOT_NULL;
3221
  //////// all checks before this line
3222
4
  return d_node->getKind() == cvc5::Kind::CONST_FLOATINGPOINT
3223
4
         && d_node->getConst<FloatingPoint>().isNaN();
3224
  ////////
3225
  CVC5_API_TRY_CATCH_END;
3226
}
3227
2
bool Term::isFloatingPointValue() const
3228
{
3229
  CVC5_API_TRY_CATCH_BEGIN;
3230
2
  CVC5_API_CHECK_NOT_NULL;
3231
  //////// all checks before this line
3232
2
  return d_node->getKind() == cvc5::Kind::CONST_FLOATINGPOINT;
3233
  ////////
3234
  CVC5_API_TRY_CATCH_END;
3235
}
3236
2
std::tuple<std::uint32_t, std::uint32_t, Term> Term::getFloatingPointValue()
3237
    const
3238
{
3239
  CVC5_API_TRY_CATCH_BEGIN;
3240
2
  CVC5_API_CHECK_NOT_NULL;
3241
2
  CVC5_API_ARG_CHECK_EXPECTED(
3242
      d_node->getKind() == cvc5::Kind::CONST_FLOATINGPOINT, *d_node)
3243
      << "Term to be a floating-point value when calling "
3244
         "getFloatingPointValue()";
3245
  //////// all checks before this line
3246
2
  const auto& fp = d_node->getConst<FloatingPoint>();
3247
4
  return std::make_tuple(fp.getSize().exponentWidth(),
3248
4
                         fp.getSize().significandWidth(),
3249
6
                         d_solver->mkValHelper<BitVector>(fp.pack()));
3250
  ////////
3251
  CVC5_API_TRY_CATCH_END;
3252
}
3253
3254
12
bool Term::isSetValue() const
3255
{
3256
  CVC5_API_TRY_CATCH_BEGIN;
3257
12
  CVC5_API_CHECK_NOT_NULL;
3258
  //////// all checks before this line
3259
12
  return d_node->getType().isSet() && d_node->isConst();
3260
  ////////
3261
  CVC5_API_TRY_CATCH_END;
3262
}
3263
3264
14
void Term::collectSet(std::set<Term>& set,
3265
                      const cvc5::Node& node,
3266
                      const Solver* slv)
3267
{
3268
  // We asserted that node has a set type, and node.isConst()
3269
  // Thus, node only contains of EMPTYSET, UNION and SINGLETON.
3270
14
  switch (node.getKind())
3271
  {
3272
2
    case cvc5::Kind::EMPTYSET: break;
3273
10
    case cvc5::Kind::SINGLETON: set.emplace(Term(slv, node[0])); break;
3274
2
    case cvc5::Kind::UNION:
3275
    {
3276
6
      for (const auto& sub : node)
3277
      {
3278
4
        collectSet(set, sub, slv);
3279
      }
3280
2
      break;
3281
    }
3282
    default:
3283
      CVC5_API_ARG_CHECK_EXPECTED(false, node)
3284
          << "Term to be a set value when calling getSetValue()";
3285
      break;
3286
  }
3287
14
}
3288
3289
10
std::set<Term> Term::getSetValue() const
3290
{
3291
  CVC5_API_TRY_CATCH_BEGIN;
3292
10
  CVC5_API_CHECK_NOT_NULL;
3293
10
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getType().isSet() && d_node->isConst(),
3294
                              *d_node)
3295
      << "Term to be a set value when calling getSetValue()";
3296
  //////// all checks before this line
3297
20
  std::set<Term> res;
3298
10
  Term::collectSet(res, *d_node, d_solver);
3299
20
  return res;
3300
  ////////
3301
  CVC5_API_TRY_CATCH_END;
3302
}
3303
3304
10
bool Term::isSequenceValue() const
3305
{
3306
  CVC5_API_TRY_CATCH_BEGIN;
3307
10
  CVC5_API_CHECK_NOT_NULL;
3308
  //////// all checks before this line
3309
10
  return d_node->getKind() == cvc5::Kind::CONST_SEQUENCE;
3310
  ////////
3311
  CVC5_API_TRY_CATCH_END;
3312
}
3313
25
std::vector<Term> Term::getSequenceValue() const
3314
{
3315
  CVC5_API_TRY_CATCH_BEGIN;
3316
25
  CVC5_API_CHECK_NOT_NULL;
3317
27
  CVC5_API_ARG_CHECK_EXPECTED(d_node->getKind() == cvc5::Kind::CONST_SEQUENCE,
3318
                              *d_node)
3319
2
      << "Term to be a sequence value when calling getSequenceValue()";
3320
  //////// all checks before this line
3321
46
  std::vector<Term> res;
3322
23
  const Sequence& seq = d_node->getConst<Sequence>();
3323
35
  for (const auto& node: seq.getVec())
3324
  {
3325
12
    res.emplace_back(Term(d_solver, node));
3326
  }
3327
46
  return res;
3328
  ////////
3329
  CVC5_API_TRY_CATCH_END;
3330
}
3331
3332
4
bool Term::isUninterpretedValue() const
3333
{
3334
  CVC5_API_TRY_CATCH_BEGIN;
3335
4
  CVC5_API_CHECK_NOT_NULL;
3336
  //////// all checks before this line
3337
4
  return d_node->getKind() == cvc5::Kind::UNINTERPRETED_CONSTANT;
3338
  ////////
3339
  CVC5_API_TRY_CATCH_END;
3340
}
3341
4
std::pair<Sort, std::int32_t> Term::getUninterpretedValue() const
3342
{
3343
  CVC5_API_TRY_CATCH_BEGIN;
3344
4
  CVC5_API_CHECK_NOT_NULL;
3345
4
  CVC5_API_ARG_CHECK_EXPECTED(
3346
      d_node->getKind() == cvc5::Kind::UNINTERPRETED_CONSTANT, *d_node)
3347
      << "Term to be an uninterpreted value when calling "
3348
         "getUninterpretedValue()";
3349
  //////// all checks before this line
3350
4
  const auto& uc = d_node->getConst<UninterpretedConstant>();
3351
8
  return std::make_pair(Sort(d_solver, uc.getType()),
3352
12
                        uc.getIndex().toUnsignedInt());
3353
  ////////
3354
  CVC5_API_TRY_CATCH_END;
3355
}
3356
3357
3142
std::ostream& operator<<(std::ostream& out, const Term& t)
3358
{
3359
3142
  out << t.toString();
3360
3142
  return out;
3361
}
3362
3363
std::ostream& operator<<(std::ostream& out, const std::vector<Term>& vector)
3364
{
3365
  container_to_stream(out, vector);
3366
  return out;
3367
}
3368
3369
std::ostream& operator<<(std::ostream& out, const std::set<Term>& set)
3370
{
3371
  container_to_stream(out, set);
3372
  return out;
3373
}
3374
3375
std::ostream& operator<<(std::ostream& out,
3376
                         const std::unordered_set<Term>& unordered_set)
3377
{
3378
  container_to_stream(out, unordered_set);
3379
  return out;
3380
}
3381
3382
template <typename V>
3383
std::ostream& operator<<(std::ostream& out, const std::map<Term, V>& map)
3384
{
3385
  container_to_stream(out, map);
3386
  return out;
3387
}
3388
3389
template <typename V>
3390
std::ostream& operator<<(std::ostream& out,
3391
                         const std::unordered_map<Term, V>& unordered_map)
3392
{
3393
  container_to_stream(out, unordered_map);
3394
  return out;
3395
}
3396
3397
/* Helpers                                                                    */
3398
/* -------------------------------------------------------------------------- */
3399
3400
/* Split out to avoid nested API calls (problematic with API tracing).        */
3401
/* .......................................................................... */
3402
3403
24220147
bool Term::isNullHelper() const
3404
{
3405
  /* Split out to avoid nested API calls (problematic with API tracing). */
3406
24220147
  return d_node->isNull();
3407
}
3408
3409
5419
Kind Term::getKindHelper() const
3410
{
3411
  /* Sequence kinds do not exist internally, so we must convert their internal
3412
   * (string) versions back to sequence. All operators where this is
3413
   * necessary are such that their first child is of sequence type, which
3414
   * we check here. */
3415
5419
  if (d_node->getNumChildren() > 0 && (*d_node)[0].getType().isSequence())
3416
  {
3417
2
    switch (d_node->getKind())
3418
    {
3419
2
      case cvc5::Kind::STRING_CONCAT: return SEQ_CONCAT;
3420
      case cvc5::Kind::STRING_LENGTH: return SEQ_LENGTH;
3421
      case cvc5::Kind::STRING_SUBSTR: return SEQ_EXTRACT;
3422
      case cvc5::Kind::STRING_UPDATE: return SEQ_UPDATE;
3423
      case cvc5::Kind::STRING_CHARAT: return SEQ_AT;
3424
      case cvc5::Kind::STRING_CONTAINS: return SEQ_CONTAINS;
3425
      case cvc5::Kind::STRING_INDEXOF: return SEQ_INDEXOF;
3426
      case cvc5::Kind::STRING_REPLACE: return SEQ_REPLACE;
3427
      case cvc5::Kind::STRING_REPLACE_ALL: return SEQ_REPLACE_ALL;
3428
      case cvc5::Kind::STRING_REV: return SEQ_REV;
3429
      case cvc5::Kind::STRING_PREFIX: return SEQ_PREFIX;
3430
      case cvc5::Kind::STRING_SUFFIX: return SEQ_SUFFIX;
3431
      default:
3432
        // fall through to conversion below
3433
        break;
3434
    }
3435
  }
3436
  // Notice that kinds like APPLY_TYPE_ASCRIPTION will be converted to
3437
  // INTERNAL_KIND.
3438
5417
  if (isCastedReal())
3439
  {
3440
2
    return CONST_RATIONAL;
3441
  }
3442
5415
  return intToExtKind(d_node->getKind());
3443
}
3444
3445
5567
bool Term::isCastedReal() const
3446
{
3447
5567
  if (d_node->getKind() == kind::CAST_TO_REAL)
3448
  {
3449
6
    return (*d_node)[0].isConst() && (*d_node)[0].getType().isInteger();
3450
  }
3451
5561
  return false;
3452
}
3453
3454
/* -------------------------------------------------------------------------- */
3455
/* Datatypes                                                                  */
3456
/* -------------------------------------------------------------------------- */
3457
3458
/* DatatypeConstructorDecl -------------------------------------------------- */
3459
3460
2
DatatypeConstructorDecl::DatatypeConstructorDecl()
3461
2
    : d_solver(nullptr), d_ctor(nullptr)
3462
{
3463
2
}
3464
3465
3075
DatatypeConstructorDecl::DatatypeConstructorDecl(const Solver* slv,
3466
3075
                                                 const std::string& name)
3467
3075
    : d_solver(slv), d_ctor(new cvc5::DTypeConstructor(name))
3468
{
3469
3075
}
3470
6194
DatatypeConstructorDecl::~DatatypeConstructorDecl()
3471
{
3472
3097
  if (d_ctor != nullptr)
3473
  {
3474
3097
    d_ctor.reset();
3475
  }
3476
3097
}
3477
3478
2979
void DatatypeConstructorDecl::addSelector(const std::string& name,
3479
                                          const Sort& sort)
3480
{
3481
  CVC5_API_TRY_CATCH_BEGIN;
3482
2979
  CVC5_API_CHECK_NOT_NULL;
3483
2979
  CVC5_API_CHECK_SORT(sort);
3484
2977
  CVC5_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort)
3485
      << "non-null range sort for selector";
3486
  //////// all checks before this line
3487
2977
  d_ctor->addArg(name, *sort.d_type);
3488
  ////////
3489
  CVC5_API_TRY_CATCH_END;
3490
2977
}
3491
3492
34
void DatatypeConstructorDecl::addSelectorSelf(const std::string& name)
3493
{
3494
  CVC5_API_TRY_CATCH_BEGIN;
3495
34
  CVC5_API_CHECK_NOT_NULL;
3496
  //////// all checks before this line
3497
34
  d_ctor->addArgSelf(name);
3498
  ////////
3499
  CVC5_API_TRY_CATCH_END;
3500
34
}
3501
3502
3091
bool DatatypeConstructorDecl::isNull() const
3503
{
3504
  CVC5_API_TRY_CATCH_BEGIN;
3505
  //////// all checks before this line
3506
3091
  return isNullHelper();
3507
  ////////
3508
  CVC5_API_TRY_CATCH_END;
3509
}
3510
3511
std::string DatatypeConstructorDecl::toString() const
3512
{
3513
  CVC5_API_TRY_CATCH_BEGIN;
3514
  //////// all checks before this line
3515
  std::stringstream ss;
3516
  ss << *d_ctor;
3517
  return ss.str();
3518
  ////////
3519
  CVC5_API_TRY_CATCH_END;
3520
}
3521
3522
std::ostream& operator<<(std::ostream& out,
3523
                         const DatatypeConstructorDecl& ctordecl)
3524
{
3525
  out << ctordecl.toString();
3526
  return out;
3527
}
3528
3529
4
std::ostream& operator<<(std::ostream& out,
3530
                         const std::vector<DatatypeConstructorDecl>& vector)
3531
{
3532
4
  container_to_stream(out, vector);
3533
4
  return out;
3534
}
3535
3536
6104
bool DatatypeConstructorDecl::isNullHelper() const { return d_ctor == nullptr; }
3537
3538
/* DatatypeDecl ------------------------------------------------------------- */
3539
3540
4
DatatypeDecl::DatatypeDecl() : d_solver(nullptr), d_dtype(nullptr) {}
3541
3542
734
DatatypeDecl::DatatypeDecl(const Solver* slv,
3543
                           const std::string& name,
3544
734
                           bool isCoDatatype)
3545
734
    : d_solver(slv), d_dtype(new cvc5::DType(name, isCoDatatype))
3546
{
3547
734
}
3548
3549
12
DatatypeDecl::DatatypeDecl(const Solver* slv,
3550
                           const std::string& name,
3551
                           const Sort& param,
3552
12
                           bool isCoDatatype)
3553
    : d_solver(slv),
3554
      d_dtype(new cvc5::DType(
3555
12
          name, std::vector<TypeNode>{*param.d_type}, isCoDatatype))
3556
{
3557
12
}
3558
3559
1532
DatatypeDecl::DatatypeDecl(const Solver* slv,
3560
                           const std::string& name,
3561
                           const std::vector<Sort>& params,
3562
1532
                           bool isCoDatatype)
3563
1532
    : d_solver(slv)
3564
{
3565
3064
  std::vector<TypeNode> tparams = Sort::sortVectorToTypeNodes(params);
3566
4596
  d_dtype = std::shared_ptr<cvc5::DType>(
3567
3064
      new cvc5::DType(name, tparams, isCoDatatype));
3568
1532
}
3569
3570
9080
bool DatatypeDecl::isNullHelper() const { return !d_dtype; }
3571
3572
8640
DatatypeDecl::~DatatypeDecl()
3573
{
3574
4320
  if (d_dtype != nullptr)
3575
  {
3576
4318
    d_dtype.reset();
3577
  }
3578
4320
}
3579
3580
3075
void DatatypeDecl::addConstructor(const DatatypeConstructorDecl& ctor)
3581
{
3582
  CVC5_API_TRY_CATCH_BEGIN;
3583
3075
  CVC5_API_CHECK_NOT_NULL;
3584
3075
  CVC5_API_ARG_CHECK_NOT_NULL(ctor);
3585
3075
  CVC5_API_ARG_CHECK_SOLVER("datatype constructor declaration", ctor);
3586
  //////// all checks before this line
3587
3075
  d_dtype->addConstructor(ctor.d_ctor);
3588
  ////////
3589
  CVC5_API_TRY_CATCH_END;
3590
3075
}
3591
3592
1618
size_t DatatypeDecl::getNumConstructors() const
3593
{
3594
  CVC5_API_TRY_CATCH_BEGIN;
3595
1618
  CVC5_API_CHECK_NOT_NULL;
3596
  //////// all checks before this line
3597
1618
  return d_dtype->getNumConstructors();
3598
  ////////
3599
  CVC5_API_TRY_CATCH_END;
3600
}
3601
3602
bool DatatypeDecl::isParametric() const
3603
{
3604
  CVC5_API_TRY_CATCH_BEGIN;
3605
  CVC5_API_CHECK_NOT_NULL;
3606
  //////// all checks before this line
3607
  return d_dtype->isParametric();
3608
  ////////
3609
  CVC5_API_TRY_CATCH_END;
3610
}
3611
3612
2
std::string DatatypeDecl::toString() const
3613
{
3614
  CVC5_API_TRY_CATCH_BEGIN;
3615
2
  CVC5_API_CHECK_NOT_NULL;
3616
  //////// all checks before this line
3617
4
  std::stringstream ss;
3618
2
  ss << *d_dtype;
3619
4
  return ss.str();
3620
  ////////
3621
  CVC5_API_TRY_CATCH_END;
3622
}
3623
3624
10
std::string DatatypeDecl::getName() const
3625
{
3626
  CVC5_API_TRY_CATCH_BEGIN;
3627
10
  CVC5_API_CHECK_NOT_NULL;
3628
  //////// all checks before this line
3629
8
  return d_dtype->getName();
3630
  ////////
3631
  CVC5_API_TRY_CATCH_END;
3632
}
3633
3634
4375
bool DatatypeDecl::isNull() const
3635
{
3636
  CVC5_API_TRY_CATCH_BEGIN;
3637
  //////// all checks before this line
3638
4375
  return isNullHelper();
3639
  ////////
3640
  CVC5_API_TRY_CATCH_END;
3641
}
3642
3643
2
std::ostream& operator<<(std::ostream& out, const DatatypeDecl& dtdecl)
3644
{
3645
2
  out << dtdecl.toString();
3646
2
  return out;
3647
}
3648
3649
1556
cvc5::DType& DatatypeDecl::getDatatype(void) const { return *d_dtype; }
3650
3651
/* DatatypeSelector --------------------------------------------------------- */
3652
3653
2
DatatypeSelector::DatatypeSelector() : d_solver(nullptr), d_stor(nullptr) {}
3654
3655
3015
DatatypeSelector::DatatypeSelector(const Solver* slv,
3656
3015
                                   const cvc5::DTypeSelector& stor)
3657
3015
    : d_solver(slv), d_stor(new cvc5::DTypeSelector(stor))
3658
{
3659
3015
  CVC5_API_CHECK(d_stor->isResolved()) << "Expected resolved datatype selector";
3660
3015
}
3661
3662
6034
DatatypeSelector::~DatatypeSelector()
3663
{
3664
3017
  if (d_stor != nullptr)
3665
  {
3666
3017
    d_stor.reset();
3667
  }
3668
3017
}
3669
3670
2875
std::string DatatypeSelector::getName() const
3671
{
3672
  CVC5_API_TRY_CATCH_BEGIN;
3673
2875
  CVC5_API_CHECK_NOT_NULL;
3674
  //////// all checks before this line
3675
2875
  return d_stor->getName();
3676
  ////////
3677
  CVC5_API_TRY_CATCH_END;
3678
}
3679
3680
2956
Term DatatypeSelector::getSelectorTerm() const
3681
{
3682
  CVC5_API_TRY_CATCH_BEGIN;
3683
2956
  CVC5_API_CHECK_NOT_NULL;
3684
  //////// all checks before this line
3685
2956
  return Term(d_solver, d_stor->getSelector());
3686
  ////////
3687
  CVC5_API_TRY_CATCH_END;
3688
}
3689
43
Term DatatypeSelector::getUpdaterTerm() const
3690
{
3691
  CVC5_API_TRY_CATCH_BEGIN;
3692
43
  CVC5_API_CHECK_NOT_NULL;
3693
  //////// all checks before this line
3694
43
  return Term(d_solver, d_stor->getUpdater());
3695
  ////////
3696
  CVC5_API_TRY_CATCH_END;
3697
}
3698
3699
10
Sort DatatypeSelector::getRangeSort() const
3700
{
3701
  CVC5_API_TRY_CATCH_BEGIN;
3702
10
  CVC5_API_CHECK_NOT_NULL;
3703
  //////// all checks before this line
3704
10
  return Sort(d_solver, d_stor->getRangeType());
3705
  ////////
3706
  CVC5_API_TRY_CATCH_END;
3707
}
3708
3709
4
bool DatatypeSelector::isNull() const
3710
{
3711
  CVC5_API_TRY_CATCH_BEGIN;
3712
  //////// all checks before this line
3713
4
  return isNullHelper();
3714
  ////////
3715
  CVC5_API_TRY_CATCH_END;
3716
}
3717
3718
std::string DatatypeSelector::toString() const
3719
{
3720
  CVC5_API_TRY_CATCH_BEGIN;
3721
  //////// all checks before this line
3722
  std::stringstream ss;
3723
  ss << *d_stor;
3724
  return ss.str();
3725
  ////////
3726
  CVC5_API_TRY_CATCH_END;
3727
}
3728
3729
std::ostream& operator<<(std::ostream& out, const DatatypeSelector& stor)
3730
{
3731
  out << stor.toString();
3732
  return out;
3733
}
3734
3735
5888
bool DatatypeSelector::isNullHelper() const { return d_stor == nullptr; }
3736
3737
/* DatatypeConstructor ------------------------------------------------------ */
3738
3739
2
DatatypeConstructor::DatatypeConstructor() : d_solver(nullptr), d_ctor(nullptr)
3740
{
3741
2
}
3742
3743
6580
DatatypeConstructor::DatatypeConstructor(const Solver* slv,
3744
6580
                                         const cvc5::DTypeConstructor& ctor)
3745
6580
    : d_solver(slv), d_ctor(new cvc5::DTypeConstructor(ctor))
3746
{
3747
6580
  CVC5_API_CHECK(d_ctor->isResolved())
3748
      << "Expected resolved datatype constructor";
3749
6580
}
3750
3751
13164
DatatypeConstructor::~DatatypeConstructor()
3752
{
3753
6582
  if (d_ctor != nullptr)
3754
  {
3755
6582
    d_ctor.reset();
3756
  }
3757
6582
}
3758
3759
2909
std::string DatatypeConstructor::getName() const
3760
{
3761
  CVC5_API_TRY_CATCH_BEGIN;
3762
2909
  CVC5_API_CHECK_NOT_NULL;
3763
  //////// all checks before this line
3764
2909
  return d_ctor->getName();
3765
  ////////
3766
  CVC5_API_TRY_CATCH_END;
3767
}
3768
3769
4753
Term DatatypeConstructor::getConstructorTerm() const
3770
{
3771
  CVC5_API_TRY_CATCH_BEGIN;
3772
4753
  CVC5_API_CHECK_NOT_NULL;
3773
  //////// all checks before this line
3774
4753
  return Term(d_solver, d_ctor->getConstructor());
3775
  ////////
3776
  CVC5_API_TRY_CATCH_END;
3777
}
3778
3779
42
Term DatatypeConstructor::getSpecializedConstructorTerm(
3780
    const Sort& retSort) const
3781
{
3782
  CVC5_API_TRY_CATCH_BEGIN;
3783
42
  CVC5_API_CHECK_NOT_NULL;
3784
42
  CVC5_API_CHECK(d_ctor->isResolved())
3785
      << "Expected resolved datatype constructor";
3786
44
  CVC5_API_CHECK(retSort.isDatatype())
3787
2
      << "Cannot get specialized constructor type for non-datatype type "
3788
      << retSort;
3789
  //////// all checks before this line
3790
3791
40
  NodeManager* nm = d_solver->getNodeManager();
3792
  Node ret =
3793
      nm->mkNode(kind::APPLY_TYPE_ASCRIPTION,
3794
80
                 nm->mkConst(AscriptionType(
3795
80
                     d_ctor->getSpecializedConstructorType(*retSort.d_type))),
3796
160
                 d_ctor->getConstructor());
3797
40
  (void)ret.getType(true); /* kick off type checking */
3798
  // apply type ascription to the operator
3799
80
  Term sctor = api::Term(d_solver, ret);
3800
80
  return sctor;
3801
  ////////
3802
  CVC5_API_TRY_CATCH_END;
3803
}
3804
3805
4595
Term DatatypeConstructor::getTesterTerm() const
3806
{
3807
  CVC5_API_TRY_CATCH_BEGIN;
3808
4595
  CVC5_API_CHECK_NOT_NULL;
3809
  //////// all checks before this line
3810
4595
  return Term(d_solver, d_ctor->getTester());
3811
  ////////
3812
  CVC5_API_TRY_CATCH_END;
3813
}
3814
3815
2935
size_t DatatypeConstructor::getNumSelectors() const
3816
{
3817
  CVC5_API_TRY_CATCH_BEGIN;
3818
2935
  CVC5_API_CHECK_NOT_NULL;
3819
  //////// all checks before this line
3820
2935
  return d_ctor->getNumArgs();
3821
  ////////
3822
  CVC5_API_TRY_CATCH_END;
3823
}
3824
3825
2956
DatatypeSelector DatatypeConstructor::operator[](size_t index) const
3826
{
3827
  CVC5_API_TRY_CATCH_BEGIN;
3828
2956
  CVC5_API_CHECK_NOT_NULL;
3829
  //////// all checks before this line
3830
2956
  return DatatypeSelector(d_solver, (*d_ctor)[index]);
3831
  ////////
3832
  CVC5_API_TRY_CATCH_END;
3833
}
3834
3835
4
DatatypeSelector DatatypeConstructor::operator[](const std::string& name) const
3836
{
3837
  CVC5_API_TRY_CATCH_BEGIN;
3838
4
  CVC5_API_CHECK_NOT_NULL;
3839
  //////// all checks before this line
3840
4
  return getSelectorForName(name);
3841
  ////////
3842
  CVC5_API_TRY_CATCH_END;
3843
}
3844
3845
24
DatatypeSelector DatatypeConstructor::getSelector(const std::string& name) const
3846
{
3847
  CVC5_API_TRY_CATCH_BEGIN;
3848
24
  CVC5_API_CHECK_NOT_NULL;
3849
  //////// all checks before this line
3850
24
  return getSelectorForName(name);
3851
  ////////
3852
  CVC5_API_TRY_CATCH_END;
3853
}
3854
3855
18
Term DatatypeConstructor::getSelectorTerm(const std::string& name) const
3856
{
3857
  CVC5_API_TRY_CATCH_BEGIN;
3858
18
  CVC5_API_CHECK_NOT_NULL;
3859
  //////// all checks before this line
3860
18
  return getSelector(name).getSelectorTerm();
3861
  ////////
3862
  CVC5_API_TRY_CATCH_END;
3863
}
3864
3865
DatatypeConstructor::const_iterator DatatypeConstructor::begin() const
3866
{
3867
  return DatatypeConstructor::const_iterator(d_solver, *d_ctor, true);
3868
}
3869
3870
DatatypeConstructor::const_iterator DatatypeConstructor::end() const
3871
{
3872
  return DatatypeConstructor::const_iterator(d_solver, *d_ctor, false);
3873
}
3874
3875
DatatypeConstructor::const_iterator::const_iterator(
3876
    const Solver* slv, const cvc5::DTypeConstructor& ctor, bool begin)
3877
{
3878
  d_solver = slv;
3879
  d_int_stors = &ctor.getArgs();
3880
3881
  const std::vector<std::shared_ptr<cvc5::DTypeSelector>>& sels =
3882
      ctor.getArgs();
3883
  for (const std::shared_ptr<cvc5::DTypeSelector>& s : sels)
3884
  {
3885
    /* Can not use emplace_back here since constructor is private. */
3886
    d_stors.push_back(DatatypeSelector(d_solver, *s.get()));
3887
  }
3888
  d_idx = begin ? 0 : sels.size();
3889
}
3890
3891
DatatypeConstructor::const_iterator::const_iterator()
3892
    : d_solver(nullptr), d_int_stors(nullptr), d_idx(0)
3893
{
3894
}
3895
3896
DatatypeConstructor::const_iterator&
3897
DatatypeConstructor::const_iterator::operator=(
3898
    const DatatypeConstructor::const_iterator& it)
3899
{
3900
  d_solver = it.d_solver;
3901
  d_int_stors = it.d_int_stors;
3902
  d_stors = it.d_stors;
3903
  d_idx = it.d_idx;
3904
  return *this;
3905
}
3906
3907
const DatatypeSelector& DatatypeConstructor::const_iterator::operator*() const
3908
{
3909
  return d_stors[d_idx];
3910
}
3911
3912
const DatatypeSelector* DatatypeConstructor::const_iterator::operator->() const
3913
{
3914
  return &d_stors[d_idx];
3915
}
3916
3917
DatatypeConstructor::const_iterator&
3918
DatatypeConstructor::const_iterator::operator++()
3919
{
3920
  ++d_idx;
3921
  return *this;
3922
}
3923
3924
DatatypeConstructor::const_iterator
3925
DatatypeConstructor::const_iterator::operator++(int)
3926
{
3927
  DatatypeConstructor::const_iterator it(*this);
3928
  ++d_idx;
3929
  return it;
3930
}
3931
3932
bool DatatypeConstructor::const_iterator::operator==(
3933
    const DatatypeConstructor::const_iterator& other) const
3934
{
3935
  return d_int_stors == other.d_int_stors && d_idx == other.d_idx;
3936
}
3937
3938
bool DatatypeConstructor::const_iterator::operator!=(
3939
    const DatatypeConstructor::const_iterator& other) const
3940
{
3941
  return d_int_stors != other.d_int_stors || d_idx != other.d_idx;
3942
}
3943
3944
4
bool DatatypeConstructor::isNull() const
3945
{
3946
  CVC5_API_TRY_CATCH_BEGIN;
3947
  //////// all checks before this line
3948
4
  return isNullHelper();
3949
  ////////
3950
  CVC5_API_TRY_CATCH_END;
3951
}
3952
3953
std::string DatatypeConstructor::toString() const
3954
{
3955
  CVC5_API_TRY_CATCH_BEGIN;
3956
  //////// all checks before this line
3957
  std::stringstream ss;
3958
  ss << *d_ctor;
3959
  return ss.str();
3960
  ////////
3961
  CVC5_API_TRY_CATCH_END;
3962
}
3963
3964
18240
bool DatatypeConstructor::isNullHelper() const { return d_ctor == nullptr; }
3965
3966
28
DatatypeSelector DatatypeConstructor::getSelectorForName(
3967
    const std::string& name) const
3968
{
3969
28
  bool foundSel = false;
3970
28
  size_t index = 0;
3971
42
  for (size_t i = 0, nsels = getNumSelectors(); i < nsels; i++)
3972
  {
3973
40
    if ((*d_ctor)[i].getName() == name)
3974
    {
3975
26
      index = i;
3976
26
      foundSel = true;
3977
26
      break;
3978
    }
3979
  }
3980
28
  if (!foundSel)
3981
  {
3982
4
    std::stringstream snames;
3983
2
    snames << "{ ";
3984
6
    for (size_t i = 0, ncons = getNumSelectors(); i < ncons; i++)
3985
    {
3986
4
      snames << (*d_ctor)[i].getName() << " ";
3987
    }
3988
2
    snames << "} ";
3989
10
    CVC5_API_CHECK(foundSel) << "No selector " << name << " for constructor "
3990
8
                             << getName() << " exists among " << snames.str();
3991
  }
3992
26
  return DatatypeSelector(d_solver, (*d_ctor)[index]);
3993
}
3994
3995
std::ostream& operator<<(std::ostream& out, const DatatypeConstructor& ctor)
3996
{
3997
  out << ctor.toString();
3998
  return out;
3999
}
4000
4001
/* Datatype ----------------------------------------------------------------- */
4002
4003
6782
Datatype::Datatype(const Solver* slv, const cvc5::DType& dtype)
4004
6782
    : d_solver(slv), d_dtype(new cvc5::DType(dtype))
4005
{
4006
6782
  CVC5_API_CHECK(d_dtype->isResolved()) << "Expected resolved datatype";
4007
6782
}
4008
4009
2
Datatype::Datatype() : d_solver(nullptr), d_dtype(nullptr) {}
4010
4011
13568
Datatype::~Datatype()
4012
{
4013
6784
  if (d_dtype != nullptr)
4014
  {
4015
6784
    d_dtype.reset();
4016
  }
4017
6784
}
4018
4019
4802
DatatypeConstructor Datatype::operator[](size_t idx) const
4020
{
4021
  CVC5_API_TRY_CATCH_BEGIN;
4022
4802
  CVC5_API_CHECK_NOT_NULL;
4023
4802
  CVC5_API_CHECK(idx < getNumConstructors()) << "Index out of bounds.";
4024
  //////// all checks before this line
4025
4800
  return DatatypeConstructor(d_solver, (*d_dtype)[idx]);
4026
  ////////
4027
  CVC5_API_TRY_CATCH_END;
4028
}
4029
4030
24
DatatypeConstructor Datatype::operator[](const std::string& name) const
4031
{
4032
  CVC5_API_TRY_CATCH_BEGIN;
4033
24
  CVC5_API_CHECK_NOT_NULL;
4034
  //////// all checks before this line
4035
24
  return getConstructorForName(name);
4036
  ////////
4037
  CVC5_API_TRY_CATCH_END;
4038
}
4039
4040
1736
DatatypeConstructor Datatype::getConstructor(const std::string& name) const
4041
{
4042
  CVC5_API_TRY_CATCH_BEGIN;
4043
1736
  CVC5_API_CHECK_NOT_NULL;
4044
  //////// all checks before this line
4045
1736
  return getConstructorForName(name);
4046
  ////////
4047
  CVC5_API_TRY_CATCH_END;
4048
}
4049
4050
24
Term Datatype::getConstructorTerm(const std::string& name) const
4051
{
4052
  CVC5_API_TRY_CATCH_BEGIN;
4053
24
  CVC5_API_CHECK_NOT_NULL;
4054
  //////// all checks before this line
4055
24
  return getConstructorForName(name).getConstructorTerm();
4056
  ////////
4057
  CVC5_API_TRY_CATCH_END;
4058
}
4059
4060
35
DatatypeSelector Datatype::getSelector(const std::string& name) const
4061
{
4062
  CVC5_API_TRY_CATCH_BEGIN;
4063
35
  CVC5_API_CHECK_NOT_NULL;
4064
  //////// all checks before this line
4065
35
  return getSelectorForName(name);
4066
  ////////
4067
  CVC5_API_TRY_CATCH_END;
4068
}
4069
4070
1538
std::string Datatype::getName() const
4071
{
4072
  CVC5_API_TRY_CATCH_BEGIN;
4073
1538
  CVC5_API_CHECK_NOT_NULL;
4074
  //////// all checks before this line
4075
1538
  return d_dtype->getName();
4076
  ////////
4077
  CVC5_API_TRY_CATCH_END;
4078
}
4079
4080
8151
size_t Datatype::getNumConstructors() const
4081
{
4082
  CVC5_API_TRY_CATCH_BEGIN;
4083
8151
  CVC5_API_CHECK_NOT_NULL;
4084
  //////// all checks before this line
4085
8151
  return d_dtype->getNumConstructors();
4086
  ////////
4087
  CVC5_API_TRY_CATCH_END;
4088
}
4089
4090
12
bool Datatype::isParametric() const
4091
{
4092
  CVC5_API_TRY_CATCH_BEGIN;
4093
12
  CVC5_API_CHECK_NOT_NULL;
4094
  //////// all checks before this line
4095
12
  return d_dtype->isParametric();
4096
  ////////
4097
  CVC5_API_TRY_CATCH_END;
4098
}
4099
4100
1530
bool Datatype::isCodatatype() const
4101
{
4102
  CVC5_API_TRY_CATCH_BEGIN;
4103
1530
  CVC5_API_CHECK_NOT_NULL;
4104
  //////// all checks before this line
4105
1530
  return d_dtype->isCodatatype();
4106
  ////////
4107
  CVC5_API_TRY_CATCH_END;
4108
}
4109
4110
8
bool Datatype::isTuple() const
4111
{
4112
  CVC5_API_TRY_CATCH_BEGIN;
4113
8
  CVC5_API_CHECK_NOT_NULL;
4114
  //////// all checks before this line
4115
8
  return d_dtype->isTuple();
4116
  ////////
4117
  CVC5_API_TRY_CATCH_END;
4118
}
4119
4120
6
bool Datatype::isRecord() const
4121
{
4122
  CVC5_API_TRY_CATCH_BEGIN;
4123
6
  CVC5_API_CHECK_NOT_NULL;
4124
  //////// all checks before this line
4125
6
  return d_dtype->isRecord();
4126
  ////////
4127
  CVC5_API_TRY_CATCH_END;
4128
}
4129
4130
14
bool Datatype::isFinite() const
4131
{
4132
  CVC5_API_TRY_CATCH_BEGIN;
4133
14
  CVC5_API_CHECK_NOT_NULL;
4134
  //////// all checks before this line
4135
  // we assume that finite model finding is disabled by passing false as the
4136
  // second argument
4137
14
  return isCardinalityClassFinite(d_dtype->getCardinalityClass(), false);
4138
  ////////
4139
  CVC5_API_TRY_CATCH_END;
4140
}
4141
4142
1504
bool Datatype::isWellFounded() const
4143
{
4144
  CVC5_API_TRY_CATCH_BEGIN;
4145
1504
  CVC5_API_CHECK_NOT_NULL;
4146
  //////// all checks before this line
4147
1504
  return d_dtype->isWellFounded();
4148
  ////////
4149
  CVC5_API_TRY_CATCH_END;
4150
}
4151
18
bool Datatype::hasNestedRecursion() const
4152
{
4153
  CVC5_API_TRY_CATCH_BEGIN;
4154
18
  CVC5_API_CHECK_NOT_NULL;
4155
  //////// all checks before this line
4156
18
  return d_dtype->hasNestedRecursion();
4157
  ////////
4158
  CVC5_API_TRY_CATCH_END;
4159
}
4160
4161
4
bool Datatype::isNull() const
4162
{
4163
  CVC5_API_TRY_CATCH_BEGIN;
4164
  //////// all checks before this line
4165
4
  return isNullHelper();
4166
  ////////
4167
  CVC5_API_TRY_CATCH_END;
4168
}
4169
4170
std::string Datatype::toString() const
4171
{
4172
  CVC5_API_TRY_CATCH_BEGIN;
4173
  CVC5_API_CHECK_NOT_NULL;
4174
  //////// all checks before this line
4175
  return d_dtype->getName();
4176
  ////////
4177
  CVC5_API_TRY_CATCH_END;
4178
}
4179
4180
Datatype::const_iterator Datatype::begin() const
4181
{
4182
  return Datatype::const_iterator(d_solver, *d_dtype, true);
4183
}
4184
4185
Datatype::const_iterator Datatype::end() const
4186
{
4187
  return Datatype::const_iterator(d_solver, *d_dtype, false);
4188
}
4189
4190
1784
DatatypeConstructor Datatype::getConstructorForName(
4191
    const std::string& name) const
4192
{
4193
1784
  bool foundCons = false;
4194
1784
  size_t index = 0;
4195
3347
  for (size_t i = 0, ncons = getNumConstructors(); i < ncons; i++)
4196
  {
4197
3343
    if ((*d_dtype)[i].getName() == name)
4198
    {
4199
1780
      index = i;
4200
1780
      foundCons = true;
4201
1780
      break;
4202
    }
4203
  }
4204
1784
  if (!foundCons)
4205
  {
4206
8
    std::stringstream snames;
4207
4
    snames << "{ ";
4208
12
    for (size_t i = 0, ncons = getNumConstructors(); i < ncons; i++)
4209
    {
4210
8
      snames << (*d_dtype)[i].getName() << " ";
4211
    }
4212
4
    snames << "}";
4213
20
    CVC5_API_CHECK(foundCons) << "No constructor " << name << " for datatype "
4214
16
                              << getName() << " exists, among " << snames.str();
4215
  }
4216
1780
  return DatatypeConstructor(d_solver, (*d_dtype)[index]);
4217
}
4218
4219
35
DatatypeSelector Datatype::getSelectorForName(const std::string& name) const
4220
{
4221
35
  bool foundSel = false;
4222
35
  size_t index = 0;
4223
35
  size_t sindex = 0;
4224
39
  for (size_t i = 0, ncons = getNumConstructors(); i < ncons; i++)
4225
  {
4226
37
    int si = (*d_dtype)[i].getSelectorIndexForName(name);
4227
37
    if (si >= 0)
4228
    {
4229
33
      sindex = static_cast<size_t>(si);
4230
33
      index = i;
4231
33
      foundSel = true;
4232
33
      break;
4233
    }
4234
  }
4235
35
  if (!foundSel)
4236
  {
4237
8
    CVC5_API_CHECK(foundSel)
4238
6
        << "No select " << name << " for datatype " << getName() << " exists";
4239
  }
4240
33
  return DatatypeSelector(d_solver, (*d_dtype)[index][sindex]);
4241
}
4242
4243
Datatype::const_iterator::const_iterator(const Solver* slv,
4244
                                         const cvc5::DType& dtype,
4245
                                         bool begin)
4246
    : d_solver(slv), d_int_ctors(&dtype.getConstructors())
4247
{
4248
  const std::vector<std::shared_ptr<DTypeConstructor>>& cons =
4249
      dtype.getConstructors();
4250
  for (const std::shared_ptr<DTypeConstructor>& c : cons)
4251
  {
4252
    /* Can not use emplace_back here since constructor is private. */
4253
    d_ctors.push_back(DatatypeConstructor(d_solver, *c.get()));
4254
  }
4255
  d_idx = begin ? 0 : cons.size();
4256
}
4257
4258
Datatype::const_iterator::const_iterator()
4259
    : d_solver(nullptr), d_int_ctors(nullptr), d_idx(0)
4260
{
4261
}
4262
4263
Datatype::const_iterator& Datatype::const_iterator::operator=(
4264
    const Datatype::const_iterator& it)
4265
{
4266
  d_solver = it.d_solver;
4267
  d_int_ctors = it.d_int_ctors;
4268
  d_ctors = it.d_ctors;
4269
  d_idx = it.d_idx;
4270
  return *this;
4271
}
4272
4273
const DatatypeConstructor& Datatype::const_iterator::operator*() const
4274
{
4275
  return d_ctors[d_idx];
4276
}
4277
4278
const DatatypeConstructor* Datatype::const_iterator::operator->() const
4279
{
4280
  return &d_ctors[d_idx];
4281
}
4282
4283
Datatype::const_iterator& Datatype::const_iterator::operator++()
4284
{
4285
  ++d_idx;
4286
  return *this;
4287
}
4288
4289
Datatype::const_iterator Datatype::const_iterator::operator++(int)
4290
{
4291
  Datatype::const_iterator it(*this);
4292
  ++d_idx;
4293
  return it;
4294
}
4295
4296
bool Datatype::const_iterator::operator==(
4297
    const Datatype::const_iterator& other) const
4298
{
4299
  return d_int_ctors == other.d_int_ctors && d_idx == other.d_idx;
4300
}
4301
4302
bool Datatype::const_iterator::operator!=(
4303
    const Datatype::const_iterator& other) const
4304
{
4305
  return d_int_ctors != other.d_int_ctors || d_idx != other.d_idx;
4306
}
4307
4308
19406
bool Datatype::isNullHelper() const { return d_dtype == nullptr; }
4309
4310
/* -------------------------------------------------------------------------- */
4311
/* Grammar                                                                    */
4312
/* -------------------------------------------------------------------------- */
4313
4314
Grammar::Grammar()
4315
    : d_solver(nullptr),
4316
      d_sygusVars(),
4317
      d_ntSyms(),
4318
      d_ntsToTerms(0),
4319
      d_allowConst(),
4320
      d_allowVars(),
4321
      d_isResolved(false)
4322
{
4323
}
4324
4325
315
Grammar::Grammar(const Solver* slv,
4326
                 const std::vector<Term>& sygusVars,
4327
315
                 const std::vector<Term>& ntSymbols)
4328
    : d_solver(slv),
4329
      d_sygusVars(sygusVars),
4330
      d_ntSyms(ntSymbols),
4331
      d_ntsToTerms(ntSymbols.size()),
4332
      d_allowConst(),
4333
      d_allowVars(),
4334
315
      d_isResolved(false)
4335
{
4336
986
  for (Term ntsymbol : d_ntSyms)
4337
  {
4338
671
    d_ntsToTerms.emplace(ntsymbol, std::vector<Term>());
4339
  }
4340
315
}
4341
4342
2744
void Grammar::addRule(const Term& ntSymbol, const Term& rule)
4343
{
4344
  CVC5_API_TRY_CATCH_BEGIN;
4345
2746
  CVC5_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
4346
2
                                   "it as an argument to synthFun/synthInv";
4347
2742
  CVC5_API_CHECK_TERM(ntSymbol);
4348
2740
  CVC5_API_CHECK_TERM(rule);
4349
2740
  CVC5_API_ARG_CHECK_EXPECTED(
4350
      d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
4351
      << "ntSymbol to be one of the non-terminal symbols given in the "
4352
2
         "predeclaration";
4353
2738
  CVC5_API_CHECK(ntSymbol.d_node->getType() == rule.d_node->getType())
4354
2
      << "Expected ntSymbol and rule to have the same sort";
4355
2736
  CVC5_API_ARG_CHECK_EXPECTED(!containsFreeVariables(rule), rule)
4356
      << "a term whose free variables are limited to synthFun/synthInv "
4357
2
         "parameters and non-terminal symbols of the grammar";
4358
  //////// all checks before this line
4359
2732
  d_ntsToTerms[ntSymbol].push_back(rule);
4360
  ////////
4361
  CVC5_API_TRY_CATCH_END;
4362
2732
}
4363
4364
14
void Grammar::addRules(const Term& ntSymbol, const std::vector<Term>& rules)
4365
{
4366
  CVC5_API_TRY_CATCH_BEGIN;
4367
16
  CVC5_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
4368
2
                                   "it as an argument to synthFun/synthInv";
4369
12
  CVC5_API_CHECK_TERM(ntSymbol);
4370
10
  CVC5_API_CHECK_TERMS_WITH_SORT(rules, ntSymbol.getSort());
4371
8
  CVC5_API_ARG_CHECK_EXPECTED(
4372
      d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
4373
      << "ntSymbol to be one of the non-terminal symbols given in the "
4374
2
         "predeclaration";
4375
6
  for (size_t i = 0, n = rules.size(); i < n; ++i)
4376
  {
4377
8
    CVC5_API_ARG_AT_INDEX_CHECK_EXPECTED(
4378
        !containsFreeVariables(rules[i]), rules[i], rules, i)
4379
        << "a term whose free variables are limited to synthFun/synthInv "
4380
4
           "parameters and non-terminal symbols of the grammar";
4381
  }
4382
  //////// all checks before this line
4383
4
  d_ntsToTerms[ntSymbol].insert(
4384
2
      d_ntsToTerms[ntSymbol].cend(), rules.cbegin(), rules.cend());
4385
  ////////
4386
  CVC5_API_TRY_CATCH_END;
4387
2
}
4388
4389
40
void Grammar::addAnyConstant(const Term& ntSymbol)
4390
{
4391
  CVC5_API_TRY_CATCH_BEGIN;
4392
42
  CVC5_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
4393
2
                                   "it as an argument to synthFun/synthInv";
4394
38
  CVC5_API_CHECK_TERM(ntSymbol);
4395
38
  CVC5_API_ARG_CHECK_EXPECTED(
4396
      d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
4397
      << "ntSymbol to be one of the non-terminal symbols given in the "
4398
2
         "predeclaration";
4399
  //////// all checks before this line
4400
34
  d_allowConst.insert(ntSymbol);
4401
  ////////
4402
  CVC5_API_TRY_CATCH_END;
4403
34
}
4404
4405
32
void Grammar::addAnyVariable(const Term& ntSymbol)
4406
{
4407
  CVC5_API_TRY_CATCH_BEGIN;
4408
34
  CVC5_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
4409
2
                                   "it as an argument to synthFun/synthInv";
4410
30
  CVC5_API_CHECK_TERM(ntSymbol);
4411
30
  CVC5_API_ARG_CHECK_EXPECTED(
4412
      d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
4413
      << "ntSymbol to be one of the non-terminal symbols given in the "
4414
2
         "predeclaration";
4415
  //////// all checks before this line
4416
26
  d_allowVars.insert(ntSymbol);
4417
  ////////
4418
  CVC5_API_TRY_CATCH_END;
4419
26
}
4420
4421
/**
4422
 * This function concatenates the outputs of calling f on each element between
4423
 * first and last, seperated by sep.
4424
 * @param first the beginning of the range
4425
 * @param last the end of the range
4426
 * @param f the function to call on each element in the range, its output must
4427
 *          be overloaded for operator<<
4428
 * @param sep the string to add between successive calls to f
4429
 */
4430
template <typename Iterator, typename Function>
4431
std::string join(Iterator first, Iterator last, Function f, std::string sep)
4432
{
4433
  std::stringstream ss;
4434
  Iterator i = first;
4435
4436
  if (i != last)
4437
  {
4438
    ss << f(*i);
4439
    ++i;
4440
  }
4441
4442
  while (i != last)
4443
  {
4444
    ss << sep << f(*i);
4445
    ++i;
4446
  }
4447
4448
  return ss.str();
4449
}
4450
4451
std::string Grammar::toString() const
4452
{
4453
  CVC5_API_TRY_CATCH_BEGIN;
4454
  //////// all checks before this line
4455
  std::stringstream ss;
4456
  ss << "  ("  // pre-declaration
4457
     << join(
4458
            d_ntSyms.cbegin(),
4459
            d_ntSyms.cend(),
4460
            [](const Term& t) {
4461
              std::stringstream s;
4462
              s << '(' << t << ' ' << t.getSort() << ')';
4463
              return s.str();
4464
            },
4465
            " ")
4466
     << ")\n  ("  // grouped rule listing
4467
     << join(
4468
            d_ntSyms.cbegin(),
4469
            d_ntSyms.cend(),
4470
            [this](const Term& t) {
4471
              bool allowConst = d_allowConst.find(t) != d_allowConst.cend(),
4472
                   allowVars = d_allowVars.find(t) != d_allowVars.cend();
4473
              const std::vector<Term>& rules = d_ntsToTerms.at(t);
4474
              std::stringstream s;
4475
              s << '(' << t << ' ' << t.getSort() << " ("
4476
                << (allowConst ? "(Constant " + t.getSort().toString() + ")"
4477
                               : "")
4478
                << (allowConst && allowVars ? " " : "")
4479
                << (allowVars ? "(Var " + t.getSort().toString() + ")" : "")
4480
                << ((allowConst || allowVars) && !rules.empty() ? " " : "")
4481
                << join(
4482
                       rules.cbegin(),
4483
                       rules.cend(),
4484
                       [](const Term& rule) { return rule.toString(); },
4485
                       " ")
4486
                << "))";
4487
              return s.str();
4488
            },
4489
            "\n   ")
4490
     << ')';
4491
4492
  return ss.str();
4493
  ////////
4494
  CVC5_API_TRY_CATCH_END;
4495
}
4496
4497
302
Sort Grammar::resolve()
4498
{
4499
  CVC5_API_TRY_CATCH_BEGIN;
4500
  //////// all checks before this line
4501
4502
302
  d_isResolved = true;
4503
4504
604
  Term bvl;
4505
4506
302
  if (!d_sygusVars.empty())
4507
  {
4508
259
    bvl = Term(
4509
        d_solver,
4510
777
        d_solver->getNodeManager()->mkNode(
4511
518
            cvc5::kind::BOUND_VAR_LIST, Term::termVectorToNodes(d_sygusVars)));
4512
  }
4513
4514
604
  std::unordered_map<Term, Sort> ntsToUnres(d_ntSyms.size());
4515
4516
956
  for (Term ntsymbol : d_ntSyms)
4517
  {
4518
    // make the unresolved type, used for referencing the final version of
4519
    // the ntsymbol's datatype
4520
654
    ntsToUnres[ntsymbol] =
4521
1308
        Sort(d_solver, d_solver->getNodeManager()->mkSort(ntsymbol.toString()));
4522
  }
4523
4524
604
  std::vector<cvc5::DType> datatypes;
4525
604
  std::set<TypeNode> unresTypes;
4526
4527
302
  datatypes.reserve(d_ntSyms.size());
4528
4529
956
  for (const Term& ntSym : d_ntSyms)
4530
  {
4531
    // make the datatype, which encodes terms generated by this non-terminal
4532
1308
    DatatypeDecl dtDecl(d_solver, ntSym.toString());
4533
4534
3379
    for (const Term& consTerm : d_ntsToTerms[ntSym])
4535
    {
4536
2725
      addSygusConstructorTerm(dtDecl, consTerm, ntsToUnres);
4537
    }
4538
4539
654
    if (d_allowVars.find(ntSym) != d_allowVars.cend())
4540
    {
4541
22
      addSygusConstructorVariables(dtDecl,
4542
44
                                   Sort(d_solver, ntSym.d_node->getType()));
4543
    }
4544
4545
654
    bool aci = d_allowConst.find(ntSym) != d_allowConst.end();
4546
1308
    TypeNode btt = ntSym.d_node->getType();
4547
654
    dtDecl.d_dtype->setSygus(btt, *bvl.d_node, aci, false);
4548
4549
    // We can be in a case where the only rule specified was (Variable T)
4550
    // and there are no variables of type T, in which case this is a bogus
4551
    // grammar. This results in the error below.
4552
654
    CVC5_API_CHECK(dtDecl.d_dtype->getNumConstructors() != 0)
4553
        << "Grouped rule listing for " << *dtDecl.d_dtype
4554
        << " produced an empty rule list";
4555
4556
654
    datatypes.push_back(*dtDecl.d_dtype);
4557
654
    unresTypes.insert(*ntsToUnres[ntSym].d_type);
4558
  }
4559
4560
  std::vector<TypeNode> datatypeTypes =
4561
302
      d_solver->getNodeManager()->mkMutualDatatypeTypes(
4562
604
          datatypes, unresTypes, NodeManager::DATATYPE_FLAG_PLACEHOLDER);
4563
4564
  // return is the first datatype
4565
604
  return Sort(d_solver, datatypeTypes[0]);
4566
  ////////
4567
  CVC5_API_TRY_CATCH_END;
4568
}
4569
4570
2725
void Grammar::addSygusConstructorTerm(
4571
    DatatypeDecl& dt,
4572
    const Term& term,
4573
    const std::unordered_map<Term, Sort>& ntsToUnres) const
4574
{
4575
  CVC5_API_TRY_CATCH_BEGIN;
4576
2725
  CVC5_API_CHECK_DTDECL(dt);
4577
2725
  CVC5_API_CHECK_TERM(term);
4578
2725
  CVC5_API_CHECK_TERMS_MAP(ntsToUnres);
4579
  //////// all checks before this line
4580
4581
  // At this point, we should know that dt is well founded, and that its
4582
  // builtin sygus operators are well-typed.
4583
  // Now, purify each occurrence of a non-terminal symbol in term, replace by
4584
  // free variables. These become arguments to constructors. Notice we must do
4585
  // a tree traversal in this function, since unique paths to the same term
4586
  // should be treated as distinct terms.
4587
  // Notice that let expressions are forbidden in the input syntax of term, so
4588
  // this does not lead to exponential behavior with respect to input size.
4589
5450
  std::vector<Term> args;
4590
5450
  std::vector<Sort> cargs;
4591
5450
  Term op = purifySygusGTerm(term, args, cargs, ntsToUnres);
4592
5450
  std::stringstream ssCName;
4593
2725
  ssCName << op.getKind();
4594
2725
  if (!args.empty())
4595
  {
4596
    Term lbvl =
4597
1493
        Term(d_solver,
4598
4479
             d_solver->getNodeManager()->mkNode(cvc5::kind::BOUND_VAR_LIST,
4599
5972
                                                Term::termVectorToNodes(args)));
4600
    // its operator is a lambda
4601
1493
    op = Term(d_solver,
4602
5972
              d_solver->getNodeManager()->mkNode(
4603
2986
                  cvc5::kind::LAMBDA, *lbvl.d_node, *op.d_node));
4604
  }
4605
5450
  std::vector<TypeNode> cargst = Sort::sortVectorToTypeNodes(cargs);
4606
2725
  dt.d_dtype->addSygusConstructor(*op.d_node, ssCName.str(), cargst);
4607
  ////////
4608
  CVC5_API_TRY_CATCH_END;
4609
2725
}
4610
4611
5726
Term Grammar::purifySygusGTerm(
4612
    const Term& term,
4613
    std::vector<Term>& args,
4614
    std::vector<Sort>& cargs,
4615
    const std::unordered_map<Term, Sort>& ntsToUnres) const
4616
{
4617
  CVC5_API_TRY_CATCH_BEGIN;
4618
5726
  CVC5_API_CHECK_TERM(term);
4619
5726
  CVC5_API_CHECK_TERMS(args);
4620
5726
  CVC5_API_CHECK_SORTS(cargs);
4621
5726
  CVC5_API_CHECK_TERMS_MAP(ntsToUnres);
4622
  //////// all checks before this line
4623
4624
5726
  std::unordered_map<Term, Sort>::const_iterator itn = ntsToUnres.find(term);
4625
5726
  if (itn != ntsToUnres.cend())
4626
  {
4627
    Term ret =
4628
2853
        Term(d_solver,
4629
8559
             d_solver->getNodeManager()->mkBoundVar(term.d_node->getType()));
4630
2853
    args.push_back(ret);
4631
2853
    cargs.push_back(itn->second);
4632
2853
    return ret;
4633
  }
4634
5746
  std::vector<Term> pchildren;
4635
2873
  bool childChanged = false;
4636
5874
  for (unsigned i = 0, nchild = term.d_node->getNumChildren(); i < nchild; i++)
4637
  {
4638
    Term ptermc = purifySygusGTerm(
4639
6002
        Term(d_solver, (*term.d_node)[i]), args, cargs, ntsToUnres);
4640
3001
    pchildren.push_back(ptermc);
4641
3001
    childChanged = childChanged || *ptermc.d_node != (*term.d_node)[i];
4642
  }
4643
2873
  if (!childChanged)
4644
  {
4645
1390
    return term;
4646
  }
4647
4648
2966
  Node nret;
4649
4650
1483
  if (term.d_node->getMetaKind() == kind::metakind::PARAMETERIZED)
4651
  {
4652
    // it's an indexed operator so we should provide the op
4653
416
    NodeBuilder nb(term.d_node->getKind());
4654
208
    nb << term.d_node->getOperator();
4655
208
    nb.append(Term::termVectorToNodes(pchildren));
4656
208
    nret = nb.constructNode();
4657
  }
4658
  else
4659
  {
4660
2550
    nret = d_solver->getNodeManager()->mkNode(
4661
2550
        term.d_node->getKind(), Term::termVectorToNodes(pchildren));
4662
  }
4663
4664
1483
  return Term(d_solver, nret);
4665
  ////////
4666
  CVC5_API_TRY_CATCH_END;
4667
}
4668
4669
22
void Grammar::addSygusConstructorVariables(DatatypeDecl& dt,
4670
                                           const Sort& sort) const
4671
{
4672
  CVC5_API_TRY_CATCH_BEGIN;
4673
22
  CVC5_API_CHECK_DTDECL(dt);
4674
22
  CVC5_API_CHECK_SORT(sort);
4675
  //////// all checks before this line
4676
4677
  // each variable of appropriate type becomes a sygus constructor in dt.
4678
102
  for (unsigned i = 0, size = d_sygusVars.size(); i < size; i++)
4679
  {
4680
160
    Term v = d_sygusVars[i];
4681
80
    if (v.d_node->getType() == *sort.d_type)
4682
    {
4683
128
      std::stringstream ss;
4684
64
      ss << v;
4685
128
      std::vector<TypeNode> cargs;
4686
64
      dt.d_dtype->addSygusConstructor(*v.d_node, ss.str(), cargs);
4687
    }
4688
  }
4689
  ////////
4690
  CVC5_API_TRY_CATCH_END;
4691
22
}
4692
4693
2738
bool Grammar::containsFreeVariables(const Term& rule) const
4694
{
4695
5476
  std::unordered_set<TNode> scope;
4696
4697
8533
  for (const Term& sygusVar : d_sygusVars)
4698
  {
4699
5795
    scope.emplace(*sygusVar.d_node);
4700
  }
4701
4702
13472
  for (const Term& ntsymbol : d_ntSyms)
4703
  {
4704
10734
    scope.emplace(*ntsymbol.d_node);
4705
  }
4706
4707
5476
  std::unordered_set<Node> fvs;
4708
5476
  return expr::getFreeVariablesScope(*rule.d_node, fvs, scope, false);
4709
}
4710
4711
std::ostream& operator<<(std::ostream& out, const Grammar& grammar)
4712
{
4713
  return out << grammar.toString();
4714
}
4715
4716
/* -------------------------------------------------------------------------- */
4717
/* Rounding Mode for Floating Points                                          */
4718
/* -------------------------------------------------------------------------- */
4719
4720
10379
const static std::unordered_map<RoundingMode, cvc5::RoundingMode> s_rmodes{
4721
    {ROUND_NEAREST_TIES_TO_EVEN,
4722
     cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_EVEN},
4723
    {ROUND_TOWARD_POSITIVE, cvc5::RoundingMode::ROUND_TOWARD_POSITIVE},
4724
    {ROUND_TOWARD_NEGATIVE, cvc5::RoundingMode::ROUND_TOWARD_NEGATIVE},
4725
    {ROUND_TOWARD_ZERO, cvc5::RoundingMode::ROUND_TOWARD_ZERO},
4726
    {ROUND_NEAREST_TIES_TO_AWAY,
4727
     cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_AWAY},
4728
};
4729
4730
const static std::unordered_map<cvc5::RoundingMode,
4731
                                RoundingMode,
4732
                                cvc5::RoundingModeHashFunction>
4733
10379
    s_rmodes_internal{
4734
        {cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_EVEN,
4735
         ROUND_NEAREST_TIES_TO_EVEN},
4736
        {cvc5::RoundingMode::ROUND_TOWARD_POSITIVE, ROUND_TOWARD_POSITIVE},
4737
        {cvc5::RoundingMode::ROUND_TOWARD_POSITIVE, ROUND_TOWARD_NEGATIVE},
4738
        {cvc5::RoundingMode::ROUND_TOWARD_ZERO, ROUND_TOWARD_ZERO},
4739
        {cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_AWAY,
4740
         ROUND_NEAREST_TIES_TO_AWAY},
4741
    };
4742
4743
/* -------------------------------------------------------------------------- */
4744
/* Options                                                                    */
4745
/* -------------------------------------------------------------------------- */
4746
4747
271452
DriverOptions::DriverOptions(const Solver& solver) : d_solver(solver) {}
4748
4749
std::istream& DriverOptions::in() const
4750
{
4751
  return *d_solver.d_slv->getOptions().base.in;
4752
}
4753
13126
std::ostream& DriverOptions::err() const
4754
{
4755
13126
  return *d_solver.d_slv->getOptions().base.err;
4756
}
4757
249016
std::ostream& DriverOptions::out() const
4758
{
4759
249016
  return *d_solver.d_slv->getOptions().base.out;
4760
}
4761
4762
/* -------------------------------------------------------------------------- */
4763
/* Statistics                                                                 */
4764
/* -------------------------------------------------------------------------- */
4765
4766
struct Stat::StatData
4767
{
4768
  cvc5::StatExportData data;
4769
  template <typename T>
4770
  StatData(T&& t) : data(std::forward<T>(t))
4771
  {
4772
  }
4773
  StatData() : data() {}
4774
};
4775
4776
Stat::~Stat() {}
4777
Stat::Stat(const Stat& s)
4778
    : d_expert(s.d_expert),
4779
      d_default(s.d_default),
4780
      d_data(std::make_unique<StatData>(s.d_data->data))
4781
{
4782
}
4783
Stat& Stat::operator=(const Stat& s)
4784
{
4785
  d_expert = s.d_expert;
4786
  d_data = std::make_unique<StatData>(s.d_data->data);
4787
  return *this;
4788
}
4789
4790
bool Stat::isExpert() const { return d_expert; }
4791
bool Stat::isDefault() const { return d_default; }
4792
4793
bool Stat::isInt() const
4794
{
4795
  return std::holds_alternative<int64_t>(d_data->data);
4796
}
4797
int64_t Stat::getInt() const
4798
{
4799
  CVC5_API_TRY_CATCH_BEGIN;
4800
  CVC5_API_RECOVERABLE_CHECK(isInt()) << "Expected Stat of type int64_t.";
4801
  return std::get<int64_t>(d_data->data);
4802
  CVC5_API_TRY_CATCH_END;
4803
}
4804
bool Stat::isDouble() const
4805
{
4806
  return std::holds_alternative<double>(d_data->data);
4807
}
4808
double Stat::getDouble() const
4809
{
4810
  CVC5_API_TRY_CATCH_BEGIN;
4811
  CVC5_API_RECOVERABLE_CHECK(isDouble()) << "Expected Stat of type double.";
4812
  return std::get<double>(d_data->data);
4813
  CVC5_API_TRY_CATCH_END;
4814
}
4815
bool Stat::isString() const
4816
{
4817
  return std::holds_alternative<std::string>(d_data->data);
4818
}
4819
const std::string& Stat::getString() const
4820
{
4821
  CVC5_API_TRY_CATCH_BEGIN;
4822
  CVC5_API_RECOVERABLE_CHECK(isString())
4823
      << "Expected Stat of type std::string.";
4824
  return std::get<std::string>(d_data->data);
4825
  CVC5_API_TRY_CATCH_END;
4826
}
4827
bool Stat::isHistogram() const
4828
{
4829
  return std::holds_alternative<HistogramData>(d_data->data);
4830
}
4831
const Stat::HistogramData& Stat::getHistogram() const
4832
{
4833
  CVC5_API_TRY_CATCH_BEGIN;
4834
  CVC5_API_RECOVERABLE_CHECK(isHistogram())
4835
      << "Expected Stat of type histogram.";
4836
  return std::get<HistogramData>(d_data->data);
4837
  CVC5_API_TRY_CATCH_END;
4838
}
4839
4840
Stat::Stat(bool expert, bool defaulted, StatData&& sd)
4841
    : d_expert(expert),
4842
      d_default(defaulted),
4843
      d_data(std::make_unique<StatData>(std::move(sd)))
4844
{
4845
}
4846
4847
std::ostream& operator<<(std::ostream& os, const Stat& sv)
4848
{
4849
  return cvc5::detail::print(os, sv.d_data->data);
4850
}
4851
4852
Statistics::BaseType::const_reference Statistics::iterator::operator*() const
4853
{
4854
  return d_it.operator*();
4855
}
4856
Statistics::BaseType::const_pointer Statistics::iterator::operator->() const
4857
{
4858
  return d_it.operator->();
4859
}
4860
Statistics::iterator& Statistics::iterator::operator++()
4861
{
4862
  do
4863
  {
4864
    ++d_it;
4865
  } while (!isVisible());
4866
  return *this;
4867
}
4868
Statistics::iterator Statistics::iterator::operator++(int)
4869
{
4870
  iterator tmp = *this;
4871
  do
4872
  {
4873
    ++d_it;
4874
  } while (!isVisible());
4875
  return tmp;
4876
}
4877
Statistics::iterator& Statistics::iterator::operator--()
4878
{
4879
  do
4880
  {
4881
    --d_it;
4882
  } while (!isVisible());
4883
  return *this;
4884
}
4885
Statistics::iterator Statistics::iterator::operator--(int)
4886
{
4887
  iterator tmp = *this;
4888
  do
4889
  {
4890
    --d_it;
4891
  } while (!isVisible());
4892
  return tmp;
4893
}
4894
bool Statistics::iterator::operator==(const Statistics::iterator& rhs) const
4895
{
4896
  return d_it == rhs.d_it;
4897
}
4898
bool Statistics::iterator::operator!=(const Statistics::iterator& rhs) const
4899
{
4900
  return d_it != rhs.d_it;
4901
}
4902
Statistics::iterator::iterator(Statistics::BaseType::const_iterator it,
4903
                               const Statistics::BaseType& base,
4904
                               bool expert,
4905
                               bool defaulted)
4906
    : d_it(it), d_base(&base), d_showExpert(expert), d_showDefault(defaulted)
4907
{
4908
  while (!isVisible())
4909
  {
4910
    ++d_it;
4911
  }
4912
}
4913
bool Statistics::iterator::isVisible() const
4914
{
4915
  if (d_it == d_base->end()) return true;
4916
  if (!d_showExpert && d_it->second.isExpert()) return false;
4917
  if (!d_showDefault && d_it->second.isDefault()) return false;
4918
  return true;
4919
}
4920
4921
const Stat& Statistics::get(const std::string& name)
4922
{
4923
  CVC5_API_TRY_CATCH_BEGIN;
4924
  auto it = d_stats.find(name);
4925
  CVC5_API_RECOVERABLE_CHECK(it != d_stats.end())
4926
      << "No stat with name \"" << name << "\" exists.";
4927
  return it->second;
4928
  CVC5_API_TRY_CATCH_END;
4929
}
4930
4931
Statistics::iterator Statistics::begin(bool expert, bool defaulted) const
4932
{
4933
  return iterator(d_stats.begin(), d_stats, expert, defaulted);
4934
}
4935
Statistics::iterator Statistics::end() const
4936
{
4937
  return iterator(d_stats.end(), d_stats, false, false);
4938
}
4939
4940
Statistics::Statistics(const StatisticsRegistry& reg)
4941
{
4942
  for (const auto& svp : reg)
4943
  {
4944
    d_stats.emplace(svp.first,
4945
                    Stat(svp.second->d_expert,
4946
                         svp.second->isDefault(),
4947
                         svp.second->getViewer()));
4948
  }
4949
}
4950
4951
std::ostream& operator<<(std::ostream& out, const Statistics& stats)
4952
{
4953
  for (const auto& stat : stats)
4954
  {
4955
    out << stat.first << " = " << stat.second << std::endl;
4956
  }
4957
  return out;
4958
}
4959
4960
/* -------------------------------------------------------------------------- */
4961
/* Solver                                                                     */
4962
/* -------------------------------------------------------------------------- */
4963
4964
10071
Solver::Solver(std::unique_ptr<Options>&& original)
4965
{
4966
10071
  d_nodeMgr = NodeManager::currentNM();
4967
10071
  d_nodeMgr->init();
4968
10071
  d_originalOptions = std::move(original);
4969
10071
  d_slv.reset(new SolverEngine(d_nodeMgr, d_originalOptions.get()));
4970
10071
  d_slv->setSolver(this);
4971
10071
  d_rng.reset(new Random(d_slv->getOptions().driver.seed));
4972
10071
  resetStatistics();
4973
10071
}
4974
4975
10028
Solver::Solver() : Solver(std::make_unique<Options>()) {}
4976
4977
7322
Solver::~Solver() {}
4978
4979
/* Helpers and private functions                                              */
4980
/* -------------------------------------------------------------------------- */
4981
4982
1292440
NodeManager* Solver::getNodeManager(void) const { return d_nodeMgr; }
4983
4984
2453761
void Solver::increment_term_stats(Kind kind) const
4985
{
4986
  if constexpr (Configuration::isStatisticsBuild())
4987
  {
4988
2453761
    d_stats->d_terms << kind;
4989
  }
4990
2453761
}
4991
4992
175235
void Solver::increment_vars_consts_stats(const Sort& sort, bool is_var) const
4993
{
4994
  if constexpr (Configuration::isStatisticsBuild())
4995
  {
4996
350470
    const TypeNode tn = sort.getTypeNode();
4997
175235
    TypeConstant tc = tn.getKind() == cvc5::kind::TYPE_CONSTANT
4998
175235
                          ? tn.getConst<TypeConstant>()
4999
175235
                          : LAST_TYPE;
5000
175235
    if (is_var)
5001
    {
5002
60775
      d_stats->d_vars << tc;
5003
    }
5004
    else
5005
    {
5006
114460
      d_stats->d_consts << tc;
5007
    }
5008
  }
5009
175235
}
5010
5011
/* Split out to avoid nested API calls (problematic with API tracing).        */
5012
/* .......................................................................... */
5013
5014
template <typename T>
5015
616316
Term Solver::mkValHelper(T t) const
5016
{
5017
  //////// all checks before this line
5018
1232632
  Node res = getNodeManager()->mkConst(t);
5019
616316
  (void)res.getType(true); /* kick off type checking */
5020
1232626
  return Term(this, res);
5021
}
5022
5023
393162
Term Solver::mkRealFromStrHelper(const std::string& s) const
5024
{
5025
  //////// all checks before this line
5026
  try
5027
  {
5028
393162
    cvc5::Rational r = s.find('/') != std::string::npos
5029
                           ? cvc5::Rational(s)
5030
786300
                           : cvc5::Rational::fromDecimal(s);
5031
786276
    return mkValHelper<cvc5::Rational>(r);
5032
  }
5033
48
  catch (const std::invalid_argument& e)
5034
  {
5035
    /* Catch to throw with a more meaningful error message. To be caught in
5036
     * enclosing CVC5_API_TRY_CATCH_* block to throw CVC5ApiException. */
5037
48
    std::stringstream message;
5038
24
    message << "Cannot construct Real or Int from string argument '" << s << "'"
5039
24
            << std::endl;
5040
24
    throw std::invalid_argument(message.str());
5041
  }
5042
}
5043
5044
16
Term Solver::mkBVFromIntHelper(uint32_t size, uint64_t val) const
5045
{
5046
16
  CVC5_API_ARG_CHECK_EXPECTED(size > 0, size) << "a bit-width > 0";
5047
  //////// all checks before this line
5048
14
  return mkValHelper<cvc5::BitVector>(cvc5::BitVector(size, val));
5049
}
5050
5051
95459
Term Solver::mkBVFromStrHelper(uint32_t size,
5052
                               const std::string& s,
5053
                               uint32_t base) const
5054
{
5055
95459
  CVC5_API_ARG_CHECK_EXPECTED(!s.empty(), s) << "a non-empty string";
5056
95463
  CVC5_API_ARG_CHECK_EXPECTED(base == 2 || base == 10 || base == 16, base)
5057
6
      << "base 2, 10, or 16";
5058
  //////// all checks before this line
5059
5060
190894
  Integer val(s, base);
5061
5062
95443
  if (val.strictlyNegative())
5063
  {
5064
28
    CVC5_API_CHECK(val >= -Integer("2", 10).pow(size - 1))
5065
6
        << "Overflow in bitvector construction (specified bitvector size "
5066
6
        << size << " too small to hold value " << s << ")";
5067
  }
5068
  else
5069
  {
5070
95429
    CVC5_API_CHECK(val.modByPow2(size) == val)
5071
8
        << "Overflow in bitvector construction (specified bitvector size "
5072
8
        << size << " too small to hold value " << s << ")";
5073
  }
5074
190858
  return mkValHelper<cvc5::BitVector>(cvc5::BitVector(size, val));
5075
}
5076
5077
121
Term Solver::getValueHelper(const Term& term) const
5078
{
5079
  // Note: Term is checked in the caller to avoid double checks
5080
121
  CVC5_API_RECOVERABLE_CHECK(!expr::hasFreeVar(term.getNode()))
5081
      << "Cannot get value of term containing free variables";
5082
  //////// all checks before this line
5083
242
  Node value = d_slv->getValue(*term.d_node);
5084
242
  Term res = Term(this, value);
5085
  // May need to wrap in real cast so that user know this is a real.
5086
242
  TypeNode tn = (*term.d_node).getType();
5087
121
  if (!tn.isInteger() && value.getType().isInteger())
5088
  {
5089
12
    return ensureRealSort(res);
5090
  }
5091
109
  return res;
5092
}
5093
5094
6501
Sort Solver::mkTupleSortHelper(const std::vector<Sort>& sorts) const
5095
{
5096
  // Note: Sorts are checked in the caller to avoid double checks
5097
  //////// all checks before this line
5098
13002
  std::vector<TypeNode> typeNodes = Sort::sortVectorToTypeNodes(sorts);
5099
13002
  return Sort(this, getNodeManager()->mkTupleType(typeNodes));
5100
}
5101
5102
8
Term Solver::mkTermFromKind(Kind kind) const
5103
{
5104
12
  CVC5_API_KIND_CHECK_EXPECTED(kind == PI || kind == REGEXP_EMPTY
5105
                                   || kind == REGEXP_SIGMA || kind == SEP_EMP,
5106
                               kind)
5107
4
      << "PI, REGEXP_EMPTY, REGEXP_SIGMA or SEP_EMP";
5108
  //////// all checks before this line
5109
12
  Node res;
5110
6
  cvc5::Kind k = extToIntKind(kind);
5111
6
  if (kind == REGEXP_EMPTY || kind == REGEXP_SIGMA)
5112
  {
5113
4
    Assert(isDefinedIntKind(k));
5114
4
    res = d_nodeMgr->mkNode(k, std::vector<Node>());
5115
  }
5116
2
  else if (kind == SEP_EMP)
5117
  {
5118
    res = d_nodeMgr->mkNullaryOperator(d_nodeMgr->booleanType(), k);
5119
  }
5120
  else
5121
  {
5122
2
    Assert(kind == PI);
5123
2
    res = d_nodeMgr->mkNullaryOperator(d_nodeMgr->realType(), k);
5124
  }
5125
6
  (void)res.getType(true); /* kick off type checking */
5126
6
  increment_term_stats(kind);
5127
12
  return Term(this, res);
5128
}
5129
5130
2453779
Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
5131
{
5132
  // Note: Kind and children are checked in the caller to avoid double checks
5133
  //////// all checks before this line
5134
5135
4907558
  std::vector<Node> echildren = Term::termVectorToNodes(children);
5136
2453779
  cvc5::Kind k = extToIntKind(kind);
5137
4907558
  Node res;
5138
2453779
  if (echildren.size() > 2)
5139
  {
5140
505409
    if (kind == INTS_DIVISION || kind == XOR || kind == MINUS
5141
504782
        || kind == DIVISION || kind == HO_APPLY || kind == REGEXP_DIFF)
5142
    {
5143
      // left-associative, but cvc5 internally only supports 2 args
5144
735
      res = d_nodeMgr->mkLeftAssociative(k, echildren);
5145
    }
5146
504674
    else if (kind == IMPLIES)
5147
    {
5148
      // right-associative, but cvc5 internally only supports 2 args
5149
6
      res = d_nodeMgr->mkRightAssociative(k, echildren);
5150
    }
5151
504668
    else if (kind == EQUAL || kind == LT || kind == GT || kind == LEQ
5152
503878
             || kind == GEQ)
5153
    {
5154
      // "chainable", but cvc5 internally only supports 2 args
5155
799
      res = d_nodeMgr->mkChain(k, echildren);
5156
    }
5157
503869
    else if (kind::isAssociative(k))
5158
    {
5159
      // mkAssociative has special treatment for associative operators with lots
5160
      // of children
5161
50644
      res = d_nodeMgr->mkAssociative(k, echildren);
5162
    }
5163
    else
5164
    {
5165
      // default case, must check kind
5166
453225
      checkMkTerm(kind, children.size());
5167
453225
      res = d_nodeMgr->mkNode(k, echildren);
5168
    }
5169
  }
5170
1948370
  else if (kind::isAssociative(k))
5171
  {
5172
    // associative case, same as above
5173
638227
    res = d_nodeMgr->mkAssociative(k, echildren);
5174
  }
5175
  else
5176
  {
5177
    // default case, same as above
5178
1310143
    checkMkTerm(kind, children.size());
5179
1310135
    if (kind == api::SINGLETON)
5180
    {
5181
      // the type of the term is the same as the type of the internal node
5182
      // see Term::getSort()
5183
926
      TypeNode type = children[0].d_node->getType();
5184
      // Internally NodeManager::mkSingleton needs a type argument
5185
      // to construct a singleton, since there is no difference between
5186
      // integers and reals (both are Rationals).
5187
      // At the API, mkReal and mkInteger are different and therefore the
5188
      // element type can be used safely here.
5189
463
      res = getNodeManager()->mkSingleton(type, *children[0].d_node);
5190
    }
5191
1309672
    else if (kind == api::MK_BAG)
5192
    {
5193
      // the type of the term is the same as the type of the internal node
5194
      // see Term::getSort()
5195
134
      TypeNode type = children[0].d_node->getType();
5196
      // Internally NodeManager::mkBag needs a type argument
5197
      // to construct a bag, since there is no difference between
5198
      // integers and reals (both are Rationals).
5199
      // At the API, mkReal and mkInteger are different and therefore the
5200
      // element type can be used safely here.
5201
201
      res = getNodeManager()->mkBag(
5202
134
          type, *children[0].d_node, *children[1].d_node);
5203
    }
5204
    else
5205
    {
5206
1309605
      res = d_nodeMgr->mkNode(k, echildren);
5207
    }
5208
  }
5209
5210
2453755
  (void)res.getType(true); /* kick off type checking */
5211
2453755
  increment_term_stats(kind);
5212
4907510
  return Term(this, res);
5213
}
5214
5215
76647
Term Solver::mkTermHelper(const Op& op, const std::vector<Term>& children) const
5216
{
5217
  // Note: Op and children are checked in the caller to avoid double checks
5218
76647
  checkMkTerm(op.d_kind, children.size());
5219
  //////// all checks before this line
5220
5221
76637
  if (!op.isIndexedHelper())
5222
  {
5223
4
    return mkTermHelper(op.d_kind, children);
5224
  }
5225
5226
76633
  const cvc5::Kind int_kind = extToIntKind(op.d_kind);
5227
153266
  std::vector<Node> echildren = Term::termVectorToNodes(children);
5228
5229
153266
  NodeBuilder nb(int_kind);
5230
76633
  nb << *op.d_node;
5231
76633
  nb.append(echildren);
5232
153259
  Node res = nb.constructNode();
5233
5234
76626
  (void)res.getType(true); /* kick off type checking */
5235
76626
  return Term(this, res);
5236
}
5237
5238
1186
std::vector<Sort> Solver::mkDatatypeSortsInternal(
5239
    const std::vector<DatatypeDecl>& dtypedecls,
5240
    const std::set<Sort>& unresolvedSorts) const
5241
{
5242
  // Note: dtypedecls and unresolvedSorts are checked in the caller to avoid
5243
  //       double checks
5244
  //////// all checks before this line
5245
5246
2372
  std::vector<cvc5::DType> datatypes;
5247
2742
  for (size_t i = 0, ndts = dtypedecls.size(); i < ndts; ++i)
5248
  {
5249
1556
    datatypes.push_back(dtypedecls[i].getDatatype());
5250
  }
5251
5252
2372
  std::set<TypeNode> utypes = Sort::sortSetToTypeNodes(unresolvedSorts);
5253
  std::vector<cvc5::TypeNode> dtypes =
5254
2372
      getNodeManager()->mkMutualDatatypeTypes(datatypes, utypes);
5255
1186
  std::vector<Sort> retTypes = Sort::typeNodeVectorToSorts(this, dtypes);
5256
2372
  return retTypes;
5257
}
5258
5259
711
Term Solver::synthFunHelper(const std::string& symbol,
5260
                            const std::vector<Term>& boundVars,
5261
                            const Sort& sort,
5262
                            bool isInv,
5263
                            Grammar* grammar) const
5264
{
5265
  // Note: boundVars, sort and grammar are checked in the caller to avoid
5266
  //       double checks.
5267
1422
  std::vector<TypeNode> varTypes;
5268
2368
  for (const auto& bv : boundVars)
5269
  {
5270
1661
    if (grammar)
5271
    {
5272
956
      CVC5_API_CHECK(grammar->d_ntSyms[0].d_node->getType() == *sort.d_type)
5273
4
          << "Invalid Start symbol for grammar, Expected Start's sort to be "
5274
4
          << *sort.d_type << " but found "
5275
480
          << grammar->d_ntSyms[0].d_node->getType();
5276
    }
5277
1657
    varTypes.push_back(bv.d_node->getType());
5278
  }
5279
  //////// all checks before this line
5280
5281
767
  TypeNode funType = varTypes.empty() ? *sort.d_type
5282
                                      : getNodeManager()->mkFunctionType(
5283
1474
                                          varTypes, *sort.d_type);
5284
5285
1414
  Node fun = getNodeManager()->mkBoundVar(symbol, funType);
5286
707
  (void)fun.getType(true); /* kick off type checking */
5287
5288
1414
  std::vector<Node> bvns = Term::termVectorToNodes(boundVars);
5289
5290
997
  d_slv->declareSynthFun(
5291
      fun,
5292
997
      grammar == nullptr ? funType : *grammar->resolve().d_type,
5293
      isInv,
5294
      bvns);
5295
5296
1414
  return Term(this, fun);
5297
}
5298
5299
27916
Term Solver::ensureTermSort(const Term& term, const Sort& sort) const
5300
{
5301
  // Note: Term and sort are checked in the caller to avoid double checks
5302
27920
  CVC5_API_CHECK(term.getSort() == sort
5303
                 || (term.getSort().isInteger() && sort.isReal()))
5304
4
      << "Expected conversion from Int to Real";
5305
  //////// all checks before this line
5306
5307
55824
  Sort t = term.getSort();
5308
27912
  if (term.getSort() == sort)
5309
  {
5310
27910
    return term;
5311
  }
5312
5313
  // Integers are reals, too
5314
2
  Assert(t.d_type->isReal());
5315
4
  Term res = term;
5316
2
  if (t.isInteger())
5317
  {
5318
    // Must cast to Real to ensure correct type is passed to parametric type
5319
    // constructors. We do this cast using division with 1. This has the
5320
    // advantage wrt using TO_REAL since (constant) division is always included
5321
    // in the theory.
5322
2
    res = Term(this,
5323
8
               d_nodeMgr->mkNode(extToIntKind(DIVISION),
5324
2
                                 *res.d_node,
5325
4
                                 d_nodeMgr->mkConst(cvc5::Rational(1))));
5326
  }
5327
2
  Assert(res.getSort() == sort);
5328
2
  return res;
5329
}
5330
5331
24524
Term Solver::ensureRealSort(const Term& t) const
5332
{
5333
24524
  Assert(this == t.d_solver);
5334
24524
  CVC5_API_ARG_CHECK_EXPECTED(
5335
      t.getSort() == getIntegerSort() || t.getSort() == getRealSort(),
5336
      " an integer or real term");
5337
  // Note: Term is checked in the caller to avoid double checks
5338
  //////// all checks before this line
5339
24524
  if (t.getSort() == getIntegerSort())
5340
  {
5341
48224
    Node n = getNodeManager()->mkNode(kind::CAST_TO_REAL, *t.d_node);
5342
24112
    return Term(this, n);
5343
  }
5344
412
  return t;
5345
}
5346
5347
368753
bool Solver::isValidInteger(const std::string& s) const
5348
{
5349
  //////// all checks before this line
5350
368753
  if (s.length() == 0)
5351
  {
5352
    // string should not be empty
5353
6
    return false;
5354
  }
5355
5356
368747
  size_t index = 0;
5357
368747
  if (s[index] == '-')
5358
  {
5359
27
    if (s.length() == 1)
5360
    {
5361
      // negative integers should contain at least one digit
5362
2
      return false;
5363
    }
5364
25
    index = 1;
5365
  }
5366
5367
368745
  if (s[index] == '0' && s.length() > (index + 1))
5368
  {
5369
    // From SMT-Lib 2.6: A <numeral> is the digit 0 or a non-empty sequence of
5370
    // digits not starting with 0. So integers like 001, 000 are not allowed
5371
12
    return false;
5372
  }
5373
5374
  // all remaining characters should be decimal digits
5375
1240725
  for (; index < s.length(); ++index)
5376
  {
5377
436042
    if (!std::isdigit(s[index]))
5378
    {
5379
46
      return false;
5380
    }
5381
  }
5382
5383
368687
  return true;
5384
}
5385
5386
10071
void Solver::resetStatistics()
5387
{
5388
  if constexpr (Configuration::isStatisticsBuild())
5389
  {
5390
50355
    d_stats.reset(new APIStatistics{
5391
10071
        d_slv->getStatisticsRegistry().registerHistogram<TypeConstant>(
5392
            "api::CONSTANT"),
5393
10071
        d_slv->getStatisticsRegistry().registerHistogram<TypeConstant>(
5394
            "api::VARIABLE"),
5395
10071
        d_slv->getStatisticsRegistry().registerHistogram<Kind>("api::TERM"),
5396
10071
    });
5397
  }
5398
10071
}
5399
5400
void Solver::printStatisticsSafe(int fd) const
5401
{
5402
  d_slv->printStatisticsSafe(fd);
5403
}
5404
5405
/* Helpers for mkTerm checks.                                                 */
5406
/* .......................................................................... */
5407
5408
1840019
void Solver::checkMkTerm(Kind kind, uint32_t nchildren) const
5409
{
5410
1840019
  CVC5_API_KIND_CHECK(kind);
5411
1840019
  Assert(isDefinedIntKind(extToIntKind(kind)));
5412
1840019
  const cvc5::kind::MetaKind mk = kind::metaKindOf(extToIntKind(kind));
5413
1840019
  CVC5_API_KIND_CHECK_EXPECTED(
5414
      mk == kind::metakind::PARAMETERIZED || mk == kind::metakind::OPERATOR,
5415
      kind)
5416
      << "Only operator-style terms are created with mkTerm(), "
5417
         "to create variables, constants and values see mkVar(), mkConst() "
5418
         "and the respective theory-specific functions to create values, "
5419
         "e.g., mkBitVector().";
5420
3680104
  CVC5_API_KIND_CHECK_EXPECTED(
5421
      nchildren >= minArity(kind) && nchildren <= maxArity(kind), kind)
5422
1840085
      << "Terms with kind " << kindToString(kind) << " must have at least "
5423
22
      << minArity(kind) << " children and at most " << maxArity(kind)
5424
22
      << " children (the one under construction has " << nchildren << ")";
5425
1839997
}
5426
5427
/* Sorts Handling                                                             */
5428
/* -------------------------------------------------------------------------- */
5429
5430
5210
Sort Solver::getNullSort(void) const
5431
{
5432
  CVC5_API_TRY_CATCH_BEGIN;
5433
  //////// all checks before this line
5434
5210
  return Sort(this, TypeNode());
5435
  ////////
5436
  CVC5_API_TRY_CATCH_END;
5437
}
5438
5439
101080
Sort Solver::getBooleanSort(void) const
5440
{
5441
  CVC5_API_TRY_CATCH_BEGIN;
5442
  //////// all checks before this line
5443
101080
  return Sort(this, getNodeManager()->booleanType());
5444
  ////////
5445
  CVC5_API_TRY_CATCH_END;
5446
}
5447
5448
425796
Sort Solver::getIntegerSort(void) const
5449
{
5450
  CVC5_API_TRY_CATCH_BEGIN;
5451
  //////// all checks before this line
5452
425796
  return Sort(this, getNodeManager()->integerType());
5453
  ////////
5454
  CVC5_API_TRY_CATCH_END;
5455
}
5456
5457
28114
Sort Solver::getRealSort(void) const
5458
{
5459
  CVC5_API_TRY_CATCH_BEGIN;
5460
  //////// all checks before this line
5461
28114
  return Sort(this, getNodeManager()->realType());
5462
  ////////
5463
  CVC5_API_TRY_CATCH_END;
5464
}
5465
5466
3049
Sort Solver::getRegExpSort(void) const
5467
{
5468
  CVC5_API_TRY_CATCH_BEGIN;
5469
  //////// all checks before this line
5470
3049
  return Sort(this, getNodeManager()->regExpType());
5471
  ////////
5472
  CVC5_API_TRY_CATCH_END;
5473
}
5474
5475
3056
Sort Solver::getStringSort(void) const
5476
{
5477
  CVC5_API_TRY_CATCH_BEGIN;
5478
  //////// all checks before this line
5479
3056
  return Sort(this, getNodeManager()->stringType());
5480
  ////////
5481
  CVC5_API_TRY_CATCH_END;
5482
}
5483
5484
2625
Sort Solver::getRoundingModeSort(void) const
5485
{
5486
  CVC5_API_TRY_CATCH_BEGIN;
5487
  //////// all checks before this line
5488
2625
  return Sort(this, getNodeManager()->roundingModeType());
5489
  ////////
5490
  CVC5_API_TRY_CATCH_END;
5491
}
5492
5493
/* Create sorts ------------------------------------------------------- */
5494
5495
2360
Sort Solver::mkArraySort(const Sort& indexSort, const Sort& elemSort) const
5496
{
5497
  CVC5_API_TRY_CATCH_BEGIN;
5498
2360
  CVC5_API_SOLVER_CHECK_SORT(indexSort);
5499
2358
  CVC5_API_SOLVER_CHECK_SORT(elemSort);
5500
  //////// all checks before this line
5501
  return Sort(
5502
2358
      this, getNodeManager()->mkArrayType(*indexSort.d_type, *elemSort.d_type));
5503
  ////////
5504
  CVC5_API_TRY_CATCH_END;
5505
}
5506
5507
17090
Sort Solver::mkBitVectorSort(uint32_t size) const
5508
{
5509
  CVC5_API_TRY_CATCH_BEGIN;
5510
17090
  CVC5_API_ARG_CHECK_EXPECTED(size > 0, size) << "size > 0";
5511
  //////// all checks before this line
5512
17088
  return Sort(this, getNodeManager()->mkBitVectorType(size));
5513
  ////////
5514
  CVC5_API_TRY_CATCH_END;
5515
}
5516
5517
10648
Sort Solver::mkFloatingPointSort(uint32_t exp, uint32_t sig) const
5518
{
5519
  CVC5_API_TRY_CATCH_BEGIN;
5520
10648
  CVC5_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "exponent size > 0";
5521
10646
  CVC5_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "significand size > 0";
5522
  //////// all checks before this line
5523
10644
  return Sort(this, getNodeManager()->mkFloatingPointType(exp, sig));
5524
  ////////
5525
  CVC5_API_TRY_CATCH_END;
5526
}
5527
5528
60
Sort Solver::mkDatatypeSort(const DatatypeDecl& dtypedecl) const
5529
{
5530
  CVC5_API_TRY_CATCH_BEGIN;
5531
60
  CVC5_API_SOLVER_CHECK_DTDECL(dtypedecl);
5532
  //////// all checks before this line
5533
56
  return Sort(this, getNodeManager()->mkDatatypeType(*dtypedecl.d_dtype));
5534
  ////////
5535
  CVC5_API_TRY_CATCH_END;
5536
}
5537
5538
8
std::vector<Sort> Solver::mkDatatypeSorts(
5539
    const std::vector<DatatypeDecl>& dtypedecls) const
5540
{
5541
8
  CVC5_API_SOLVER_CHECK_DTDECLS(dtypedecls);
5542
  CVC5_API_TRY_CATCH_BEGIN;
5543
  //////// all checks before this line
5544
2
  return mkDatatypeSortsInternal(dtypedecls, {});
5545
  ////////
5546
  CVC5_API_TRY_CATCH_END;
5547
}
5548
5549
1186
std::vector<Sort> Solver::mkDatatypeSorts(
5550
    const std::vector<DatatypeDecl>& dtypedecls,
5551
    const std::set<Sort>& unresolvedSorts) const
5552
{
5553
  CVC5_API_TRY_CATCH_BEGIN;
5554
1186
  CVC5_API_SOLVER_CHECK_DTDECLS(dtypedecls);
5555
1184
  CVC5_API_SOLVER_CHECK_SORTS(unresolvedSorts);
5556
  //////// all checks before this line
5557
1184
  return mkDatatypeSortsInternal(dtypedecls, unresolvedSorts);
5558
  ////////
5559
  CVC5_API_TRY_CATCH_END;
5560
}
5561
5562
326
Sort Solver::mkFunctionSort(const Sort& domain, const Sort& codomain) const
5563
{
5564
  CVC5_API_TRY_CATCH_BEGIN;
5565
326
  CVC5_API_SOLVER_CHECK_DOMAIN_SORT(domain);
5566
322
  CVC5_API_SOLVER_CHECK_CODOMAIN_SORT(codomain);
5567
  //////// all checks before this line
5568
  return Sort(
5569
318
      this, getNodeManager()->mkFunctionType(*domain.d_type, *codomain.d_type));
5570
  ////////
5571
  CVC5_API_TRY_CATCH_END;
5572
}
5573
5574
19694
Sort Solver::mkFunctionSort(const std::vector<Sort>& sorts,
5575
                            const Sort& codomain) const
5576
{
5577
  CVC5_API_TRY_CATCH_BEGIN;
5578
19694
  CVC5_API_ARG_SIZE_CHECK_EXPECTED(sorts.size() >= 1, sorts)
5579
      << "at least one parameter sort for function sort";
5580
19694
  CVC5_API_SOLVER_CHECK_DOMAIN_SORTS(sorts);
5581
19692
  CVC5_API_SOLVER_CHECK_CODOMAIN_SORT(codomain);
5582
  //////// all checks before this line
5583
39376
  std::vector<TypeNode> argTypes = Sort::sortVectorToTypeNodes(sorts);
5584
  return Sort(this,
5585
39376
              getNodeManager()->mkFunctionType(argTypes, *codomain.d_type));
5586
  ////////
5587
  CVC5_API_TRY_CATCH_END;
5588
}
5589
5590
28
Sort Solver::mkParamSort(const std::string& symbol) const
5591
{
5592
  CVC5_API_TRY_CATCH_BEGIN;
5593
  //////// all checks before this line
5594
  return Sort(
5595
      this,
5596
28
      getNodeManager()->mkSort(symbol, NodeManager::SORT_FLAG_PLACEHOLDER));
5597
  ////////
5598
  CVC5_API_TRY_CATCH_END;
5599
}
5600
5601
10
Sort Solver::mkPredicateSort(const std::vector<Sort>& sorts) const
5602
{
5603
  CVC5_API_TRY_CATCH_BEGIN;
5604
12
  CVC5_API_ARG_SIZE_CHECK_EXPECTED(sorts.size() >= 1, sorts)
5605
2
      << "at least one parameter sort for predicate sort";
5606
8
  CVC5_API_SOLVER_CHECK_DOMAIN_SORTS(sorts);
5607
  //////// all checks before this line
5608
  return Sort(
5609
      this,
5610
6
      getNodeManager()->mkPredicateType(Sort::sortVectorToTypeNodes(sorts)));
5611
  ////////
5612
  CVC5_API_TRY_CATCH_END;
5613
}
5614
5615
12
Sort Solver::mkRecordSort(
5616
    const std::vector<std::pair<std::string, Sort>>& fields) const
5617
{
5618
  CVC5_API_TRY_CATCH_BEGIN;
5619
24
  std::vector<std::pair<std::string, TypeNode>> f;
5620
30
  for (size_t i = 0, size = fields.size(); i < size; ++i)
5621
  {
5622
20
    const auto& p = fields[i];
5623
20
    CVC5_API_ARG_AT_INDEX_CHECK_EXPECTED(!p.second.isNull(), "sort", fields, i)
5624
        << "non-null sort";
5625
24
    CVC5_API_ARG_AT_INDEX_CHECK_EXPECTED(
5626
        this == p.second.d_solver, "sort", fields, i)
5627
4
        << "sort associated with this solver object";
5628
18
    f.emplace_back(p.first, *p.second.d_type);
5629
  }
5630
  //////// all checks before this line
5631
20
  return Sort(this, getNodeManager()->mkRecordType(f));
5632
  ////////
5633
  CVC5_API_TRY_CATCH_END;
5634
}
5635
5636
2013
Sort Solver::mkSetSort(const Sort& elemSort) const
5637
{
5638
  CVC5_API_TRY_CATCH_BEGIN;
5639
2013
  CVC5_API_SOLVER_CHECK_SORT(elemSort);
5640
  //////// all checks before this line
5641
2011
  return Sort(this, getNodeManager()->mkSetType(*elemSort.d_type));
5642
  ////////
5643
  CVC5_API_TRY_CATCH_END;
5644
}
5645
5646
129
Sort Solver::mkBagSort(const Sort& elemSort) const
5647
{
5648
  CVC5_API_TRY_CATCH_BEGIN;
5649
129
  CVC5_API_SOLVER_CHECK_SORT(elemSort);
5650
  //////// all checks before this line
5651
127
  return Sort(this, getNodeManager()->mkBagType(*elemSort.d_type));
5652
  ////////
5653
  CVC5_API_TRY_CATCH_END;
5654
}
5655
5656
250
Sort Solver::mkSequenceSort(const Sort& elemSort) const
5657
{
5658
  CVC5_API_TRY_CATCH_BEGIN;
5659
250
  CVC5_API_SOLVER_CHECK_SORT(elemSort);
5660
  //////// all checks before this line
5661
248
  return Sort(this, getNodeManager()->mkSequenceType(*elemSort.d_type));
5662
  ////////
5663
  CVC5_API_TRY_CATCH_END;
5664
}
5665
5666
5799
Sort Solver::mkUninterpretedSort(const std::string& symbol) const
5667
{
5668
  CVC5_API_TRY_CATCH_BEGIN;
5669
  //////// all checks before this line
5670
5799
  return Sort(this, getNodeManager()->mkSort(symbol));
5671
  ////////
5672
  CVC5_API_TRY_CATCH_END;
5673
}
5674
5675
100
Sort Solver::mkSortConstructorSort(const std::string& symbol,
5676
                                   size_t arity) const
5677
{
5678
  CVC5_API_TRY_CATCH_BEGIN;
5679
100
  CVC5_API_ARG_CHECK_EXPECTED(arity > 0, arity) << "an arity > 0";
5680
  //////// all checks before this line
5681
98
  return Sort(this, getNodeManager()->mkSortConstructor(symbol, arity));
5682
  ////////
5683
  CVC5_API_TRY_CATCH_END;
5684
}
5685
5686
4695
Sort Solver::mkTupleSort(const std::vector<Sort>& sorts) const
5687
{
5688
  CVC5_API_TRY_CATCH_BEGIN;
5689
4695
  CVC5_API_SOLVER_CHECK_SORTS_NOT_FUNCTION_LIKE(sorts);
5690
  //////// all checks before this line
5691
4691
  return mkTupleSortHelper(sorts);
5692
  ////////
5693
  CVC5_API_TRY_CATCH_END;
5694
}
5695
5696
/* Create consts                                                              */
5697
/* -------------------------------------------------------------------------- */
5698
5699
6809
Term Solver::mkTrue(void) const
5700
{
5701
  CVC5_API_TRY_CATCH_BEGIN;
5702
  //////// all checks before this line
5703
6809
  return Term(this, d_nodeMgr->mkConst<bool>(true));
5704
  ////////
5705
  CVC5_API_TRY_CATCH_END;
5706
}
5707
5708
6750
Term Solver::mkFalse(void) const
5709
{
5710
  CVC5_API_TRY_CATCH_BEGIN;
5711
  //////// all checks before this line
5712
6750
  return Term(this, d_nodeMgr->mkConst<bool>(false));
5713
  ////////
5714
  CVC5_API_TRY_CATCH_END;
5715
}
5716
5717
57
Term Solver::mkBoolean(bool val) const
5718
{
5719
  CVC5_API_TRY_CATCH_BEGIN;
5720
  //////// all checks before this line
5721
57
  return Term(this, d_nodeMgr->mkConst<bool>(val));
5722
  ////////
5723
  CVC5_API_TRY_CATCH_END;
5724
}
5725
5726
2662
Term Solver::mkPi() const
5727
{
5728
  CVC5_API_TRY_CATCH_BEGIN;
5729
  //////// all checks before this line
5730
  Node res =
5731
5324
      d_nodeMgr->mkNullaryOperator(d_nodeMgr->realType(), cvc5::kind::PI);
5732
2662
  (void)res.getType(true); /* kick off type checking */
5733
5324
  return Term(this, res);
5734
  ////////
5735
  CVC5_API_TRY_CATCH_END;
5736
}
5737
5738
368753
Term Solver::mkInteger(const std::string& s) const
5739
{
5740
  CVC5_API_TRY_CATCH_BEGIN;
5741
368753
  CVC5_API_ARG_CHECK_EXPECTED(isValidInteger(s), s) << " an integer ";
5742
737374
  Term integer = mkRealFromStrHelper(s);
5743
368687
  CVC5_API_ARG_CHECK_EXPECTED(integer.getSort() == getIntegerSort(), s)
5744
      << " a string representing an integer";
5745
  //////// all checks before this line
5746
737374
  return integer;
5747
  ////////
5748
  CVC5_API_TRY_CATCH_END;
5749
}
5750
5751
226
Term Solver::mkInteger(int64_t val) const
5752
{
5753
  CVC5_API_TRY_CATCH_BEGIN;
5754
  //////// all checks before this line
5755
452
  Term integer = mkValHelper<cvc5::Rational>(cvc5::Rational(val));
5756
226
  Assert(integer.getSort() == getIntegerSort());
5757
452
  return integer;
5758
  ////////
5759
  CVC5_API_TRY_CATCH_END;
5760
}
5761
5762
24479
Term Solver::mkReal(const std::string& s) const
5763
{
5764
  CVC5_API_TRY_CATCH_BEGIN;
5765
  /* CLN and GMP handle this case differently, CLN interprets it as 0, GMP
5766
   * throws an std::invalid_argument exception. For consistency, we treat it
5767
   * as invalid. */
5768
24483
  CVC5_API_ARG_CHECK_EXPECTED(s != ".", s)
5769
4
      << "a string representing a real or rational value.";
5770
  //////// all checks before this line
5771
48926
  Term rational = mkRealFromStrHelper(s);
5772
48902
  return ensureRealSort(rational);
5773
  ////////
5774
  CVC5_API_TRY_CATCH_END;
5775
}
5776
5777
51
Term Solver::mkReal(int64_t val) const
5778
{
5779
  CVC5_API_TRY_CATCH_BEGIN;
5780
  //////// all checks before this line
5781
102
  Term rational = mkValHelper<cvc5::Rational>(cvc5::Rational(val));
5782
102
  return ensureRealSort(rational);
5783
  ////////
5784
  CVC5_API_TRY_CATCH_END;
5785
}
5786
5787
10
Term Solver::mkReal(int64_t num, int64_t den) const
5788
{
5789
  CVC5_API_TRY_CATCH_BEGIN;
5790
  //////// all checks before this line
5791
20
  Term rational = mkValHelper<cvc5::Rational>(cvc5::Rational(num, den));
5792
20
  return ensureRealSort(rational);
5793
  ////////
5794
  CVC5_API_TRY_CATCH_END;
5795
}
5796
5797
3043
Term Solver::mkRegexpEmpty() const
5798
{
5799
  CVC5_API_TRY_CATCH_BEGIN;
5800
  //////// all checks before this line
5801
  Node res =
5802
6086
      d_nodeMgr->mkNode(cvc5::kind::REGEXP_EMPTY, std::vector<cvc5::Node>());
5803
3043
  (void)res.getType(true); /* kick off type checking */
5804
6086
  return Term(this, res);
5805
  ////////
5806
  CVC5_API_TRY_CATCH_END;
5807
}
5808
5809
6084
Term Solver::mkRegexpSigma() const
5810
{
5811
  CVC5_API_TRY_CATCH_BEGIN;
5812
  //////// all checks before this line
5813
  Node res =
5814
12168
      d_nodeMgr->mkNode(cvc5::kind::REGEXP_SIGMA, std::vector<cvc5::Node>());
5815
6084
  (void)res.getType(true); /* kick off type checking */
5816
12168
  return Term(this, res);
5817
  ////////
5818
  CVC5_API_TRY_CATCH_END;
5819
}
5820
5821
2818
Term Solver::mkEmptySet(const Sort& sort) const
5822
{
5823
  CVC5_API_TRY_CATCH_BEGIN;
5824
2820
  CVC5_API_ARG_CHECK_EXPECTED(sort.isNull() || sort.isSet(), sort)
5825
2
      << "null sort or set sort";
5826
2818
  CVC5_API_ARG_CHECK_EXPECTED(sort.isNull() || this == sort.d_solver, sort)
5827
2
      << "set sort associated with this solver object";
5828
  //////// all checks before this line
5829
2814
  return mkValHelper<cvc5::EmptySet>(cvc5::EmptySet(*sort.d_type));
5830
  ////////
5831
  CVC5_API_TRY_CATCH_END;
5832
}
5833
5834
2587
Term Solver::mkEmptyBag(const Sort& sort) const
5835
{
5836
  CVC5_API_TRY_CATCH_BEGIN;
5837
2589
  CVC5_API_ARG_CHECK_EXPECTED(sort.isNull() || sort.isBag(), sort)
5838
2
      << "null sort or bag sort";
5839
2587
  CVC5_API_ARG_CHECK_EXPECTED(sort.isNull() || this == sort.d_solver, sort)
5840
2
      << "bag sort associated with this solver object";
5841
  //////// all checks before this line
5842
2583
  return mkValHelper<cvc5::EmptyBag>(cvc5::EmptyBag(*sort.d_type));
5843
  ////////
5844
  CVC5_API_TRY_CATCH_END;
5845
}
5846
5847
2566
Term Solver::mkSepEmp() const
5848
{
5849
  CVC5_API_TRY_CATCH_BEGIN;
5850
  //////// all checks before this line
5851
5132
  Node res = getNodeManager()->mkNullaryOperator(d_nodeMgr->booleanType(),
5852
7698
                                                 cvc5::Kind::SEP_EMP);
5853
2566
  (void)res.getType(true); /* kick off type checking */
5854
5132
  return Term(this, res);
5855
  ////////
5856
  CVC5_API_TRY_CATCH_END;
5857
}
5858
5859
2622
Term Solver::mkSepNil(const Sort& sort) const
5860
{
5861
  CVC5_API_TRY_CATCH_BEGIN;
5862
2622
  CVC5_API_SOLVER_CHECK_SORT(sort);
5863
  //////// all checks before this line
5864
  Node res =
5865
5236
      getNodeManager()->mkNullaryOperator(*sort.d_type, cvc5::kind::SEP_NIL);
5866
2618
  (void)res.getType(true); /* kick off type checking */
5867
5236
  return Term(this, res);
5868
  ////////
5869
  CVC5_API_TRY_CATCH_END;
5870
}
5871
5872
9401
Term Solver::mkString(const std::string& s, bool useEscSequences) const
5873
{
5874
  CVC5_API_TRY_CATCH_BEGIN;
5875
  //////// all checks before this line
5876
9401
  return mkValHelper<cvc5::String>(cvc5::String(s, useEscSequences));
5877
  ////////
5878
  CVC5_API_TRY_CATCH_END;
5879
}
5880
5881
9492
Term Solver::mkString(const std::wstring& s) const
5882
{
5883
  CVC5_API_TRY_CATCH_BEGIN;
5884
  //////// all checks before this line
5885
9492
  return mkValHelper<cvc5::String>(cvc5::String(s));
5886
  ////////
5887
  CVC5_API_TRY_CATCH_END;
5888
}
5889
5890
3062
Term Solver::mkEmptySequence(const Sort& sort) const
5891
{
5892
  CVC5_API_TRY_CATCH_BEGIN;
5893
3062
  CVC5_API_SOLVER_CHECK_SORT(sort);
5894
  //////// all checks before this line
5895
6120
  std::vector<Node> seq;
5896
6120
  Node res = d_nodeMgr->mkConst(Sequence(*sort.d_type, seq));
5897
6120
  return Term(this, res);
5898
  ////////
5899
  CVC5_API_TRY_CATCH_END;
5900
}
5901
5902
2738
Term Solver::mkUniverseSet(const Sort& sort) const
5903
{
5904
  CVC5_API_TRY_CATCH_BEGIN;
5905
2738
  CVC5_API_SOLVER_CHECK_SORT(sort);
5906
  //////// all checks before this line
5907
5908
2734
  Node res = getNodeManager()->mkNullaryOperator(*sort.d_type,
5909
8202
                                                 cvc5::kind::UNIVERSE_SET);
5910
  // TODO(#2771): Reenable?
5911
  // (void)res->getType(true); /* kick off type checking */
5912
5468
  return Term(this, res);
5913
  ////////
5914
  CVC5_API_TRY_CATCH_END;
5915
}
5916
5917
16
Term Solver::mkBitVector(uint32_t size, uint64_t val) const
5918
{
5919
  CVC5_API_TRY_CATCH_BEGIN;
5920
  //////// all checks before this line
5921
16
  return mkBVFromIntHelper(size, val);
5922
  ////////
5923
  CVC5_API_TRY_CATCH_END;
5924
}
5925
5926
95459
Term Solver::mkBitVector(uint32_t size,
5927
                         const std::string& s,
5928
                         uint32_t base) const
5929
{
5930
  CVC5_API_TRY_CATCH_BEGIN;
5931
  //////// all checks before this line
5932
95459
  return mkBVFromStrHelper(size, s, base);
5933
  ////////
5934
  CVC5_API_TRY_CATCH_END;
5935
}
5936
5937
98
Term Solver::mkConstArray(const Sort& sort, const Term& val) const
5938
{
5939
  CVC5_API_TRY_CATCH_BEGIN;
5940
98
  CVC5_API_SOLVER_CHECK_SORT(sort);
5941
94
  CVC5_API_SOLVER_CHECK_TERM(val);
5942
90
  CVC5_API_ARG_CHECK_EXPECTED(sort.isArray(), sort) << "an array sort";
5943
90
  CVC5_API_CHECK(val.getSort().isSubsortOf(sort.getArrayElementSort()))
5944
2
      << "Value does not match element sort";
5945
  //////// all checks before this line
5946
5947
  // handle the special case of (CAST_TO_REAL n) where n is an integer
5948
172
  Node n = *val.d_node;
5949
86
  if (val.isCastedReal())
5950
  {
5951
    // this is safe because the constant array stores its type
5952
4
    n = n[0];
5953
  }
5954
  Term res =
5955
172
      mkValHelper<cvc5::ArrayStoreAll>(cvc5::ArrayStoreAll(*sort.d_type, n));
5956
172
  return res;
5957
  ////////
5958
  CVC5_API_TRY_CATCH_END;
5959
}
5960
5961
8
Term Solver::mkPosInf(uint32_t exp, uint32_t sig) const
5962
{
5963
  CVC5_API_TRY_CATCH_BEGIN;
5964
  //////// all checks before this line
5965
  return mkValHelper<cvc5::FloatingPoint>(
5966
8
      FloatingPoint::makeInf(FloatingPointSize(exp, sig), false));
5967
  ////////
5968
  CVC5_API_TRY_CATCH_END;
5969
}
5970
5971
8
Term Solver::mkNegInf(uint32_t exp, uint32_t sig) const
5972
{
5973
  CVC5_API_TRY_CATCH_BEGIN;
5974
  //////// all checks before this line
5975
  return mkValHelper<cvc5::FloatingPoint>(
5976
8
      FloatingPoint::makeInf(FloatingPointSize(exp, sig), true));
5977
  ////////
5978
  CVC5_API_TRY_CATCH_END;
5979
}
5980
5981
8
Term Solver::mkNaN(uint32_t exp, uint32_t sig) const
5982
{
5983
  CVC5_API_TRY_CATCH_BEGIN;
5984
  //////// all checks before this line
5985
  return mkValHelper<cvc5::FloatingPoint>(
5986
8
      FloatingPoint::makeNaN(FloatingPointSize(exp, sig)));
5987
  ////////
5988
  CVC5_API_TRY_CATCH_END;
5989
}
5990
5991
9
Term Solver::mkPosZero(uint32_t exp, uint32_t sig) const
5992
{
5993
  CVC5_API_TRY_CATCH_BEGIN;
5994
  //////// all checks before this line
5995
  return mkValHelper<cvc5::FloatingPoint>(
5996
9
      FloatingPoint::makeZero(FloatingPointSize(exp, sig), false));
5997
  ////////
5998
  CVC5_API_TRY_CATCH_END;
5999
}
6000
6001
6
Term Solver::mkNegZero(uint32_t exp, uint32_t sig) const
6002
{
6003
  CVC5_API_TRY_CATCH_BEGIN;
6004
  //////// all checks before this line
6005
  return mkValHelper<cvc5::FloatingPoint>(
6006
6
      FloatingPoint::makeZero(FloatingPointSize(exp, sig), true));
6007
  ////////
6008
  CVC5_API_TRY_CATCH_END;
6009
}
6010
6011
26214
Term Solver::mkRoundingMode(RoundingMode rm) const
6012
{
6013
  CVC5_API_TRY_CATCH_BEGIN;
6014
  //////// all checks before this line
6015
26214
  return mkValHelper<cvc5::RoundingMode>(s_rmodes.at(rm));
6016
  ////////
6017
  CVC5_API_TRY_CATCH_END;
6018
}
6019
6020
4
Term Solver::mkUninterpretedConst(const Sort& sort, int32_t index) const
6021
{
6022
  CVC5_API_TRY_CATCH_BEGIN;
6023
4
  CVC5_API_SOLVER_CHECK_SORT(sort);
6024
  //////// all checks before this line
6025
  return mkValHelper<cvc5::UninterpretedConstant>(
6026
4
      cvc5::UninterpretedConstant(*sort.d_type, index));
6027
  ////////
6028
  CVC5_API_TRY_CATCH_END;
6029
}
6030
6031
16
Term Solver::mkAbstractValue(const std::string& index) const
6032
{
6033
  CVC5_API_TRY_CATCH_BEGIN;
6034
16
  CVC5_API_ARG_CHECK_EXPECTED(!index.empty(), index) << "a non-empty string";
6035
6036
26
  cvc5::Integer idx(index, 10);
6037
14
  CVC5_API_ARG_CHECK_EXPECTED(idx > 0, index)
6038
4
      << "a string representing an integer > 0";
6039
  //////// all checks before this line
6040
12
  return Term(this, getNodeManager()->mkConst(cvc5::AbstractValue(idx)));
6041
  // do not call getType(), for abstract values, type can not be computed
6042
  // until it is substituted away
6043
  ////////
6044
  CVC5_API_TRY_CATCH_END;
6045
}
6046
6047
16
Term Solver::mkAbstractValue(uint64_t index) const
6048
{
6049
  CVC5_API_TRY_CATCH_BEGIN;
6050
16
  CVC5_API_ARG_CHECK_EXPECTED(index > 0, index) << "an integer > 0";
6051
  //////// all checks before this line
6052
  return Term(this,
6053
14
              getNodeManager()->mkConst(cvc5::AbstractValue(Integer(index))));
6054
  // do not call getType(), for abstract values, type can not be computed
6055
  // until it is substituted away
6056
  ////////
6057
  CVC5_API_TRY_CATCH_END;
6058
}
6059
6060
17
Term Solver::mkFloatingPoint(uint32_t exp, uint32_t sig, Term val) const
6061
{
6062
  CVC5_API_TRY_CATCH_BEGIN;
6063
17
  CVC5_API_SOLVER_CHECK_TERM(val);
6064
13
  CVC5_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "a value > 0";
6065
11
  CVC5_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "a value > 0";
6066
9
  uint32_t bw = exp + sig;
6067
13
  CVC5_API_ARG_CHECK_EXPECTED(bw == val.d_node->getType().getBitVectorSize(),
6068
                              val)
6069
4
      << "a bit-vector constant with bit-width '" << bw << "'";
6070
5
  CVC5_API_ARG_CHECK_EXPECTED(
6071
      val.d_node->getType().isBitVector() && val.d_node->isConst(), val)
6072
      << "bit-vector constant";
6073
  //////// all checks before this line
6074
  return mkValHelper<cvc5::FloatingPoint>(
6075
5
      cvc5::FloatingPoint(exp, sig, val.d_node->getConst<BitVector>()));
6076
  ////////
6077
  CVC5_API_TRY_CATCH_END;
6078
}
6079
6080
44
Term Solver::mkCardinalityConstraint(const Sort& sort, uint32_t upperBound) const
6081
{
6082
  CVC5_API_TRY_CATCH_BEGIN;
6083
44
  CVC5_API_SOLVER_CHECK_SORT(sort);
6084
44
  CVC5_API_ARG_CHECK_EXPECTED(sort.isUninterpretedSort(), sort)
6085
2
      << "an uninterpreted sort";
6086
40
  CVC5_API_ARG_CHECK_EXPECTED(upperBound > 0, upperBound) << "a value > 0";
6087
  //////// all checks before this line
6088
  Node cco =
6089
76
      d_nodeMgr->mkConst(cvc5::CardinalityConstraint(*sort.d_type, upperBound));
6090
76
  Node cc = d_nodeMgr->mkNode(cvc5::Kind::CARDINALITY_CONSTRAINT, cco);
6091
76
  return Term(this, cc);
6092
  ////////
6093
  CVC5_API_TRY_CATCH_END;
6094
}
6095
6096
/* Create constants                                                           */
6097
/* -------------------------------------------------------------------------- */
6098
6099
114444
Term Solver::mkConst(const Sort& sort, const std::string& symbol) const
6100
{
6101
  CVC5_API_TRY_CATCH_BEGIN;
6102
114444
  CVC5_API_SOLVER_CHECK_SORT(sort);
6103
  //////// all checks before this line
6104
228884
  Node res = d_nodeMgr->mkVar(symbol, *sort.d_type);
6105
114442
  (void)res.getType(true); /* kick off type checking */
6106
114442
  increment_vars_consts_stats(sort, false);
6107
228884
  return Term(this, res);
6108
  ////////
6109
  CVC5_API_TRY_CATCH_END;
6110
}
6111
6112
22
Term Solver::mkConst(const Sort& sort) const
6113
{
6114
  CVC5_API_TRY_CATCH_BEGIN;
6115
22
  CVC5_API_SOLVER_CHECK_SORT(sort);
6116
  //////// all checks before this line
6117
36
  Node res = d_nodeMgr->mkVar(*sort.d_type);
6118
18
  (void)res.getType(true); /* kick off type checking */
6119
18
  increment_vars_consts_stats(sort, false);
6120
36
  return Term(this, res);
6121
  ////////
6122
  CVC5_API_TRY_CATCH_END;
6123
}
6124
6125
/* Create variables                                                           */
6126
/* -------------------------------------------------------------------------- */
6127
6128
60781
Term Solver::mkVar(const Sort& sort, const std::string& symbol) const
6129
{
6130
  CVC5_API_TRY_CATCH_BEGIN;
6131
60781
  CVC5_API_SOLVER_CHECK_SORT(sort);
6132
  //////// all checks before this line
6133
60823
  Node res = symbol.empty() ? d_nodeMgr->mkBoundVar(*sort.d_type)
6134
121598
                            : d_nodeMgr->mkBoundVar(symbol, *sort.d_type);
6135
60775
  (void)res.getType(true); /* kick off type checking */
6136
60775
  increment_vars_consts_stats(sort, true);
6137
121550
  return Term(this, res);
6138
  ////////
6139
  CVC5_API_TRY_CATCH_END;
6140
}
6141
6142
/* Create datatype constructor declarations                                   */
6143
/* -------------------------------------------------------------------------- */
6144
6145
3075
DatatypeConstructorDecl Solver::mkDatatypeConstructorDecl(
6146
    const std::string& name)
6147
{
6148
  CVC5_API_TRY_CATCH_BEGIN;
6149
  //////// all checks before this line
6150
3075
  return DatatypeConstructorDecl(this, name);
6151
  ////////
6152
  CVC5_API_TRY_CATCH_END;
6153
}
6154
6155
/* Create datatype declarations                                               */
6156
/* -------------------------------------------------------------------------- */
6157
6158
74
DatatypeDecl Solver::mkDatatypeDecl(const std::string& name, bool isCoDatatype)
6159
{
6160
  CVC5_API_TRY_CATCH_BEGIN;
6161
  //////// all checks before this line
6162
74
  return DatatypeDecl(this, name, isCoDatatype);
6163
  ////////
6164
  CVC5_API_TRY_CATCH_END;
6165
}
6166
6167
12
DatatypeDecl Solver::mkDatatypeDecl(const std::string& name,
6168
                                    Sort param,
6169
                                    bool isCoDatatype)
6170
{
6171
  CVC5_API_TRY_CATCH_BEGIN;
6172
12
  CVC5_API_SOLVER_CHECK_SORT(param);
6173
  //////// all checks before this line
6174
12
  return DatatypeDecl(this, name, param, isCoDatatype);
6175
  ////////
6176
  CVC5_API_TRY_CATCH_END;
6177
}
6178
6179
1532
DatatypeDecl Solver::mkDatatypeDecl(const std::string& name,
6180
                                    const std::vector<Sort>& params,
6181
                                    bool isCoDatatype)
6182
{
6183
  CVC5_API_TRY_CATCH_BEGIN;
6184
1532
  CVC5_API_SOLVER_CHECK_SORTS(params);
6185
  //////// all checks before this line
6186
1532
  return DatatypeDecl(this, name, params, isCoDatatype);
6187
  ////////
6188
  CVC5_API_TRY_CATCH_END;
6189
}
6190
6191
/* Create terms                                                               */
6192
/* -------------------------------------------------------------------------- */
6193
6194
8
Term Solver::mkTerm(Kind kind) const
6195
{
6196
  CVC5_API_TRY_CATCH_BEGIN;
6197
8
  CVC5_API_KIND_CHECK(kind);
6198
  //////// all checks before this line
6199
8
  return mkTermFromKind(kind);
6200
  ////////
6201
  CVC5_API_TRY_CATCH_END;
6202
}
6203
6204
128623
Term Solver::mkTerm(Kind kind, const Term& child) const
6205
{
6206
  CVC5_API_TRY_CATCH_BEGIN;
6207
128623
  CVC5_API_KIND_CHECK(kind);
6208
128623
  CVC5_API_SOLVER_CHECK_TERM(child);
6209
  //////// all checks before this line
6210
128627
  return mkTermHelper(kind, std::vector<Term>{child});
6211
  ////////
6212
  CVC5_API_TRY_CATCH_END;
6213
}
6214
6215
11018
Term Solver::mkTerm(Kind kind, const Term& child1, const Term& child2) const
6216
{
6217
  CVC5_API_TRY_CATCH_BEGIN;
6218
11018
  CVC5_API_KIND_CHECK(kind);
6219
11018
  CVC5_API_SOLVER_CHECK_TERM(child1);
6220
11014
  CVC5_API_SOLVER_CHECK_TERM(child2);
6221
  //////// all checks before this line
6222
11018
  return mkTermHelper(kind, std::vector<Term>{child1, child2});
6223
  ////////
6224
  CVC5_API_TRY_CATCH_END;
6225
}
6226
6227
80
Term Solver::mkTerm(Kind kind,
6228
                    const Term& child1,
6229
                    const Term& child2,
6230
                    const Term& child3) const
6231
{
6232
  CVC5_API_TRY_CATCH_BEGIN;
6233
80
  CVC5_API_KIND_CHECK(kind);
6234
80
  CVC5_API_SOLVER_CHECK_TERM(child1);
6235
74
  CVC5_API_SOLVER_CHECK_TERM(child2);
6236
72
  CVC5_API_SOLVER_CHECK_TERM(child3);
6237
  //////// all checks before this line
6238
  // need to use internal term call to check e.g. associative construction
6239
72
  return mkTermHelper(kind, std::vector<Term>{child1, child2, child3});
6240
  ////////
6241
  CVC5_API_TRY_CATCH_END;
6242
}
6243
6244
2314078
Term Solver::mkTerm(Kind kind, const std::vector<Term>& children) const
6245
{
6246
  CVC5_API_TRY_CATCH_BEGIN;
6247
2314078
  CVC5_API_KIND_CHECK(kind);
6248
2314078
  CVC5_API_SOLVER_CHECK_TERMS(children);
6249
  //////// all checks before this line
6250
2314076
  return mkTermHelper(kind, children);
6251
  ////////
6252
  CVC5_API_TRY_CATCH_END;
6253
}
6254
6255
4
Term Solver::mkTerm(const Op& op) const
6256
{
6257
  CVC5_API_TRY_CATCH_BEGIN;
6258
4
  CVC5_API_SOLVER_CHECK_OP(op);
6259
4
  checkMkTerm(op.d_kind, 0);
6260
  //////// all checks before this line
6261
6262
  if (!op.isIndexedHelper())
6263
  {
6264
    return mkTermFromKind(op.d_kind);
6265
  }
6266
6267
  const cvc5::Kind int_kind = extToIntKind(op.d_kind);
6268
  Term res = Term(this, getNodeManager()->mkNode(int_kind, *op.d_node));
6269
6270
  (void)res.d_node->getType(true); /* kick off type checking */
6271
  return res;
6272
  ////////
6273
  CVC5_API_TRY_CATCH_END;
6274
}
6275
6276
36
Term Solver::mkTerm(const Op& op, const Term& child) const
6277
{
6278
  CVC5_API_TRY_CATCH_BEGIN;
6279
36
  CVC5_API_SOLVER_CHECK_OP(op);
6280
34
  CVC5_API_SOLVER_CHECK_TERM(child);
6281
  //////// all checks before this line
6282
38
  return mkTermHelper(op, std::vector<Term>{child});
6283
  ////////
6284
  CVC5_API_TRY_CATCH_END;
6285
}
6286
6287
8
Term Solver::mkTerm(const Op& op, const Term& child1, const Term& child2) const
6288
{
6289
  CVC5_API_TRY_CATCH_BEGIN;
6290
8
  CVC5_API_SOLVER_CHECK_OP(op);
6291
8
  CVC5_API_SOLVER_CHECK_TERM(child1);
6292
6
  CVC5_API_SOLVER_CHECK_TERM(child2);
6293
  //////// all checks before this line
6294
8
  return mkTermHelper(op, std::vector<Term>{child1, child2});
6295
  ////////
6296
  CVC5_API_TRY_CATCH_END;
6297
}
6298
6299
4
Term Solver::mkTerm(const Op& op,
6300
                    const Term& child1,
6301
                    const Term& child2,
6302
                    const Term& child3) const
6303
{
6304
  CVC5_API_TRY_CATCH_BEGIN;
6305
4
  CVC5_API_SOLVER_CHECK_OP(op);
6306
4
  CVC5_API_SOLVER_CHECK_TERM(child1);
6307
4
  CVC5_API_SOLVER_CHECK_TERM(child2);
6308
4
  CVC5_API_SOLVER_CHECK_TERM(child3);
6309
  //////// all checks before this line
6310
4
  return mkTermHelper(op, std::vector<Term>{child1, child2, child3});
6311
  ////////
6312
  CVC5_API_TRY_CATCH_END;
6313
}
6314
6315
76613
Term Solver::mkTerm(const Op& op, const std::vector<Term>& children) const
6316
{
6317
  CVC5_API_TRY_CATCH_BEGIN;
6318
76613
  CVC5_API_SOLVER_CHECK_OP(op);
6319
76611
  CVC5_API_SOLVER_CHECK_TERMS(children);
6320
  //////// all checks before this line
6321
76609
  return mkTermHelper(op, children);
6322
  ////////
6323
  CVC5_API_TRY_CATCH_END;
6324
}
6325
6326
1820
Term Solver::mkTuple(const std::vector<Sort>& sorts,
6327
                     const std::vector<Term>& terms) const
6328
{
6329
  CVC5_API_TRY_CATCH_BEGIN;
6330
1822
  CVC5_API_CHECK(sorts.size() == terms.size())
6331
2
      << "Expected the same number of sorts and elements";
6332
1818
  CVC5_API_SOLVER_CHECK_SORTS(sorts);
6333
1816
  CVC5_API_SOLVER_CHECK_TERMS(terms);
6334
  //////// all checks before this line
6335
3628
  std::vector<cvc5::Node> args;
6336
5438
  for (size_t i = 0, size = sorts.size(); i < size; i++)
6337
  {
6338
3628
    args.push_back(*(ensureTermSort(terms[i], sorts[i])).d_node);
6339
  }
6340
6341
3620
  Sort s = mkTupleSortHelper(sorts);
6342
3620
  Datatype dt = s.getDatatype();
6343
3620
  NodeBuilder nb(extToIntKind(APPLY_CONSTRUCTOR));
6344
1810
  nb << *dt[0].getConstructorTerm().d_node;
6345
1810
  nb.append(args);
6346
3620
  Node res = nb.constructNode();
6347
1810
  (void)res.getType(true); /* kick off type checking */
6348
3620
  return Term(this, res);
6349
  ////////
6350
  CVC5_API_TRY_CATCH_END;
6351
}
6352
6353
/* Create operators                                                           */
6354
/* -------------------------------------------------------------------------- */
6355
6356
10
Op Solver::mkOp(Kind kind) const
6357
{
6358
  CVC5_API_TRY_CATCH_BEGIN;
6359
10
  CVC5_API_KIND_CHECK(kind);
6360
12
  CVC5_API_CHECK(s_indexed_kinds.find(kind) == s_indexed_kinds.end())
6361
2
      << "Expected a kind for a non-indexed operator.";
6362
  //////// all checks before this line
6363
8
  return Op(this, kind);
6364
  ////////
6365
  CVC5_API_TRY_CATCH_END
6366
}
6367
6368
4
Op Solver::mkOp(Kind kind, const std::string& arg) const
6369
{
6370
  CVC5_API_TRY_CATCH_BEGIN;
6371
4
  CVC5_API_KIND_CHECK(kind);
6372
4
  CVC5_API_KIND_CHECK_EXPECTED((kind == DIVISIBLE), kind) << "DIVISIBLE";
6373
  //////// all checks before this line
6374
4
  Op res;
6375
  /* CLN and GMP handle this case differently, CLN interprets it as 0, GMP
6376
   * throws an std::invalid_argument exception. For consistency, we treat it
6377
   * as invalid. */
6378
2
  CVC5_API_ARG_CHECK_EXPECTED(arg != ".", arg)
6379
      << "a string representing an integer, real or rational value.";
6380
2
  res = Op(this,
6381
           kind,
6382
4
           *mkValHelper<cvc5::Divisible>(cvc5::Divisible(cvc5::Integer(arg)))
6383
2
                .d_node);
6384
4
  return res;
6385
  ////////
6386
  CVC5_API_TRY_CATCH_END;
6387
}
6388
6389
64321
Op Solver::mkOp(Kind kind, uint32_t arg) const
6390
{
6391
  CVC5_API_TRY_CATCH_BEGIN;
6392
64321
  CVC5_API_KIND_CHECK(kind);
6393
  //////// all checks before this line
6394
128642
  Op res;
6395
64321
  switch (kind)
6396
  {
6397
10
    case DIVISIBLE:
6398
10
      res = Op(this,
6399
               kind,
6400
20
               *mkValHelper<cvc5::Divisible>(cvc5::Divisible(arg)).d_node);
6401
10
      break;
6402
3046
    case BITVECTOR_REPEAT:
6403
3046
      res = Op(this,
6404
               kind,
6405
6092
               *mkValHelper<cvc5::BitVectorRepeat>(cvc5::BitVectorRepeat(arg))
6406
3046
                    .d_node);
6407
3046
      break;
6408
32239
    case BITVECTOR_ZERO_EXTEND:
6409
32239
      res = Op(this,
6410
               kind,
6411
64478
               *mkValHelper<cvc5::BitVectorZeroExtend>(
6412
                    cvc5::BitVectorZeroExtend(arg))
6413
32239
                    .d_node);
6414
32239
      break;
6415
25638
    case BITVECTOR_SIGN_EXTEND:
6416
25638
      res = Op(this,
6417
               kind,
6418
51276
               *mkValHelper<cvc5::BitVectorSignExtend>(
6419
                    cvc5::BitVectorSignExtend(arg))
6420
25638
                    .d_node);
6421
25638
      break;
6422
1390
    case BITVECTOR_ROTATE_LEFT:
6423
1390
      res = Op(this,
6424
               kind,
6425
2780
               *mkValHelper<cvc5::BitVectorRotateLeft>(
6426
                    cvc5::BitVectorRotateLeft(arg))
6427
1390
                    .d_node);
6428
1390
      break;
6429
1720
    case BITVECTOR_ROTATE_RIGHT:
6430
1720
      res = Op(this,
6431
               kind,
6432
3440
               *mkValHelper<cvc5::BitVectorRotateRight>(
6433
                    cvc5::BitVectorRotateRight(arg))
6434
1720
                    .d_node);
6435
1720
      break;
6436
188
    case INT_TO_BITVECTOR:
6437
187
      res = Op(
6438
          this,
6439
          kind,
6440
375
          *mkValHelper<cvc5::IntToBitVector>(cvc5::IntToBitVector(arg)).d_node);
6441
187
      break;
6442
67
    case IAND:
6443
67
      res =
6444
134
          Op(this, kind, *mkValHelper<cvc5::IntAnd>(cvc5::IntAnd(arg)).d_node);
6445
67
      break;
6446
6
    case FLOATINGPOINT_TO_UBV:
6447
6
      res = Op(
6448
          this,
6449
          kind,
6450
12
          *mkValHelper<cvc5::FloatingPointToUBV>(cvc5::FloatingPointToUBV(arg))
6451
6
               .d_node);
6452
6
      break;
6453
9
    case FLOATINGPOINT_TO_SBV:
6454
9
      res = Op(
6455
          this,
6456
          kind,
6457
18
          *mkValHelper<cvc5::FloatingPointToSBV>(cvc5::FloatingPointToSBV(arg))
6458
9
               .d_node);
6459
9
      break;
6460
4
    case REGEXP_REPEAT:
6461
4
      res =
6462
8
          Op(this,
6463
             kind,
6464
8
             *mkValHelper<cvc5::RegExpRepeat>(cvc5::RegExpRepeat(arg)).d_node);
6465
4
      break;
6466
4
    default:
6467
12
      CVC5_API_KIND_CHECK_EXPECTED(false, kind)
6468
8
          << "operator kind with uint32_t argument";
6469
  }
6470
64316
  Assert(!res.isNull());
6471
128632
  return res;
6472
  ////////
6473
  CVC5_API_TRY_CATCH_END;
6474
}
6475
6476
12411
Op Solver::mkOp(Kind kind, uint32_t arg1, uint32_t arg2) const
6477
{
6478
  CVC5_API_TRY_CATCH_BEGIN;
6479
12411
  CVC5_API_KIND_CHECK(kind);
6480
  //////// all checks before this line
6481
6482
24822
  Op res;
6483
12411
  switch (kind)
6484
  {
6485
12220
    case BITVECTOR_EXTRACT:
6486
12220
      res = Op(this,
6487
               kind,
6488
24440
               *mkValHelper<cvc5::BitVectorExtract>(
6489
                    cvc5::BitVectorExtract(arg1, arg2))
6490
12220
                    .d_node);
6491
12220
      break;
6492
6
    case FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
6493
6
      res = Op(this,
6494
               kind,
6495
12
               *mkValHelper<cvc5::FloatingPointToFPIEEEBitVector>(
6496
12
                    cvc5::FloatingPointToFPIEEEBitVector(arg1, arg2))
6497
6
                    .d_node);
6498
6
      break;
6499
6
    case FLOATINGPOINT_TO_FP_FLOATINGPOINT:
6500
6
      res = Op(this,
6501
               kind,
6502
12
               *mkValHelper<cvc5::FloatingPointToFPFloatingPoint>(
6503
12
                    cvc5::FloatingPointToFPFloatingPoint(arg1, arg2))
6504
6
                    .d_node);
6505
6
      break;
6506
6
    case FLOATINGPOINT_TO_FP_REAL:
6507
6
      res = Op(this,
6508
               kind,
6509
12
               *mkValHelper<cvc5::FloatingPointToFPReal>(
6510
12
                    cvc5::FloatingPointToFPReal(arg1, arg2))
6511
6
                    .d_node);
6512
6
      break;
6513
6
    case FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
6514
6
      res = Op(this,
6515
               kind,
6516
12
               *mkValHelper<cvc5::FloatingPointToFPSignedBitVector>(
6517
12
                    cvc5::FloatingPointToFPSignedBitVector(arg1, arg2))
6518
6
                    .d_node);
6519
6
      break;
6520
18
    case FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
6521
18
      res = Op(this,
6522
               kind,
6523
36
               *mkValHelper<cvc5::FloatingPointToFPUnsignedBitVector>(
6524
36
                    cvc5::FloatingPointToFPUnsignedBitVector(arg1, arg2))
6525
18
                    .d_node);
6526
18
      break;
6527
115
    case FLOATINGPOINT_TO_FP_GENERIC:
6528
115
      res = Op(this,
6529
               kind,
6530
230
               *mkValHelper<cvc5::FloatingPointToFPGeneric>(
6531
230
                    cvc5::FloatingPointToFPGeneric(arg1, arg2))
6532
115
                    .d_node);
6533
115
      break;
6534
32
    case REGEXP_LOOP:
6535
32
      res = Op(
6536
          this,
6537
          kind,
6538
64
          *mkValHelper<cvc5::RegExpLoop>(cvc5::RegExpLoop(arg1, arg2)).d_node);
6539
32
      break;
6540
2
    default:
6541
6
      CVC5_API_KIND_CHECK_EXPECTED(false, kind)
6542
4
          << "operator kind with two uint32_t arguments";
6543
  }
6544
12409
  Assert(!res.isNull());
6545
24818
  return res;
6546
  ////////
6547
  CVC5_API_TRY_CATCH_END;
6548
}
6549
6550
22
Op Solver::mkOp(Kind kind, const std::vector<uint32_t>& args) const
6551
{
6552
  CVC5_API_TRY_CATCH_BEGIN;
6553
22
  CVC5_API_KIND_CHECK(kind);
6554
  //////// all checks before this line
6555
6556
44
  Op res;
6557
22
  switch (kind)
6558
  {
6559
22
    case TUPLE_PROJECT:
6560
    {
6561
22
      res = Op(this,
6562
               kind,
6563
44
               *mkValHelper<cvc5::TupleProjectOp>(cvc5::TupleProjectOp(args))
6564
22
                    .d_node);
6565
    }
6566
22
    break;
6567
    default:
6568
    {
6569
      std::string message = "operator kind with " + std::to_string(args.size())
6570
                            + " uint32_t arguments";
6571
      CVC5_API_KIND_CHECK_EXPECTED(false, kind) << message;
6572
    }
6573
  }
6574
22
  Assert(!res.isNull());
6575
44
  return res;
6576
  ////////
6577
  CVC5_API_TRY_CATCH_END;
6578
}
6579
6580
/* Non-SMT-LIB commands                                                       */
6581
/* -------------------------------------------------------------------------- */
6582
6583
74
Term Solver::simplify(const Term& term)
6584
{
6585
  CVC5_API_TRY_CATCH_BEGIN;
6586
74
  CVC5_API_SOLVER_CHECK_TERM(term);
6587
  //////// all checks before this line
6588
70
  return Term(this, d_slv->simplify(*term.d_node));
6589
  ////////
6590
  CVC5_API_TRY_CATCH_END;
6591
}
6592
6593
57
Result Solver::checkEntailed(const Term& term) const
6594
{
6595
  CVC5_API_TRY_CATCH_BEGIN;
6596
59
  CVC5_API_CHECK(!d_slv->isQueryMade()
6597
                 || d_slv->getOptions().base.incrementalSolving)
6598
      << "Cannot make multiple queries unless incremental solving is enabled "
6599
2
         "(try --incremental)";
6600
55
  CVC5_API_SOLVER_CHECK_TERM(term);
6601
  //////// all checks before this line
6602
45
  return d_slv->checkEntailed(*term.d_node);
6603
  ////////
6604
  CVC5_API_TRY_CATCH_END;
6605
}
6606
6607
6
Result Solver::checkEntailed(const std::vector<Term>& terms) const
6608
{
6609
  CVC5_API_TRY_CATCH_BEGIN;
6610
6
  CVC5_API_CHECK(!d_slv->isQueryMade()
6611
                 || d_slv->getOptions().base.incrementalSolving)
6612
      << "Cannot make multiple queries unless incremental solving is enabled "
6613
         "(try --incremental)";
6614
6
  CVC5_API_SOLVER_CHECK_TERMS(terms);
6615
  //////// all checks before this line
6616
4
  return d_slv->checkEntailed(Term::termVectorToNodes(terms));
6617
  ////////
6618
  CVC5_API_TRY_CATCH_END;
6619
}
6620
6621
/* SMT-LIB commands                                                           */
6622
/* -------------------------------------------------------------------------- */
6623
6624
81237
void Solver::assertFormula(const Term& term) const
6625
{
6626
  CVC5_API_TRY_CATCH_BEGIN;
6627
81237
  CVC5_API_SOLVER_CHECK_TERM(term);
6628
81233
  CVC5_API_SOLVER_CHECK_TERM_WITH_SORT(term, getBooleanSort());
6629
  //////// all checks before this line
6630
81233
  d_slv->assertFormula(*term.d_node);
6631
  ////////
6632
1
  CVC5_API_TRY_CATCH_END;
6633
81232
}
6634
6635
9534
Result Solver::checkSat(void) const
6636
{
6637
  CVC5_API_TRY_CATCH_BEGIN;
6638
9536
  CVC5_API_CHECK(!d_slv->isQueryMade()
6639
                 || d_slv->getOptions().base.incrementalSolving)
6640
      << "Cannot make multiple queries unless incremental solving is enabled "
6641
2
         "(try --incremental)";
6642
  //////// all checks before this line
6643
9532
  return d_slv->checkSat();
6644
  ////////
6645
  CVC5_API_TRY_CATCH_END;
6646
}
6647
6648
34
Result Solver::checkSatAssuming(const Term& assumption) const
6649
{
6650
  CVC5_API_TRY_CATCH_BEGIN;
6651
36
  CVC5_API_CHECK(!d_slv->isQueryMade()
6652
                 || d_slv->getOptions().base.incrementalSolving)
6653
      << "Cannot make multiple queries unless incremental solving is enabled "
6654
2
         "(try --incremental)";
6655
32
  CVC5_API_SOLVER_CHECK_TERM_WITH_SORT(assumption, getBooleanSort());
6656
  //////// all checks before this line
6657
22
  return d_slv->checkSat(*assumption.d_node);
6658
  ////////
6659
  CVC5_API_TRY_CATCH_END;
6660
}
6661
6662
1569
Result Solver::checkSatAssuming(const std::vector<Term>& assumptions) const
6663
{
6664
  CVC5_API_TRY_CATCH_BEGIN;
6665
1569
  CVC5_API_CHECK(!d_slv->isQueryMade() || assumptions.size() == 0
6666
                 || d_slv->getOptions().base.incrementalSolving)
6667
      << "Cannot make multiple queries unless incremental solving is enabled "
6668
         "(try --incremental)";
6669
1569
  CVC5_API_SOLVER_CHECK_TERMS_WITH_SORT(assumptions, getBooleanSort());
6670
  //////// all checks before this line
6671
3168
  for (const Term& term : assumptions)
6672
  {
6673
1601
    CVC5_API_SOLVER_CHECK_TERM(term);
6674
  }
6675
3134
  std::vector<Node> eassumptions = Term::termVectorToNodes(assumptions);
6676
3131
  return d_slv->checkSat(eassumptions);
6677
  ////////
6678
  CVC5_API_TRY_CATCH_END;
6679
}
6680
6681
12
Sort Solver::declareDatatype(
6682
    const std::string& symbol,
6683
    const std::vector<DatatypeConstructorDecl>& ctors) const
6684
{
6685
  CVC5_API_TRY_CATCH_BEGIN;
6686
16
  CVC5_API_ARG_CHECK_EXPECTED(ctors.size() > 0, ctors)
6687
4
      << "a datatype declaration with at least one constructor";
6688
8
  CVC5_API_SOLVER_CHECK_DTCTORDECLS(ctors);
6689
  //////// all checks before this line
6690
12
  DatatypeDecl dtdecl(this, symbol);
6691
16
  for (size_t i = 0, size = ctors.size(); i < size; i++)
6692
  {
6693
10
    dtdecl.addConstructor(ctors[i]);
6694
  }
6695
12
  return Sort(this, getNodeManager()->mkDatatypeType(*dtdecl.d_dtype));
6696
  ////////
6697
  CVC5_API_TRY_CATCH_END;
6698
}
6699
6700
36
Term Solver::declareFun(const std::string& symbol,
6701
                        const std::vector<Sort>& sorts,
6702
                        const Sort& sort) const
6703
{
6704
  CVC5_API_TRY_CATCH_BEGIN;
6705
36
  CVC5_API_SOLVER_CHECK_DOMAIN_SORTS(sorts);
6706
36
  CVC5_API_SOLVER_CHECK_CODOMAIN_SORT(sort);
6707
  //////// all checks before this line
6708
6709
60
  TypeNode type = *sort.d_type;
6710
30
  if (!sorts.empty())
6711
  {
6712
56
    std::vector<TypeNode> types = Sort::sortVectorToTypeNodes(sorts);
6713
28
    type = getNodeManager()->mkFunctionType(types, type);
6714
  }
6715
60
  return Term(this, d_nodeMgr->mkVar(symbol, type));
6716
  ////////
6717
  CVC5_API_TRY_CATCH_END;
6718
}
6719
6720
6
Sort Solver::declareSort(const std::string& symbol, uint32_t arity) const
6721
{
6722
  CVC5_API_TRY_CATCH_BEGIN;
6723
  //////// all checks before this line
6724
6
  if (arity == 0)
6725
  {
6726
2
    return Sort(this, getNodeManager()->mkSort(symbol));
6727
  }
6728
4
  return Sort(this, getNodeManager()->mkSortConstructor(symbol, arity));
6729
  ////////
6730
  CVC5_API_TRY_CATCH_END;
6731
}
6732
6733
7497
Term Solver::defineFun(const std::string& symbol,
6734
                       const std::vector<Term>& bound_vars,
6735
                       const Sort& sort,
6736
                       const Term& term,
6737
                       bool global) const
6738
{
6739
  CVC5_API_TRY_CATCH_BEGIN;
6740
7497
  CVC5_API_SOLVER_CHECK_CODOMAIN_SORT(sort);
6741
7491
  CVC5_API_SOLVER_CHECK_TERM(term);
6742
7489
  CVC5_API_CHECK(term.getSort().isSubsortOf(sort))
6743
2
      << "Invalid sort of function body '" << term << "', expected '" << sort
6744
2
      << "'";
6745
6746
14970
  std::vector<Sort> domain_sorts;
6747
11819
  for (const auto& bv : bound_vars)
6748
  {
6749
4334
    domain_sorts.push_back(bv.getSort());
6750
  }
6751
  Sort fun_sort =
6752
7485
      domain_sorts.empty()
6753
          ? sort
6754
          : Sort(this,
6755
10457
                 getNodeManager()->mkFunctionType(
6756
25427
                     Sort::sortVectorToTypeNodes(domain_sorts), *sort.d_type));
6757
14970
  Term fun = mkConst(fun_sort, symbol);
6758
6759
7485
  CVC5_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bound_vars, domain_sorts);
6760
  //////// all checks before this line
6761
6762
29916
  d_slv->defineFunction(
6763
22437
      *fun.d_node, Term::termVectorToNodes(bound_vars), *term.d_node, global);
6764
14958
  return fun;
6765
  ////////
6766
  CVC5_API_TRY_CATCH_END;
6767
}
6768
6769
32
Term Solver::defineFunRec(const std::string& symbol,
6770
                          const std::vector<Term>& bound_vars,
6771
                          const Sort& sort,
6772
                          const Term& term,
6773
                          bool global) const
6774
{
6775
  CVC5_API_TRY_CATCH_BEGIN;
6776
6777
34
  CVC5_API_CHECK(d_slv->getUserLogicInfo().isQuantified())
6778
2
      << "recursive function definitions require a logic with quantifiers";
6779
30
  CVC5_API_CHECK(d_slv->getUserLogicInfo().isTheoryEnabled(theory::THEORY_UF))
6780
      << "recursive function definitions require a logic with uninterpreted "
6781
         "functions";
6782
6783
30
  CVC5_API_SOLVER_CHECK_TERM(term);
6784
26
  CVC5_API_SOLVER_CHECK_CODOMAIN_SORT(sort);
6785
22
  CVC5_API_CHECK(sort == term.getSort())
6786
2
      << "Invalid sort of function body '" << term << "', expected '" << sort
6787
2
      << "'";
6788
6789
36
  std::vector<Sort> domain_sorts;
6790
42
  for (const auto& bv : bound_vars)
6791
  {
6792
24
    domain_sorts.push_back(bv.getSort());
6793
  }
6794
  Sort fun_sort =
6795
18
      domain_sorts.empty()
6796
          ? sort
6797
          : Sort(this,
6798
42
                 getNodeManager()->mkFunctionType(
6799
78
                     Sort::sortVectorToTypeNodes(domain_sorts), *sort.d_type));
6800
36
  Term fun = mkConst(fun_sort, symbol);
6801
6802
18
  CVC5_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bound_vars, domain_sorts);
6803
  //////// all checks before this line
6804
6805
48
  d_slv->defineFunctionRec(
6806
36
      *fun.d_node, Term::termVectorToNodes(bound_vars), *term.d_node, global);
6807
6808
24
  return fun;
6809
  ////////
6810
  CVC5_API_TRY_CATCH_END;
6811
}
6812
6813
16
Term Solver::defineFunRec(const Term& fun,
6814
                          const std::vector<Term>& bound_vars,
6815
                          const Term& term,
6816
                          bool global) const
6817
{
6818
  CVC5_API_TRY_CATCH_BEGIN;
6819
6820
18
  CVC5_API_CHECK(d_slv->getUserLogicInfo().isQuantified())
6821
2
      << "recursive function definitions require a logic with quantifiers";
6822
14
  CVC5_API_CHECK(d_slv->getUserLogicInfo().isTheoryEnabled(theory::THEORY_UF))
6823
      << "recursive function definitions require a logic with uninterpreted "
6824
         "functions";
6825
6826
14
  CVC5_API_SOLVER_CHECK_TERM(fun);
6827
14
  CVC5_API_SOLVER_CHECK_TERM(term);
6828
14
  if (fun.getSort().isFunction())
6829
  {
6830
24
    std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
6831
12
    CVC5_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bound_vars, domain_sorts);
6832
16
    Sort codomain = fun.getSort().getFunctionCodomainSort();
6833
12
    CVC5_API_CHECK(codomain == term.getSort())
6834
4
        << "Invalid sort of function body '" << term << "', expected '"
6835
4
        << codomain << "'";
6836
  }
6837
  else
6838
  {
6839
2
    CVC5_API_SOLVER_CHECK_BOUND_VARS(bound_vars);
6840
4
    CVC5_API_ARG_CHECK_EXPECTED(bound_vars.size() == 0, fun)
6841
2
        << "function or nullary symbol";
6842
  }
6843
  //////// all checks before this line
6844
6845
8
  std::vector<Node> ebound_vars = Term::termVectorToNodes(bound_vars);
6846
4
  d_slv->defineFunctionRec(*fun.d_node, ebound_vars, *term.d_node, global);
6847
8
  return fun;
6848
  ////////
6849
  CVC5_API_TRY_CATCH_END;
6850
}
6851
6852
160
void Solver::defineFunsRec(const std::vector<Term>& funs,
6853
                           const std::vector<std::vector<Term>>& bound_vars,
6854
                           const std::vector<Term>& terms,
6855
                           bool global) const
6856
{
6857
  CVC5_API_TRY_CATCH_BEGIN;
6858
6859
165
  CVC5_API_CHECK(d_slv->getUserLogicInfo().isQuantified())
6860
5
      << "recursive function definitions require a logic with quantifiers";
6861
155
  CVC5_API_CHECK(d_slv->getUserLogicInfo().isTheoryEnabled(theory::THEORY_UF))
6862
      << "recursive function definitions require a logic with uninterpreted "
6863
         "functions";
6864
155
  CVC5_API_SOLVER_CHECK_TERMS(funs);
6865
151
  CVC5_API_SOLVER_CHECK_TERMS(terms);
6866
6867
147
  size_t funs_size = funs.size();
6868
147
  CVC5_API_ARG_SIZE_CHECK_EXPECTED(funs_size == bound_vars.size(), bound_vars)
6869
      << "'" << funs_size << "'";
6870
147
  CVC5_API_ARG_SIZE_CHECK_EXPECTED(funs_size == terms.size(), terms)
6871
      << "'" << funs_size << "'";
6872
6873
335
  for (size_t j = 0; j < funs_size; ++j)
6874
  {
6875
204
    const Term& fun = funs[j];
6876
204
    const std::vector<Term>& bvars = bound_vars[j];
6877
204
    const Term& term = terms[j];
6878
6879
204
    CVC5_API_ARG_AT_INDEX_CHECK_EXPECTED(
6880
        this == fun.d_solver, "function", funs, j)
6881
        << "function associated with this solver object";
6882
204
    CVC5_API_ARG_AT_INDEX_CHECK_EXPECTED(
6883
        this == term.d_solver, "term", terms, j)
6884
        << "term associated with this solver object";
6885
6886
204
    if (fun.getSort().isFunction())
6887
    {
6888
374
      std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
6889
187
      CVC5_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bvars, domain_sorts);
6890
350
      Sort codomain = fun.getSort().getFunctionCodomainSort();
6891
179
      CVC5_API_ARG_AT_INDEX_CHECK_EXPECTED(
6892
          codomain == term.getSort(), "sort of function body", terms, j)
6893
4
          << "'" << codomain << "'";
6894
    }
6895
    else
6896
    {
6897
17
      CVC5_API_SOLVER_CHECK_BOUND_VARS(bvars);
6898
19
      CVC5_API_ARG_CHECK_EXPECTED(bvars.size() == 0, fun)
6899
2
          << "function or nullary symbol";
6900
    }
6901
  }
6902
  //////// all checks before this line
6903
262
  std::vector<Node> efuns = Term::termVectorToNodes(funs);
6904
262
  std::vector<std::vector<Node>> ebound_vars;
6905
313
  for (const auto& v : bound_vars)
6906
  {
6907
182
    ebound_vars.push_back(Term::termVectorToNodes(v));
6908
  }
6909
262
  std::vector<Node> nodes = Term::termVectorToNodes(terms);
6910
131
  d_slv->defineFunctionsRec(efuns, ebound_vars, nodes, global);
6911
  ////////
6912
  CVC5_API_TRY_CATCH_END;
6913
131
}
6914
6915
void Solver::echo(std::ostream& out, const std::string& str) const
6916
{
6917
  out << str;
6918
}
6919
6920
std::vector<Term> Solver::getAssertions(void) const
6921
{
6922
  CVC5_API_TRY_CATCH_BEGIN;
6923
  //////// all checks before this line
6924
  std::vector<Node> assertions = d_slv->getAssertions();
6925
  /* Can not use
6926
   *   return std::vector<Term>(assertions.begin(), assertions.end());
6927
   * here since constructor is private */
6928
  std::vector<Term> res;
6929
  for (const Node& e : assertions)
6930
  {
6931
    res.push_back(Term(this, e));
6932
  }
6933
  return res;
6934
  ////////
6935
  CVC5_API_TRY_CATCH_END;
6936
}
6937
6938
24
std::string Solver::getInfo(const std::string& flag) const
6939
{
6940
  CVC5_API_TRY_CATCH_BEGIN;
6941
30
  CVC5_API_UNSUPPORTED_CHECK(d_slv->isValidGetInfoFlag(flag))
6942
6
      << "Unrecognized flag: " << flag << ".";
6943
  //////// all checks before this line
6944
18
  return d_slv->getInfo(flag);
6945
  ////////
6946
  CVC5_API_TRY_CATCH_END;
6947
}
6948
6949
1268357
std::string Solver::getOption(const std::string& option) const
6950
{
6951
  try
6952
  {
6953
1268357
    return d_slv->getOption(option);
6954
  }
6955
4
  catch (OptionException& e)
6956
  {
6957
2
    throw CVC5ApiUnsupportedException(e.getMessage());
6958
  }
6959
}
6960
6961
// Supports a visitor from a list of lambdas
6962
// Taken from https://en.cppreference.com/w/cpp/utility/variant/visit
6963
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
6964
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
6965
6966
1762904
bool OptionInfo::boolValue() const
6967
{
6968
  CVC5_API_TRY_CATCH_BEGIN;
6969
1762904
  CVC5_API_RECOVERABLE_CHECK(std::holds_alternative<ValueInfo<bool>>(valueInfo))
6970
      << name << " is not a bool option";
6971
  //////// all checks before this line
6972
1762904
  return std::get<ValueInfo<bool>>(valueInfo).currentValue;
6973
  ////////
6974
  CVC5_API_TRY_CATCH_END;
6975
}
6976
9
std::string OptionInfo::stringValue() const
6977
{
6978
  CVC5_API_TRY_CATCH_BEGIN;
6979
9
  CVC5_API_RECOVERABLE_CHECK(
6980
      std::holds_alternative<ValueInfo<std::string>>(valueInfo))
6981
      << name << " is not a string option";
6982
  //////// all checks before this line
6983
9
  return std::get<ValueInfo<std::string>>(valueInfo).currentValue;
6984
  ////////
6985
  CVC5_API_TRY_CATCH_END;
6986
}
6987
242401
int64_t OptionInfo::intValue() const
6988
{
6989
  CVC5_API_TRY_CATCH_BEGIN;
6990
242401
  CVC5_API_RECOVERABLE_CHECK(
6991
      std::holds_alternative<NumberInfo<int64_t>>(valueInfo))
6992
      << name << " is not an int option";
6993
  //////// all checks before this line
6994
242401
  return std::get<NumberInfo<int64_t>>(valueInfo).currentValue;
6995
  ////////
6996
  CVC5_API_TRY_CATCH_END;
6997
}
6998
6581
uint64_t OptionInfo::uintValue() const
6999
{
7000
  CVC5_API_TRY_CATCH_BEGIN;
7001
6581
  CVC5_API_RECOVERABLE_CHECK(
7002
      std::holds_alternative<NumberInfo<uint64_t>>(valueInfo))
7003
      << name << " is not a uint option";
7004
  //////// all checks before this line
7005
6581
  return std::get<NumberInfo<uint64_t>>(valueInfo).currentValue;
7006
  ////////
7007
  CVC5_API_TRY_CATCH_END;
7008
}
7009
2
double OptionInfo::doubleValue() const
7010
{
7011
  CVC5_API_TRY_CATCH_BEGIN;
7012
2
  CVC5_API_RECOVERABLE_CHECK(
7013
      std::holds_alternative<NumberInfo<double>>(valueInfo))
7014
      << name << " is not a double option";
7015
  //////// all checks before this line
7016
2
  return std::get<NumberInfo<double>>(valueInfo).currentValue;
7017
  ////////
7018
  CVC5_API_TRY_CATCH_END;
7019
}
7020
7021
std::ostream& operator<<(std::ostream& os, const OptionInfo& oi)
7022
{
7023
  os << "OptionInfo{ " << oi.name;
7024
  if (oi.setByUser)
7025
  {
7026
    os << " | set by user";
7027
  }
7028
  if (!oi.aliases.empty())
7029
  {
7030
    container_to_stream(os, oi.aliases, ", ", "", ", ");
7031
  }
7032
  auto printNum = [&os](const std::string& type, const auto& vi) {
7033
    os << " | " << type << " | " << vi.currentValue << " | default "
7034
       << vi.defaultValue;
7035
    if (vi.minimum || vi.maximum)
7036
    {
7037
      os << " |";
7038
      if (vi.minimum)
7039
      {
7040
        os << " " << *vi.minimum << " <=";
7041
      }
7042
      os << " x";
7043
      if (vi.maximum)
7044
      {
7045
        os << " <= " << *vi.maximum;
7046
      }
7047
    }
7048
  };
7049
  std::visit(overloaded{
7050
                 [&os](const OptionInfo::VoidInfo& vi) { os << " | void"; },
7051
                 [&os](const OptionInfo::ValueInfo<bool>& vi) {
7052
                   os << " | bool | " << vi.currentValue << " | default "
7053
                      << vi.defaultValue;
7054
                 },
7055
                 [&os](const OptionInfo::ValueInfo<std::string>& vi) {
7056
                   os << " | string | " << vi.currentValue << " | default "
7057
                      << vi.defaultValue;
7058
                 },
7059
                 [&printNum](const OptionInfo::NumberInfo<int64_t>& vi) {
7060
                   printNum("int64_t", vi);
7061
                 },
7062
                 [&printNum](const OptionInfo::NumberInfo<uint64_t>& vi) {
7063
                   printNum("uint64_t", vi);
7064
                 },
7065
                 [&printNum](const OptionInfo::NumberInfo<double>& vi) {
7066
                   printNum("double", vi);
7067
                 },
7068
                 [&os](const OptionInfo::ModeInfo& vi) {
7069
                   os << " | mode | " << vi.currentValue << " | default "
7070
                      << vi.defaultValue << " | modes: ";
7071
                   container_to_stream(os, vi.modes, "", "", ", ");
7072
                 },
7073
             },
7074
             oi.valueInfo);
7075
  os << " }";
7076
  return os;
7077
}
7078
7079
2
std::vector<std::string> Solver::getOptionNames() const
7080
{
7081
  CVC5_API_TRY_CATCH_BEGIN;
7082
  //////// all checks before this line
7083
2
  return options::getNames();
7084
  ////////
7085
  CVC5_API_TRY_CATCH_END;
7086
}
7087
7088
2031780
OptionInfo Solver::getOptionInfo(const std::string& option) const
7089
{
7090
  CVC5_API_TRY_CATCH_BEGIN;
7091
  //////// all checks before this line
7092
4063560
  auto info = options::getInfo(d_slv->getOptions(), option);
7093
2031782
  CVC5_API_CHECK(info.name != "")
7094
2
      << "Querying invalid or unknown option " << option;
7095
  return std::visit(
7096
4063556
      overloaded{
7097
8
          [&info](const options::OptionInfo::VoidInfo& vi) {
7098
            return OptionInfo{info.name,
7099
                              info.aliases,
7100
2
                              info.setByUser,
7101
                              OptionInfo::VoidInfo{}};
7102
8
          },
7103
7104264
          [&info](const options::OptionInfo::ValueInfo<bool>& vi) {
7104
            return OptionInfo{
7105
                info.name,
7106
                info.aliases,
7107
1776066
                info.setByUser,
7108
3552132
                OptionInfo::ValueInfo<bool>{vi.defaultValue, vi.currentValue}};
7109
10656396
          },
7110
26896
          [&info](const options::OptionInfo::ValueInfo<std::string>& vi) {
7111
            return OptionInfo{info.name,
7112
                              info.aliases,
7113
6724
                              info.setByUser,
7114
13448
                              OptionInfo::ValueInfo<std::string>{
7115
                                  vi.defaultValue, vi.currentValue}};
7116
40344
          },
7117
969604
          [&info](const options::OptionInfo::NumberInfo<int64_t>& vi) {
7118
            return OptionInfo{
7119
                info.name,
7120
                info.aliases,
7121
242401
                info.setByUser,
7122
727203
                OptionInfo::NumberInfo<int64_t>{
7123
484802
                    vi.defaultValue, vi.currentValue, vi.minimum, vi.maximum}};
7124
1454406
          },
7125
26324
          [&info](const options::OptionInfo::NumberInfo<uint64_t>& vi) {
7126
            return OptionInfo{
7127
                info.name,
7128
                info.aliases,
7129
6581
                info.setByUser,
7130
19743
                OptionInfo::NumberInfo<uint64_t>{
7131
13162
                    vi.defaultValue, vi.currentValue, vi.minimum, vi.maximum}};
7132
39486
          },
7133
8
          [&info](const options::OptionInfo::NumberInfo<double>& vi) {
7134
            return OptionInfo{
7135
                info.name,
7136
                info.aliases,
7137
2
                info.setByUser,
7138
6
                OptionInfo::NumberInfo<double>{
7139
4
                    vi.defaultValue, vi.currentValue, vi.minimum, vi.maximum}};
7140
12
          },
7141
8
          [&info](const options::OptionInfo::ModeInfo& vi) {
7142
            return OptionInfo{info.name,
7143
                              info.aliases,
7144
2
                              info.setByUser,
7145
4
                              OptionInfo::ModeInfo{
7146
                                  vi.defaultValue, vi.currentValue, vi.modes}};
7147
12
          },
7148
      },
7149
4063556
      info.valueInfo);
7150
  ////////
7151
  CVC5_API_TRY_CATCH_END;
7152
}
7153
7154
271452
DriverOptions Solver::getDriverOptions() const { return DriverOptions(*this); }
7155
7156
22
std::vector<Term> Solver::getUnsatAssumptions(void) const
7157
{
7158
  CVC5_API_TRY_CATCH_BEGIN;
7159
24
  CVC5_API_CHECK(d_slv->getOptions().base.incrementalSolving)
7160
      << "Cannot get unsat assumptions unless incremental solving is enabled "
7161
2
         "(try --incremental)";
7162
22
  CVC5_API_CHECK(d_slv->getOptions().smt.unsatAssumptions)
7163
      << "Cannot get unsat assumptions unless explicitly enabled "
7164
2
         "(try --produce-unsat-assumptions)";
7165
20
  CVC5_API_CHECK(d_slv->getSmtMode() == SmtMode::UNSAT)
7166
2
      << "Cannot get unsat assumptions unless in unsat mode.";
7167
  //////// all checks before this line
7168
7169
32
  std::vector<Node> uassumptions = d_slv->getUnsatAssumptions();
7170
  /* Can not use
7171
   *   return std::vector<Term>(uassumptions.begin(), uassumptions.end());
7172
   * here since constructor is private */
7173
32
  std::vector<Term> res;
7174
32
  for (const Node& n : uassumptions)
7175
  {
7176
16
    res.push_back(Term(this, n));
7177
  }
7178
32
  return res;
7179
  ////////
7180
  CVC5_API_TRY_CATCH_END;
7181
}
7182
7183
20
std::vector<Term> Solver::getUnsatCore(void) const
7184
{
7185
  CVC5_API_TRY_CATCH_BEGIN;
7186
24
  CVC5_API_CHECK(d_slv->getOptions().smt.unsatCores)
7187
      << "Cannot get unsat core unless explicitly enabled "
7188
4
         "(try --produce-unsat-cores)";
7189
18
  CVC5_API_RECOVERABLE_CHECK(d_slv->getSmtMode() == SmtMode::UNSAT)
7190
2
      << "Cannot get unsat core unless in unsat mode.";
7191
  //////// all checks before this line
7192
28
  UnsatCore core = d_slv->getUnsatCore();
7193
  /* Can not use
7194
   *   return std::vector<Term>(core.begin(), core.end());
7195
   * here since constructor is private */
7196
28
  std::vector<Term> res;
7197
341
  for (const Node& e : core)
7198
  {
7199
327
    res.push_back(Term(this, e));
7200
  }
7201
28
  return res;
7202
  ////////
7203
  CVC5_API_TRY_CATCH_END;
7204
}
7205
7206
8
std::map<Term, Term> Solver::getDifficulty() const
7207
{
7208
  CVC5_API_TRY_CATCH_BEGIN;
7209
10
  CVC5_API_RECOVERABLE_CHECK(d_slv->getSmtMode() == SmtMode::UNSAT
7210
                             || d_slv->getSmtMode() == SmtMode::SAT
7211
                             || d_slv->getSmtMode() == SmtMode::SAT_UNKNOWN)
7212
2
      << "Cannot get difficulty unless after a UNSAT, SAT or UNKNOWN response.";
7213
  //////// all checks before this line
7214
12
  std::map<Term, Term> res;
7215
12
  std::map<Node, Node> dmap;
7216
6
  d_slv->getDifficultyMap(dmap);
7217
4
  for (const std::pair<const Node, Node>& d : dmap)
7218
  {
7219
    res[Term(this, d.first)] = Term(this, d.second);
7220
  }
7221
8
  return res;
7222
  ////////
7223
  CVC5_API_TRY_CATCH_END;
7224
}
7225
7226
6
std::string Solver::getProof(void) const
7227
{
7228
  CVC5_API_TRY_CATCH_BEGIN;
7229
6
  CVC5_API_CHECK(d_slv->getOptions().smt.produceProofs)
7230
      << "Cannot get proof unless proofs are enabled (try --produce-proofs)";
7231
6
  CVC5_API_RECOVERABLE_CHECK(d_slv->getSmtMode() == SmtMode::UNSAT)
7232
      << "Cannot get proof unless in unsat mode.";
7233
6
  return d_slv->getProof();
7234
  CVC5_API_TRY_CATCH_END;
7235
}
7236
7237
25
Term Solver::getValue(const Term& term) const
7238
{
7239
  CVC5_API_TRY_CATCH_BEGIN;
7240
29
  CVC5_API_RECOVERABLE_CHECK(d_slv->getOptions().smt.produceModels)
7241
      << "Cannot get value unless model generation is enabled "
7242
4
         "(try --produce-models)";
7243
25
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7244
4
      << "Cannot get value unless after a SAT or UNKNOWN response.";
7245
17
  CVC5_API_SOLVER_CHECK_TERM(term);
7246
17
  CVC5_API_RECOVERABLE_CHECK(term.getSort().isFirstClass())
7247
      << "Cannot get value of a term that is not first class.";
7248
  //////// all checks before this line
7249
17
  return getValueHelper(term);
7250
  ////////
7251
  CVC5_API_TRY_CATCH_END;
7252
}
7253
7254
78
std::vector<Term> Solver::getValue(const std::vector<Term>& terms) const
7255
{
7256
  CVC5_API_TRY_CATCH_BEGIN;
7257
78
  CVC5_API_RECOVERABLE_CHECK(d_slv->getOptions().smt.produceModels)
7258
      << "Cannot get value unless model generation is enabled "
7259
         "(try --produce-models)";
7260
82
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7261
4
      << "Cannot get value unless after a SAT or UNKNOWN response.";
7262
178
  for (const Term& t : terms)
7263
  {
7264
108
    CVC5_API_RECOVERABLE_CHECK(t.getSort().isFirstClass())
7265
2
        << "Cannot get value of a term that is not first class.";
7266
  }
7267
72
  CVC5_API_SOLVER_CHECK_TERMS(terms);
7268
  //////// all checks before this line
7269
7270
144
  std::vector<Term> res;
7271
176
  for (size_t i = 0, n = terms.size(); i < n; ++i)
7272
  {
7273
    /* Can not use emplace_back here since constructor is private. */
7274
104
    res.push_back(getValueHelper(terms[i]));
7275
  }
7276
144
  return res;
7277
  ////////
7278
  CVC5_API_TRY_CATCH_END;
7279
}
7280
7281
14
std::vector<Term> Solver::getModelDomainElements(const Sort& s) const
7282
{
7283
  CVC5_API_TRY_CATCH_BEGIN;
7284
14
  CVC5_API_RECOVERABLE_CHECK(d_slv->getOptions().smt.produceModels)
7285
      << "Cannot get domain elements unless model generation is enabled "
7286
         "(try --produce-models)";
7287
14
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7288
      << "Cannot get domain elements unless after a SAT or UNKNOWN response.";
7289
14
  CVC5_API_SOLVER_CHECK_SORT(s);
7290
16
  CVC5_API_RECOVERABLE_CHECK(s.isUninterpretedSort())
7291
      << "Expecting an uninterpreted sort as argument to "
7292
2
         "getModelDomainElements.";
7293
  //////// all checks before this line
7294
24
  std::vector<Term> res;
7295
24
  std::vector<Node> elements = d_slv->getModelDomainElements(s.getTypeNode());
7296
32
  for (const Node& n : elements)
7297
  {
7298
20
    res.push_back(Term(this, n));
7299
  }
7300
24
  return res;
7301
  ////////
7302
  CVC5_API_TRY_CATCH_END;
7303
}
7304
7305
8
bool Solver::isModelCoreSymbol(const Term& v) const
7306
{
7307
  CVC5_API_TRY_CATCH_BEGIN;
7308
8
  CVC5_API_RECOVERABLE_CHECK(d_slv->getOptions().smt.produceModels)
7309
      << "Cannot check if model core symbol unless model generation is enabled "
7310
         "(try --produce-models)";
7311
8
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7312
      << "Cannot check if model core symbol unless after a SAT or UNKNOWN "
7313
         "response.";
7314
8
  CVC5_API_SOLVER_CHECK_TERM(v);
7315
10
  CVC5_API_RECOVERABLE_CHECK(v.getKind() == CONSTANT)
7316
2
      << "Expecting a free constant as argument to isModelCoreSymbol.";
7317
  //////// all checks before this line
7318
6
  return d_slv->isModelCoreSymbol(v.getNode());
7319
  ////////
7320
  CVC5_API_TRY_CATCH_END;
7321
}
7322
7323
40
std::string Solver::getModel(const std::vector<Sort>& sorts,
7324
                             const std::vector<Term>& vars) const
7325
{
7326
  CVC5_API_TRY_CATCH_BEGIN;
7327
40
  CVC5_API_RECOVERABLE_CHECK(d_slv->getOptions().smt.produceModels)
7328
      << "Cannot get model unless model generation is enabled "
7329
         "(try --produce-models)";
7330
47
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7331
7
      << "Cannot get model unless after a SAT or UNKNOWN response.";
7332
33
  CVC5_API_SOLVER_CHECK_SORTS(sorts);
7333
41
  for (const Sort& s : sorts)
7334
  {
7335
12
    CVC5_API_RECOVERABLE_CHECK(s.isUninterpretedSort())
7336
        << "Expecting an uninterpreted sort as argument to "
7337
2
           "getModel.";
7338
  }
7339
31
  CVC5_API_SOLVER_CHECK_TERMS(vars);
7340
63
  for (const Term& v : vars)
7341
  {
7342
34
    CVC5_API_RECOVERABLE_CHECK(v.getKind() == CONSTANT)
7343
        << "Expecting a free constant as argument to getModel.";
7344
  }
7345
  //////// all checks before this line
7346
58
  return d_slv->getModel(Sort::sortVectorToTypeNodes(sorts),
7347
87
                         Term::termVectorToNodes(vars));
7348
  ////////
7349
  CVC5_API_TRY_CATCH_END;
7350
}
7351
7352
14
Term Solver::getQuantifierElimination(const Term& q) const
7353
{
7354
  CVC5_API_TRY_CATCH_BEGIN;
7355
14
  CVC5_API_SOLVER_CHECK_TERM(q);
7356
  //////// all checks before this line
7357
10
  return Term(this, d_slv->getQuantifierElimination(q.getNode(), true, true));
7358
  ////////
7359
  CVC5_API_TRY_CATCH_END;
7360
}
7361
7362
7
Term Solver::getQuantifierEliminationDisjunct(const Term& q) const
7363
{
7364
  CVC5_API_TRY_CATCH_BEGIN;
7365
7
  CVC5_API_SOLVER_CHECK_TERM(q);
7366
  //////// all checks before this line
7367
3
  return Term(this, d_slv->getQuantifierElimination(q.getNode(), false, true));
7368
  ////////
7369
  CVC5_API_TRY_CATCH_END;
7370
}
7371
7372
99
void Solver::declareSepHeap(const Sort& locSort, const Sort& dataSort) const
7373
{
7374
  CVC5_API_TRY_CATCH_BEGIN;
7375
99
  CVC5_API_SOLVER_CHECK_SORT(locSort);
7376
99
  CVC5_API_SOLVER_CHECK_SORT(dataSort);
7377
99
  CVC5_API_CHECK(d_slv->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP))
7378
      << "Cannot obtain separation logic expressions if not using the "
7379
         "separation logic theory.";
7380
  //////// all checks before this line
7381
101
  d_slv->declareSepHeap(locSort.getTypeNode(), dataSort.getTypeNode());
7382
  ////////
7383
  CVC5_API_TRY_CATCH_END;
7384
97
}
7385
7386
12
Term Solver::getValueSepHeap() const
7387
{
7388
  CVC5_API_TRY_CATCH_BEGIN;
7389
15
  CVC5_API_CHECK(d_slv->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP))
7390
      << "Cannot obtain separation logic expressions if not using the "
7391
3
         "separation logic theory.";
7392
11
  CVC5_API_CHECK(d_slv->getOptions().smt.produceModels)
7393
      << "Cannot get separation heap term unless model generation is enabled "
7394
2
         "(try --produce-models)";
7395
9
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7396
2
      << "Can only get separtion heap term after SAT or UNKNOWN response.";
7397
  //////// all checks before this line
7398
5
  return Term(this, d_slv->getSepHeapExpr());
7399
  ////////
7400
  CVC5_API_TRY_CATCH_END;
7401
}
7402
7403
12
Term Solver::getValueSepNil() const
7404
{
7405
  CVC5_API_TRY_CATCH_BEGIN;
7406
15
  CVC5_API_CHECK(d_slv->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP))
7407
      << "Cannot obtain separation logic expressions if not using the "
7408
3
         "separation logic theory.";
7409
11
  CVC5_API_CHECK(d_slv->getOptions().smt.produceModels)
7410
      << "Cannot get separation nil term unless model generation is enabled "
7411
2
         "(try --produce-models)";
7412
9
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7413
2
      << "Can only get separtion nil term after SAT or UNKNOWN response.";
7414
  //////// all checks before this line
7415
5
  return Term(this, d_slv->getSepNilExpr());
7416
  ////////
7417
  CVC5_API_TRY_CATCH_END;
7418
}
7419
7420
7
Term Solver::declarePool(const std::string& symbol,
7421
                         const Sort& sort,
7422
                         const std::vector<Term>& initValue) const
7423
{
7424
  CVC5_API_TRY_CATCH_BEGIN;
7425
7
  CVC5_API_SOLVER_CHECK_SORT(sort);
7426
5
  CVC5_API_SOLVER_CHECK_TERMS(initValue);
7427
  //////// all checks before this line
7428
10
  TypeNode setType = getNodeManager()->mkSetType(*sort.d_type);
7429
10
  Node pool = getNodeManager()->mkBoundVar(symbol, setType);
7430
10
  std::vector<Node> initv = Term::termVectorToNodes(initValue);
7431
5
  d_slv->declarePool(pool, initv);
7432
10
  return Term(this, pool);
7433
  ////////
7434
  CVC5_API_TRY_CATCH_END;
7435
}
7436
7437
2888
void Solver::pop(uint32_t nscopes) const
7438
{
7439
  CVC5_API_TRY_CATCH_BEGIN;
7440
2890
  CVC5_API_CHECK(d_slv->getOptions().base.incrementalSolving)
7441
2
      << "Cannot pop when not solving incrementally (use --incremental)";
7442
2890
  CVC5_API_CHECK(nscopes <= d_slv->getNumUserLevels())
7443
4
      << "Cannot pop beyond first pushed context";
7444
  //////// all checks before this line
7445
5764
  for (uint32_t n = 0; n < nscopes; ++n)
7446
  {
7447
2882
    d_slv->pop();
7448
  }
7449
  ////////
7450
  CVC5_API_TRY_CATCH_END;
7451
2882
}
7452
7453
9
bool Solver::getInterpolant(const Term& conj, Term& output) const
7454
{
7455
  CVC5_API_TRY_CATCH_BEGIN;
7456
9
  CVC5_API_SOLVER_CHECK_TERM(conj);
7457
  //////// all checks before this line
7458
18
  Node result;
7459
9
  bool success = d_slv->getInterpol(*conj.d_node, result);
7460
9
  if (success)
7461
  {
7462
9
    output = Term(this, result);
7463
  }
7464
18
  return success;
7465
  ////////
7466
  CVC5_API_TRY_CATCH_END;
7467
}
7468
7469
1
bool Solver::getInterpolant(const Term& conj,
7470
                            Grammar& grammar,
7471
                            Term& output) const
7472
{
7473
  CVC5_API_TRY_CATCH_BEGIN;
7474
1
  CVC5_API_SOLVER_CHECK_TERM(conj);
7475
  //////// all checks before this line
7476
2
  Node result;
7477
  bool success =
7478
1
      d_slv->getInterpol(*conj.d_node, *grammar.resolve().d_type, result);
7479
1
  if (success)
7480
  {
7481
1
    output = Term(this, result);
7482
  }
7483
2
  return success;
7484
  ////////
7485
  CVC5_API_TRY_CATCH_END;
7486
}
7487
7488
34
bool Solver::getAbduct(const Term& conj, Term& output) const
7489
{
7490
  CVC5_API_TRY_CATCH_BEGIN;
7491
34
  CVC5_API_SOLVER_CHECK_TERM(conj);
7492
36
  CVC5_API_CHECK(d_slv->getOptions().smt.produceAbducts)
7493
2
      << "Cannot get abduct unless abducts are enabled (try --produce-abducts)";
7494
  //////// all checks before this line
7495
64
  Node result;
7496
32
  bool success = d_slv->getAbduct(*conj.d_node, result);
7497
30
  if (success)
7498
  {
7499
26
    output = Term(this, result);
7500
  }
7501
60
  return success;
7502
  ////////
7503
  CVC5_API_TRY_CATCH_END;
7504
}
7505
7506
10
bool Solver::getAbduct(const Term& conj, Grammar& grammar, Term& output) const
7507
{
7508
  CVC5_API_TRY_CATCH_BEGIN;
7509
10
  CVC5_API_SOLVER_CHECK_TERM(conj);
7510
10
  CVC5_API_CHECK(d_slv->getOptions().smt.produceAbducts)
7511
      << "Cannot get abduct unless abducts are enabled (try --produce-abducts)";
7512
  //////// all checks before this line
7513
20
  Node result;
7514
  bool success =
7515
12
      d_slv->getAbduct(*conj.d_node, *grammar.resolve().d_type, result);
7516
8
  if (success)
7517
  {
7518
8
    output = Term(this, result);
7519
  }
7520
16
  return success;
7521
  ////////
7522
  CVC5_API_TRY_CATCH_END;
7523
}
7524
7525
22
void Solver::blockModel() const
7526
{
7527
  CVC5_API_TRY_CATCH_BEGIN;
7528
24
  CVC5_API_CHECK(d_slv->getOptions().smt.produceModels)
7529
      << "Cannot get value unless model generation is enabled "
7530
2
         "(try --produce-models)";
7531
22
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7532
2
      << "Can only block model after SAT or UNKNOWN response.";
7533
  //////// all checks before this line
7534
18
  d_slv->blockModel();
7535
  ////////
7536
  CVC5_API_TRY_CATCH_END;
7537
16
}
7538
7539
22
void Solver::blockModelValues(const std::vector<Term>& terms) const
7540
{
7541
  CVC5_API_TRY_CATCH_BEGIN;
7542
24
  CVC5_API_CHECK(d_slv->getOptions().smt.produceModels)
7543
      << "Cannot get value unless model generation is enabled "
7544
2
         "(try --produce-models)";
7545
22
  CVC5_API_RECOVERABLE_CHECK(d_slv->isSmtModeSat())
7546
2
      << "Can only block model values after SAT or UNKNOWN response.";
7547
20
  CVC5_API_ARG_SIZE_CHECK_EXPECTED(!terms.empty(), terms)
7548
2
      << "a non-empty set of terms";
7549
16
  CVC5_API_SOLVER_CHECK_TERMS(terms);
7550
  //////// all checks before this line
7551
14
  d_slv->blockModelValues(Term::termVectorToNodes(terms));
7552
  ////////
7553
  CVC5_API_TRY_CATCH_END;
7554
10
}
7555
7556
15
void Solver::printInstantiations(std::ostream& out) const
7557
{
7558
  CVC5_API_TRY_CATCH_BEGIN;
7559
  //////// all checks before this line
7560
15
  d_slv->printInstantiations(out);
7561
  ////////
7562
  CVC5_API_TRY_CATCH_END;
7563
15
}
7564
7565
3430
void Solver::push(uint32_t nscopes) const
7566
{
7567
  CVC5_API_TRY_CATCH_BEGIN;
7568
3432
  CVC5_API_CHECK(d_slv->getOptions().base.incrementalSolving)
7569
2
      << "Cannot push when not solving incrementally (use --incremental)";
7570
  //////// all checks before this line
7571
6862
  for (uint32_t n = 0; n < nscopes; ++n)
7572
  {
7573
3434
    d_slv->push();
7574
  }
7575
  ////////
7576
  CVC5_API_TRY_CATCH_END;
7577
3428
}
7578
7579
43
void Solver::resetAssertions(void) const
7580
{
7581
  CVC5_API_TRY_CATCH_BEGIN;
7582
  //////// all checks before this line
7583
43
  d_slv->resetAssertions();
7584
  ////////
7585
  CVC5_API_TRY_CATCH_END;
7586
43
}
7587
7588
12491
void Solver::setInfo(const std::string& keyword, const std::string& value) const
7589
{
7590
  CVC5_API_TRY_CATCH_BEGIN;
7591
12509
  CVC5_API_UNSUPPORTED_CHECK(
7592
      keyword == "source" || keyword == "category" || keyword == "difficulty"
7593
      || keyword == "filename" || keyword == "license" || keyword == "name"
7594
      || keyword == "notes" || keyword == "smt-lib-version"
7595
      || keyword == "status")
7596
      << "Unrecognized keyword: " << keyword
7597
      << ", expected 'source', 'category', 'difficulty', "
7598
         "'filename', 'license', 'name', "
7599
18
         "'notes', 'smt-lib-version' or 'status'";
7600
12475
  CVC5_API_RECOVERABLE_ARG_CHECK_EXPECTED(
7601
      keyword != "smt-lib-version" || value == "2" || value == "2.0"
7602
          || value == "2.5" || value == "2.6",
7603
      value)
7604
2
      << "'2.0', '2.5', '2.6'";
7605
12473
  CVC5_API_ARG_CHECK_EXPECTED(keyword != "status" || value == "sat"
7606
                                  || value == "unsat" || value == "unknown",
7607
                              value)
7608
2
      << "'sat', 'unsat' or 'unknown'";
7609
  //////// all checks before this line
7610
12469
  d_slv->setInfo(keyword, value);
7611
  ////////
7612
  CVC5_API_TRY_CATCH_END;
7613
12469
}
7614
7615
6658
void Solver::setLogic(const std::string& logic) const
7616
{
7617
  CVC5_API_TRY_CATCH_BEGIN;
7618
6660
  CVC5_API_CHECK(!d_slv->isFullyInited())
7619
2
      << "Invalid call to 'setLogic', solver is already fully initialized";
7620
13312
  cvc5::LogicInfo logic_info(logic);
7621
  //////// all checks before this line
7622
6654
  d_slv->setLogic(logic_info);
7623
  ////////
7624
  CVC5_API_TRY_CATCH_END;
7625
6654
}
7626
7627
39629
void Solver::setOption(const std::string& option,
7628
                       const std::string& value) const
7629
{
7630
  CVC5_API_TRY_CATCH_BEGIN;
7631
76529
  std::vector<std::string> options = options::getNames();
7632
39629
  CVC5_API_UNSUPPORTED_CHECK(
7633
      option.find("command-verbosity") != std::string::npos
7634
      || std::find(options.cbegin(), options.cend(), option) != options.cend())
7635
      << "Unrecognized option: " << option << '.';
7636
  static constexpr auto mutableOpts = {"diagnostic-output-channel",
7637
                                       "print-success",
7638
                                       "regular-output-channel",
7639
                                       "reproducible-resource-limit",
7640
                                       "verbosity"};
7641
79258
  if (std::find(mutableOpts.begin(), mutableOpts.end(), option)
7642
39629
      == mutableOpts.end())
7643
  {
7644
39599
    CVC5_API_CHECK(!d_slv->isFullyInited())
7645
        << "Invalid call to 'setOption' for option '" << option
7646
8
        << "', solver is already fully initialized";
7647
  }
7648
  //////// all checks before this line
7649
39621
  d_slv->setOption(option, value);
7650
  ////////
7651
2
  CVC5_API_TRY_CATCH_END;
7652
36890
}
7653
7654
633
Term Solver::mkSygusVar(const Sort& sort, const std::string& symbol) const
7655
{
7656
  CVC5_API_TRY_CATCH_BEGIN;
7657
633
  CVC5_API_SOLVER_CHECK_SORT(sort);
7658
  //////// all checks before this line
7659
1254
  Node res = getNodeManager()->mkBoundVar(symbol, *sort.d_type);
7660
627
  (void)res.getType(true); /* kick off type checking */
7661
7662
627
  d_slv->declareSygusVar(res);
7663
7664
1254
  return Term(this, res);
7665
  ////////
7666
  CVC5_API_TRY_CATCH_END;
7667
}
7668
7669
327
Grammar Solver::mkSygusGrammar(const std::vector<Term>& boundVars,
7670
                               const std::vector<Term>& ntSymbols) const
7671
{
7672
  CVC5_API_TRY_CATCH_BEGIN;
7673
329
  CVC5_API_ARG_SIZE_CHECK_EXPECTED(!ntSymbols.empty(), ntSymbols)
7674
2
      << "a non-empty vector";
7675
325
  CVC5_API_SOLVER_CHECK_BOUND_VARS(boundVars);
7676
321
  CVC5_API_SOLVER_CHECK_BOUND_VARS(ntSymbols);
7677
  //////// all checks before this line
7678
315
  return Grammar(this, boundVars, ntSymbols);
7679
  ////////
7680
  CVC5_API_TRY_CATCH_END;
7681
}
7682
7683
394
Term Solver::synthFun(const std::string& symbol,
7684
                      const std::vector<Term>& boundVars,
7685
                      const Sort& sort) const
7686
{
7687
  CVC5_API_TRY_CATCH_BEGIN;
7688
394
  CVC5_API_SOLVER_CHECK_BOUND_VARS(boundVars);
7689
390
  CVC5_API_SOLVER_CHECK_SORT(sort);
7690
  //////// all checks before this line
7691
386
  return synthFunHelper(symbol, boundVars, sort);
7692
  ////////
7693
  CVC5_API_TRY_CATCH_END;
7694
}
7695
7696
290
Term Solver::synthFun(const std::string& symbol,
7697
                      const std::vector<Term>& boundVars,
7698
                      Sort sort,
7699
                      Grammar& grammar) const
7700
{
7701
  CVC5_API_TRY_CATCH_BEGIN;
7702
290
  CVC5_API_SOLVER_CHECK_BOUND_VARS(boundVars);
7703
290
  CVC5_API_SOLVER_CHECK_SORT(sort);
7704
  //////// all checks before this line
7705
290
  return synthFunHelper(symbol, boundVars, sort, false, &grammar);
7706
  ////////
7707
  CVC5_API_TRY_CATCH_END;
7708
}
7709
7710
33
Term Solver::synthInv(const std::string& symbol,
7711
                      const std::vector<Term>& boundVars) const
7712
{
7713
  CVC5_API_TRY_CATCH_BEGIN;
7714
33
  CVC5_API_SOLVER_CHECK_BOUND_VARS(boundVars);
7715
  //////// all checks before this line
7716
  return synthFunHelper(
7717
31
      symbol, boundVars, Sort(this, getNodeManager()->booleanType()), true);
7718
  ////////
7719
  CVC5_API_TRY_CATCH_END;
7720
}
7721
7722
4
Term Solver::synthInv(const std::string& symbol,
7723
                      const std::vector<Term>& boundVars,
7724
                      Grammar& grammar) const
7725
{
7726
  CVC5_API_TRY_CATCH_BEGIN;
7727
4
  CVC5_API_SOLVER_CHECK_BOUND_VARS(boundVars);
7728
  //////// all checks before this line
7729
  return synthFunHelper(symbol,
7730
                        boundVars,
7731
8
                        Sort(this, getNodeManager()->booleanType()),
7732
                        true,
7733
6
                        &grammar);
7734
  ////////
7735
  CVC5_API_TRY_CATCH_END;
7736
}
7737
7738
1254
void Solver::addSygusConstraint(const Term& term) const
7739
{
7740
  CVC5_API_TRY_CATCH_BEGIN;
7741
1254
  CVC5_API_SOLVER_CHECK_TERM(term);
7742
1252
  CVC5_API_ARG_CHECK_EXPECTED(
7743
      term.d_node->getType() == getNodeManager()->booleanType(), term)
7744
2
      << "boolean term";
7745
  //////// all checks before this line
7746
1248
  d_slv->assertSygusConstraint(*term.d_node, false);
7747
  ////////
7748
  CVC5_API_TRY_CATCH_END;
7749
1248
}
7750
7751
12
void Solver::addSygusAssume(const Term& term) const
7752
{
7753
  CVC5_API_TRY_CATCH_BEGIN;
7754
12
  CVC5_API_SOLVER_CHECK_TERM(term);
7755
10
  CVC5_API_ARG_CHECK_EXPECTED(
7756
      term.d_node->getType() == getNodeManager()->booleanType(), term)
7757
2
      << "boolean term";
7758
  //////// all checks before this line
7759
6
  d_slv->assertSygusConstraint(*term.d_node, true);
7760
  ////////
7761
  CVC5_API_TRY_CATCH_END;
7762
6
}
7763
7764
65
void Solver::addSygusInvConstraint(Term inv,
7765
                                   Term pre,
7766
                                   Term trans,
7767
                                   Term post) const
7768
{
7769
  CVC5_API_TRY_CATCH_BEGIN;
7770
65
  CVC5_API_SOLVER_CHECK_TERM(inv);
7771
61
  CVC5_API_SOLVER_CHECK_TERM(pre);
7772
57
  CVC5_API_SOLVER_CHECK_TERM(trans);
7773
53
  CVC5_API_SOLVER_CHECK_TERM(post);
7774
7775
51
  CVC5_API_ARG_CHECK_EXPECTED(inv.d_node->getType().isFunction(), inv)
7776
2
      << "a function";
7777
7778
94
  TypeNode invType = inv.d_node->getType();
7779
7780
49
  CVC5_API_ARG_CHECK_EXPECTED(invType.getRangeType().isBoolean(), inv)
7781
2
      << "boolean range";
7782
7783
47
  CVC5_API_CHECK(pre.d_node->getType() == invType)
7784
2
      << "Expected inv and pre to have the same sort";
7785
7786
45
  CVC5_API_CHECK(post.d_node->getType() == invType)
7787
2
      << "Expected inv and post to have the same sort";
7788
  //////// all checks before this line
7789
7790
82
  const std::vector<TypeNode>& invArgTypes = invType.getArgTypes();
7791
7792
82
  std::vector<TypeNode> expectedTypes;
7793
41
  expectedTypes.reserve(2 * invArgTypes.size() + 1);
7794
7795
240
  for (size_t i = 0, n = invArgTypes.size(); i < 2 * n; i += 2)
7796
  {
7797
199
    expectedTypes.push_back(invArgTypes[i % n]);
7798
199
    expectedTypes.push_back(invArgTypes[(i + 1) % n]);
7799
  }
7800
7801
41
  expectedTypes.push_back(invType.getRangeType());
7802
82
  TypeNode expectedTransType = getNodeManager()->mkFunctionType(expectedTypes);
7803
7804
51
  CVC5_API_CHECK(trans.d_node->getType() == expectedTransType)
7805
10
      << "Expected trans's sort to be " << invType;
7806
7807
155
  d_slv->assertSygusInvConstraint(
7808
124
      *inv.d_node, *pre.d_node, *trans.d_node, *post.d_node);
7809
  ////////
7810
  CVC5_API_TRY_CATCH_END;
7811
31
}
7812
7813
382
Result Solver::checkSynth() const
7814
{
7815
  CVC5_API_TRY_CATCH_BEGIN;
7816
  //////// all checks before this line
7817
382
  return d_slv->checkSynth();
7818
  ////////
7819
  CVC5_API_TRY_CATCH_END;
7820
}
7821
7822
22
Term Solver::getSynthSolution(Term term) const
7823
{
7824
  CVC5_API_TRY_CATCH_BEGIN;
7825
22
  CVC5_API_SOLVER_CHECK_TERM(term);
7826
7827
36
  std::map<cvc5::Node, cvc5::Node> map;
7828
18
  CVC5_API_CHECK(d_slv->getSynthSolutions(map))
7829
      << "The solver is not in a state immediately preceded by a "
7830
         "successful call to checkSynth";
7831
7832
18
  std::map<cvc5::Node, cvc5::Node>::const_iterator it = map.find(*term.d_node);
7833
7834
18
  CVC5_API_CHECK(it != map.cend()) << "Synth solution not found for given term";
7835
  //////// all checks before this line
7836
28
  return Term(this, it->second);
7837
  ////////
7838
  CVC5_API_TRY_CATCH_END;
7839
}
7840
7841
16
std::vector<Term> Solver::getSynthSolutions(
7842
    const std::vector<Term>& terms) const
7843
{
7844
  CVC5_API_TRY_CATCH_BEGIN;
7845
16
  CVC5_API_ARG_SIZE_CHECK_EXPECTED(!terms.empty(), terms) << "non-empty vector";
7846
12
  CVC5_API_SOLVER_CHECK_TERMS(terms);
7847
7848
16
  std::map<cvc5::Node, cvc5::Node> map;
7849
8
  CVC5_API_CHECK(d_slv->getSynthSolutions(map))
7850
      << "The solver is not in a state immediately preceded by a "
7851
         "successful call to checkSynth";
7852
  //////// all checks before this line
7853
7854
16
  std::vector<Term> synthSolution;
7855
8
  synthSolution.reserve(terms.size());
7856
7857
14
  for (size_t i = 0, n = terms.size(); i < n; ++i)
7858
  {
7859
    std::map<cvc5::Node, cvc5::Node>::const_iterator it =
7860
10
        map.find(*terms[i].d_node);
7861
7862
14
    CVC5_API_CHECK(it != map.cend())
7863
4
        << "Synth solution not found for term at index " << i;
7864
7865
6
    synthSolution.push_back(Term(this, it->second));
7866
  }
7867
7868
8
  return synthSolution;
7869
  ////////
7870
  CVC5_API_TRY_CATCH_END;
7871
}
7872
7873
Statistics Solver::getStatistics() const
7874
{
7875
  return Statistics(d_slv->getStatisticsRegistry());
7876
}
7877
7878
242434
bool Solver::isOutputOn(const std::string& tag) const
7879
{
7880
  // `isOutputOn(tag)` may raise an `OptionException`, which we do not want to
7881
  // forward as such. We thus do not use the standard exception handling macros
7882
  // here but roll our own.
7883
  try
7884
  {
7885
242434
    return d_slv->getEnv().isOutputOn(tag);
7886
  }
7887
4
  catch (const cvc5::Exception& e)
7888
  {
7889
2
    throw CVC5ApiException("Invalid output tag " + tag);
7890
  }
7891
}
7892
7893
27
std::ostream& Solver::getOutput(const std::string& tag) const
7894
{
7895
  // `output(tag)` may raise an `OptionException`, which we do not want to
7896
  // forward as such. We thus do not use the standard exception handling macros
7897
  // here but roll our own.
7898
  try
7899
  {
7900
27
    return d_slv->getEnv().output(tag);
7901
  }
7902
4
  catch (const cvc5::Exception& e)
7903
  {
7904
2
    throw CVC5ApiException("Invalid output tag " + tag);
7905
  }
7906
}
7907
7908
}  // namespace api
7909
7910
}  // namespace cvc5
7911
7912
namespace std {
7913
7914
20088735
size_t hash<cvc5::api::Kind>::operator()(cvc5::api::Kind k) const
7915
{
7916
20088735
  return static_cast<size_t>(k);
7917
}
7918
7919
size_t hash<cvc5::api::Op>::operator()(const cvc5::api::Op& t) const
7920
{
7921
  if (t.isIndexedHelper())
7922
  {
7923
    return std::hash<cvc5::Node>()(*t.d_node);
7924
  }
7925
  else
7926
  {
7927
    return std::hash<cvc5::api::Kind>()(t.d_kind);
7928
  }
7929
}
7930
7931
78109
size_t std::hash<cvc5::api::RoundingMode>::operator()(
7932
    cvc5::api::RoundingMode rm) const
7933
{
7934
78109
  return static_cast<size_t>(rm);
7935
}
7936
7937
size_t std::hash<cvc5::api::Sort>::operator()(const cvc5::api::Sort& s) const
7938
{
7939
  return std::hash<cvc5::TypeNode>()(*s.d_type);
7940
}
7941
7942
2931645
size_t std::hash<cvc5::api::Term>::operator()(const cvc5::api::Term& t) const
7943
{
7944
2931645
  return std::hash<cvc5::Node>()(*t.d_node);
7945
}
7946
7947
31137
}  // namespace std