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