diff options
author | Aina Niemetz <aina.niemetz@gmail.com> | 2019-01-29 11:47:04 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-29 11:47:04 -0800 |
commit | d4870775e67c7878c32c17f10b1217c14dc5869b (patch) | |
tree | 8e2bcd1a731eab54041724bb9310e1c7aaaf3e4c /src | |
parent | 1eaf6cf987fa1452528dc0598ca7235be735ba3b (diff) |
New C++ API: Fix checks for mkTerm. (#2820)
This required fixing the OpTerm handling for mkTerm functions in the API.
Diffstat (limited to 'src')
-rw-r--r-- | src/api/cvc4cpp.cpp | 173 | ||||
-rw-r--r-- | src/api/cvc4cpp.h | 51 | ||||
-rw-r--r-- | src/api/cvc4cppkind.h | 26 | ||||
-rw-r--r-- | src/expr/expr_manager_template.cpp | 27 |
4 files changed, 182 insertions, 95 deletions
diff --git a/src/api/cvc4cpp.cpp b/src/api/cvc4cpp.cpp index 123613797..ddb17c3a7 100644 --- a/src/api/cvc4cpp.cpp +++ b/src/api/cvc4cpp.cpp @@ -1444,6 +1444,14 @@ DatatypeSelector::DatatypeSelector(const CVC4::DatatypeConstructorArg& stor) DatatypeSelector::~DatatypeSelector() {} +bool DatatypeSelector::isResolved() const { return d_stor->isResolved(); } + +OpTerm DatatypeSelector::getSelectorTerm() const +{ + CVC4_API_CHECK(isResolved()) << "Expected resolved datatype selector."; + return d_stor->getSelector(); +} + std::string DatatypeSelector::toString() const { std::stringstream ss; @@ -1478,10 +1486,10 @@ DatatypeConstructor::~DatatypeConstructor() {} bool DatatypeConstructor::isResolved() const { return d_ctor->isResolved(); } -Term DatatypeConstructor::getConstructorTerm() const +OpTerm DatatypeConstructor::getConstructorTerm() const { CVC4_API_CHECK(isResolved()) << "Expected resolved datatype constructor."; - return Term(d_ctor->getConstructor()); + return OpTerm(d_ctor->getConstructor()); } DatatypeSelector DatatypeConstructor::operator[](const std::string& name) const @@ -1498,7 +1506,7 @@ DatatypeSelector DatatypeConstructor::getSelector(const std::string& name) const return (*d_ctor)[name]; } -Term DatatypeConstructor::getSelectorTerm(const std::string& name) const +OpTerm DatatypeConstructor::getSelectorTerm(const std::string& name) const { // CHECK: cons with name exists? // CHECK: is resolved? @@ -1627,7 +1635,7 @@ DatatypeConstructor Datatype::getConstructor(const std::string& name) const return (*d_dtype)[name]; } -Term Datatype::getConstructorTerm(const std::string& name) const +OpTerm Datatype::getConstructorTerm(const std::string& name) const { // CHECK: cons with name exists? // CHECK: is resolved? @@ -2451,40 +2459,41 @@ void Solver::checkMkTerm(Kind kind, uint32_t nchildren) const << "Only operator-style terms are created with mkTerm(), " "to create variables and constants see mkVar(), mkBoundVar(), " "and mkConst()."; - if (nchildren) - { - const uint32_t n = - nchildren - (mk == CVC4::kind::metakind::PARAMETERIZED ? 1 : 0); - CVC4_API_KIND_CHECK_EXPECTED(n >= minArity(kind) && n <= maxArity(kind), - kind) - << "Terms with kind " << kindToString(kind) << " must have at least " - << minArity(kind) << " children and at most " << maxArity(kind) - << " children (the one under construction has " << n << ")"; - } + CVC4_API_KIND_CHECK_EXPECTED( + nchildren >= minArity(kind) && nchildren <= maxArity(kind), kind) + << "Terms with kind " << kindToString(kind) << " must have at least " + << minArity(kind) << " children and at most " << maxArity(kind) + << " children (the one under construction has " << nchildren << ")"; } -void Solver::checkMkOpTerm(OpTerm opTerm, uint32_t nchildren) const +void Solver::checkMkOpTerm(Kind kind, OpTerm opTerm, uint32_t nchildren) const { - const Kind kind = opTerm.getKind(); Assert(isDefinedIntKind(extToIntKind(kind))); const CVC4::Kind int_kind = extToIntKind(kind); - const CVC4::Kind int_op_kind = + const CVC4::Kind int_op_kind = opTerm.d_expr->getKind(); + const CVC4::Kind int_op_to_kind = NodeManager::operatorToKind(opTerm.d_expr->getNode()); - CVC4_API_ARG_CHECK_EXPECTED(int_kind == kind::BUILTIN - || CVC4::kind::metaKindOf(int_op_kind) - == kind::metakind::PARAMETERIZED, - opTerm) + CVC4_API_ARG_CHECK_EXPECTED( + int_kind == int_op_to_kind + || (kind == APPLY_CONSTRUCTOR + && int_op_to_kind == CVC4::Kind::UNDEFINED_KIND) + || (kind == APPLY_SELECTOR + && int_op_to_kind == CVC4::Kind::UNDEFINED_KIND) + || (kind == APPLY_UF && int_op_to_kind == CVC4::Kind::UNDEFINED_KIND), + kind) + << "kind that matches kind associated with given operator term"; + CVC4_API_ARG_CHECK_EXPECTED( + int_op_kind == CVC4::kind::BUILTIN + || CVC4::kind::metaKindOf(int_kind) == kind::metakind::PARAMETERIZED, + opTerm) << "This term constructor is for parameterized kinds only"; - if (nchildren) - { - uint32_t min_arity = ExprManager::minArity(int_op_kind); - uint32_t max_arity = ExprManager::maxArity(int_op_kind); - CVC4_API_KIND_CHECK_EXPECTED( - nchildren >= min_arity && nchildren <= max_arity, kind) - << "Terms with kind " << kindToString(kind) << " must have at least " - << min_arity << " children and at most " << max_arity - << " children (the one under construction has " << nchildren << ")"; - } + uint32_t min_arity = ExprManager::minArity(int_kind); + uint32_t max_arity = ExprManager::maxArity(int_kind); + CVC4_API_KIND_CHECK_EXPECTED(nchildren >= min_arity && nchildren <= max_arity, + kind) + << "Terms with kind " << kindToString(kind) << " must have at least " + << min_arity << " children and at most " << max_arity + << " children (the one under construction has " << nchildren << ")"; } Term Solver::mkTerm(Kind kind) const @@ -2611,13 +2620,30 @@ Term Solver::mkTerm(Kind kind, const std::vector<Term>& children) const } } -Term Solver::mkTerm(OpTerm opTerm, Term child) const +Term Solver::mkTerm(Kind kind, OpTerm opTerm) const +{ + try + { + checkMkOpTerm(kind, opTerm, 0); + const CVC4::Kind int_kind = extToIntKind(kind); + Term res = d_exprMgr->mkExpr(int_kind, *opTerm.d_expr); + (void)res.d_expr->getType(true); /* kick off type checking */ + return res; + } + catch (const CVC4::TypeCheckingException& e) + { + throw CVC4ApiException(e.getMessage()); + } +} + +Term Solver::mkTerm(Kind kind, OpTerm opTerm, Term child) const { try { CVC4_API_ARG_CHECK_EXPECTED(!child.isNull(), child) << "non-null term"; - checkMkOpTerm(opTerm, 1); - Term res = d_exprMgr->mkExpr(*opTerm.d_expr, *child.d_expr); + checkMkOpTerm(kind, opTerm, 1); + const CVC4::Kind int_kind = extToIntKind(kind); + Term res = d_exprMgr->mkExpr(int_kind, *opTerm.d_expr, *child.d_expr); (void)res.d_expr->getType(true); /* kick off type checking */ return res; } @@ -2627,15 +2653,16 @@ Term Solver::mkTerm(OpTerm opTerm, Term child) const } } -Term Solver::mkTerm(OpTerm opTerm, Term child1, Term child2) const +Term Solver::mkTerm(Kind kind, OpTerm opTerm, Term child1, Term child2) const { try { CVC4_API_ARG_CHECK_EXPECTED(!child1.isNull(), child1) << "non-null term"; CVC4_API_ARG_CHECK_EXPECTED(!child2.isNull(), child2) << "non-null term"; - checkMkOpTerm(opTerm, 2); - Term res = - d_exprMgr->mkExpr(*opTerm.d_expr, *child1.d_expr, *child2.d_expr); + checkMkOpTerm(kind, opTerm, 2); + const CVC4::Kind int_kind = extToIntKind(kind); + Term res = d_exprMgr->mkExpr( + int_kind, *opTerm.d_expr, *child1.d_expr, *child2.d_expr); (void)res.d_expr->getType(true); /* kick off type checking */ return res; } @@ -2645,16 +2672,21 @@ Term Solver::mkTerm(OpTerm opTerm, Term child1, Term child2) const } } -Term Solver::mkTerm(OpTerm opTerm, Term child1, Term child2, Term child3) const +Term Solver::mkTerm( + Kind kind, OpTerm opTerm, Term child1, Term child2, Term child3) const { try { CVC4_API_ARG_CHECK_EXPECTED(!child1.isNull(), child1) << "non-null term"; CVC4_API_ARG_CHECK_EXPECTED(!child2.isNull(), child2) << "non-null term"; CVC4_API_ARG_CHECK_EXPECTED(!child3.isNull(), child3) << "non-null term"; - checkMkOpTerm(opTerm, 3); - Term res = d_exprMgr->mkExpr( - *opTerm.d_expr, *child1.d_expr, *child2.d_expr, *child3.d_expr); + checkMkOpTerm(kind, opTerm, 3); + const CVC4::Kind int_kind = extToIntKind(kind); + Term res = d_exprMgr->mkExpr(int_kind, + *opTerm.d_expr, + *child1.d_expr, + *child2.d_expr, + *child3.d_expr); (void)res.d_expr->getType(true); /* kick off type checking */ return res; } @@ -2664,7 +2696,9 @@ Term Solver::mkTerm(OpTerm opTerm, Term child1, Term child2, Term child3) const } } -Term Solver::mkTerm(OpTerm opTerm, const std::vector<Term>& children) const +Term Solver::mkTerm(Kind kind, + OpTerm opTerm, + const std::vector<Term>& children) const { try { @@ -2674,9 +2708,10 @@ Term Solver::mkTerm(OpTerm opTerm, const std::vector<Term>& children) const !children[i].isNull(), "parameter term", children[i], i) << "non-null term"; } - checkMkOpTerm(opTerm, children.size()); + checkMkOpTerm(kind, opTerm, children.size()); + const CVC4::Kind int_kind = extToIntKind(kind); std::vector<Expr> echildren = termVectorToExprs(children); - Term res = d_exprMgr->mkExpr(*opTerm.d_expr, echildren); + Term res = d_exprMgr->mkExpr(int_kind, *opTerm.d_expr, echildren); (void)res.d_expr->getType(true); /* kick off type checking */ return res; } @@ -2691,16 +2726,26 @@ Term Solver::mkTuple(const std::vector<Sort>& sorts, { CVC4_API_CHECK(sorts.size() == terms.size()) << "Expected the same number of sorts and elements"; - std::vector<Term> args; - for (size_t i = 0, size = sorts.size(); i < size; i++) + try { - args.push_back(ensureTermSort(terms[i], sorts[i])); - } + std::vector<CVC4::Expr> args; + for (size_t i = 0, size = sorts.size(); i < size; i++) + { + args.push_back(*(ensureTermSort(terms[i], sorts[i])).d_expr); + } - Sort s = mkTupleSort(sorts); - Datatype dt = s.getDatatype(); - args.insert(args.begin(), dt[0].getConstructorTerm()); - return mkTerm(APPLY_CONSTRUCTOR, args); + Sort s = mkTupleSort(sorts); + Datatype dt = s.getDatatype(); + Term res = d_exprMgr->mkExpr(extToIntKind(APPLY_CONSTRUCTOR), + *dt[0].getConstructorTerm().d_expr, + args); + (void)res.d_expr->getType(true); /* kick off type checking */ + return res; + } + catch (const CVC4::TypeCheckingException& e) + { + throw CVC4ApiException(e.getMessage()); + } } std::vector<Expr> Solver::termVectorToExprs( @@ -3458,28 +3503,32 @@ void Solver::setOption(const std::string& option, } } -Term Solver::ensureTermSort(const Term& t, const Sort& s) const +Term Solver::ensureTermSort(const Term& term, const Sort& sort) const { - CVC4_API_CHECK(t.getSort() == s || (t.getSort().isInteger() && s.isReal())) + CVC4_API_CHECK(term.getSort() == sort + || (term.getSort().isInteger() && sort.isReal())) << "Expected conversion from Int to Real"; - if (t.getSort() == s) + Sort t = term.getSort(); + if (term.getSort() == sort) { - return t; + return term; } // Integers are reals, too - Assert(t.getSort().isReal()); - Term res = t; - if (t.getSort().isInteger()) + Assert(t.isReal()); + Term res = term; + if (t.isInteger()) { // Must cast to Real to ensure correct type is passed to parametric type // constructors. We do this cast using division with 1. This has the // advantage wrt using TO_REAL since (constant) division is always included // in the theory. - res = mkTerm(DIVISION, *t.d_expr, mkReal(1)); + res = Term(d_exprMgr->mkExpr(extToIntKind(DIVISION), + *res.d_expr, + d_exprMgr->mkConst(CVC4::Rational(1)))); } - Assert(res.getSort() == s); + Assert(res.getSort() == sort); return res; } diff --git a/src/api/cvc4cpp.h b/src/api/cvc4cpp.h index a06f2e415..b8da070fc 100644 --- a/src/api/cvc4cpp.h +++ b/src/api/cvc4cpp.h @@ -1100,6 +1100,17 @@ class CVC4_PUBLIC DatatypeSelector ~DatatypeSelector(); /** + * @return true if this datatype selector has been resolved. + */ + bool isResolved() const; + + /** + * Get the selector operator of this datatype selector. + * @return the selector operator + */ + OpTerm getSelectorTerm() const; + + /** * @return a string representation of this datatype selector */ std::string toString() const; @@ -1154,7 +1165,7 @@ class CVC4_PUBLIC DatatypeConstructor * Get the constructor operator of this datatype constructor. * @return the constructor operator */ - Term getConstructorTerm() const; + OpTerm getConstructorTerm() const; /** * Get the datatype selector with the given name. @@ -1173,7 +1184,7 @@ class CVC4_PUBLIC DatatypeConstructor * @param name the name of the datatype selector * @return a term representing the datatype selector with the given name */ - Term getSelectorTerm(const std::string& name) const; + OpTerm getSelectorTerm(const std::string& name) const; /** * @return a string representation of this datatype constructor @@ -1320,7 +1331,7 @@ class CVC4_PUBLIC Datatype * similarly-named constructors, the * first is returned. */ - Term getConstructorTerm(const std::string& name) const; + OpTerm getConstructorTerm(const std::string& name) const; /** Get the number of constructors for this Datatype. */ size_t getNumConstructors() const; @@ -1725,43 +1736,59 @@ class CVC4_PUBLIC Solver Term mkTerm(Kind kind, const std::vector<Term>& children) const; /** - * Create unary term from a given operator term. + * Create nullary term of given kind from a given operator term. + * Create operator terms with mkOpTerm(). + * @param kind the kind of the term + * @param the operator term + * @return the Term + */ + Term mkTerm(Kind kind, OpTerm opTerm) const; + + /** + * Create unary term of given kind from a given operator term. * Create operator terms with mkOpTerm(). + * @param kind the kind of the term * @param the operator term * @child the child of the term * @return the Term */ - Term mkTerm(OpTerm opTerm, Term child) const; + Term mkTerm(Kind kind, OpTerm opTerm, Term child) const; /** - * Create binary term from a given operator term. + * Create binary term of given kind from a given operator term. + * @param kind the kind of the term * Create operator terms with mkOpTerm(). * @param the operator term * @child1 the first child of the term * @child2 the second child of the term * @return the Term */ - Term mkTerm(OpTerm opTerm, Term child1, Term child2) const; + Term mkTerm(Kind kind, OpTerm opTerm, Term child1, Term child2) const; /** - * Create ternary term from a given operator term. + * Create ternary term of given kind from a given operator term. * Create operator terms with mkOpTerm(). + * @param kind the kind of the term * @param the operator term * @child1 the first child of the term * @child2 the second child of the term * @child3 the third child of the term * @return the Term */ - Term mkTerm(OpTerm opTerm, Term child1, Term child2, Term child3) const; + Term mkTerm( + Kind kind, OpTerm opTerm, Term child1, Term child2, Term child3) const; /** - * Create n-ary term from a given operator term. + * Create n-ary term of given kind from a given operator term. * Create operator terms with mkOpTerm(). + * @param kind the kind of the term * @param the operator term * @children the children of the term * @return the Term */ - Term mkTerm(OpTerm opTerm, const std::vector<Term>& children) const; + Term mkTerm(Kind kind, + OpTerm opTerm, + const std::vector<Term>& children) const; /** * Create a tuple term. Terms are automatically converted if sorts are @@ -2485,7 +2512,7 @@ class CVC4_PUBLIC Solver /* Helper to convert a vector of sorts to internal types. */ std::vector<Expr> termVectorToExprs(const std::vector<Term>& vector) const; /* Helper to check for API misuse in mkTerm functions. */ - void checkMkOpTerm(OpTerm opTerm, uint32_t nchildren) const; + void checkMkOpTerm(Kind kind, OpTerm opTerm, uint32_t nchildren) const; /* Helper to check for API misuse in mkOpTerm functions. */ void checkMkTerm(Kind kind, uint32_t nchildren) const; /* Helper for mk-functions that call d_exprMgr->mkConst(). */ diff --git a/src/api/cvc4cppkind.h b/src/api/cvc4cppkind.h index a7f6926bb..4e69ddfe1 100644 --- a/src/api/cvc4cppkind.h +++ b/src/api/cvc4cppkind.h @@ -1649,30 +1649,32 @@ enum CVC4_PUBLIC Kind : int32_t /** * Constructor application. * Paramters: n > 0 - * -[1]: Constructor + * -[1]: Constructor (operator term) * -[2]..[n]: Parameters to the constructor * Create with: - * mkTerm(Kind kind) - * mkTerm(Kind kind, Term child) - * mkTerm(Kind kind, Term child1, Term child2) - * mkTerm(Kind kind, Term child1, Term child2, Term child3) - * mkTerm(Kind kind, const std::vector<Term>& children) + * mkTerm(Kind kind, OpTerm opTerm) + * mkTerm(Kind kind, OpTerm opTerm, Term child) + * mkTerm(Kind kind, OpTerm opTerm, Term child1, Term child2) + * mkTerm(Kind kind, OpTerm opTerm, Term child1, Term child2, Term child3) + * mkTerm(Kind kind, OpTerm opTerm, const std::vector<Term>& children) */ - APPLY_SELECTOR, + APPLY_CONSTRUCTOR, /** * Datatype selector application. * Parameters: 1 - * -[1]: Datatype term (undefined if mis-applied) + * -[1]: Selector (operator term) + * -[2]: Datatype term (undefined if mis-applied) * Create with: - * mkTerm(Kind kind, Term child) + * mkTerm(Kind kind, OpTerm opTerm, Term child) */ - APPLY_CONSTRUCTOR, + APPLY_SELECTOR, /** * Datatype selector application. * Parameters: 1 - * -[1]: Datatype term (defined rigidly if mis-applied) + * -[1]: Selector (operator term) + * -[2]: Datatype term (defined rigidly if mis-applied) * Create with: - * mkTerm(Kind kind, Term child) + * mkTerm(Kind kind, OpTerm opTerm, Term child) */ APPLY_SELECTOR_TOTAL, /** diff --git a/src/expr/expr_manager_template.cpp b/src/expr/expr_manager_template.cpp index e6b89b498..d0d36508f 100644 --- a/src/expr/expr_manager_template.cpp +++ b/src/expr/expr_manager_template.cpp @@ -301,21 +301,30 @@ Expr ExprManager::mkExpr(Kind kind, Expr child1, Expr child2, Expr child3, } } -Expr ExprManager::mkExpr(Kind kind, const std::vector<Expr>& children) { +Expr ExprManager::mkExpr(Kind kind, const std::vector<Expr>& children) +{ + const size_t nchildren = children.size(); const kind::MetaKind mk = kind::metaKindOf(kind); - const unsigned n = children.size() - (mk == kind::metakind::PARAMETERIZED ? 1 : 0); PrettyCheckArgument( - mk == kind::metakind::PARAMETERIZED || - mk == kind::metakind::OPERATOR, kind, + mk == kind::metakind::PARAMETERIZED || mk == kind::metakind::OPERATOR, + kind, "Only operator-style expressions are made with mkExpr(); " "to make variables and constants, see mkVar(), mkBoundVar(), " "and mkConst()."); PrettyCheckArgument( - n >= minArity(kind) && n <= maxArity(kind), kind, - "Exprs with kind %s must have at least %u children and " - "at most %u children (the one under construction has %u)", - kind::kindToString(kind).c_str(), - minArity(kind), maxArity(kind), n); + mk != kind::metakind::PARAMETERIZED || nchildren > 0, + kind, + "Terms with kind %s must have an operator expression as first argument", + kind::kindToString(kind).c_str()); + const size_t n = nchildren - (mk == kind::metakind::PARAMETERIZED ? 1 : 0); + PrettyCheckArgument(n >= minArity(kind) && n <= maxArity(kind), + kind, + "Exprs with kind %s must have at least %u children and " + "at most %u children (the one under construction has %u)", + kind::kindToString(kind).c_str(), + minArity(kind), + maxArity(kind), + n); NodeManagerScope nms(d_nodeManager); |