//! Namespace reference type. #![cfg(not(feature = "no_module"))] use crate::ast::Ident; use crate::tokenizer::Token; use crate::{Position, StaticVec}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ fmt, num::NonZeroUsize, ops::{Deref, DerefMut}, }; /// _(internals)_ A chain of [module][crate::Module] names to namespace-qualify a variable or function call. /// Exported under the `internals` feature only. /// /// Not available under `no_module`. /// /// A [`u64`] offset to the current stack of imported [modules][crate::Module] in the /// [global runtime state][crate::GlobalRuntimeState] is cached for quick search purposes. /// /// A [`StaticVec`] is used because the vast majority of namespace-qualified access contains only /// one level, and it is wasteful to always allocate a [`Vec`] with one element. #[derive(Clone, Eq, PartialEq, Default, Hash)] pub struct Namespace { path: StaticVec, index: Option, } impl fmt::Debug for Namespace { #[cold] #[inline(never)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_empty() { return f.write_str("NONE"); } if let Some(index) = self.index { write!(f, "{index} -> ")?; } f.write_str( &self .path .iter() .map(Ident::as_str) .collect::>() .join(Token::DoubleColon.literal_syntax()), ) } } impl fmt::Display for Namespace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_empty() { return Ok(()); } f.write_str( &self .path .iter() .map(Ident::as_str) .collect::>() .join(Token::DoubleColon.literal_syntax()), ) } } impl Deref for Namespace { type Target = StaticVec; #[inline(always)] fn deref(&self) -> &Self::Target { &self.path } } impl DerefMut for Namespace { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.path } } impl From> for Namespace { #[inline] fn from(mut path: Vec) -> Self { path.shrink_to_fit(); Self { index: None, path: path.into(), } } } impl From> for Namespace { #[inline] fn from(mut path: StaticVec) -> Self { path.shrink_to_fit(); Self { index: None, path } } } impl Namespace { /// Constant for no namespace. pub const NONE: Self = Self { index: None, path: StaticVec::new_const(), }; /// Create a new [`Namespace`]. #[inline(always)] #[must_use] pub fn new(root: impl Into) -> Self { let mut path = StaticVec::new_const(); path.push(root.into()); Self { index: None, path } } /// Get the [`Scope`][crate::Scope] index offset. #[inline(always)] #[must_use] pub(crate) const fn index(&self) -> Option { self.index } /// Set the [`Scope`][crate::Scope] index offset. #[inline(always)] pub(crate) fn set_index(&mut self, index: Option) { self.index = index; } /// Get the [position][Position] of this [`Namespace`]. /// /// # Panics /// /// Panics if the path is empty. #[inline(always)] #[must_use] pub fn position(&self) -> Position { self.path[0].pos } /// Get the first path segment of this [`Namespace`]. /// /// # Panics /// /// Panics if the path is empty. #[inline(always)] #[must_use] pub fn root(&self) -> &str { &self.path[0].name } }