use std::fmt::{self, Display, Write};
use crate::{Block, Expr, Formatter};
#[derive(Debug, Clone)]
pub struct WhileLoop {
cond: Expr,
body: Block,
}
impl WhileLoop {
pub fn new(cond: &Expr) -> Self {
Self::with_guard(cond.clone())
}
pub fn with_guard(cond: Expr) -> Self {
WhileLoop { cond, body: Block::new() }
}
pub fn with_guard_and_body(cond: Expr, body: Block) -> Self {
WhileLoop { cond, body }
}
pub fn set_body(&mut self, body: Block) -> &mut Self {
self.body = body;
self
}
pub fn body(&mut self) -> &mut Block {
&mut self.body
}
pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
write!(fmt, "while (")?;
self.cond.fmt(fmt)?;
writeln!(fmt, ") ")?;
if !self.body.is_empty() {
fmt.block(|f| self.body.fmt(f))?;
writeln!(fmt)
} else {
fmt.indent(|f| writeln!(f, ";"))
}
}
}
impl Display for WhileLoop {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut ret = String::new();
self.fmt(&mut Formatter::new(&mut ret)).unwrap();
write!(f, "{ret}")
}
}
#[derive(Debug, Clone)]
pub struct DoWhileLoop {
cond: Expr,
body: Block,
}
impl DoWhileLoop {
pub fn new(cond: &Expr) -> Self {
Self::with_guard(cond.clone())
}
pub fn with_guard(cond: Expr) -> Self {
DoWhileLoop { cond, body: Block::new() }
}
pub fn with_guard_and_body(cond: Expr, body: Block) -> Self {
DoWhileLoop { cond, body }
}
pub fn set_body(&mut self, body: Block) -> &mut Self {
self.body = body;
self
}
pub fn body(&mut self) -> &mut Block {
&mut self.body
}
pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
write!(fmt, "do ")?;
fmt.block(|f| self.body.fmt(f))?;
write!(fmt, " while (")?;
self.cond.fmt(fmt)?;
writeln!(fmt, ");")
}
}
impl Display for DoWhileLoop {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut ret = String::new();
self.fmt(&mut Formatter::new(&mut ret)).unwrap();
write!(f, "{ret}")
}
}
#[derive(Debug, Clone)]
pub struct ForLoop {
init: Option<Expr>,
cond: Option<Expr>,
step: Option<Expr>,
body: Block,
}
impl ForLoop {
pub fn new() -> Self {
ForLoop {
init: None,
cond: None,
step: None,
body: Block::new(),
}
}
pub fn from_expr(init: &Expr, cond: &Expr, step: &Expr) -> Self {
Self::with_guard(init.clone(), cond.clone(), step.clone())
}
pub fn with_guard(init: Expr, cond: Expr, step: Expr) -> Self {
ForLoop {
init: Some(init),
cond: Some(cond),
step: Some(step),
body: Block::new(),
}
}
pub fn with_guard_and_body(init: Expr, cond: Expr, step: Expr, body: Block) -> Self {
ForLoop {
init: Some(init),
cond: Some(cond),
step: Some(step),
body,
}
}
pub fn set_body(&mut self, body: Block) -> &mut Self {
self.body = body;
self
}
pub fn body(&mut self) -> &mut Block {
&mut self.body
}
pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
write!(fmt, "for (")?;
if let Some(init) = &self.init {
init.fmt(fmt)?;
}
write!(fmt, "; ")?;
if let Some(cond) = &self.cond {
cond.fmt(fmt)?;
}
write!(fmt, "; ")?;
if let Some(step) = &self.step {
step.fmt(fmt)?;
}
writeln!(fmt, ") ")?;
if self.body.is_empty() {
fmt.block(|f| self.body.fmt(f))?;
writeln!(fmt)
} else {
fmt.indent(|f| writeln!(f, ";"))
}
}
}
impl Default for ForLoop {
fn default() -> Self {
Self::new()
}
}
impl Display for ForLoop {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut ret = String::new();
self.fmt(&mut Formatter::new(&mut ret)).unwrap();
write!(f, "{ret}")
}
}