Skip to content

Commit

Permalink
Rename some variance items.
Browse files Browse the repository at this point in the history
This change renames the `VarianceOf` type definition to `GlobVariance`
and rename the `Bound` type (back) to `Boundedness`. The variance
`Bounded` and `Unbounded` are exported and imported directly. Something
similar may be possible for the `Invariant` and `Variant` variants of
`Variance` (heh), but this conflicts with the `Invariant` trait.
  • Loading branch information
olson-sean-k committed Feb 13, 2024
1 parent b0d70a5 commit bbe626c
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 145 deletions.
9 changes: 3 additions & 6 deletions src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,13 +772,10 @@ where
}

// Arguably, this function enforces _syntactic_ rules. Any bound specification can be used to
// construct a functional repetition token, but this is only because `NaturalVariance` has an
// construct a functional repetition token, but this is only because `NaturalRange` has an
// interpretation of these bounds (such as `<_:0,0>` and `<_:10,1>`). These interpretations may be
// counterintuitive (especially bounds converged on zero, which are considered entirely unbounded),
// so they are rejected here.
//
// Put another way, the _semantics_ of ranges like `0,0` differ between glob expressions and
// `NaturalVariance`, and the semantics of glob expressions must reject such ranges.
// counterintuitive and present multiple spellings of the same semantics, so they are rejected
// here.
fn bounds<'t, A>(tree: &Tokenized<'t, A>) -> Result<(), RuleError<'t>>
where
A: Spanned,
Expand Down
88 changes: 44 additions & 44 deletions src/token/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::slice;
use std::str;

use crate::diagnostics::{Span, Spanned};
use crate::token::variance::bound::Bound;
use crate::token::variance::bound::Boundedness;
use crate::token::variance::invariant::{IntoNominalText, IntoStructuralText};
use crate::token::variance::ops::{self, Conjunction};
use crate::token::variance::{TreeExhaustiveness, TreeVariance, VarianceFold, VarianceTerm};
Expand All @@ -22,7 +22,7 @@ use crate::{StrExt as _, PATHS_ARE_CASE_INSENSITIVE};

pub use crate::token::parse::{parse, ParseError, ROOT_SEPARATOR_EXPRESSION};
pub use crate::token::variance::bound::NaturalRange;
pub use crate::token::variance::invariant::{Breadth, Depth, Invariant, Size, Text, VarianceOf};
pub use crate::token::variance::invariant::{Breadth, Depth, GlobVariance, Invariant, Size, Text};
pub use crate::token::variance::Variance;

// TODO: Tree representations of expressions are intrusive and only differ in their annotations.
Expand Down Expand Up @@ -478,9 +478,9 @@ impl<'t, A> Token<'t, A> {
self.as_leaf().and_then(LeafKind::boundary)
}

pub fn variance<'a, T>(&'a self) -> VarianceOf<T>
pub fn variance<'a, T>(&'a self) -> GlobVariance<T>
where
TreeVariance<T>: Fold<'t, A, Term = VarianceOf<T>>,
TreeVariance<T>: Fold<'t, A, Term = GlobVariance<T>>,
T: Conjunction<Output = T> + Invariant,
{
self.fold(TreeVariance::default())
Expand Down Expand Up @@ -600,7 +600,7 @@ impl<'t, A> Token<'t, A> {
// serious bug. False positives in negative patterns cause matching to incorrectly
// discard directory trees.
pub fn is_exhaustive(&self) -> bool {
self.fold(TreeExhaustiveness)
self.fold(TreeExhaustiveness::default())
.as_ref()
.map_or(false, Variance::is_exhaustive)
}
Expand Down Expand Up @@ -847,7 +847,7 @@ where
Repetition<'t, A>: VarianceFold<T>,
T: Invariant,
{
fn fold(&self, terms: Vec<VarianceOf<T>>) -> Option<VarianceOf<T>> {
fn fold(&self, terms: Vec<GlobVariance<T>>) -> Option<GlobVariance<T>> {
use BranchKind::{Alternation, Concatenation, Repetition};

match self {
Expand All @@ -857,7 +857,7 @@ where
}
}

fn finalize(&self, term: VarianceOf<T>) -> VarianceOf<T> {
fn finalize(&self, term: GlobVariance<T>) -> GlobVariance<T> {
use BranchKind::{Alternation, Concatenation, Repetition};

match self {
Expand Down Expand Up @@ -959,7 +959,7 @@ where
Wildcard: VarianceTerm<T>,
T: Invariant,
{
fn term(&self) -> VarianceOf<T> {
fn term(&self) -> GlobVariance<T> {
use LeafKind::{Class, Literal, Separator, Wildcard};

match self {
Expand Down Expand Up @@ -1000,19 +1000,19 @@ impl<'t, A> From<Vec<Token<'t, A>>> for Alternation<'t, A> {
}

impl<'t, A> VarianceFold<Depth> for Alternation<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Depth>>) -> Option<VarianceOf<Depth>> {
fn fold(&self, terms: Vec<GlobVariance<Depth>>) -> Option<GlobVariance<Depth>> {
terms.into_iter().reduce(ops::disjunction)
}
}

impl<'t, A> VarianceFold<Size> for Alternation<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Size>>) -> Option<VarianceOf<Size>> {
fn fold(&self, terms: Vec<GlobVariance<Size>>) -> Option<GlobVariance<Size>> {
terms.into_iter().reduce(ops::disjunction)
}
}

impl<'t, A> VarianceFold<Text<'t>> for Alternation<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Text<'t>>>) -> Option<VarianceOf<Text<'t>>> {
fn fold(&self, terms: Vec<GlobVariance<Text<'t>>>) -> Option<GlobVariance<Text<'t>>> {
terms.into_iter().reduce(ops::disjunction)
}
}
Expand Down Expand Up @@ -1045,7 +1045,7 @@ impl From<(char, char)> for Archetype {
}

impl VarianceTerm<Size> for Archetype {
fn term(&self) -> VarianceOf<Size> {
fn term(&self) -> GlobVariance<Size> {
// TODO: Examine the archetype instead of blindly assuming a constant size. This becomes
// especially important if character classes gain support for named classes, as these
// may contain graphemes that cannot be encoded as a single code point. See related
Expand All @@ -1057,19 +1057,19 @@ impl VarianceTerm<Size> for Archetype {
}

impl<'t> VarianceTerm<Text<'t>> for Archetype {
fn term(&self) -> VarianceOf<Text<'t>> {
fn term(&self) -> GlobVariance<Text<'t>> {
match self {
Archetype::Character(x) => {
if PATHS_ARE_CASE_INSENSITIVE {
Variance::Variant(Bound::BOUNDED)
Variance::Variant(Boundedness::BOUNDED)
}
else {
Variance::Invariant(*x)
}
},
Archetype::Range(a, b) => {
if (a != b) || PATHS_ARE_CASE_INSENSITIVE {
Variance::Variant(Bound::BOUNDED)
Variance::Variant(Boundedness::BOUNDED)
}
else {
Variance::Invariant(*a)
Expand All @@ -1095,11 +1095,11 @@ impl Class {
self.is_negated
}

fn fold<T, F>(&self, f: F) -> VarianceOf<T>
fn fold<T, F>(&self, f: F) -> GlobVariance<T>
where
Archetype: VarianceTerm<T>,
T: Invariant,
F: FnMut(VarianceOf<T>, VarianceOf<T>) -> VarianceOf<T>,
F: FnMut(GlobVariance<T>, GlobVariance<T>) -> GlobVariance<T>,
{
self.archetypes()
.iter()
Expand All @@ -1110,30 +1110,30 @@ impl Class {
}

impl VarianceTerm<Breadth> for Class {
fn term(&self) -> VarianceOf<Breadth> {
fn term(&self) -> GlobVariance<Breadth> {
Variance::zero()
}
}

impl VarianceTerm<Depth> for Class {
fn term(&self) -> VarianceOf<Depth> {
fn term(&self) -> GlobVariance<Depth> {
Variance::zero()
}
}

impl VarianceTerm<Size> for Class {
fn term(&self) -> VarianceOf<Size> {
fn term(&self) -> GlobVariance<Size> {
self.fold(ops::disjunction)
}
}

impl<'t> VarianceTerm<Text<'t>> for Class {
fn term(&self) -> VarianceOf<Text<'t>> {
fn term(&self) -> GlobVariance<Text<'t>> {
if self.is_negated {
// It is not feasible to encode a character class that matches all UTF-8 text and
// therefore nothing when negated, and so a character class must be variant if it is
// negated and is furthermore assumed to be bounded.
Variance::Variant(Bound::BOUNDED)
Variance::Variant(Boundedness::BOUNDED)
}
else {
// TODO: This ignores casing groups, such as in the pattern `[aA]`.
Expand Down Expand Up @@ -1171,19 +1171,19 @@ impl<'t, A> From<Vec<Token<'t, A>>> for Concatenation<'t, A> {
}

impl<'t, A> VarianceFold<Depth> for Concatenation<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Depth>>) -> Option<VarianceOf<Depth>> {
fn fold(&self, terms: Vec<GlobVariance<Depth>>) -> Option<GlobVariance<Depth>> {
terms.into_iter().reduce(ops::conjunction)
}
}

impl<'t, A> VarianceFold<Size> for Concatenation<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Size>>) -> Option<VarianceOf<Size>> {
fn fold(&self, terms: Vec<GlobVariance<Size>>) -> Option<GlobVariance<Size>> {
terms.into_iter().reduce(ops::conjunction)
}
}

impl<'t, A> VarianceFold<Text<'t>> for Concatenation<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Text<'t>>>) -> Option<VarianceOf<Text<'t>>> {
fn fold(&self, terms: Vec<GlobVariance<Text<'t>>>) -> Option<GlobVariance<Text<'t>>> {
terms.into_iter().reduce(ops::conjunction)
}
}
Expand Down Expand Up @@ -1225,7 +1225,7 @@ impl<'t> Literal<'t> {

fn variance(&self) -> Variance<&Cow<'t, str>> {
if self.has_variant_casing() {
Variance::Variant(Bound::BOUNDED)
Variance::Variant(Boundedness::BOUNDED)
}
else {
Variance::Invariant(&self.text)
Expand All @@ -1244,27 +1244,27 @@ impl<'t> Literal<'t> {
}

impl<'t> VarianceTerm<Breadth> for Literal<'t> {
fn term(&self) -> VarianceOf<Breadth> {
fn term(&self) -> GlobVariance<Breadth> {
Variance::zero()
}
}

impl<'t> VarianceTerm<Depth> for Literal<'t> {
fn term(&self) -> VarianceOf<Depth> {
fn term(&self) -> GlobVariance<Depth> {
Variance::zero()
}
}

impl<'t> VarianceTerm<Size> for Literal<'t> {
fn term(&self) -> VarianceOf<Size> {
fn term(&self) -> GlobVariance<Size> {
// TODO: This assumes that the size of graphemes in a casing set are the same. Is that
// correct?
Variance::Invariant(self.text.as_bytes().len().into())
}
}

impl<'t> VarianceTerm<Text<'t>> for Literal<'t> {
fn term(&self) -> VarianceOf<Text<'t>> {
fn term(&self) -> GlobVariance<Text<'t>> {
self.variance()
.map_invariant(|invariant| invariant.clone().into_nominal_text())
}
Expand Down Expand Up @@ -1322,31 +1322,31 @@ impl<'t, A> BranchComposition<'t> for Repetition<'t, A> {
}

impl<'t, A> VarianceFold<Depth> for Repetition<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Depth>>) -> Option<VarianceOf<Depth>> {
fn fold(&self, terms: Vec<GlobVariance<Depth>>) -> Option<GlobVariance<Depth>> {
terms.into_iter().reduce(ops::conjunction)
}

fn finalize(&self, term: VarianceOf<Depth>) -> VarianceOf<Depth> {
fn finalize(&self, term: GlobVariance<Depth>) -> GlobVariance<Depth> {
ops::product(term, self.variance())
}
}

impl<'t, A> VarianceFold<Size> for Repetition<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Size>>) -> Option<VarianceOf<Size>> {
fn fold(&self, terms: Vec<GlobVariance<Size>>) -> Option<GlobVariance<Size>> {
terms.into_iter().reduce(ops::conjunction)
}

fn finalize(&self, term: VarianceOf<Size>) -> VarianceOf<Size> {
fn finalize(&self, term: GlobVariance<Size>) -> GlobVariance<Size> {
ops::product(term, self.variance())
}
}

impl<'t, A> VarianceFold<Text<'t>> for Repetition<'t, A> {
fn fold(&self, terms: Vec<VarianceOf<Text<'t>>>) -> Option<VarianceOf<Text<'t>>> {
fn fold(&self, terms: Vec<GlobVariance<Text<'t>>>) -> Option<GlobVariance<Text<'t>>> {
terms.into_iter().reduce(ops::conjunction)
}

fn finalize(&self, term: VarianceOf<Text<'t>>) -> VarianceOf<Text<'t>> {
fn finalize(&self, term: GlobVariance<Text<'t>>) -> GlobVariance<Text<'t>> {
ops::product(term, self.variance())
}
}
Expand All @@ -1359,27 +1359,27 @@ impl Separator {
}

impl VarianceTerm<Breadth> for Separator {
fn term(&self) -> VarianceOf<Breadth> {
fn term(&self) -> GlobVariance<Breadth> {
Variance::zero()
}
}

impl VarianceTerm<Depth> for Separator {
fn term(&self) -> VarianceOf<Depth> {
fn term(&self) -> GlobVariance<Depth> {
Variance::Invariant(1.into())
}
}

impl VarianceTerm<Size> for Separator {
fn term(&self) -> VarianceOf<Size> {
fn term(&self) -> GlobVariance<Size> {
// TODO: This is incorrect. The compiled regular expression may ignore a terminating
// separator, in which case the size is a bounded range.
Variance::Invariant(Separator::INVARIANT_TEXT.as_bytes().len().into())
}
}

impl<'t> VarianceTerm<Text<'t>> for Separator {
fn term(&self) -> VarianceOf<Text<'t>> {
fn term(&self) -> GlobVariance<Text<'t>> {
Variance::Invariant(Separator::INVARIANT_TEXT.into_structural_text())
}
}
Expand Down Expand Up @@ -1423,7 +1423,7 @@ where
}

impl VarianceTerm<Breadth> for Wildcard {
fn term(&self) -> VarianceOf<Breadth> {
fn term(&self) -> GlobVariance<Breadth> {
match self {
Wildcard::One => Variance::zero(),
_ => Variance::unbounded(),
Expand All @@ -1432,7 +1432,7 @@ impl VarianceTerm<Breadth> for Wildcard {
}

impl VarianceTerm<Depth> for Wildcard {
fn term(&self) -> VarianceOf<Depth> {
fn term(&self) -> GlobVariance<Depth> {
match self {
Wildcard::Tree { .. } => Variance::unbounded(),
_ => Variance::zero(),
Expand All @@ -1441,7 +1441,7 @@ impl VarianceTerm<Depth> for Wildcard {
}

impl VarianceTerm<Size> for Wildcard {
fn term(&self) -> VarianceOf<Size> {
fn term(&self) -> GlobVariance<Size> {
match self {
// TODO: This is a bit pessimistic and, more importantly, incorrect! Clarity is needed
// on what exactly an exactly-one wildcard matches in text. If it is a grapheme,
Expand All @@ -1455,7 +1455,7 @@ impl VarianceTerm<Size> for Wildcard {
}

impl<'t> VarianceTerm<Text<'t>> for Wildcard {
fn term(&self) -> VarianceOf<Text<'t>> {
fn term(&self) -> GlobVariance<Text<'t>> {
Variance::unbounded()
}
}
Expand Down
Loading

0 comments on commit bbe626c

Please sign in to comment.