/*****************************************************************************/
/*!
* \file translator.cpp
* \brief Description: Code for translation between languages
*
* Author: Clark Barrett
*
* Created: Sat Jun 25 18:06:52 2005
*
* <hr>
*
* License to use, copy, modify, sell and/or distribute this software
* and its documentation for any purpose is hereby granted without
* royalty, subject to the terms and conditions defined in the \ref
* LICENSE file provided with this distribution.
*
* <hr>
*
*/
/*****************************************************************************/
#include "translator.h"
#include "expr.h"
#include "theory_core.h"
#include "theory_uf.h"
#include "theory_arith.h"
#include "theory_bitvector.h"
#include "theory_array.h"
#include "theory_quant.h"
#include "theory_records.h"
#include "theory_simulate.h"
#include "theory_datatype.h"
#include "theory_datatype_lazy.h"
#include "smtlib_exception.h"
using namespace std;
using namespace CVC3;
string Translator::fileToSMTLIBIdentifier(const string& filename)
{
string tmpName;
string::size_type pos = filename.rfind("/");
if (pos == string::npos) {
tmpName = filename;
}
else {
tmpName = filename.substr(pos+1);
}
char c = tmpName[0];
string res;
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
res = "B_";
}
for (unsigned i = 0; i < tmpName.length(); ++i) {
c = tmpName[i];
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
(c < '0' || c > '9') && (c != '.' && c != '_')) {
c = '_';
}
res += c;
}
return res;
}
Expr Translator::preprocessRec(const Expr& e, ExprMap<Expr>& cache)
{
ExprMap<Expr>::iterator i(cache.find(e));
if(i != cache.end()) {
return (*i).second;
}
if (e.isClosure()) {
Expr newBody = preprocessRec(e.getBody(), cache);
Expr e2(e);
if (newBody != e.getBody()) {
e2 = d_em->newClosureExpr(e.getKind(), e.getVars(), newBody);
}
d_theoryCore->theoryOf(e2)->setUsed();
cache[e] = e2;
return e2;
}
Expr e2(e);
vector<Expr> children;
bool diff = false;
for(int k = 0; k < e.arity(); ++k) {
// Recursively preprocess the kids
Expr child = preprocessRec(e[k], cache);
if (child != e[k]) diff = true;
children.push_back(child);
}
if (diff) {
e2 = Expr(e.getOp(), children);
}
Rational r;
switch (e2.getKind()) {
case APPLY:
// Expand lambda applications
if (e2.getOpKind() == LAMBDA) {
Expr lambda(e2.getOpExpr());
Expr body(lambda.getBody());
const vector<Expr>& vars = lambda.getVars();
FatalAssert(vars.size() == (size_t)e2.arity(),
"wrong number of arguments applied to lambda\n");
body = body.substExpr(vars, e2.getKids());
e2 = preprocessRec(body, cache);
}
break;
case EQ:
if (d_theoryArith->getBaseType(e2[0]) != d_theoryArith->realType())
break;
goto arith_rewrites;
case UMINUS:
if (d_theoryArith->isSyntacticRational(e2, r)) {
e2 = preprocessRec(d_em->newRatExpr(r), cache);
break;
}
goto arith_rewrites;
case DIVIDE:
if (d_theoryArith->isSyntacticRational(e2, r)) {
e2 = preprocessRec(d_em->newRatExpr(r), cache);
break;
}
else if (d_convertArith && e2[1].isRational()) {
r = e2[1].getRational();
if (r != 0) {
e2 = d_em->newRatExpr(1/r) * e2[0];
e2 = preprocessRec(e2, cache);
break;
}
}
goto arith_rewrites;
case PLUS:
if (d_convertArith) {
// Flatten and combine constants
vector<Expr> terms;
bool changed = false;
r = 0;
Expr::iterator i = e2.begin(), iend = e2.end();
for(; i!=iend; ++i) {
if ((*i).getKind() == PLUS) {
changed = true;
Expr::iterator i2 = (*i).begin(), i2end = (*i).end();
for (; i2 != i2end; ++i2) {
if ((*i2).isRational()) r += (*i2).getRational();
else terms.push_back(*i2);
}
}
else {
if ((*i).isRational()) {
if (r != 0) changed = true;
r += (*i).getRational();
}
else terms.push_back(*i);
}
}
if (terms.size() == 0) {
e2 = preprocessRec(d_em->newRatExpr(r), cache);
break;
}
else if (terms.size() == 1) {
if (r == 0) {
e2 = terms[0];
break;
}
else if (r < 0) {
e2 = preprocessRec(Expr(MINUS, terms[0], d_em->newRatExpr(-r)), cache);
break;
}
}
if (changed) {
if (r != 0) terms.push_back(d_em->newRatExpr(r));
e2 = preprocessRec(Expr(PLUS, terms), cache);
break;
}
}
goto arith_rewrites;
case POW:
if (d_convertArith && e2[0].isRational()) {
r = e2[0].getRational();
if (r.isInteger() && r.getNumerator() == 2) {
e2 = preprocessRec(e2[1] * e2[1], cache);
break;
}
}
// fall through
case LT:
case GT:
case LE:
case GE:
case MINUS:
case MULT:
case INTDIV:
case MOD:
arith_rewrites:
if (d_iteLiftArith) {
diff = false;
children.clear();
vector<Expr> children2;
Expr cond;
for (int k = 0; k < e2.arity(); ++k) {
if (e2[k].getKind() == ITE && !diff) {
diff = true;
cond = e2[k][0];
children.push_back(e2[k][1]);
children2.push_back(e2[k][2]);
}
else {
children.push_back(e2[k]);
children2.push_back(e2[k]);
}
}
if (diff) {
Expr thenpart = Expr(e2.getOp(), children);
Expr elsepart = Expr(e2.getOp(), children2);
e2 = cond.iteExpr(thenpart, elsepart);
e2 = preprocessRec(e2, cache);
break;
}
}
if (d_convertToDiff != "" && d_theoryArith->isAtomicArithFormula(e2)) {
Expr e3 = d_theoryArith->rewriteToDiff(e2);
if (e2 != e3) {
DebugAssert(e3 == d_theoryArith->rewriteToDiff(e3), "Expected idempotent rewrite");
e2 = preprocessRec(e3, cache);
}
break;
}
break;
default:
break;
}
// Figure out language
switch (e2.getKind()) {
case RATIONAL_EXPR:
r = e2.getRational();
if (r.isInteger()) {
d_intConstUsed = true;
}
else {
d_realUsed = true;
}
if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
break;
case IS_INTEGER:
d_unknown = true;
break;
case PLUS: {
if (e2.arity() == 2) {
int nonconst = 0, isconst = 0;
Expr::iterator i = e2.begin(), iend = e2.end();
for(; i!=iend; ++i) {
if ((*i).isRational()) {
if ((*i).getRational() <= 0) {
d_UFIDL_ok = false;
break;
}
else ++isconst;
}
else ++nonconst;
}
if (nonconst > 1 || isconst > 1)
d_UFIDL_ok = false;
}
else d_UFIDL_ok = false;
if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
break;
}
case MINUS:
if (!e2[1].isRational() || e2[1].getRational() <= 0) {
d_UFIDL_ok = false;
}
if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
break;
case UMINUS:
d_UFIDL_ok = false;
if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
break;
case MULT: {
d_UFIDL_ok = false;
if (d_langUsed == NONLINEAR) break;
d_langUsed = LINEAR;
bool nonconst = false;
for (int i=0; i!=e2.arity(); ++i) {
if (e2[i].isRational()) continue;
if (nonconst) {
d_langUsed = NONLINEAR;
break;
}
nonconst = true;
}
break;
}
case POW:
case DIVIDE:
d_unknown = true;
break;
case EQ:
if (d_theoryArith->getBaseType(e2[0]) != d_theoryArith->realType())
break;
case LT:
case GT:
case LE:
case GE:
if (d_langUsed >= LINEAR) break;
if (!d_theoryArith->isAtomicArithFormula(e2)) {
d_langUsed = LINEAR;
break;
}
if (e2[0].getKind() == MINUS &&
d_theoryArith->isLeaf(e2[0][0]) &&
d_theoryArith->isLeaf(e2[0][1]) &&
e2[1].isRational()) {
d_langUsed = DIFF_ONLY;
break;
}
if (d_theoryArith->isLeaf(e2[0]) &&
d_theoryArith->isLeaf(e2[1])) {
d_langUsed = DIFF_ONLY;
break;
}
d_langUsed = LINEAR;
break;
default:
break;
}
d_theoryCore->theoryOf(e2)->setUsed();
cache[e] = e2;
return e2;
}
Expr Translator::preprocess(const Expr& e, ExprMap<Expr>& cache)
{
Expr result;
try {
result = preprocessRec(e, cache);
} catch (SmtlibException& ex) {
cerr << "Error while processing the formula:\n"
<< e.toString() << endl;
throw ex;
}
return result;
}
Expr Translator::preprocess2Rec(const Expr& e, ExprMap<Expr>& cache, Type desiredType)
{
ExprMap<Expr>::iterator i(cache.find(e));
if(i != cache.end()) {
if ((desiredType.isNull() &&
(*i).second.getType() != d_theoryArith->realType()) ||
(*i).second.getType() == desiredType) {
return (*i).second;
}
}
if (e.isClosure()) {
Expr newBody = preprocess2Rec(e.getBody(), cache, Type());
Expr e2(e);
if (newBody != e.getBody()) {
e2 = d_em->newClosureExpr(e.getKind(), e.getVars(), newBody);
}
cache[e] = e2;
return e2;
}
bool forceReal = false;
if (desiredType == d_theoryArith->intType() &&
e.getType() != d_theoryArith->intType()) {
d_unknown = true;
// throw SmtlibException("Unable to separate int and real "+
// e.getType().getExpr().toString()+
// "\n\nwhile processing the term:\n"+
// e.toString(PRESENTATION_LANG));
}
// Try to force type-compliance
switch (e.getKind()) {
case EQ:
case LT:
case GT:
case LE:
case GE:
if (e[0].getType() != e[1].getType()) {
if (e[0].getType() != d_theoryArith->intType() &&
e[1].getType() != d_theoryArith->intType()) {
d_unknown = true;
throw SmtlibException("Expected each side to be REAL or INT, but we got lhs: "+
e[0].getType().getExpr().toString()+" and rhs: "+
e[1].getType().getExpr().toString()+
"\n\nwhile processing the term:\n"+
e.toString());
}
forceReal = true;
break;
case ITE:
case UMINUS:
case PLUS:
case MINUS:
case MULT:
if (desiredType == d_theoryArith->realType())
forceReal = true;
break;
case DIVIDE:
forceReal = true;
break;
default:
break;
}
}
Expr e2(e);
vector<Expr> children;
bool diff = false;
Type funType;
if (e.isApply()) {
funType = e.getOpExpr().getType();
if (funType.getExpr().getKind() == ANY_TYPE) funType = Type();
}
for(int k = 0; k < e.arity(); ++k) {
Type t;
if (forceReal && e[k].getType() == d_theoryArith->intType())
t = d_theoryArith->realType();
else if (!funType.isNull()) t = funType[k];
// Recursively preprocess the kids
Expr child = preprocess2Rec(e[k], cache, t);
if (child != e[k]) diff = true;
children.push_back(child);
}
if (diff) {
e2 = Expr(e.getOp(), children);
}
else if (e2.getKind() == RATIONAL_EXPR) {
if (e2.getType() == d_theoryArith->realType() ||
(e2.getType() == d_theoryArith->intType() &&
desiredType == d_theoryArith->realType()))
e2 = Expr(REAL_CONST, e2);
}
if (!desiredType.isNull() && e2.getType() != desiredType) {
d_unknown = true;
throw SmtlibException("Type error: expected "+
desiredType.getExpr().toString()+
" but instead got "+
e2.getType().getExpr().toString()+
"\n\nwhile processing term:\n"+
e.toString());
}
cache[e] = e2;
return e2;
}
Expr Translator::preprocess2(const Expr& e, ExprMap<Expr>& cache)
{
Expr result;
try {
result = preprocess2Rec(e, cache, Type());
} catch (SmtlibException& ex) {
cerr << "Error while processing the formula:\n"
<< e.toString() << endl;
throw ex;
}
return result;
}
bool Translator::containsArray(const Expr& e)
{
if (e.getKind() == ARRAY) return true;
Expr::iterator i = e.begin(), iend=e.end();
for(; i!=iend; ++i) if (containsArray(*i)) return true;
return false;
}
Translator::Translator(ExprManager* em,
const bool& translate,
const bool& real2int,
const bool& convertArith,
const string& convertToDiff,
bool iteLiftArith,
const string& expResult,
const string& category,
bool convertArray,
bool combineAssump)
: d_em(em), d_translate(translate),
d_real2int(real2int),
d_convertArith(convertArith),
d_convertToDiff(convertToDiff),
d_iteLiftArith(iteLiftArith),
d_expResult(expResult),
d_category(category),
d_convertArray(convertArray),
d_combineAssump(combineAssump),
d_dump(false), d_dumpFileOpen(false),
d_intIntArray(false), d_intRealArray(false), d_intIntRealArray(false),
d_ax(false), d_unknown(false),
d_realUsed(false), d_intUsed(false), d_intConstUsed(false),
d_langUsed(NOT_USED), d_UFIDL_ok(true), d_arithUsed(false),
d_zeroVar(NULL)
{}
bool Translator::start(const string& dumpFile)
{
if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
d_dump = true;
if (dumpFile == "") {
d_osdump = &cout;
}
else {
d_osdumpFile.open(dumpFile.c_str());
if(!d_osdumpFile)
throw Exception("cannot open a log file: "+dumpFile);
else {
d_dumpFileOpen = true;
d_osdump = &d_osdumpFile;
}
}
*d_osdump <<
"(benchmark " << fileToSMTLIBIdentifier(dumpFile) << endl <<
" :source {" << endl;
string tmpName;
string::size_type pos = dumpFile.rfind("/");
if (pos == string::npos) {
tmpName = "README";
}
else {
tmpName = dumpFile.substr(0,pos+1) + "README";
}
d_tmpFile.open(tmpName.c_str());
char c;
if (d_tmpFile.is_open()) {
d_tmpFile.get(c);
while (!d_tmpFile.eof()) {
if (c == '{' || c == '}') *d_osdump << '\\';
*d_osdump << c;
d_tmpFile.get(c);
}
d_tmpFile.close();
}
else {
*d_osdump << "Source unknown";
}
*d_osdump << endl;// <<
// "This benchmark was automatically translated into SMT-LIB format from" << endl <<
// "CVC format using CVC3" << endl;
*d_osdump << "}" << endl;
}
else {
if (dumpFile == "") {
if (d_translate) {
d_osdump = &cout;
d_dump = true;
}
}
else {
d_osdumpFile.open(dumpFile.c_str());
if(!d_osdumpFile)
throw Exception("cannot open a log file: "+dumpFile);
else {
d_dump = true;
d_dumpFileOpen = true;
d_osdump = &d_osdumpFile;
}
}
}
return d_dump;
}
void Translator::dump(const Expr& e, bool dumpOnly)
{
DebugAssert(d_dump, "dump called unexpectedly");
if (!dumpOnly || !d_translate) {
if (d_convertArray && e.getKind() == CONST &&
e.arity() == 2) {
if (e[1].getKind() == ARRAY) {
if (containsArray(e[1][0]) ||
containsArray(e[1][1])) {
throw Exception("convertArray failed because of nested arrays in"+
e[1].toString());
}
Expr funType = Expr(ARROW, e[1][0], e[1][1]);
Expr outExpr = Expr(CONST, e[0], funType);
if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
d_dumpExprs.push_back(outExpr);
}
else {
*d_osdump << outExpr << endl;
}
}
else if (containsArray(e[1])) {
throw Exception("convertArray failed becauase of use of arrays in"+
e[1].toString());
}
else if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
d_dumpExprs.push_back(e);
}
else *d_osdump << e << endl;
}
else if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
d_dumpExprs.push_back(e);
}
else *d_osdump << e << endl;
}
}
bool Translator::dumpAssertion(const Expr& e)
{
Expr outExpr = Expr(ASSERT, e);
if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
d_dumpExprs.push_back(outExpr);
}
else {
*d_osdump << outExpr << endl;
}
return d_translate;
}
bool Translator::dumpQuery(const Expr& e)
{
Expr outExpr = Expr(QUERY, e);
if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
d_dumpExprs.push_back(outExpr);
}
else {
*d_osdump << outExpr << endl;
}
return d_translate;
}
void Translator::dumpQueryResult(QueryResult qres)
{
if(d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
*d_osdump << " :status ";
switch (qres) {
case UNSATISFIABLE:
*d_osdump << "unsat" << endl;
break;
case SATISFIABLE:
*d_osdump << "sat" << endl;
break;
default:
*d_osdump << "unknown" << endl;
break;
}
}
}
Expr Translator::processType(const Expr& e)
{
switch (e.getKind()) {
case INT:
d_intUsed = true;
break;
case REAL:
if (d_real2int) {
d_intUsed = true;
return d_theoryArith->intType().getExpr();
}
else {
d_realUsed = true;
}
break;
case SUBRANGE:
d_unknown = true;
break;
default:
break;
}
d_theoryCore->theoryOf(e)->setUsed();
if (e.arity() == 0) return e;
bool changed = false;
vector<Expr> vec;
for (int i = 0; i < e.arity(); ++i) {
vec.push_back(processType(e[i]));
if (vec.back() != e[i]) changed = true;
}
if (changed)
return Expr(e.getOp(), vec);
return e;
}
void Translator::finish()
{
if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
// Print the rest of the preamble for smt-lib benchmarks
// Get status from expResult flag
*d_osdump << " :status ";
if (d_expResult == "invalid" ||
d_expResult == "satisfiable")
*d_osdump << "sat";
else if (d_expResult == "valid" ||
d_expResult == "unsatisfiable")
*d_osdump << "unsat";
else *d_osdump << "unknown";
*d_osdump << endl;
// difficulty
*d_osdump << " :difficulty { unknown }" << endl;
// category
*d_osdump << " :category { ";
*d_osdump << d_category << " }" << endl;
// Compute logic for smt-lib
bool qf_uf = false;
{
{
ExprMap<Expr> cache;
// Step 1: preprocess asserts, queries, and types
vector<Expr>::iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
for (; i != iend; ++i) {
Expr e = *i;
switch (e.getKind()) {
case ASSERT: {
Expr e2 = preprocess(e[0], cache);
if (e[0] == e2) break;
e2.getType();
*i = Expr(ASSERT, e2);
break;
}
case QUERY: {
Expr e2 = preprocess(e[0].negate(), cache);
if (e[0].negate() == e2) break;
e2.getType();
*i = Expr(QUERY, e2.negate());
break;
}
case CONST: {
DebugAssert(e.arity() == 2, "Expected CONST with arity 2");
Expr e2 = processType(e[1]);
if (e[1] == e2) break;
*i = Expr(CONST, e[0], e2);
break;
}
default:
break;
}
}
}
if (d_zeroVar) {
d_dumpExprs.insert(d_dumpExprs.begin(),
Expr(CONST, Expr(ID, d_em->newStringExpr("cvc3Zero")),
processType(d_zeroVar->getType().getExpr())));
}
// Step 2: If both int and real are used, try to separate them
if (!d_unknown && d_intUsed && d_realUsed) {
ExprMap<Expr> cache;
vector<Expr>::iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
for (; i != iend; ++i) {
Expr e = *i;
switch (e.getKind()) {
case ASSERT: {
Expr e2 = preprocess2(e[0], cache);
e2.getType();
*i = Expr(ASSERT, e2);
break;
}
case QUERY: {
Expr e2 = preprocess2(e[0].negate(), cache);
e2.getType();
*i = Expr(QUERY, e2.negate());
break;
}
default:
break;
}
}
}
d_arithUsed = d_realUsed || d_intUsed || d_intConstUsed || (d_langUsed != NOT_USED);
// Step 3: Go through the cases and figure out the right logic
*d_osdump << " :logic ";
if (d_unknown ||
d_theoryRecords->theoryUsed() ||
d_theorySimulate->theoryUsed() ||
d_theoryDatatype->theoryUsed()) {
*d_osdump << "unknown";
}
else {
if ((d_ax && (d_arithUsed ||
d_theoryBitvector->theoryUsed() ||
d_theoryUF->theoryUsed())) ||
(d_intIntArray && d_realUsed) ||
(d_arithUsed && d_theoryBitvector->theoryUsed())) {
*d_osdump << "unknown";
}
else {
bool QF = false;
bool A = false;
bool UF = false;
if (!d_theoryQuant->theoryUsed()) {
QF = true;
*d_osdump << "QF_";
}
if (d_theoryArray->theoryUsed() && !d_convertArray) {
A = true;
*d_osdump << "A";
}
// Promote undefined subset logics
else if (!QF && !d_theoryBitvector->theoryUsed()) {
A = true;
*d_osdump << "A";
}
if (d_theoryUF->theoryUsed() ||
(d_theoryArray->theoryUsed() && d_convertArray)) {
UF = true;
*d_osdump << "UF";
}
// Promote undefined subset logics
else if (!QF &&
!d_theoryBitvector->theoryUsed()) {
UF = true;
*d_osdump << "UF";
}
if (d_arithUsed) {
if (d_intUsed && d_realUsed) {
if (d_langUsed < NONLINEAR) {
*d_osdump << "LIRA";
}
else *d_osdump << "NIRA";
}
else if (d_realUsed) {
if (d_langUsed <= DIFF_ONLY) {
// Promote undefined subset logics
if (!QF) {
*d_osdump << "LIRA";
} else
*d_osdump << "RDL";
}
else if (d_langUsed <= LINEAR) {
// Promote undefined subset logics
if (!QF) {
*d_osdump << "LIRA";
} else
*d_osdump << "LRA";
}
else {
// Promote undefined subset logics
if (!QF) {
*d_osdump << "NIRA";
} else
*d_osdump << "NRA";
}
}
else {
if (QF && !A && UF && d_langUsed <= LINEAR) {
if (!d_realUsed && d_langUsed <= LINEAR && d_UFIDL_ok) {
*d_osdump << "IDL";
}
else {
*d_osdump << "LIA";
}
}
else if (d_langUsed <= DIFF_ONLY) {
// Promote undefined subset logics
if (!QF) {
*d_osdump << "LIA";
}
else if (A) {
if (!UF) {
UF = true;
*d_osdump << "UF";
}
*d_osdump << "LIA";
} else
*d_osdump << "IDL";
}
else if (d_langUsed <= LINEAR) {
// Promote undefined subset logics
if (QF && A && !UF) {
UF = true;
*d_osdump << "UF";
}
if (QF && !A && (!d_realUsed && d_langUsed <= LINEAR && d_UFIDL_ok)) {
*d_osdump << "UFIDL";
}
else {
*d_osdump << "LIA";
}
}
else {
// Promote undefined subset logics
if (!QF) {
*d_osdump << "NIRA";
} else
*d_osdump << "NIA";
}
}
}
else if (d_theoryBitvector->theoryUsed()) {
// Promote undefined subset logics
if (A && QF && !UF) {
UF = true;
*d_osdump << "UF";
}
*d_osdump << "BV";//[" << d_theoryBitvector->getMaxSize() << "]";
}
else {
if (d_ax) {
*d_osdump << "X";
}
// Promote undefined subset logics
else if (!QF || (A && UF)) {
*d_osdump << "LIA";
} else {
// Default logic
if (!A && !UF) {
UF = true;
*d_osdump << "UF";
}
qf_uf = QF && UF && (!A);
}
}
}
}
}
*d_osdump << endl;
// Dump the actual expressions
vector<Expr>::const_iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
vector<Expr> assumps;
for (; i != iend; ++i) {
Expr e = *i;
switch (e.getKind()) {
case ASSERT: {
if (d_combineAssump) {
assumps.push_back(e[0]);
}
else {
*d_osdump << " :assumption" << endl;
*d_osdump << e[0] << endl;
}
break;
}
case QUERY: {
*d_osdump << " :formula" << endl;
if (!assumps.empty()) {
assumps.push_back(e[0].negate());
e = Expr(AND, assumps);
*d_osdump << e << endl;
}
else {
*d_osdump << e[0].negate() << endl;
}
break;
}
default:
if (qf_uf && e.getKind() == TYPE && e[0].getKind() == RAW_LIST &&
e[0][0].getKind() == ID && e[0][0][0].getKind() == STRING_EXPR &&
e[0][0][0].getString() == "U")
break;
*d_osdump << e << endl;
break;
}
}
*d_osdump << ")" << endl;
}
if (d_dumpFileOpen) d_osdumpFile.close();
if (d_zeroVar) delete d_zeroVar;
}
const string Translator::fixConstName(const string& s)
{
if (d_em->getOutputLang() == SMTLIB_LANG) {
if (s[0] == '_') {
return "smt"+s;
}
}
return s;
}
bool Translator::printArrayExpr(ExprStream& os, const Expr& e)
{
if (e.getKind() == ARRAY) {
if (d_convertArray) {
os << Expr(ARROW, e[0], e[1]);
return true;
}
if (d_em->getOutputLang() != SMTLIB_LANG) return false;
if (e[0].getKind() == TYPEDECL) {
DebugAssert(e[0].arity() == 1, "expected arity 1");
if (e[0][0].getString() == "Index") {
if (e[1].getKind() == TYPEDECL) {
DebugAssert(e[1].arity() == 1, "expected arity 1");
if (e[1][0].getString() == "Element") {
d_ax = true;
os << "Array";
return true;
}
}
}
}
else if (isInt(Type(e[0]))) {
if (isInt(Type(e[1]))) {
d_intIntArray = true;
os << "Array";
return true;
}
else if (isReal(Type(e[1]))) {
d_intRealArray = true;
os << "Array1";
return true;
}
else if (isArray(Type(e[1])) &&
isInt(Type(e[1][0])) &&
isReal(Type(e[1][1]))) {
d_intIntRealArray = true;
os << "Array2";
return true;
}
}
else if (e[0].getKind() == BITVECTOR &&
e[1].getKind() == BITVECTOR) {
os << "Array[";
os << d_theoryBitvector->getBitvectorTypeParam(Type(e[0]));
os << ":";
os << d_theoryBitvector->getBitvectorTypeParam(Type(e[1]));
os << "]";
return true;
}
os << "Array";
d_unknown = true;
return true;
}
switch (e.getKind()) {
case READ:
if (d_convertArray) {
if (e[0].getKind() == UCONST) {
os << Expr(d_em->newSymbolExpr(e[0].getName(), UFUNC).mkOp(), e[1]);
return true;
}
else if (e[0].getKind() == WRITE) {
throw Exception("READ of WRITE not implemented yet for convertArray");
}
else {
throw Exception("Unexpected case for convertArray");
}
}
break;
case WRITE:
if (d_convertArray) {
throw Exception("WRITE expression encountered while attempting "
"to convert arrays to uninterpreted functions");
}
break;
case ARRAY_LITERAL:
if (d_convertArray) {
throw Exception("ARRAY_LITERAL expression encountered while attempting"
" to convert arrays to uninterpreted functions");
}
break;
default:
throw Exception("Unexpected case in printArrayExpr");
break;
}
return false;
}
Expr Translator::zeroVar()
{
if (!d_zeroVar) {
d_zeroVar = new Expr();
if (d_convertToDiff == "int") {
*d_zeroVar = d_theoryCore->newVar("cvc3Zero", d_theoryArith->intType().getExpr());
}
else if (d_convertToDiff == "real") {
*d_zeroVar = d_theoryCore->newVar("cvc3Zero", d_theoryArith->realType().getExpr());
}
}
return *d_zeroVar;
}
syntax highlighted by Code2HTML, v. 0.9.1