Towards parser/API migration.
CVC4_API_SOLVER_TRY_CATCH_END;
}
+Term Solver::mkTermInternal(Kind kind, const std::vector<Term>& children) const
+{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ for (size_t i = 0, size = children.size(); i < size; ++i)
+ {
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ !children[i].isNull(), "parameter term", children[i], i)
+ << "non-null term";
+ }
+
+ std::vector<Expr> echildren = termVectorToExprs(children);
+ CVC4::Kind k = extToIntKind(kind);
+ Assert(isDefinedIntKind(k));
+
+ Term res;
+ if (echildren.size() > 2)
+ {
+ if (kind == INTS_DIVISION || kind == XOR || kind == MINUS
+ || kind == DIVISION || kind == BITVECTOR_XNOR || kind == HO_APPLY)
+ {
+ // left-associative, but CVC4 internally only supports 2 args
+ res = d_exprMgr->mkLeftAssociative(k, echildren);
+ }
+ else if (kind == IMPLIES)
+ {
+ // right-associative, but CVC4 internally only supports 2 args
+ res = d_exprMgr->mkRightAssociative(k, echildren);
+ }
+ else if (kind == EQUAL || kind == LT || kind == GT || kind == LEQ
+ || kind == GEQ)
+ {
+ // "chainable", but CVC4 internally only supports 2 args
+ res = d_exprMgr->mkChain(k, echildren);
+ }
+ else if (kind::isAssociative(k))
+ {
+ // mkAssociative has special treatment for associative operators with lots
+ // of children
+ res = d_exprMgr->mkAssociative(k, echildren);
+ }
+ else
+ {
+ // default case, must check kind
+ checkMkTerm(kind, children.size());
+ res = d_exprMgr->mkExpr(k, echildren);
+ }
+ }
+ else if (kind::isAssociative(k))
+ {
+ // associative case, same as above
+ res = d_exprMgr->mkAssociative(k, echildren);
+ }
+ else
+ {
+ // default case, same as above
+ checkMkTerm(kind, children.size());
+ res = d_exprMgr->mkExpr(k, echildren);
+ }
+
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ CVC4_API_SOLVER_TRY_CATCH_END;
+}
+
/* Helpers for converting vectors. */
/* .......................................................................... */
Term Solver::mkTerm(Kind kind, Term child1, Term child2, Term child3) const
{
- CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- 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";
- checkMkTerm(kind, 3);
-
- std::vector<Expr> echildren{*child1.d_expr, *child2.d_expr, *child3.d_expr};
- CVC4::Kind k = extToIntKind(kind);
- Assert(isDefinedIntKind(k));
- Term res = kind::isAssociative(k) ? d_exprMgr->mkAssociative(k, echildren)
- : d_exprMgr->mkExpr(k, echildren);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
-
- CVC4_API_SOLVER_TRY_CATCH_END;
+ // need to use internal term call to check e.g. associative construction
+ return mkTermInternal(kind, std::vector<Term>{child1, child2, child3});
}
Term Solver::mkTerm(Kind kind, const std::vector<Term>& children) const
{
- CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- for (size_t i = 0, size = children.size(); i < size; ++i)
- {
- CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
- !children[i].isNull(), "parameter term", children[i], i)
- << "non-null term";
- }
- checkMkTerm(kind, children.size());
-
- std::vector<Expr> echildren = termVectorToExprs(children);
- CVC4::Kind k = extToIntKind(kind);
- Assert(isDefinedIntKind(k));
- Term res = kind::isAssociative(k) ? d_exprMgr->mkAssociative(k, echildren)
- : d_exprMgr->mkExpr(k, echildren);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
-
- CVC4_API_SOLVER_TRY_CATCH_END;
+ return mkTermInternal(kind, children);
}
Term Solver::mkTerm(Op op) const
*/
Term ensureRealSort(Term expr) const;
+ /**
+ * Create n-ary term of given kind. This handles the cases of left/right
+ * associative operators, chainable operators, and cases when the number of
+ * children exceeds the maximum arity for the kind.
+ * @param kind the kind of the term
+ * @param children the children of the term
+ * @return the Term
+ */
+ Term mkTermInternal(Kind kind, const std::vector<Term>& children) const;
+
/* The expression manager of this solver. */
std::unique_ptr<ExprManager> d_exprMgr;
/* The SMT engine of this solver. */
BUILTIN,
#endif
/**
- * Equality.
- * Parameters: 2
- * -[1]..[2]: Terms with same sort
+ * Equality, chainable.
+ * Parameters: n > 1
+ * -[1]..[n]: Terms with same sorts
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
EQUAL,
/**
* Disequality.
* Parameters: n > 1
- * -[1]..[n]: Terms with same sort
+ * -[1]..[n]: Terms with same sorts
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
* mkTerm(Kind kind, Term child1, Term child2, Term child3)
AND,
/**
* Logical implication.
- * Parameters: 2
- * -[1]..[2]: Boolean Terms, [1] implies [2]
+ * Parameters: n > 1
+ * -[1]..[n]: Boolean Terms, right associative
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
IMPLIES,
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
OR,
- /* Logical exclusive or.
- * Parameters: 2
- * -[1]..[2]: Boolean Terms, [1] xor [2]
+ /* Logical exclusive or, left associative.
+ * Parameters: n > 1
+ * -[1]..[n]: Boolean Terms, [1] xor ... xor [n]
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
XOR,
PARTIAL_APPLY_UF,
#endif
/**
- * Higher-order applicative encoding of function application.
- * Parameters: 2
+ * Higher-order applicative encoding of function application, left
+ * associative.
+ * Parameters: n > 1
* -[1]: Function to apply
- * -[2]: Argument of the function
+ * -[2] ... [n]: Arguments of the function
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
HO_APPLY,
NONLINEAR_MULT,
#endif
/**
- * Arithmetic subtraction.
- * Parameters: 2
- * -[1]..[2]: Terms of sort Integer, Real (sorts must match)
+ * Arithmetic subtraction, left associative.
+ * Parameters: n
+ * -[1]..[n]: Terms of sort Integer, Real (sorts must match)
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
MINUS,
*/
UMINUS,
/**
- * Real division, division by 0 undefined
- * Parameters: 2
- * -[1]..[2]: Terms of sort Integer, Real
+ * Real division, division by 0 undefined, left associative.
+ * Parameters: n > 1
+ * -[1]..[n]: Terms of sort Integer, Real
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
DIVISION,
/**
- * Integer division, division by 0 undefined.
- * Parameters: 2
- * -[1]..[2]: Terms of sort Integer
+ * Integer division, division by 0 undefined, left associative.
+ * Parameters: n > 1
+ * -[1]..[n]: Terms of sort Integer
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
INTS_DIVISION,
*/
CONST_RATIONAL,
/**
- * Less than.
- * Parameters: 2
- * -[1]..[2]: Terms of sort Integer, Real; [1] < [2]
+ * Less than, chainable.
+ * Parameters: n
+ * -[1]..[n]: Terms of sort Integer, Real; [1] < ... < [n]
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
LT,
/**
- * Less than or equal.
- * Parameters: 2
- * -[1]..[2]: Terms of sort Integer, Real; [1] <= [2]
+ * Less than or equal, chainable.
+ * Parameters: n > 1
+ * -[1]..[n]: Terms of sort Integer, Real; [1] <= ... <= [n]
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
LEQ,
/**
- * Greater than.
- * Parameters: 2
- * -[1]..[2]: Terms of sort Integer, Real, [1] > [2]
+ * Greater than, chainable.
+ * Parameters: n > 1
+ * -[1]..[n]: Terms of sort Integer, Real, [1] > ... > [n]
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
GT,
/**
- * Greater than or equal.
- * Parameters: 2
- * -[1]..[2]: Terms of sort Integer, Real; [1] >= [2]
+ * Greater than or equal, chainable.
+ * Parameters: n > 1
+ * -[1]..[n]: Terms of sort Integer, Real; [1] >= ... >= [n]
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
GEQ,
*/
BITVECTOR_NOR,
/**
- * Bit-wise xnor.
- * Parameters: 2
- * -[1]..[2]: Terms of bit-vector sort (sorts must match)
+ * Bit-wise xnor, left associative.
+ * Parameters: n > 1
+ * -[1]..[n]: Terms of bit-vector sort (sorts must match)
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
* mkTerm(Kind kind, const std::vector<Term>& children)
* -[1]..[2]: Terms of bit-vector sort (sorts must match)
* Create with:
* mkTerm(Kind kind, Term child1, Term child2)
+ * mkTerm(Kind kind, Term child1, Term child2, Term child3)
* mkTerm(Kind kind, const std::vector<Term>& children)
*/
BITVECTOR_COMP,
return n.toExpr();
}
+Expr ExprManager::mkChain(Kind kind, const std::vector<Expr>& children)
+{
+ if (children.size() == 2)
+ {
+ // if this is the case exactly 1 pair will be generated so the
+ // AND is not required
+ return mkExpr(kind, children[0], children[1]);
+ }
+ std::vector<Expr> cchildren;
+ for (size_t i = 0, nargsmo = children.size() - 1; i < nargsmo; i++)
+ {
+ cchildren.push_back(mkExpr(kind, children[i], children[i + 1]));
+ }
+ return mkExpr(kind::AND, cchildren);
+}
+
unsigned ExprManager::minArity(Kind kind) {
return metakind::getLowerBoundForKind(kind);
}
*/
Expr mkRightAssociative(Kind kind, const std::vector<Expr>& children);
+ /** make chain
+ *
+ * Given a kind k and arguments t_1, ..., t_n, this returns the
+ * conjunction of:
+ * (k t_1 t_2) .... (k t_{n-1} t_n)
+ * It is expected that k is a kind denoting a predicate, and args is a list
+ * of terms of size >= 2 such that the terms above are well-typed.
+ */
+ Expr mkChain(Kind kind, const std::vector<Expr>& children);
+
/**
* Determine whether Exprs of a particular Kind have operators.
* @returns true if Exprs of Kind k have operators.
return expr;
}
-api::Term Parser::mkChain(api::Kind k, const std::vector<api::Term>& args)
-{
- if (args.size() == 2)
- {
- // if this is the case exactly 1 pair will be generated so the
- // AND is not required
- return d_solver->mkTerm(k, args[0], args[1]);
- }
- std::vector<api::Term> children;
- for (size_t i = 0, nargsmo = args.size() - 1; i < nargsmo; i++)
- {
- children.push_back(d_solver->mkTerm(k, args[i], args[i + 1]));
- }
- return d_solver->mkTerm(api::AND, children);
-}
-
bool Parser::isDeclared(const std::string& name, SymbolType type) {
switch (type) {
case SYM_VARIABLE:
*/
Expr mkHoApply(Expr expr, std::vector<Expr>& args);
- /** make chain
- *
- * Given a kind k and argument terms t_1, ..., t_n, this returns the
- * conjunction of:
- * (k t_1 t_2) .... (k t_{n-1} t_n)
- * It is expected that k is a kind denoting a predicate, and args is a list
- * of terms of size >= 2 such that the terms above are well-typed.
- */
- api::Term mkChain(api::Kind k, const std::vector<api::Term>& args);
-
/**
* Add an operator to the current legal set.
*
|| kind == kind::LEQ || kind == kind::GEQ)
{
/* "chainable", but CVC4 internally only supports 2 args */
- api::Term ret =
- mkChain(intToExtKind(kind), api::exprVectorToTerms(args));
- return ret.getExpr();
+ return em->mkChain(kind, args);
}
}
|| kind == kind::LEQ || kind == kind::GEQ)
{
/* "chainable", but CVC4 internally only supports 2 args */
- api::Term ret =
- mkChain(intToExtKind(kind), api::exprVectorToTerms(args));
- return ret.getExpr();
+ return em->mkChain(kind, args);
}
}