Skip to content

Commit

Permalink
Move more types into query.
Browse files Browse the repository at this point in the history
This change also uses type aliases in bound APIs for consistency in code
and documentation.
  • Loading branch information
olson-sean-k committed Mar 18, 2024
1 parent a6cdb88 commit e8e03ab
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 35 deletions.
4 changes: 2 additions & 2 deletions src/diagnostics/mod.rs
Expand Up @@ -73,8 +73,8 @@ impl Spanned for Span {
///
/// [`BuildError::locations`]: crate::BuildError::locations
/// [`Display`]: std::fmt::Display
/// [`LocatedError::span`]: crate::LocatedError::span
/// [`Span`]: crate::Span
/// [`LocatedError::span`]: crate::query::LocatedError::span
/// [`Span`]: crate::query::Span
pub trait LocatedError: Display {
/// Gets the span within the glob expression with which the error is associated.
fn span(&self) -> Span;
Expand Down
34 changes: 17 additions & 17 deletions src/lib.rs
Expand Up @@ -58,9 +58,10 @@ pub mod walk;
/// }
/// ```
pub mod prelude {
pub use crate::query::LocatedError as _;
#[cfg(feature = "walk")]
pub use crate::walk::{Entry as _, FileIterator as _, PathExt as _};
pub use crate::{LocatedError as _, Program as _};
pub use crate::Program as _;
}

#[cfg(feature = "miette")]
Expand All @@ -75,18 +76,17 @@ use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
use thiserror::Error;

use crate::diagnostics::LocatedError;
use crate::encode::CompileError;
use crate::query::{CapturingToken, When};
use crate::query::{CapturingToken, DepthVariance, TextVariance, When};
use crate::rule::{Checked, RuleError};
use crate::token::{
ConcatenationTree, Depth, ExpressionMetadata, ParseError, Text, Token, TokenTree,
TokenVariance, Tokenized,
ConcatenationTree, ExpressionMetadata, ParseError, Token, TokenTree, Tokenized,
};
#[cfg(feature = "walk")]
use crate::walk::WalkError;

pub use crate::capture::MatchedText;
pub use crate::diagnostics::{LocatedError, Span};

#[cfg(windows)]
const PATHS_ARE_CASE_INSENSITIVE: bool = true;
Expand Down Expand Up @@ -174,9 +174,9 @@ pub trait Program<'t>: Pattern<'t, Error = Infallible> {
/// [`MatchedText`]: crate::MatchedText
fn matched<'p>(&self, path: &'p CandidatePath<'_>) -> Option<MatchedText<'p>>;

fn depth(&self) -> TokenVariance<Depth>;
fn depth(&self) -> DepthVariance;

fn text(&self) -> TokenVariance<Text<'t>>;
fn text(&self) -> TextVariance<'t>;

/// Returns `true` if the glob has a root.
///
Expand Down Expand Up @@ -307,8 +307,8 @@ impl BuildError {
/// [`Glob`]: crate::Glob
/// [`Glob::partition`]: crate::Glob::partition
/// [`Iterator`]: std::iter::Iterator
/// [`LocatedError`]: crate::LocatedError
/// [`Span`]: crate::Span
/// [`LocatedError`]: crate::query::LocatedError
/// [`Span`]: crate::query::Span
pub fn locations(&self) -> impl Iterator<Item = &dyn LocatedError> {
let locations: Vec<_> = match self.kind {
BuildErrorKind::Parse(ref error) => error
Expand Down Expand Up @@ -699,12 +699,12 @@ impl<'t> Program<'t> for Glob<'t> {
self.program.captures(path.as_ref()).map(From::from)
}

fn depth(&self) -> TokenVariance<Depth> {
self.tree.as_ref().as_token().variance()
fn depth(&self) -> DepthVariance {
self.tree.as_ref().as_token().variance().into()
}

fn text(&self) -> TokenVariance<Text<'t>> {
self.tree.as_ref().as_token().variance()
fn text(&self) -> TextVariance<'t> {
self.tree.as_ref().as_token().variance().into()
}

fn has_root(&self) -> When {
Expand Down Expand Up @@ -758,12 +758,12 @@ impl<'t> Program<'t> for Any<'t> {
self.program.captures(path.as_ref()).map(From::from)
}

fn depth(&self) -> TokenVariance<Depth> {
self.tree.as_ref().as_token().variance()
fn depth(&self) -> DepthVariance {
self.tree.as_ref().as_token().variance().into()
}

fn text(&self) -> TokenVariance<Text<'t>> {
self.tree.as_ref().as_token().variance()
fn text(&self) -> TextVariance<'t> {
self.tree.as_ref().as_token().variance().into()
}

fn has_root(&self) -> When {
Expand Down
81 changes: 78 additions & 3 deletions src/query.rs
@@ -1,10 +1,85 @@
use crate::diagnostics::Span;
//! [`Program`] diagnostic and inspection types.
//!
//! [`Program`]: crate::Program

use std::borrow::Cow;

use crate::token::{Depth, Text, TokenVariance};

pub use crate::diagnostics::{LocatedError, Span};
pub use crate::token::{
BoundedVariantRange, Boundedness, Depth, Invariant, Text, TokenVariance, UnitBound, Variance,
VariantRange,
BoundedVariantRange, Boundedness, NonZeroBound, NonZeroLower, NonZeroUpper, VariantRange,
};

// TODO: `VariantRange` is a complex type composition that requires many re-exported types. Define
// a simpler local type if possible.
pub type DepthVariance = Variance<usize, VariantRange>;
pub type TextVariance<'t> = Variance<Cow<'t, str>, ()>;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Variance<T, B> {
Invariant(T),
Variant(B),
}

impl<T, B> Variance<T, B> {
pub fn invariant(self) -> Option<T> {
match self {
Variance::Invariant(invariance) => Some(invariance),
_ => None,
}
}

pub fn variant(self) -> Option<B> {
match self {
Variance::Variant(variance) => Some(variance),
_ => None,
}
}

pub fn as_ref(&self) -> Variance<&T, &B> {
match self {
Variance::Invariant(ref invariance) => Variance::Invariant(invariance),
Variance::Variant(ref variance) => Variance::Variant(variance),
}
}

pub fn is_invariant(&self) -> bool {
matches!(self, Variance::Invariant(_))
}

pub fn is_variant(&self) -> bool {
matches!(self, Variance::Variant(_))
}
}

impl<'t> From<TextVariance<'t>> for Option<Cow<'t, str>> {
fn from(text: TextVariance<'t>) -> Self {
match text {
TextVariance::Invariant(text) => Some(text),
_ => None,
}
}
}

impl<'t> From<TokenVariance<Text<'t>>> for TextVariance<'t> {
fn from(text: TokenVariance<Text<'t>>) -> Self {
match text {
TokenVariance::Invariant(text) => TextVariance::Invariant(text.to_string()),
TokenVariance::Variant(_) => TextVariance::Variant(()),
}
}
}

impl From<TokenVariance<Depth>> for DepthVariance {
fn from(depth: TokenVariance<Depth>) -> Self {
match depth {
TokenVariance::Invariant(depth) => DepthVariance::Invariant(depth.into()),
TokenVariance::Variant(bounds) => DepthVariance::Variant(bounds),
}
}
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum When {
Always,
Expand Down
5 changes: 3 additions & 2 deletions src/token/mod.rs
Expand Up @@ -22,9 +22,10 @@ use crate::{StrExt as _, PATHS_ARE_CASE_INSENSITIVE};

pub use crate::token::parse::{parse, ParseError, ROOT_SEPARATOR_EXPRESSION};
pub use crate::token::variance::bound::{
BoundedVariantRange, Boundedness, NaturalRange, VariantRange,
BoundedVariantRange, Boundedness, NaturalRange, NonZeroBound, NonZeroLower, NonZeroUpper,
VariantRange,
};
pub use crate::token::variance::invariant::{Breadth, Depth, Invariant, Size, Text, UnitBound};
pub use crate::token::variance::invariant::{Breadth, Depth, Invariant, Size, Text};
pub use crate::token::variance::{TokenVariance, Variance};

// TODO: Tree representations of expressions are intrusive and only differ in their annotations.
Expand Down
12 changes: 6 additions & 6 deletions src/token/variance/bound.rs
Expand Up @@ -169,14 +169,14 @@ impl NaturalRange {
Self::from_closed_and_open(lower.into_usize(), upper.into_usize())
}

pub fn lower(&self) -> Lower<NaturalBound> {
pub fn lower(&self) -> NaturalLower {
match self {
Variance::Invariant(ref n) => NaturalBound::from(*n).into_lower(),
Variance::Variant(ref range) => range.lower().map(Variance::Variant),
}
}

pub fn upper(&self) -> Upper<NaturalBound> {
pub fn upper(&self) -> NaturalUpper {
match self {
Variance::Invariant(ref n) => NaturalBound::from(*n).into_upper(),
Variance::Variant(ref range) => range.upper().map(Variance::Variant),
Expand Down Expand Up @@ -304,13 +304,13 @@ impl From<usize> for NonZeroBound {
}

impl VariantRange {
pub fn lower(&self) -> Lower<NonZeroBound> {
pub fn lower(&self) -> NonZeroLower {
self.as_ref()
.bounded()
.map_or_else(|| Unbounded.into_lower(), BoundedVariantRange::lower)
}

pub fn upper(&self) -> Upper<NonZeroBound> {
pub fn upper(&self) -> NonZeroUpper {
self.as_ref()
.bounded()
.map_or_else(|| Unbounded.into_upper(), BoundedVariantRange::upper)
Expand Down Expand Up @@ -564,7 +564,7 @@ impl BoundedVariantRange {
}
}

pub fn lower(&self) -> Lower<NonZeroBound> {
pub fn lower(&self) -> NonZeroLower {
use BoundedVariantRange::{Both, Lower, Upper};

match self {
Expand All @@ -574,7 +574,7 @@ impl BoundedVariantRange {
.into_lower()
}

pub fn upper(&self) -> Upper<NonZeroBound> {
pub fn upper(&self) -> NonZeroUpper {
use BoundedVariantRange::{Both, Lower, Upper};

match self {
Expand Down
7 changes: 2 additions & 5 deletions src/walk/behavior.rs
Expand Up @@ -210,15 +210,12 @@ impl DepthBehavior {
}
}

pub fn bounded_with_depth_variance(
pub fn bounded_at_depth_variance(
min: impl Into<Option<usize>>,
max: impl Into<Option<usize>>,
depth: TokenVariance<Depth>,
) -> Option<Self> {
let lower = depth
.map_invariant(From::from)
.map_variant(|bound| bound.lower().into_usize())
.into_inner();
let lower = depth.map_invariant(usize::from).lower().into_usize();
let translation = move |depth: Option<usize>| -> Result<Option<usize>, ()> {
depth
.map(|depth| depth.checked_add(lower).ok_or(()))
Expand Down

0 comments on commit e8e03ab

Please sign in to comment.