/*******************************************************************\

Module:

Author: Daniel Kroening, kroening@cs.cmu.edu

\*******************************************************************/

#include "boolbv.h"

/*******************************************************************\

Function: boolbvt::convert_bitwise

  Inputs:

 Outputs:

 Purpose:

\*******************************************************************/

bool boolbvt::convert_bitwise(const exprt &expr, bvt &bv)
{
  unsigned width;
  if(get_width(expr.type(), width))
    return true;

  if(expr.id()=="bitnot")
  {
    if(expr.operands().size()!=1)
      throw "bitnot takes one operand";

    const exprt &op0=expr.op0();
    
    bvt op_bv;
    if(convert_bv(op0, op_bv)) return true;

    bv.resize(width);
    
    if(op_bv.size()!=width)
      throw "convert_bitwise: unexpected operand width";

    for(unsigned i=0; i<width; i++)
      bv[i]=prop.lnot(op_bv[i]);

    return false;
  }
  else if(expr.id()=="bitand" || expr.id()=="bitor" ||
          expr.id()=="bitxor")
  {
    bv.resize(width);

    for(unsigned i=0; i<width; i++)
      bv[i]=prop.constant(expr.id()=="bitand");
    
    forall_operands(it, expr)
    {
      bvt op;

      if(convert_bv(*it, op)) return true;

      if(op.size()!=width)
        throw "convert_bitwise: unexpected operand width";

      for(unsigned i=0; i<width; i++)
      {
        if(expr.id()=="bitand")
          bv[i]=prop.land(bv[i], op[i]);
        else if(expr.id()=="bitor")
          bv[i]=prop.lor(bv[i], op[i]);
        else if(expr.id()=="bitxor")
          bv[i]=prop.lxor(bv[i], op[i]);
        else
          throw "unexpected operand";
      }
    }    

    return false;
  }
 
  throw "unexpected bitwise operand";
}
