Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Printing

This section is a work-in-progress experiment about making the book executable.

These printers turn the AST back into Rust syntax.

#![allow(unused)]
fn main() {
pub fn print_program(program: &Program) -> String {
    program.to_string() + "\n"
}

impl Display for Program {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.items.iter().format("\n\n"))
    }
}

impl Display for Function {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{} ", self.qualifiers)?;
        write!(
            f,
            "fn {}{}({})",
            self.name,
            self.generic_params,
            self.parameters.iter().format(", ")
        )?;

        if let Some(return_type) = &self.return_type {
            write!(f, " -> {return_type}")?;
        }
        write!(f, " {}", self.where_clauses)?;
        match &self.body {
            FunctionBody::Block(block) => write!(f, " {block}"),
            FunctionBody::Missing => f.write_str(";"),
        }
    }
}

impl Display for Item {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        if !self.attrs.is_empty() {
            write!(f, "{} ", self.attrs.iter().format(" "))?;
        }
        if let Some(visibility) = &self.visibility {
            write!(f, "{visibility} ")?;
        }
        write!(f, "{}", self.kind)
    }
}

impl Display for ItemKind {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            ItemKind::Function(function) => write!(f, "{function}"),
        }
    }
}

impl Display for FunctionQualifiers {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        if self.is_const {
            f.write_str("const")?;
        }
        if self.is_async {
            f.write_str(" async")?;
        }
        if let Some(safety) = &self.safety {
            write!(f, " {safety}")?;
        }
        if let Some(extern_abi) = &self.extern_abi {
            write!(f, " {extern_abi}")?;
        }
        Ok(())
    }
}

impl Display for ItemSafety {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            ItemSafety::Safe => "safe",
            ItemSafety::Unsafe => "unsafe",
        })
    }
}

impl Display for Visibility {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Visibility::Pub => f.write_str("pub"),
            Visibility::PubCrate => f.write_str("pub(crate)"),
            Visibility::PubSelf => f.write_str("pub(self)"),
            Visibility::PubSuper => f.write_str("pub(super)"),
            Visibility::InPath(path) => write!(f, "pub(in {path})"),
        }
    }
}

impl Display for Mutability {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Self::Mutable => "mut ",
            Self::Immutable => "",
        })
    }
}

impl Display for ExternAbi {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match &self.abi {
            Some(abi) => write!(f, "extern \"{abi}\""),
            None => f.write_str("extern"),
        }
    }
}

impl Display for FunctionParam {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        if !self.attrs.is_empty() {
            write!(f, "{} ", self.attrs.iter().format(" "))?;
        }
        write!(f, "{}", self.kind)
    }
}

impl Display for FunctionParamKind {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            FunctionParamKind::Regular { pattern, ty } => {
                if let Some(pattern) = pattern {
                    write!(f, "{pattern}: ")?;
                }
                write!(f, "{ty}")
            }
            FunctionParamKind::RefSelfShorthand {
                lifetime,
                mutability,
            } => {
                write!(f, "&")?;
                if let Some(lifetime) = lifetime {
                    write!(f, "{lifetime} ")?;
                }
                write!(f, "{mutability}")?;
                f.write_str("self")
            }
            FunctionParamKind::SelfParam { mutability, ty } => {
                write!(f, "{mutability}")?;
                f.write_str("self")?;
                if let Some(ty) = ty {
                    write!(f, ": {ty}")?;
                }
                Ok(())
            }
        }
    }
}

impl Display for FunctionParamType {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            FunctionParamType::Type(ty) => write!(f, "{ty}"),
            FunctionParamType::Variadic => f.write_str("..."),
        }
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Type::Unit => write!(f, "()"),
            Type::Bool => write!(f, "bool"),
            Type::Str => write!(f, "str"),
            Type::TraitSelf => write!(f, "Self"),
            Type::Ref(lifetime, mutability, ty) => {
                f.write_str("&")?;
                if let Some(lifetime) = lifetime {
                    write!(f, "{lifetime} ")?;
                }
                write!(f, "{mutability}")?;
                write!(f, "{ty}")
            }
        }
    }
}

impl Display for BlockExpression {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str("{")?;
        for statement in &self.statements {
            write!(f, " {statement}")?;
        }
        if let Some(tail) = &self.tail {
            write!(f, " {tail}")?;
        }
        f.write_str(" }")
    }
}

impl Display for Statement {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Statement::Empty => f.write_str(";"),
            Statement::Item(item) => write!(f, "{item}"),
            Statement::Let {
                attrs,
                pattern,
                ty,
                initial_value,
                else_branch,
            } => {
                write!(f, "{} ", attrs.iter().format(" "))?;
                write!(f, "let {pattern}")?;
                if let Some(ty) = ty {
                    write!(f, ": {ty}")?;
                }
                if let Some(initial_value) = initial_value {
                    write!(f, " = {initial_value}")?;
                }
                if let Some(else_branch) = else_branch {
                    write!(f, " else {else_branch}")?;
                }
                f.write_str(";")
            }
            Statement::Expr(expression) => write!(f, "{expression};"),
        }
    }
}

impl Display for Expression {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{} ", self.attrs.iter().format(" "))?;
        write!(f, "{}", self.kind)
    }
}

impl Display for ExpressionKind {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            ExpressionKind::Literal(literal) => write!(f, "{literal}"),
            ExpressionKind::Path(path) => write!(f, "{path}"),
            ExpressionKind::Operator(operator) => write!(f, "{operator}"),
            ExpressionKind::Block(block) => write!(f, "{block}"),
            ExpressionKind::Tuple(tuple) => write!(f, "{tuple}"),
            ExpressionKind::Call(call) => write!(f, "{call}"),
        }
    }
}

impl Display for LiteralExpression {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            LiteralExpression::String(value) => write!(f, "\"{value}\""),
            LiteralExpression::Integer(value) => write!(f, "{value}"),
            LiteralExpression::Bool(value) => write!(f, "{value}"),
        }
    }
}

impl Display for TupleExpression {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            TupleExpression::Unit => f.write_str("()"),
        }
    }
}

impl Display for CallExpression {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}({})", self.callee, self.args.iter().format(", "))
    }
}

impl Display for OperatorExpression {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            OperatorExpression::Add(left, right) => write!(f, "{left} + {right}"),
            OperatorExpression::Assignment(left, right) => write!(f, "{left} = {right}"),
        }
    }
}

impl Display for GenericParams {
    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

impl Display for WhereClauses {
    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

impl Display for OuterAttribute {
    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

impl Display for Lifetime {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str("'_")
    }
}

impl Display for Pattern {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Pattern::Identifier(name) => f.write_str(name),
            Pattern::Wildcard => f.write_str("_"),
        }
    }
}
}