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,21 +1,31 @@
use std::ops::{Add, Index};
use std::{ops::{Add, Index}, rc::Rc, fmt::Debug};
use hashbrown::{HashMap, hash_map::IntoIter};
use mappable_rc::Mrc;
use hashbrown::HashMap;
use crate::expression::Expr;
#[derive(Debug, PartialEq, Eq)]
pub enum Entry {
Vec(Rc<Vec<Expr>>),
Scalar(Rc<Expr>),
Name(Rc<String>),
NameOpt(Option<Rc<String>>)
}
/// A bucket of indexed expression fragments. Addition may fail if there's a conflict.
#[derive(PartialEq, Eq)]
pub struct State(HashMap<String, Mrc<Vec<Expr>>>);
#[derive(PartialEq, Eq, Clone)]
pub struct State(HashMap<String, Entry>);
/// Clone without also cloning arbitrarily heavy Expr objects.
/// Key is expected to be a very short string with an allocator overhead close to zero.
impl Clone for State {
impl Clone for Entry {
fn clone(&self) -> Self {
Self(HashMap::from_iter(
self.0.iter().map(|(k, v)| (k.clone(), Mrc::clone(v)))
))
match self {
Self::Name(n) => Self::Name(Rc::clone(n)),
Self::Scalar(x) => Self::Scalar(Rc::clone(x)),
Self::Vec(v) => Self::Vec(Rc::clone(v)),
Self::NameOpt(o) => Self::NameOpt(o.as_ref().map(Rc::clone))
}
}
}
@@ -23,24 +33,65 @@ impl State {
pub fn new() -> Self {
Self(HashMap::new())
}
/// Insert a new element, return None on conflict, clone only on success
pub fn insert<S>(mut self, k: &S, v: &[Expr]) -> Option<State>
pub fn insert_vec<S>(mut self, k: &S, v: &[Expr]) -> Option<Self>
where S: AsRef<str> + ToString + ?Sized + Debug {
eprintln!("{:?} + {k:?}-{v:?}", self.0);
if let Some(old) = self.0.get(k.as_ref()) {
if let Entry::Vec(val) = old {
if val.as_slice() != v {return None}
} else {return None}
} else {
self.0.insert(k.to_string(), Entry::Vec(Rc::new(v.to_vec())));
}
Some(self)
}
pub fn insert_scalar<S>(mut self, k: &S, v: &Expr) -> Option<Self>
where S: AsRef<str> + ToString + ?Sized {
if let Some(old) = self.0.get(k.as_ref()) {
if old.as_ref() != v {return None}
if let Entry::Scalar(val) = old {
if val.as_ref() != v {return None}
} else {return None}
} else {
self.0.insert(k.to_string(), Mrc::new(v.to_vec()));
self.0.insert(k.to_string(), Entry::Scalar(Rc::new(v.to_owned())));
}
return Some(self)
Some(self)
}
pub fn insert_name<S1, S2>(mut self, k: &S1, v: &S2) -> Option<Self>
where
S1: AsRef<str> + ToString + ?Sized,
S2: AsRef<str> + ToString + ?Sized
{
if let Some(old) = self.0.get(k.as_ref()) {
if let Entry::Name(val) = old {
if val.as_str() != v.as_ref() {return None}
} else {return None}
} else {
self.0.insert(k.to_string(), Entry::Name(Rc::new(v.to_string())));
}
Some(self)
}
pub fn insert_name_opt<S1, S2>(mut self, k: &S1, v: Option<&S2>) -> Option<Self>
where
S1: AsRef<str> + ToString + ?Sized,
S2: AsRef<str> + ToString + ?Sized
{
if let Some(old) = self.0.get(k.as_ref()) {
if let Entry::NameOpt(val) = old {
if val.as_ref().map(|s| s.as_ref().as_str()) != v.map(|s| s.as_ref()) {return None}
} else {return None}
} else {
self.0.insert(k.to_string(), Entry::NameOpt(v.map(|s| Rc::new(s.to_string()))));
}
Some(self)
}
/// Insert a new entry, return None on conflict
pub fn insert_pair(mut self, (k, v): (String, Mrc<Vec<Expr>>)) -> Option<State> {
pub fn insert_pair(mut self, (k, v): (String, Entry)) -> Option<State> {
if let Some(old) = self.0.get(&k) {
if old != &v {return None}
} else {
self.0.insert(k, v);
}
return Some(self)
Some(self)
}
/// Returns `true` if the state contains no data
pub fn empty(&self) -> bool {
@@ -58,7 +109,7 @@ impl Add for State {
for pair in rhs.0 {
self = self.insert_pair(pair)?
}
return Some(self);
Some(self)
}
}
@@ -70,20 +121,20 @@ impl Add<Option<State>> for State {
}
}
impl<'a, S> Index<&S> for State where S: AsRef<str> {
type Output = Vec<Expr>;
impl<S> Index<S> for State where S: AsRef<str> {
type Output = Entry;
fn index(&self, index: &S) -> &Self::Output {
fn index(&self, index: S) -> &Self::Output {
return &self.0[index.as_ref()]
}
}
impl IntoIterator for State {
type Item = (String, Mrc<Vec<Expr>>);
type Item = (String, Entry);
type IntoIter = IntoIter<String, Mrc<Vec<Expr>>>;
type IntoIter = hashbrown::hash_map::IntoIter<String, Entry>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
}