///|
fn format_regular(tag : LanguageTag) -> String {
  let parts : Array[String] = []
  parts.push(tag.language)
  let mut i = 0
  while i < tag.extlang.length() {
    parts.push(tag.extlang[i])
    i += 1
  }
  if tag.script.length() > 0 {
    parts.push(tag.script)
  }
  if tag.region.length() > 0 {
    parts.push(tag.region)
  }
  i = 0
  while i < tag.variants.length() {
    parts.push(tag.variants[i])
    i += 1
  }
  i = 0
  while i < tag.extensions.length() {
    parts.push(tag.extensions[i].singleton)
    let mut j = 0
    while j < tag.extensions[i].parts.length() {
      parts.push(tag.extensions[i].parts[j])
      j += 1
    }
    i += 1
  }
  if tag.private_use.length() > 0 {
    parts.push("x")
    i = 0
    while i < tag.private_use.length() {
      parts.push(tag.private_use[i])
      i += 1
    }
  }
  join_dash(parts)
}

///|
/// Format a parsed tag using BCP 47 recommended capitalization.
pub fn format(tag : LanguageTag) -> String {
  match tag.kind {
    Grandfathered => tag.grandfathered
    PrivateUse => "x-" + join_dash(tag.private_use)
    Regular => format_regular(tag)
  }
}

///|
pub fn Diagnostic::format(self : Diagnostic) -> String {
  let severity = match self.severity {
    Error => "error"
    Warning => "warning"
  }
  "\{self.span.line}:\{self.span.column}: \{severity} \{self.code}: \{self.message}"
}