GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/api/cpp/cvc5.cpp Lines: 2614 3440 76.0 %
Date: 2021-09-07 Branches: 7049 25902 27.2 %

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