///|
pub trait SyntaxPrinter {
  print(Self, StringBuilder) -> Unit
}

///|
/// Public implementations of Printer trait for all @syntax types
/// These implementations delegate to the existing print_XX functions
pub impl SyntaxPrinter for @syntax.Constant with print(self, logger) {
  print_constant(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Label with print(self, logger) {
  print_label(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Binder with print(self, logger) {
  print_binder(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Var with print(self, logger) {
  print_var(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.LongIdent with print(self, logger) {
  print_long_ident(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.TypeName with print(self, logger) {
  print_type_name(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.ConstrName with print(self, logger) {
  print_constr_name(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Constructor with print(self, logger) {
  print_constructor(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.TypeVarBinder with print(self, logger) {
  print_type_var_binder(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.TypeVarConstraint with print(self, logger) {
  print_type_var_constraint(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Visibility with print(self, logger) {
  print_visibility(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.ErrorType with print(self, logger) {
  print_error_type(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Type with print(self, logger) {
  print_type(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.ArrayPattern with print(self, logger) {
  print_array_pattern(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.ArrayPatterns with print(self, logger) {
  print_array_patterns(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.ConstrPatArg with print(self, logger) {
  print_constr_pat_arg(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.FieldPat with print(self, logger) {
  print_record_field_pat(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.MapPatElem with print(self, logger) {
  print_map_pat_elem(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Pattern with print(self, logger) {
  print_pattern(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Impl with print(self, logger) {
  print_impl(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Func with print(self, logger) {
  print_func(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Expr with print(self, logger) {
  print_expr(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Parameter with print(self, logger) {
  print_parameter(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.FunDecl with print(self, logger) {
  print_fun_decl(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.DeclBody with print(self, logger) {
  print_decl_body(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.TypeDecl with print(self, logger) {
  print_type_decl(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.ArgumentKind with print(self, logger) {
  match self {
    Positional => logger.write_string("positional")
    Labelled(label) => {
      print_label(label, logger)
      logger.write_string("~")
    }
    LabelledPun(label) => {
      print_label(label, logger)
      logger.write_string("~")
    }
    LabelledOption(label~, ..) => {
      print_label(label, logger)
      logger.write_string("?")
    }
    LabelledOptionPun(label~, ..) => {
      print_label(label, logger)
      logger.write_string("?")
    }
  }
}

///|
pub impl SyntaxPrinter for @syntax.Argument with print(self, logger) {
  print_argument(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.SpreadableElem with print(self, logger) {
  print_spreadable_elem(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.FieldDef with print(self, logger) {
  print_field_def(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.Accessor with print(self, logger) {
  print_accessor(self, logger)
}

///|
pub impl SyntaxPrinter for @syntax.DotDotBinder with print(self, logger) {
  print_dot_dot_binder(self, logger)
}

///|
/// Additional implementations for types that don't have dedicated print functions yet
/// These use simple fallback implementations
pub impl SyntaxPrinter for @syntax.ConstrId with print(self, logger) {
  print_long_ident(self.id, logger)
}

///|
/// Convenience function to convert any Printer-implementing type to string
pub fn[T : SyntaxPrinter] to_string(value : T) -> String {
  let logger : StringBuilder = StringBuilder::new()
  SyntaxPrinter::print(value, logger)
  logger.to_string()
}

///|
pub fnalias SyntaxPrinter::print