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