GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/api/cpp/cvc5.cpp Lines: 2511 3341 75.2 %
Date: 2021-09-29 Branches: 6869 25590 26.8 %

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