Rule execution now runs, no tests tho
This commit is contained in:
@@ -1,37 +1,60 @@
|
||||
use std::{hash::Hash, cell::RefCell};
|
||||
use std::{hash::Hash, cell::RefCell, rc::Rc};
|
||||
use hashbrown::HashMap;
|
||||
use mappable_rc::Mrc;
|
||||
|
||||
/// Convenience trait for overriding Mrc's strange cloning logic
|
||||
pub trait MyClone {
|
||||
fn my_clone(&self) -> Self;
|
||||
}
|
||||
|
||||
impl<T> MyClone for T where T: Clone {
|
||||
default fn my_clone(&self) -> Self { self.clone() }
|
||||
}
|
||||
|
||||
impl<T: ?Sized> MyClone for Rc<T> {
|
||||
fn my_clone(&self) -> Self { Rc::clone(self) }
|
||||
}
|
||||
impl<T: ?Sized> MyClone for Mrc<T> {
|
||||
fn my_clone(&self) -> Self { Mrc::clone(self) }
|
||||
}
|
||||
|
||||
/// Cache the return values of an effectless closure in a hashmap
|
||||
/// Inspired by the closure_cacher crate.
|
||||
pub struct Cache<'a, I, O: 'static> /*where O: Clone*/ {
|
||||
pub struct Cache<'a, I, O: 'static> {
|
||||
store: RefCell<HashMap<I, Mrc<O>>>,
|
||||
closure: RefCell<Box<dyn FnMut (I, &Self) -> Mrc<O> + 'a>>
|
||||
closure: Box<dyn Fn (I, &Self) -> Mrc<O> + 'a>
|
||||
}
|
||||
|
||||
impl<'a, I, O> Cache<'a, I, O> where
|
||||
I: Eq + Hash + Clone
|
||||
I: Eq + Hash + MyClone
|
||||
{
|
||||
pub fn new<F: 'a>(mut closure: F) -> Self where F: FnMut(I, &Self) -> O {
|
||||
pub fn new<F: 'a>(closure: F) -> Self where F: Fn(I, &Self) -> O {
|
||||
Self::new_raw(move |o, s| Mrc::new(closure(o, s)))
|
||||
}
|
||||
|
||||
/// Take an Mrc<O> closure rather than an O closure
|
||||
/// Used internally to derive caches from other systems working with Mrc-s
|
||||
pub fn new_raw<F: 'a>(closure: F) -> Self where F: FnMut(I, &Self) -> Mrc<O> {
|
||||
pub fn new_raw<F: 'a>(closure: F) -> Self where F: Fn(I, &Self) -> Mrc<O> {
|
||||
Self {
|
||||
store: RefCell::new(HashMap::new()),
|
||||
closure: RefCell::new(Box::new(closure))
|
||||
closure: Box::new(closure)
|
||||
}
|
||||
}
|
||||
|
||||
/// Produce and cache a result by cloning I if necessary
|
||||
pub fn find(&self, i: &I) -> Mrc<O> {
|
||||
let mut closure = self.closure.borrow_mut();
|
||||
let closure = &self.closure;
|
||||
if let Some(v) = self.store.borrow().get(i) {
|
||||
return Mrc::clone(v)
|
||||
}
|
||||
// In the moment of invocation the refcell is on immutable
|
||||
// this is important for recursive calculations
|
||||
let result = closure(i.my_clone(), self);
|
||||
let mut store = self.store.borrow_mut();
|
||||
Mrc::clone(store.raw_entry_mut().from_key(i)
|
||||
.or_insert_with(|| (i.clone(), closure(i.clone(), self))).1)
|
||||
.or_insert_with(|| (i.my_clone(), result)).1)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Return the result if it has already been computed
|
||||
pub fn known(&self, i: &I) -> Option<Mrc<O>> {
|
||||
@@ -46,7 +69,7 @@ impl<'a, I, O> Cache<'a, I, O> where
|
||||
}
|
||||
|
||||
impl<'a, I, O, E> Cache<'a, I, Result<O, E>> where
|
||||
I: Eq + Hash + Clone,
|
||||
I: Eq + Hash + MyClone,
|
||||
// O: Clone,
|
||||
E: Clone
|
||||
{
|
||||
@@ -60,7 +83,7 @@ impl<'a, I, O, E> Cache<'a, I, Result<O, E>> where
|
||||
}
|
||||
|
||||
impl<'a, I, O> Cache<'a, I, Option<O>> where
|
||||
I: Eq + Hash + Clone,
|
||||
I: Eq + Hash + MyClone,
|
||||
// O: Clone
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
@@ -70,4 +93,4 @@ impl<'a, I, O> Cache<'a, I, Option<O>> where
|
||||
let ent = self.find(i);
|
||||
Mrc::try_map(ent, |o| o.as_ref()).ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
src/utils/iter.rs
Normal file
36
src/utils/iter.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
/// Utility functions to get rid of explicit casts to BoxedIter which are tedious
|
||||
|
||||
use std::iter;
|
||||
|
||||
pub type BoxedIter<'a, T> = Box<dyn Iterator<Item = T> + 'a>;
|
||||
pub type BoxedIterIter<'a, T> = BoxedIter<'a, BoxedIter<'a, T>>;
|
||||
/// BoxedIter of a single element
|
||||
pub fn box_once<'a, T: 'a>(t: T) -> BoxedIter<'a, T> {
|
||||
Box::new(iter::once(t))
|
||||
}
|
||||
/// BoxedIter of no elements
|
||||
pub fn box_empty<'a, T: 'a>() -> BoxedIter<'a, T> {
|
||||
Box::new(iter::empty())
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! box_chain {
|
||||
($curr:expr) => {
|
||||
Box::new($curr) as BoxedIter<_>
|
||||
};
|
||||
($curr:expr, $($rest:expr),*) => {
|
||||
Box::new($curr$(.chain($rest))*) as $crate::utils::iter::BoxedIter<_>
|
||||
};
|
||||
}
|
||||
|
||||
pub fn box_flatten<'a, T: 'a, I: 'a, J: 'a>(i: I) -> BoxedIter<'a, T>
|
||||
where
|
||||
J: Iterator<Item = T>,
|
||||
I: Iterator<Item = J>,
|
||||
{
|
||||
Box::new(i.flatten())
|
||||
}
|
||||
pub fn into_boxed_iter<'a, T: 'a>(t: T) -> BoxedIter<'a, <T as IntoIterator>::Item>
|
||||
where T: IntoIterator {
|
||||
Box::new(t.into_iter())
|
||||
}
|
||||
@@ -2,11 +2,33 @@ mod cache;
|
||||
mod substack;
|
||||
mod side;
|
||||
mod merge_sorted;
|
||||
mod sorted_pairs;
|
||||
mod unwrap_or_continue;
|
||||
pub mod iter;
|
||||
pub use cache::Cache;
|
||||
use mappable_rc::Mrc;
|
||||
pub use substack::Stackframe;
|
||||
pub use side::Side;
|
||||
pub use merge_sorted::merge_sorted;
|
||||
pub use iter::BoxedIter;
|
||||
|
||||
pub type BoxedIter<'a, T> = Box<dyn Iterator<Item = T> + 'a>;
|
||||
pub fn mrc_derive<T: ?Sized, P, U: ?Sized>(m: &Mrc<T>, p: P) -> Mrc<U>
|
||||
where P: for<'a> FnOnce(&'a T) -> &'a U {
|
||||
Mrc::map(Mrc::clone(m), p)
|
||||
}
|
||||
|
||||
pub fn mrc_try_derive<T: ?Sized, P, U: ?Sized>(m: &Mrc<T>, p: P) -> Option<Mrc<U>>
|
||||
where P: for<'a> FnOnce(&'a T) -> Option<&'a U> {
|
||||
Mrc::try_map(Mrc::clone(m), p).ok()
|
||||
}
|
||||
|
||||
pub fn to_mrc_slice<T>(v: Vec<T>) -> Mrc<[T]> {
|
||||
Mrc::map(Mrc::new(v), |v| v.as_slice())
|
||||
}
|
||||
|
||||
pub fn collect_to_mrc<I>(iter: I) -> Mrc<[I::Item]> where I: Iterator {
|
||||
to_mrc_slice(iter.collect())
|
||||
}
|
||||
|
||||
pub fn mrc_derive_slice<T>(mv: &Mrc<Vec<T>>) -> Mrc<[T]> {
|
||||
mrc_derive(mv, |v| v.as_slice())
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
use std::ops::Add;
|
||||
|
||||
/// Combine two sorted iterators with their mapper function into a sorted iterator of pairs
|
||||
pub struct SortedPairs<L, R, IL, IR, ML, MR, O> {
|
||||
left: IL, right: IR,
|
||||
left_map: ML, right_map: MR,
|
||||
left_buf: Vec<(L, O)>, right_buf: Vec<(R, O)>
|
||||
}
|
||||
|
||||
impl<L, R, IL, IR, ML, MR, O> SortedPairs<L, R, IL, IR, ML, MR, O>
|
||||
where IL: Iterator<Item = L>, IR: Iterator<Item = R>,
|
||||
ML: Fn(L) -> O, MR: Fn(R) -> O,
|
||||
O: Ord + Add + Clone
|
||||
{
|
||||
pub fn new(left: IL, right: IR, left_map: ML, right_map: MR) -> Self {
|
||||
Self {
|
||||
left, right, left_map, right_map,
|
||||
left_buf: Vec::new(),
|
||||
right_buf: Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, L: 'a, R: 'a, IL: 'a, IR: 'a, ML: 'a, MR: 'a, O: 'a> Iterator
|
||||
for &'a mut SortedPairs<L, R, IL, IR, ML, MR, O>
|
||||
where IL: Iterator<Item = L>, IR: Iterator<Item = R>,
|
||||
ML: Fn(L) -> O, MR: Fn(R) -> O,
|
||||
O: Ord + Add + Clone,
|
||||
{
|
||||
type Item = (&'a L, &'a R);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user