type
 Alternative_Seq*[T] = object
  length*: int
, capacity*: int
  data*: ptr UncheckedArray[T]

proc `=destroy`*[T](x: Alternative_Seq[T]) =
  if x.data != nil:
    for i in 0..<x.len: `=destroy`(x.data[i])
    dealloc(x.data)

proc `=trace`[T](x: var Alternative_Seq[T]; env: pointer) =
  # `=trace` allows the cycle collector `--mm:orc`
  # to understand how to trace the object graph.
  if x.data != nil:
    for i in 0..<x.len: `=trace`(x.data[i], env)

proc `=copy`*[T](a: var Alternative_Seq[T]; b: Alternative_Seq[T]) =
  # do nothing for self-assignments:
  if a.data == b.data: return
  `=destroy`(a)
  wasMoved(a)
  a.len = b.len
  a.cap = b.cap
  if b.data != nil:
    a.data = cast[typeof(a.data)](alloc(a.cap * sizeof(T)))
    for i in 0..<a.len:
      a.data[i] = b.data[i]

proc `=dup`*[T](a: Alternative_Seq[T]): Alternative_Seq[T] {.nodestroy.} =
  # an optimized version of `=wasMoved(tmp); `=copy(tmp, src)`
  # usually present if a custom `=copy` hook is overridden
  result.len = a.len
  result.cap = a.cap
  if a.data != nil:
    result.data = cast[typeof(result.data)](alloc(result.cap * sizeof(T)))
    for i in 0..<result.len:
      result.data[i] = `=dup`(a.data[i])

proc `=sink`*[T](a: var Alternative_Seq[T]; b: Alternative_Seq[T]) =
  # move assignment, optional.
  # Compiler is using `=destroy` and `copyMem` when not provided
  `=destroy`(a)
  wasMoved(a)
  a.len = b.len
  a.cap = b.cap
  a.data = b.data

proc add*[T](x: var Alternative_Seq[T]; y: sink T) =
  if x.len >= x.cap:
    x.cap = max(x.len + 1, x.cap * 2)
    x.data = cast[typeof(x.data)](realloc(x.data, x.cap * sizeof(T)))
  x.data[x.len] = y
  inc x.len

proc `[]`*[T](x: Alternative_Seq[T]; i: Natural): lent T =
  assert i < x.len
  x.data[i]

proc `[]=`*[T](x: var Alternative_Seq[T]; i: Natural; y: sink T) =
  assert i < x.len
  x.data[i] = y

proc an_alternative_seq*[T](elems: varargs[T]): Alternative_Seq[T] =
  result.cap = elems.len
  result.len = elems.len
  result.data = cast[typeof(result.data)](alloc(result.cap * sizeof(T)))
  for i in 0..<result.len: result.data[i] = elems[i]

proc len*[T](x: Alternative_Seq[T]): int {.inline.} = x.len