// must convert recursively, since nullTerm may have subterms.
ret = convert(nullTerm);
}
- // the kind to chain
- Kind ck = k;
// check whether we are also changing the operator name, in which case
// we build a binary uninterpreted function opc
- Node opc;
- if (k == ADD || k == MULT || k == NONLINEAR_MULT)
+ bool isArithOp = (k == ADD || k == MULT || k == NONLINEAR_MULT);
+ std::stringstream arithOpName;
+ if (isArithOp)
{
- std::stringstream opName;
// currently allow subtyping
- opName << "a.";
- opName << printer::smt2::Smt2Printer::smtKindString(k);
- TypeNode ftype = nm->mkFunctionType({tn, tn}, tn);
- opc = getSymbolInternal(k, ftype, opName.str());
- ck = APPLY_UF;
+ arithOpName << "a.";
+ arithOpName << printer::smt2::Smt2Printer::smtKindString(k);
}
// now, iterate over children and make binary conversion
for (size_t i = istart, npchild = children.size(); i < npchild; i++)
{
- if (!opc.isNull())
+ if (isArithOp)
{
- ret = nm->mkNode(ck, opc, children[i], ret);
+ // Arithmetic operators must deal with permissive type rules for
+ // ADD, MULT, NONLINEAR_MULT. We use the properly typed operator to
+ // avoid debug failures.
+ TypeNode tn1 = children[i].getType();
+ TypeNode tn2 = ret.getType();
+ TypeNode ftype = nm->mkFunctionType({tn1, tn2}, tn);
+ Node opc = getSymbolInternal(k, ftype, arithOpName.str());
+ ret = nm->mkNode(APPLY_UF, opc, children[i], ret);
}
else
{
- ret = nm->mkNode(ck, children[i], ret);
+ ret = nm->mkNode(k, children[i], ret);
}
}
Trace("lfsc-term-process-debug")
std::vector<TypeNode> argTypes;
for (const Node& nc : n)
{
- // We take the base type, so that e.g. arithmetic operators are over
- // real. This avoids issues with subtyping when currying during proof
- // postprocessing
- argTypes.push_back(nc.getType().getBaseType());
+ argTypes.push_back(nc.getType());
}
// we only use binary operators
if (NodeManager::isNAryKind(k))
size_t ii = (nchildren - 1) - i;
Trace("lfsc-pp-cong") << "Process child " << ii << std::endl;
Node uop = op;
- // special case: each bv concat in the chain has a different type,
- // so remake the operator here.
- if (k == kind::BITVECTOR_CONCAT)
+ // special case: applications of the following kinds in the chain may
+ // have a different type, so remake the operator here.
+ if (k == kind::BITVECTOR_CONCAT || k == ADD || k == MULT
+ || k == NONLINEAR_MULT)
{
// we get the operator of the next argument concatenated with the
// current accumulated remainder.
- Node currApp =
- nm->mkNode(kind::BITVECTOR_CONCAT, children[ii][0], currEq[0]);
+ Node currApp = nm->mkNode(k, children[ii][0], currEq[0]);
uop = d_tproc.getOperatorOfTerm(currApp);
}
Trace("lfsc-pp-cong") << "Apply " << uop << " to " << children[ii][0]