#include "Rts.h"   

#define Node         1 
#define Cycle        2 
#define Thunk        3 
#define Char         4 
#define Int          5 
#define SmallInteger 6 
#define LargeInteger 7 
#define Float        8 
#define Double       9 
#define Exception    10 
#define Async        11 
#define Fun          12 
#define Unknown      13

#define app2(A, B) rts_apply((A),(B))
#define app3(A, B, C) rts_apply(rts_apply((A),(B)),(C))
#define app4(A, B, C, D) rts_apply(rts_apply(rts_apply((A),(B)),(C)),(D))
#define app5(A, B, C, D, E) rts_apply(rts_apply(rts_apply(rts_apply((A),(B)),(C)),(D)),(E))
#define app6(A, B, C, D, E, F) rts_apply(rts_apply(rts_apply(rts_apply(rts_apply((A),(B)),(C)),(D)),(E)),(F))


typedef struct _graphNode GraphNode; 
typedef union  _val Val;
typedef char Tag;

union _val
{
   char         character;
   int          machineInt;
   float        machineFloat;
   char *       descriptor;
   StgStablePtr largeIntegerSPtr;
   double       machineDouble;
};

struct _graphNode
{
   StgWord   unique;          /* unique value for this node */
   Val       val;             /* value at this node */
   Tag       tag;             /* node type  */
   short int numChildren;     /* the number of children, 16 bits should be plenty */
   GraphNode **children;      /* children arcs, zero or more */
};

typedef struct _listNode List; 

struct _listNode
{
   StgWord val;
   List *next;
};

typedef enum {False=0, True=1} Bool;

GraphNode *makeGraphNode (StgWord unique, Tag tag, char *descriptor, int numChildren);
void freeGraph (GraphNode *node);

List *cons (StgWord val, List *l);
List *freeListNode (List *l);

Bool isIOC (StgStablePtr objPtr);
Bool isThunkC (StgStablePtr objPtr);
Bool isExceptionC (StgStablePtr objPtr);
void reEvalC (StgStablePtr runApply, StgStablePtr old, StgStablePtr new);
GraphNode *makeHeapGraph (StgStablePtr obj);

StgStablePtr reifyC ( StgStablePtr ptrObj
                    , StgStablePtr ptrAppNode
                    , StgStablePtr ptrCharNode
                    , StgStablePtr ptrIntNode
                    , StgStablePtr ptrIntegerNode
                    , StgStablePtr ptrFloatNode
                    , StgStablePtr ptrDoubleNode
                    , StgStablePtr ptrNullNode
                    , StgStablePtr ptrNil
                    , StgStablePtr ptrCons );

StgClosure* removeIndirections (StgClosure* p);

HaskellObj followMutVar (HaskellObj);
