///|
// Sequence cursors retain O(depth) work, including for wide instruction lists.
priv enum ControlEncodeWork {
  ControlInstruction(Instruction)
  ControlSequence(Array[Instruction], Int)
  ControlCatches(Array[@lib.LegacyCatch], Int)
  ControlDelegate(@lib.LabelIdx)
  ControlByte(Byte)
}

///|
fn encode_control_work(
  work : Array[ControlEncodeWork],
  buf : @buffer.Buffer,
  work_items? : Array[Int]? = None,
) -> Result[Unit, BinaryEncodeError] {
  while work.pop() is Some(task) {
    match work_items {
      Some(count) => count[0] += 1
      None => ()
    }
    match task {
      ControlByte(value) => buf.write_byte(value)
      ControlDelegate(label) => {
        buf.write_byte(0x18)
        if Encode::encode(label, buf) is Err(err) {
          return Err(err)
        }
      }
      ControlSequence(values, index) => {
        let mut cursor = index
        while cursor < values.length() {
          let instruction = values[cursor]
          match instruction {
            Block(_, _)
            | Loop(_, _)
            | If(_, _, _)
            | Try(_, _, _, _)
            | TryTable(_, _, _) => {
              if cursor + 1 < values.length() {
                work.push(ControlSequence(values, cursor + 1))
              }
              work.push(ControlInstruction(instruction))
              break
            }
            _ =>
              if encode_leaf_instruction_error(instruction, buf) is Some(err) {
                return Err(err)
              }
          }
          cursor += 1
        }
      }
      ControlCatches(values, index) =>
        if index < values.length() {
          if index + 1 < values.length() {
            work.push(ControlCatches(values, index + 1))
          }
          match values[index] {
            @lib.LegacyCatch(tag, @lib.Expr(body)) => {
              buf.write_byte(0x07)
              if Encode::encode(tag, buf) is Err(err) {
                return Err(err)
              }
              work.push(ControlSequence(body, 0))
            }
            @lib.LegacyCatchAll(@lib.Expr(body)) => {
              buf.write_byte(0x19)
              work.push(ControlSequence(body, 0))
            }
          }
        }
      ControlInstruction(instruction) =>
        match instruction {
          Block(bt, @lib.Expr(body)) | Loop(bt, @lib.Expr(body)) => {
            buf.write_byte(if instruction is Block(_, _) { 0x02 } else { 0x03 })
            if Encode::encode(bt, buf) is Err(err) {
              return Err(err)
            }
            work.push(ControlByte(0x0B))
            work.push(ControlSequence(body, 0))
          }
          If(bt, then_body, else_body) => {
            buf.write_byte(0x04)
            if Encode::encode(bt, buf) is Err(err) {
              return Err(err)
            }
            work.push(ControlByte(0x0B))
            if else_body is Some(body) {
              work.push(ControlSequence(body, 0))
              work.push(ControlByte(0x05))
            }
            work.push(ControlSequence(then_body, 0))
          }
          Try(bt, @lib.Expr(body), catches, delegate) => {
            if (catches.is_empty() && delegate is None) ||
              (!catches.is_empty() && delegate is Some(_)) {
              return Err(BinaryEncodeError::InvalidLegacyTryShape)
            }
            buf.write_byte(0x06)
            if Encode::encode(bt, buf) is Err(err) {
              return Err(err)
            }
            match delegate {
              Some(label) => work.push(ControlDelegate(label))
              None => {
                work.push(ControlByte(0x0B))
                work.push(ControlCatches(catches, 0))
              }
            }
            work.push(ControlSequence(body, 0))
          }
          TryTable(bt, catches, @lib.Expr(body)) => {
            buf.write_byte(0x1F)
            if Encode::encode(bt, buf) is Err(err) {
              return Err(err)
            }
            if Encode::encode(catches, buf) is Err(err) {
              return Err(err)
            }
            work.push(ControlByte(0x0B))
            work.push(ControlSequence(body, 0))
          }
          _ =>
            if encode_leaf_instruction_error(instruction, buf) is Some(err) {
              return Err(err)
            }
        }
    }
  }
  Ok(())
}