forked from Orchid/orchid
Public API and docs
This commit is contained in:
@@ -20,13 +20,7 @@ pub trait InternedDisplay {
|
||||
|
||||
/// Converts the value to a string to be displayed
|
||||
fn to_string_i(&self, i: &Interner) -> String {
|
||||
// Copied from <https://doc.rust-lang.org/src/alloc/string.rs.html#2526>
|
||||
let mut buf = String::new();
|
||||
let mut formatter = Formatter::new(&mut buf);
|
||||
// Bypass format_args!() to avoid write_str with zero-length strs
|
||||
Self::fmt_i(self, &mut formatter, i)
|
||||
.expect("a Display implementation returned an error unexpectedly");
|
||||
buf
|
||||
self.bundle(i).to_string()
|
||||
}
|
||||
|
||||
fn bundle<'a>(&'a self, interner: &'a Interner) -> DisplayBundle<'a, Self> {
|
||||
@@ -47,12 +41,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to an [InternedDisplay] type and an [Interner] tied together
|
||||
/// to implement [Display]
|
||||
pub struct DisplayBundle<'a, T: InternedDisplay + ?Sized> {
|
||||
interner: &'a Interner,
|
||||
data: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, T: InternedDisplay> Display for DisplayBundle<'a, T> {
|
||||
impl<'a, T: InternedDisplay + ?Sized> Display for DisplayBundle<'a, T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.data.fmt_i(f, self.interner)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
//! A type-agnostic interner
|
||||
//!
|
||||
//! Can be used to deduplicate various structures for fast equality comparisons.
|
||||
//! The parser uses it to intern strings.
|
||||
mod display;
|
||||
mod monotype;
|
||||
mod multitype;
|
||||
@@ -10,9 +14,9 @@ pub use token::Tok;
|
||||
|
||||
/// A symbol, nsname, nname or namespaced name is a sequence of namespaces
|
||||
/// and an identifier. The [Vec] can never be empty.
|
||||
///
|
||||
///
|
||||
/// Throughout different stages of processing, these names can be
|
||||
///
|
||||
///
|
||||
/// - local names to be prefixed with the current module
|
||||
/// - imported names starting with a segment
|
||||
/// - ending a single import or
|
||||
|
||||
@@ -8,7 +8,8 @@ use hashbrown::HashMap;
|
||||
use super::token::Tok;
|
||||
|
||||
/// An interner for any type that implements [Borrow]. This is inspired by
|
||||
/// Lasso but much simpler, in part because not much can be known about the type.
|
||||
/// Lasso but much simpler, in part because not much can be known about the
|
||||
/// type.
|
||||
pub struct TypedInterner<T: 'static + Eq + Hash + Clone> {
|
||||
tokens: RefCell<HashMap<&'static T, Tok<T>>>,
|
||||
values: RefCell<Vec<(&'static T, bool)>>,
|
||||
@@ -45,7 +46,7 @@ impl<T: Eq + Hash + Clone> TypedInterner<T> {
|
||||
*kv.1
|
||||
}
|
||||
|
||||
/// Resolve a token, obtaining an object
|
||||
/// Resolve a token, obtaining a reference to the held object.
|
||||
/// It is illegal to use a token obtained from one interner with
|
||||
/// another.
|
||||
pub fn r(&self, t: Tok<T>) -> &T {
|
||||
@@ -74,6 +75,12 @@ impl<T: Eq + Hash + Clone> TypedInterner<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq + Hash + Clone> Default for TypedInterner<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq + Hash + Clone> Drop for TypedInterner<T> {
|
||||
fn drop(&mut self) {
|
||||
// make sure all values leaked by us are dropped
|
||||
|
||||
@@ -16,10 +16,12 @@ pub struct Interner {
|
||||
interners: RefCell<HashMap<TypeId, Rc<dyn Any>>>,
|
||||
}
|
||||
impl Interner {
|
||||
/// Create a new interner
|
||||
pub fn new() -> Self {
|
||||
Self { interners: RefCell::new(HashMap::new()) }
|
||||
}
|
||||
|
||||
/// Intern something
|
||||
pub fn i<Q: ?Sized + Eq + Hash + ToOwned>(&self, q: &Q) -> Tok<Q::Owned>
|
||||
where
|
||||
Q::Owned: 'static + Eq + Hash + Clone + Borrow<Q>,
|
||||
@@ -29,6 +31,7 @@ impl Interner {
|
||||
interner.i(q)
|
||||
}
|
||||
|
||||
/// Resolve a token to a reference
|
||||
pub fn r<T: 'static + Eq + Hash + Clone>(&self, t: Tok<T>) -> &T {
|
||||
let mut interners = self.interners.borrow_mut();
|
||||
let interner = get_interner(&mut interners);
|
||||
@@ -36,7 +39,7 @@ impl Interner {
|
||||
unsafe { (interner.r(t) as *const T).as_ref().unwrap() }
|
||||
}
|
||||
|
||||
/// Fully resolve
|
||||
/// Fully resolve an interned list of interned things
|
||||
/// TODO: make this generic over containers
|
||||
pub fn extern_vec<T: 'static + Eq + Hash + Clone>(
|
||||
&self,
|
||||
@@ -49,6 +52,7 @@ impl Interner {
|
||||
v.iter().map(|t| t_int.r(*t)).cloned().collect()
|
||||
}
|
||||
|
||||
/// Fully resolve a list of interned things.
|
||||
pub fn extern_all<T: 'static + Eq + Hash + Clone>(
|
||||
&self,
|
||||
s: &[Tok<T>],
|
||||
|
||||
Reference in New Issue
Block a user