use std::{cell::Cell, fmt};
use super::Statement;
pub struct DisplayBracketed<T>(pub T);
impl<T: fmt::Display> fmt::Display for DisplayBracketed<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", &self.0)
}
}
pub struct DisplayList<'a, T>(pub &'a [T]);
impl<T: fmt::Display> fmt::Display for DisplayList<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", DisplayCsv::new(self.0.iter()))
}
}
#[allow(dead_code)]
pub struct DisplayParenthesized<T>(pub T);
impl<T: fmt::Display> fmt::Display for DisplayParenthesized<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({})", &self.0)
}
}
pub struct DisplayTuple<'a, T>(pub &'a [T]);
impl<T: fmt::Display> fmt::Display for DisplayTuple<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({})", DisplayCsv::new(self.0.iter()))
}
}
pub struct DisplayTypedTuple<'a, V, T>(pub &'a [(V, T)]);
impl<V: fmt::Display, T: fmt::Display> fmt::Display for DisplayTypedTuple<'_, V, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"({})",
DisplayCsv::new(self.0.iter().map(|(v, t)| format!("{v}: {t}")))
)
}
}
pub struct DisplayCsv<T>(Cell<Option<T>>);
impl<T, I> DisplayCsv<I>
where
T: fmt::Display,
I: Iterator<Item = T>,
{
pub fn new(iter: I) -> Self {
Self(Cell::new(Some(iter)))
}
}
impl<T, I> fmt::Display for DisplayCsv<I>
where
T: fmt::Display,
I: Iterator<Item = T>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let iter = self.0.take().unwrap();
for (i, item) in iter.enumerate() {
if i > 0 {
f.write_str(", ")?;
}
write!(f, "{item}")?;
}
Ok(())
}
}
pub struct DisplayStatement<'a> {
pub statement: &'a Statement,
pub indent: usize,
}
impl DisplayStatement<'_> {
const INDENT: &'static str = " ";
fn write_indent(&self, f: &mut fmt::Formatter) -> fmt::Result {
for _ in 0..self.indent {
f.write_str(Self::INDENT)?;
}
Ok(())
}
}
impl fmt::Display for DisplayStatement<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.write_indent(f)?;
match self.statement {
Statement::Let(expr) => {
let display = DisplayLet {
let_expr: expr,
indent: self.indent,
in_expr_position: false,
};
write!(f, "{display}")
}
Statement::Enforce(expr) => {
write!(f, "enf {expr}")
}
Statement::EnforceIf(expr, selector) => {
write!(f, "enf {expr} when {selector}")
}
Statement::EnforceAll(expr) => {
write!(f, "enf {expr}")
}
Statement::Expr(expr) => write!(f, "return {expr}"),
Statement::BusEnforce(expr) => write!(f, "enf {expr}"),
}
}
}
pub struct DisplayLet<'a> {
pub let_expr: &'a super::Let,
pub indent: usize,
pub in_expr_position: bool,
}
impl DisplayLet<'_> {
const INDENT: &'static str = " ";
fn write_indent(&self, f: &mut fmt::Formatter) -> fmt::Result {
for _ in 0..self.indent {
f.write_str(Self::INDENT)?;
}
Ok(())
}
}
impl fmt::Display for DisplayLet<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use core::fmt::Write;
self.write_indent(f)?;
match &self.let_expr.value {
super::Expr::Let(value) => {
writeln!(f, "let {} = {{", self.let_expr.name)?;
let display = DisplayLet {
let_expr: value,
indent: self.indent + 1,
in_expr_position: true,
};
writeln!(f, "{display}")?;
self.write_indent(f)?;
if self.in_expr_position {
f.write_str("} in {\n")?;
} else {
f.write_str("}\n")?;
}
}
value => {
write!(f, "let {} = {}", self.let_expr.name, value)?;
if self.in_expr_position {
f.write_str(" in {\n")?;
} else {
f.write_char('\n')?;
}
}
}
for stmt in self.let_expr.body.iter() {
writeln!(f, "{}", stmt.display(self.indent + 1))?;
}
if self.in_expr_position {
self.write_indent(f)?;
f.write_char('}')?;
}
Ok(())
}
}