///|
/// Independent format; all families and instances survive text Top limits.
pub fn render_generic_instances_json(report : GenericInstancesReport) -> String {
  let root : Map[String, Json] = Map([])
  root.set("format", Json::string("moonsize-generic-instances"))
  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("name_status", Json::string(report.name_status))
  root.set("recognition_scope", Json::string(report.recognition_scope))
  let c = report.coverage
  let coverage : Map[String, Json] = Map([])
  coverage.set("total_functions", int_json(c.total_functions))
  coverage.set("total_size", int_json(c.total_size))
  coverage.set("grouped_functions", int_json(c.grouped_functions))
  coverage.set("grouped_size", int_json(c.grouped_size))
  coverage.set(
    "named_ungrouped_functions",
    int_json(c.named_ungrouped_functions),
  )
  coverage.set("named_ungrouped_size", int_json(c.named_ungrouped_size))
  coverage.set("unnamed_functions", int_json(c.unnamed_functions))
  coverage.set("unnamed_size", int_json(c.unnamed_size))
  root.set("coverage", Json::object(coverage))
  root.set(
    "families",
    Json::array(
      report.families.map(fn(family) {
        let row : Map[String, Json] = Map([])
        row.set("family_key", Json::string(family.family_key))
        row.set("display_name", Json::string(family.display_name))
        row.set("definition_count", int_json(family.definition_count))
        row.set("type_encoding_count", int_json(family.type_encoding_count))
        row.set("total_size", int_json(family.total_size))
        row.set(
          "instances",
          Json::array(
            family.instances.map(fn(instance) {
              let item : Map[String, Json] = Map([])
              item.set("index", int_json(instance.index))
              item.set("raw_name", Json::string(instance.raw_name))
              item.set(
                "raw_type_arguments",
                Json::string(instance.raw_type_arguments),
              )
              item.set(
                "type_labels",
                Json::array(instance.type_labels.map(Json::string)),
              )
              item.set("total_size", int_json(instance.total_size))
              Json::object(item)
            }),
          ),
        )
        Json::object(row)
      }),
    ),
  )
  Json::object(root).stringify(indent=2) + "\n"
}

///|
pub fn render_generic_instances(
  report : GenericInstancesReport,
  top : Int,
) -> String {
  let out = StringBuilder()
  let shown = top.max(0).min(report.families.length())
  let c = report.coverage
  out.write_string("MOONBIT GENERIC INSTANCES\n\n")
  out.write_string(
    "Input: \{report.file_size} bytes; SHA-256 \{report.sha256}\n",
  )
  out.write_string("Name information: \{report.name_status}\n")
  if report.name_status == "unreadable" {
    out.write_string(
      "Name information could not be read completely; no names are trusted for grouping.\n",
    )
  } else if report.name_status == "missing" {
    out.write_string(
      "No name section is present; grouping requires usable raw symbols.\n",
    )
  }
  out.write_string(
    "\nCOVERAGE LEDGER (local function definitions / encoded bytes)\n",
  )
  out.write_string("All: \{c.total_functions} / \{c.total_size} B\n")
  out.write_string(
    "Grouped generic: \{c.grouped_functions} / \{c.grouped_size} B\n",
  )
  out.write_string(
    "Named, ungrouped: \{c.named_ungrouped_functions} / \{c.named_ungrouped_size} B\n",
  )
  out.write_string(
    "Without usable names: \{c.unnamed_functions} / \{c.unnamed_size} B\n",
  )
  out.write_string(
    "All = grouped generic + named ungrouped + without usable names.\n",
  )
  out.write_string(
    "\nShowing \{shown} of \{report.families.length()} families; Top limits text only.\n",
  )
  if report.families.is_empty() {
    out.write_string(
      "No instances recognized within the supported encoding scope; this does not establish that the project has no generics.\n",
    )
  }
  for i in 0..