/* Builtin ------------------------------------------------------------- */
{UNINTERPRETED_CONSTANT, CVC4::Kind::UNINTERPRETED_CONSTANT},
{ABSTRACT_VALUE, CVC4::Kind::ABSTRACT_VALUE},
- {FUNCTION, CVC4::Kind::FUNCTION},
- {APPLY, CVC4::Kind::APPLY},
{EQUAL, CVC4::Kind::EQUAL},
{DISTINCT, CVC4::Kind::DISTINCT},
{CONSTANT, CVC4::Kind::VARIABLE},
/* Builtin --------------------------------------------------------- */
{CVC4::Kind::UNINTERPRETED_CONSTANT, UNINTERPRETED_CONSTANT},
{CVC4::Kind::ABSTRACT_VALUE, ABSTRACT_VALUE},
- {CVC4::Kind::FUNCTION, FUNCTION},
- {CVC4::Kind::APPLY, APPLY},
{CVC4::Kind::EQUAL, EQUAL},
{CVC4::Kind::DISTINCT, DISTINCT},
{CVC4::Kind::VARIABLE, CONSTANT},
/* Built-in operator */
BUILTIN,
#endif
- /**
- * Defined function.
- * Parameters: 3 (4)
- * See defineFun().
- * Create with:
- * defineFun(const std::string& symbol,
- * const std::vector<Term>& bound_vars,
- * Sort sort,
- * Term term)
- * defineFun(Term fun,
- * const std::vector<Term>& bound_vars,
- * Term term)
- */
- FUNCTION,
- /**
- * Application of a defined function.
- * Parameters: n > 1
- * -[1]..[n]: Function argument instantiation Terms
- * Create with:
- * 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)
- */
- APPLY,
/**
* Equality.
* Parameters: 2
/**
* Returns a node representing the operator of this expression.
- * If this is an APPLY, then the operator will be a functional term.
+ * If this is an APPLY_UF, then the operator will be a functional term.
* Otherwise, it will be a node with kind BUILTIN.
*/
NodeTemplate<true> getOperator() const;
/**
* Returns a node representing the operator of this expression.
- * If this is an APPLY, then the operator will be a functional term.
+ * If this is an APPLY_UF, then the operator will be a functional term.
* Otherwise, it will be a node with kind BUILTIN.
*/
template <bool ref_count>
}
// now, post-process the expression
assert( !expr.isNull() );
- if(isDefinedFunction(expr)) {
- // defined functions/constants are wrapped in an APPLY so that they are
- // expanded into their definition, e.g. during SmtEnginePrivate::expandDefinitions
- expr = getExprManager()->mkExpr(CVC4::kind::APPLY, expr);
- }else{
- Type te = expr.getType();
- if(te.isConstructor() && ConstructorType(te).getArity() == 0) {
- // nullary constructors have APPLY_CONSTRUCTOR kind with no children
- expr = getExprManager()->mkExpr(CVC4::kind::APPLY_CONSTRUCTOR, expr);
- }
+ Type te = expr.getType();
+ if (te.isConstructor() && ConstructorType(te).getArity() == 0)
+ {
+ // nullary constructors have APPLY_CONSTRUCTOR kind with no children
+ expr = getExprManager()->mkExpr(CVC4::kind::APPLY_CONSTRUCTOR, expr);
}
return expr;
}
Kind Parser::getKindForFunction(Expr fun) {
if(isDefinedFunction(fun)) {
- return APPLY;
+ return APPLY_UF;
}
Type t = fun.getType();
if(t.isConstructor()) {
// however, we need to apply partial version since we don't have the internal selector available
aargs.push_back( MK_EXPR( CVC4::kind::APPLY_SELECTOR, dtc[i].getSelector(), expr ) );
}
- patexprs.push_back( MK_EXPR( CVC4::kind::APPLY, aargs ) );
+ patexprs.push_back( MK_EXPR( CVC4::kind::APPLY_UF, aargs ) );
patconds.push_back( MK_EXPR( CVC4::kind::APPLY_TESTER, dtc.getTester(), expr ) );
}
RPAREN_TOK
children.push_back( it->second );
}
}
- Kind sk = sop.getKind() != kind::BUILTIN ? kind::APPLY : getExprManager()->operatorToKind(sop);
+ Kind sk = sop.getKind() != kind::BUILTIN
+ ? kind::APPLY_UF
+ : getExprManager()->operatorToKind(sop);
Debug("parser-sygus") << ": operator " << sop << " with " << sop.getKind() << " " << sk << std::endl;
Expr e = getExprManager()->mkExpr( sk, children );
Debug("parser-sygus") << ": constructed " << e << ", which has type " << e.getType() << std::endl;
}
children.insert(children.end(), largs.begin(), largs.end());
Kind sk = ops[i].getKind() != kind::BUILTIN
- ? kind::APPLY
+ ? kind::APPLY_UF
: getExprManager()->operatorToKind(ops[i]);
Expr body = getExprManager()->mkExpr(sk, children);
// replace by lambda
std::vector<Expr> largs;
Expr lbvl = makeSygusBoundVarList(dt, i, ftypes, largs);
largs.insert(largs.begin(), ops[i]);
- Expr body = getExprManager()->mkExpr(kind::APPLY, largs);
+ Expr body = getExprManager()->mkExpr(kind::APPLY_UF, largs);
ops[i] = getExprManager()->mkExpr(kind::LAMBDA, lbvl, body);
Debug("parser-sygus") << " ...replace op : " << ops[i]
<< std::endl;
}
else
{
- ops[i] = getExprManager()->mkExpr(kind::APPLY, ops[i]);
Debug("parser-sygus") << " ...replace op : " << ops[i]
<< std::endl;
}
out << ")";
return;
break;
- case kind::APPLY:
- toStream(op, n.getOperator(), depth, types, true);
- break;
case kind::CHAIN:
case kind::DISTINCT: // chain and distinct not supported directly in CVC4, blast them away with the rewriter
toStream(out, theory::Rewriter::rewrite(n), depth, types, true);
}
switch(Kind k = n.getKind()) {
// builtin theory
- case kind::APPLY: break;
case kind::EQUAL:
case kind::DISTINCT:
out << smtKindString(k, d_variant) << " ";
{
switch(k) {
// builtin theory
- case kind::APPLY: break;
case kind::EQUAL: return "=";
case kind::DISTINCT: return "distinct";
case kind::CHAIN: break;
this->DefineFunctionCommand::invoke(smtEngine);
if (!d_func.isNull() && d_func.getType().isBoolean())
{
- smtEngine->addToAssignment(
- d_func.getExprManager()->mkExpr(kind::APPLY, d_func));
+ smtEngine->addToAssignment(d_func);
}
d_commandStatus = CommandSuccess::instance();
}
for (const auto& p : assignments)
{
vector<SExpr> v;
- if (p.first.getKind() == kind::APPLY)
- {
- v.emplace_back(SExpr::Keyword(p.first.getOperator().toString()));
- }
- else
- {
- v.emplace_back(SExpr::Keyword(p.first.toString()));
- }
+ v.emplace_back(SExpr::Keyword(p.first.toString()));
v.emplace_back(SExpr::Keyword(p.second.toString()));
sexprs.emplace_back(v);
}
if(n.isVar()) {
SmtEngine::DefinedFunctionMap::const_iterator i = d_smt.d_definedFunctions->find(n);
if(i != d_smt.d_definedFunctions->end()) {
+ Node f = (*i).second.getFormula();
+ // must expand its definition
+ Node fe = expandDefinitions(f, cache, expandOnly);
// replacement must be closed
if((*i).second.getFormals().size() > 0) {
- result.push(d_smt.d_nodeManager->mkNode(kind::LAMBDA, d_smt.d_nodeManager->mkNode(kind::BOUND_VAR_LIST, (*i).second.getFormals()), (*i).second.getFormula()));
+ result.push(d_smt.d_nodeManager->mkNode(
+ kind::LAMBDA,
+ d_smt.d_nodeManager->mkNode(kind::BOUND_VAR_LIST,
+ (*i).second.getFormals()),
+ fe));
continue;
}
// don't bother putting in the cache
- result.push((*i).second.getFormula());
+ result.push(fe);
continue;
}
// don't bother putting in the cache
// otherwise expand it
bool doExpand = false;
- if (k == kind::APPLY)
- {
- doExpand = true;
- }
- else if (k == kind::APPLY_UF)
+ if (k == kind::APPLY_UF)
{
// Always do beta-reduction here. The reason is that there may be
// operators such as INTS_MODULUS in the body of the lambda that would
{
doExpand = true;
}
- else if (options::macrosQuant() || options::sygusInference())
+ else
{
- // The above options assign substitutions to APPLY_UF, thus we check
- // here and expand if this operator corresponds to a defined function.
+ // We always check if this operator corresponds to a defined function.
doExpand = d_smt.isDefinedFunction(n.getOperator().toExpr());
}
}
{
children.insert(children.end(), vars.begin(), vars.end());
}
- terms[i] =
- d_nodeManager->mkNode(i == 0 ? kind::APPLY_UF : kind::APPLY, children);
+ terms[i] = d_nodeManager->mkNode(kind::APPLY_UF, children);
// make application of Inv on primed variables
if (i == 0)
{
"expected Boolean-typed variable or function application "
"in addToAssignment()" );
Node n = e.getNode();
- // must be an APPLY of a zero-ary defined function, or a variable
+ // must be a defined constant, or a variable
PrettyCheckArgument(
- ( ( n.getKind() == kind::APPLY &&
- ( d_definedFunctions->find(n.getOperator()) !=
- d_definedFunctions->end() ) &&
- n.getNumChildren() == 0 ) ||
- n.isVar() ), e,
+ (((d_definedFunctions->find(n) != d_definedFunctions->end())
+ && n.getNumChildren() == 0)
+ || n.isVar()),
+ e,
"expected variable or defined-function application "
- "in addToAssignment(),\ngot %s", e.toString().c_str() );
+ "in addToAssignment(),\ngot %s",
+ e.toString().c_str());
if(!options::produceAssignments()) {
return false;
}
// ensure it's a constant
Assert(resultNode.isConst());
- Assert(as.getKind() == kind::APPLY || as.isVar());
- Assert(as.getKind() != kind::APPLY || as.getNumChildren() == 0);
+ Assert(as.isVar());
res.emplace_back(as.toExpr(), resultNode.toExpr());
}
}
"expr/kind.h" \
"the kind of expressions representing built-in operators"
-variable FUNCTION "a defined function"
-parameterized APPLY FUNCTION 0: "application of a defined function"
-
operator EQUAL 2 "equality (two parameters only, sorts must match)"
operator DISTINCT 2: "disequality (N-ary, sorts must match)"
variable VARIABLE "a variable (not permitted in bindings)"
"::CVC4::theory::builtin::SExprProperties::mkGroundTerm(%TYPE%)" \
"theory/builtin/theory_builtin_type_rules.h"
-typerule APPLY ::CVC4::theory::builtin::ApplyTypeRule
typerule EQUAL ::CVC4::theory::builtin::EqualityTypeRule
typerule DISTINCT ::CVC4::theory::builtin::DistinctTypeRule
typerule SEXPR ::CVC4::theory::builtin::SExprTypeRule
namespace theory {
namespace builtin {
-class ApplyTypeRule {
- public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
- {
- TNode f = n.getOperator();
- TypeNode fType = f.getType(check);
- if( !fType.isFunction() && n.getNumChildren() > 0 ) {
- throw TypeCheckingExceptionPrivate(n, "operator does not have function type");
- }
- if( check ) {
- if(fType.isFunction()) {
- if(n.getNumChildren() != fType.getNumChildren() - 1) {
- throw TypeCheckingExceptionPrivate(n, "number of arguments does not match the function type");
- }
- TNode::iterator argument_it = n.begin();
- TNode::iterator argument_it_end = n.end();
- TypeNode::iterator argument_type_it = fType.begin();
- for(; argument_it != argument_it_end; ++argument_it, ++argument_type_it) {
- if(!(*argument_it).getType().isComparableTo(*argument_type_it)) {
- std::stringstream ss;
- ss << "argument types do not match the function type:\n"
- << "argument: " << *argument_it << "\n"
- << "has type: " << (*argument_it).getType() << "\n"
- << "not equal: " << *argument_type_it;
- throw TypeCheckingExceptionPrivate(n, ss.str());
- }
- }
- } else {
- if( n.getNumChildren() > 0 ) {
- throw TypeCheckingExceptionPrivate(n, "number of arguments does not match the function type");
- }
- }
- }
- return fType.isFunction() ? fType.getRangeType() : fType;
- }
-};/* class ApplyTypeRule */
-
-
class EqualityTypeRule {
public:
inline static TypeNode computeType(NodeManager* nodeManager,
Assert(op.getKind() != BUILTIN);
if (op.getKind() == LAMBDA)
{
- // we use APPLY_UF instead of APPLY, since the rewriter for APPLY_UF
- // does beta-reduction but does not for APPLY
return APPLY_UF;
}
TypeNode tn = op.getType();
Kind ok = NodeManager::operatorToKind(op);
if (ok != UNDEFINED_KIND)
{
- ret = NodeManager::currentNM()->mkNode(ok, schildren);
+ if (ok == APPLY_UF && schildren.size() == 1)
+ {
+ // This case is triggered for defined constant symbols. In this case,
+ // we return the operator itself instead of an APPLY_UF node.
+ ret = schildren[0];
+ }
+ else
+ {
+ ret = NodeManager::currentNM()->mkNode(ok, schildren);
+ }
Trace("dt-sygus-util") << "...return (op) " << ret << std::endl;
return ret;
}
regress0/decision/wchains010ue.delta02.smt
regress0/declare-fun-is-match.smt2
regress0/declare-funs.smt2
+ regress0/define-fun-model.smt2
regress0/distinct.smt
regress0/expect/scrub.01.smt
regress0/expect/scrub.02.smt
--- /dev/null
+; SCRUBBER: sed -e 's/BOUND_VARIABLE_[0-9]*/BOUND_VARIABLE/'
+; EXPECT: sat
+; EXPECT: (((f 4) 7))
+; EXPECT: ((g (lambda ((BOUND_VARIABLE Int)) 7)))
+; EXPECT: ((f (lambda ((BOUND_VARIABLE Int)) 7)))
+(set-logic UFLIA)
+(set-option :produce-models true)
+(define-fun f ((x Int)) Int 7)
+(declare-fun g (Int) Int)
+
+(assert (= (g 5) (f 5)))
+
+(check-sat)
+(get-value ((f 4)))
+(get-value (g))
+(get-value (f))