//
// array
// Bytecode set support for arrays
// F.J. Alberti
//


case kNewarray: {
  // Pushes reference to fresh array of the specified size,
  // initialised to given value
  int size = m->top[m->pp+1];    // array size
  if (size == NIL) {
#if defined(SCOL_DEBUG)
    checkUnderflow(m)
#endif
    m->top[++m->pp] = NIL;
    break;
  }
  size >>= 1;
  if (size < 0)
    throw Exception(MERRTYP, "(!) "MSGEILLARRAYSIZE"\n", size); 
  int s = MMmalloc(m, size, TYPETAB);
  if (s == NIL)
    throw Exception(MERRMEM);

  // Initialise array with passed initial value
#if defined(SCOL_DEBUG)
  checkUnderflow(m)
#endif
  int init = m->top[m->pp++];  // initial value
  for (int i = 0; i < size; i++)
    m->tape[s+SizeHeader+i] = init;
  m->top[m->pp] = s<<1|0x00000001;
  break;
}


case kArraysize: {
  // Push array size
  int a = m->top[m->pp];       // array
  if (a == NIL) 
    break;
  // Least-significant bit contains a 1 (the type of a tuple)
  m->top[m->pp] = m->tape[a>>1]&0xfffffffe;
  break;
}


case kArrayget: {
  // Get the element of the given array at the specified index
#if defined(SCOL_DEBUG)
  checkUnderflow(m)
#endif
  int i = m->top[m->pp++];    // index
  int p = m->top[m->pp];      // array
  if (i == NIL || p == NIL) {
    m->top[m->pp] = NIL;
    break;
  }
  m->top[m->pp] = m->tape[(p>>1)+SizeHeader+(i>>1)];
  break;
}


case kArrayset: {
  // Set the element of the given array at the specified index
  // with the value at the top of the stack
#if defined(SCOL_DEBUG)
  checkUnderflow(m)
#endif
  int val = m->top[m->pp++];  // value
#if defined(SCOL_DEBUG)
  checkUnderflow(m)
#endif
  int i = m->top[m->pp++];    // index
  int p = m->top[m->pp];      // array
  if (i == NIL || p == NIL) {
    m->top[m->pp] = NIL;
    break;
  }
  m->tape[(p>>1)+SizeHeader+(i>>1)] = m->top[m->pp] = val;
  break;
}


case kArraycheck: {
  // Check if index is within the bounds of the given array.
  // Throw an exception if it's not the case
  int i = m->top[m->pp];    // index
  int p = m->top[m->pp+1];  // array
  if (i == NIL || p == NIL)
    break;
  i >>= 1;
  int size = (m->tape[p>>1]&0xfffffffe)>>1;
  if (i < 0 || i >= size)
    throw Exception(MERRTYP, "(!) "MSGEILLARRAYINDEX"\n", i, size); 
  break;
}