GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/api/cpp/cvc5.cpp Lines: 2520 3301 76.3 %
Date: 2021-08-14 Branches: 6930 25330 27.4 %

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