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