xo65 0.1.0

Library for parsing cc65 object files (xo65 format)
Documentation
use tabled::Tabled;

use xo65::{scope::ScopeFlags, Xo65};

use crate::query::Xo65Query as _;
use crate::util::fmt_option;

pub fn dump(obj: &Xo65) {
    println!("Scope:");
    println!("{}", FmtScopeTable { obj });
    println!();
}

#[derive(Debug)]
struct FmtScopeTable<'a, 'data> {
    obj: &'a Xo65<'data>,
}

impl std::fmt::Display for FmtScopeTable<'_, '_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        use tabled::{
            settings::{object::Columns, Alignment, Style},
            Table,
        };

        let fmt_str = |idx: u32| self.obj.fmt_string(idx).to_string();

        let rows = self
            .obj
            .scope_table()
            .iter()
            .enumerate()
            .map(|(idx, scope)| {
                let name = fmt_str(scope.name());
                let kind = format!("{:?}", scope.kind());
                let parent = scope.parent().to_string(); // TODO: 名前も付ける?
                let lex_lvl = scope.lexical_level();
                let flags = scope.flags();
                let flags = format!("{:#X} ({})", flags.get(), FmtFlagsDesc(flags));
                let size = fmt_option(&scope.size()).to_string();
                let label = fmt_option(&scope.label()).to_string();
                // spans については個数のみ表示。
                let spans = scope.spans().len();
                FmtScopeTableRow {
                    idx,
                    name,
                    kind,
                    parent,
                    lex_lvl,
                    flags,
                    size,
                    label,
                    spans,
                }
            });

        Table::new(rows)
            .with(Style::empty())
            .modify(Columns::single(0), Alignment::right()) // idx
            .modify(Columns::single(4), Alignment::right()) // lex_lvl
            .modify(Columns::single(6), Alignment::right()) // size
            .modify(Columns::single(8), Alignment::right()) // spans
            .fmt(f)
    }
}

#[derive(Debug)]
struct FmtFlagsDesc(ScopeFlags);

impl std::fmt::Display for FmtFlagsDesc {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        use itertools::Itertools as _;

        let s = [
            self.0.has_size().then_some("HAS_SIZE"),
            self.0.has_label().then_some("HAS_LABEL"),
        ]
        .into_iter()
        .flatten()
        .join(",");

        s.fmt(f)
    }
}

#[derive(Debug, Tabled)]
struct FmtScopeTableRow {
    idx: usize,
    name: String,
    kind: String,
    parent: String,
    lex_lvl: u32,
    flags: String,
    size: String,
    label: String,
    spans: usize,
}