Skip to content

Commit

Permalink
Finalize opposing terms in coalescing conjunctions.
Browse files Browse the repository at this point in the history
  • Loading branch information
olson-sean-k committed Mar 25, 2024
1 parent 572ffbc commit 5a3d9b4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/token/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1480,8 +1480,8 @@ impl VarianceTerm<Breadth> for Wildcard {
impl VarianceTerm<Depth> for Wildcard {
fn term(&self) -> <Depth as Invariant>::Term {
match self {
Wildcard::Tree { ref has_root, .. } => BoundaryTerm::Conjunctive(SeparatedTerm(
if *has_root { Separation::Closed } else { Separation::Last },
Wildcard::Tree { .. } => BoundaryTerm::Conjunctive(SeparatedTerm(
Separation::Closed { is_coalescent: true },
Variance::unbounded(),
)),
_ => Zero::zero(),
Expand Down
3 changes: 1 addition & 2 deletions src/token/variance/invariant/natural.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,9 @@ impl Finalize for SeparatedTerm<TokenVariance<Depth>> {

let SeparatedTerm(separation, term) = self;
match separation {
//Open(Some(Component)) | First | Last => term,
Open => ops::conjunction(term, Invariant(Depth::ONE)),
First | Last => term,
Closed => term.map_invariant(|term| Depth(term.0.saturating_sub(1))),
Closed { .. } => term.map_invariant(|term| Depth(term.0.saturating_sub(1))),
}
}
}
Expand Down
42 changes: 35 additions & 7 deletions src/token/variance/invariant/separation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,18 @@ pub enum Separation {
Open,
First,
Last,
Closed,
Closed {
is_coalescent: bool,
},
}

impl Separation {
pub fn is_coalescent(&self) -> bool {
match self {
Separation::Closed { ref is_coalescent } => *is_coalescent,
_ => false,
}
}
}

impl Conjunction for Separation {
Expand All @@ -290,9 +301,10 @@ impl Conjunction for Separation {
use Separation::{Closed, First, Last, Open};

match (self, rhs) {
(Closed, Closed) | (First, Last | Closed) | (Closed, Last) => Closed,
(Last | Open, Closed) | (Last | Open, Last) => Last,
(Closed, First | Open) | (First, First | Open) => First,
(Closed { is_coalescent: lhs }, Closed { is_coalescent: rhs }) => Closed { is_coalescent: lhs && rhs },
(First, Last | Closed { .. }) | (Closed { .. }, Last) => Closed { is_coalescent: false },
(Last | Open, Closed { .. }) | (Last | Open, Last) => Last,
(Closed { .. }, First | Open) | (First, First | Open) => First,
(Open, First | Open) | (Last, First | Open) => Open,
}
}
Expand Down Expand Up @@ -346,18 +358,34 @@ impl<T> SeparatedTerm<T> {
pub fn into_inner(self) -> T {
self.1
}

fn finalize_in_place(self) -> Self
where
Self: Finalize<Output = T>,
{
let separation = self.0;
SeparatedTerm(separation, self.finalize())
}
}

impl<T, U> Conjunction<SeparatedTerm<U>> for SeparatedTerm<T>
where
SeparatedTerm<T>: Finalize<Output = T>,
SeparatedTerm<U>: Finalize<Output = U>,
T: Conjunction<U>,
{
type Output = SeparatedTerm<T::Output>;

fn conjunction(self, rhs: SeparatedTerm<U>) -> Self::Output {
let (lhs, rhs) = match (self.0.is_coalescent(), rhs.0.is_coalescent()) {
(true, true) => (self, rhs),
(true, _) => (self, rhs.finalize_in_place()),
(_, true) => (self.finalize_in_place(), rhs),
_ => (self, rhs),
};
SeparatedTerm(
ops::conjunction(self.0, rhs.0),
ops::conjunction(self.1, rhs.1),
ops::conjunction(lhs.0, rhs.0),
ops::conjunction(lhs.1, rhs.1),
)
}
}
Expand Down Expand Up @@ -408,7 +436,7 @@ where
T: One,
{
fn one() -> Self {
SeparatedTerm(Separation::Closed, T::one())
SeparatedTerm(Separation::Closed { is_coalescent: false }, T::one())
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/token/variance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,12 +543,12 @@ mod tests {
#[case("**", Variance::unbounded())]
#[case("a/**", harness::range(1, None))]
#[case("a/**/b", harness::range(2, None))]
#[case("a/<*/>b", harness::range(2, None))]
//#[case("a/**/b/**/c", harness::range(3, None))]
//#[case("a/<*/>b", harness::range(2, None))]
#[case("a/**/b/**/c", harness::range(3, None))]
#[case("*/**", harness::range(1, None))]
#[case("**/*", harness::range(1, None))]
#[case("**/*/**", harness::range(1, None))]
//#[case("{a/b/,c/**/}*.ext", harness::range(2, None))]
#[case("{a/b/,c/**/}*.ext", harness::range(2, None))]
fn parse_expression_depth_variance_eq(
#[case] expression: &str,
#[case] expected: TokenVariance<Depth>,
Expand Down

0 comments on commit 5a3d9b4

Please sign in to comment.