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