GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/api/cpp/cvc5.cpp Lines: 2638 3467 76.1 %
Date: 2021-09-15 Branches: 7117 26062 27.3 %

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