// Descrptors.h -- operand descriptors for Delayed Code Generation	-*- C++ -*-
// 
// Author: Ian.Piumarta@INRIA.Fr
//
// Last edited: Thu Dec 23 03:29:40 1999 by piumarta (Ian Piumarta) on aria


class Descriptor
{
public:
  int type;
  int value;
  int flags;
  enum flags {
    tagged= 0x01
  };
public:
  Descriptor(void) : type(0), value(0), flags(0) {}
  Descriptor(int t, int v) : type(t), value(v), flags(0) {}

public:  
  char *printString(void) const;

  inline bool isStack(void) const;
  inline bool isInteger(void) const;
  inline bool isRegister(void) const;
  inline bool isCondition(void) const;

  inline bool isTrue(void) const;
  inline bool isFalse(void) const;

  inline void beStack(void);

  inline Descriptor &beTagged(void)
    {
      flags|= tagged;
      return *this;
    }

  inline bool isTagged(void) const
    {
      return (flags & tagged);
    }
};



class Stack : public Descriptor
{
public:
  static const int Type= 1;
public:
  Stack(void) : Descriptor(Type, 0) {}
};


inline void Descriptor::beStack(void)
{
  type= Stack::Type;
  value= 0;
}


inline bool Descriptor::isStack(void) const
{
  return type == Stack::Type;
}


class Integer : public Descriptor
{
public:
  static const int Type= 2;
public:
  Integer(int val) : Descriptor(Type, val) {}
};


inline bool Descriptor::isInteger(void) const
{
  return type == Integer::Type;
}


class Register : public Descriptor
{
public:
  static const int Type= 3;
public:
  Register(int val) : Descriptor(Type, val) {}
};


inline bool Descriptor::isRegister(void) const
{
  return type == Register::Type;
}


class Condition : public Descriptor
{
public:
  static const int Type= 4;
public:
  // the following is inexcusable, but ANSI refuses to let me initialise
  // the array as a static const member.  hurrah for standardisation.
  static inline const char *name(int i)
    {
      static char *cc[]= {"t","lt","le","eq","ne","gt","ge","f" };
      return cc[i - TR];
    };
  enum ccode		 { TR, LT,  LE,  EQ,  NE,  GT,  GE,  FA };
  static Condition	   Tr, Lt,  Le,  Eq,  Ne,  Gt,  Ge,  Fa;
public:
  Condition(ccode val) : Descriptor(Type, val) {}
  inline Condition inverted(void);
  inline static ccode inverted(const ccode cc)
    {
      return (ccode)(TR + FA - cc);
    }
};


inline bool Descriptor::isCondition(void) const
{
  return type == Condition::Type;
}


inline bool Descriptor::isTrue(void) const
{
  return (type == Condition::Type) && (value == Condition::TR);
}


inline bool Descriptor::isFalse(void) const
{
  return (type == Condition::Type) && (value == Condition::FA);
}


inline Condition Condition::inverted(void)
{
  return Condition(Condition::inverted((ccode)value));
}


Condition Condition::Tr(Condition::TR);
Condition Condition::Lt(Condition::LT);
Condition Condition::Le(Condition::LE);
Condition Condition::Eq(Condition::EQ);
Condition Condition::Ne(Condition::NE);
Condition Condition::Gt(Condition::GT);
Condition Condition::Ge(Condition::GE);
Condition Condition::Fa(Condition::FA);


char *Descriptor::printString(void) const
{
  static char bufs[4][32];
  static int bidx= 0;
  char *buf= bufs[bidx++ % 4], *ptr= buf;
  switch (type)
    {
    case Stack::Type:
      ptr+= sprintf(ptr, "Stack");
      break;
    case Integer::Type:
      ptr+= sprintf(ptr, "Integer(%d)", value);
      break;
    case Register::Type:
      ptr+= sprintf(ptr, "Register(%d)", value);
      break;
    case Condition::Type:
      ptr+= sprintf(ptr, "Condition(%s)", Condition::name(value));
      break;
    default:
      fatal("this cannot happen");
      break;
    }
  if (flags)
    {
      ptr+= sprintf(ptr, "[%s]", (isTagged() ? "t" : ""));
    }
  return buf;
}

