1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
//! Namespace reference type.
#![cfg(not(feature = "no_module"))]
use crate::ast::Ident;
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<Ident>,
index: Option<NonZeroUsize>,
}
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::<StaticVec<_>>()
.join(crate::engine::NAMESPACE_SEPARATOR),
)
}
}
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::<StaticVec<_>>()
.join(crate::engine::NAMESPACE_SEPARATOR),
)
}
}
impl Deref for Namespace {
type Target = StaticVec<Ident>;
#[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<Vec<Ident>> for Namespace {
#[inline]
fn from(mut path: Vec<Ident>) -> Self {
path.shrink_to_fit();
Self {
index: None,
path: path.into(),
}
}
}
impl From<StaticVec<Ident>> for Namespace {
#[inline]
fn from(mut path: StaticVec<Ident>) -> 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<Ident>) -> 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<NonZeroUsize> {
self.index
}
/// Set the [`Scope`][crate::Scope] index offset.
#[inline(always)]
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
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
}
}