Implement tightness check

This commit is contained in:
2020-05-29 14:57:00 +02:00
parent b94ee5134a
commit 93db8d02b5
7 changed files with 178 additions and 121 deletions

View File

@@ -83,11 +83,64 @@ impl foliage::flavor::FunctionDeclaration for FunctionDeclaration
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum PredicateDependencySign
{
OnlyPositive,
OnlyNegative,
PositiveAndNegative,
}
impl PredicateDependencySign
{
pub fn and_positive(self) -> Self
{
match self
{
Self::OnlyPositive => Self::OnlyPositive,
Self::OnlyNegative
| Self::PositiveAndNegative => Self::PositiveAndNegative,
}
}
pub fn and_negative(self) -> Self
{
match self
{
Self::OnlyNegative => Self::OnlyNegative,
Self::OnlyPositive
| Self::PositiveAndNegative => Self::PositiveAndNegative,
}
}
pub fn is_positive(&self) -> bool
{
match self
{
Self::OnlyPositive
| Self::PositiveAndNegative => true,
Self::OnlyNegative => false,
}
}
pub fn is_negative(&self) -> bool
{
match self
{
Self::OnlyPositive => false,
Self::OnlyNegative
| Self::PositiveAndNegative => true,
}
}
}
pub type PredicateDependencies =
std::collections::BTreeMap<std::rc::Rc<PredicateDeclaration>, PredicateDependencySign>;
pub struct PredicateDeclaration
{
pub declaration: foliage::PredicateDeclaration,
pub dependencies:
std::cell::RefCell<Option<std::collections::BTreeSet<std::rc::Rc<PredicateDeclaration>>>>,
pub dependencies: std::cell::RefCell<Option<PredicateDependencies>>,
pub is_input: std::cell::RefCell<bool>,
pub is_output: std::cell::RefCell<bool>,
}
@@ -109,8 +162,8 @@ impl PredicateDeclaration
*self.is_input.borrow() || *self.is_output.borrow()
}
fn collect_transitive_private_dependencies(&self,
mut transitive_dependencies: &mut std::collections::BTreeSet<
fn collect_positive_dependencies(&self,
mut positive_dependencies: &mut std::collections::BTreeSet<
std::rc::Rc<crate::PredicateDeclaration>>)
{
let dependencies = self.dependencies.borrow();
@@ -121,21 +174,61 @@ impl PredicateDeclaration
None => return,
};
for dependency in dependencies.iter()
for (dependency, sign) in dependencies.iter()
{
if transitive_dependencies.contains(&*dependency)
if positive_dependencies.contains(&*dependency)
|| dependency.is_built_in()
|| !sign.is_positive()
{
continue;
}
positive_dependencies.insert(std::rc::Rc::clone(dependency));
dependency.collect_positive_dependencies(&mut positive_dependencies);
}
}
fn collect_private_dependencies(&self,
mut private_dependencies: &mut std::collections::BTreeSet<
std::rc::Rc<crate::PredicateDeclaration>>)
{
let dependencies = self.dependencies.borrow();
let dependencies = match *dependencies
{
Some(ref dependencies) => dependencies,
// Input predicates dont have completed definitions and no dependencies, so ignore them
None => return,
};
for (dependency, _) in dependencies.iter()
{
if private_dependencies.contains(&*dependency)
|| dependency.is_public()
|| dependency.is_built_in()
{
continue;
}
transitive_dependencies.insert(std::rc::Rc::clone(&dependency));
private_dependencies.insert(std::rc::Rc::clone(dependency));
dependency.collect_transitive_private_dependencies(&mut transitive_dependencies);
dependency.collect_private_dependencies(&mut private_dependencies);
}
}
pub fn has_positive_dependency_cycle(&self) -> bool
{
if self.is_built_in()
{
return false;
}
let mut positive_dependencies = std::collections::BTreeSet::new();
self.collect_positive_dependencies(&mut positive_dependencies);
positive_dependencies.contains(self)
}
pub fn has_private_dependency_cycle(&self) -> bool
{
if self.is_public() || self.is_built_in()
@@ -143,10 +236,10 @@ impl PredicateDeclaration
return false;
}
let mut transitive_dependencies = std::collections::BTreeSet::new();
self.collect_transitive_private_dependencies(&mut transitive_dependencies);
let mut private_dependencies = std::collections::BTreeSet::new();
self.collect_private_dependencies(&mut private_dependencies);
transitive_dependencies.contains(self)
private_dependencies.contains(self)
}
}