From 7748068be7bda40978cde549cea9e7a1aab899a8 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 17:47:26 +0100 Subject: [PATCH] Start creating Separated2 type for easier manipulation --- src/desugar.rs | 1 + src/desugar/basic.rs | 145 ++++++++++++++++++++++++++++++++++++ src/desugar/table_constr.rs | 17 +++++ 3 files changed, 163 insertions(+) create mode 100644 src/desugar/table_constr.rs diff --git a/src/desugar.rs b/src/desugar.rs index 7402709..db66687 100644 --- a/src/desugar.rs +++ b/src/desugar.rs @@ -4,4 +4,5 @@ mod expr; mod field; mod lit; mod program; +mod table_constr; mod var; diff --git a/src/desugar/basic.rs b/src/desugar/basic.rs index ba2fde0..c4d8a51 100644 --- a/src/desugar/basic.rs +++ b/src/desugar/basic.rs @@ -1,4 +1,7 @@ +use std::mem; + use crate::ast::Separated; +use crate::span::Span; impl Separated { pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { @@ -34,3 +37,145 @@ impl Separated { } } } + +/// A version of [`Separated`] that includes its leading and trailing +/// whitespace. +enum Separated2 { + // 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, + span: Span, + }, +} + +impl Separated2 { + pub fn from_separated(before: S, separated: Separated, 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, 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 { + Keep(A), + Remove(B), +} + +impl Separated2 { + pub fn remove( + self, + decide: impl Fn(E) -> Decision, + ) -> (Separated2, 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 { + before: S, + separated: Separated, + after: S, + removed: Vec<(S, B, S)>, +} + +impl Separated { + pub fn remove_elems( + self, + before: S, + after: S, + separate: impl Fn(E) -> Decision, + ) -> Removed { + todo!() + } +} diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs new file mode 100644 index 0000000..1fd7e62 --- /dev/null +++ b/src/desugar/table_constr.rs @@ -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!() + } +}