///|
/// Main implementation functions
fn print_impl(syn : @syntax.Impl, logger : StringBuilder) -> Unit {
  match syn {
    TopExpr(expr~, is_main~, ..) => {
      if is_main {
        logger.write_string("main ")
      }
      print_expr(expr, logger)
    }
    TopTest(expr~, name~, ..) => {
      logger.write_string("test")
      match name {
        Some((test_name, _)) => {
          logger.write_string(" \"")
          logger.write_string(test_name)
          logger.write_string("\"")
        }
        None => ()
      }
      logger.write_string(" { ")
      print_expr(expr, logger)
      logger.write_string(" }")
    }
    TopLetDef(binder~, ty~, expr~, vis~, is_constant~, ..) => {
      print_visibility(vis, logger)
      if is_constant {
        logger.write_string("const ")
      } else {
        logger.write_string("let ")
      }
      print_binder(binder, logger)
      match ty {
        Some(t) => {
          logger.write_string(" : ")
          print_type(t, logger)
        }
        None => ()
      }
      logger.write_string(" = ")
      print_expr(expr, logger)
    }
    TopFuncDef(fun_decl~, decl_body~, ..) => {
      print_fun_decl(fun_decl, logger)
      logger.write_string(" ")
      print_decl_body(decl_body, logger)
    }
    TopTypeDef(type_decl) => print_type_decl(type_decl, logger)
    TopFuncAlias(pkg~, type_name~, targets~, vis~, ..) => {
      print_visibility(vis, logger)
      logger.write_string("fnalias ")
      match pkg {
        Some(pkg_label) => {
          logger.write_string("@")
          print_label(pkg_label, logger)
          logger.write_string(".")
        }
        None => ()
      }
      match type_name {
        Some(type_name) => {
          print_label(type_name, logger)
          logger.write_string("::")
        }
        None => ()
      }
      let mut first = true
      logger.write_string("(")
      for target in targets {
        if not(first) {
          logger.write_string(", ")
        }
        first = false
        match target.target {
          Some(target_label) => {
            print_label(target_label, logger)
            logger.write_string(" as ")
            print_binder(target.binder, logger)
          }
          None => print_binder(target.binder, logger)
        }
      }
      logger.write_string(")")
    }
    TopTrait(trait_decl) => {
      print_visibility(trait_decl.vis, logger)
      logger.write_string("trait ")
      print_binder(trait_decl.name, logger)
      logger.write_string(" { ")
      for trait_method in trait_decl.methods {
        print_binder(trait_method.name, logger)
        logger.write_string("(")
        print_list(
          trait_method.params,
          print_trait_method_parameter,
          ", ",
          logger,
        )
        logger.write_string(")")
        match trait_method.return_type {
          Some(ret_ty) => {
            logger.write_string(" -> ")
            print_type(ret_ty, logger)
          }
          None => ()
        }
        print_error_type(trait_method.error_type, logger)
        logger.write_string("; ")
      }
      logger.write_string("}")
    }
    TopBatchTypeAlias(pkg~, targets~, vis~, ..) => {
      print_visibility(vis, logger)
      logger.write_string("typealias ")
      let mut need_parentheses = false
      match pkg {
        Some(pkg_label) => {
          logger.write_string("@")
          print_label(pkg_label, logger)
          logger.write_string(".")
          need_parentheses = true
        }
        None => ()
      }
      let mut first = true
      if need_parentheses {
        logger.write_string("(")
      }
      // logger.write_string("(")
      for target in targets {
        if not(first) {
          logger.write_string(", ")
        }
        first = false
        match target.target {
          Some(target_label) => {
            print_label(target_label, logger)
            logger.write_string(" as ")
            print_binder(target.binder, logger)
          }
          None => print_binder(target.binder, logger)
        }
      }
      if need_parentheses {
        logger.write_string(")")
      }
      // logger.write_string(")") 
    }
    TopBatchTraitAlias(pkg~, targets~, vis~, ..) => {
      print_visibility(vis, logger)
      logger.write_string("traitalias ")
      match pkg {
        Some(pkg_label) => {
          logger.write_string("@")
          print_label(pkg_label, logger)
          logger.write_string(".")
        }
        None => ()
      }
      let mut first = true
      logger.write_string("(")
      for target in targets {
        if not(first) {
          logger.write_string(", ")
        }
        first = false
        print_binder(target.binder, logger)
        match target.target {
          Some(target_label) => {
            logger.write_string(" as ")
            print_label(target_label, logger)
          }
          None => ()
        }
      }
      logger.write_string(")")
    }
    TopImpl(
      self_ty~,
      trait_~,
      method_name~,
      has_error~,
      quantifiers~,
      params~,
      ret_ty~,
      err_ty~,
      body~,
      vis~,
      ..
    ) => {
      let _ = has_error
      print_visibility(vis, logger)
      logger.write_string("impl")

      // Print generic parameters/quantifiers
      if not(quantifiers.is_empty()) {
        logger.write_string("[")
        print_list(quantifiers, print_type_var_binder, ", ", logger)
        logger.write_string("]")
      }
      logger.write_string(" ")
      print_type_name(trait_, logger)

      // Print "for Type" if self_ty is provided
      match self_ty {
        Some(ty) => {
          logger.write_string(" for ")
          print_type(ty, logger)
        }
        None => ()
      }
      logger.write_string(" with ")
      print_binder(method_name, logger)
      logger.write_string("(")
      print_list(params, print_impl_parameter, ", ", logger)
      logger.write_string(")")
      match ret_ty {
        Some(return_type) => {
          logger.write_string(" -> ")
          print_type(return_type, logger)
        }
        None => ()
      }
      print_error_type(err_ty, logger)
      logger.write_string(" ")
      print_decl_body(body, logger)
    }
    TopView(
      source_ty~,
      view_type_name~,
      view_constrs~,
      view_func_name~,
      parameters~,
      body~,
      vis~,
      ..
    ) => {
      print_visibility(vis, logger)
      logger.write_string("view ")
      print_type(source_ty, logger)
      logger.write_string(" as ")
      logger.write_string(view_type_name)
      logger.write_string(" { ")
      for constr in view_constrs {
        logger.write_string(constr.name.name)
        logger.write_string("; ")
      }
      logger.write_string("} with ")
      print_binder(view_func_name, logger)
      logger.write_string("(")
      print_list(parameters, print_parameter, ", ", logger)
      logger.write_string(") { ")
      print_expr(body, logger)
      logger.write_string(" }")
    }
    TopImplRelation(self_ty~, trait_~, vis~, ..) => {
      print_visibility(vis, logger)
      logger.write_string("impl ")
      print_type(self_ty, logger)
      logger.write_string(" : ")
      print_type_name(trait_, logger)
    }
  }
}

///|
fn to_string_impl(syn : @syntax.Impl) -> String {
  let logger = StringBuilder::new()
  print_impl(syn, logger)
  let result = logger.to_string()
  result
}

///|
fn parse_impl(s : String) -> @syntax.Impl {
  @parser.parse_string(s).0.unsafe_head()
}