Skip to content

Commit

Permalink
Generalize Composition.
Browse files Browse the repository at this point in the history
  • Loading branch information
olson-sean-k committed Feb 8, 2024
1 parent dca4bb0 commit e5754fa
Showing 1 changed file with 79 additions and 46 deletions.
125 changes: 79 additions & 46 deletions src/token/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,44 +124,83 @@ impl From<bool> for When {
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Composition<T> {
Conjunctive(T),
Disjunctive(T),
pub enum Composition<C, D> {
Conjunctive(C),
Disjunctive(D),
}

impl<T> Composition<T> {
pub fn into_inner(self) -> T {
pub type TokenComposition<T> = Composition<T, T>;

impl<C, D> Composition<C, D> {
pub fn map_conjunctive<T, F>(self, f: F) -> Composition<T, D>
where
F: FnOnce(C) -> T,
{
match self {
Composition::Conjunctive(inner) | Composition::Disjunctive(inner) => inner,
Composition::Conjunctive(inner) => Composition::Conjunctive(f(inner)),
Composition::Disjunctive(inner) => Composition::Disjunctive(inner),
}
}

pub fn map<U, F>(self, f: F) -> Composition<U>
pub fn map_disjunctive<T, F>(self, f: F) -> Composition<C, T>
where
F: FnOnce(T) -> U,
F: FnOnce(D) -> T,
{
match self {
Composition::Conjunctive(inner) => Composition::Conjunctive(f(inner)),
Composition::Conjunctive(inner) => Composition::Conjunctive(inner),
Composition::Disjunctive(inner) => Composition::Disjunctive(f(inner)),
}
}

pub fn conjunctive(self) -> Option<T> {
pub fn conjunctive(self) -> Option<C> {
match self {
Composition::Conjunctive(inner) => Some(inner),
_ => None,
}
}

pub fn disjunctive(self) -> Option<T> {
pub fn disjunctive(self) -> Option<D> {
match self {
Composition::Disjunctive(inner) => Some(inner),
_ => None,
}
}

pub fn as_ref(&self) -> Composition<&C, &D> {
match self {
Composition::Conjunctive(ref inner) => Composition::Conjunctive(inner),
Composition::Disjunctive(ref inner) => Composition::Disjunctive(inner),
}
}
}

impl<T> Composition<T, T> {
pub fn into_inner(self) -> T {
match self {
Composition::Conjunctive(inner) | Composition::Disjunctive(inner) => inner,
}
}

pub fn map<U, F>(self, f: F) -> Composition<U, U>
where
F: FnOnce(T) -> U,
{
match self {
Composition::Conjunctive(inner) => Composition::Conjunctive(f(inner)),
Composition::Disjunctive(inner) => Composition::Disjunctive(f(inner)),
}
}

pub fn get(&self) -> &T {
AsRef::as_ref(self)
}

pub fn get_mut(&mut self) -> &mut T {
AsMut::as_mut(self)
}
}

impl<T> AsMut<T> for Composition<T> {
impl<T> AsMut<T> for Composition<T, T> {
fn as_mut(&mut self) -> &mut T {
match self {
Composition::Conjunctive(ref mut inner) => inner,
Expand All @@ -170,7 +209,7 @@ impl<T> AsMut<T> for Composition<T> {
}
}

impl<T> AsRef<T> for Composition<T> {
impl<T> AsRef<T> for Composition<T, T> {
fn as_ref(&self) -> &T {
match self {
Composition::Conjunctive(ref inner) => inner,
Expand Down Expand Up @@ -354,7 +393,7 @@ impl<'t, A> Token<'t, A> {
}
}

pub fn tokens(&self) -> Option<Composition<&[Self]>> {
pub fn tokens(&self) -> Option<TokenComposition<&[Self]>> {
self.as_branch().map(BranchKind::tokens)
}

Expand Down Expand Up @@ -397,7 +436,7 @@ impl<'t, A> Token<'t, A> {
}
}

pub fn composition(&self) -> Composition<()> {
pub fn composition(&self) -> TokenComposition<()> {
self.as_branch()
.map_or(Composition::Conjunctive(()), |branch| branch.composition())
}
Expand Down Expand Up @@ -530,9 +569,9 @@ impl<'t, A> Token<'t, A> {
// NOTE: False positives in this function may cause logic errors and are completely
// unacceptable. The discovery of a false positive here is likely a serious bug.
pub fn is_exhaustive(&self) -> bool {
type TokenComposition<'i, 't, A> = Composition<TokenSum<'i, 't, A>>;
type TokenNode<'i, 't, A> = TokenComposition<TokenSum<'i, 't, A>>;

impl<'i, 't, A> TokenComposition<'i, 't, A> {
impl<'i, 't, A> TokenNode<'i, 't, A> {
// NOTE: This differs from the `VarianceFold` implementations for branch tokens.
fn fold(&mut self, depth: VarianceOf<Depth>) {
use Bound::Unbounded;
Expand Down Expand Up @@ -569,7 +608,7 @@ impl<'t, A> Token<'t, A> {
fn finalize(self, parent: Option<&mut Self>) -> Result<VarianceOf<Depth>, ()> {
use Variance::{Invariant, Variant};

let sum = self.as_ref();
let sum = self.get();
let term = sum.branch.map_or(sum.depth, |branch| match branch {
branch @ BranchKind::Repetition(_) => match sum.depth {
// When folding a term into a repetition, only finalize variant terms
Expand Down Expand Up @@ -597,7 +636,7 @@ impl<'t, A> Token<'t, A> {
}
}

impl<'i, 't, A> From<&'i BranchKind<'t, A>> for TokenComposition<'i, 't, A> {
impl<'i, 't, A> From<&'i BranchKind<'t, A>> for TokenNode<'i, 't, A> {
fn from(branch: &'i BranchKind<'t, A>) -> Self {
let sum = TokenSum {
depth: Variance::identity(),
Expand All @@ -618,13 +657,13 @@ impl<'t, A> Token<'t, A> {
}
}

impl<'i, 't, A> From<&'i Token<'t, A>> for TokenComposition<'i, 't, A> {
impl<'i, 't, A> From<&'i Token<'t, A>> for TokenNode<'i, 't, A> {
fn from(token: &'i Token<'t, A>) -> Self {
if let Some(branch) = token.as_branch() {
Self::from(branch)
}
else {
TokenComposition::Conjunctive(TokenSum {
TokenNode::Conjunctive(TokenSum {
depth: Variance::identity(),
branch: None,
tokens: vec![token],
Expand Down Expand Up @@ -692,17 +731,17 @@ impl<'t, A> Token<'t, A> {
}
}

let mut tokens = vec![TokenComposition::from(self)];
'composition: while let Some(mut composition) = tokens.pop() {
eprintln!("Popped composition: {}", display_sum(composition.as_ref()));
'sum: while let Some(token) = composition.as_mut().tokens.pop() {
let mut tokens = vec![TokenNode::from(self)];
'node: while let Some(mut node) = tokens.pop() {
eprintln!("Popped node: {}", display_sum(node.get()));
'sum: while let Some(token) = node.as_mut().tokens.pop() {
eprintln!("Popped token: {}", display_token(&token));
match token.topology() {
TokenTopology::Branch(branch) => {
eprintln!("Pushing composition and token.");
tokens.push(composition);
eprintln!("Pushing node and token.");
tokens.push(node);
tokens.push(branch.into());
continue 'composition;
continue 'node;
},
TokenTopology::Leaf(leaf) => {
if let None | Some(Boundary::Component) = token.boundary() {
Expand All @@ -715,39 +754,33 @@ impl<'t, A> Token<'t, A> {
breadth,
text,
);
let sum = composition.as_mut();
let sum = node.as_mut();
if sum
.depth
.variant()
.map_or(true, |bound| bound.upper().into_bound().is_bounded())
{
eprintln!(
"Composition has bounded depth: {:?}. Resetting.",
sum.depth
"Node has bounded depth: {:?}. Resetting.",
sum.depth,
);
sum.reset();
}
eprintln!(
"Composition is now: {}",
display_sum(composition.as_ref())
);
eprintln!("Node is now: {}", display_sum(node.get()));
break 'sum;
}
eprintln!("Token has unbounded breadth and text.");
}
let depth = leaf.term();
eprintln!("Folding token depth into composition: {:?}", depth);
composition.fold(depth);
eprintln!("Composition is now: {}", display_sum(composition.as_ref()));
eprintln!("Folding token depth into node: {:?}", depth);
node.fold(depth);
eprintln!("Node is now: {}", display_sum(node.get()));
},
}
}
eprintln!("Stopped or exhausted tokens in composition. Finalizing.");
if let Ok(term) = composition.finalize(tokens.last_mut()) {
eprintln!(
"Exhausted compositions in tree. Exiting.\n\tDepth: {:?}",
term
);
eprintln!("Stopped or exhausted tokens in node. Finalizing.");
if let Ok(term) = node.finalize(tokens.last_mut()) {
eprintln!("Exhausted nodes in tree. Exiting.\n\tDepth: {:?}", term);
//return term.is_unbounded();
return term
.variant()
Expand Down Expand Up @@ -954,7 +987,7 @@ impl<'t, A> BranchKind<'t, A> {
}
}

pub fn tokens(&self) -> Composition<&[Token<'t, A>]> {
pub fn tokens(&self) -> TokenComposition<&[Token<'t, A>]> {
use BranchKind::{Alternation, Concatenation, Repetition};
use Composition::{Conjunctive, Disjunctive};

Expand All @@ -965,7 +998,7 @@ impl<'t, A> BranchKind<'t, A> {
}
}

pub fn composition(&self) -> Composition<()> {
pub fn composition(&self) -> TokenComposition<()> {
self.tokens().map(|_| ())
}

Expand Down

0 comments on commit e5754fa

Please sign in to comment.