-
Notifications
You must be signed in to change notification settings - Fork 8
/
mod.rs
149 lines (118 loc) · 3.86 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
mod natural;
mod separation;
mod text;
use std::num::NonZeroUsize;
use crate::token::variance::bound::{BoundedVariantRange, Boundedness, OpenedUpperBound};
use crate::token::variance::ops::{Conjunction, Disjunction, Product};
use crate::token::variance::TokenVariance;
pub use crate::token::variance::invariant::natural::{Depth, DepthTerm, Size};
pub use crate::token::variance::invariant::separation::{
BoundaryTerm, Finalize, SeparatedTerm, Termination,
};
pub use crate::token::variance::invariant::text::{IntoNominalText, IntoStructuralText, Text};
pub type InvariantBound<T> = <T as BoundedVariance>::Bound;
pub trait BoundedVariance {
type Bound;
}
pub trait Zero {
fn zero() -> Self;
}
pub trait One {
fn one() -> Self;
}
// TODO: Recombine these traits? Or rename them? It's confusing that this has a bound on
// `InvariantTerm`, but its `Term` does not!
pub trait Invariant: InvariantTerm + Sized {
type Term: Zero;
fn finalize(term: Self::Term) -> TokenVariance<Self>;
}
pub trait InvariantTerm: BoundedVariance + Zero + Sized {
fn bound(lhs: Self, rhs: Self) -> Boundedness<Self::Bound>;
fn into_lower_bound(self) -> Boundedness<Self::Bound>;
}
// Breadth is the maximum size (UTF-8 bytes) of component text in a glob expression. For example,
// the breadth of `{a/,a/b/}<c/d:2>` is two (bytes).
//
// Composition is not implemented for breadth and it is only queried from leaf tokens. No values
// are associated with its invariant nor bounds. Breadth is probably the least interesting and yet
// most difficult quantity to compute. Determining correct breadth values likely involves:
//
// - Complex terms that support both running sums and running maximums across boundaries.
// - Searches from the start and end of sub-trees in repetitions, where terminals may interact.
// Consider `<a/b:2>` vs. `<a/b/:2>`, which have breadths of two and one, respectively.
// - Potentially large sets for bounds. Ranges lose too much information, in particular information
// about boundaries when composing terms.
//
// There are likely other difficult composition problems. As such, breadth is only implemented as
// much as needed. Any requirements on more complete breadth computations ought to be considered
// carefully.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Breadth;
impl Breadth {
pub const fn new() -> Self {
Breadth
}
}
impl BoundedVariance for Breadth {
type Bound = ();
}
impl Zero for Breadth {
fn zero() -> Self {
Breadth
}
}
impl Invariant for Breadth {
type Term = TokenVariance<Self>;
fn finalize(term: Self::Term) -> TokenVariance<Self> {
term
}
}
impl InvariantTerm for Breadth {
fn bound(_: Self, _: Self) -> Boundedness<Self::Bound> {
().into()
}
fn into_lower_bound(self) -> Boundedness<Self::Bound> {
().into()
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct UnitBound;
impl<T> Conjunction<T> for UnitBound {
type Output = Self;
fn conjunction(self, _: T) -> Self::Output {
self
}
}
impl Disjunction for UnitBound {
type Output = Boundedness<Self>;
fn disjunction(self, _: Self) -> Self::Output {
self.into()
}
}
impl From<()> for UnitBound {
fn from(_: ()) -> Self {
UnitBound
}
}
impl From<BoundedVariantRange> for UnitBound {
fn from(_: BoundedVariantRange) -> Self {
UnitBound
}
}
impl OpenedUpperBound for UnitBound {
fn opened_upper_bound(self) -> Boundedness<Self> {
UnitBound.into()
}
}
impl Product<BoundedVariantRange> for UnitBound {
type Output = Boundedness<Self>;
fn product(self, _: BoundedVariantRange) -> Self::Output {
self.into()
}
}
impl Product<NonZeroUsize> for Boundedness<UnitBound> {
type Output = Self;
fn product(self, _: NonZeroUsize) -> Self::Output {
self
}
}