SMTStabilizer API
Public API documentation for SMTStabilizer
Loading...
Searching...
No Matches
op_parser.cpp
Go to the documentation of this file.
1/* -*- Source -*-
2 *
3 * An SMT/OMT Parser (Operator part)
4 *
5 * Author: Fuqi Jia <jiafq@ios.ac.cn>
6 *
7 * Copyright (C) 2025 Fuqi Jia
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27
28// Modified by Xiang Zhang, 2026
29// Additional changes licensed under the MIT License
30#include <algorithm>
31#include <memory>
32#include <queue>
33#include <stack>
34#include <vector>
35
36#include "parser.h"
37#include "parser/dag.h"
38#include "parser/kind.h"
39#include "parser/sort.h"
40#include "util.h"
41
42namespace stabilizer::parser {
43
44bool isIntParam(std::shared_ptr<DAGNode> param) {
45 auto sort = param->getSort();
46 return sort && (sort->isInt() || sort->isIntOrReal());
47}
48bool isRealParam(std::shared_ptr<DAGNode> param) {
49 auto sort = param->getSort();
50 return sort && (sort->isReal() || sort->isIntOrReal());
51}
52bool isBoolParam(std::shared_ptr<DAGNode> param) {
53 auto sort = param->getSort();
54 return sort && sort->isBool();
55}
56bool isBvParam(std::shared_ptr<DAGNode> param) {
57 auto sort = param->getSort();
58 return sort && sort->isBv();
59}
60bool isFpParam(std::shared_ptr<DAGNode> param) {
61 auto sort = param->getSort();
62 return sort && sort->isFp();
63}
64bool isStrParam(std::shared_ptr<DAGNode> param) {
65 auto sort = param->getSort();
66 return sort && sort->isStr();
67}
68bool isRegParam(std::shared_ptr<DAGNode> param) {
69 auto sort = param->getSort();
70 return sort && sort->isReg();
71}
72bool isArrayParam(std::shared_ptr<DAGNode> param) {
73 auto sort = param->getSort();
74 return sort && sort->isArray();
75}
76
77// mk operations
78std::shared_ptr<DAGNode> Parser::mkTrue() { return NodeManager::TRUE_NODE; }
79std::shared_ptr<DAGNode> Parser::mkFalse() { return NodeManager::FALSE_NODE; }
80std::shared_ptr<DAGNode> Parser::mkUnknown() {
82}
83// mk oper
85 switch (t) {
111
116 // case NODE_KIND::NT_SUB:
117 // case NODE_KIND::NT_DIV_REAL:
118 return true;
119 default:
120 return false;
121 }
122}
123
124bool canExempt(std::shared_ptr<Sort> l, std::shared_ptr<Sort> r) {
125 if ((l->isInt() || l->isReal()) && (r->isInt() || r->isReal())) {
126 return true;
127 }
128 return false;
129}
130std::shared_ptr<Sort>
131Parser::getSort(const std::vector<std::shared_ptr<DAGNode>> &params) {
132 std::shared_ptr<Sort> sort = nullptr;
133 // use the maximum sort only for int/real
134 bool is_int_real_sort = params[0]->getSort()->isInt() ||
135 params[0]->getSort()->isReal() ||
136 params[0]->getSort()->isIntOrReal();
137 if (is_int_real_sort) {
138 for (size_t i = 0; i < params.size(); i++) {
139 if (params[i]->getSort()->isReal()) {
141 break;
142 }
143 }
144 if (sort == nullptr) {
146 }
147 }
148 else {
149 for (size_t i = 0; i < params.size(); i++) {
150 if (!params[i]->isConst()) {
151 sort = params[i]->getSort();
152 break;
153 }
154 }
155 }
156 // all constant -> nullptr
157 return sort;
158}
159std::shared_ptr<Sort> Parser::getSort(std::shared_ptr<DAGNode> param) {
160 return param->getSort();
161}
162std::shared_ptr<Sort> Parser::getSort(std::shared_ptr<DAGNode> l,
163 std::shared_ptr<DAGNode> r) {
164 return getSort({l, r});
165}
166std::shared_ptr<Sort> Parser::getSort(std::shared_ptr<DAGNode> l,
167 std::shared_ptr<DAGNode> r,
168 std::shared_ptr<DAGNode> m) {
169 return getSort({l, r, m});
170}
171
172std::vector<std::shared_ptr<DAGNode>>
173Parser::sortParams(const std::vector<std::shared_ptr<DAGNode>> &p) {
174 // fast path
175 if (p.size() <= 1) {
176 return p;
177 }
178
179 // large case
180 std::vector<std::shared_ptr<DAGNode>> params = p;
181
182 // pre-compute hash code
183 std::vector<std::pair<std::shared_ptr<DAGNode>, size_t>> params_with_hash;
184 params_with_hash.reserve(params.size());
185
186 for (const auto &param : params) {
187 params_with_hash.emplace_back(param, param->hashCode());
188 }
189
190 // sort by hash code
191 std::sort(params_with_hash.begin(), params_with_hash.end(), [](const std::pair<std::shared_ptr<DAGNode>, size_t> &a, const std::pair<std::shared_ptr<DAGNode>, size_t> &b) {
192 if (a.second != b.second)
193 return a.second < b.second;
194 else
195 return a.first < b.first;
196 });
197
198 // extract sorted nodes
199 for (size_t i = 0; i < params_with_hash.size(); i++) {
200 params[i] = params_with_hash[i].first;
201 }
202
203 return params;
204}
205std::shared_ptr<DAGNode> Parser::mkOper(const std::shared_ptr<Sort> &sort,
206 const NODE_KIND &t,
207 std::shared_ptr<DAGNode> p) {
208 std::vector<std::shared_ptr<DAGNode>> params;
209 params.emplace_back(p);
210 return mkOper(sort, t, params);
211}
212std::shared_ptr<DAGNode> Parser::mkOper(const std::shared_ptr<Sort> &sort,
213 const NODE_KIND &t,
214 std::shared_ptr<DAGNode> l,
215 std::shared_ptr<DAGNode> r) {
216 std::vector<std::shared_ptr<DAGNode>> params;
217 params.emplace_back(l);
218 params.emplace_back(r);
219 return mkOper(sort, t, params);
220}
221std::shared_ptr<DAGNode> Parser::mkOper(const std::shared_ptr<Sort> &sort,
222 const NODE_KIND &t,
223 std::shared_ptr<DAGNode> l,
224 std::shared_ptr<DAGNode> m,
225 std::shared_ptr<DAGNode> r) {
226 std::vector<std::shared_ptr<DAGNode>> params;
227 params.emplace_back(l);
228 params.emplace_back(m);
229 params.emplace_back(r);
230 return mkOper(sort, t, params);
231}
232std::shared_ptr<DAGNode>
233Parser::mkOper(const std::shared_ptr<Sort> &sort, const NODE_KIND &t, const std::vector<std::shared_ptr<DAGNode>> &p) {
234 // std::cout << "Creating operation: " << kindToString(t) << std::endl;
235 if (p.size() == 0) {
236 // std::cout << kindToString(t) << std::endl;
237 err_all(ERROR_TYPE::ERR_PARAM_MIS, "No parameters for operation", line_number);
238
239 return mkUnknown();
240 }
241 else if (t == NODE_KIND::NT_FORALL || t == NODE_KIND::NT_EXISTS) {
242 static size_t quant_counter = 0;
243 quant_counter++;
244 for (size_t i = 1, isz = p.size(); i < isz; i++) {
245 p.at(i)->setName("Q" + std::to_string(quant_counter) + "-" +
246 std::to_string(i - 1));
247 }
248 }
249
250 NODE_KIND kind = t;
251 switch (t) {
252 case NODE_KIND::NT_GE:
253 kind = NODE_KIND::NT_LE;
254 break;
256 kind = NODE_KIND::NT_FP_LE;
257 break;
260 break;
263 break;
266 break;
267 case NODE_KIND::NT_GT:
268 kind = NODE_KIND::NT_LT;
269 break;
271 kind = NODE_KIND::NT_FP_LT;
272 break;
275 break;
278 break;
281 break;
282
283 default:
284 return mkInternalOper(sort, t, p);
285 }
286 // std::cout << "Warning: converting " << kindToString(t) << " to " <<
287 // kindToString(kind) << " at line " << line_number << std::endl; std::cout <<
288 // p.size() << std::endl;
289 auto np = p;
290 std::reverse(np.begin(), np.end());
291 return mkInternalOper(sort, kind, np);
292}
293std::shared_ptr<DAGNode>
294Parser::mkInternalOper(const std::shared_ptr<Sort> &sort, const NODE_KIND &t, const std::vector<std::shared_ptr<DAGNode>> &p) {
295 // std::cout << "Creating operation: " << kindToString(t) << std::endl;
296 // make the params unique
297 std::vector<std::shared_ptr<DAGNode>> params(p);
298 for (auto &child : params) {
299 if (child->isFuncDef()) {
300 // Found a function definition or declaration, apply it with parameters
301 if (child->getChildrenSize() != 1) {
302 throw std::runtime_error("Error: function " + child->getName() + " is not fully defined.");
303 }
304 child = child->getFuncBody();
305 }
306 }
307 auto nt = t;
308 auto result = rewrite_oper(nt, params);
309 // auto result = nullptr;
310 if (result != nullptr)
311 return result;
312
313 if (isCommutative(t)) {
314 switch (t) {
319 std::vector<std::shared_ptr<DAGNode>> nparams(params.begin() + 1,
320 params.end());
321 nparams = sortParams(nparams);
322 nparams.insert(nparams.begin(), params[0]);
323 params = nparams;
324 break;
325 }
326 default:
327 params = sortParams(params);
328 break;
329 }
330 }
331 // if (t == NODE_KIND::NT_BV_NOT) {
332 // std::cout << p.at(0)->toString() << ' ' <<
333 // p.at(0)->getChild(0)->getSort()->toString() << std::endl;
334 // }
335 // auto result = nullptr;
336 // std::cout << kindToString(nt) << ' ' << static_cast<size_t>(nt) << ' ' <<
337 // params.size() << std::endl;
338 if (result != nullptr)
339 return result;
340 else
341 return node_manager->createNode(sort, nt, kindToString(nt), params);
342}
343
344// mk function
345std::shared_ptr<DAGNode>
346Parser::mkFuncDec(const std::string &name,
347 const std::vector<std::shared_ptr<Sort>> &params,
348 std::shared_ptr<Sort> out_sort) {
349 if (fun_key_map.find(name) != fun_key_map.end()) {
350 // // multiple declarations
351 // err_all(ERROR_TYPE::ERR_MUL_DECL, "Multiple declarations of function",
352 // line_number); return mkUnknown();
353 fun_dup_count_map[name]++;
354 std::string new_name =
355 name + "_dup_" + std::to_string(fun_dup_count_map[name]);
356 std::vector<std::shared_ptr<DAGNode>> children;
357 for (auto &param : params) {
358 // TODO, a random name and not record it.
359 std::shared_ptr<DAGNode> param_node = node_manager->createNode(
360 param, NODE_KIND::NT_FUNC_PARAM, param->toString());
361 children.emplace_back(param_node);
362 }
363 // add a NodeManager::NULL_NODE to represent the function body.
364 children.insert(children.begin(), NodeManager::NULL_NODE);
365
366 std::shared_ptr<DAGNode> func = node_manager->createNode(
367 out_sort, NODE_KIND::NT_FUNC_DEC, new_name, children);
368
369 fun_key_map.insert(std::pair<std::string, std::shared_ptr<DAGNode>>(
370 new_name, fun_key_map.at(name)));
371 fun_key_map.at(name) = func;
372 return func;
373 }
374 else {
375 // create a new function
376 // children: params
377 // out_sort: return sort
378 std::vector<std::shared_ptr<DAGNode>> children;
379 for (auto &param : params) {
380 // TODO, a random name and not record it.
381 std::shared_ptr<DAGNode> param_node = node_manager->createNode(
382 param, NODE_KIND::NT_FUNC_PARAM, param->toString());
383 children.emplace_back(param_node);
384 }
385 // add a NodeManager::NULL_NODE to represent the function body.
386 children.insert(children.begin(), NodeManager::NULL_NODE);
387
388 std::shared_ptr<DAGNode> func = node_manager->createNode(
389 out_sort, NODE_KIND::NT_FUNC_DEC, name, children);
390 fun_key_map.insert(
391 std::pair<std::string, std::shared_ptr<DAGNode>>(name, func));
392 return func;
393 }
394}
395
396std::shared_ptr<DAGNode>
397Parser::mkFuncDef(const std::string &name,
398 const std::vector<std::shared_ptr<DAGNode>> &params,
399 std::shared_ptr<Sort> out_sort,
400 std::shared_ptr<DAGNode> body) {
401 std::shared_ptr<DAGNode> func = nullptr;
402 if (fun_key_map.find(name) != fun_key_map.end()) {
403 func = fun_key_map[name];
404 condAssert(func->getKind() == NODE_KIND::NT_FUNC_DEC,
405 "mkFuncDef: func is not a function declaration");
406 // NOTE: we still check it, even if it is not necessary.
407 if (func->getKind() == NODE_KIND::NT_FUNC_DEC) {
408 // update the function
409 func = fun_key_map[name];
410 func->updateFuncDef(out_sort, body, params);
411 return func;
412 }
413 else {
414 // multiple definitions
415 err_all(ERROR_TYPE::ERR_MUL_DEF, "Multiple definitions of function", line_number);
416 return mkUnknown();
417 }
418 }
419 else {
420 // create a new function
421 // children: params
422 // out_sort: return sort
423 // body: function body
424 std::vector<std::shared_ptr<DAGNode>> children;
425 children.emplace_back(body);
426 for (auto &param : params) {
427 children.emplace_back(param);
428 }
429 std::shared_ptr<DAGNode> func = node_manager->createNode(
430 out_sort, NODE_KIND::NT_FUNC_DEF, name, children);
431 fun_key_map.insert(
432 std::pair<std::string, std::shared_ptr<DAGNode>>(name, func));
433 return func;
434 }
435}
436
437std::shared_ptr<DAGNode>
438Parser::mkFuncRec(const std::string &name,
439 const std::vector<std::shared_ptr<DAGNode>> &params,
440 std::shared_ptr<Sort> out_sort,
441 std::shared_ptr<DAGNode> body) {
442 std::shared_ptr<DAGNode> func = nullptr;
443 if (fun_key_map.find(name) != fun_key_map.end()) {
444 func = fun_key_map[name];
445 condAssert(func->getKind() == NODE_KIND::NT_FUNC_DEC,
446 "mkFuncRec: func is not a function declaration");
447 // NOTE: we still check it, even if it is not necessary.
448 if (func->getKind() == NODE_KIND::NT_FUNC_DEC) {
449 // update the function to recursive function
450 func = fun_key_map[name];
451 func->updateFuncDef(out_sort, body, params, true);
452 return func;
453 }
454 else {
455 // multiple definitions
457 "Multiple definitions of recursive function",
459 return mkUnknown();
460 }
461 }
462 else {
463 // create a new recursive function
464 // children: params
465 // out_sort: return sort
466 // body: function body
467 std::vector<std::shared_ptr<DAGNode>> children;
468 children.emplace_back(body);
469 for (auto &param : params) {
470 children.emplace_back(param);
471 }
472 std::shared_ptr<DAGNode> func = node_manager->createNode(
473 out_sort, NODE_KIND::NT_FUNC_REC, name, children);
474 fun_key_map.insert(
475 std::pair<std::string, std::shared_ptr<DAGNode>>(name, func));
476 return func;
477 }
478}
479
480std::shared_ptr<Sort> Parser::mkSortDec(const std::string &name,
481 const size_t &arity) {
482 return sort_manager->createSortDec(name, arity);
483}
484
485std::shared_ptr<Sort>
486Parser::mkSortDef(const std::string &name,
487 const std::vector<std::shared_ptr<Sort>> &params,
488 std::shared_ptr<Sort> out_sort) {
489 return sort_manager->createSortDef(name, params, out_sort);
490}
491std::shared_ptr<Sort> Parser::mkIntSort() { return SortManager::INT_SORT; }
492std::shared_ptr<Sort> Parser::mkRealSort() { return SortManager::REAL_SORT; }
493std::shared_ptr<Sort> Parser::mkBoolSort() { return SortManager::BOOL_SORT; }
494std::shared_ptr<Sort> Parser::mkStrSort() { return SortManager::STR_SORT; }
495std::shared_ptr<Sort> Parser::mkRegSort() { return SortManager::REG_SORT; }
496std::shared_ptr<Sort> Parser::mkRoundingModeSort() {
498}
499std::shared_ptr<Sort> Parser::mkNatSort() { return SortManager::NAT_SORT; }
500std::shared_ptr<Sort> Parser::mkBVSort(const size_t &width) {
501 return sort_manager->createBVSort(width);
502}
503std::shared_ptr<Sort> Parser::mkFPSort(const size_t &e, const size_t &s) {
504 return sort_manager->createFPSort(e, s);
505}
506std::shared_ptr<Sort> Parser::mkArraySort(std::shared_ptr<Sort> index,
507 std::shared_ptr<Sort> elem) {
508 return sort_manager->createArraySort(index, elem);
509}
510
511// CORE OPERATORS
512std::shared_ptr<DAGNode>
513Parser::mkEq(const std::vector<std::shared_ptr<DAGNode>> &params) {
514 if (params.size() < 2) {
515 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for equality", line_number);
516 return mkUnknown();
517 }
518 std::shared_ptr<Sort> sort = getSort(params);
519
520 // if (params.size() == 2) {
521 // return mkEq(params[0], params[1]);
522 // }
523
524 std::vector<std::shared_ptr<DAGNode>> new_params;
525
526 for (size_t i = 0; i < params.size(); i++) {
527 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
528 if (canExempt(params[i]->getSort(), sort)) {
529 std::cerr << "Type mismatch in eq, but now exempt for int/real"
530 << std::endl;
531 }
532 else {
533 err_all(params[i], "Type mismatch in equality", line_number);
534 return mkUnknown();
535 }
536 }
537 if (params[i]->isTrue()) {
538 // x = true => x
539 continue;
540 }
541 else {
542 new_params.emplace_back(params[i]);
543 }
544 }
545
546 if (new_params.size() == 0) {
547 // all true constant
548 return mkTrue();
549 }
550 else if (new_params.size() == 1) {
551 // only one uncertain param
552 return new_params[0];
553 }
554 else {
555 // if (new_params.size() > 100) {
556 // // [OPTIMIZE] have not use mkOper, because it will sort parameters
557 // return node_manager->createNode(SortManager::BOOL_SORT,
558 // NODE_KIND::NT_EQ, "eq", new_params);
559 // }
560 // else {
562 // }
563 }
564}
565
566std::shared_ptr<DAGNode>
567Parser::mkDistinct(const std::vector<std::shared_ptr<DAGNode>> &params) {
568 if (params.size() < 2) {
569 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for distinct", line_number);
570 return mkUnknown();
571 }
572 std::shared_ptr<Sort> sort = getSort(params);
573
574 std::vector<std::shared_ptr<DAGNode>> new_params;
575
576 for (size_t i = 0; i < params.size(); i++) {
577 if (params[i]->isErr())
578 return params[i];
579 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
580 if (canExempt(params[i]->getSort(), sort)) {
581 std::cerr << "Type mismatch in distinct, but now exempt for int/real"
582 << std::endl;
583 }
584 else {
585 err_all(params[i], "Type mismatch in distinct", line_number);
586 return mkUnknown();
587 }
588 }
589 if (params[i]->isFalse()) {
590 // x != False => x
591 continue;
592 }
593 else {
594 new_params.emplace_back(params[i]);
595 }
596 }
597
598 if (new_params.size() == 0) {
599 // all false constant
600 return mkFalse();
601 }
602 else if (new_params.size() == 1) {
603 // only one uncertain param
604 return new_params[0];
605 }
606 else {
607 // // for large distinct, create node directly without sorting parameters
608 // // the semantics of distinct does not depend on the order of parameters,
609 // and sorting is too expensive if (new_params.size() > 100) {
610 // // [OPTIMIZE] have not use mkOper, because it will sort parameters
611 // return node_manager->createNode(SortManager::BOOL_SORT,
612 // NODE_KIND::NT_DISTINCT, "distinct", new_params);
613 // }
614 // else {
616 // }
617 }
618}
619// CONST
620std::shared_ptr<DAGNode> Parser::declareVar(const std::string &name,
621 const std::string &sort) {
622 return mkVar(sort_key_map[sort], name);
623}
624std::shared_ptr<DAGNode> Parser::declareVar(const std::string &name,
625 const std::shared_ptr<Sort> &sort) {
626 return mkVar(sort, name);
627}
628
629// LET
630std::shared_ptr<DAGNode>
631Parser::mkLetBindVar(const std::string &name,
632 const std::shared_ptr<DAGNode> &expr) {
633 if (preserving_let_key_map.find(name) != preserving_let_key_map.end()) {
634 // multiple declarations
635 return preserving_let_key_map[name];
636 }
637 else {
638 std::vector<std::shared_ptr<DAGNode>> children;
639 children.emplace_back(expr);
640 std::shared_ptr<DAGNode> new_var = node_manager->createNode(
641 expr->getSort(), NODE_KIND::NT_LET_BIND_VAR, name, children);
643 std::pair<std::string, std::shared_ptr<DAGNode>>(name, new_var));
644 return new_var;
645 }
646}
647
648std::shared_ptr<DAGNode> Parser::mkLetBindVarList(
649 const std::vector<std::shared_ptr<DAGNode>> &bind_vars) {
650 // empty is allowed
651
652 // Use the sort of the first binding variable for the list
653 std::shared_ptr<Sort> list_sort = bind_vars[0]->getSort();
654 return node_manager->createNode(list_sort, NODE_KIND::NT_LET_BIND_VAR_LIST, "", bind_vars);
655}
656
657std::shared_ptr<DAGNode>
658Parser::mkLetChain(const std::vector<std::shared_ptr<DAGNode>> &bind_var_lists,
659 const std::shared_ptr<DAGNode> &body) {
660 if (!body) {
662 }
663
664 // Create children: [bind_var_lists..., body]
665 std::vector<std::shared_ptr<DAGNode>> children;
666 for (const auto &list : bind_var_lists) {
667 children.emplace_back(list);
668 }
669 children.emplace_back(body);
670
671 return node_manager->createNode(body->getSort(), NODE_KIND::NT_LET_CHAIN, "", children);
672}
673
674std::shared_ptr<DAGNode> Parser::mkConstInt(const Integer &v) {
675 std::string v_str = ConversionUtils::toString(v);
676 return node_manager->createNode(SortManager::INTOREAL_SORT,
678 v_str);
679}
680std::shared_ptr<DAGNode> Parser::mkConstInt(const std::string &v) {
681 return mkConstInt(Integer(v));
682}
683std::shared_ptr<DAGNode> Parser::mkConstInt(const int &v) {
684 return mkConstInt(Integer(v));
685}
686std::shared_ptr<DAGNode> Parser::mkConstInt(const Number &v) {
687 return mkConstInt(v.toInteger());
688}
689std::shared_ptr<DAGNode> Parser::mkConstReal(const std::string &v) {
690 condAssert(TypeChecker::isReal(v) || v == "e" || v == "pi",
691 "mkConstReal: invalid real constant");
692 if (v == "e")
693 return NodeManager::E_NODE;
694 if (v == "pi")
697}
698std::shared_ptr<DAGNode> Parser::mkConstReal(const Real &v) {
699 std::string v_str = ConversionUtils::toString(v);
700 return node_manager->createNode(SortManager::REAL_SORT, NODE_KIND::NT_CONST, v_str);
701}
702std::shared_ptr<DAGNode> Parser::mkConstReal(const double &v) {
703 std::string v_str = std::to_string(v);
704 return node_manager->createNode(SortManager::REAL_SORT, NODE_KIND::NT_CONST, v_str);
705}
706std::shared_ptr<DAGNode> Parser::mkConstReal(const Integer &v) {
707 std::string v_str = ConversionUtils::toString(v);
708 return node_manager->createNode(SortManager::REAL_SORT, NODE_KIND::NT_CONST, v_str);
709}
710std::shared_ptr<DAGNode> Parser::mkConstReal(const Number &v) {
711 return mkConstReal(v.toReal());
712}
713std::shared_ptr<DAGNode> Parser::mkConstStr(const std::string &v) {
714 // process the escape characters in the string
715 std::string processed_v = v;
716
717 // if the string is quoted, remove the quotes
718 // if (v.length() >= 2 && v[0] == '"' && v[v.length() - 1] == '"') {
719 // processed_v = ConversionUtils::unescapeString(v.substr(1, v.length() - 2));
720 // processed_v = "\"" + ConversionUtils::escapeString(processed_v) + "\"";
721 // }
722 // else
723 // processed_v = "\"" + ConversionUtils::escapeString(processed_v) + "\"";
724
725 return node_manager->createNode(SortManager::STR_SORT, NODE_KIND::NT_CONST, processed_v);
726}
727std::shared_ptr<DAGNode> Parser::mkConstBv(const std::string &v,
728 const size_t &width) {
729 std::string sort_key_name = "BV_" + std::to_string(width);
730 std::shared_ptr<Sort> sort = nullptr;
731 if (sort_key_map.find(sort_key_name) == sort_key_map.end()) {
732 sort = sort_manager->createBVSort(width);
733 sort_key_map.insert(
734 std::pair<std::string, std::shared_ptr<Sort>>(sort_key_name, sort));
735 }
736 else {
737 sort = sort_key_map[sort_key_name];
738 }
739 std::string bv_v = BitVectorUtils::natToBv(v, width);
740 return node_manager->createNode(sort, NODE_KIND::NT_CONST, bv_v);
741}
742std::shared_ptr<DAGNode> Parser::mkConstFp(const std::string &v,
743 const size_t &e,
744 const size_t &s) {
745 std::string sort_key_name =
746 "FP_" + std::to_string(e) + "_" + std::to_string(s);
747 std::shared_ptr<Sort> sort = nullptr;
748 if (sort_key_map.find(sort_key_name) == sort_key_map.end()) {
749 sort = sort_manager->createFPSort(e, s);
750 sort_key_map.insert(
751 std::pair<std::string, std::shared_ptr<Sort>>(sort_key_name, sort));
752 }
753 else {
754 sort = sort_key_map[sort_key_name];
755 }
756 return node_manager->createNode(sort, NODE_KIND::NT_CONST, v);
757}
758std::shared_ptr<DAGNode> Parser::mkConstFP(const std::string &fp_expr) {
759 return node_manager->createNode(nullptr, NODE_KIND::NT_CONST, fp_expr);
760}
761std::shared_ptr<DAGNode> Parser::mkConstReg(const std::string &v) {
763}
764
765std::shared_ptr<DAGNode> Parser::mkRoundingMode(const std::string &mode) {
766 // Create a special sort for rounding mode
767 std::shared_ptr<Sort> rounding_mode_sort = SortManager::ROUNDING_MODE_SORT;
768 return node_manager->createNode(rounding_mode_sort, NODE_KIND::NT_CONST, mode);
769}
770
771// VAR
772std::shared_ptr<DAGNode> Parser::mkTempVar(const std::shared_ptr<Sort> &sort) {
773 std::string temp_var_name = "temp_" + std::to_string(temp_var_counter++);
774 if (temp_var_names.find(temp_var_name) != temp_var_names.end()) {
775 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Temp variable name already exists", line_number);
776 return mkUnknown();
777 }
778 std::shared_ptr<DAGNode> newvar =
779 node_manager->createNode(sort, NODE_KIND::NT_TEMP_VAR, temp_var_name);
780 temp_var_names.insert(std::pair<std::string, size_t>(
781 temp_var_name, node_manager->getIndex(newvar)));
782 return newvar;
783}
784std::shared_ptr<DAGNode> Parser::mkVar(const std::shared_ptr<Sort> &sort,
785 const std::string &name) {
786 if (var_names.find(name) != var_names.end()) {
787 // multiple declarations
788 return node_manager->getNode(var_names[name]);
789 }
790 else {
791 std::shared_ptr<DAGNode> newvar =
792 node_manager->createNode(sort, NODE_KIND::NT_VAR, name);
793 var_names.insert(
794 std::pair<std::string, size_t>(name, node_manager->getIndex(newvar)));
795 return newvar;
796 }
797}
798
799std::shared_ptr<DAGNode> Parser::mkPlaceholderVar(const std::string &name) {
800 if (placeholder_var_names.find(name) != placeholder_var_names.end()) {
801 // placeholder variable already exists
802 return node_manager->getNode(placeholder_var_names[name]);
803 }
804 else {
805 // Create new placeholder variable with the specified sort
806 std::shared_ptr<Sort> sort =
808 std::shared_ptr<DAGNode> newvar =
809 node_manager->createNode(sort, NODE_KIND::NT_PLACEHOLDER_VAR, name);
810 condAssert(newvar->isPlaceholderVar(),
811 "Created placeholder variable is not a placeholder variable");
813 std::pair<std::string, size_t>(name, node_manager->getIndex(newvar)));
814 return newvar;
815 }
816}
817std::shared_ptr<DAGNode> Parser::mkVarBool(const std::string &name) {
818 return mkVar(SortManager::BOOL_SORT, name);
819}
820std::shared_ptr<DAGNode> Parser::mkVarInt(const std::string &name) {
821 return mkVar(SortManager::INT_SORT, name);
822}
823std::shared_ptr<DAGNode> Parser::mkVarReal(const std::string &name) {
824 return mkVar(SortManager::REAL_SORT, name);
825}
826std::shared_ptr<DAGNode> Parser::mkVarBv(const std::string &name,
827 const size_t &width) {
828 std::string sort_key_name = "BV_" + std::to_string(width);
829 std::shared_ptr<Sort> sort = nullptr;
830 if (sort_key_map.find(sort_key_name) == sort_key_map.end()) {
831 sort = sort_manager->createBVSort(width);
832 sort_key_map.insert(
833 std::pair<std::string, std::shared_ptr<Sort>>(sort_key_name, sort));
834 }
835 else {
836 sort = sort_key_map[sort_key_name];
837 }
838 return mkVar(sort, name);
839}
840std::shared_ptr<DAGNode> Parser::mkVarFp(const std::string &name,
841 const size_t &e,
842 const size_t &s) {
843 std::string sort_key_name =
844 "FP_" + std::to_string(e) + "_" + std::to_string(s);
845 std::shared_ptr<Sort> sort = nullptr;
846 if (sort_key_map.find(sort_key_name) == sort_key_map.end()) {
847 sort = sort_manager->createFPSort(e, s);
848 sort_key_map.insert(
849 std::pair<std::string, std::shared_ptr<Sort>>(sort_key_name, sort));
850 }
851 else {
852 sort = sort_key_map[sort_key_name];
853 }
854 return mkVar(sort, name);
855}
856std::shared_ptr<DAGNode> Parser::mkVarStr(const std::string &name) {
857 return mkVar(SortManager::STR_SORT, name);
858}
859std::shared_ptr<DAGNode> Parser::mkVarReg(const std::string &name) {
860 return mkVar(SortManager::REG_SORT, name);
861}
862std::shared_ptr<DAGNode> Parser::mkVarRoundingMode(const std::string &name) {
863 // Create a special sort for rounding mode
864 std::shared_ptr<Sort> rounding_mode_sort =
865 std::make_shared<Sort>(SORT_KIND::SK_ROUNDING_MODE, "RoundingMode", 0);
866 return mkVar(rounding_mode_sort, name);
867}
868std::shared_ptr<DAGNode> Parser::mkFunParamVar(std::shared_ptr<Sort> sort,
869 const std::string &name) {
870 std::shared_ptr<DAGNode> newvar =
871 node_manager->createNode(sort, NODE_KIND::NT_FUNC_PARAM, name);
872 // do not insert into variables
873 // it is a function parameter
874 return newvar;
875}
876// ARRAY
877std::shared_ptr<DAGNode> Parser::mkArray(const std::string &name,
878 std::shared_ptr<Sort> index,
879 std::shared_ptr<Sort> elem) {
880 std::string sort_key_name =
881 "ARRAY_" + index->toString() + "_" + elem->toString();
882 std::shared_ptr<Sort> sort = nullptr;
883 if (sort_key_map.find(sort_key_name) == sort_key_map.end()) {
884 sort = sort_manager->createArraySort(index, elem);
885 sort_key_map.insert(
886 std::pair<std::string, std::shared_ptr<Sort>>(sort_key_name, sort));
887 }
888 else {
889 sort = sort_key_map[sort_key_name];
890 }
891 return mkVar(sort, name);
892}
893
894/*
895(as const T) value, return Array
896Creates a constant array where all elements have the same value
897*/
898std::shared_ptr<DAGNode> Parser::mkConstArray(std::shared_ptr<Sort> sort,
899 std::shared_ptr<DAGNode> value) {
900 if (!sort->isArray()) {
901 err_all(value, "ConstArray on non-array sort", line_number);
902 return mkUnknown();
903 }
904
905 // Check if value type matches array element type
906 std::shared_ptr<Sort> elem_sort = sort->getElemSort();
907 std::shared_ptr<Sort> value_sort = value->getSort();
908
909 return node_manager->createNode(sort, NODE_KIND::NT_CONST_ARRAY, "const_array", {value});
910}
911
912// BOOLEAN
913/*
914(not Bool), return Bool
915*/
916std::shared_ptr<DAGNode> Parser::mkNot(std::shared_ptr<DAGNode> param) {
917 if (!isBoolParam(param)) {
918 err_all(param, "Negation on non-boolean", line_number);
919 return mkUnknown();
920 }
921 else {
923 }
924}
925
926std::shared_ptr<DAGNode>
927Parser::mkAnd(const std::vector<std::shared_ptr<DAGNode>> &params) {
928 if (params.size() == 0) {
929 std::cerr << "AND on empty parameters, return true" << std::endl;
930 return mkTrue();
931 }
932 else if (params.size() == 1) {
933 return params[0];
934 }
935
936 std::vector<std::shared_ptr<DAGNode>> new_params;
937
938 for (size_t i = 0; i < params.size(); i++) {
939 if (!isBoolParam(params[i])) {
940 err_type_mis("AND on non-boolean", line_number);
941 return mkUnknown();
942 }
943 if (params[i]->isErr()) {
944 return params[i];
945 }
946 else if (params[i]->isTrue()) {
947 // true constant
948 continue;
949 }
950 else if (params[i]->isFalse()) {
951 // false constant
952 return mkFalse();
953 }
954 else {
955 // insert uncertain param
956 new_params.emplace_back(params[i]);
957 }
958 }
959
960 if (new_params.size() == 0) {
961 // all true constant
962 return mkTrue();
963 }
964 else if (new_params.size() == 1) {
965 // only one uncertain param
966 return new_params[0];
967 }
968 else {
969 // make new AND operator
971 }
972}
973
974std::shared_ptr<DAGNode>
975Parser::mkOr(const std::vector<std::shared_ptr<DAGNode>> &params) {
976 if (params.size() == 0) {
977 std::cerr << "OR on empty parameters, return false" << std::endl;
978 return mkFalse();
979 }
980 else if (params.size() == 1) {
981 return params[0];
982 }
983
984 std::vector<std::shared_ptr<DAGNode>> new_params;
985
986 for (size_t i = 0; i < params.size(); i++) {
987 if (!isBoolParam(params[i])) {
988 err_type_mis("OR on non-boolean", line_number);
989 return mkUnknown();
990 }
991 if (params[i]->isErr()) {
992 return params[i];
993 }
994 else if (params[i]->isFalse()) {
995 // false constant
996 continue;
997 }
998 else if (params[i]->isTrue()) {
999 // true constant
1000 return mkTrue();
1001 }
1002 else {
1003 // insert uncertain param
1004 new_params.emplace_back(params[i]);
1005 }
1006 }
1007
1008 if (new_params.size() == 0) {
1009 // all false constant
1010 return mkFalse();
1011 }
1012 else if (new_params.size() == 1) {
1013 // only one uncertain param
1014 return new_params[0];
1015 }
1016 else {
1017 // make new OR operator
1018 return mkOper(SortManager::BOOL_SORT, NODE_KIND::NT_OR, new_params);
1019 }
1020}
1021std::shared_ptr<DAGNode>
1022Parser::mkImplies(const std::vector<std::shared_ptr<DAGNode>> &params) {
1023 if (params.size() < 2) {
1024 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for implies", line_number);
1025 return mkUnknown();
1026 }
1027
1028 std::vector<std::shared_ptr<DAGNode>> new_params;
1029 // (=> a b c d) <=> (or -a -b -c d)
1030 for (size_t i = 0; i < params.size() - 1; i++) {
1031 if (params[i]->isErr())
1032 return params[i];
1033 if (params[i]->isFalse()) {
1034 // -params[i] => true
1035 return mkTrue();
1036 }
1037 else if (params[i]->isTrue()) {
1038 continue;
1039 }
1040 else {
1041 new_params.emplace_back(params[i]);
1042 }
1043 }
1044
1045 if (params.back()->isErr())
1046 return params.back();
1047
1048 if (new_params.size() == 0) {
1049 // all true constant
1050 // true -> params.back() => params.back()
1051 return params.back();
1052 }
1053
1054 new_params.emplace_back(params.back());
1056}
1057
1058std::shared_ptr<DAGNode>
1059Parser::mkXor(const std::vector<std::shared_ptr<DAGNode>> &params) {
1060 if (params.size() == 0) {
1061 std::cerr << "XOR on empty parameters, return false" << std::endl;
1062 return mkFalse();
1063 }
1064 else if (params.size() == 1) {
1065 return params[0];
1066 }
1067
1068 std::vector<std::shared_ptr<DAGNode>> new_params;
1069 for (size_t i = 0; i < params.size(); i++) {
1070 if (params[i]->isErr())
1071 return params[i];
1072 if (params[i]->isFalse()) {
1073 // x xor false = x
1074 continue;
1075 }
1076 else {
1077 new_params.emplace_back(params[i]);
1078 }
1079 }
1080
1081 if (new_params.size() == 0) {
1082 // all false constant
1083 return mkFalse();
1084 }
1085 else if (new_params.size() == 1) {
1086 // only one uncertain param
1087 return new_params[0];
1088 }
1089 else {
1090 return mkOper(SortManager::BOOL_SORT, NODE_KIND::NT_XOR, new_params);
1091 }
1092}
1093/*
1094(ite Bool A A), return A
1095*/
1096std::shared_ptr<DAGNode> Parser::mkIte(std::shared_ptr<DAGNode> cond,
1097 std::shared_ptr<DAGNode> l,
1098 std::shared_ptr<DAGNode> r) {
1099 if (cond->isErr())
1100 return cond;
1101 if (l->isErr())
1102 return l;
1103 if (r->isErr())
1104 return r;
1105 return mkOper(l->getSort(), NODE_KIND::NT_ITE, cond, l, r);
1106}
1107std::shared_ptr<DAGNode>
1108Parser::mkIte(const std::vector<std::shared_ptr<DAGNode>> &params) {
1109 if (params.size() != 3) {
1110 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for ite", line_number);
1111 return mkUnknown();
1112 }
1113
1114 return mkIte(params[0], params[1], params[2]);
1115}
1116// ARITHMATIC COMMON OPERATORS
1117
1118std::shared_ptr<DAGNode>
1119Parser::mkAdd(const std::vector<std::shared_ptr<DAGNode>> &params) {
1120 if (params.size() == 0) {
1121 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for add", line_number);
1122 return mkUnknown();
1123 }
1124 else if (params.size() == 1) {
1125 return params[0];
1126 }
1127 condAssert(params.size() >= 2, "mkAdd: params has less than 2 elements");
1128 std::shared_ptr<Sort> sort = getSort(params);
1129
1130 std::vector<std::shared_ptr<DAGNode>> new_params;
1131
1132 for (size_t i = 0; i < params.size(); i++) {
1133 if (params[i]->isErr())
1134 return params[i];
1135 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
1136 if (canExempt(params[i]->getSort(), sort)) {
1137 std::cerr << "Type mismatch in add, but now exempt for int/real"
1138 << std::endl;
1139 }
1140 else {
1141 err_all(params[i], "Type mismatch in add", line_number);
1142 return mkUnknown();
1143 }
1144 }
1145 if (isZero(params[i])) {
1146 continue;
1147 }
1148 else {
1149 new_params.emplace_back(params[i]);
1150 }
1151 }
1152
1153 // checking
1154 if (new_params.size() == 0) {
1155 // all 0 constant
1156 if (options->isRealTheory()) {
1157 return mkConstReal(0.0);
1158 }
1159 else if (options->isIntTheory()) {
1160 return mkConstInt(0);
1161 }
1162 else {
1163 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in add", line_number);
1164 return mkUnknown();
1165 }
1166 }
1167 else if (new_params.size() == 1) {
1168 // only one uncertain param
1169 return new_params[0];
1170 }
1171 else {
1172 if (sort == nullptr) {
1173 if (options->isRealTheory()) {
1175 }
1176 else if (options->isIntTheory()) {
1177 sort = SortManager::INT_SORT;
1178 }
1179 else {
1180 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in add", line_number);
1181 return mkUnknown();
1182 }
1183 }
1184 return mkOper(sort, NODE_KIND::NT_ADD, new_params);
1185 }
1186}
1187
1188std::shared_ptr<DAGNode>
1189Parser::mkMul(const std::vector<std::shared_ptr<DAGNode>> &params) {
1190 if (params.size() == 1) {
1191 return params[0];
1192 }
1193 condAssert(params.size() >= 2, "mkMul: params has less than 2 elements");
1194 std::shared_ptr<Sort> sort = getSort(params);
1195
1196 std::vector<std::shared_ptr<DAGNode>> new_params;
1197
1198 for (size_t i = 0; i < params.size(); i++) {
1199 if (params[i]->isErr())
1200 return params[i];
1201 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
1202 if (canExempt(params[i]->getSort(), sort)) {
1203 std::cerr << "Type mismatch in mul, but now exempt for int/real"
1204 << std::endl;
1205 }
1206 else {
1207 err_all(params[i], "Type mismatch in mul", line_number);
1208 return mkUnknown();
1209 }
1210 }
1211 if (isZero(params[i])) {
1212 if (options->isIntTheory()) {
1213 return mkConstInt(0);
1214 }
1215 else if (options->isRealTheory()) {
1216 return mkConstReal(0.0);
1217 }
1218 }
1219 else if (isOne(params[i])) {
1220 continue;
1221 }
1222 else {
1223 new_params.emplace_back(params[i]);
1224 }
1225 }
1226
1227 if (new_params.size() == 0) {
1228 // all 1 constant
1229 if (options->isIntTheory()) {
1230 return mkConstInt(1);
1231 }
1232 else if (options->isRealTheory()) {
1233 return mkConstReal(1.0);
1234 }
1235 else {
1236 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in mul", line_number);
1237 return mkUnknown();
1238 }
1239 }
1240 else if (new_params.size() == 1) {
1241 // only one uncertain param
1242 return new_params[0];
1243 }
1244 else {
1245 if (sort == nullptr) {
1246 if (options->isRealTheory()) {
1248 }
1249 else if (options->isIntTheory()) {
1250 sort = SortManager::INT_SORT;
1251 }
1252 else {
1253 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in mul", line_number);
1254 return mkUnknown();
1255 }
1256 }
1257 if (new_params.size() == 2) {
1258 if (new_params[0]->isCInt() && new_params[1]->isCInt()) {
1259 return mkConstInt(toInt(new_params[0]) * toInt(new_params[1]));
1260 }
1261 else if (new_params[0]->isCReal() && new_params[1]->isCReal()) {
1262 return mkConstReal(toReal(new_params[0]) * toReal(new_params[1]));
1263 }
1264 }
1265 return mkOper(sort, NODE_KIND::NT_MUL, new_params);
1266 }
1267}
1268
1269/*
1270(iand rt rt+), return rt
1271*/
1272std::shared_ptr<DAGNode>
1273Parser::mkIand(const std::vector<std::shared_ptr<DAGNode>> &params) {
1274 if (params.size() == 1) {
1275 return params[0];
1276 }
1277 condAssert(params.size() >= 2, "mkIand: params has less than 2 elements");
1278 std::shared_ptr<Sort> sort = getSort(params);
1279
1280 std::vector<std::shared_ptr<DAGNode>> new_params;
1281 for (size_t i = 0; i < params.size(); i++) {
1282 if (params[i]->isErr())
1283 return params[i];
1284 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
1285 if (canExempt(params[i]->getSort(), sort)) {
1286 std::cerr << "Type mismatch in iand, but now exempt for int/real"
1287 << std::endl;
1288 }
1289 else {
1290 err_all(params[i], "Type mismatch in iand", line_number);
1291 return mkUnknown();
1292 }
1293 }
1294
1295 new_params.emplace_back(params[i]);
1296 }
1297
1298 if (sort == nullptr) {
1299 if (options->isRealTheory()) {
1301 }
1302 else if (options->isIntTheory()) {
1303 sort = SortManager::INT_SORT;
1304 }
1305 else {
1306 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in iand", line_number);
1307 return mkUnknown();
1308 }
1309 }
1310 if (new_params.size() == 2) {
1311 if (new_params[0]->isCInt() && new_params[1]->isCInt()) {
1312 return mkConstInt(toInt(new_params[0]) & toInt(new_params[1]));
1313 }
1314 }
1315
1316 return mkOper(sort, NODE_KIND::NT_IAND, new_params);
1317}
1318std::shared_ptr<DAGNode> Parser::mkPow2(std::shared_ptr<DAGNode> param) {
1319 return mkOper(param->getSort(), NODE_KIND::NT_POW2, param);
1320}
1321std::shared_ptr<DAGNode> Parser::mkPow(std::shared_ptr<DAGNode> l,
1322 std::shared_ptr<DAGNode> r) {
1323 return mkOper(l->getSort(), NODE_KIND::NT_POW, l, r);
1324}
1325
1326std::shared_ptr<DAGNode>
1327Parser::mkSub(const std::vector<std::shared_ptr<DAGNode>> &params) {
1328 if (params.size() == 0) {
1329 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for sub", line_number);
1330 return mkUnknown();
1331 }
1332 if (params.size() == 1) {
1333 return mkNeg(params[0]);
1334 }
1335
1336 std::shared_ptr<Sort> sort = getSort(params);
1337 std::vector<std::shared_ptr<DAGNode>> new_params;
1338 // (- a b c)
1339 for (size_t i = 0; i < params.size(); i++) {
1340 if (params[i]->isErr())
1341 return params[i];
1342 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
1343 if (canExempt(params[i]->getSort(), sort)) {
1344 std::cerr << "Type mismatch in sub, but now exempt for int/real"
1345 << std::endl;
1346 }
1347 else {
1348 err_all(params[i], "Type mismatch in sub", line_number);
1349 return mkUnknown();
1350 }
1351 }
1352 new_params.emplace_back(params[i]);
1353 }
1354 if (sort == nullptr) {
1355 if (options->isRealTheory()) {
1357 }
1358 else if (options->isIntTheory()) {
1359 sort = SortManager::INT_SORT;
1360 }
1361 else {
1362 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in sub", line_number);
1363 return mkUnknown();
1364 }
1365 }
1366 if (new_params.size() == 2) {
1367 if ((sort->isInt() || sort->isIntOrReal()) && new_params[0]->isCInt() &&
1368 new_params[1]->isCInt()) {
1369 return mkConstInt(toInt(new_params[0]) - toInt(new_params[1]));
1370 }
1371 else if (sort->isReal() && new_params[0]->isCReal() &&
1372 new_params[1]->isCReal()) {
1373 return mkConstReal(toReal(new_params[0]) - toReal(new_params[1]));
1374 }
1375 else if (isZero(new_params[0])) {
1376 return mkNeg(new_params[1]);
1377 }
1378 else if (isZero(new_params[1])) {
1379 return new_params[0];
1380 }
1381 }
1382 return mkOper(sort, NODE_KIND::NT_SUB, new_params);
1383}
1384/*
1385(- rt), return rt
1386*/
1387std::shared_ptr<DAGNode> Parser::mkNeg(std::shared_ptr<DAGNode> param) {
1388 return mkOper(param->getSort(), NODE_KIND::NT_NEG, param);
1389}
1390
1391std::shared_ptr<DAGNode>
1392Parser::mkDivInt(const std::vector<std::shared_ptr<DAGNode>> &params) {
1393 if (params.size() < 2) {
1394 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for div", line_number);
1395 return mkUnknown();
1396 }
1397 if (params.size() == 1) {
1398 return params[0];
1399 }
1401}
1402
1403std::shared_ptr<DAGNode>
1404Parser::mkDiv(const std::vector<std::shared_ptr<DAGNode>> &params) {
1405 return mkDivReal(params);
1406}
1407
1408std::shared_ptr<DAGNode>
1409Parser::mkDivReal(const std::vector<std::shared_ptr<DAGNode>> &params) {
1410 if (params.size() < 2) {
1411 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for div", line_number);
1412 return mkUnknown();
1413 }
1414 if (params.size() == 1) {
1415 return params[0];
1416 }
1418}
1419/*
1420(mod Int Int), return Int
1421*/
1422std::shared_ptr<DAGNode> Parser::mkMod(std::shared_ptr<DAGNode> l,
1423 std::shared_ptr<DAGNode> r) {
1424 if (!isIntParam(l) || !isIntParam(r)) {
1425 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in mod", line_number);
1426 return mkUnknown();
1427 }
1429}
1430/*
1431(abs Int), return Int
1432(abs Real), return Real
1433*/
1434std::shared_ptr<DAGNode> Parser::mkAbs(std::shared_ptr<DAGNode> param) {
1435 if (!isIntParam(param) && !isRealParam(param)) {
1436 err_all(param, "Absolute value on non-integer or non-real", line_number);
1437 return mkUnknown();
1438 }
1439 return mkOper(param->getSort(), NODE_KIND::NT_ABS, param);
1440}
1441/*
1442(sqrt Real), return Real
1443(sqrt Int), return Real
1444*/
1445std::shared_ptr<DAGNode> Parser::mkSqrt(std::shared_ptr<DAGNode> param) {
1446 if (!isIntParam(param) && !isRealParam(param)) {
1447 err_all(param, "Square root on non-integer or non-real", line_number);
1448 return mkUnknown();
1449 }
1450 return mkOper(param->getSort(), NODE_KIND::NT_SQRT, param);
1451}
1452/*
1453(safesqrt Real), return Real
1454(safesqrt Int), return Real
1455*/
1456std::shared_ptr<DAGNode> Parser::mkSafeSqrt(std::shared_ptr<DAGNode> param) {
1457 if (!isIntParam(param) && !isRealParam(param)) {
1458 err_all(param, "Safe square root on non-integer or non-real", line_number);
1459 return mkUnknown();
1460 }
1461 return mkOper(param->getSort(), NODE_KIND::NT_SAFESQRT, param);
1462}
1463/*
1464(ceil Real), return Int
1465*/
1466std::shared_ptr<DAGNode> Parser::mkCeil(std::shared_ptr<DAGNode> param) {
1467 if (!isIntParam(param) && !isRealParam(param)) {
1468 err_all(param, "Ceiling on non-integer or non-real", line_number);
1469 return mkUnknown();
1470 }
1471 return mkOper(param->getSort(), NODE_KIND::NT_CEIL, param);
1472}
1473/*
1474(floor Real), return Int
1475*/
1476std::shared_ptr<DAGNode> Parser::mkFloor(std::shared_ptr<DAGNode> param) {
1478}
1479/*
1480(round Real), return Int
1481*/
1482std::shared_ptr<DAGNode> Parser::mkRound(std::shared_ptr<DAGNode> param) {
1484}
1485// TRANSCENDENTAL ARITHMATIC
1486/*
1487(exp Real), return Real
1488*/
1489std::shared_ptr<DAGNode> Parser::mkExp(std::shared_ptr<DAGNode> param) {
1491}
1492/*
1493(ln Real), return Real
1494*/
1495std::shared_ptr<DAGNode> Parser::mkLn(std::shared_ptr<DAGNode> param) {
1497}
1498/*
1499(lb Real), return Real
1500*/
1501std::shared_ptr<DAGNode> Parser::mkLb(std::shared_ptr<DAGNode> param) {
1503}
1504/*
1505(lg Real), return Real
1506*/
1507std::shared_ptr<DAGNode> Parser::mkLg(std::shared_ptr<DAGNode> param) {
1509}
1510/*
1511(log Real Real), return Real
1512*/
1513std::shared_ptr<DAGNode> Parser::mkLog(std::shared_ptr<DAGNode> l,
1514 std::shared_ptr<DAGNode> r) {
1515 if (!l->getSort()->isEqTo(r->getSort())) {
1516 if (canExempt(l->getSort(), r->getSort())) {
1517 std::cerr << "Type mismatch in log, but now exempt for int/real"
1518 << std::endl;
1519 }
1520 else {
1521 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in log", line_number);
1522 return mkUnknown();
1523 }
1524 }
1526}
1527/*
1528(sin Real), return Real
1529*/
1530std::shared_ptr<DAGNode> Parser::mkSin(std::shared_ptr<DAGNode> param) {
1532}
1533/*
1534(cos Real), return Real
1535*/
1536std::shared_ptr<DAGNode> Parser::mkCos(std::shared_ptr<DAGNode> param) {
1538}
1539/*
1540(sec Real), return Real
1541*/
1542std::shared_ptr<DAGNode> Parser::mkSec(std::shared_ptr<DAGNode> param) {
1544}
1545/*
1546(csc Real), return Real
1547*/
1548std::shared_ptr<DAGNode> Parser::mkCsc(std::shared_ptr<DAGNode> param) {
1550}
1551/*
1552(tan Real), return Real
1553*/
1554std::shared_ptr<DAGNode> Parser::mkTan(std::shared_ptr<DAGNode> param) {
1556}
1557/*
1558(cot Real), return Real
1559*/
1560std::shared_ptr<DAGNode> Parser::mkCot(std::shared_ptr<DAGNode> param) {
1562}
1563/*
1564(asin Real), return Real
1565*/
1566std::shared_ptr<DAGNode> Parser::mkAsin(std::shared_ptr<DAGNode> param) {
1568}
1569/*
1570(acos Real), return Real
1571*/
1572std::shared_ptr<DAGNode> Parser::mkAcos(std::shared_ptr<DAGNode> param) {
1574}
1575/*
1576(asec Real), return Real
1577*/
1578std::shared_ptr<DAGNode> Parser::mkAsec(std::shared_ptr<DAGNode> param) {
1580}
1581/*
1582(acsc Real), return Real
1583*/
1584std::shared_ptr<DAGNode> Parser::mkAcsc(std::shared_ptr<DAGNode> param) {
1586}
1587/*
1588(atan Real), return Real
1589*/
1590std::shared_ptr<DAGNode> Parser::mkAtan(std::shared_ptr<DAGNode> param) {
1592}
1593/*
1594(acot Real), return Real
1595*/
1596std::shared_ptr<DAGNode> Parser::mkAcot(std::shared_ptr<DAGNode> param) {
1598}
1599/*
1600(sinh Real), return Real
1601*/
1602std::shared_ptr<DAGNode> Parser::mkSinh(std::shared_ptr<DAGNode> param) {
1604}
1605/*
1606(cosh Real), return Real
1607*/
1608std::shared_ptr<DAGNode> Parser::mkCosh(std::shared_ptr<DAGNode> param) {
1610}
1611/*
1612(tanh Real), return Real
1613*/
1614std::shared_ptr<DAGNode> Parser::mkTanh(std::shared_ptr<DAGNode> param) {
1616}
1617/*
1618(sech Real), return Real
1619*/
1620std::shared_ptr<DAGNode> Parser::mkSech(std::shared_ptr<DAGNode> param) {
1622}
1623/*
1624(csch Real), return Real
1625*/
1626std::shared_ptr<DAGNode> Parser::mkCsch(std::shared_ptr<DAGNode> param) {
1628}
1629/*
1630(coth Real), return Real
1631*/
1632std::shared_ptr<DAGNode> Parser::mkCoth(std::shared_ptr<DAGNode> param) {
1634}
1635/*
1636(asinh Real), return Real
1637*/
1638std::shared_ptr<DAGNode> Parser::mkAsinh(std::shared_ptr<DAGNode> param) {
1640}
1641/*
1642(acosh Real), return Real
1643*/
1644std::shared_ptr<DAGNode> Parser::mkAcosh(std::shared_ptr<DAGNode> param) {
1646}
1647/*
1648(atanh Real), return Real
1649*/
1650std::shared_ptr<DAGNode> Parser::mkAtanh(std::shared_ptr<DAGNode> param) {
1652}
1653/*
1654(asech Real), return Real
1655*/
1656std::shared_ptr<DAGNode> Parser::mkAsech(std::shared_ptr<DAGNode> param) {
1658}
1659/*
1660(acsch Real), return Real
1661*/
1662std::shared_ptr<DAGNode> Parser::mkAcsch(std::shared_ptr<DAGNode> param) {
1664}
1665/*
1666(acoth Real), return Real
1667*/
1668std::shared_ptr<DAGNode> Parser::mkAcoth(std::shared_ptr<DAGNode> param) {
1670}
1671/*
1672(atan2 Real Real), return Real
1673*/
1674std::shared_ptr<DAGNode> Parser::mkAtan2(std::shared_ptr<DAGNode> l,
1675 std::shared_ptr<DAGNode> r) {
1677}
1678
1679std::shared_ptr<DAGNode>
1680Parser::mkLe(const std::vector<std::shared_ptr<DAGNode>> &params) {
1681 if (params.size() < 2) {
1682 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for le", line_number);
1683 return mkUnknown();
1684 }
1686}
1687std::shared_ptr<DAGNode>
1688Parser::mkLt(const std::vector<std::shared_ptr<DAGNode>> &params) {
1689 if (params.size() < 2) {
1690 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for lt", line_number);
1691 return mkUnknown();
1692 }
1694}
1695std::shared_ptr<DAGNode>
1696Parser::mkGe(const std::vector<std::shared_ptr<DAGNode>> &params) {
1697 if (params.size() < 2) {
1698 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for ge", line_number);
1699 return mkUnknown();
1700 }
1701 // std::vector<std::shared_ptr<DAGNode>> nparams(params.rbegin(),
1702 // params.rend());
1704}
1705std::shared_ptr<DAGNode>
1706Parser::mkGt(const std::vector<std::shared_ptr<DAGNode>> &params) {
1707 if (params.size() < 2) {
1708 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for gt", line_number);
1709 return mkUnknown();
1710 }
1712}
1713// ARITHMATIC CONVERSION
1714/*
1715(to_int Real), return Int
1716*/
1717std::shared_ptr<DAGNode> Parser::mkToInt(std::shared_ptr<DAGNode> param) {
1718 if (!isRealParam(param)) {
1719 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in to_int", line_number);
1720 return mkUnknown();
1721 }
1723}
1724/*
1725(to_real Int), return Real
1726*/
1727std::shared_ptr<DAGNode> Parser::mkToReal(std::shared_ptr<DAGNode> param) {
1728 if (!isIntParam(param)) {
1729 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in to_real", line_number);
1730 return mkUnknown();
1731 }
1733}
1734// ARITHMATIC PROPERTIES
1735/*
1736(is_int Real), return Bool
1737*/
1738std::shared_ptr<DAGNode> Parser::mkIsInt(std::shared_ptr<DAGNode> param) {
1739 if (!isRealParam(param)) {
1740 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in is_int", line_number);
1741 return mkUnknown();
1742 }
1744}
1745/*
1746(is_divisible Int Int), return Bool
1747*/
1748std::shared_ptr<DAGNode> Parser::mkIsDivisible(std::shared_ptr<DAGNode> l,
1749 std::shared_ptr<DAGNode> r) {
1750 if (!isIntParam(l) || !isIntParam(r)) {
1751 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in is_divisible", line_number);
1752 return mkUnknown();
1753 }
1755}
1756/*
1757(is_prime Int), return Bool
1758*/
1759std::shared_ptr<DAGNode> Parser::mkIsPrime(std::shared_ptr<DAGNode> param) {
1760 if (!isIntParam(param)) {
1761 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in is_prime", line_number);
1762 return mkUnknown();
1763 }
1765}
1766/*
1767(is_even Int), return Bool
1768*/
1769std::shared_ptr<DAGNode> Parser::mkIsEven(std::shared_ptr<DAGNode> param) {
1770 if (!isIntParam(param)) {
1771 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in is_even", line_number);
1772 return mkUnknown();
1773 }
1775}
1776/*
1777(is_odd Int), return Bool
1778*/
1779std::shared_ptr<DAGNode> Parser::mkIsOdd(std::shared_ptr<DAGNode> param) {
1780 if (!isIntParam(param)) {
1781 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in is_odd", line_number);
1782 return mkUnknown();
1783 }
1785}
1786// ARITHMATIC CONSTANTS
1787std::shared_ptr<DAGNode> Parser::mkPi() { return NodeManager::PI_NODE; }
1788std::shared_ptr<DAGNode> Parser::mkE() { return NodeManager::E_NODE; }
1789std::shared_ptr<DAGNode> Parser::mkInfinity(std::shared_ptr<Sort> sort) {
1790 if (sort->isEqTo(SortManager::STR_SORT)) {
1792 }
1793 else if (sort->isEqTo(SortManager::INT_SORT)) {
1795 }
1796 else if (sort->isEqTo(SortManager::REAL_SORT)) {
1798 }
1799 else {
1800 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in infinity", line_number);
1801 return mkUnknown();
1802 }
1803}
1804std::shared_ptr<DAGNode> Parser::mkPosInfinity(std::shared_ptr<Sort> sort) {
1805 if (!sort) {
1807 }
1808 else if (sort->isFp()) {
1809 // For floating point, create a node with full name including eb and sb
1810 size_t eb = sort->getExponentWidth();
1811 size_t sb = sort->getSignificandWidth();
1812 std::string const_name =
1813 "(_ +oo " + std::to_string(eb) + " " + std::to_string(sb) + ")";
1814 return node_manager->createNode(sort, NODE_KIND::NT_POS_INFINITY, const_name);
1815 }
1816 else if (sort->isEqTo(SortManager::STR_SORT)) {
1818 }
1819 else if (sort->isEqTo(SortManager::INT_SORT)) {
1821 }
1822 else if (sort->isEqTo(SortManager::REAL_SORT)) {
1824 }
1825 else {
1826 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in pos_infinity", line_number);
1827 return mkUnknown();
1828 }
1829}
1830std::shared_ptr<DAGNode> Parser::mkNegInfinity(std::shared_ptr<Sort> sort) {
1831 if (!sort) {
1833 }
1834 else if (sort->isFp()) {
1835 // For floating point, create a node with full name including eb and sb
1836 size_t eb = sort->getExponentWidth();
1837 size_t sb = sort->getSignificandWidth();
1838 std::string const_name =
1839 "(_ -oo " + std::to_string(eb) + " " + std::to_string(sb) + ")";
1840 return node_manager->createNode(sort, NODE_KIND::NT_NEG_INFINITY, const_name);
1841 }
1842 else if (sort->isEqTo(SortManager::STR_SORT)) {
1844 }
1845 else if (sort->isEqTo(SortManager::INT_SORT)) {
1847 }
1848 else if (sort->isEqTo(SortManager::REAL_SORT)) {
1850 }
1851 else {
1852 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in neg_infinity", line_number);
1853 return mkUnknown();
1854 }
1855}
1856std::shared_ptr<DAGNode> Parser::mkNaN(std::shared_ptr<Sort> sort) {
1857 if (!sort) {
1858 return NodeManager::NAN_NODE;
1859 }
1860 else if (sort->isFp()) {
1861 // For floating point, create a node with full name including eb and sb
1862 size_t eb = sort->getExponentWidth();
1863 size_t sb = sort->getSignificandWidth();
1864 std::string const_name =
1865 "(_ NaN " + std::to_string(eb) + " " + std::to_string(sb) + ")";
1866 return node_manager->createNode(sort, NODE_KIND::NT_NAN, const_name);
1867 }
1868 else {
1869 return NodeManager::NAN_NODE;
1870 }
1871}
1872std::shared_ptr<DAGNode> Parser::mkEpsilon() {
1874}
1875std::shared_ptr<DAGNode> Parser::mkPosEpsilon() {
1877}
1878std::shared_ptr<DAGNode> Parser::mkNegEpsilon() {
1880}
1881// ARITHMATIC FUNCTIONS
1882// /*
1883// (sum rt rt+), return rt
1884// */
1885// std::shared_ptr<DAGNode> Parser::mkSum(const
1886// std::vector<std::shared_ptr<DAGNode>> &params); // \Sum params
1887// std::shared_ptr<DAGNode> Parser::mkProd(const
1888// std::vector<std::shared_ptr<DAGNode>> &params); // \Prod params
1889/*
1890(gcd Int Int), return Int
1891*/
1892std::shared_ptr<DAGNode> Parser::mkGcd(std::shared_ptr<DAGNode> l,
1893 std::shared_ptr<DAGNode> r) {
1894 if (!isIntParam(l) || !isIntParam(r)) {
1895 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in gcd", line_number);
1896 return mkUnknown();
1897 }
1899}
1900/*
1901(lcm Int Int), return Int
1902*/
1903std::shared_ptr<DAGNode> Parser::mkLcm(std::shared_ptr<DAGNode> l,
1904 std::shared_ptr<DAGNode> r) {
1905 if (!isIntParam(l) || !isIntParam(r)) {
1906 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in lcm", line_number);
1907 return mkUnknown();
1908 }
1910}
1911/*
1912(factorial Int), return Int
1913*/
1914std::shared_ptr<DAGNode> Parser::mkFact(std::shared_ptr<DAGNode> param) {
1915 if (!isIntParam(param)) {
1916 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in factorial", line_number);
1917 return mkUnknown();
1918 }
1920}
1921// BITVECTOR COMMON OPERATORS
1922/*
1923(bv_not Bv), return Bv
1924*/
1925std::shared_ptr<DAGNode> Parser::mkBvNot(std::shared_ptr<DAGNode> param) {
1926 if (!isBvParam(param)) {
1927 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_not", line_number);
1928 return mkUnknown();
1929 }
1930 return mkOper(param->getSort(), NODE_KIND::NT_BV_NOT, param);
1931}
1932std::shared_ptr<DAGNode>
1933Parser::mkBvAnd(const std::vector<std::shared_ptr<DAGNode>> &params) {
1934 if (params.size() == 0) {
1935 std::cerr << "BVAND on empty parameters, return true" << std::endl;
1936 return mkTrue();
1937 }
1938 else if (params.size() == 1) {
1939 return params[0];
1940 }
1941 std::shared_ptr<Sort> sort = getSort(params);
1942
1943 std::vector<std::shared_ptr<DAGNode>> new_params;
1944
1945 for (size_t i = 0; i < params.size(); i++) {
1946 if (params[i]->isErr())
1947 return params[i];
1948 if (sort != nullptr && !isBvParam(params[i])) {
1949 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_and", line_number);
1950 return mkUnknown();
1951 }
1952 new_params.emplace_back(params[i]);
1953 }
1954
1955 if (sort == nullptr) {
1956 sort = new_params[0]->getSort();
1957 }
1958
1959 return mkOper(sort, NODE_KIND::NT_BV_AND, new_params);
1960}
1961
1962/*
1963(bvor Bv Bv+), return Bv
1964*/
1965std::shared_ptr<DAGNode>
1966Parser::mkBvOr(const std::vector<std::shared_ptr<DAGNode>> &params) {
1967 if (params.size() == 0) {
1968 std::cerr << "BVOR on empty parameters, return false" << std::endl;
1969 return mkFalse();
1970 }
1971 else if (params.size() == 1) {
1972 return params[0];
1973 }
1974 std::shared_ptr<Sort> sort = getSort(params);
1975
1976 std::vector<std::shared_ptr<DAGNode>> new_params;
1977
1978 for (size_t i = 0; i < params.size(); i++) {
1979 if (params[i]->isErr())
1980 return params[i];
1981 if (sort != nullptr && !isBvParam(params[i])) {
1982 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_or", line_number);
1983 return mkUnknown();
1984 }
1985 new_params.emplace_back(params[i]);
1986 }
1987
1988 if (sort == nullptr) {
1989 sort = new_params[0]->getSort();
1990 }
1991
1992 return mkOper(sort, NODE_KIND::NT_BV_OR, new_params);
1993}
1994
1995std::shared_ptr<DAGNode>
1996Parser::mkBvXor(const std::vector<std::shared_ptr<DAGNode>> &params) {
1997 if (params.size() == 0) {
1998 std::cerr << "BVXOR on empty parameters, return false" << std::endl;
1999 return mkFalse();
2000 }
2001 else if (params.size() == 1) {
2002 return params[0];
2003 }
2004 std::shared_ptr<Sort> sort = getSort(params);
2005
2006 std::vector<std::shared_ptr<DAGNode>> new_params;
2007
2008 for (size_t i = 0; i < params.size(); i++) {
2009 if (params[i]->isErr())
2010 return params[i];
2011 if (sort != nullptr && !isBvParam(params[i])) {
2012 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_xor", line_number);
2013 return mkUnknown();
2014 }
2015 new_params.emplace_back(params[i]);
2016 }
2017
2018 if (sort == nullptr) {
2019 sort = new_params[0]->getSort();
2020 }
2021
2022 return mkOper(sort, NODE_KIND::NT_BV_XOR, new_params);
2023}
2024
2025std::shared_ptr<DAGNode> Parser::mkBvNand(std::shared_ptr<DAGNode> l,
2026 std::shared_ptr<DAGNode> r) {
2027 std::shared_ptr<Sort> sort = getSort(l, r);
2028 if (sort == nullptr) {
2029 sort = l->getSort();
2030 }
2031
2032 return mkOper(sort, NODE_KIND::NT_BV_NAND, l, r);
2033}
2034
2035std::shared_ptr<DAGNode> Parser::mkBvNor(std::shared_ptr<DAGNode> l,
2036 std::shared_ptr<DAGNode> r) {
2037 std::shared_ptr<Sort> sort = getSort(l, r);
2038 if (sort == nullptr) {
2039 sort = l->getSort();
2040 }
2041
2042 return mkOper(sort, NODE_KIND::NT_BV_NOR, l, r);
2043}
2044
2045std::shared_ptr<DAGNode>
2046Parser::mkBvComp(const std::vector<std::shared_ptr<DAGNode>> &params) {
2047 std::shared_ptr<Sort> sort = sort_manager->createBVSort(1);
2048
2049 return mkOper(sort, NODE_KIND::NT_BV_COMP, params);
2050}
2051
2052std::shared_ptr<DAGNode> Parser::mkBvXnor(std::shared_ptr<DAGNode> l,
2053 std::shared_ptr<DAGNode> r) {
2054 std::shared_ptr<Sort> sort = getSort(l, r);
2055
2056 if (sort == nullptr) {
2057 sort = l->getSort();
2058 }
2059
2060 return mkOper(sort, NODE_KIND::NT_BV_XNOR, l, r);
2061}
2062
2063/*
2064(bvneg Bv), return Bv
2065*/
2066std::shared_ptr<DAGNode> Parser::mkBvNeg(std::shared_ptr<DAGNode> param) {
2067 return mkOper(param->getSort(), NODE_KIND::NT_BV_NEG, param);
2068}
2069
2070std::shared_ptr<DAGNode>
2071Parser::mkBvAdd(const std::vector<std::shared_ptr<DAGNode>> &params) {
2072 if (params.size() == 0) {
2073 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for bv_add", line_number);
2074 return mkUnknown();
2075 }
2076 else if (params.size() == 1) {
2077 return params[0];
2078 }
2079 std::shared_ptr<Sort> sort = getSort(params);
2080 std::vector<std::shared_ptr<DAGNode>> new_params;
2081
2082 for (size_t i = 0; i < params.size(); i++) {
2083 if (params[i]->isErr())
2084 return params[i];
2085 if (sort != nullptr && !isBvParam(params[i])) {
2086 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_add", line_number);
2087 return mkUnknown();
2088 }
2089 new_params.emplace_back(params[i]);
2090 }
2091
2092 if (sort == nullptr) {
2093 sort = new_params[0]->getSort();
2094 }
2095
2096 return mkOper(sort, NODE_KIND::NT_BV_ADD, new_params);
2097}
2098
2099std::shared_ptr<DAGNode> Parser::mkBvSub(std::shared_ptr<DAGNode> l,
2100 std::shared_ptr<DAGNode> r) {
2101 std::shared_ptr<Sort> sort = getSort(l, r);
2102
2103 if (sort == nullptr) {
2104 sort = l->getSort();
2105 }
2106
2107 return mkOper(sort, NODE_KIND::NT_BV_SUB, l, r);
2108}
2109
2110std::shared_ptr<DAGNode>
2111Parser::mkBvMul(const std::vector<std::shared_ptr<DAGNode>> &params) {
2112 if (params.size() == 0) {
2113 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for bv_mul", line_number);
2114 return mkUnknown();
2115 }
2116 else if (params.size() == 1) {
2117 return params[0];
2118 }
2119 std::shared_ptr<Sort> sort = getSort(params);
2120 std::vector<std::shared_ptr<DAGNode>> new_params;
2121 for (size_t i = 0; i < params.size(); i++) {
2122 if (params[i]->isErr())
2123 return params[i];
2124 if (sort != nullptr && !isBvParam(params[i])) {
2125 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_mul", line_number);
2126 return mkUnknown();
2127 }
2128 new_params.emplace_back(params[i]);
2129 }
2130
2131 if (sort == nullptr) {
2132 sort = new_params[0]->getSort();
2133 }
2134
2135 return mkOper(sort, NODE_KIND::NT_BV_MUL, new_params);
2136}
2137/*
2138(bvudiv Bv Bv), return Bv
2139*/
2140std::shared_ptr<DAGNode> Parser::mkBvUdiv(std::shared_ptr<DAGNode> l,
2141 std::shared_ptr<DAGNode> r) {
2142 if (!isBvParam(l) || !isBvParam(r)) {
2143 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_udiv", line_number);
2144 return mkUnknown();
2145 }
2146 return mkOper(l->getSort(), NODE_KIND::NT_BV_UDIV, l, r);
2147}
2148/*
2149(bvurem Bv Bv), return Bv
2150*/
2151std::shared_ptr<DAGNode> Parser::mkBvUrem(std::shared_ptr<DAGNode> l,
2152 std::shared_ptr<DAGNode> r) {
2153 if (!isBvParam(l) || !isBvParam(r)) {
2154 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_urem", line_number);
2155 return mkUnknown();
2156 }
2157 return mkOper(l->getSort(), NODE_KIND::NT_BV_UREM, l, r);
2158}
2159/*
2160(bvumod Bv Bv), return Bv
2161*/
2162std::shared_ptr<DAGNode> Parser::mkBvUmod(std::shared_ptr<DAGNode> l,
2163 std::shared_ptr<DAGNode> r) {
2164 if (!isBvParam(l) || !isBvParam(r)) {
2165 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_umod", line_number);
2166 return mkUnknown();
2167 }
2168 return mkOper(l->getSort(), NODE_KIND::NT_BV_UMOD, l, r);
2169}
2170/*
2171(bvsdiv Bv Bv), return Bv
2172*/
2173std::shared_ptr<DAGNode> Parser::mkBvSdiv(std::shared_ptr<DAGNode> l,
2174 std::shared_ptr<DAGNode> r) {
2175 if (!isBvParam(l) || !isBvParam(r)) {
2176 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_sdiv", line_number);
2177 return mkUnknown();
2178 }
2179 return mkOper(l->getSort(), NODE_KIND::NT_BV_SDIV, l, r);
2180}
2181/*
2182(bvsrem Bv Bv), return Bv
2183*/
2184std::shared_ptr<DAGNode> Parser::mkBvSrem(std::shared_ptr<DAGNode> l,
2185 std::shared_ptr<DAGNode> r) {
2186 if (!isBvParam(l) || !isBvParam(r)) {
2187 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_srem", line_number);
2188 return mkUnknown();
2189 }
2190 return mkOper(l->getSort(), NODE_KIND::NT_BV_SREM, l, r);
2191}
2192/*
2193(bvsmod Bv Bv), return Bv
2194*/
2195std::shared_ptr<DAGNode> Parser::mkBvSmod(std::shared_ptr<DAGNode> l,
2196 std::shared_ptr<DAGNode> r) {
2197 if (!isBvParam(l) || !isBvParam(r)) {
2198 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_smod", line_number);
2199 return mkUnknown();
2200 }
2201 return mkOper(l->getSort(), NODE_KIND::NT_BV_SMOD, l, r);
2202}
2203/*
2204(bvshl Bv Bv), return Bv
2205*/
2206std::shared_ptr<DAGNode> Parser::mkBvShl(std::shared_ptr<DAGNode> l,
2207 std::shared_ptr<DAGNode> r) {
2208 if (!isBvParam(l) || !isBvParam(r)) {
2209 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_shl", line_number);
2210 return mkUnknown();
2211 }
2212 return mkOper(l->getSort(), NODE_KIND::NT_BV_SHL, l, r);
2213}
2214/*
2215(bvlshr Bv Bv), return Bv
2216*/
2217std::shared_ptr<DAGNode> Parser::mkBvLshr(std::shared_ptr<DAGNode> l,
2218 std::shared_ptr<DAGNode> r) {
2219 if (!isBvParam(l) || !isBvParam(r)) {
2220 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_lshr", line_number);
2221 return mkUnknown();
2222 }
2223 return mkOper(l->getSort(), NODE_KIND::NT_BV_LSHR, l, r);
2224}
2225/*
2226(bvashr Bv Bv), return Bv
2227*/
2228std::shared_ptr<DAGNode> Parser::mkBvAshr(std::shared_ptr<DAGNode> l,
2229 std::shared_ptr<DAGNode> r) {
2230 if (!isBvParam(l) || !isBvParam(r)) {
2231 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_ashr", line_number);
2232 return mkUnknown();
2233 }
2234 return mkOper(l->getSort(), NODE_KIND::NT_BV_ASHR, l, r);
2235}
2236/*
2237(bvconcat Bv Bv+), return Bv
2238*/
2239std::shared_ptr<DAGNode>
2240Parser::mkBvConcat(const std::vector<std::shared_ptr<DAGNode>> &params) {
2241 if (params.size() == 0) {
2242 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for bv_concat", line_number);
2243 return mkUnknown();
2244 }
2245 else if (params.size() == 1) {
2246 return params[0];
2247 }
2248 std::vector<std::shared_ptr<DAGNode>> new_params;
2249
2250 size_t width = 0;
2251 for (size_t i = 0; i < params.size(); i++) {
2252 if (params[i]->isErr())
2253 return params[i];
2254 // no need to check equal sort
2255 if (!isBvParam(params[i])) {
2256 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_concat", line_number);
2257 return mkUnknown();
2258 }
2259 width += params[i]->getSort()->getBitWidth();
2260 new_params.emplace_back(params[i]);
2261 }
2262 std::shared_ptr<Sort> new_sort = sort_manager->createBVSort(width);
2263
2264 return mkOper(new_sort, NODE_KIND::NT_BV_CONCAT, new_params);
2265}
2266/*
2267(bvextract Bv Int Int), return Bv
2268*/
2269std::shared_ptr<DAGNode> Parser::mkBvExtract(std::shared_ptr<DAGNode> l,
2270 std::shared_ptr<DAGNode> r,
2271 std::shared_ptr<DAGNode> s) {
2272 if (l->isErr() || r->isErr() || s->isErr())
2273 return l->isErr() ? l : r;
2274 if (!isBvParam(l) || !isIntParam(r) || !isIntParam(s)) {
2275 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_extract", line_number);
2276 return mkUnknown();
2277 }
2278 size_t width = toInt(r).toULong() - toInt(s).toULong() + 1;
2279 std::shared_ptr<Sort> new_sort = sort_manager->createBVSort(width);
2280
2281 return mkOper(new_sort, NODE_KIND::NT_BV_EXTRACT, l, r, s);
2282}
2283/*
2284(bvrepeat Bv Int), return Bv
2285*/
2286std::shared_ptr<DAGNode> Parser::mkBvRepeat(std::shared_ptr<DAGNode> l,
2287 std::shared_ptr<DAGNode> r) {
2288 if (!isBvParam(l) || !isIntParam(r)) {
2289 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_repeat", line_number);
2290 return mkUnknown();
2291 }
2292 size_t width = l->getSort()->getBitWidth() * toInt(r).toULong();
2293 std::shared_ptr<Sort> new_sort = sort_manager->createBVSort(width);
2294
2295 return mkOper(new_sort, NODE_KIND::NT_BV_REPEAT, l, r);
2296}
2297/*
2298(zero_extend Bv Int), return Bv
2299*/
2300std::shared_ptr<DAGNode> Parser::mkBvZeroExt(std::shared_ptr<DAGNode> l,
2301 std::shared_ptr<DAGNode> r) {
2302 if (!isBvParam(l) || !isIntParam(r)) {
2303 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_zero_ext", line_number);
2304 return mkUnknown();
2305 }
2306 size_t width = toInt(r).toULong();
2307 std::shared_ptr<Sort> new_sort =
2308 sort_manager->createBVSort(width + l->getSort()->getBitWidth());
2309 return mkOper(new_sort, NODE_KIND::NT_BV_ZERO_EXT, l, r);
2310}
2311/*
2312(bvsign_extend Bv Int), return Bv
2313*/
2314std::shared_ptr<DAGNode> Parser::mkBvSignExt(std::shared_ptr<DAGNode> l,
2315 std::shared_ptr<DAGNode> r) {
2316 if (!isBvParam(l) || !isIntParam(r)) {
2317 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_sign_ext", line_number);
2318 return mkUnknown();
2319 }
2320 size_t width = toInt(r).toULong();
2321 std::shared_ptr<Sort> new_sort =
2322 sort_manager->createBVSort(width + l->getSort()->getBitWidth());
2323
2324 return mkOper(new_sort, NODE_KIND::NT_BV_SIGN_EXT, l, r);
2325}
2326/*
2327(bvrotate_left Bv Int), return Bv
2328*/
2329std::shared_ptr<DAGNode> Parser::mkBvRotateLeft(std::shared_ptr<DAGNode> l,
2330 std::shared_ptr<DAGNode> r) {
2331 if (!isBvParam(l) || !isIntParam(r)) {
2332 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_rotate_left", line_number);
2333 return mkUnknown();
2334 }
2335
2336 size_t width = l->getSort()->getBitWidth();
2337 std::shared_ptr<Sort> new_sort = sort_manager->createBVSort(width);
2338
2339 return mkOper(new_sort, NODE_KIND::NT_BV_ROTATE_LEFT, l, r);
2340}
2341/*
2342(bvrotate_right Bv Int), return Bv
2343*/
2344std::shared_ptr<DAGNode> Parser::mkBvRotateRight(std::shared_ptr<DAGNode> l,
2345 std::shared_ptr<DAGNode> r) {
2346 if (!isBvParam(l) || !isIntParam(r)) {
2347 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_rotate_right", line_number);
2348 return mkUnknown();
2349 }
2350 size_t width = l->getSort()->getBitWidth();
2351 std::shared_ptr<Sort> new_sort = sort_manager->createBVSort(width);
2352
2353 return mkOper(new_sort, NODE_KIND::NT_BV_ROTATE_RIGHT, l, r);
2354}
2355// BITVECTOR COMP
2356/*
2357(bvult Bv Bv), return Bool
2358*/
2359std::shared_ptr<DAGNode> Parser::mkBvUlt(std::shared_ptr<DAGNode> l,
2360 std::shared_ptr<DAGNode> r) {
2361 if (!isBvParam(l) || !isBvParam(r)) {
2362 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_ult", line_number);
2363 return mkUnknown();
2364 }
2365 else if (l == r) {
2366 return mkFalse();
2367 }
2369}
2370/*
2371(bvule Bv Bv), return Bool
2372*/
2373std::shared_ptr<DAGNode> Parser::mkBvUle(std::shared_ptr<DAGNode> l,
2374 std::shared_ptr<DAGNode> r) {
2375 if (!isBvParam(l) || !isBvParam(r)) {
2376 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_ule", line_number);
2377 return mkUnknown();
2378 }
2379
2380 if (l->isCBV() && r->isCBV()) {
2381 return BitVectorUtils::bvComp(l->toString(), r->toString(), NODE_KIND::NT_BV_ULE)
2382 ? mkTrue()
2383 : mkFalse();
2384 }
2385 else if (l == r) {
2386 return mkTrue();
2387 }
2388
2390}
2391/*
2392(bvugt Bv Bv), return Bool
2393*/
2394std::shared_ptr<DAGNode> Parser::mkBvUgt(std::shared_ptr<DAGNode> l,
2395 std::shared_ptr<DAGNode> r) {
2396 if (!isBvParam(l) || !isBvParam(r)) {
2397 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_ugt", line_number);
2398 return mkUnknown();
2399 }
2400
2401 if (l->isCBV() && r->isCBV()) {
2402 return BitVectorUtils::bvComp(l->toString(), r->toString(), NODE_KIND::NT_BV_UGT)
2403 ? mkTrue()
2404 : mkFalse();
2405 }
2406 else if (l == r) {
2407 return mkFalse();
2408 }
2409
2411}
2412/*
2413(bvuge Bv Bv), return Bool
2414*/
2415std::shared_ptr<DAGNode> Parser::mkBvUge(std::shared_ptr<DAGNode> l,
2416 std::shared_ptr<DAGNode> r) {
2417 if (!isBvParam(l) || !isBvParam(r)) {
2418 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_uge", line_number);
2419 return mkUnknown();
2420 }
2421
2422 if (l->isCBV() && r->isCBV()) {
2423 return BitVectorUtils::bvComp(l->toString(), r->toString(), NODE_KIND::NT_BV_UGE)
2424 ? mkTrue()
2425 : mkFalse();
2426 }
2427 else if (l == r) {
2428 return mkTrue();
2429 }
2430
2432}
2433/*
2434(bvslt Bv Bv), return Bool
2435*/
2436std::shared_ptr<DAGNode> Parser::mkBvSlt(std::shared_ptr<DAGNode> l,
2437 std::shared_ptr<DAGNode> r) {
2438 if (!isBvParam(l) || !isBvParam(r)) {
2439 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_slt", line_number);
2440 return mkUnknown();
2441 }
2442
2443 if (l->isCBV() && r->isCBV()) {
2444 return BitVectorUtils::bvComp(l->toString(), r->toString(), NODE_KIND::NT_BV_SLT)
2445 ? mkTrue()
2446 : mkFalse();
2447 }
2448 else if (l == r) {
2449 return mkFalse();
2450 }
2451
2453}
2454/*
2455(bvsle Bv Bv), return Bool
2456*/
2457std::shared_ptr<DAGNode> Parser::mkBvSle(std::shared_ptr<DAGNode> l,
2458 std::shared_ptr<DAGNode> r) {
2459 if (!isBvParam(l) || !isBvParam(r)) {
2460 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_sle", line_number);
2461 return mkUnknown();
2462 }
2463
2464 if (l->isCBV() && r->isCBV()) {
2465 return BitVectorUtils::bvComp(l->toString(), r->toString(), NODE_KIND::NT_BV_SLE)
2466 ? mkTrue()
2467 : mkFalse();
2468 }
2469 else if (l == r) {
2470 return mkTrue();
2471 }
2472
2474}
2475/*
2476(bvsgt Bv Bv), return Bool
2477*/
2478std::shared_ptr<DAGNode> Parser::mkBvSgt(std::shared_ptr<DAGNode> l,
2479 std::shared_ptr<DAGNode> r) {
2480 if (!isBvParam(l) || !isBvParam(r)) {
2481 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_sgt", line_number);
2482 return mkUnknown();
2483 }
2484
2485 if (l->isCBV() && r->isCBV()) {
2486 return BitVectorUtils::bvComp(l->toString(), r->toString(), NODE_KIND::NT_BV_SGT)
2487 ? mkTrue()
2488 : mkFalse();
2489 }
2490 else if (l == r) {
2491 return mkFalse();
2492 }
2493
2495}
2496/*
2497(bvsge Bv Bv), return Bool
2498*/
2499std::shared_ptr<DAGNode> Parser::mkBvSge(std::shared_ptr<DAGNode> l,
2500 std::shared_ptr<DAGNode> r) {
2501 if (!isBvParam(l) || !isBvParam(r)) {
2502 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_sge", line_number);
2503 return mkUnknown();
2504 }
2505
2506 if (l->isCBV() && r->isCBV()) {
2507 return BitVectorUtils::bvComp(l->toString(), r->toString(), NODE_KIND::NT_BV_SGE)
2508 ? mkTrue()
2509 : mkFalse();
2510 }
2511 else if (l == r) {
2512 return mkTrue();
2513 }
2514
2516}
2517// BITVECTOR CONVERSION
2518/*
2519(bv2nat Bv), return Nat
2520*/
2521std::shared_ptr<DAGNode> Parser::mkBvToNat(std::shared_ptr<DAGNode> param) {
2522 if (!isBvParam(param)) {
2523 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_to_nat", line_number);
2524 return mkUnknown();
2525 }
2526
2528}
2529/*
2530(nat2bv Nat Int), return Bv
2531*/
2532std::shared_ptr<DAGNode> Parser::mkNatToBv(std::shared_ptr<DAGNode> param,
2533 std::shared_ptr<DAGNode> size) {
2534 if (!isIntParam(param) || !isIntParam(size)) {
2535 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in nat_to_bv", line_number);
2536 return mkUnknown();
2537 }
2538 std::shared_ptr<Sort> new_sort =
2539 sort_manager->createBVSort(toInt(size).toULong());
2540 return mkOper(new_sort, NODE_KIND::NT_NAT_TO_BV, param, size);
2541}
2542/*
2543(bv2int Bv), return Int
2544*/
2545std::shared_ptr<DAGNode> Parser::mkBvToInt(std::shared_ptr<DAGNode> param) {
2546 if (!isBvParam(param)) {
2547 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in bv_to_int", line_number);
2548 return mkUnknown();
2549 }
2551}
2552
2553std::shared_ptr<DAGNode> Parser::mkUbvToInt(std::shared_ptr<DAGNode> param) {
2554 if (!isBvParam(param)) {
2555 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in ubv_to_int", line_number);
2556 return mkUnknown();
2557 }
2559}
2560
2561std::shared_ptr<DAGNode> Parser::mkSbvToInt(std::shared_ptr<DAGNode> param) {
2562 if (!isBvParam(param)) {
2563 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in sbv_to_int", line_number);
2564 return mkUnknown();
2565 }
2567}
2568/*
2569(int2bv Int Int), return Bv
2570*/
2571std::shared_ptr<DAGNode> Parser::mkIntToBv(std::shared_ptr<DAGNode> param,
2572 std::shared_ptr<DAGNode> size) {
2573 if (!isIntParam(param) || !isIntParam(size)) {
2574 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in int_to_bv", line_number);
2575 return mkUnknown();
2576 }
2577 std::shared_ptr<Sort> new_sort =
2578 sort_manager->createBVSort(toInt(size).toULong());
2579 return mkOper(new_sort, NODE_KIND::NT_INT_TO_BV, param, size);
2580}
2581
2582// FLOATING POINT COMMON OPERATORS
2583/*
2584(fp.add RoundingMode FloatingPoint FloatingPoint), return FloatingPoint
2585*/
2586std::shared_ptr<DAGNode>
2587Parser::mkFpAdd(const std::vector<std::shared_ptr<DAGNode>> &params) {
2588 if (params.size() != 3) {
2590 "fp.add requires exactly 3 parameters: RoundingMode, "
2591 "FloatingPoint, FloatingPoint",
2592 line_number);
2593 return mkUnknown();
2594 }
2595
2596 if (params[0]->isErr() || params[1]->isErr() || params[2]->isErr()) {
2597 return params[0]->isErr() ? params[0]
2598 : (params[1]->isErr() ? params[1] : params[2]);
2599 }
2600
2601 if (!params[0]->getSort()->isRoundingMode()) {
2603 "First parameter of fp.add must be a rounding mode",
2604 line_number);
2605 return mkUnknown();
2606 }
2607
2608 if (!isFpParam(params[1]) || !isFpParam(params[2])) {
2609 err_all(
2611 "Second and third parameters of fp.add must be floating point numbers",
2612 line_number);
2613 return mkUnknown();
2614 }
2615
2616 std::shared_ptr<Sort> result_sort = params[1]->getSort();
2617 if (!(*result_sort == *params[2]->getSort())) {
2619 "Floating point operands must have the same sort",
2620 line_number);
2621 return mkUnknown();
2622 }
2623
2624 return mkOper(result_sort, NODE_KIND::NT_FP_ADD, params);
2625}
2626/*
2627(fp.sub RoundingMode FloatingPoint FloatingPoint), return FloatingPoint
2628*/
2629std::shared_ptr<DAGNode>
2630Parser::mkFpSub(const std::vector<std::shared_ptr<DAGNode>> &params) {
2631 if (params.size() != 3) {
2633 "fp.sub requires exactly 3 parameters: RoundingMode, "
2634 "FloatingPoint, FloatingPoint",
2635 line_number);
2636 return mkUnknown();
2637 }
2638
2639 if (params[0]->isErr() || params[1]->isErr() || params[2]->isErr()) {
2640 return params[0]->isErr() ? params[0]
2641 : (params[1]->isErr() ? params[1] : params[2]);
2642 }
2643
2644 if (!params[0]->getSort()->isRoundingMode()) {
2646 "First parameter of fp.sub must be a rounding mode",
2647 line_number);
2648 return mkUnknown();
2649 }
2650
2651 if (!isFpParam(params[1]) || !isFpParam(params[2])) {
2652 err_all(
2654 "Second and third parameters of fp.sub must be floating point numbers",
2655 line_number);
2656 return mkUnknown();
2657 }
2658
2659 std::shared_ptr<Sort> result_sort = params[1]->getSort();
2660 if (!(*result_sort == *params[2]->getSort())) {
2662 "Floating point operands must have the same sort",
2663 line_number);
2664 return mkUnknown();
2665 }
2666
2667 return mkOper(result_sort, NODE_KIND::NT_FP_SUB, params);
2668}
2669/*
2670(fp.mul RoundingMode FloatingPoint FloatingPoint), return FloatingPoint
2671*/
2672std::shared_ptr<DAGNode>
2673Parser::mkFpMul(const std::vector<std::shared_ptr<DAGNode>> &params) {
2674 if (params.size() != 3) {
2676 "fp.mul requires exactly 3 parameters: RoundingMode, "
2677 "FloatingPoint, FloatingPoint",
2678 line_number);
2679 return mkUnknown();
2680 }
2681
2682 if (params[0]->isErr() || params[1]->isErr() || params[2]->isErr()) {
2683 return params[0]->isErr() ? params[0]
2684 : (params[1]->isErr() ? params[1] : params[2]);
2685 }
2686
2687 if (!params[0]->getSort()->isRoundingMode()) {
2689 "First parameter of fp.mul must be a rounding mode",
2690 line_number);
2691 return mkUnknown();
2692 }
2693
2694 if (!isFpParam(params[1]) || !isFpParam(params[2])) {
2695 err_all(
2697 "Second and third parameters of fp.mul must be floating point numbers",
2698 line_number);
2699 return mkUnknown();
2700 }
2701
2702 std::shared_ptr<Sort> result_sort = params[1]->getSort();
2703 if (!(*result_sort == *params[2]->getSort())) {
2705 "Floating point operands must have the same sort",
2706 line_number);
2707 return mkUnknown();
2708 }
2709
2710 return mkOper(result_sort, NODE_KIND::NT_FP_MUL, params);
2711}
2712/*
2713(fp.div RoundingMode FloatingPoint FloatingPoint), return FloatingPoint
2714*/
2715std::shared_ptr<DAGNode>
2716Parser::mkFpDiv(const std::vector<std::shared_ptr<DAGNode>> &params) {
2717 if (params.size() != 3) {
2719 "fp.div requires exactly 3 parameters: RoundingMode, "
2720 "FloatingPoint, FloatingPoint",
2721 line_number);
2722 return mkUnknown();
2723 }
2724
2725 if (params[0]->isErr() || params[1]->isErr() || params[2]->isErr()) {
2726 return params[0]->isErr() ? params[0]
2727 : (params[1]->isErr() ? params[1] : params[2]);
2728 }
2729
2730 if (!params[0]->getSort()->isRoundingMode()) {
2732 "First parameter of fp.div must be a rounding mode",
2733 line_number);
2734 return mkUnknown();
2735 }
2736
2737 if (!isFpParam(params[1]) || !isFpParam(params[2])) {
2738 err_all(
2740 "Second and third parameters of fp.div must be floating point numbers",
2741 line_number);
2742 return mkUnknown();
2743 }
2744
2745 std::shared_ptr<Sort> result_sort = params[1]->getSort();
2746 if (!(*result_sort == *params[2]->getSort())) {
2748 "Floating point operands must have the same sort",
2749 line_number);
2750 return mkUnknown();
2751 }
2752
2753 return mkOper(result_sort, NODE_KIND::NT_FP_DIV, params);
2754}
2755/*
2756(fp.abs Fp), return Fp
2757*/
2758std::shared_ptr<DAGNode> Parser::mkFpAbs(std::shared_ptr<DAGNode> param) {
2759 if (!isFpParam(param)) {
2760 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_abs", line_number);
2761 return mkUnknown();
2762 }
2763
2764 return mkOper(param->getSort(), NODE_KIND::NT_FP_ABS, param);
2765}
2766/*
2767(fp.neg Fp), return Fp
2768*/
2769std::shared_ptr<DAGNode> Parser::mkFpNeg(std::shared_ptr<DAGNode> param) {
2770 if (!isFpParam(param)) {
2771 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_neg", line_number);
2772 return mkUnknown();
2773 }
2774
2775 return mkOper(param->getSort(), NODE_KIND::NT_FP_NEG, param);
2776}
2777/*
2778(fp.rem Fp Fp), return Fp
2779*/
2780std::shared_ptr<DAGNode> Parser::mkFpRem(std::shared_ptr<DAGNode> l,
2781 std::shared_ptr<DAGNode> r) {
2782 if (!isFpParam(l) || !isFpParam(r)) {
2783 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_rem", line_number);
2784 return mkUnknown();
2785 }
2786
2787 return mkOper(l->getSort(), NODE_KIND::NT_FP_REM, l, r);
2788}
2789/*
2790(fp.fma RoundingMode Fp Fp Fp), return Fp
2791*/
2792std::shared_ptr<DAGNode>
2793Parser::mkFpFma(const std::vector<std::shared_ptr<DAGNode>> &params) {
2794 if (params.size() != 4) {
2796 "fp.fma requires exactly 4 parameters: RoundingMode Fp Fp Fp",
2797 line_number);
2798 return mkUnknown();
2799 }
2800
2801 // Check if first parameter is rounding mode
2802 if (!params[0]->getSort()->isRoundingMode()) {
2804 "First parameter must be a rounding mode in fp.fma",
2805 line_number);
2806 return mkUnknown();
2807 }
2808
2809 // Check if other parameters are floating point
2810 for (size_t i = 1; i < params.size(); i++) {
2811 if (params[i]->isErr())
2812 return params[i];
2813 if (!isFpParam(params[i])) {
2815 "Parameters 2-4 must be floating point in fp.fma",
2816 line_number);
2817 return mkUnknown();
2818 }
2819 }
2820
2821 // All floating point parameters should have the same sort
2822 std::shared_ptr<Sort> sort = params[1]->getSort();
2823 for (size_t i = 2; i < params.size(); i++) {
2824 if (!(*params[i]->getSort() == *sort)) {
2826 "All floating point parameters must have the same sort in fp.fma",
2827 line_number);
2828 return mkUnknown();
2829 }
2830 }
2831
2832 return mkOper(sort, NODE_KIND::NT_FP_FMA, params);
2833}
2834/*
2835(fp.sqrt RoundingMode Fp), return Fp
2836*/
2837std::shared_ptr<DAGNode> Parser::mkFpSqrt(std::shared_ptr<DAGNode> rm,
2838 std::shared_ptr<DAGNode> param) {
2839 if (rm->isErr() || param->isErr())
2840 return rm->isErr() ? rm : param;
2841
2842 if (!isFpParam(param)) {
2843 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_sqrt", line_number);
2844 return mkUnknown();
2845 }
2846
2847 return mkOper(param->getSort(), NODE_KIND::NT_FP_SQRT, rm, param);
2848}
2849/*
2850(fp.sqrt Fp), return Fp
2851*/
2852std::shared_ptr<DAGNode> Parser::mkFpSqrt(std::shared_ptr<DAGNode> param) {
2853 if (!isFpParam(param)) {
2854 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_sqrt", line_number);
2855 return mkUnknown();
2856 }
2857
2858 return mkOper(param->getSort(), NODE_KIND::NT_FP_SQRT, param);
2859}
2860/*
2861(fp.roundToIntegral RoundingMode Fp), return Fp
2862*/
2863std::shared_ptr<DAGNode>
2864Parser::mkFpRoundToIntegral(std::shared_ptr<DAGNode> rm,
2865 std::shared_ptr<DAGNode> param) {
2866 if (rm->isErr() || param->isErr())
2867 return rm->isErr() ? rm : param;
2868
2869 if (!isFpParam(param)) {
2870 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_roundToIntegral", line_number);
2871 return mkUnknown();
2872 }
2873
2874 return mkOper(param->getSort(), NODE_KIND::NT_FP_ROUND_TO_INTEGRAL, rm, param);
2875}
2876/*
2877(fp.roundToIntegral Fp), return Fp
2878*/
2879std::shared_ptr<DAGNode>
2880Parser::mkFpRoundToIntegral(std::shared_ptr<DAGNode> param) {
2881 if (!isFpParam(param)) {
2882 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_roundToIntegral", line_number);
2883 return mkUnknown();
2884 }
2885
2886 return mkOper(param->getSort(), NODE_KIND::NT_FP_ROUND_TO_INTEGRAL, param);
2887}
2888/*
2889(fp.min Fp+), return Fp
2890*/
2891std::shared_ptr<DAGNode> Parser::mkFpMin(std::shared_ptr<DAGNode> l,
2892 std::shared_ptr<DAGNode> r) {
2893 std::shared_ptr<Sort> sort = getSort(l, r);
2894
2895 if (sort == nullptr) {
2896 sort = l->getSort();
2897 }
2898
2899 return mkOper(sort, NODE_KIND::NT_FP_MIN, l, r);
2900}
2901/*
2902(fp.max Fp+), return Fp
2903*/
2904std::shared_ptr<DAGNode> Parser::mkFpMax(std::shared_ptr<DAGNode> l,
2905 std::shared_ptr<DAGNode> r) {
2906 std::shared_ptr<Sort> sort = getSort(l, r);
2907
2908 if (sort == nullptr) {
2909 sort = l->getSort();
2910 }
2911
2912 return mkOper(sort, NODE_KIND::NT_FP_MAX, l, r);
2913}
2914// FLOATING POINT COMP
2915/*
2916(fp.leq Fp Fp), return Bool
2917*/
2918std::shared_ptr<DAGNode>
2919Parser::mkFpLe(const std::vector<std::shared_ptr<DAGNode>> &params) {
2920 // if (!isFpParam(l) || !isFpParam(r)) {
2921 // err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_le",
2922 // line_number); return mkUnknown();
2923 // }
2924 // Note: Cannot simplify (fp.le x x) to true because x might be NaN, and (NaN
2925 // <= NaN) is false
2926
2928}
2929/*
2930(fp.lt Fp Fp), return Bool
2931*/
2932std::shared_ptr<DAGNode>
2933Parser::mkFpLt(const std::vector<std::shared_ptr<DAGNode>> &params) {
2934 // if (!isFpParam(l) || !isFpParam(r)) {
2935 // err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_lt",
2936 // line_number); return mkUnknown();
2937 // }
2938 // Note: Cannot simplify (fp.lt x x) to false without knowing if x is NaN
2939 // While the result is always false, we should not simplify at parse time
2940 // std::cout << "mkFpLt called" << std::endl;
2942}
2943/*
2944(fp.geq Fp Fp), return Bool
2945*/
2946std::shared_ptr<DAGNode>
2947Parser::mkFpGe(const std::vector<std::shared_ptr<DAGNode>> &params) {
2948 // if (!isFpParam(l) || !isFpParam(r)) {
2949 // err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_ge",
2950 // line_number); return mkUnknown();
2951 // }
2952 // Note: Cannot simplify (fp.ge x x) to true because x might be NaN, and (NaN
2953 // >= NaN) is false std::cout << "mkFpGe called" << std::endl;
2955}
2956/*
2957(fp.gt Fp Fp), return Bool
2958*/
2959std::shared_ptr<DAGNode>
2960Parser::mkFpGt(const std::vector<std::shared_ptr<DAGNode>> &params) {
2961 // if (!isFpParam(l) || !isFpParam(r)) {
2962 // err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_gt",
2963 // line_number); return mkUnknown();
2964 // }
2965 // Note: Cannot simplify (fp.gt x x) to false without knowing if x is NaN
2966 // While the result is always false, we should not simplify at parse time
2968}
2969/*
2970(fp.eq Fp Fp), return Bool
2971*/
2972std::shared_ptr<DAGNode>
2973Parser::mkFpEq(const std::vector<std::shared_ptr<DAGNode>> &params) {
2974 // if (!isFpParam(l) || !isFpParam(r)) {
2975 // err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_eq",
2976 // line_number); return mkUnknown();
2977 // }
2978 // Note: Cannot simplify (fp.eq x x) to true because x might be NaN, and (NaN
2979 // == NaN) is false per IEEE-754
2980
2982}
2983// FLOATING POINT CONVERSION
2984/*
2985(fp.to_ubv Fp), return Bv
2986*/
2987std::shared_ptr<DAGNode> Parser::mkFpToUbv(std::shared_ptr<DAGNode> rm,
2988 std::shared_ptr<DAGNode> param,
2989 std::shared_ptr<DAGNode> size) {
2990 if (!rm->getSort()->isRoundingMode() || !isFpParam(param) ||
2991 !isIntParam(size)) {
2992 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_to_ubv", line_number);
2993 return mkUnknown();
2994 }
2995
2996 if (param->isCBV() && size->isCBV()) {
2997 return mkConstBv(
2998 FloatingPointUtils::fpToUbv(param->toString(), toInt(size)),
2999 toInt(size).toULong());
3000 }
3001
3002 std::shared_ptr<Sort> new_sort =
3003 sort_manager->createBVSort(toInt(size).toULong());
3004
3005 return mkOper(new_sort, NODE_KIND::NT_FP_TO_UBV, rm, param, size);
3006}
3007std::shared_ptr<DAGNode> Parser::mkFpToSbv(std::shared_ptr<DAGNode> rm,
3008 std::shared_ptr<DAGNode> param,
3009 std::shared_ptr<DAGNode> size) {
3010 if (!rm->getSort()->isRoundingMode() || !isFpParam(param) ||
3011 !isIntParam(size)) {
3012 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_to_sbv", line_number);
3013 return mkUnknown();
3014 }
3015
3016 if (param->isCBV() && size->isCBV()) {
3017 return mkConstBv(
3018 FloatingPointUtils::fpToSbv(param->toString(), toInt(size)),
3019 toInt(size).toULong());
3020 }
3021
3022 std::shared_ptr<Sort> new_sort =
3023 sort_manager->createBVSort(toInt(size).toULong());
3024
3025 return mkOper(new_sort, NODE_KIND::NT_FP_TO_SBV, rm, param, size);
3026}
3027std::shared_ptr<DAGNode> Parser::mkFpToReal(std::shared_ptr<DAGNode> param) {
3028 if (!isFpParam(param)) {
3029 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_to_real", line_number);
3030 return mkUnknown();
3031 }
3032
3034}
3035/*
3036(to_fp eb sb param), return Fp
3037Supports:
30381. ((_ to_fp eb sb) RoundingMode Real) -> params: [eb, sb], args: [RoundingMode,
3039Real]
30402. ((_ to_fp eb sb) RoundingMode (_ BitVec m)) -> params: [eb, sb], args:
3041[RoundingMode, BitVec]
30423. ((_ to_fp eb sb) (_ BitVec m)) -> params: [eb, sb], args: [BitVec]
3043*/
3044std::shared_ptr<DAGNode> Parser::mkToFp(std::shared_ptr<DAGNode> eb,
3045 std::shared_ptr<DAGNode> sb,
3046 std::shared_ptr<DAGNode> rm,
3047 std::shared_ptr<DAGNode> param) {
3048 if (eb->isErr() || sb->isErr() || rm->isErr() || param->isErr())
3049 return eb->isErr() ? eb : (sb->isErr() ? sb : (rm->isErr() ? rm : param));
3050
3051 // Validate eb and sb are integers
3052 if (!eb->isCInt() && !eb->isConst()) {
3054 "Exponent width must be an integer in to_fp",
3055 line_number);
3056 return mkUnknown();
3057 }
3058 if (!sb->isCInt() && !sb->isConst()) {
3060 "Significand width must be an integer in to_fp",
3061 line_number);
3062 return mkUnknown();
3063 }
3064
3065 // Validate rounding mode
3066 if (!rm->getSort()->isRoundingMode()) {
3068 "Third parameter must be a rounding mode in to_fp",
3069 line_number);
3070 return mkUnknown();
3071 }
3072
3073 // Get floating point sort
3074 size_t exponent_width = toInt(eb).toULong();
3075 size_t significand_width = toInt(sb).toULong();
3076 std::shared_ptr<Sort> sort =
3077 sort_manager->createFPSort(exponent_width, significand_width);
3078
3079 // Validate param type
3080 if (!isRealParam(param) && !isBvParam(param) && !isFpParam(param)) {
3082 "Fourth parameter must be Real, BitVec, or FloatingPoint in to_fp",
3083 line_number);
3084 return mkUnknown();
3085 }
3086
3087 std::vector<std::shared_ptr<DAGNode>> params = {eb, sb, rm, param};
3088 return mkOper(sort, NODE_KIND::NT_FP_TO_FP, params);
3089}
3090
3091std::shared_ptr<DAGNode> Parser::mkToFp(std::shared_ptr<DAGNode> eb,
3092 std::shared_ptr<DAGNode> sb,
3093 std::shared_ptr<DAGNode> param) {
3094 if (eb->isErr() || sb->isErr() || param->isErr())
3095 return eb->isErr() ? eb : (sb->isErr() ? sb : param);
3096
3097 // Validate eb and sb are integers
3098 if (!eb->isCInt() && !eb->isConst()) {
3100 "Exponent width must be an integer in to_fp",
3101 line_number);
3102 return mkUnknown();
3103 }
3104 if (!sb->isCInt() && !sb->isConst()) {
3106 "Significand width must be an integer in to_fp",
3107 line_number);
3108 return mkUnknown();
3109 }
3110
3111 // Get floating point sort
3112 size_t exponent_width = toInt(eb).toULong();
3113 size_t significand_width = toInt(sb).toULong();
3114 std::shared_ptr<Sort> sort =
3115 sort_manager->createFPSort(exponent_width, significand_width);
3116
3117 // Validate param type (must be BitVec for this overload)
3118 if (!isBvParam(param)) {
3119 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Parameter must be BitVec in to_fp", line_number);
3120 return mkUnknown();
3121 }
3122
3123 return mkOper(sort, NODE_KIND::NT_FP_TO_FP, eb, sb, param);
3124}
3125/*
3126((_ to_fp_unsigned eb sb) RoundingMode (_ BitVec m)), return Fp
3127*/
3128std::shared_ptr<DAGNode>
3129Parser::mkToFpUnsigned(std::shared_ptr<DAGNode> eb, std::shared_ptr<DAGNode> sb, std::shared_ptr<DAGNode> rm, std::shared_ptr<DAGNode> param) {
3130 if (eb->isErr() || sb->isErr() || rm->isErr() || param->isErr())
3131 return eb->isErr() ? eb : (sb->isErr() ? sb : (rm->isErr() ? rm : param));
3132
3133 if (!eb->isCInt() && !eb->isConst()) {
3135 "Exponent width must be an integer in to_fp_unsigned",
3136 line_number);
3137 return mkUnknown();
3138 }
3139 if (!sb->isCInt() && !sb->isConst()) {
3140 // std::cout << kindToString(sb->getKind()) << std::endl;
3142 "Significand width must be an integer in to_fp_unsigned",
3143 line_number);
3144 return mkUnknown();
3145 }
3146
3147 size_t exponent_width = toInt(eb).toULong();
3148 size_t significand_width = toInt(sb).toULong();
3149 std::shared_ptr<Sort> sort =
3150 sort_manager->createFPSort(exponent_width, significand_width);
3151
3152 if (!rm->getSort()->isRoundingMode()) {
3154 "Third parameter must be a rounding mode in to_fp_unsigned",
3155 line_number);
3156 return mkUnknown();
3157 }
3158
3159 if (!isBvParam(param)) {
3161 "Fourth parameter must be BitVec in to_fp_unsigned",
3162 line_number);
3163 return mkUnknown();
3164 }
3165
3166 std::vector<std::shared_ptr<DAGNode>> params = {eb, sb, rm, param};
3167 return mkOper(sort, NODE_KIND::NT_FP_TO_FP_UNSIGNED, params);
3168}
3169/*
3170(fp sign exp mant), return Fp
3171*/
3172std::shared_ptr<DAGNode> Parser::mkFpConst(std::shared_ptr<DAGNode> sign,
3173 std::shared_ptr<DAGNode> exp,
3174 std::shared_ptr<DAGNode> mant) {
3175 if (sign->isErr() || exp->isErr() || mant->isErr())
3176 return sign->isErr() ? sign : (exp->isErr() ? exp : mant);
3177
3178 if (!isBvParam(sign) || !isBvParam(exp) || !isBvParam(mant)) {
3180 "All parameters must be BitVec in fp constant",
3181 line_number);
3182 return mkUnknown();
3183 }
3184
3185 size_t sign_width = sign->getSort()->getBitWidth();
3186 size_t exp_width = exp->getSort()->getBitWidth();
3187 size_t mant_width = mant->getSort()->getBitWidth();
3188
3189 if (sign_width != 1) {
3190 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Sign bit must be 1 bit wide", line_number);
3191 return mkUnknown();
3192 }
3193
3194 std::shared_ptr<Sort> sort =
3195 sort_manager->createFPSort(exp_width, mant_width + 1);
3196 std::vector<std::shared_ptr<DAGNode>> children = {sign, exp, mant};
3197 return node_manager->createNode(sort, NODE_KIND::NT_CONST, "(fp_bit_representation)", children);
3198}
3199// FLOATING POINT PROPERTIES
3200/*
3201(fp.isNormal Fp), return Bool
3202*/
3203std::shared_ptr<DAGNode> Parser::mkFpIsNormal(std::shared_ptr<DAGNode> param) {
3204 if (!isFpParam(param)) {
3205 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_isNormal", line_number);
3206 return mkUnknown();
3207 }
3208
3210}
3211/*
3212(fp.isSubnormal Fp), return Bool
3213*/
3214std::shared_ptr<DAGNode>
3215Parser::mkFpIsSubnormal(std::shared_ptr<DAGNode> param) {
3216 if (!isFpParam(param)) {
3217 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_isSubnormal", line_number);
3218 return mkUnknown();
3219 }
3220
3222}
3223/*
3224(fp.isZero Fp), return Bool
3225*/
3226std::shared_ptr<DAGNode> Parser::mkFpIsZero(std::shared_ptr<DAGNode> param) {
3227 if (!isFpParam(param)) {
3228 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_isZero", line_number);
3229 return mkUnknown();
3230 }
3231
3233}
3234/*
3235(fp.isInfinite Fp), return Bool
3236*/
3237std::shared_ptr<DAGNode> Parser::mkFpIsInf(std::shared_ptr<DAGNode> param) {
3238 if (!isFpParam(param)) {
3239 err_all(param, "Expected floating-point parameter", line_number);
3240 return mkUnknown();
3241 }
3242
3244}
3245/*
3246(fp.isNaN Fp), return Bool
3247*/
3248std::shared_ptr<DAGNode> Parser::mkFpIsNaN(std::shared_ptr<DAGNode> param) {
3249 if (!isFpParam(param)) {
3250 err_all(param, "Expected floating-point parameter", line_number);
3251 return mkUnknown();
3252 }
3253
3255}
3256/*
3257(fp.isNegative Fp), return Bool
3258*/
3259std::shared_ptr<DAGNode> Parser::mkFpIsNeg(std::shared_ptr<DAGNode> param) {
3260 if (!isFpParam(param)) {
3261 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_isNeg", line_number);
3262 return mkUnknown();
3263 }
3264
3266}
3267/*
3268(fp.isPositive Fp), return Bool
3269*/
3270std::shared_ptr<DAGNode> Parser::mkFpIsPos(std::shared_ptr<DAGNode> param) {
3271 if (!isFpParam(param)) {
3272 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in fp_isPos", line_number);
3273 return mkUnknown();
3274 }
3275
3277}
3278// ARRAY
3279/*
3280(select Array Int/BV), return Int/BV
3281*/
3282std::shared_ptr<DAGNode> Parser::mkSelect(std::shared_ptr<DAGNode> l,
3283 std::shared_ptr<DAGNode> r) {
3284 if (!isArrayParam(l)) {
3285 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in select", line_number);
3286 return mkUnknown();
3287 }
3288
3289 return mkOper(l->getSort()->getElemSort(), NODE_KIND::NT_SELECT, l, r);
3290}
3291/*
3292(store Array Int Int), return Array
3293*/
3294std::shared_ptr<DAGNode> Parser::mkStore(std::shared_ptr<DAGNode> l,
3295 std::shared_ptr<DAGNode> r,
3296 std::shared_ptr<DAGNode> v) {
3297 if (l->isErr() || r->isErr() || v->isErr())
3298 return l->isErr() ? l : r;
3299 // if (!isArrayParam(l) || (!isIntParam(r) && !isBvParam(r))) {
3300 // err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in store",
3301 // line_number); return mkUnknown();
3302 // }
3303
3304 return mkOper(l->getSort(), NODE_KIND::NT_STORE, l, r, v);
3305}
3306// STRINGS COMMON OPERATORS
3307/*
3308(str.len Str), return Nat
3309*/
3310std::shared_ptr<DAGNode> Parser::mkStrLen(std::shared_ptr<DAGNode> param) {
3311 if (!isStrParam(param)) {
3312 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_len", line_number);
3313 return mkUnknown();
3314 }
3315
3317}
3318/*
3319(str.++ Str Str+), return Str
3320*/
3321std::shared_ptr<DAGNode>
3322Parser::mkStrConcat(const std::vector<std::shared_ptr<DAGNode>> &params) {
3323 if (params.size() == 0) {
3324 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for str_concat", line_number);
3325 return mkUnknown();
3326 }
3327 else if (params.size() == 1) {
3328 return params[0];
3329 }
3330 std::vector<std::shared_ptr<DAGNode>> new_params;
3331
3332 for (size_t i = 0; i < params.size(); i++) {
3333 if (params[i]->isErr())
3334 return params[i];
3335 if (!isStrParam(params[i])) {
3336 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_concat", line_number);
3337 return mkUnknown();
3338 }
3339 new_params.emplace_back(params[i]);
3340 }
3341
3342 if (new_params.size() == 0)
3343 return mkConstStr("");
3344 if (new_params.size() == 1)
3345 return new_params[0];
3347}
3348/*
3349(str.substr Str Int Int), return Str
3350*/
3351std::shared_ptr<DAGNode> Parser::mkStrSubstr(std::shared_ptr<DAGNode> l,
3352 std::shared_ptr<DAGNode> r,
3353 std::shared_ptr<DAGNode> s) {
3354 if (l->isErr() || r->isErr() || s->isErr())
3355 return l->isErr() ? l : r;
3356 if (!isStrParam(l) || !isIntParam(r) || !isIntParam(s)) {
3357 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_substr", line_number);
3358 return mkUnknown();
3359 }
3360
3361 return mkOper(l->getSort(), NODE_KIND::NT_STR_SUBSTR, l, r, s);
3362}
3363/*
3364(str.prefixof Str Str), return Bool
3365*/
3366std::shared_ptr<DAGNode> Parser::mkStrPrefixof(std::shared_ptr<DAGNode> l,
3367 std::shared_ptr<DAGNode> r) {
3368 if (!isStrParam(l) || !isStrParam(r)) {
3369 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_prefixof", line_number);
3370 return mkUnknown();
3371 }
3372
3374}
3375/*
3376(str.suffixof Str Str), return Bool
3377*/
3378std::shared_ptr<DAGNode> Parser::mkStrSuffixof(std::shared_ptr<DAGNode> l,
3379 std::shared_ptr<DAGNode> r) {
3380 if (!isStrParam(l) || !isStrParam(r)) {
3381 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_suffixof", line_number);
3382 return mkUnknown();
3383 }
3384
3386}
3387/*
3388(str.indexof Str Str Int), return Int
3389*/
3390std::shared_ptr<DAGNode> Parser::mkStrIndexof(std::shared_ptr<DAGNode> l,
3391 std::shared_ptr<DAGNode> r,
3392 std::shared_ptr<DAGNode> s) {
3393 if (l->isErr() || r->isErr() || s->isErr())
3394 return l->isErr() ? l : r;
3395 if (!isStrParam(l) || !isStrParam(r) || !isIntParam(s)) {
3396 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_indexof", line_number);
3397 return mkUnknown();
3398 }
3399
3401}
3402/*
3403(str.at Str Int), return Str
3404*/
3405std::shared_ptr<DAGNode> Parser::mkStrCharat(std::shared_ptr<DAGNode> l,
3406 std::shared_ptr<DAGNode> r) {
3407 if (!isStrParam(l) || !isIntParam(r)) {
3408 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_charat", line_number);
3409 return mkUnknown();
3410 }
3411
3413}
3414/*
3415(str.update Str Int Str), return Str
3416*/
3417std::shared_ptr<DAGNode> Parser::mkStrUpdate(std::shared_ptr<DAGNode> l,
3418 std::shared_ptr<DAGNode> r,
3419 std::shared_ptr<DAGNode> v) {
3420 if (l->isErr() || r->isErr() || v->isErr())
3421 return l->isErr() ? l : r;
3422 if (!isStrParam(l) || !isIntParam(r) || !isStrParam(v)) {
3423 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_update", line_number);
3424 return mkUnknown();
3425 }
3426
3427 return mkOper(l->getSort(), NODE_KIND::NT_STR_UPDATE, l, r, v);
3428}
3429/*
3430(str.replace Str Str Str), return Str
3431*/
3432std::shared_ptr<DAGNode> Parser::mkStrReplace(std::shared_ptr<DAGNode> l,
3433 std::shared_ptr<DAGNode> r,
3434 std::shared_ptr<DAGNode> v) {
3435 if (l->isErr() || r->isErr() || v->isErr())
3436 return l->isErr() ? l : r;
3437 if (!isStrParam(l) || !isStrParam(r) || !isStrParam(v)) {
3438 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_replace", line_number);
3439 return mkUnknown();
3440 }
3441
3442 return mkOper(l->getSort(), NODE_KIND::NT_STR_REPLACE, l, r, v);
3443}
3444/*
3445(str.replace_all Str Str Str), return Str
3446*/
3447std::shared_ptr<DAGNode> Parser::mkStrReplaceAll(std::shared_ptr<DAGNode> l,
3448 std::shared_ptr<DAGNode> r,
3449 std::shared_ptr<DAGNode> v) {
3450 if (!isStrParam(l)) {
3451 err_all(l, "Expected string parameter", line_number);
3452 return mkUnknown();
3453 }
3454 if (!isStrParam(r)) {
3455 err_all(r, "Expected string parameter", line_number);
3456 return mkUnknown();
3457 }
3458 if (!isStrParam(v)) {
3459 err_all(v, "Expected string parameter", line_number);
3460 return mkUnknown();
3461 }
3462 return mkOper(l->getSort(), NODE_KIND::NT_STR_REPLACE_ALL, l, r, v);
3463}
3464/*
3465(str.replace_re Str Reg Str), return Str
3466*/
3467std::shared_ptr<DAGNode> Parser::mkStrReplaceReg(std::shared_ptr<DAGNode> l,
3468 std::shared_ptr<DAGNode> r,
3469 std::shared_ptr<DAGNode> v) {
3470 if (l->isErr() || r->isErr() || v->isErr())
3471 return l->isErr() ? l : r;
3472 if (!isStrParam(l) || !isRegParam(r) || !isStrParam(v)) {
3473 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_replace_re", line_number);
3474 return mkUnknown();
3475 }
3476 return mkOper(l->getSort(), NODE_KIND::NT_STR_REPLACE_REG, l, r, v);
3477}
3478
3479/*
3480(str.replace_re_all Str Reg Str), return Str
3481*/
3482std::shared_ptr<DAGNode>
3483Parser::mkStrReplaceRegAll(std::shared_ptr<DAGNode> l,
3484 std::shared_ptr<DAGNode> r,
3485 std::shared_ptr<DAGNode> v) {
3486 if (l->isErr() || r->isErr() || v->isErr())
3487 return l->isErr() ? l : r;
3488 if (!isStrParam(l) || !isRegParam(r) || !isStrParam(v)) {
3489 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_replace_re_all", line_number);
3490 return mkUnknown();
3491 }
3492 return mkOper(l->getSort(), NODE_KIND::NT_STR_REPLACE_REG_ALL, l, r, v);
3493}
3494
3495/*
3496(str.indexof_re Str Reg), return Int
3497*/
3498std::shared_ptr<DAGNode> Parser::mkStrIndexofReg(std::shared_ptr<DAGNode> l,
3499 std::shared_ptr<DAGNode> r) {
3500 if (l->isErr() || r->isErr())
3501 return l->isErr() ? l : r;
3502 if (!isStrParam(l) || !isRegParam(r)) {
3503 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_indexof_re", line_number);
3504 return mkUnknown();
3505 }
3507}
3508
3509/*
3510(str.to_lower Str), return Str
3511*/
3512std::shared_ptr<DAGNode> Parser::mkStrToLower(std::shared_ptr<DAGNode> param) {
3513 if (!isStrParam(param)) {
3514 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_to_lower", line_number);
3515 return mkUnknown();
3516 }
3517
3519}
3520/*
3521(str.to_upper Str), return Str
3522*/
3523std::shared_ptr<DAGNode> Parser::mkStrToUpper(std::shared_ptr<DAGNode> param) {
3524 if (!isStrParam(param)) {
3525 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_to_upper", line_number);
3526 return mkUnknown();
3527 }
3528
3530}
3531/*
3532(str.rev Str), return Str
3533*/
3534std::shared_ptr<DAGNode> Parser::mkStrRev(std::shared_ptr<DAGNode> param) {
3535 if (!isStrParam(param)) {
3536 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_rev", line_number);
3537 return mkUnknown();
3538 }
3539
3541}
3542/*
3543(str.split Str Str), return (_ Array Int Str)
3544*/
3545std::shared_ptr<DAGNode> Parser::mkStrSplit(std::shared_ptr<DAGNode> l,
3546 std::shared_ptr<DAGNode> r) {
3547 if (!isStrParam(l) || !isStrParam(r)) {
3548 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_split", line_number);
3549 return mkUnknown();
3550 }
3551 return mkOper(sort_manager->createArraySort(SortManager::INT_SORT,
3554 l,
3555 r);
3556}
3557std::shared_ptr<DAGNode> Parser::mkStrSplitAt(std::shared_ptr<DAGNode> l,
3558 std::shared_ptr<DAGNode> r,
3559 std::shared_ptr<DAGNode> s) {
3560 if (!isStrParam(l) || !isStrParam(r) || !isIntParam(s)) {
3561 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_split_at", line_number);
3562 return mkUnknown();
3563 }
3565}
3566std::shared_ptr<DAGNode> Parser::mkStrSplitRest(std::shared_ptr<DAGNode> l,
3567 std::shared_ptr<DAGNode> r,
3568 std::shared_ptr<DAGNode> s) {
3569 if (!isStrParam(l) || !isStrParam(r) || !isIntParam(s)) {
3570 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_split_rest", line_number);
3571 return mkUnknown();
3572 }
3574}
3575std::shared_ptr<DAGNode> Parser::mkStrNumSplits(std::shared_ptr<DAGNode> l,
3576 std::shared_ptr<DAGNode> r) {
3577 if (!isStrParam(l) || !isStrParam(r)) {
3578 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_num_splits", line_number);
3579 return mkUnknown();
3580 }
3582}
3583/*
3584(str.split_at_re Str Reg Int), return Str
3585*/
3586std::shared_ptr<DAGNode> Parser::mkStrSplitAtRe(std::shared_ptr<DAGNode> l,
3587 std::shared_ptr<DAGNode> r,
3588 std::shared_ptr<DAGNode> s) {
3589 if (!isStrParam(l) || !isRegParam(r) || !isIntParam(s)) {
3590 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_split_at_re", line_number);
3591 return mkUnknown();
3592 }
3594}
3595/*
3596(str.split_rest_re Str Reg Int), return Str
3597*/
3598std::shared_ptr<DAGNode> Parser::mkStrSplitRestRe(std::shared_ptr<DAGNode> l,
3599 std::shared_ptr<DAGNode> r,
3600 std::shared_ptr<DAGNode> s) {
3601 if (!isStrParam(l) || !isRegParam(r) || !isIntParam(s)) {
3602 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_split_rest_re", line_number);
3603 return mkUnknown();
3604 }
3606}
3607/*
3608(str.num_splits_re Str Reg), return Int
3609*/
3610std::shared_ptr<DAGNode> Parser::mkStrNumSplitsRe(std::shared_ptr<DAGNode> l,
3611 std::shared_ptr<DAGNode> r) {
3612 if (!isStrParam(l) || !isRegParam(r)) {
3613 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_num_splits_re", line_number);
3614 return mkUnknown();
3615 }
3617}
3618// STRINGS COMP
3619/*
3620(str.< Str Str), return Bool
3621*/
3622std::shared_ptr<DAGNode>
3623Parser::mkStrLt(const std::vector<std::shared_ptr<DAGNode>> &params) {
3624 // if (!isStrParam(l) || !isStrParam(r)) {
3625 // err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_lt",
3626 // line_number); return mkUnknown();
3627 // }
3629}
3630/*
3631(str.<= Str Str), return Bool
3632*/
3633std::shared_ptr<DAGNode>
3634Parser::mkStrLe(const std::vector<std::shared_ptr<DAGNode>> &params) {
3636}
3637/*
3638(str.> Str Str), return Bool
3639*/
3640std::shared_ptr<DAGNode>
3641Parser::mkStrGt(const std::vector<std::shared_ptr<DAGNode>> &params) {
3643}
3644/*
3645(str.>= Str Str), return Bool
3646*/
3647std::shared_ptr<DAGNode>
3648Parser::mkStrGe(const std::vector<std::shared_ptr<DAGNode>> &params) {
3649 std::vector<std::shared_ptr<DAGNode>> nparams(params.rbegin(), params.rend());
3651}
3652// STRINGS PROPERTIES
3653/*
3654(str.in_re Str Reg), return Bool
3655*/
3656std::shared_ptr<DAGNode> Parser::mkStrInReg(std::shared_ptr<DAGNode> l,
3657 std::shared_ptr<DAGNode> r) {
3658 if (!isStrParam(l)) {
3659 err_all(l, "Expected string parameter", line_number);
3660 return mkUnknown();
3661 }
3662 if (!isRegParam(r)) {
3663 err_all(r, "Expected regex parameter", line_number);
3664 return mkUnknown();
3665 }
3667}
3668/*
3669(str.contains Str Str), return Bool
3670*/
3671std::shared_ptr<DAGNode> Parser::mkStrContains(std::shared_ptr<DAGNode> l,
3672 std::shared_ptr<DAGNode> r) {
3673 if (!isStrParam(l) || !isStrParam(r)) {
3674 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_contains", line_number);
3675 return mkUnknown();
3676 }
3677
3679}
3680/*
3681(str.is_digit Str), return Bool
3682*/
3683std::shared_ptr<DAGNode> Parser::mkStrIsDigit(std::shared_ptr<DAGNode> param) {
3684 if (!isStrParam(param)) {
3685 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_is_digit", line_number);
3686 return mkUnknown();
3687 }
3688
3690}
3691// STRINGS CONVERSION
3692std::shared_ptr<DAGNode> Parser::mkStrFromInt(std::shared_ptr<DAGNode> param) {
3693 if (!isIntParam(param)) {
3694 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_from_int", line_number);
3695 return mkUnknown();
3696 }
3697
3699}
3700/*
3701(str.to_int Str), return Int
3702*/
3703std::shared_ptr<DAGNode> Parser::mkStrToInt(std::shared_ptr<DAGNode> param) {
3704 if (!isStrParam(param)) {
3705 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_to_int", line_number);
3706 return mkUnknown();
3707 }
3708
3710}
3711/*
3712(str.to_re Str), return Reg
3713*/
3714std::shared_ptr<DAGNode> Parser::mkStrToReg(std::shared_ptr<DAGNode> param) {
3715 if (!isStrParam(param)) {
3716 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_to_reg", line_number);
3717 return mkUnknown();
3718 }
3719
3721}
3722/*
3723(str.to_code Str), return Int
3724*/
3725std::shared_ptr<DAGNode> Parser::mkStrToCode(std::shared_ptr<DAGNode> param) {
3726 if (!isStrParam(param)) {
3727 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_to_code", line_number);
3728 return mkUnknown();
3729 }
3730
3732}
3733/*
3734(str.from_code Int), return Str
3735*/
3736std::shared_ptr<DAGNode> Parser::mkStrFromCode(std::shared_ptr<DAGNode> param) {
3737 if (!isIntParam(param)) {
3738 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_from_code", line_number);
3739 return mkUnknown();
3740 }
3741
3743}
3744// STRINGS RE CONSTANTS
3745std::shared_ptr<DAGNode> Parser::mkRegNone() { return mkConstReg("re.none"); }
3746std::shared_ptr<DAGNode> Parser::mkRegAll() { return mkConstReg("re.all"); }
3747std::shared_ptr<DAGNode> Parser::mkRegAllChar() {
3748 return mkConstReg("re.allchar");
3749}
3750// STRINGS RE COMMON OPERATORS
3751/*
3752(re.++ Reg Reg+), return Reg
3753*/
3754std::shared_ptr<DAGNode>
3755Parser::mkRegConcat(const std::vector<std::shared_ptr<DAGNode>> &params) {
3756 if (params.size() == 0) {
3757 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for reg_concat", line_number);
3758 return mkUnknown();
3759 }
3760 else if (params.size() == 1) {
3761 return params[0];
3762 }
3763 std::vector<std::shared_ptr<DAGNode>> new_params;
3764
3765 for (size_t i = 0; i < params.size(); i++) {
3766 if (params[i]->isErr())
3767 return params[i];
3768 if (!isRegParam(params[i])) {
3769 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_concat", line_number);
3770 return mkUnknown();
3771 }
3772 new_params.emplace_back(params[i]);
3773 }
3774
3776}
3777/*
3778(re.union Reg Reg+), return Reg
3779*/
3780std::shared_ptr<DAGNode>
3781Parser::mkRegUnion(const std::vector<std::shared_ptr<DAGNode>> &params) {
3782 if (params.size() == 0) {
3783 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for reg_union", line_number);
3784 return mkUnknown();
3785 }
3786 else if (params.size() == 1) {
3787 return params[0];
3788 }
3789 std::vector<std::shared_ptr<DAGNode>> new_params;
3790
3791 for (size_t i = 0; i < params.size(); i++) {
3792 if (params[i]->isErr())
3793 return params[i];
3794 if (!isRegParam(params[i])) {
3795 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_union", line_number);
3796 return mkUnknown();
3797 }
3798 new_params.emplace_back(params[i]);
3799 }
3800
3802}
3803/*
3804(re.inter Reg Reg+), return Reg
3805*/
3806std::shared_ptr<DAGNode>
3807Parser::mkRegInter(const std::vector<std::shared_ptr<DAGNode>> &params) {
3808 if (params.size() == 0) {
3809 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for reg_inter", line_number);
3810 return mkUnknown();
3811 }
3812 else if (params.size() == 1) {
3813 return params[0];
3814 }
3815 std::vector<std::shared_ptr<DAGNode>> new_params;
3816
3817 for (size_t i = 0; i < params.size(); i++) {
3818 if (params[i]->isErr())
3819 return params[i];
3820 if (!isRegParam(params[i])) {
3821 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_inter", line_number);
3822 return mkUnknown();
3823 }
3824 new_params.emplace_back(params[i]);
3825 }
3826
3828}
3829/*
3830(re.diff Reg Reg), return Reg
3831*/
3832std::shared_ptr<DAGNode>
3833Parser::mkRegDiff(const std::vector<std::shared_ptr<DAGNode>> &params) {
3834 if (params.size() != 2) {
3835 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for reg_diff", line_number);
3836 return mkUnknown();
3837 }
3838 if (params[0]->isErr() || params[1]->isErr())
3839 return params[0]->isErr() ? params[0] : params[1];
3840 if (!isRegParam(params[0]) || !isRegParam(params[1])) {
3841 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_diff", line_number);
3842 return mkUnknown();
3843 }
3844
3845 return mkOper(SortManager::REG_SORT, NODE_KIND::NT_REG_DIFF, params[0], params[1]);
3846}
3847/*
3848(re.* Reg), return Reg
3849*/
3850std::shared_ptr<DAGNode> Parser::mkRegStar(std::shared_ptr<DAGNode> param) {
3851 if (!isRegParam(param)) {
3852 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_star", line_number);
3853 return mkUnknown();
3854 }
3855
3857}
3858/*
3859(re.+ Reg), return Reg
3860*/
3861std::shared_ptr<DAGNode> Parser::mkRegPlus(std::shared_ptr<DAGNode> param) {
3862 if (!isRegParam(param)) {
3863 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_plus", line_number);
3864 return mkUnknown();
3865 }
3866
3868}
3869/*
3870(re.opt Reg), return Reg
3871*/
3872std::shared_ptr<DAGNode> Parser::mkRegOpt(std::shared_ptr<DAGNode> param) {
3873 if (!isRegParam(param)) {
3874 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_opt", line_number);
3875 return mkUnknown();
3876 }
3877
3879}
3880/*
3881(re.range Str Str), return Reg
3882*/
3883std::shared_ptr<DAGNode> Parser::mkRegRange(std::shared_ptr<DAGNode> l,
3884 std::shared_ptr<DAGNode> r) {
3885 if (!isStrParam(l) || !isStrParam(r)) {
3886 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_range", line_number);
3887 return mkUnknown();
3888 }
3889
3891}
3892/*
3893(reg.^n Reg Int), return Reg
3894*/
3895std::shared_ptr<DAGNode> Parser::mkRegRepeat(std::shared_ptr<DAGNode> l,
3896 std::shared_ptr<DAGNode> r) {
3897 // e.g. (re.^ (str.to.re "a") 3)
3898
3899 if (!isRegParam(l) || !isIntParam(r)) {
3900 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_repeat", line_number);
3901 return mkUnknown();
3902 }
3903
3905}
3906/*
3907(re.loop Reg Int Int), return Reg
3908*/
3909std::shared_ptr<DAGNode> Parser::mkRegLoop(std::shared_ptr<DAGNode> l,
3910 std::shared_ptr<DAGNode> r,
3911 std::shared_ptr<DAGNode> s) {
3912 if (l->isErr() || r->isErr() || s->isErr())
3913 return l->isErr() ? l : r;
3914 if (!isRegParam(l) || !isIntParam(r) || !isIntParam(s)) {
3915 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_loop", line_number);
3916 return mkUnknown();
3917 }
3918
3920}
3921/*
3922(re.comp Reg), return Reg
3923*/
3924std::shared_ptr<DAGNode>
3925Parser::mkRegComplement(std::shared_ptr<DAGNode> param) {
3926 if (!isRegParam(param)) {
3927 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in reg_complement", line_number);
3928 return mkUnknown();
3929 }
3930
3932}
3933// STRINGS RE FUNCTIONS
3934/*
3935(str.replace_re Str Reg Str), return Str
3936*/
3937std::shared_ptr<DAGNode> Parser::mkReplaceReg(std::shared_ptr<DAGNode> l,
3938 std::shared_ptr<DAGNode> r,
3939 std::shared_ptr<DAGNode> v) {
3940 if (l->isErr() || r->isErr() || v->isErr())
3941 return l->isErr() ? l : r;
3942 if (!isStrParam(l) || !isRegParam(r) || !isStrParam(v)) {
3943 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_replace_re", line_number);
3944 return mkUnknown();
3945 }
3946
3948}
3949/*
3950(str.replace_re_all Str Reg Str), return Str
3951*/
3952std::shared_ptr<DAGNode> Parser::mkReplaceRegAll(std::shared_ptr<DAGNode> l,
3953 std::shared_ptr<DAGNode> r,
3954 std::shared_ptr<DAGNode> v) {
3955 if (l->isErr() || r->isErr() || v->isErr())
3956 return l->isErr() ? l : r;
3957 if (!isStrParam(l) || !isRegParam(r) || !isStrParam(v)) {
3958 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_replace_re_all", line_number);
3959 return mkUnknown();
3960 }
3961
3963}
3964/*
3965(str.indexof_re Str Reg), return Int
3966*/
3967std::shared_ptr<DAGNode> Parser::mkIndexofReg(std::shared_ptr<DAGNode> l,
3968 std::shared_ptr<DAGNode> r) {
3969 if (!isStrParam(l) || !isRegParam(r)) {
3970 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in str_indexof_re", line_number);
3971 return mkUnknown();
3972 }
3973
3975}
3976
3977// INTERVAL
3978std::shared_ptr<DAGNode>
3979Parser::mkMax(const std::vector<std::shared_ptr<DAGNode>> &params) {
3980 if (params.size() == 0) {
3981 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for max", line_number);
3982 return mkUnknown();
3983 }
3984 else if (params.size() == 1) {
3985 return params[0];
3986 }
3987 std::shared_ptr<Sort> sort = getSort(params);
3988
3989 std::vector<std::shared_ptr<DAGNode>> new_params;
3990
3991 // pair-wise comparison: (< a b c d) <=> (and (< a b) (< b c) (< c d))
3992 for (size_t i = 0; i < params.size() - 1; i++) {
3993 if (params[i]->isErr())
3994 return params[i];
3995 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
3996 if (canExempt(params[i]->getSort(), sort)) {
3997 std::cerr << "Type mismatch in max, but now exempt for int/real"
3998 << std::endl;
3999 }
4000 else {
4001 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in max", line_number);
4002 return mkUnknown();
4003 }
4004 }
4005 new_params.emplace_back(params[i]);
4006 }
4007
4008 return mkOper(sort, NODE_KIND::NT_MAX, new_params);
4009}
4010std::shared_ptr<DAGNode>
4011Parser::mkMin(const std::vector<std::shared_ptr<DAGNode>> &params) {
4012 if (params.size() == 0) {
4013 err_all(ERROR_TYPE::ERR_PARAM_MIS, "Not enough parameters for min", line_number);
4014 return mkUnknown();
4015 }
4016 else if (params.size() == 1) {
4017 return params[0];
4018 }
4019 std::shared_ptr<Sort> sort = getSort(params);
4020
4021 std::vector<std::shared_ptr<DAGNode>> new_params;
4022
4023 // pair-wise comparison: (< a b c d) <=> (and (< a b) (< b c) (< c d))
4024 for (size_t i = 0; i < params.size() - 1; i++) {
4025 if (params[i]->isErr())
4026 return params[i];
4027 if (sort != nullptr && !params[i]->getSort()->isEqTo(sort)) {
4028 if (canExempt(params[i]->getSort(), sort)) {
4029 std::cerr << "Type mismatch in min, but now exempt for int/real"
4030 << std::endl;
4031 }
4032 else {
4033 err_all(ERROR_TYPE::ERR_TYPE_MIS, "Type mismatch in min", line_number);
4034 return mkUnknown();
4035 }
4036 }
4037 new_params.emplace_back(params[i]);
4038 }
4039
4040 return mkOper(sort, NODE_KIND::NT_MIN, new_params);
4041}
4042
4044 switch (k) {
4045 // zero-ary
4046 case NODE_KIND::NT_NULL:
4048 case NODE_KIND::NT_VAR:
4057 case NODE_KIND::NT_NAN:
4065 return 0;
4066
4067 // unary
4069 case NODE_KIND::NT_NOT:
4070 case NODE_KIND::NT_NEG:
4071 case NODE_KIND::NT_ABS:
4072 case NODE_KIND::NT_SQRT:
4074 case NODE_KIND::NT_CEIL:
4077 case NODE_KIND::NT_EXP:
4078 case NODE_KIND::NT_LN:
4079 case NODE_KIND::NT_LG:
4080 case NODE_KIND::NT_LB:
4081 case NODE_KIND::NT_SIN:
4082 case NODE_KIND::NT_COS:
4083 case NODE_KIND::NT_SEC:
4084 case NODE_KIND::NT_CSC:
4085 case NODE_KIND::NT_TAN:
4086 case NODE_KIND::NT_COT:
4087 case NODE_KIND::NT_ASIN:
4088 case NODE_KIND::NT_ACOS:
4089 case NODE_KIND::NT_ASEC:
4090 case NODE_KIND::NT_ACSC:
4091 case NODE_KIND::NT_ATAN:
4092 case NODE_KIND::NT_ACOT:
4093 case NODE_KIND::NT_SINH:
4094 case NODE_KIND::NT_COSH:
4095 case NODE_KIND::NT_TANH:
4096 case NODE_KIND::NT_SECH:
4097 case NODE_KIND::NT_CSCH:
4098 case NODE_KIND::NT_COTH:
4111 case NODE_KIND::NT_FACT:
4143 case NODE_KIND::NT_POW2:
4144 return 1;
4145
4146 // binary
4147 case NODE_KIND::NT_POW:
4148 case NODE_KIND::NT_MOD:
4149 case NODE_KIND::NT_LOG:
4152 case NODE_KIND::NT_GCD:
4153 case NODE_KIND::NT_LCM:
4187
4204 return 2;
4205
4206 // ternary
4207 case NODE_KIND::NT_ITE:
4229 return 3;
4230
4231 // 4-ary
4233 return 4;
4234
4235 // n-ary
4236 case NODE_KIND::NT_LE:
4237 case NODE_KIND::NT_LT:
4238 case NODE_KIND::NT_GE:
4239 case NODE_KIND::NT_GT:
4240 case NODE_KIND::NT_EQ:
4252 case NODE_KIND::NT_AND:
4253 case NODE_KIND::NT_OR:
4255 case NODE_KIND::NT_XOR:
4256 case NODE_KIND::NT_ADD:
4257 case NODE_KIND::NT_MUL:
4258 case NODE_KIND::NT_IAND:
4259 case NODE_KIND::NT_SUB:
4283 case NODE_KIND::NT_MAX:
4284 case NODE_KIND::NT_MIN:
4285 return -1;
4286 case NODE_KIND::NT_FP_TO_FP: // 3 or 4
4287 return -2;
4288
4289 default:
4290 return -1;
4291 }
4292}
4293
4294// ROOT OBJECT
4295std::shared_ptr<DAGNode> Parser::mkRootObj(std::shared_ptr<DAGNode> expr,
4296 int index) {
4297 if (expr->isErr())
4298 return expr;
4299
4300 // Create index as integer constant
4301 std::shared_ptr<DAGNode> index_node = mkConstInt(index);
4302
4303 // Create root-obj node with real sort
4304 std::shared_ptr<Sort> sort = SortManager::REAL_SORT;
4305 std::string name =
4306 "root-obj(" + toString(expr) + "," + std::to_string(index) + ")";
4307 std::vector<std::shared_ptr<DAGNode>> children = {expr, index_node};
4308
4309 return node_manager->createNode(sort, NODE_KIND::NT_ROOT_OBJ, name, children);
4310}
4311
4312std::shared_ptr<DAGNode> Parser::mkRootOfWithInterval(
4313 const std::vector<std::shared_ptr<DAGNode>> &coeffs,
4314 std::shared_ptr<DAGNode> lower_bound,
4315 std::shared_ptr<DAGNode> upper_bound) {
4316 if (lower_bound->isErr())
4317 return lower_bound;
4318 if (upper_bound->isErr())
4319 return upper_bound;
4320
4321 // Check if any coefficient has error
4322 for (const auto &coeff : coeffs) {
4323 if (coeff->isErr())
4324 return coeff;
4325 }
4326
4327 // Create root-of-with-interval node with real sort
4328 std::shared_ptr<Sort> sort = SortManager::REAL_SORT;
4329
4330 // Build name string
4331 std::string name = "root-of-with-interval(coeffs:";
4332 for (size_t i = 0; i < coeffs.size(); i++) {
4333 if (i > 0)
4334 name += ",";
4335 name += toString(coeffs[i]);
4336 }
4337 name += ",lb:" + toString(lower_bound) + ",ub:" + toString(upper_bound) + ")";
4338
4339 // Create children vector: coefficients + bounds
4340 std::vector<std::shared_ptr<DAGNode>> children;
4341 children.insert(children.end(), coeffs.begin(), coeffs.end());
4342 children.push_back(lower_bound);
4343 children.push_back(upper_bound);
4344
4345 return node_manager->createNode(sort, NODE_KIND::NT_ROOT_OF_WITH_INTERVAL, name, children);
4346}
4347} // namespace stabilizer::parser
#define condAssert(cond, msg)
Definition asserting.h:35
static bool bvComp(const std::string &bv1, const std::string &bv2, const NODE_KIND &kind)
Definition util.cpp:637
static std::string natToBv(const Integer &i, const Integer &n)
Definition util.cpp:733
static std::string toString(const Integer &i)
Definition util.cpp:1111
static std::string fpToSbv(const std::string &fp, const Integer &n)
Definition util.cpp:923
static std::string fpToUbv(const std::string &fp, const Integer &n)
Definition util.cpp:897
static const std::shared_ptr< DAGNode > E_NODE
Definition dag.h:1279
static const std::shared_ptr< DAGNode > INT_INF_NODE
Definition dag.h:1315
static const std::shared_ptr< DAGNode > STR_NEG_INF_NODE
Definition dag.h:1311
static const std::shared_ptr< DAGNode > POS_EPSILON_NODE
Definition dag.h:1295
static const std::shared_ptr< DAGNode > PI_NODE
Definition dag.h:1281
static const std::shared_ptr< DAGNode > UNKNOWN_NODE
Definition dag.h:1269
static const std::shared_ptr< DAGNode > NAN_NODE
Definition dag.h:1291
static const std::shared_ptr< DAGNode > REAL_INF_NODE
Definition dag.h:1325
static const std::shared_ptr< DAGNode > STR_POS_INF_NODE
Definition dag.h:1307
static const std::shared_ptr< DAGNode > REAL_NEG_INF_NODE
Definition dag.h:1331
static const std::shared_ptr< DAGNode > NEG_EPSILON_NODE
Definition dag.h:1299
static const std::shared_ptr< DAGNode > REAL_POS_INF_NODE
Definition dag.h:1327
static const std::shared_ptr< DAGNode > TRUE_NODE
Definition dag.h:1275
static const std::shared_ptr< DAGNode > STR_INF_NODE
Definition dag.h:1305
static const std::shared_ptr< DAGNode > NULL_NODE
Definition dag.h:1267
static const std::shared_ptr< DAGNode > INT_POS_INF_NODE
Definition dag.h:1317
static const std::shared_ptr< DAGNode > INT_NEG_INF_NODE
Definition dag.h:1321
static const std::shared_ptr< DAGNode > EPSILON_NODE
Definition dag.h:1293
static const std::shared_ptr< DAGNode > FALSE_NODE
Definition dag.h:1277
HighPrecisionInteger toInteger() const
Definition number.cpp:1169
HighPrecisionReal toReal(mpfr_prec_t precision=128) const
Definition number.cpp:1178
std::shared_ptr< DAGNode > mkSelect(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an array select node.
std::shared_ptr< DAGNode > mkBvSub(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector subtraction node.
std::shared_ptr< DAGNode > mkReplaceRegAll(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-all-regex node.
void err_all(const ERROR_TYPE e, const std::string s="", const size_t ln=0) const
std::shared_ptr< DAGNode > mkAnd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an and node.
std::shared_ptr< DAGNode > mkCot(std::shared_ptr< DAGNode > param)
Create a cot node.
std::shared_ptr< GlobalOptions > options
Definition parser.h:242
std::shared_ptr< DAGNode > mkSin(std::shared_ptr< DAGNode > param)
Create an sin node.
std::shared_ptr< DAGNode > mkSbvToInt(std::shared_ptr< DAGNode > param)
std::shared_ptr< DAGNode > mkConstArray(std::shared_ptr< Sort > sort, std::shared_ptr< DAGNode > value)
Create a constant array node.
std::shared_ptr< DAGNode > mkStrLt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string less-than node.
std::shared_ptr< DAGNode > mkFpToSbv(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > size)
Create a floating-point to signed bitvector conversion node.
std::shared_ptr< Sort > mkRealSort()
Create a real sort.
std::shared_ptr< DAGNode > mkAsinh(std::shared_ptr< DAGNode > param)
Create an asinh node.
std::shared_ptr< DAGNode > mkAsec(std::shared_ptr< DAGNode > param)
Create an asec node.
std::shared_ptr< DAGNode > mkCeil(std::shared_ptr< DAGNode > param)
Create an ceil node.
std::shared_ptr< Sort > mkSortDef(const std::string &name, const std::vector< std::shared_ptr< Sort > > &params, std::shared_ptr< Sort > out_sort)
Create a sort definition.
std::unordered_map< std::string, size_t > fun_dup_count_map
Definition parser.h:216
std::shared_ptr< DAGNode > mkLcm(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a lcm node.
std::shared_ptr< DAGNode > mkXor(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an xor node.
std::shared_ptr< DAGNode > mkStrPrefixof(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string prefix check node.
std::unordered_map< std::string, size_t > temp_var_names
Definition parser.h:234
std::shared_ptr< DAGNode > mkStrToReg(std::shared_ptr< DAGNode > param)
Create a string to-regex conversion node.
std::shared_ptr< DAGNode > mkVarBool(const std::string &name)
Create a boolean variable.
std::shared_ptr< DAGNode > mkIntToBv(std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > width)
Create an integer to bitvector conversion node.
bool isOne(std::shared_ptr< DAGNode > expr)
Check if an expression is one.
std::shared_ptr< DAGNode > mkAcsc(std::shared_ptr< DAGNode > param)
Create an acsc node.
std::shared_ptr< DAGNode > mkFpEq(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point equality node.
std::shared_ptr< DAGNode > mkBvAdd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector addition node.
std::shared_ptr< DAGNode > mkStrSplitAt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::shared_ptr< DAGNode > mkBvSmod(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed modulo node.
static std::vector< std::shared_ptr< DAGNode > > sortParams(const std::vector< std::shared_ptr< DAGNode > > &p)
Return sorted operand list for deterministic commutative handling.
std::shared_ptr< DAGNode > mkStrInReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string in-regex check node.
std::shared_ptr< DAGNode > mkBvXnor(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector xnor node.
std::shared_ptr< DAGNode > mkTan(std::shared_ptr< DAGNode > param)
Create an tan node.
std::shared_ptr< DAGNode > mkFalse()
Create a false node.
Definition op_parser.cpp:79
std::shared_ptr< DAGNode > mkGt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a gt node.
std::shared_ptr< DAGNode > mkNegEpsilon()
Create a negative epsilon node.
std::shared_ptr< DAGNode > mkBvSrem(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed remainder node.
std::shared_ptr< DAGNode > mkNegInfinity(std::shared_ptr< Sort > sort=nullptr)
Create a negative infinity node.
std::shared_ptr< DAGNode > mkTanh(std::shared_ptr< DAGNode > param)
Create a tanh node.
std::shared_ptr< DAGNode > mkCsch(std::shared_ptr< DAGNode > param)
Create a csch node.
std::shared_ptr< DAGNode > mkIsInt(std::shared_ptr< DAGNode > param)
Create a is_int node.
std::shared_ptr< DAGNode > mkNot(std::shared_ptr< DAGNode > param)
Create a not node.
std::shared_ptr< DAGNode > mkBvSdiv(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed division node.
std::shared_ptr< DAGNode > mkVarRoundingMode(const std::string &name)
Create a rounding mode variable.
std::shared_ptr< DAGNode > mkBvUlt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned less than node.
std::shared_ptr< DAGNode > mkIsOdd(std::shared_ptr< DAGNode > param)
Create a is_odd node.
std::shared_ptr< DAGNode > mkSec(std::shared_ptr< DAGNode > param)
Create an sec node.
std::shared_ptr< DAGNode > mkUbvToInt(std::shared_ptr< DAGNode > param)
std::shared_ptr< DAGNode > mkStrReplaceReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-regex node.
std::shared_ptr< DAGNode > mkLb(std::shared_ptr< DAGNode > param)
Create an lb/log2 node.
std::shared_ptr< DAGNode > mkBvZeroExt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector zero extension node.
std::shared_ptr< DAGNode > mkEpsilon()
Create a epsilon node.
std::shared_ptr< DAGNode > mkMul(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an mul node.
std::shared_ptr< DAGNode > mkVarInt(const std::string &name)
Create an integer variable.
std::shared_ptr< DAGNode > mkRegInter(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex intersection node.
std::shared_ptr< DAGNode > mkLe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a le node.
std::shared_ptr< Sort > mkFPSort(const size_t &e, const size_t &s)
Create a floating-point sort.
std::shared_ptr< DAGNode > mkStrContains(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string contains check node.
std::shared_ptr< DAGNode > mkFpIsSubnormal(std::shared_ptr< DAGNode > param)
Create a floating-point is-subnormal check node.
std::shared_ptr< DAGNode > mkInternalOper(const std::shared_ptr< Sort > &sort, const NODE_KIND &t, const std::vector< std::shared_ptr< DAGNode > > &p)
std::shared_ptr< DAGNode > mkRegAll()
Create a regex all node.
std::shared_ptr< DAGNode > mkStore(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create an array store node.
std::shared_ptr< DAGNode > mkFpRoundToIntegral(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
Create a floating-point round to integral node.
std::shared_ptr< DAGNode > mkRegOpt(std::shared_ptr< DAGNode > param)
Create a regex option node.
std::shared_ptr< DAGNode > mkRegLoop(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a regex loop node.
std::shared_ptr< DAGNode > mkMax(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a max node.
std::shared_ptr< DAGNode > mkRegUnion(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex union node.
std::shared_ptr< DAGNode > mkRegDiff(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex difference node.
std::shared_ptr< Sort > mkArraySort(std::shared_ptr< Sort > index, std::shared_ptr< Sort > elem)
Create an array sort.
std::shared_ptr< DAGNode > mkDistinct(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a distinct node.
std::shared_ptr< DAGNode > mkFpDiv(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point division node.
std::shared_ptr< DAGNode > mkAcsch(std::shared_ptr< DAGNode > param)
Create an acsch node.
std::shared_ptr< Sort > placeholder_var_sort
Definition parser.h:195
std::shared_ptr< DAGNode > mkFpSqrt(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
Create a floating-point square root node.
Integer toInt(std::shared_ptr< DAGNode > expr)
Convert an expression to an integer.
std::unordered_map< std::string, std::shared_ptr< DAGNode > > preserving_let_key_map
Definition parser.h:208
std::shared_ptr< DAGNode > mkIsEven(std::shared_ptr< DAGNode > param)
Create a is_even node.
std::shared_ptr< DAGNode > mkTrue()
Create a true node.
Definition op_parser.cpp:78
std::shared_ptr< DAGNode > mkAsin(std::shared_ptr< DAGNode > param)
Create an asin node.
std::shared_ptr< DAGNode > mkAcosh(std::shared_ptr< DAGNode > param)
Create an acosh node.
std::shared_ptr< DAGNode > mkVarStr(const std::string &name)
Create a string variable.
std::shared_ptr< DAGNode > mkStrCharat(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string char-at node.
std::string toString(std::shared_ptr< DAGNode > expr)
Print an expression.
std::shared_ptr< DAGNode > mkBvToNat(std::shared_ptr< DAGNode > param)
Create a bitvector to natural number conversion node.
std::shared_ptr< DAGNode > mkRegRepeat(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a regex repeat node.
std::shared_ptr< DAGNode > mkSub(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an sub node.
std::shared_ptr< DAGNode > mkBvNot(std::shared_ptr< DAGNode > param)
Create a bitvector not node.
std::shared_ptr< Sort > mkNatSort()
Create a natural sort.
std::shared_ptr< DAGNode > mkRegConcat(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex concatenation node.
std::unordered_map< std::string, size_t > var_names
Definition parser.h:231
std::shared_ptr< DAGNode > mkFpIsZero(std::shared_ptr< DAGNode > param)
Create a floating-point is-zero check node.
std::shared_ptr< DAGNode > mkInfinity(std::shared_ptr< Sort > sort)
Create a infinity node.
std::shared_ptr< DAGNode > mkStrSubstr(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a string substring node.
std::shared_ptr< DAGNode > mkConstBv(const std::string &v, const size_t &width)
Create a bit-vector constant.
std::unordered_map< std::string, std::shared_ptr< Sort > > sort_key_map
Definition parser.h:212
std::shared_ptr< DAGNode > mkFpRem(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a floating-point remainder node.
std::shared_ptr< DAGNode > mkBvRotateLeft(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector rotate left node.
std::shared_ptr< DAGNode > mkPosInfinity(std::shared_ptr< Sort > sort=nullptr)
Create a positive infinity node.
std::shared_ptr< DAGNode > mkBvToInt(std::shared_ptr< DAGNode > param)
Create a bitvector to integer conversion node.
std::shared_ptr< DAGNode > mkBvNeg(std::shared_ptr< DAGNode > param)
Create a bitvector negation node.
std::shared_ptr< Sort > mkStrSort()
Create a string sort.
std::shared_ptr< DAGNode > mkStrReplace(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace node.
std::shared_ptr< DAGNode > mkIndexofReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string index-of-regex node.
std::shared_ptr< DAGNode > mkConstReal(const std::string &v)
Create a real constant from string.
std::shared_ptr< Sort > mkSortDec(const std::string &name, const size_t &arity)
Create a sort declaration.
std::shared_ptr< DAGNode > mkRegComplement(std::shared_ptr< DAGNode > param)
Create a regex complement node.
std::shared_ptr< DAGNode > mkDivReal(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an div node.
std::shared_ptr< DAGNode > mkToFp(std::shared_ptr< DAGNode > eb, std::shared_ptr< DAGNode > sb, std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
Create a value to floating-point conversion node.
std::shared_ptr< DAGNode > mkFpMin(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a floating-point minimum node.
std::shared_ptr< DAGNode > mkConstReg(const std::string &v)
Create a regular expression constant.
std::shared_ptr< DAGNode > mkStrSplit(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string split node.
std::shared_ptr< DAGNode > mkFuncDec(const std::string &name, const std::vector< std::shared_ptr< Sort > > &params, std::shared_ptr< Sort > out_sort)
Create a function declaration.
std::shared_ptr< DAGNode > mkFpConst(std::shared_ptr< DAGNode > sign, std::shared_ptr< DAGNode > exp, std::shared_ptr< DAGNode > mant)
std::shared_ptr< DAGNode > mkCosh(std::shared_ptr< DAGNode > param)
Create a cosh node.
std::shared_ptr< DAGNode > mkFpMax(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a floating-point maximum node.
std::shared_ptr< DAGNode > mkVarBv(const std::string &name, const size_t &width)
Create a bit-vector variable.
std::shared_ptr< DAGNode > mkErr(const ERROR_TYPE t)
std::shared_ptr< DAGNode > mkUnknown()
Create an unknown node.
Definition op_parser.cpp:80
std::shared_ptr< DAGNode > mkFpLt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point less than node.
std::shared_ptr< DAGNode > mkStrGt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string greater-than node.
std::shared_ptr< DAGNode > mkToReal(std::shared_ptr< DAGNode > param)
Create a to_real node.
std::shared_ptr< DAGNode > mkOr(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an or node.
std::shared_ptr< DAGNode > mkBvRepeat(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector repeat node.
std::shared_ptr< DAGNode > mkLetBindVar(const std::string &name, const std::shared_ptr< DAGNode > &expr)
std::shared_ptr< DAGNode > mkIsPrime(std::shared_ptr< DAGNode > param)
Create a is_prime node.
std::shared_ptr< DAGNode > mkBvShl(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector shift left node.
std::shared_ptr< DAGNode > mkAcos(std::shared_ptr< DAGNode > param)
Create an acos node.
std::shared_ptr< DAGNode > mkSafeSqrt(std::shared_ptr< DAGNode > param)
Create an safeSqrt node.
std::shared_ptr< DAGNode > mkStrToUpper(std::shared_ptr< DAGNode > param)
Create a string to-upper node.
std::shared_ptr< DAGNode > mkBvUle(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned less than or equal node.
std::shared_ptr< DAGNode > mkLetBindVarList(const std::vector< std::shared_ptr< DAGNode > > &bind_vars)
std::shared_ptr< DAGNode > mkStrToInt(std::shared_ptr< DAGNode > param)
Create a string to-integer conversion node.
std::shared_ptr< DAGNode > mkBvConcat(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector concatenation node.
std::shared_ptr< DAGNode > mkConstInt(const std::string &v)
Create an integer constant from string.
std::shared_ptr< DAGNode > mkOper(const std::shared_ptr< Sort > &sort, const NODE_KIND &t, std::shared_ptr< DAGNode > p)
Create an operation.
std::shared_ptr< DAGNode > mkIsDivisible(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a is_divisible node.
bool isZero(std::shared_ptr< DAGNode > expr)
Check if an expression is zero.
std::shared_ptr< DAGNode > mkBvComp(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector comparison node.
std::shared_ptr< DAGNode > mkLetChain(const std::vector< std::shared_ptr< DAGNode > > &bind_var_lists, const std::shared_ptr< DAGNode > &body)
std::shared_ptr< DAGNode > mkStrNumSplits(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
std::shared_ptr< DAGNode > mkStrFromCode(std::shared_ptr< DAGNode > param)
Create a string from-code conversion node.
std::shared_ptr< DAGNode > mkFuncDef(const std::string &name, const std::vector< std::shared_ptr< DAGNode > > &params, std::shared_ptr< Sort > out_sort, std::shared_ptr< DAGNode > body)
Create a function definition.
std::shared_ptr< DAGNode > mkBvUrem(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned remainder node.
std::shared_ptr< DAGNode > mkFpToReal(std::shared_ptr< DAGNode > param)
Create a floating-point to real conversion node.
std::shared_ptr< DAGNode > mkSqrt(std::shared_ptr< DAGNode > param)
Create an sqrt node.
std::shared_ptr< DAGNode > mkDiv(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an div node.
std::shared_ptr< DAGNode > mkStrIndexof(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a string index-of node.
std::shared_ptr< DAGNode > mkE()
Create a e node.
std::shared_ptr< DAGNode > mkFpToUbv(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > size)
Create a floating-point to unsigned bitvector conversion node.
std::shared_ptr< DAGNode > mkCos(std::shared_ptr< DAGNode > param)
Create an cos node.
std::shared_ptr< DAGNode > mkFpAdd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point addition node.
std::shared_ptr< DAGNode > mkRegAllChar()
Create a regex allchar node.
std::shared_ptr< DAGNode > mkRootObj(std::shared_ptr< DAGNode > expr, int index)
std::shared_ptr< DAGNode > rewrite_oper(NODE_KIND &t, std::vector< std::shared_ptr< DAGNode > > &p)
Core operation rewrite helper used before node-manager creation.
std::shared_ptr< DAGNode > mkGcd(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a gcd node.
std::shared_ptr< DAGNode > mkToFpUnsigned(std::shared_ptr< DAGNode > eb, std::shared_ptr< DAGNode > sb, std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
std::shared_ptr< DAGNode > mkRootOfWithInterval(const std::vector< std::shared_ptr< DAGNode > > &coeffs, std::shared_ptr< DAGNode > lower_bound, std::shared_ptr< DAGNode > upper_bound)
std::shared_ptr< Sort > mkBVSort(const size_t &width)
Create a bit-vector sort.
std::shared_ptr< DAGNode > mkStrIsDigit(std::shared_ptr< DAGNode > param)
Create a string is-digit check node.
std::shared_ptr< DAGNode > mkGe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a ge node.
std::shared_ptr< DAGNode > mkBvSignExt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector sign extension node.
std::shared_ptr< DAGNode > mkFpGe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point greater than or equal node.
std::shared_ptr< DAGNode > mkTempVar(const std::shared_ptr< Sort > &sort)
Create a temporary variable.
std::shared_ptr< DAGNode > mkPi()
Create a pi node.
std::shared_ptr< DAGNode > mkFact(std::shared_ptr< DAGNode > param)
Create a factorial node.
std::shared_ptr< DAGNode > mkFpIsPos(std::shared_ptr< DAGNode > param)
Create a floating-point is-positive check node.
std::shared_ptr< DAGNode > mkDivInt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an div node.
std::shared_ptr< Sort > mkRegSort()
Create a regular expression sort.
std::shared_ptr< DAGNode > mkArray(const std::string &name, std::shared_ptr< Sort > index, std::shared_ptr< Sort > elem)
Create an array.
std::shared_ptr< DAGNode > mkBvUmod(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned modulo node.
Real toReal(std::shared_ptr< DAGNode > expr)
Convert an expression to a real.
std::shared_ptr< Sort > mkIntSort()
Create an integer sort.
std::shared_ptr< DAGNode > mkFpNeg(std::shared_ptr< DAGNode > param)
Create a floating-point negation node.
std::shared_ptr< DAGNode > mkRegStar(std::shared_ptr< DAGNode > param)
Create a regex star node.
std::shared_ptr< DAGNode > mkStrSplitRestRe(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::shared_ptr< DAGNode > mkStrUpdate(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string update node.
std::shared_ptr< DAGNode > mkBvUdiv(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned division node.
std::shared_ptr< DAGNode > mkRegPlus(std::shared_ptr< DAGNode > param)
Create a regex plus node.
std::shared_ptr< DAGNode > mkVarFp(const std::string &name, const size_t &e, const size_t &s)
Create a floating-point variable.
std::shared_ptr< DAGNode > mkStrConcat(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string concatenation node.
std::shared_ptr< DAGNode > mkEq(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an equality node.
std::shared_ptr< DAGNode > mkBvSlt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed less than node.
std::shared_ptr< DAGNode > mkSinh(std::shared_ptr< DAGNode > param)
Create a sinh node.
std::shared_ptr< DAGNode > mkSech(std::shared_ptr< DAGNode > param)
Create a sech node.
std::shared_ptr< DAGNode > mkBvRotateRight(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector rotate right node.
std::shared_ptr< DAGNode > mkBvOr(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector or node.
std::shared_ptr< DAGNode > mkBvMul(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector multiplication node.
std::shared_ptr< DAGNode > mkLn(std::shared_ptr< DAGNode > param)
Create an ln node.
void err_type_mis(const std::string nm, const size_t ln) const
std::shared_ptr< DAGNode > mkFpIsInf(std::shared_ptr< DAGNode > param)
Create a floating-point is-infinity check node.
std::shared_ptr< DAGNode > mkPow2(std::shared_ptr< DAGNode > param)
Create an pow2 node.
std::shared_ptr< DAGNode > mkConstFP(const std::string &fp_expr)
Create a floating-point constant from expression.
std::shared_ptr< DAGNode > mkFpAbs(std::shared_ptr< DAGNode > param)
Create a floating-point absolute value node.
std::shared_ptr< DAGNode > mkBvExtract(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a bitvector extract node.
std::shared_ptr< DAGNode > mkFpIsNeg(std::shared_ptr< DAGNode > param)
Create a floating-point is-negative check node.
std::shared_ptr< DAGNode > mkBvAshr(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector arithmetic shift right node.
std::shared_ptr< DAGNode > mkVarReg(const std::string &name)
Create a regular expression variable.
std::shared_ptr< DAGNode > mkBvAnd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector and node.
std::shared_ptr< DAGNode > mkBvNor(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector nor node.
std::shared_ptr< DAGNode > mkAcoth(std::shared_ptr< DAGNode > param)
Create an acoth node.
std::shared_ptr< DAGNode > mkRegNone()
Create a regex none node.
std::shared_ptr< DAGNode > mkAtan(std::shared_ptr< DAGNode > param)
Create an atan node.
std::shared_ptr< DAGNode > mkStrLen(std::shared_ptr< DAGNode > param)
Create a string length node.
std::shared_ptr< DAGNode > mkStrLe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string less-than-or-equal node.
std::shared_ptr< DAGNode > mkRound(std::shared_ptr< DAGNode > param)
Create an round node.
std::shared_ptr< DAGNode > mkIte(std::shared_ptr< DAGNode > cond, std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an ite node.
std::shared_ptr< DAGNode > mkStrToLower(std::shared_ptr< DAGNode > param)
Create a string to-lower node.
std::shared_ptr< DAGNode > mkAtanh(std::shared_ptr< DAGNode > param)
Create an atanh node.
std::shared_ptr< DAGNode > mkBvNand(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector nand node.
std::shared_ptr< DAGNode > mkPosEpsilon()
Create a positive epsilon node.
std::unordered_map< std::string, size_t > placeholder_var_names
Definition parser.h:236
std::shared_ptr< DAGNode > mkCoth(std::shared_ptr< DAGNode > param)
Create a coth node.
std::shared_ptr< DAGNode > mkFunParamVar(std::shared_ptr< Sort > sort, const std::string &name)
Create a function parameter variable.
std::shared_ptr< DAGNode > mkToInt(std::shared_ptr< DAGNode > param)
Create a to_int node.
std::shared_ptr< DAGNode > mkStrFromInt(std::shared_ptr< DAGNode > param)
Create a string from-integer conversion node.
std::shared_ptr< DAGNode > mkNaN(std::shared_ptr< Sort > sort=nullptr)
Create a NaN node.
std::shared_ptr< DAGNode > mkAsech(std::shared_ptr< DAGNode > param)
Create an asech node.
std::shared_ptr< DAGNode > mkAdd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an add node.
std::shared_ptr< Sort > mkBoolSort()
Create a boolean sort.
std::shared_ptr< DAGNode > mkBvSle(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed less than or equal node.
std::shared_ptr< DAGNode > mkPow(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an pow node.
std::shared_ptr< DAGNode > mkBvSge(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed greater than or equal node.
std::shared_ptr< DAGNode > mkStrIndexofReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string indexof-regex node.
std::shared_ptr< DAGNode > mkFpFma(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point fused multiply-add node.
std::shared_ptr< DAGNode > mkStrReplaceAll(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-all node.
std::shared_ptr< DAGNode > mkLg(std::shared_ptr< DAGNode > param)
Create an lg/log10 node.
std::shared_ptr< DAGNode > mkBvUge(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned greater than or equal node.
std::shared_ptr< DAGNode > mkBvXor(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector xor node.
std::shared_ptr< DAGNode > mkNatToBv(std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > width)
Create a natural number to bitvector conversion node.
std::shared_ptr< DAGNode > mkStrNumSplitsRe(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
std::shared_ptr< DAGNode > mkFpIsNormal(std::shared_ptr< DAGNode > param)
Create a floating-point is-normal check node.
std::shared_ptr< DAGNode > mkVar(const std::shared_ptr< Sort > &sort, const std::string &name)
Create a variable.
std::shared_ptr< DAGNode > mkLt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a lt node.
std::shared_ptr< DAGNode > mkFpLe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point less than or equal node.
std::shared_ptr< DAGNode > mkFpIsNaN(std::shared_ptr< DAGNode > param)
Create a floating-point is-NaN check node.
std::shared_ptr< DAGNode > mkIand(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an iand node.
std::shared_ptr< DAGNode > mkRegRange(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a regex range node.
std::shared_ptr< DAGNode > mkBvSgt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed greater than node.
std::shared_ptr< DAGNode > mkFpMul(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point multiplication node.
std::shared_ptr< DAGNode > mkReplaceReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-regex node.
std::shared_ptr< DAGNode > mkLog(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an log node.
std::shared_ptr< DAGNode > mkStrGe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string greater-than-or-equal node.
std::shared_ptr< DAGNode > mkStrSplitAtRe(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::unique_ptr< NodeManager > node_manager
Definition parser.h:201
std::shared_ptr< DAGNode > mkStrSuffixof(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string suffix check node.
std::shared_ptr< DAGNode > mkAtan2(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an atan2 node.
std::shared_ptr< DAGNode > mkVarReal(const std::string &name)
Create a real variable.
std::shared_ptr< DAGNode > mkStrToCode(std::shared_ptr< DAGNode > param)
Create a string to-code conversion node.
int getArity(NODE_KIND k) const
Get the arity of a node kind.
std::shared_ptr< DAGNode > mkConstStr(const std::string &v)
Create a string constant.
static bool isCommutative(NODE_KIND t)
Check whether an operation kind is treated as commutative.
Definition op_parser.cpp:84
std::unique_ptr< SortManager > sort_manager
Definition parser.h:203
std::shared_ptr< DAGNode > mkPlaceholderVar(const std::string &name)
std::shared_ptr< DAGNode > mkRoundingMode(const std::string &mode)
Create a rounding mode constant.
std::shared_ptr< DAGNode > mkConstFp(const std::string &v, const size_t &e, const size_t &s)
Create a floating-point constant.
std::shared_ptr< DAGNode > mkStrReplaceRegAll(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-regex-all node.
std::shared_ptr< DAGNode > mkImplies(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an implies node.
std::shared_ptr< DAGNode > mkStrRev(std::shared_ptr< DAGNode > param)
Create a string reverse node.
std::shared_ptr< DAGNode > mkCsc(std::shared_ptr< DAGNode > param)
Create an csc node.
std::shared_ptr< DAGNode > mkBvUgt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned greater than node.
std::shared_ptr< Sort > getSort(const std::vector< std::shared_ptr< DAGNode > > &params)
Get sort.
std::shared_ptr< DAGNode > mkFpGt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point greater than node.
std::unordered_map< std::string, std::shared_ptr< DAGNode > > fun_key_map
Definition parser.h:209
std::shared_ptr< DAGNode > mkFpSub(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point subtraction node.
std::shared_ptr< DAGNode > mkFloor(std::shared_ptr< DAGNode > param)
Create an floor node.
std::shared_ptr< DAGNode > mkAbs(std::shared_ptr< DAGNode > param)
Create an abs node.
std::shared_ptr< DAGNode > declareVar(const std::string &name, const std::string &sort)
Declare a variable.
std::shared_ptr< DAGNode > mkNeg(std::shared_ptr< DAGNode > param)
Create an neg node.
std::shared_ptr< DAGNode > mkExp(std::shared_ptr< DAGNode > param)
Create an exp node.
std::shared_ptr< Sort > mkRoundingModeSort()
Create a rounding mode sort.
std::shared_ptr< DAGNode > mkMin(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a min node.
std::shared_ptr< DAGNode > mkBvLshr(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector logical shift right node.
std::shared_ptr< DAGNode > mkStrSplitRest(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::shared_ptr< DAGNode > mkFuncRec(const std::string &name, const std::vector< std::shared_ptr< DAGNode > > &params, std::shared_ptr< Sort > out_sort, std::shared_ptr< DAGNode > body)
Create a recursive function definition.
std::shared_ptr< DAGNode > mkAcot(std::shared_ptr< DAGNode > param)
Create an acot node.
std::shared_ptr< DAGNode > mkMod(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an mod node.
static const std::shared_ptr< Sort > INTOREAL_SORT
Definition sort.h:408
static const std::shared_ptr< Sort > ROUNDING_MODE_SORT
Definition sort.h:419
static const std::shared_ptr< Sort > STR_SORT
Definition sort.h:398
static const std::shared_ptr< Sort > INT_SORT
Definition sort.h:390
static const std::shared_ptr< Sort > REG_SORT
Definition sort.h:400
static const std::shared_ptr< Sort > BOOL_SORT
Definition sort.h:388
static const std::shared_ptr< Sort > REAL_SORT
Definition sort.h:392
static const std::shared_ptr< Sort > NAT_SORT
Definition sort.h:404
static bool isReal(const std::string &str)
Definition util.cpp:58
bool isRegParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:68
bool isArrayParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:72
std::string kindToString(const NODE_KIND &nk)
Definition kind.cpp:35
HighPrecisionInteger Integer
Definition number.h:136
bool isRealParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:48
bool isStrParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:64
bool isBoolParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:52
bool isIntParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:44
bool canExempt(std::shared_ptr< Sort > l, std::shared_ptr< Sort > r)
bool isBvParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:56
bool isFpParam(std::shared_ptr< DAGNode > param)
Definition op_parser.cpp:60