Rule execution now runs, no tests tho

This commit is contained in:
2022-08-19 12:55:02 +02:00
parent 329dea72b7
commit 891d78c112
30 changed files with 925 additions and 560 deletions

View File

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

View File

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

View File

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