Public API and docs

This commit is contained in:
2023-05-26 15:23:15 +01:00
parent 3c1a6e2be2
commit fdf18e6ff8
99 changed files with 503 additions and 406 deletions

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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>],