use crate::ir::*;
use crate::module::functions::{Function, FunctionKind, ImportedFunction, LocalFunction};
use id_arena::Id;
use std::mem;
pub trait DisplayIr {
type Context;
fn display_ir(&self, f: &mut String, ctx: &Self::Context, indent: usize);
}
impl DisplayIr for Function {
type Context = ();
fn display_ir(&self, f: &mut String, _: &(), indent: usize) {
assert_eq!(indent, 0);
match self.kind {
FunctionKind::Import(ref i) => i.display_ir(f, &(), indent),
FunctionKind::Local(ref l) => l.display_ir(f, &(), indent),
FunctionKind::Uninitialized(_) => unreachable!(),
}
}
}
impl DisplayIr for ImportedFunction {
type Context = ();
fn display_ir(&self, f: &mut String, _: &(), indent: usize) {
assert_eq!(indent, 0);
f.push_str("(import func)");
}
}
impl DisplayIr for LocalFunction {
type Context = ();
fn display_ir(&self, f: &mut String, _: &(), indent: usize) {
assert_eq!(indent, 0);
let mut visitor = DisplayExpr {
func: self,
f,
indent,
first_arg: false,
line: 0,
};
visitor.f.push_str(" (func\n");
self.entry_block().visit(&mut visitor);
visitor.f.push_str(" )");
}
}
pub(crate) struct DisplayExpr<'a, 'b> {
pub(crate) func: &'a LocalFunction,
pub(crate) f: &'b mut String,
indent: usize,
first_arg: bool,
line: usize,
}
impl DisplayExpr<'_, '_> {
pub(crate) fn id<T>(&mut self, id: Id<T>) {
self.f.push_str(" ");
self.f.push_str(&id.index().to_string());
}
fn line(&mut self) {
self.line += 1;
self.f.push_str("\n");
}
pub(crate) fn expr_id(&mut self, id: ExprId) {
let first_arg = mem::replace(&mut self.first_arg, true);
if first_arg {
self.line();
}
self.f.push_str("(;");
self.f.push_str(&format!("{:3}", id.index()));
self.f.push_str(";)");
self.indent += 1;
self.indent();
self.f.push_str("(");
let start = self.line;
id.visit(self);
if start != self.line {
self.f.push_str(" ");
self.indent();
}
self.indent -= 1;
self.f.push_str(")");
self.line();
self.first_arg = false;
}
fn indent(&mut self) {
self.f.push_str(" ");
for _ in 0..self.indent {
self.f.push_str(" ");
}
}
}