///|
fn escape_moonbit_string(s : String) -> String {
  let buf = StringBuilder::new()
  buf.write_char('"')
  for c in s {
    match c {
      '\\' => buf.write_string("\\\\")
      '"' => buf.write_string("\\\"")
      '\n' => buf.write_string("\\n")
      '\r' => buf.write_string("\\r")
      '\t' => buf.write_string("\\t")
      _ => buf.write_char(c)
    }
  }
  buf.write_char('"')
  buf.to_string()
}

///|
priv struct CodeWriter {
  lines : Array[String]
  mut current_line : StringBuilder
  mut indent_level : Int
  indent_str : String?
}

///|
fn CodeWriter::new(indent : String?) -> CodeWriter {
  {
    lines: [],
    current_line: StringBuilder::new(),
    indent_level: 0,
    indent_str: indent,
  }
}

///|
fn CodeWriter::write(self : CodeWriter, s : String) -> Unit {
  self.current_line.write_string(s)
}

///|
fn CodeWriter::write_indent(self : CodeWriter) -> Unit {
  match self.indent_str {
    Some(indent) =>
      for _ in 0.. ()
  }
}

///|
fn CodeWriter::newline(self : CodeWriter) -> Unit {
  match self.indent_str {
    Some(_) => {
      self.lines.push(self.current_line.to_string())
      self.current_line = StringBuilder::new()
    }
    None => self.write(" ")
  }
}

///|
fn CodeWriter::indent(self : CodeWriter) -> Unit {
  self.indent_level += 1
}

///|
fn CodeWriter::dedent(self : CodeWriter) -> Unit {
  self.indent_level -= 1
}

///|
fn CodeWriter::to_string(self : CodeWriter) -> String {
  let all = StringBuilder::new()
  for line in self.lines {
    all.write_string(line)
    match self.indent_str {
      Some(_) => all.write_char('\n')
      None => ()
    }
  }
  let last = self.current_line.to_string()
  if last.length() > 0 {
    all.write_string(last)
  }
  all.to_string()
}