use super::*;
use itertools::Itertools;
use std::cmp::Ordering;
#[cfg_attr(doc, katexit::katexit)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PartialComplexEntity {
pub indices: Vec<usize>,
}
impl PartialOrd for PartialComplexEntity {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
Some(self.cmp(rhs))
}
}
impl Ord for PartialComplexEntity {
fn cmp(&self, rhs: &Self) -> Ordering {
match Ord::cmp(&self.indices.len(), &rhs.indices.len()) {
Ordering::Equal => Ord::cmp(&self.indices, &rhs.indices),
a @ Ordering::Less | a @ Ordering::Greater => a,
}
}
}
impl PartialComplexEntity {
pub fn new(indices: &[usize]) -> Self {
PartialComplexEntity {
indices: indices.iter().cloned().dedup().collect(),
}
}
pub fn as_path(&self, ns: &Namespace) -> Vec<Path> {
self.indices
.iter()
.map(|index| {
let (path, _ast) = &ns[*index];
path.clone()
})
.collect()
}
}
impl From<&[usize]> for PartialComplexEntity {
fn from(indices: &[usize]) -> PartialComplexEntity {
PartialComplexEntity::new(indices)
}
}
impl std::ops::BitAnd for PartialComplexEntity {
type Output = Self;
fn bitand(mut self, mut rhs: Self) -> Self {
self.indices.append(&mut rhs.indices);
self.indices.sort_unstable();
PartialComplexEntity {
indices: self.indices.into_iter().dedup().collect(),
}
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Instantiables {
pub parts: Vec<PartialComplexEntity>,
}
impl Instantiables {
pub fn new(pces: &[PartialComplexEntity]) -> Self {
Self {
parts: pces.to_vec(),
}
}
pub fn single(index: usize) -> Self {
Self {
parts: vec![PartialComplexEntity::new(&[index])],
}
}
pub fn oneof(parts: Vec<Self>) -> Self {
let mut is = Self::default();
for p in parts {
is = is + p;
}
is
}
pub fn and(terms: Vec<Self>) -> Self {
assert!(terms.len() >= 2);
let mut constrait = None;
for c in terms {
constrait = Some(if let Some(constrait) = constrait {
constrait & c
} else {
c
});
}
constrait.unwrap()
}
pub fn andor(factors: Vec<Self>) -> Self {
assert!(!factors.is_empty());
let n = factors.len() as u32;
let mut constrait = Self::default();
for mut i in 1..(2usize.pow(n)) {
let mut c: Option<Self> = None;
for factor in &factors {
if i % 2 == 1 {
c = Some(if let Some(pre) = c {
pre & factor.clone()
} else {
factor.clone()
});
}
i >>= 1;
}
constrait = constrait + c.unwrap();
}
constrait
}
pub fn from_constraint_expr(
ns: &Namespace,
expr: &ConstraintExpr,
) -> Result<Self, SemanticError> {
use ConstraintExpr::*;
match expr {
Reference(path) => {
let (_ast, index) = ns.get(path)?;
Ok(Self::single(index))
}
OneOf(exprs) => {
let exprs = exprs
.iter()
.map(|e| Self::from_constraint_expr(ns, e))
.collect::<Result<Vec<Self>, SemanticError>>()?;
Ok(Self::oneof(exprs))
}
And(exprs) => {
let exprs = exprs
.iter()
.map(|e| Self::from_constraint_expr(ns, e))
.collect::<Result<Vec<Self>, SemanticError>>()?;
Ok(Self::and(exprs))
}
AndOr(exprs) => {
let exprs = exprs
.iter()
.map(|e| Self::from_constraint_expr(ns, e))
.collect::<Result<Vec<Self>, SemanticError>>()?;
Ok(Self::andor(exprs))
}
}
}
pub fn as_path(&self, ns: &Namespace) -> Vec<Vec<Path>> {
self.parts.iter().map(|pce| pce.as_path(ns)).collect()
}
}
impl<'a> FromIterator<&'a PartialComplexEntity> for Instantiables {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = &'a PartialComplexEntity>,
{
Self {
parts: iter.into_iter().cloned().sorted().dedup().collect(),
}
}
}
impl std::ops::Add for Instantiables {
type Output = Self;
fn add(mut self, mut rhs: Instantiables) -> Self {
self.parts.append(&mut rhs.parts);
Self {
parts: self.parts.into_iter().sorted().dedup().collect(),
}
}
}
impl std::ops::Add<PartialComplexEntity> for Instantiables {
type Output = Self;
fn add(mut self, rhs: PartialComplexEntity) -> Self {
self.parts.push(rhs);
Self {
parts: self.parts.into_iter().sorted().dedup().collect(),
}
}
}
impl std::ops::Add<Instantiables> for PartialComplexEntity {
type Output = Instantiables;
fn add(self, rhs: Instantiables) -> Instantiables {
rhs + self
}
}
impl std::ops::BitAnd for Instantiables {
type Output = Instantiables;
fn bitand(self, rhs: Instantiables) -> Instantiables {
let mut parts = Vec::with_capacity(self.parts.len() * rhs.parts.len());
for p in &self.parts {
for q in &rhs.parts {
parts.push(p.clone() & q.clone());
}
}
Instantiables {
parts: parts.into_iter().sorted().dedup().collect(),
}
}
}
impl std::ops::BitAnd<PartialComplexEntity> for Instantiables {
type Output = Instantiables;
fn bitand(self, q: PartialComplexEntity) -> Instantiables {
Instantiables {
parts: self
.parts
.into_iter()
.map(|p| p & q.clone())
.sorted()
.dedup()
.collect(),
}
}
}
impl std::ops::BitAnd<Instantiables> for PartialComplexEntity {
type Output = Instantiables;
fn bitand(self, rhs: Instantiables) -> Instantiables {
rhs & self
}
}
impl std::ops::Sub for Instantiables {
type Output = Self;
fn sub(self, rhs: Instantiables) -> Self {
Instantiables {
parts: self
.parts
.into_iter()
.filter(|p| rhs.parts.iter().all(|q| p != q))
.collect(),
}
}
}
impl std::ops::Sub<PartialComplexEntity> for Instantiables {
type Output = Self;
fn sub(self, q: PartialComplexEntity) -> Self {
Instantiables {
parts: self.parts.into_iter().filter(|p| p != &q).collect(),
}
}
}
impl std::ops::Div for Instantiables {
type Output = Self;
fn div(self, rhs: Instantiables) -> Self {
Instantiables {
parts: self
.parts
.into_iter()
.filter(|p| {
for q in &rhs.parts {
if q.indices.iter().all(|j| p.indices.binary_search(j).is_ok()) {
return true;
}
}
false
})
.collect(),
}
}
}
impl std::ops::Div<PartialComplexEntity> for Instantiables {
type Output = Instantiables;
fn div(self, rhs: PartialComplexEntity) -> Instantiables {
Instantiables {
parts: self
.parts
.into_iter()
.filter(|part| {
rhs.indices
.iter()
.all(|i| part.indices.binary_search(i).is_ok())
})
.collect(),
}
}
}