use std::cell::RefCell;
use allocative::Allocative;
use starlark_syntax::syntax::ast::Visibility;
use crate::collections::Hashed;
use crate::collections::SmallMap;
use crate::environment::slots::ModuleSlotId;
use crate::values::FrozenStringValue;
#[derive(Debug)]
pub(crate) struct MutableNames(RefCell<SmallMap<FrozenStringValue, (ModuleSlotId, Visibility)>>);
#[derive(Debug, Allocative)]
pub(crate) struct FrozenNames(SmallMap<FrozenStringValue, (ModuleSlotId, Visibility)>);
impl MutableNames {
pub(crate) fn new() -> Self {
Self(RefCell::new(SmallMap::new()))
}
pub(crate) fn slot_count(&self) -> u32 {
self.0.borrow().len().try_into().unwrap()
}
pub(crate) fn get_slot(&self, slot: ModuleSlotId) -> Option<FrozenStringValue> {
for (s, (i, _vis)) in &*self.0.borrow() {
if *i == slot {
return Some(*s);
}
}
None
}
pub(crate) fn get_name(&self, name: Hashed<&str>) -> Option<(ModuleSlotId, Visibility)> {
self.0.borrow().get_hashed(name).copied()
}
pub(crate) fn add_name_visibility(
&self,
name: FrozenStringValue,
vis: Visibility,
) -> ModuleSlotId {
let mut x = self.0.borrow_mut();
match x.get_mut_hashed(name.get_hashed().as_ref()) {
Some((slot, stored_vis)) => {
if *stored_vis == Visibility::Private {
*stored_vis = vis;
}
*slot
}
None => {
let slot = ModuleSlotId::new(x.len().try_into().unwrap());
x.insert_hashed(name.get_hashed(), (slot, vis));
slot
}
}
}
pub(crate) fn add_name(&self, name: FrozenStringValue) -> ModuleSlotId {
self.add_name_visibility(name, Visibility::Public)
}
pub(crate) fn hide_name(&self, name: &str) {
self.0.borrow_mut().shift_remove(name);
}
pub(crate) fn all_names_and_slots(&self) -> Vec<(FrozenStringValue, ModuleSlotId)> {
self.0
.borrow()
.iter()
.map(|(name, (slot, _vis))| (*name, *slot))
.collect()
}
pub(crate) fn all_names_and_visibilities(&self) -> Vec<(FrozenStringValue, Visibility)> {
self.0
.borrow()
.iter()
.map(|(name, (_slot, vis))| (*name, *vis))
.collect()
}
pub(crate) fn all_names_slots_and_visibilities(
&self,
) -> Vec<(FrozenStringValue, ModuleSlotId, Visibility)> {
self.0
.borrow()
.iter()
.map(|(name, (slot, vis))| (*name, *slot, *vis))
.collect()
}
pub(crate) fn freeze(self) -> FrozenNames {
FrozenNames(self.0.into_inner())
}
}
impl FrozenNames {
pub(crate) fn get_name(&self, name: &str) -> Option<(ModuleSlotId, Visibility)> {
self.0.get(name).copied()
}
pub(crate) fn all_symbols(
&self,
) -> impl Iterator<Item = (FrozenStringValue, ModuleSlotId)> + '_ {
self.0.iter().map(|(name, (slot, _vis))| (*name, *slot))
}
pub(crate) fn symbols(&self) -> impl Iterator<Item = (FrozenStringValue, ModuleSlotId)> + '_ {
self.0.iter().filter_map(|(name, (slot, vis))| match vis {
Visibility::Private => None,
Visibility::Public => Some((*name, *slot)),
})
}
}