///|
/// Parsing for component instance and alias sections (sections 5 and 6).

///|
pub(all) struct InstantiateArg {
  name : String
  sortidx : SortIdx
} derive(Debug, Eq)

///|
pub(all) struct InlineExport {
  name : String
  attributes : Array[NameAttribute]
  sortidx : SortIdx
} derive(Debug, Eq)

///|
pub(all) enum InstanceExpr {
  Instantiate(Int, Array[InstantiateArg])
  InlineExports(Array[InlineExport])
} derive(Debug, Eq)

///|
pub impl Show for InstanceExpr with fn output(self, logger) {
  logger.write_string(@types.compact_show_repr(Repr(self).to_string()))
}

///|
pub(all) struct Instance {
  expr : InstanceExpr
} derive(Debug, Eq)

///|
fn parse_inlineexport(
  reader : Reader,
) -> InlineExport raise ComponentParseError {
  // Inline exports use the same nameattributes encoding as component exports.
  let tag = reader.read_u8()
  let (name, attributes) = if tag == 0x00 {
    let len = reader.read_leb_u32()
    let bytes = reader.read_bytes(len)
    (decode_utf8_validated(bytes), [])
  } else if tag == 0x01 {
    let len = reader.read_leb_u32()
    let bytes = reader.read_bytes(len)
    (decode_utf8_validated(bytes), [])
  } else if tag == 0x02 {
    let len = reader.read_leb_u32()
    let bytes = reader.read_bytes(len)
    (decode_utf8_validated(bytes), parse_attributes(reader))
  } else {
    raise InvalidInstanceSection
  }
  let sortidx = parse_sortidx(reader)
  { name, attributes, sortidx, }
}

///|
fn parse_instantiatearg(
  reader : Reader,
) -> InstantiateArg raise ComponentParseError {
  let name = reader.read_name()
  let sortidx = parse_sortidx(reader)
  { name, sortidx, }
}

///|
fn parse_instanceexpr(
  reader : Reader,
) -> InstanceExpr raise ComponentParseError {
  let tag = reader.read_u8()
  if tag == 0x00 {
    let component_idx = reader.read_leb_u32()
    let n = reader.read_leb_u32()
    let args : Array[InstantiateArg] = []
    for _ in 0.. Array[Instance] raise ComponentParseError {
  let reader = Reader::Reader(payload)
  let n = reader.read_leb_u32()
  let instances : Array[Instance] = []
  for _ in 0.. AliasTarget raise ComponentParseError {
  let tag = reader.read_u8()
  if tag == 0x00 {
    let instance_idx = reader.read_leb_u32()
    let name = reader.read_name()
    Export(instance_idx, name)
  } else if tag == 0x01 {
    let core_instance_idx = reader.read_leb_u32()
    let name = reader.read_name()
    CoreExport(core_instance_idx, name)
  } else if tag == 0x02 {
    let ct = reader.read_leb_u32()
    let idx = reader.read_leb_u32()
    Outer(ct, idx)
  } else {
    raise InvalidAliasSection
  }
}

///|
fn parse_alias(reader : Reader) -> Alias raise ComponentParseError {
  let sort = parse_sort(reader)
  let target = parse_aliastarget(reader)
  { sort, target, }
}

///|
pub fn parse_alias_section(
  payload : Bytes,
) -> Array[Alias] raise ComponentParseError {
  let reader = Reader::Reader(payload)
  let n = reader.read_leb_u32()
  let aliases : Array[Alias] = []
  for _ in 0..