redid the parser, patched up the project too.

This commit is contained in:
2022-07-03 18:01:40 +02:00
parent 6fb4b581b1
commit 2b55fae10d
30 changed files with 967 additions and 570 deletions

View File

@@ -1,71 +1,68 @@
use std::hash::Hash;
use std::{hash::Hash, cell::RefCell};
use hashbrown::HashMap;
use mappable_rc::Mrc;
/// Cache the return values of an effectless closure in a hashmap
/// Inspired by the closure_cacher crate.
pub struct Cache<I, O, F> {
store: HashMap<I, O>,
closure: F
pub struct Cache<I, O: 'static> where O: Clone {
store: RefCell<HashMap<I, Mrc<O>>>,
closure: RefCell<Box<dyn FnMut (I) -> O + 'static>>
}
impl<I: 'static, O, F> Cache<I, O, F> where
I: Eq + Hash,
F: FnMut(I) -> O
impl<I, O> Cache<I, O> where
I: Eq + Hash + Clone,
O: Clone
{
pub fn new(closure: F) -> Self {
Self { store: HashMap::new(), closure }
}
/// Produce and cache a result by copying I if necessary
pub fn by_copy(&mut self, i: &I) -> &O where I: Copy {
let closure = &mut self.closure;
self.store.raw_entry_mut().from_key(i)
.or_insert_with(|| (*i, closure(*i))).1
pub fn new<F: 'static>(closure: F) -> Self where F: FnMut(I) -> O {
Self {
store: RefCell::new(HashMap::new()),
closure: RefCell::new(Box::new(closure))
}
}
/// Produce and cache a result by cloning I if necessary
pub fn by_clone(&mut self, i: &I) -> &O where I: Clone {
let closure = &mut self.closure;
self.store.raw_entry_mut().from_key(i)
.or_insert_with(|| (i.clone(), closure(i.clone()))).1
pub fn find(&self, i: &I) -> Mrc<O> {
let mut closure = self.closure.borrow_mut();
let mut store = self.store.borrow_mut();
Mrc::clone(store.raw_entry_mut().from_key(i)
.or_insert_with(|| (i.clone(), Mrc::new(closure(i.clone())))).1)
}
#[allow(dead_code)]
/// Return the result if it has already been computed
pub fn known(&self, i: &I) -> Option<&O> {
self.store.get(i)
pub fn known(&self, i: &I) -> Option<Mrc<O>> {
let store = self.store.borrow();
store.get(i).map(Mrc::clone)
}
#[allow(dead_code)]
/// Forget the output for the given input
pub fn drop(&mut self, i: &I) -> bool {
self.store.remove(i).is_some()
pub fn drop(&self, i: &I) -> bool {
self.store.borrow_mut().remove(i).is_some()
}
}
impl<I: 'static, O, E, F> Cache<I, Result<O, E>, F> where
I: Eq + Hash,
E: Clone,
F: FnMut(I) -> Result<O, E>
impl<I, O, E> Cache<I, Result<O, E>> where
I: Eq + Hash + Clone,
O: Clone,
E: Clone
{
/// Sink the ref from a Result into the Ok value, such that copying only occurs on the sad path
/// but the return value can be short-circuited
pub fn by_copy_fallible(&mut self, i: &I) -> Result<&O, E> where I: Copy {
self.by_clone(i).as_ref().map_err(|e| e.clone())
}
/// Sink the ref from a Result into the Ok value, such that cloning only occurs on the sad path
/// but the return value can be short-circuited
pub fn by_clone_fallible(&mut self, i: &I) -> Result<&O, E> where I: Clone {
self.by_clone(i).as_ref().map_err(|e| e.clone())
pub fn try_find(&self, i: &I) -> Result<Mrc<O>, E> {
let ent = self.find(i);
Mrc::try_map(ent, |t| t.as_ref().ok())
.map_err(|res| Result::as_ref(&res).err().unwrap().to_owned())
}
}
impl<I: 'static, O, F> Cache<I, Option<O>, F> where
I: Eq + Hash,
F: FnMut(I) -> Option<O>
impl<I, O> Cache<I, Option<O>> where
I: Eq + Hash + Clone,
O: Clone
{
#[allow(dead_code)]
/// Sink the ref from an Option into the Some value such that the return value can be
/// short-circuited
pub fn by_copy_fallible(&mut self, i: &I) -> Option<&O> where I: Copy {
self.by_copy(i).as_ref()
}
/// Sink the ref from an Option into the Some value such that the return value can be
/// short-circuited
pub fn by_clone_fallible(&mut self, i: &I) -> Option<&O> where I: Clone {
self.by_clone(i).as_ref()
pub fn try_find(&self, i: &I) -> Option<Mrc<O>> where I: Clone {
let ent = self.find(i);
Mrc::try_map(ent, |o| o.as_ref()).ok()
}
}

View File

@@ -1,8 +1,8 @@
mod cache;
mod substack;
mod result_iter_collect;
pub use cache::Cache;
pub use substack::Substack;
pub use result_iter_collect::result_iter_collect;
pub fn as_modpath(path: &Vec<String>) -> String {
path.join("::")
}
pub type BoxedIter<'a, T> = Box<dyn Iterator<Item = T> + 'a>;

View File

@@ -0,0 +1,19 @@
pub fn result_iter_collect<T, E>(i: &mut dyn Iterator<Item = Result<T, E>>)
-> (Vec<Option<T>>, Vec<Option<E>>) {
i.fold((Vec::new(), Vec::new()), |(mut succ, mut err), mut next| {
match next {
Ok(res) => succ.push(Some(res)),
Err(e) => err.push(Some(e))
}
(succ, err)
})
}
pub fn recoverable_iter_collect<T, E>(i: &mut dyn Iterator<Item=(Option<T>, Vec<E>)>)
-> (Vec<Option<T>>, Vec<E>) {
i.fold((Vec::new(), Vec::new()), |(mut succ, mut err), (res, mut errv)| {
succ.push(res);
err.append(&mut errv);
(succ, err)
})
}

View File

@@ -9,7 +9,9 @@ pub struct Substack<'a, T> {
}
impl<'a, T> Substack<'a, T> {
#[allow(dead_code)]
pub fn item(&self) -> &T { &self.item }
#[allow(dead_code)]
pub fn prev(&self) -> Option<&'a Substack<'a, T>> { self.prev }
pub fn new(item: T) -> Self {