#ifndef NEWTYPE_H
#define NEWTYPE_H

#define HasAType(v, T) ((v).type==(T) \
  || ((v).type==PtrT && MemGetType(v.addr) == (struct Type*)(T)))

#ifndef __GNUC__
extern struct Any MAKE_ANY(void *, struct Type *);
#else
#define MAKE_ANY(addr,type) ((struct Any){type, addr})
#endif
#define Object_TO_Any(ob) MAKE_ANY(ob, (struct Type*)&Root_classDesc)
#define DefaultPrefix PostfixApply
/*extern struct Any DefaultPrefix(struct Any, struct Any);*/
#ifndef _TAKES
#define _TAKES(params) params
#endif
#if 0
extern struct Any DefaultPostfix _TAKES((struct Any, struct Any));
extern struct Any DefaultNamefix _TAKES((struct Any, Name, struct Any));
extern struct Any DefaultLastfix _TAKES((struct Any));
extern struct Any PrefixApply _TAKES((struct Any, struct Any));
extern struct Any PostfixApply _TAKES((struct Any, struct Any));
extern struct Any LastfixApply _TAKES((struct Any));
#endif

#define FIELD_FIRST_INCLUDED(fld) ((int)(fld)->name)
#define Field1_CD_offset(cd) FIELD_FIRST_INCLUDED((cd)->fields)
#define FOR_EACH_FIELD(fld, desc) \
    for (fld = (desc)->fields; fld != NULL; fld = fld->next())

#define Constant_Field 1
#define Method_Field 2
#define Pointer_Field 3
#define Struct_Field 4
#define Include_Field 5
#define Bit_Field 6

enum Privacy { IsPublic, IsProtected, IsPrivate, IsLastField};
#if 0
class FieldPrivacy {
    Field *fld;
  public:
    FieldPrivacy(Field* f) { fld = f; }
    operator enum Privacy();
    operator= (enum Privacy priv);
};
FieldPrivacy::operator enum Privacy() { return fld->_privacy; }
FieldPrivacy::operator= (enum Privacy priv) { fld->_privacy = priv; }
#endif
enum Indirection { IsConst, IsField, IsIndirect};

struct Field {
   Symbol *name; /* or perhaps: Name name; */
   struct Type *type;
   union {
       void *value;
       int offset;
#if 0
       struct { /* Used for virtual methods etc */
	   int offset1 : 12; /* location of virtual table */
	   int offset2 : 20; /* offset in virtual table */
       } indirected;
#endif
       struct { short size; char is_signed; } b;
       struct Function *func;
       struct { short first, last; } h;
   } u;
   enum Privacy _privacy: 2;
   enum Indirection indirection : 2;
   unsigned int bit_offset : 3;
   unsigned kind: 3;
   int flags : 22;
#ifdef __cplusplus
   inline int ival() const { return (int)u.value; }
   inline int offset1() const { return ival() >> 20; }
   inline int offset2() const { return (ival() << 12) >> 12; }
   inline enum Privacy privacy() const { return (enum Privacy)_privacy; }
   inline void setPrivacy(enum Privacy priv) { _privacy = priv; }
   inline int isLastField() const { return _privacy == IsLastField; }
   inline int isPrivate() { return privacy() > IsPublic; }
   inline void setPrivate(int mode) { _privacy = IsPrivate; }
   inline struct Type * & ftype() { return type; }
   inline Symbol * fname() { return name; }
//   inline struct Field *fnext() { return this + _next; }
   Root *coerceToRoot(void *base) const;
   inline void *faddr() const { return u.value;}
   inline Field *fchain() const { return (Field*)u.value;}
   inline Field *next() const {
       const Field *n = this+1;
       if (n->isLastField()) return n->fchain(); else return (Field*)n;
   }
   inline Field **fchain_ptr() { return (Field**)&u.value;}
   inline void set_fchain(Field *chain) {
       _privacy = IsLastField; *fchain_ptr() = (Field*)chain; }
   inline void set_const(void *addr) {
       indirection = IsConst; kind = Constant_Field; u.value = addr; }
   inline void set_value(Root *addr) {
       set_const((void*)addr); type = &RefRoot; }
   inline void set_value(Any val) {
     set_const(val.addr); type = val.type; }
   inline int is_const() { return kind == Constant_Field; }
   inline void *get_const() { return u.value; }
   inline void set_proc(Function *func) {
       indirection = IsConst; kind = Method_Field; u.func = func; }
   inline int is_proc() { return kind == Method_Field; }
   inline Function *get_proc() { return u.func; }
   inline void set_pointer_field(int offset, Type *typ) {
       indirection = IsField;
       type = typ;
       u.offset = offset;
       kind = Pointer_Field;
   }
   inline void set_struct_field(int offset, Type *typ) {
       indirection = IsField;
       type = typ;
       u.offset = offset;
       kind = Struct_Field;
   }
   inline int get_offset() const { return u.offset; }
   struct Any extract(void *base) const;
   Root * extractObject(void *base) const
       { return extract(base).coerceToRoot(); }
   const Root * extractObject(const void *base) const
       { return (const Root*)extract((void*)base).coerceToRoot(); }
#endif
};

/* what about bitfield enums ??? */
#if 0
kind=Constant_Field:
  Name; addr; type or SELF_DESCRIBING; visibility

kind=Method_Field
  Name; function

kind=Field_Field
  Name; offset; type; visibility

kind=Pointer_Field
  Name; offset; type or SELF_DESCRIBING; visibility

kind=Include_Field
  Name; offset; type; visibility; index of first child


kind=Bit_Field
  Name; type (pointer or integer or enum?); bit-size; offset,bit-offset
]type

MUST FIX  uses of type->hash:
extract.c
init (FuncSearch, and calls on it)
optimize.c
typeio.c
apply.c (Lookup{1,2})
genops.c: _Compare
#endif
#endif /* NEWTYPE_H */
