Beispiel #1
0
//input should be in non-cascaded form
LFSCProof* LFSCProof::Make_and_elim( const Expr& form, LFSCProof* p, int n,  const Expr& expected )
{
  Expr e = cascade_expr( form );
  for( int a=0; a<n; a++ ){
    if( e.arity()==2 ){
      e = e[1];
    }else{
      print_error( "WARNING: and elim out of range", cout );
    }
  }
  if( form.arity()>1 )
  {
    ostringstream os1, os2;
    os1 << "(and_elim";
    if( n==form.arity()-1 )
      os1 << "_end";
    os1 << " _ _ " << n << " ";
    os2 << ")";
    return LFSCProofGeneric::Make( os1.str(), p, os2.str() );
  }
  else
  {
    return p;
  }
}
Beispiel #2
0
bool TheoryArith::isAtomicArithTerm(const Expr& e)
{
  switch (e.getKind()) {
    case RATIONAL_EXPR:
      return true;
    case ITE:
      return false;
    case UMINUS:
    case PLUS:
    case MINUS:
    case MULT:
    case DIVIDE:
    case POW:
    case INTDIV:
    case MOD: {
      int i=0, iend=e.arity();
      for(; i!=iend; ++i) {
        if (!isAtomicArithTerm(e[i])) return false;
      }
      break;
    }
    default:
      break;
  }
  return true;
}
Beispiel #3
0
bool TheoryArith::leavesAreNumConst(const Expr& e)
{
  DebugAssert(e.isTerm() ||
              (e.isPropAtom() && theoryOf(e) == this),
              "Expected term or arith prop atom");

  if (e.validTerminalsConstFlag()) {
    return e.getTerminalsConstFlag();
  }

  if (e.isRational()) {
    e.setTerminalsConstFlag(true);
    return true;
  }

  if (e.isAtomic() && isLeaf(e)) {
    e.setTerminalsConstFlag(false);
    return false;
  }

  DebugAssert(e.arity() > 0, "Expected non-zero arity");
  int k = 0;

  if (e.isITE()) {
    k = 1;
  }

  for (; k < e.arity(); ++k) {
    if (!leavesAreNumConst(e[k])) {
      e.setTerminalsConstFlag(false);
      return false;
    }
  }
  e.setTerminalsConstFlag(true);
  return true;
}
void VCCmd::findAxioms(const Expr& e,  ExprMap<bool>& skolemAxioms,
		       ExprMap<bool>& visited) {
  if(visited.count(e)>0)
    return;
  else visited[e] = true;
  if(e.isSkolem()) {
    skolemAxioms.insert(e.getExistential(), true);
    return;
  }
  if(e.isClosure()) {
    findAxioms(e.getBody(), skolemAxioms, visited);
  }
  if(e.arity()>0) {
    Expr::iterator end = e.end();
    for(Expr::iterator i = e.begin(); i!=end; ++i)
      findAxioms(*i, skolemAxioms, visited);
  }

}
Beispiel #5
0
Theorem TheoryArith::canonRec(const Expr& e)
{
  if (isLeaf(e)) return reflexivityRule(e);
  int ar = e.arity();
  if (ar > 0) {
    vector<Theorem> newChildrenThm;
    vector<unsigned> changed;
    for(int k = 0; k < ar; ++k) {
      // Recursively canonize the kids
      Theorem thm = canonRec(e[k]);
      if (thm.getLHS() != thm.getRHS()) {
	newChildrenThm.push_back(thm);
	changed.push_back(k);
      }
    }
    if(changed.size() > 0) {
      return canonThm(substitutivityRule(e, changed, newChildrenThm));
    }
  }
  return canon(e);
}
Beispiel #6
0
Theorem TheoryArith::canonSimp(const Expr& e)
{
  DebugAssert(canonRec(e).getRHS() == e, "canonSimp expects input to be canonized");
  int ar = e.arity();
  if (isLeaf(e)) return find(e);
  if (ar > 0) {
    vector<Theorem> newChildrenThm;
    vector<unsigned> changed;
    Theorem thm;
    for (int k = 0; k < ar; ++k) {
      thm = canonSimp(e[k]);
      if (thm.getLHS() != thm.getRHS()) {
        newChildrenThm.push_back(thm);
        changed.push_back(k);
      }
    }
    if(changed.size() > 0) {
      thm = canonThm(substitutivityRule(e, changed, newChildrenThm));
      return transitivityRule(thm, find(thm.getRHS()));
    }
    else return find(e);
  }
  return find(e);
}
Beispiel #7
0
Expr TheoryArith::rewriteToDiff(const Expr& e)
{
  Expr tmp = e[0] - e[1];
  tmp = canonRec(tmp).getRHS();
  switch (tmp.getKind()) {
    case RATIONAL_EXPR: {
      Rational r = tmp.getRational();
      switch (e.getKind()) {
        case LT:
          if (r < 0) return trueExpr();
          else return falseExpr();
        case LE:
          if (r <= 0) return trueExpr();
          else return falseExpr();
        case GT:
          if (r > 0) return trueExpr();
          else return falseExpr();
        case GE:
          if (r >= 0) return trueExpr();
          else return falseExpr();
        case EQ:
          if (r == 0) return trueExpr();
          else return falseExpr();
      }
    }
    case MULT:
      DebugAssert(tmp[0].isRational(), "Unexpected term structure from canon");
      if (tmp[0].getRational() != -1) return e;
      return Expr(e.getOp(), theoryCore()->getTranslator()->zeroVar() - tmp[1], rat(0));
    case PLUS: {
      DebugAssert(tmp[0].isRational(), "Unexpected term structure from canon");
      Rational c = tmp[0].getRational();
      Expr x, y;
      if (tmp.arity() == 2) {
        if (tmp[1].getKind() == MULT) {
          x = theoryCore()->getTranslator()->zeroVar();
          y = tmp[1];
        }
        else {
          x = tmp[1];
          y = rat(-1) * theoryCore()->getTranslator()->zeroVar();
        }
      }
      else if (tmp.arity() == 3) {
        if (tmp[1].getKind() == MULT) {
          x = tmp[2];
          y = tmp[1];
        }
        else if (tmp[2].getKind() == MULT) {
          x = tmp[1];
          y = tmp[2];
        }
        else return e;
      }
      else return e;
      if (x.getKind() == MULT) return e;
      DebugAssert(y[0].isRational(), "Unexpected term structure from canon");
      if (y[0].getRational() != -1) return e;
      return Expr(e.getOp(), x - y[1], getEM()->newRatExpr(-c));
    }
    default:
      return Expr(e.getOp(), tmp - theoryCore()->getTranslator()->zeroVar(), rat(0));
      break;
  }
  return e;
}
bool VCCmd::evaluateCommand(const Expr& e0)
{
  TRACE("commands", "evaluateCommand(", e0.toString(PRESENTATION_LANG), ") {");
  Expr e(e0);
  if(e.getKind() != RAW_LIST || e.arity() == 0 || e[0].getKind() != ID)
    throw EvalException("Invalid command: "+e.toString());
  const string& kindName = e[0][0].getString();
  int kind = d_vc->getEM()->getKind(kindName);
  if(kind == NULL_KIND)
    throw EvalException("Unknown command: "+e.toString());
  switch(kind) {
  case CONST: { // (CONST (id_1 ... id_n) type) or (CONST id type)
    if(e.arity() == 3) {
      Type t(d_vc->parseExpr(e[2]));
      vector<Expr> vars;
      if(e[1].getKind() == RAW_LIST)
	vars = e[1].getKids();
      else
	vars.push_back(e[1]);
      for(vector<Expr>::iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) {
	if((*i).getKind() != ID)
	  throw EvalException("Constant name must be an identifier: "
			      +i->toString());
      }
      if (t.isFunction()) {
	for(vector<Expr>::iterator i=vars.begin(), iend=vars.end();
	    i!=iend; ++i) {
	  Op op = d_vc->createOp((*i)[0].getString(), t);
	  TRACE("commands", "evaluateNext: declare new uninterpreted function: ",
		op, "");
	}
      }
      else {
	for(vector<Expr>::iterator i=vars.begin(), iend=vars.end();
	    i!=iend; ++i) {
	  // Add to variable list
	  Expr v = d_vc->varExpr((*i)[0].getString(), t);
	  TRACE_MSG("commands", "** [commands] Declare new variable");
	  TRACE("commands verbose", "evaluateNext: declare new UCONST: ",
		v, "");
	}
      }
    } else if(e.arity() == 4) { // Constant definition (CONST id type def)
      TRACE_MSG("commands", "** [commands] Define new constant");
      // Set the type for later typechecking
      DebugAssert(e[1].getKind() == ID, "Expected ID kind");
      Type t(d_vc->parseExpr(e[2]));
      Expr def(d_vc->parseExpr(e[3]));

      if(t.isFunction()) {
	d_vc->createOp(e[1][0].getString(), t, def);
	TRACE("commands verbose", "evaluateNext: define new function: ",
	      e[1][0].getString(), "");
      } else {
	d_vc->varExpr(e[1][0].getString(), t, def);
	TRACE("commands verbose", "evaluateNext: define new variable: ",
	      e[1][0].getString(), "");
      }
    } else
      throw EvalException("Wrong number of arguments in CONST: "+e.toString());
    break;
  }
  case DEFUN: { // (DEFUN name ((x y z type1) ... ) resType [ body ])
    if(e.arity() != 5 && e.arity() != 4)
      throw EvalException
	("DEFUN requires 3 or 4 arguments:"
	 " (DEFUN f (args) type [ body ]):\n\n  "
	 +e.toString());
    if(e[2].getKind() != RAW_LIST)
      throw EvalException
	("2nd argument of DEFUN must be a list of arguments:\n\n  "
	 +e.toString());

    // Build a CONST declaration and parse it recursively

    // Build the function type
    vector<Expr> argTps;
    for(Expr::iterator i=e[2].begin(), iend=e[2].end(); i!=iend; ++i) {
      if(i->getKind() != RAW_LIST || i->arity() < 2)
	throw EvalException
	  ("DEFUN: bad argument declaration:\n\n  "+i->toString()
	   +"\n\nIn the following statement:\n\n  "
	   +e.toString());
      Expr tp((*i)[i->arity()-1]);
      for(int j=0, jend=i->arity()-1; j<jend; ++j)
	argTps.push_back(tp);
    }
    argTps.push_back(e[3]);
    Expr fnType = d_vc->listExpr("ARROW", argTps);
    Expr newDecl; // The resulting transformed declaration
    if(e.arity() == 5) {
      // Build the LAMBDA expression
      Expr lambda(d_vc->listExpr("LAMBDA", e[2], e[4]));
      // Construct the (CONST name fnType lambda) declaration
      newDecl = d_vc->listExpr("CONST", e[1], fnType, lambda);
    } else {
      newDecl = d_vc->listExpr("CONST", e[1], fnType);
    }
    // Parse the new declaration
    return evaluateCommand(newDecl);
    break;
  }
  case TYPEDEF: {
    if (e.arity() == 2) {
      // Datatype command
      DebugAssert(e.arity() == 2, "Bad TYPEDEF");
      Expr res = d_vc->parseExpr(e[1]);
      // convert res to vectors

      Expr eNames = res[0];
      Expr eCons = res[1];
      Expr eSel = res[2];
      Expr eTypes = res[3];

      vector<string> names;
      vector<vector<string> > constructors(eNames.arity());
      vector<vector<vector<string> > > selectors(eNames.arity());
      vector<vector<vector<Expr> > > types(eNames.arity());

      int i, j, k;
      for (i = 0; i < eNames.arity(); ++i) {
        names.push_back(eNames[i].getString());
        selectors[i].resize(eSel[i].arity());
        types[i].resize(eTypes[i].arity());
        for (j = 0; j < eCons[i].arity(); ++j) {
          constructors[i].push_back(eCons[i][j].getString());
          for (k = 0; k < eSel[i][j].arity(); ++k) {
            selectors[i][j].push_back(eSel[i][j][k].getString());
            types[i][j].push_back(eTypes[i][j][k]);
          }
        }
      }

      vector<Type> returnTypes;
      d_vc->dataType(names, constructors, selectors, types, returnTypes);
      break;
    }
    DebugAssert(e.arity() == 3, "Bad TYPEDEF");
    Expr def(d_vc->parseExpr(e[2]));
    Type t = d_vc->createType(e[1][0].getString(), def);
    TRACE("commands", "evaluateNext: declare new TYPEDEF: ", t, "");
  }
    break;
  case TYPE: {
    if(e.arity() < 2)
      throw EvalException("Bad TYPE declaration: "+e.toString());
    Expr::iterator i=e.begin(), iend=e.end();
    ++i; // Skip "TYPE" symbol
    for(; i!=iend; ++i) {
      if(i->getKind() != ID)
	throw EvalException("Type name must be an identifier: "+i->toString());
      Type t = d_vc->createType((*i)[0].getString());
      TRACE("commands", "evaluateNext: declare new TYPEDECL: ", t, "");
    }
  }
    break;
  case ASSERT: {
    if(e.arity() != 2)
      throw EvalException("ASSERT requires exactly one argument, but is given "
			  +int2string(e.arity()-1)+":\n "+e.toString());
    TRACE_MSG("commands", "** [commands] Asserting formula");
    d_vc->assertFormula(d_vc->parseExpr(e[1]));
    break;
  }
  case QUERY: {
    if(e.arity() != 2)
      throw EvalException("QUERY requires exactly one argument, but is given "
			  +int2string(e.arity()-1)+":\n "+e.toString());
    TRACE_MSG("commands", "** [commands] Query formula");
    QueryResult qres = d_vc->query(d_vc->parseExpr(e[1]));
    if (qres == UNKNOWN && d_vc->getFlags()["unknown-check-model"].getBool())
		qres = d_vc->tryModelGeneration();
    reportResult(qres);
    if (qres == INVALID) {
      if (d_vc->getFlags()["counterexample"].getBool()) {
        printCounterExample();
      }
      if (d_vc->getFlags()["model"].getBool()) {
        printModel();
      }
    }
    break;
  }
  case CHECKSAT: {
    QueryResult qres;
    TRACE_MSG("commands", "** [commands] CheckSat");
    if (e.arity() == 1) {
      qres = d_vc->checkUnsat(d_vc->trueExpr());
    }
    else if (e.arity() == 2) {
      qres = d_vc->checkUnsat(d_vc->parseExpr(e[1]));
    }
    else {
      throw EvalException("CHECKSAT requires no more than one argument, but is given "
			  +int2string(e.arity()-1)+":\n "+e.toString());
    }
    if (qres == UNKNOWN && !d_vc->getFlags()["translate"].getBool() && d_vc->getFlags()["unknown-check-model"].getBool())
    	qres = d_vc->tryModelGeneration();
    reportResult(qres, false);
    if (qres == SATISFIABLE) {
      if (d_vc->getFlags()["counterexample"].getBool()) {
        printCounterExample();
      }
      if (d_vc->getFlags()["model"].getBool()) {
        printModel();
      }
    }
//     {//for debug only by yeting
//       Proof p = d_vc->getProof();
//       if (d_vc->getFlags()["printResults"].getBool()) {
//  	cout << p << endl;
//  	cout << flush;
//       }
//     }


    break;
  }
  case CONTINUE: {
    if (e.arity() != 1) {
      throw EvalException("CONTINUE takes no arguments");
    }
    TRACE_MSG("commands", "** [commands] Continue");
    QueryResult qres = d_vc->checkContinue();
    if (d_vc->getFlags()["printResults"].getBool()) {
      switch (qres) {
        case VALID:
          cout << "No more models found." << endl;
          break;
        case INVALID:
          cout << "Model found" << endl;
          break;
        case ABORT:
          cout << "Unknown: resource limit exhausted." << endl;
          break;
        case UNKNOWN: {
          // Vector of reasons in case of incomplete result
          vector<string> reasons;
          IF_DEBUG(bool b =) d_vc->incomplete(reasons);
          DebugAssert(b, "Expected incompleteness");
          cout << "Unknown.\n\n";
          cout << "CVC3 was incomplete in this example due to:";
          for(vector<string>::iterator i=reasons.begin(), iend=reasons.end();
              i!=iend; ++i)
            cout << "\n * " << (*i);
          cout << endl << endl;
          break;
        }
        default:
          FatalAssert(false, "Unexpected case");
      }
      cout << flush;
    }
    break;
  }
  case RESTART: {
    if(e.arity() != 2)
      throw EvalException("RESTART requires exactly one argument, but is given "
			  +int2string(e.arity()-1)+":\n "+e.toString());
    TRACE_MSG("commands", "** [commands] Restart formula");
    QueryResult qres = d_vc->restart(d_vc->parseExpr(e[1]));
    reportResult(qres);
    if (qres == INVALID) {
      if (d_vc->getFlags()["counterexample"].getBool()) {
        printCounterExample();
      }
      if (d_vc->getFlags()["model"].getBool()) {
        printModel();
      }
    }
    break;
  }
  case TRANSFORM: {
    if(e.arity() != 2)
      throw EvalException
	("TRANSFORM requires exactly one argument, but is given "
	 +int2string(e.arity()-1)+":\n "+e.toString());
    TRACE_MSG("commands", "** [commands] Transforming expression");
    Expr ee = d_vc->parseExpr(e[1]);
    e = d_vc->simplify(ee);
    if (d_vc->getFlags()["printResults"].getBool()) d_vc->printExpr(e);
    break;
  }
  case PRINT:
    if(e.arity() != 2)
      throw EvalException
	("PRINT requires exactly one argument, but is given "
	 +int2string(e.arity()-1)+":\n "+e.toString());
    d_vc->printExpr(d_vc->parseExpr(e[1]));
    break;
  case PUSH:
  case POP:
  case PUSH_SCOPE:
  case POP_SCOPE: {
    int arg;
    if (e.arity() == 1) arg = 1;
    else {
      DebugAssert(e.arity() == 2 && e[1].getKind() == RATIONAL_EXPR,
                  "Bad argument to "+kindName);
      arg = e[1].getRational().getInt();
      if(arg <= 0)
        throw EvalException("Argument to PUSH or POP is <= 0");
    }
    if (kind == PUSH) {
      for (int i = 0; i < arg; i++) {
        d_vc->push();
      }
    }
    else if (kind == POP) {
      if(arg > d_vc->stackLevel())
        throw EvalException("Argument to POP is out of range:\n"
                            " current stack level = "
                            +int2string(d_vc->stackLevel())
                            +"\n argument = "
                            +int2string(arg));
      for (int i = 0; i < arg; i++) {
        d_vc->pop();
      }
    }
    else if (kind == PUSH_SCOPE) {
      for (int i = 0; i < arg; i++) {
        d_vc->pushScope();
      }
    }
    else if (kind == POP_SCOPE) {
      if(arg >= d_vc->scopeLevel())
        throw EvalException("Argument to POP_SCOPE is out of range:\n"
                            " current scope = "
                            +int2string(d_vc->scopeLevel())
                            +"\n argument = "
                            +int2string(arg));
      for (int i = 0; i < arg; i++) {
        d_vc->popScope();
      }
    }
    break;
  }
  case POPTO:
  case POPTO_SCOPE: {
    int arg;
    if (e.arity() == 1) arg = 0;
    else {
      DebugAssert(e.arity() == 2 && e[1].getKind() == RATIONAL_EXPR,
                  "Bad argument to "+kindName);
      arg = e[1].getRational().getInt();
    }
    if (kind == POPTO) {
      d_vc->popto(arg);
    }
    else {
      d_vc->poptoScope(arg);
    }
    break;
  }
  case RESET: {
    throw ResetException();
    break;
  }
  case WHERE:
  case ASSERTIONS:
  case ASSUMPTIONS:
  {
    vector<Expr> assertions;
    ExprMap<bool> skolemAxioms;
    ExprMap<bool> visited;

    d_vc->getAssumptions(assertions);

    if (d_vc->getFlags()["printResults"].getBool()) {
      cout << "Current stack level is " << d_vc->stackLevel()
           << " (scope " << d_vc->scopeLevel() << ")." << endl;
      if (assertions.size() == 0) {
        cout << "% No active assumptions\n";
      } else {
        cout << "% Active assumptions:\n";
        for (unsigned i = 0; i < assertions.size(); i++) {
          cout << "ASSERT " << assertions[i] << ";" << endl;
          findAxioms(assertions[i], skolemAxioms, visited);
        }
        ExprMap<bool>::iterator it = skolemAxioms.begin();
        ExprMap<bool>::iterator end = skolemAxioms.end();
        if (it != end) {
          cout << "% Skolemization axioms" << endl;
          for(; it!=end; ++it)
            cout << "ASSERT " << skolemizeAx((*it).first) << ";" << endl;
        }
      }
      cout << endl;
    }
    break;
  }
  case COUNTEREXAMPLE: {
    if (d_vc->getFlags()["printResults"].getBool()) {
      printCounterExample();
    }
    break;
  }
  case COUNTERMODEL: {
    if (d_vc->getFlags()["printResults"].getBool()) {
      try {
        printModel();
      } catch (Exception& e) {
        throw EvalException(e.toString());
      }
    }
    break;
  }
  case TRACE: { // Set a trace flag
#ifdef _CVC3_DEBUG_MODE
    if(e.arity() != 2)
      throw EvalException("TRACE takes exactly one string argument");
    if(!e[1].isString())
      throw EvalException("TRACE requires a string argument");
    debugger.traceFlag(e[1].getString()) = true;
#endif
  }
    break;
  case UNTRACE: { // Unset a trace flag
#ifdef _CVC3_DEBUG_MODE
    if(e.arity() != 2)
      throw EvalException("UNTRACE takes exactly one string argument");
    if(!e[1].isString())
      throw EvalException("UNTRACE requires a string argument");
    debugger.traceFlag(e[1].getString()) = false;
#endif
  }
    break;
  case OPTION: {
    if(e.arity() != 3)
      throw EvalException("OPTION takes exactly two arguments "
                          "(name and value of a flag)");
    if(!e[1].isString())
      throw EvalException("OPTION: flag name must be a string");
    CLFlags& flags = d_vc->getFlags();
    string name(e[1].getString());
    vector<string> names;
    size_t n = flags.countFlags(name, names);
    if(n != 1)
      throw EvalException("OPTION: found "+int2string(n)
                          +" flags matching "+name
                          +".\nThe flag name must uniquely resolve.");
    name = names[0];
    const CLFlag& flag(flags[name]);
    // If the flag is set on the command line, ignore it
    if(flag.modified()) break;
    switch(flag.getType()) {
    case CLFLAG_BOOL:
      if(!(e[2].isRational() && e[2].getRational().isInteger()))
        throw EvalException("OPTION: flag "+name
                            +" expects a boolean value (0 or 1");
      flags.setFlag(name, e[2].getRational().getInt() != 0);
      break;
    case CLFLAG_INT:
      if(!(e[2].isRational() && e[2].getRational().isInteger()))
        throw EvalException("OPTION: flag "+name+" expects an integer value");
      flags.setFlag(name, e[2].getRational().getInt());
      break;
    case CLFLAG_STRING:
      if(!e[2].isString())
        throw EvalException("OPTION: flag "+name+" expects a string value");
      flags.setFlag(name, e[2].getString());
      break;
    default:
      throw EvalException("OPTION: the type of flag "+name
                          +" is not supported by the OPTION commnand");
      break;
    }
    d_vc->reprocessFlags();
  }
    break;
  case DUMP_PROOF: {
    Proof p = d_vc->getProof();
    if (d_vc->getFlags()["printResults"].getBool()) {
      cout << p << endl;
      cout << flush;
    }
    break;
  }
  case DUMP_ASSUMPTIONS: { // Assumption tracking
    vector<Expr> assertions;
    d_vc->getAssumptionsUsed(assertions);

    if (d_vc->getFlags()["printResults"].getBool()) {
      if(assertions.size() == 0) {
        cout << "% No relevant assumptions\n";
      } else {
        cout << "% Relevant assumptions:\n";
        for (unsigned i = 0; i < assertions.size(); i++) {
          cout << Expr(ASSERT, assertions[i]) << "\n";
        }
      }
      cout << endl << flush;
    }
    break;
  }
  case DUMP_TCC: {
    const Expr& tcc = d_vc->getTCC();

    if (d_vc->getFlags()["printResults"].getBool()) {
      if(tcc.isNull())
        cout << "% No TCC is avaialble" << endl;
      else
        cout << "% TCC for the last declaration, ASSERT, or QUERY:\n\n"
             << tcc << endl;
    }
    break;
  }
  case DUMP_TCC_ASSUMPTIONS: {
    vector<Expr> assertions;
    d_vc->getAssumptionsTCC(assertions);
    if (d_vc->getFlags()["printResults"].getBool()) {
      if(assertions.size() == 0) {
        cout << "% No relevant assumptions\n";
      } else {
        cout << "% Relevant assumptions for the last TCC:\n";
        for (unsigned i = 0; i < assertions.size(); i++) {
          cout << Expr(ASSERT, assertions[i]) << "\n";
        }
      }
      cout << endl << flush;
    }
    break;
  }
  case DUMP_TCC_PROOF: {
    const Proof& tcc = d_vc->getProofTCC();
    if (d_vc->getFlags()["printResults"].getBool()) {
      if(tcc.isNull())
        cout << "% No TCC is avaialble" << endl;
      else
        cout << "% Proof of TCC for the last declaration, ASSERT, or QUERY:\n\n"
             << tcc << endl;
    }
    break;
  }
  case DUMP_CLOSURE: {
    const Expr& cl = d_vc->getClosure();
    if (d_vc->getFlags()["printResults"].getBool()) {
      if(cl.isNull())
        cout << "% No closure is avaialble" << endl;
      else
        cout << "% Closure for the last QUERY:\n\n" << cl << endl;
    }
    break;
  }
  case DUMP_CLOSURE_PROOF: {
    const Proof& cl = d_vc->getProofClosure();
    if (d_vc->getFlags()["printResults"].getBool()) {
      if(cl.isNull())
        cout << "% No closure is avaialble" << endl;
      else
        cout << "% Proof of closure for the last QUERY:\n\n" << cl << endl;
    }
    break;
  }
  case ECHO:
    if(e.arity() != 2)
      throw EvalException("ECHO: wrong number of arguments: "
			  + e.toString());
    if(!e[1].isString())
      throw EvalException("ECHO: the argument must be a string: "
			  +e.toString());
    if (d_vc->getFlags()["printResults"].getBool()) {
      cout << e[1].getString();
      cout << endl << flush;
    }
    break;
  case SEQ: {
    Expr::iterator i=e.begin(), iend=e.end();
    ++i; // Skip "SEQ" symbol
    bool success = true;
    for(; i!=iend; ++i) {
      try {
        success = success && evaluateCommand(*i);
      } catch(ResetException& e) {
        if (++i == iend) throw e;
        throw EvalException("RESET can only be the last command in a sequence");
      }
    }
    return success;
  }
  case ARITH_VAR_ORDER: {
	  if (e.arity() <= 2)
		  throw EvalException("ARITH_VAR_ORDER takes at least two arguments");
	  Expr smaller;
	  Expr bigger = d_vc->parseExpr(e[1]);
	  for (int i = 2; i < e.arity(); i ++) {
		  smaller = bigger;
		  bigger = d_vc->parseExpr(e[i]);
		  if (!d_vc->addPairToArithOrder(smaller, bigger))
			  throw EvalException("ARITH_VAR_ORDER only takes arithmetic terms");
	  }
	  return true;
  }
  case ANNOTATION: {
    for (int i = 1; i < e.arity(); ++i) {
      if (e[i].arity() == 1) {
        d_vc->logAnnotation(Expr(ANNOTATION, e[i][0]));
      }
      else {
        DebugAssert(e[i].arity() == 2, "Expected arity 2");
        d_vc->logAnnotation(Expr(ANNOTATION, e[i][0], e[i][1]));
      }
    }
    break;
  }
  case INCLUDE: { // read in the specified file
    if(e.arity() != 2)
      throw EvalException("INCLUDE takes exactly one string argument");
    if(!e[1].isString())
      throw EvalException("INCLUDE requires a string argument");
    ifstream fs;
    fs.open(e[1].getString().c_str(),ios::in);
    if(!fs.is_open()) {
      fs.close();
      throw EvalException("File "+e[1].getString()+" does not exist");
    }
    fs.close();
    d_vc->loadFile(e[1].getString(),
                   d_vc->getEM()->getInputLang(),
                   d_vc->getFlags()["interactive"].getBool(),
                   true /* nested call */);
    break;
  }
  case HELP:
    cout << "Use the -help command-line option for help." << endl;
    break;
  case DUMP_SIG:
  case DBG:
  case SUBSTITUTE:
  case GET_CHILD:
  case GET_TYPE:
  case CHECK_TYPE:
  case FORGET:
  case CALL:
  default:
    throw EvalException("Unknown command: " + e.toString());
    break;
  }
  TRACE_MSG("commands", "evaluateCommand => true }");
  return true;
}