///|
pub fn render_function_local_accesses(
  report : FunctionLocalAccessesReport,
  top : Int,
) -> String {
  let out = StringBuilder()
  out.write_string(
    "FUNCTION LOCAL ACCESS ENCODINGS\n\nTarget: #\{report.target.index} " +
    search_terminal_string(report.target.name) +
    " (local)\nInput: \{report.file_size} B; SHA-256 \{report.sha256}\n",
  )
  for
    (label, range) in [
      ("Entry", report.entry),
      ("Prefix", report.prefix),
      ("Body", report.body),
      ("Locals encoding", report.locals_encoding),
    ] {
    out.write_string(
      "\{label}: file offset \{range.file_offset}, size \{range.size} B\n",
    )
  }
  out.write_string(
    "Encoded bytes: \{report.entry.size} = prefix \{report.prefix.size} + body \{report.body.size}\nBody bytes: \{report.body.size} = locals \{report.locals_encoding.size} + instructions \{report.instruction_bytes}\n",
  )
  out.write_string(
    "Instructions: \{report.instruction_count}\nAccesses: \{report.access_count} = get \{report.get_count} + set \{report.set_count} + tee \{report.tee_count}\nDistinct local indices: \{report.distinct_local_index_count}\nInstruction bytes: \{report.instruction_bytes} = access encodings \{report.access_encoding_bytes} + other instructions \{report.other_instruction_bytes}\nAccess encoding bytes: \{report.access_encoding_bytes} = opcode bytes \{report.access_count} + index encoding bytes \{report.index_encoding_bytes}\n",
  )
  let group_shown = top.max(0).min(report.groups.length())
  out.write_string(
    "\nGROUPS: showing \{group_shown} of \{report.groups.length()} (numeric local index order)\nLOCAL INDEX  ACCESS  GET  SET  TEE  ENCODED B  INDEX B  INSTRUCTION ORDINALS\n",
  )
  if report.accesses.is_empty() {
    out.write_string(
      "No local.get/local.set/local.tee access instructions in this local function. This does not imply no variables.\n",
    )
  }
  for i in 0.. String {
  let root : Map[String, Json] = Map([])
  root.set("format", Json::string("moonsize-function-local-accesses"))
  root.set("schema_version", int_json(1))
  root.set("file_size", int_json(report.file_size))
  root.set("sha256", Json::string(report.sha256))
  root.set("target", path_node_json(report.target))
  for
    (label, range) in [
      ("entry", report.entry),
      ("prefix", report.prefix),
      ("body", report.body),
      ("locals_encoding", report.locals_encoding),
    ] {
    root.set(label, function_instruction_range_json(range))
  }
  for
    (label, count) in [
      ("instruction_count", report.instruction_count),
      ("instruction_bytes", report.instruction_bytes),
      ("access_count", report.access_count),
      ("get_count", report.get_count),
      ("set_count", report.set_count),
      ("tee_count", report.tee_count),
      ("distinct_local_index_count", report.distinct_local_index_count),
      ("access_encoding_bytes", report.access_encoding_bytes),
      ("index_encoding_bytes", report.index_encoding_bytes),
      ("other_instruction_bytes", report.other_instruction_bytes),
    ] {
    root.set(label, int_json(count))
  }
  root.set(
    "accesses",
    Json::array(
      report.accesses.map(fn(access) {
        let row : Map[String, Json] = Map([])
        row.set("instruction_ordinal", int_json(access.instruction_ordinal))
        row.set("opcode", Json::string(access.opcode.name()))
        row.set("local_index", int_json(access.local_index))
        row.set("file_offset", int_json(access.file_offset))
        row.set("body_relative_offset", int_json(access.body_relative_offset))
        row.set("encoded_size", int_json(access.encoded_size))
        row.set(
          "index_encoding",
          function_instruction_range_json(access.index_encoding),
        )
        Json::object(row)
      }),
    ),
  )
  root.set(
    "groups",
    Json::array(
      report.groups.map(fn(group) {
        let row : Map[String, Json] = Map([])
        row.set("local_index", int_json(group.local_index))
        row.set("access_count", int_json(group.access_count))
        row.set("get_count", int_json(group.get_count))
        row.set("set_count", int_json(group.set_count))
        row.set("tee_count", int_json(group.tee_count))
        row.set("encoded_bytes", int_json(group.encoded_bytes))
        row.set("index_encoding_bytes", int_json(group.index_encoding_bytes))
        row.set(
          "instruction_ordinals",
          Json::array(group.instruction_ordinals.map(int_json)),
        )
        Json::object(row)
      }),
    ),
  )
  root.set("scope", Json::string(report.scope))
  Json::object(root).stringify(indent=2) + "\n"
}