use crate::ast::*; use crate::util::indent_writer::IndentWriter; use std::fmt::Debug; pub trait PrettyPrint { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()>; } impl PrettyPrint for Operator { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use Operator::*; match self { Binary(o) => o.pretty_print(writer), PrefixUnary(o) => o.pretty_print(writer), SuffixUnary(o) => o.pretty_print(writer), } } } impl PrettyPrint for BinaryOperator { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use BinaryOperator::*; match self { Or => writer.write("||"), And => writer.write("&&"), EqualTo => writer.write("=="), NotEqualTo => writer.write("!="), Greater => writer.write(">"), Less => writer.write("<"), GreaterEqual => writer.write(">="), LessEqual => writer.write("<="), Add => writer.write("+"), Subtract => writer.write("-"), Multiply => writer.write("*"), Divide => writer.write("/"), Modulo => writer.write("%"), LeftShift => writer.write("<<"), RightShift => writer.write(">>"), } } } impl PrettyPrint for PrefixUnaryOperator { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use PrefixUnaryOperator::*; match self { Spread => writer.write("..."), BorrowMut => writer.write("&mut"), Borrow => writer.write("&"), Mut => writer.write("mut"), Not => writer.write("!"), Negative => writer.write("-"), } } } impl PrettyPrint for SuffixUnaryOperator { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use SuffixUnaryOperator::*; match self { PlusPlus => writer.write("++"), MinusMinus => writer.write("--"), } } } impl PrettyPrint for Identifier { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!("Identifier({})", self.name)) } } impl PrettyPrint for FullyQualifiedName { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("FullyQualifiedName")?; writer.increase_indent(); for identifier in &self.identifiers { identifier.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for TypeUse { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use TypeUse::*; match self { Void => { writer.writeln_indented("TypeUse(Void)")?; } InterfaceOrClass(t) => { writer.increase_indent(); t.pretty_print(writer)?; writer.decrease_indent(); } Tuple(t) => { writer.increase_indent(); t.pretty_print(writer)?; writer.decrease_indent(); } Function(t) => { writer.increase_indent(); t.pretty_print(writer)?; writer.decrease_indent(); } } Ok(()) } } impl PrettyPrint for InterfaceOrClassTypeUse { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "InterfaceOrClassTypeUse(borrow_count = {}, is_mutable = {})", self.borrow_count, self.is_mutable ))?; writer.increase_indent(); self.fqn.pretty_print(writer)?; self.generics.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for TupleTypeUse { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "TupleTypeUse(borrow_count = {}, is_mutable = {})", self.borrow_count, self.is_mutable ))?; writer.increase_indent(); self.arguments.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for FunctionTypeUse { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "FunctionTypeUse(borrow_count = {})", self.borrow_count ))?; writer.increase_indent(); if let Some(function_type_modifier) = &self.function_modifier { function_type_modifier.pretty_print(writer)?; } self.generics.pretty_print(writer)?; self.parameters.pretty_print(writer)?; self.return_type.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for GenericArguments { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("GenericArguments")?; writer.increase_indent(); for type_use in &self.0 { type_use.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for GenericParameters { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("GenericParameters")?; writer.increase_indent(); for identifier in &self.0 { identifier.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for TupleArguments { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("TupleArguments")?; writer.increase_indent(); for type_use in &self.0 { type_use.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ImplementsList { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("ImplementsList")?; writer.increase_indent(); for type_use in &self.0 { type_use.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for FunctionTypeModifier { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use FunctionTypeModifier::*; writer.writeln_indented(&format!( "FunctionTypeModifier({})", match self { Cons => "cons", MutRef => "mut ref", Mut => "mut", Ref => "ref", } )) } } impl PrettyPrint for Parameters { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("Parameters")?; writer.increase_indent(); for parameter in &self.0 { parameter.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for Parameter { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("Parameter")?; writer.increase_indent(); self.identifier.pretty_print(writer)?; self.type_use.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ReturnType { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("ReturnType")?; writer.increase_indent(); self.declared_type.pretty_print(writer)?; self.references.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for References { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("References")?; writer.increase_indent(); for identifier in &self.0 { identifier.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for CompilationUnit { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("CompilationUnit")?; writer.increase_indent(); if let Some(namespace) = &self.namespace { writer.writeln_indented("Namespace")?; writer.increase_indent(); namespace.pretty_print(writer)?; writer.decrease_indent(); } for declaration in &self.declarations { declaration.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ModuleLevelDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use ModuleLevelDeclaration::*; match self { Module(module) => module.pretty_print(writer), Interface(interface) => interface.pretty_print(writer), Class(class) => class.pretty_print(writer), Function(function) => function.pretty_print(writer), PlatformFunction(platform_function) => platform_function.pretty_print(writer), } } } impl PrettyPrint for InterfaceLevelDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use InterfaceLevelDeclaration::*; match self { Module(module) => module.pretty_print(writer), Interface(interface) => interface.pretty_print(writer), Class(class) => class.pretty_print(writer), Function(function) => function.pretty_print(writer), OperatorFunction(operator_function) => operator_function.pretty_print(writer), } } } impl PrettyPrint for ClassLevelDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use ClassLevelDeclaration::*; match self { Module(module) => module.pretty_print(writer), Interface(interface) => interface.pretty_print(writer), Class(class) => class.pretty_print(writer), Function(function) => function.pretty_print(writer), OperatorFunction(operator_function) => operator_function.pretty_print(writer), PlatformFunction(platform_function) => platform_function.pretty_print(writer), Property(property) => property.pretty_print(writer), Field(field) => field.pretty_print(writer), } } } impl PrettyPrint for ModuleDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "ModuleDeclaration(is_public = {})", self.is_public ))?; writer.increase_indent(); self.identifier.pretty_print(writer)?; for declaration in &self.declarations { declaration.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for InterfaceDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "InterfaceDeclaration(is_public = {})", self.is_public ))?; writer.increase_indent(); self.identifier.pretty_print(writer)?; self.generics.pretty_print(writer)?; self.implements.pretty_print(writer)?; for declaration in &self.declarations { declaration.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ClassDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!("ClassDeclaration(is_public = {})", self.is_public))?; writer.increase_indent(); self.identifier.pretty_print(writer)?; self.generics.pretty_print(writer)?; if let Some(class_constructor) = &self.class_constructor { class_constructor.pretty_print(writer)?; } self.implements.pretty_print(writer)?; for declaration in &self.declarations { declaration.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for FunctionDefinition { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "FunctionDefinition(is_public = {})", self.is_public ))?; writer.increase_indent(); if let Some(modifier) = &self.modifier { modifier.pretty_print(writer)?; } self.generics.pretty_print(writer)?; self.identifier.pretty_print(writer)?; self.parameters.pretty_print(writer)?; self.return_type.pretty_print(writer)?; self.body.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for OperatorFunctionDefinition { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "OperatorFunctionDefinition(is_public = {})", self.is_public ))?; writer.increase_indent(); if let Some(modifier) = &self.modifier { modifier.pretty_print(writer)?; } self.generics.pretty_print(writer)?; self.operator.pretty_print(writer)?; self.parameters.pretty_print(writer)?; self.return_type.pretty_print(writer)?; self.body.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for PlatformFunctionDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "PlatformFunctionDeclaration(is_public = {})", self.is_public ))?; writer.increase_indent(); if let Some(modifier) = &self.modifier { modifier.pretty_print(writer)?; } self.generics.pretty_print(writer)?; self.identifier.pretty_print(writer)?; self.parameters.pretty_print(writer)?; self.return_type.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for InterfaceFunctionDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("InterfaceFunctionDeclaration")?; writer.increase_indent(); if let Some(modifier) = &self.modifier { modifier.pretty_print(writer)?; } self.generics.pretty_print(writer)?; self.identifier.pretty_print(writer)?; self.parameters.pretty_print(writer)?; self.return_type.pretty_print(writer)?; if let Some(body) = &self.body { body.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for InterfaceOperatorFunctionDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("InterfaceOperatorFunctionDeclaration")?; writer.increase_indent(); if let Some(modifier) = &self.modifier { modifier.pretty_print(writer)?; } self.generics.pretty_print(writer)?; self.operator.pretty_print(writer)?; self.parameters.pretty_print(writer)?; self.return_type.pretty_print(writer)?; if let Some(body) = &self.body { body.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for FunctionModifier { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use FunctionModifier::*; writer.writeln_indented(&format!( "FunctionModifier({})", match self { Static => "static", Cons => "cons", Mut => "mut", Ref => "ref", MutRef => "mut ref", } )) } } impl PrettyPrint for FunctionBody { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use FunctionBody::*; match self { Equals(expression) => { writer.writeln_indented("EqualsFunctionBody")?; writer.increase_indent(); expression.pretty_print(writer)?; writer.decrease_indent(); } Block(block_statement) => { writer.writeln_indented("BlockFunctionBody")?; writer.increase_indent(); block_statement.pretty_print(writer)?; writer.decrease_indent(); } Alias(identifier) => { writer.writeln_indented("AliasFunctionBody")?; writer.increase_indent(); identifier.pretty_print(writer)?; writer.decrease_indent(); } } Ok(()) } } impl PrettyPrint for ClassConstructor { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("ClassConstructor")?; writer.increase_indent(); for constructor_parameter in &self.0 { constructor_parameter.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ClassConstructorParameter { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use ClassConstructorParameter::*; match self { Property(property) => { writer.writeln_indented("PropertyConstructorParameter")?; writer.increase_indent(); property.pretty_print(writer)?; writer.decrease_indent(); } Field(field) => { writer.writeln_indented("FieldConstructorParameter")?; writer.increase_indent(); field.pretty_print(writer)?; writer.decrease_indent(); } } Ok(()) } } impl PrettyPrint for PropertyDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "PropertyDeclaration(is_mutable = {})", self.is_mutable ))?; writer.increase_indent(); self.identifier.pretty_print(writer)?; self.declared_type.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for FieldDeclaration { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "FieldDeclaration(is_mutable = {})", self.is_mutable ))?; writer.increase_indent(); self.identifier.pretty_print(writer)?; self.declared_type.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for BlockStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("BlockStatement")?; writer.increase_indent(); for statement in &self.statements { statement.pretty_print(writer)?; } if let Some(expression) = &self.expression { expression.pretty_print(writer)?; } Ok(()) } } impl PrettyPrint for Statement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use Statement::*; match self { BlockStatement(block_statement) => block_statement.pretty_print(writer), VariableDeclarationStatement(s) => s.pretty_print(writer), AssignStatement(s) => s.pretty_print(writer), CallStatement(s) => s.pretty_print(writer), ReturnStatement(s) => s.pretty_print(writer), IfStatement(s) => s.pretty_print(writer), IfElseStatement(s) => s.pretty_print(writer), WhileStatement(s) => s.pretty_print(writer), ForStatement(s) => s.pretty_print(writer), } } } impl PrettyPrint for VariableDeclarationStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented(&format!( "VariableDeclarationStatement(is_mutable = {})", self.is_mutable ))?; writer.increase_indent(); self.identifier.pretty_print(writer)?; if let Some(declared_type) = &self.declared_type { declared_type.pretty_print(writer)?; } if let Some(initializer) = &self.initializer { initializer.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for AssignStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("AssignStatement")?; writer.increase_indent(); self.lhs.pretty_print(writer)?; self.rhs.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for CallStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("CallStatement")?; writer.increase_indent(); self.0.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ReturnStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("ReturnStatement")?; if let Some(expression) = &self.0 { writer.increase_indent(); expression.pretty_print(writer)?; writer.decrease_indent(); } Ok(()) } } impl PrettyPrint for IfStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("IfStatement")?; writer.increase_indent(); self.condition.pretty_print(writer)?; self.then_block.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for IfElseStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("IfElseStatement")?; writer.increase_indent(); self.condition.pretty_print(writer)?; self.then_block.pretty_print(writer)?; for else_if in &self.else_ifs.0 { else_if.condition.pretty_print(writer)?; else_if.then_block.pretty_print(writer)?; } self.else_block.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for WhileStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("WhileStatement")?; writer.increase_indent(); self.condition.pretty_print(writer)?; self.body.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ForStatement { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("ForStatement")?; writer.increase_indent(); self.variable.pretty_print(writer)?; self.iterator.pretty_print(writer)?; self.body.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for Expression { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use Expression::*; match self { Ternary(e) => e.pretty_print(writer), Binary(e) => e.pretty_print(writer), UnaryPrefix(e) => e.pretty_print(writer), UnarySuffix(e) => e.pretty_print(writer), Call(e) => e.pretty_print(writer), ObjectAccess(o) => o.pretty_print(writer), Literal(literial) => literial.pretty_print(writer), FullyQualifiedName(fqn) => fqn.pretty_print(writer), Closure(closure) => closure.pretty_print(writer), } } } impl PrettyPrint for TernaryExpression { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("TernaryExpression")?; writer.increase_indent(); self.condition.pretty_print(writer)?; self.true_expression.pretty_print(writer)?; self.false_expression.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for BinaryExpression { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("BinaryExpression")?; writer.increase_indent(); self.left.pretty_print(writer)?; self.operator.pretty_print(writer)?; self.right.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for PrefixExpression { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("PrefixExpression")?; writer.increase_indent(); self.operator.pretty_print(writer)?; self.expression.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for SuffixExpression { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("SuffixExpression")?; writer.increase_indent(); self.expression.pretty_print(writer)?; self.operator.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for CallExpression { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("CallExpression")?; writer.increase_indent(); self.callee.pretty_print(writer)?; if let Some(turbo_fish) = &self.turbo_fish { turbo_fish.pretty_print(writer)?; } self.arguments.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for TurboFish { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("TurboFish")?; writer.increase_indent(); self.0.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for CallArguments { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("CallArguments")?; writer.increase_indent(); for call_argument in &self.0 { call_argument.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for CallArgument { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("CallArgument")?; writer.increase_indent(); self.0.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for Closure { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { todo!() } } impl PrettyPrint for ObjectAccess { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("ObjectAccess")?; writer.increase_indent(); self.receiver.pretty_print(writer)?; self.navigations.pretty_print(writer)?; writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ObjectNavigations { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("ObjectNavigations")?; writer.increase_indent(); for object_navigation in &self.0 { object_navigation.pretty_print(writer)?; } writer.decrease_indent(); Ok(()) } } impl PrettyPrint for ObjectNavigation { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use ObjectNavigation::*; match self { Index(e) => { writer.writeln_indented("Index")?; writer.increase_indent(); e.pretty_print(writer)?; writer.decrease_indent(); } Identifier(identifier) => { writer.writeln_indented("Property")?; writer.increase_indent(); identifier.pretty_print(writer)?; writer.decrease_indent(); } } Ok(()) } } impl PrettyPrint for Literal { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { use Literal::*; match self { Integer(i) => writer.writeln_indented(&format!("Integer({})", i)), Long(l) => writer.writeln_indented(&format!("Long({})", l)), Double(d) => writer.writeln_indented(&format!("Double({})", d)), USize(u) => writer.writeln_indented(&format!("USize({})", u)), String(s) => writer.writeln_indented(&format!("String({})", s)), DString(d_string) => d_string.pretty_print(writer), BacktickString(d_string) => d_string.pretty_print(writer), Boolean(b) => writer.writeln_indented(&format!("Boolean({})", b)), } } } impl PrettyPrint for DString { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("DString")?; writer.increase_indent(); for part in &self.0 { part.pretty_print(writer)?; } Ok(()) } } impl PrettyPrint for DStringPart { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { writer.writeln_indented("DStringPart")?; writer.increase_indent(); match self { DStringPart::String(s) => writer.writeln_indented(&format!("String({})", s)), DStringPart::Expression(e) => e.pretty_print(writer), } } }