ddbug 0.5.0

Display debugging information
Documentation
use std::cmp;

use parser::{FileHash, Parameter, Type, Unit};

use crate::Result;
use crate::print::{self, DiffList, DiffState, Print, PrintState, ValuePrinter};

pub(crate) fn print_decl(p: &Parameter, w: &mut dyn ValuePrinter, hash: &FileHash) -> Result<()> {
    if let Some(name) = p.name() {
        write!(w, "{}: ", name)?;
    }
    print::types::print_ref(p.ty(hash), w, hash)?;
    Ok(())
}

fn print_size_and_decl(p: &Parameter, w: &mut dyn ValuePrinter, hash: &FileHash) -> Result<()> {
    match p.byte_size(hash) {
        Some(byte_size) => write!(w, "[{}]", byte_size)?,
        None => write!(w, "[??]")?,
    }
    write!(w, "\t")?;
    print_decl(p, w, hash)
}

impl<'input> Print for Parameter<'input> {
    type Arg = Unit<'input>;

    fn print(&self, state: &mut PrintState, _unit: &Unit) -> Result<()> {
        state.expanded(
            |state| state.line(|w, state| print_size_and_decl(self, w, state)),
            |state| {
                if state.options().print_variable_locations {
                    print::register::print_list(state, self.registers().map(|x| x.1).collect())?;
                    print::frame_location::print_list(
                        state,
                        self.frame_locations().map(|x| x.1).collect(),
                    )?;
                }
                Ok(())
            },
        )
    }

    fn diff(
        state: &mut DiffState,
        _unit_a: &Unit,
        a: &Self,
        _unit_b: &Unit,
        b: &Self,
    ) -> Result<()> {
        state.expanded(
            |state| state.line(a, b, |w, state, x| print_size_and_decl(x, w, state)),
            |state| {
                if state.options().print_variable_locations {
                    print::register::diff_list(
                        state,
                        a.registers().map(|x| x.1).collect(),
                        b.registers().map(|x| x.1).collect(),
                    )?;
                    print::frame_location::diff_list(
                        state,
                        a.frame_locations().map(|x| x.1).collect(),
                        b.frame_locations().map(|x| x.1).collect(),
                    )?;
                }
                Ok(())
            },
        )
    }
}

impl<'input> DiffList for Parameter<'input> {
    fn step_cost(&self, _state: &DiffState, _arg: &Unit) -> usize {
        1
    }

    fn diff_cost(state: &DiffState, _unit_a: &Unit, a: &Self, _unit_b: &Unit, b: &Self) -> usize {
        let mut cost = 0;
        if a.name().cmp(&b.name()) != cmp::Ordering::Equal {
            cost += 1;
        }
        match (&a.ty(state.hash_a()), &b.ty(state.hash_b())) {
            (Some(ty_a), Some(ty_b)) => {
                if Type::cmp_id(state.hash_a(), ty_a, state.hash_b(), ty_b) != cmp::Ordering::Equal
                {
                    cost += 1;
                }
            }
            (None, None) => {}
            _ => {
                cost += 1;
            }
        }
        cost
    }
}