#ifndef ICI_ARRAY_H
#define ICI_ARRAY_H

/*
 * array.h - ICI array objects.
 */

#ifndef ICI_OBJECT_H
#include "object.h"
#endif

/*
 * The following portion of this file exports to ici.h. --ici.h-start--
 */
/*
 * The ICI array object. Array objects are implemented in a manner to
 * make them efficient to use as stacks. And they are used that way in the
 * execution engine. A single contiguous array of object pointers is
 * associated with the array. a_base points to its start, a_limit one
 * past its end and a_top somewhere in the middle. The stretch from a_base
 * to just less than a_top is the current contents of the array.
 */
struct array
{
    object_t    o_head;
    object_t    **a_top;    /* The next free slot. */
    object_t    **a_base;   /* The base of the array. */
    object_t    **a_limit;  /* Allocation limit, first one you can't use. */
};
#define arrayof(o)  ((array_t *)(o))
#define isarray(o)  ((o)->o_tcode == TC_ARRAY)

/*
 * Check that there are at least n elements on the end of array a. Sets error
 * on failure and return non-zero.
 */
#define popcheck(a, n)  ((a)->a_top - (a)->a_base < (n) ? ici_badindex() : 0)

/*
 * Check that there is room for n new elements on the end of a.  May reallocate
 * array memory to get more room. Return non-zero on failure, usual conventions.
 */
#define pushcheck(a, n) ((a)->a_limit-(a)->a_top < (n) ? ici_growarray((a),(n)) : 0)

/*
 * Ensure that the array a has i as a valid index.  Will grow and NULL fill
 * as necessary. Return non-zero on failure, usual conventions.
 */
#define arrayprobe(a, i) ((i) < 0 \
                || (a)->a_top-(a)->a_base <= (i) \
                || (objof(a)->o_flags & O_ATOM) \
                ? ici_faultarray((a), (i)) \
                : 0)

/*
 * End of ici.h export. --ici.h-end--
 */
#endif
