veryl-analyzer 0.16.1

A modern hardware description language
use crate::HashMap;
use crate::namespace::Namespace;
use std::cell::RefCell;
use std::fmt;
use veryl_parser::resource_table::{PathId, StrId, TokenId};

#[derive(Clone, Debug)]
pub struct NamespaceTable {
    default: Namespace,
    table: HashMap<TokenId, (Namespace, PathId)>,
}

impl NamespaceTable {
    pub fn insert(&mut self, id: TokenId, file_path: PathId, namespace: &Namespace) {
        self.table.insert(id, (namespace.clone(), file_path));
    }

    pub fn get(&self, id: TokenId) -> Option<&Namespace> {
        self.table.get(&id).map(|(x, _)| x)
    }

    pub fn dump(&self) -> String {
        format!("{self}")
    }

    pub fn drop(&mut self, file_path: PathId) {
        self.table.retain(|_, x| x.1 != file_path);
    }

    pub fn set_default(&mut self, id: &[StrId]) {
        let mut namespace = Namespace::new();
        for id in id {
            namespace.push(*id);
        }
        self.default = namespace;
    }

    pub fn get_default(&self) -> Namespace {
        self.default.clone()
    }

    pub fn clear(&mut self) {
        self.table.clear()
    }
}

impl Default for NamespaceTable {
    fn default() -> Self {
        Self {
            default: Namespace::new(),
            table: HashMap::default(),
        }
    }
}

impl fmt::Display for NamespaceTable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "NamespaceTable [")?;
        let mut id_witdh = 0;
        let mut namespace_width = 0;
        let mut vec: Vec<_> = self.table.iter().collect();
        vec.sort_by(|x, y| x.0.cmp(y.0));
        for (k, v) in &vec {
            id_witdh = id_witdh.max(format!("{k}").len());
            namespace_width = namespace_width.max(format!("{}", v.0).len());
        }
        for (k, v) in &vec {
            writeln!(
                f,
                "    {:id_witdh$}: {:namespace_width$} @ {},",
                k,
                v.0,
                v.1,
                id_witdh = id_witdh,
                namespace_width = namespace_width,
            )?;
        }
        writeln!(f, "]")?;
        Ok(())
    }
}

thread_local!(static NAMESPACE_TABLE: RefCell<NamespaceTable> = RefCell::new(NamespaceTable::default()));

pub fn insert(id: TokenId, file_path: PathId, namespace: &Namespace) {
    NAMESPACE_TABLE.with(|f| f.borrow_mut().insert(id, file_path, namespace))
}

pub fn get(id: TokenId) -> Option<Namespace> {
    NAMESPACE_TABLE.with(|f| f.borrow().get(id).cloned())
}

pub fn dump() -> String {
    NAMESPACE_TABLE.with(|f| f.borrow().dump())
}

pub fn drop(file_path: PathId) {
    NAMESPACE_TABLE.with(|f| f.borrow_mut().drop(file_path))
}

pub fn set_default(id: &[StrId]) {
    NAMESPACE_TABLE.with(|f| f.borrow_mut().set_default(id))
}

pub fn get_default() -> Namespace {
    NAMESPACE_TABLE.with(|f| f.borrow().get_default())
}

pub fn clear() {
    NAMESPACE_TABLE.with(|f| f.borrow_mut().clear())
}