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