///|
/// Validate an entire editable resource by an actual syntax round trip. Unlike
/// serialize's upstream-compatible structural renderer, this rejects invalid
/// identifier/literal spellings, unrepresentable text, Junk and lossy tree shapes.
/// Synthetic spans are ignored; returned FTL uses canonical whitespace, not the
/// original formatting. Reparse the result before using its new source positions.
pub fn serialize_checked(resource : Node) -> String raise SerializationError {
  guard resource.kind is Resource(_) else {
    raise SerializationError("Expected Resource")
  }
  let visits = match resource.walk(max_depth=128, max_nodes=100000) {
    Ok(v) => v
    Err(_) =>
      raise SerializationError("Resource exceeds validation traversal limits")
  }
  for visit in visits {
    if visit.node.kind is Junk(_, _) {
      raise SerializationError("Cannot validate a resource containing Junk")
    }
  }
  let text = serialize(resource)
  let reparsed = parse(text)
  if !resource.same_syntax(reparsed) {
    raise SerializationError(
      "Resource is not representable without syntax loss",
    )
  }
  text
}