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