///|
fn Vm::slice(
  self : Vm,
  value : Value,
  start : Value,
  end : Value,
  step : Value,
  loc : Location,
) -> Value raise {
  let items = self.sequence(value, loc)
  let length = items.length().to_double()
  let mut index = match start {
    Nil => 0.0
    _ => number_value(start, loc)
  }
  if index < 0 {
    index = Double::max(0, number_value(finite(length + index, loc), loc))
  }
  let mut stop = match end {
    Nil => length
    _ => number_value(end, loc)
  }
  if stop < 0 {
    stop = number_value(finite(stop + length, loc), loc)
  }
  let stride = match step {
    Nil => 1.0
    _ => number_value(step, loc)
  }
  if stride <= 0 {
    raise problem(Assertion, loc, "slice step must be positive")
  }
  let out = []
  while index < stop && index < length {
    self.tick(loc)
    let i = array_index(Num(index), items.length(), loc)
    out.push(
      if value is ArrayValue(_) {
        self.defer_index(value, index, loc)
      } else {
        items[i]
      },
    )
    index = number_value(finite(index + stride, loc), loc)
  }
  if value is Str(_) {
    let b = StringBuilder()
    for t in out {
      b.write_string(text_value(self.force(t, loc), loc))
    }
    Str(b.to_string())
  } else {
    ArrayValue(out)
  }
}