Improve Debug and Display implementations
This commit is contained in:
		
							parent
							
								
									49df6c9ed9
								
							
						
					
					
						commit
						d5daaa0e87
					
				| @ -44,7 +44,7 @@ pub struct InstructionHolder { | ||||
|     pub(crate) data: InstructionData, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| #[derive(Clone)] | ||||
| pub struct Builder { | ||||
|     modules: Rc<RefCell<Vec<ModuleHolder>>>, | ||||
| } | ||||
|  | ||||
| @ -1,11 +1,17 @@ | ||||
| use std::fmt::Debug; | ||||
| use std::fmt::{Debug, Write}; | ||||
| 
 | ||||
| use crate::{CmpPredicate, InstructionData, InstructionKind, TerminatorKind, builder::*}; | ||||
| 
 | ||||
| impl Debug for Builder { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_list().entries(self.get_modules().borrow().iter()); | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ModuleHolder { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_tuple(&format!("Module({})", self.data.name)) | ||||
|             .field(&self.value) | ||||
|         f.debug_tuple(&format!("{}({:#?}) ", self.data.name, self.value)) | ||||
|             .field(&self.functions) | ||||
|             .finish() | ||||
|     } | ||||
| @ -14,7 +20,7 @@ impl Debug for ModuleHolder { | ||||
| impl Debug for FunctionHolder { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_tuple(&format!( | ||||
|             "{}({:?}) -> {:?}", | ||||
|             "{}({:?}) -> {:?} ", | ||||
|             self.data.name, self.data.params, self.data.ret | ||||
|         )) | ||||
|         .field(&self.blocks) | ||||
| @ -24,8 +30,7 @@ impl Debug for FunctionHolder { | ||||
| 
 | ||||
| impl Debug for BlockHolder { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_tuple(&format!("Block({})", self.data.name)) | ||||
|             .field(&self.value) | ||||
|         f.debug_tuple(&format!("{}[{:?}]", &self.data.name, &self.value)) | ||||
|             .field(&self.instructions) | ||||
|             .field(&self.data.terminator) | ||||
|             .finish() | ||||
| @ -34,7 +39,9 @@ impl Debug for BlockHolder { | ||||
| 
 | ||||
| impl Debug for InstructionHolder { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "{:?} = {:?}", &self.value, &self.data) | ||||
|         self.value.fmt(f)?; | ||||
|         f.write_str(" = ")?; | ||||
|         self.data.fmt(f) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -46,19 +53,19 @@ impl Debug for InstructionData { | ||||
| 
 | ||||
| impl Debug for ModuleValue { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "M[{}]", &self.0) | ||||
|         write!(f, "M[{:0>2}]", self.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for FunctionValue { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "F[{}, {}]", &self.0.0, &self.1,) | ||||
|         write!(f, "F[{:0>2}-{:0>2}]", &self.0.0, self.1) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for BlockValue { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "B[{}, {}, {}]", &self.0.0.0, &self.0.1, self.1) | ||||
|         write!(f, "B[{:0>2}-{:0>2}-{:0>2}]", &self.0.0.0, &self.0.1, self.1) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -66,7 +73,7 @@ impl Debug for InstructionValue { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!( | ||||
|             f, | ||||
|             "I<{}-{}-{}-{}>", | ||||
|             "I[{:0>2}-{:0>2}-{:0>2}-{:0>2}]", | ||||
|             &self.0.0.0.0, &self.0.0.1, &self.0.1, self.1 | ||||
|         ) | ||||
|     } | ||||
| @ -75,17 +82,41 @@ impl Debug for InstructionValue { | ||||
| impl Debug for InstructionKind { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::Param(nth) => write!(f, "Param({})", &nth), | ||||
|             Self::Constant(c) => write!(f, "{:?}", &c), | ||||
|             Self::Add(lhs, rhs) => write!(f, "{:?} + {:?}", &lhs, &rhs), | ||||
|             Self::Sub(lhs, rhs) => write!(f, "{:?} + {:?}", &lhs, &rhs), | ||||
|             Self::Phi(val) => write!(f, "Phi: {:?}", &val), | ||||
|             Self::ICmp(cmp, lhs, rhs) => write!(f, "{:?} {:?} {:?}", &lhs, &cmp, &rhs), | ||||
|             Self::FunctionCall(fun, params) => write!(f, "{:?}({:?})", &fun, ¶ms), | ||||
|             Self::Param(nth) => fmt_call(f, &"Param", &nth), | ||||
|             Self::Constant(c) => c.fmt(f), | ||||
|             Self::Add(lhs, rhs) => fmt_binop(f, lhs, &"+", rhs), | ||||
|             Self::Sub(lhs, rhs) => fmt_binop(f, lhs, &"-", rhs), | ||||
|             Self::Phi(val) => fmt_call(f, &"Phi", &val), | ||||
|             Self::ICmp(cmp, lhs, rhs) => fmt_binop(f, lhs, cmp, rhs), | ||||
|             Self::FunctionCall(fun, params) => fmt_call(f, fun, params), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn fmt_binop( | ||||
|     f: &mut std::fmt::Formatter<'_>, | ||||
|     lhs: &impl std::fmt::Debug, | ||||
|     op: &impl std::fmt::Debug, | ||||
|     rhs: &impl std::fmt::Debug, | ||||
| ) -> std::fmt::Result { | ||||
|     lhs.fmt(f)?; | ||||
|     f.write_char(' ')?; | ||||
|     op.fmt(f)?; | ||||
|     f.write_char(' ')?; | ||||
|     rhs.fmt(f) | ||||
| } | ||||
| 
 | ||||
| fn fmt_call( | ||||
|     f: &mut std::fmt::Formatter<'_>, | ||||
|     fun: &impl std::fmt::Debug, | ||||
|     params: &impl std::fmt::Debug, | ||||
| ) -> std::fmt::Result { | ||||
|     fun.fmt(f)?; | ||||
|     f.write_char('(')?; | ||||
|     params.fmt(f)?; | ||||
|     f.write_char(')') | ||||
| } | ||||
| 
 | ||||
| impl Debug for CmpPredicate { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
| @ -102,9 +133,23 @@ impl Debug for CmpPredicate { | ||||
| impl Debug for TerminatorKind { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::Ret(val) => write!(f, "Ret {:?}", &val), | ||||
|             Self::Branch(val) => write!(f, "Br {:?}", &val), | ||||
|             Self::CondBr(cond, b1, b2) => write!(f, "CondBr {:?} ? {:?} : {:?}", &cond, &b1, &b2), | ||||
|             Self::Ret(val) => { | ||||
|                 write!(f, "Ret ")?; | ||||
|                 val.fmt(f) | ||||
|             } | ||||
|             Self::Branch(val) => { | ||||
|                 write!(f, "Br ")?; | ||||
|                 val.fmt(f) | ||||
|             } | ||||
|             Self::CondBr(cond, b1, b2) => { | ||||
|                 write!(f, "CondBr ")?; | ||||
|                 cond.fmt(f)?; | ||||
|                 write!(f, " ? ")?; | ||||
|                 b1.fmt(f)?; | ||||
|                 write!(f, " : ")?; | ||||
|                 b2.fmt(f)?; | ||||
|                 Ok(()) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -91,7 +91,7 @@ pub struct IfExpression( | ||||
| pub struct LetStatement(pub String, pub Option<Type>, pub Expression, pub TokenRange); | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct ImportStatement(Vec<String>, pub TokenRange); | ||||
| pub struct ImportStatement(pub Vec<String>, pub TokenRange); | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct FunctionDefinition(pub FunctionSignature, pub Block, pub TokenRange); | ||||
|  | ||||
| @ -7,6 +7,7 @@ mod ast; | ||||
| mod codegen; | ||||
| mod lexer; | ||||
| pub mod mir; | ||||
| mod pad_adapter; | ||||
| mod token_stream; | ||||
| mod util; | ||||
| 
 | ||||
| @ -39,7 +40,6 @@ pub fn compile(source: &str) -> Result<String, ReidError> { | ||||
| 
 | ||||
|     while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) { | ||||
|         let statement = token_stream.parse::<TopLevelStatement>()?; | ||||
|         dbg!(&statement); | ||||
|         statements.push(statement); | ||||
|     } | ||||
| 
 | ||||
| @ -51,17 +51,15 @@ pub fn compile(source: &str) -> Result<String, ReidError> { | ||||
|     dbg!(&ast_module); | ||||
|     let mut mir_context = mir::Context::from(vec![ast_module]); | ||||
| 
 | ||||
|     dbg!(&mir_context); | ||||
| 
 | ||||
|     let state = mir_context.pass(&mut TypeCheck {}); | ||||
|     dbg!(&mir_context); | ||||
|     dbg!(&state); | ||||
| 
 | ||||
|     println!("{}", &mir_context); | ||||
| 
 | ||||
|     if !state.errors.is_empty() { | ||||
|         return Err(ReidError::TypeCheckErrors(state.errors)); | ||||
|     } | ||||
| 
 | ||||
|     dbg!(&mir_context); | ||||
| 
 | ||||
|     let mut context = Context::new(); | ||||
|     let codegen_modules = mir_context.codegen(&mut context); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										200
									
								
								reid/src/mir/display.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								reid/src/mir/display.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,200 @@ | ||||
| use std::fmt::{write, Debug, Display, Write}; | ||||
| 
 | ||||
| use crate::pad_adapter::PadAdapter; | ||||
| 
 | ||||
| use super::*; | ||||
| 
 | ||||
| impl Display for Context { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         for module in &self.modules { | ||||
|             Display::fmt(&module, f)?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for Module { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         writeln!(f, "Module({}) {{", self.name)?; | ||||
| 
 | ||||
|         let mut state = Default::default(); | ||||
|         let mut inner_f = PadAdapter::wrap(f, &mut state); | ||||
| 
 | ||||
|         for import in &self.imports { | ||||
|             writeln!(inner_f, "{}", import)?; | ||||
|         } | ||||
|         for fun in &self.functions { | ||||
|             writeln!(inner_f, "{}", fun)?; | ||||
|         } | ||||
|         writeln!(f, "}}") | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for Import { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "import {}", self.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for FunctionDefinition { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!( | ||||
|             f, | ||||
|             "fn {}({}) -> {} ", | ||||
|             self.name, | ||||
|             self.parameters | ||||
|                 .iter() | ||||
|                 .map(|(n, t)| format!("{}: {}", n, t)) | ||||
|                 .collect::<Vec<_>>() | ||||
|                 .join(", "), | ||||
|             self.return_type | ||||
|         )?; | ||||
|         Display::fmt(&self.kind, f) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for FunctionDefinitionKind { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::Local(block, _) => { | ||||
|                 write!(f, "{}", block)?; | ||||
|                 Ok(()) | ||||
|             } | ||||
|             Self::Extern => write!(f, "<External>"), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for Block { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         writeln!(f, "{{")?; | ||||
|         let mut state = Default::default(); | ||||
|         let mut inner_f = PadAdapter::wrap(f, &mut state); | ||||
|         for statement in &self.statements { | ||||
|             write!(inner_f, "{}", statement)?; | ||||
|         } | ||||
|         if let Some(ret) = &self.return_expression { | ||||
|             match ret.0 { | ||||
|                 ReturnKind::Hard => writeln!(inner_f, "Return(Hard): {}", ret.1), | ||||
|                 ReturnKind::Soft => writeln!(inner_f, "Return(Hard): {}", ret.1), | ||||
|             }?; | ||||
|         } else { | ||||
|             writeln!(inner_f, "No Return")?; | ||||
|         } | ||||
|         writeln!(f, "}}") | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for Statement { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         writeln!(f, "{}", self.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for StmtKind { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::Let(var, block) => write!(f, "let {} = {}", var, block), | ||||
|             Self::Import(n) => write!(f, "import {}", n), | ||||
|             Self::Expression(exp) => Display::fmt(exp, f), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for Expression { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         Display::fmt(&self.0, f) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for ExprKind { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::Variable(var) => Display::fmt(var, f), | ||||
|             Self::Literal(lit) => Display::fmt(lit, f), | ||||
|             Self::BinOp(op, lhs, rhs) => write!(f, "{} {} {}", lhs, op, rhs), | ||||
|             Self::FunctionCall(fc) => Display::fmt(fc, f), | ||||
|             Self::If(if_exp) => Display::fmt(&if_exp, f), | ||||
|             Self::Block(block) => Display::fmt(block, f), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for IfExpression { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "if {} ", self.0)?; | ||||
|         Display::fmt(&self.1, f)?; | ||||
|         if let Some(e) = &self.2 { | ||||
|             Display::fmt(&e, f)?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for FunctionCall { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "{}<{}>(", self.name, self.return_type)?; | ||||
|         for (i, param) in self.parameters.iter().enumerate() { | ||||
|             Display::fmt(param, f)?; | ||||
|             if i < (self.parameters.len() - 1) { | ||||
|                 write!(f, ", ")?; | ||||
|             } | ||||
|         } | ||||
|         write!(f, ")") | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for VariableReference { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "v(\"{}\", {})", &self.1, &self.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for Literal { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::I8(val) => write!(f, "{}i8", val), | ||||
|             Self::I16(val) => write!(f, "{}i16", val), | ||||
|             Self::I32(val) => write!(f, "{}i32", val), | ||||
|             Self::I64(val) => write!(f, "{}i64", val), | ||||
|             Self::I128(val) => write!(f, "{}i128", val), | ||||
|             Self::U8(val) => write!(f, "{}u8", val), | ||||
|             Self::U16(val) => write!(f, "{}u16", val), | ||||
|             Self::U32(val) => write!(f, "{}u32", val), | ||||
|             Self::U64(val) => write!(f, "{}u64", val), | ||||
|             Self::U128(val) => write!(f, "{}u128", val), | ||||
|             Self::Vague(val) => val.fmt(f), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for BinaryOperator { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             BinaryOperator::Add => write!(f, "+"), | ||||
|             BinaryOperator::Minus => write!(f, "-"), | ||||
|             BinaryOperator::Mult => write!(f, "*"), | ||||
|             BinaryOperator::And => write!(f, "&&"), | ||||
|             BinaryOperator::Logic(op) => Display::fmt(op, f), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for LogicOperator { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             LogicOperator::LT => write!(f, "<"), | ||||
|             LogicOperator::LE => write!(f, "<="), | ||||
|             LogicOperator::GT => write!(f, ">"), | ||||
|             LogicOperator::GE => write!(f, ">="), | ||||
|             LogicOperator::EQ => write!(f, "=="), | ||||
|             LogicOperator::NE => write!(f, "!="), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for Metadata { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "{:?}", self.range) | ||||
|     } | ||||
| } | ||||
| @ -3,21 +3,16 @@ | ||||
| /// type-checked beforehand.
 | ||||
| use crate::token_stream::TokenRange; | ||||
| 
 | ||||
| mod display; | ||||
| pub mod pass; | ||||
| pub mod typecheck; | ||||
| pub mod types; | ||||
| 
 | ||||
| #[derive(Default, Debug, Clone, Copy)] | ||||
| #[derive(Debug, Default, Clone, Copy)] | ||||
| pub struct Metadata { | ||||
|     pub range: TokenRange, | ||||
| } | ||||
| 
 | ||||
| impl std::fmt::Display for Metadata { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "{:?}", self.range) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl std::ops::Add for Metadata { | ||||
|     type Output = Metadata; | ||||
| 
 | ||||
|  | ||||
| @ -141,8 +141,6 @@ impl Expression { | ||||
|     ) -> Result<TypeKind, ErrorKind> { | ||||
|         match &mut self.0 { | ||||
|             ExprKind::Variable(var_ref) => { | ||||
|                 dbg!(&state.scope); | ||||
| 
 | ||||
|                 let existing = state.or_else( | ||||
|                     state | ||||
|                         .scope | ||||
|  | ||||
							
								
								
									
										72
									
								
								reid/src/pad_adapter.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								reid/src/pad_adapter.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| // Copyright (c) The Rust Project Contributors
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any
 | ||||
| // person obtaining a copy of this software and associated
 | ||||
| // documentation files (the "Software"), to deal in the
 | ||||
| // Software without restriction, including without
 | ||||
| // limitation the rights to use, copy, modify, merge,
 | ||||
| // publish, distribute, sublicense, and/or sell copies of
 | ||||
| // the Software, and to permit persons to whom the Software
 | ||||
| // is furnished to do so, subject to the following
 | ||||
| // conditions:
 | ||||
| //
 | ||||
| // The above copyright notice and this permission notice
 | ||||
| // shall be included in all copies or substantial portions
 | ||||
| // of the Software.
 | ||||
| //
 | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
 | ||||
| // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 | ||||
| // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 | ||||
| // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 | ||||
| // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | ||||
| // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | ||||
| // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 | ||||
| // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | ||||
| // DEALINGS IN THE SOFTWARE.
 | ||||
| 
 | ||||
| use std::fmt; | ||||
| 
 | ||||
| pub struct PadAdapter<'buf, 'state> { | ||||
|     buf: &'buf mut (dyn fmt::Write + 'buf), | ||||
|     state: &'state mut PadAdapterState, | ||||
| } | ||||
| 
 | ||||
| pub struct PadAdapterState { | ||||
|     on_newline: bool, | ||||
| } | ||||
| 
 | ||||
| impl Default for PadAdapterState { | ||||
|     fn default() -> Self { | ||||
|         PadAdapterState { on_newline: true } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'buf, 'state> PadAdapter<'buf, 'state> { | ||||
|     pub fn wrap<'slot, 'fmt: 'buf + 'slot>( | ||||
|         fmt: &'fmt mut fmt::Formatter<'_>, | ||||
|         state: &'state mut PadAdapterState, | ||||
|     ) -> Self { | ||||
|         PadAdapter { buf: fmt, state } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Write for PadAdapter<'_, '_> { | ||||
|     fn write_str(&mut self, s: &str) -> fmt::Result { | ||||
|         for s in s.split_inclusive('\n') { | ||||
|             if self.state.on_newline { | ||||
|                 self.buf.write_str("    ")?; | ||||
|             } | ||||
|             self.state.on_newline = s.ends_with('\n'); | ||||
|             self.buf.write_str(s)?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     fn write_char(&mut self, c: char) -> fmt::Result { | ||||
|         if self.state.on_newline { | ||||
|             self.buf.write_str("    ")?; | ||||
|         } | ||||
|         self.state.on_newline = c == '\n'; | ||||
|         self.buf.write_char(c) | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user