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

Module:

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

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

#ifndef CPROVER_STD_EXPR_H
#define CPROVER_STD_EXPR_H

#include <assert.h>

#include <expr.h>

class transt:public exprt
{
public:
  transt()
  {
    id("trans");
    operands().resize(3);
  }

  exprt &invar() { return op0(); }
  exprt &init()  { return op1(); }
  exprt &trans() { return op2(); }

  const exprt &invar() const { return op0(); }
  const exprt &init()  const { return op1(); }
  const exprt &trans() const { return op2(); }

  friend const transt &to_trans(const exprt &expr)
  {
    assert(expr.id()=="trans" && expr.operands().size()==3);
    return (const transt &)expr;
  }

  friend transt &to_trans(exprt &expr)
  {
    assert(expr.id()=="trans" && expr.operands().size()==3);
    return (transt &)expr;
  }
};

class expr_symbolt:public exprt
{
public:
  expr_symbolt():exprt("symbol")
  {
  }

  expr_symbolt(const irep_idt &identifier):exprt("symbol")
  {
    set_identifier(identifier);
  }

  expr_symbolt(const irep_idt &identifier,
               const typet &type):exprt("symbol", type)
  {
    set_identifier(identifier);
  }

  void set_identifier(const irep_idt &identifier)
  {
    set("identifier", identifier);
  }

  const irep_idt &get_identifier() const
  {
    return get("identifier");
  }

  friend const expr_symbolt &to_expr_symbol(const exprt &expr)
  {
    assert(expr.id()=="symbol" && !expr.has_operands());
    return (const expr_symbolt &)expr;
  }

  friend expr_symbolt &to_expr_symbol(exprt &expr)
  {
    assert(expr.id()=="symbol" && !expr.has_operands());
    return (expr_symbolt &)expr;
  }
};

const expr_symbolt &to_expr_symbol(const exprt &expr);
expr_symbolt &to_expr_symbol(exprt &expr);

class expr_equalityt:public exprt
{
public:
  expr_equalityt():exprt("=", typet("bool"))
  {
    operands().resize(2);
  }

  friend const expr_equalityt &to_expr_equality(const exprt &expr)
  {
    assert(expr.id()=="=" && expr.operands().size()==2);
    return static_cast<const expr_equalityt &>(expr);
  }

  friend expr_equalityt &to_expr_equality(exprt &expr)
  {
    assert(expr.id()=="=" && expr.operands().size()==2);
    return static_cast<expr_equalityt &>(expr);
  }
  
  inline exprt &lhs()
  {
    return op0();
  }

  inline const exprt &lhs() const
  {
    return op0();
  }

  inline exprt &rhs()
  {
    return op1();
  }

  inline const exprt &rhs() const
  {
    return op1();
  }
};

#endif
