Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
7748068be7 Start creating Separated2 type for easier manipulation 2022-11-21 17:47:26 +01:00
3 changed files with 163 additions and 0 deletions

View file

@ -4,4 +4,5 @@ mod expr;
mod field; mod field;
mod lit; mod lit;
mod program; mod program;
mod table_constr;
mod var; mod var;

View file

@ -1,4 +1,7 @@
use std::mem;
use crate::ast::Separated; use crate::ast::Separated;
use crate::span::Span;
impl<E, S1, S2> Separated<E, S1, S2> { impl<E, S1, S2> Separated<E, S1, S2> {
pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) {
@ -34,3 +37,145 @@ impl<E, S1, S2> Separated<E, S1, S2> {
} }
} }
} }
/// A version of [`Separated`] that includes its leading and trailing
/// whitespace.
enum Separated2<E, S> {
// In theory, all of the second space would've already been consumed by the
// first space parser, but we still need to keep track of it because I
// haven't yet found a nicer way to model this data.
Empty(S, S, Span),
NonEmpty {
elems: Vec<(S, E, S)>,
trailing: Option<S>,
span: Span,
},
}
impl<E, S> Separated2<E, S> {
pub fn from_separated(before: S, separated: Separated<E, (S, S), S>, after: S) -> Self {
match separated {
Separated::Empty(span) => Self::Empty(before, after, span),
Separated::NonEmpty {
first_elem,
last_elems,
trailing,
span,
} => {
let mut next_before = before;
let mut next_elem = first_elem;
let mut elems = vec![];
for ((prev_after, this_before), elem) in last_elems {
elems.push((next_before, next_elem, prev_after));
next_before = this_before;
next_elem = elem;
}
let trailing = if let Some(trailing) = trailing {
elems.push((next_before, next_elem, trailing));
Some(after)
} else {
elems.push((next_before, next_elem, after));
None
};
Self::NonEmpty {
elems,
trailing,
span,
}
}
}
}
pub fn into_separated(self) -> (S, Separated<E, (S, S), S>, S) {
match self {
Self::Empty(before, after, span) => (before, Separated::Empty(span), after),
Self::NonEmpty {
elems,
trailing,
span,
} => {
let mut elems = elems.into_iter();
let (before, first_elem, mut after) = elems
.next()
.expect("non-empty Separated2 must have elements");
let mut last_elems = vec![];
for (this_before, elem, this_after) in elems {
last_elems.push(((after, this_before), elem));
after = this_after;
}
let trailing = if let Some(mut trailing) = trailing {
mem::swap(&mut after, &mut trailing);
Some(trailing)
} else {
None
};
let separated = Separated::NonEmpty {
first_elem,
last_elems,
trailing,
span,
};
(before, separated, after)
}
}
}
}
pub enum Decision<A, B> {
Keep(A),
Remove(B),
}
impl<E, S> Separated2<E, S> {
pub fn remove<E1, E2>(
self,
decide: impl Fn(E) -> Decision<E1, E2>,
) -> (Separated2<E1, S>, Vec<(S, E2, S)>) {
match self {
Self::Empty(s0, s1, span) => (Separated2::Empty(s0, s1, span), vec![]),
Self::NonEmpty {
elems,
trailing,
span,
} => {
let mut kept = vec![];
let mut removed = vec![];
for (s0, elem, s1) in elems {
match decide(elem) {
Decision::Keep(elem) => kept.push((s0, elem, s1)),
Decision::Remove(elem) => removed.push((s0, elem, s1)),
}
}
todo!()
}
}
}
}
pub struct Removed<A, B, S> {
before: S,
separated: Separated<A, (S, S), S>,
after: S,
removed: Vec<(S, B, S)>,
}
impl<E, S> Separated<E, (S, S), S> {
pub fn remove_elems<E2, E3>(
self,
before: S,
after: S,
separate: impl Fn(E) -> Decision<E2, E3>,
) -> Removed<E2, E3, S> {
todo!()
}
}

View file

@ -0,0 +1,17 @@
use crate::ast::{Expr, Lit, TableConstr, TableLit};
impl TableConstr {
pub fn desugar(self) -> (Expr, bool) {
let Self {
s0,
elems,
s1,
span,
} = self;
// `{ s0 elems s1 }`
// -> `'{ raw: '{ s0 lit_elems s1 } }` surrounded by 'set calls
todo!()
}
}