From 7748068be7bda40978cde549cea9e7a1aab899a8 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 17:47:26 +0100 Subject: [PATCH 01/29] 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!() + } +} From a1867fdc4e43901fb733af216e7acdcbe3d20ff2 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 22:49:40 +0100 Subject: [PATCH 02/29] Add BoundedSeparated with parser and printer This type should be able to replace Separated (with a bit of effort). The hope is that this type is a better representation for table-like syntax with optional trailing delimiter that will let me remove_map elements without too much difficulty. This is necessary for desugaring table constructors. --- src/ast/basic.rs | 13 +++++++++++++ src/parser/basic.rs | 42 +++++++++++++++++++++++++++++++++++++++++- src/pretty/basic.rs | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/ast/basic.rs b/src/ast/basic.rs index b9e5df0..9790f8c 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -96,3 +96,16 @@ impl HasSpan for Separated { } } } + +#[derive(Debug, Clone)] +pub struct BoundedSeparated { + pub elems: Vec<(Space, E, Space)>, + pub trailing: Option, + pub span: Span, +} + +impl HasSpan for BoundedSeparated { + fn span(&self) -> Span { + self.span + } +} diff --git a/src/parser/basic.rs b/src/parser/basic.rs index 2a65c68..300e953 100644 --- a/src/parser/basic.rs +++ b/src/parser/basic.rs @@ -3,7 +3,7 @@ use chumsky::prelude::*; use chumsky::text::Character; -use crate::ast::{Ident, Line, Separated, Space}; +use crate::ast::{BoundedSeparated, Ident, Line, Separated, Space}; use crate::span::Span; pub type Error = Simple; @@ -82,3 +82,43 @@ pub fn separated_by( }) .boxed() } + +pub fn bounded_separated( + space: impl Parser + Clone + 'static, + start: impl Parser + 'static, + end: impl Parser + 'static, + separator: impl Parser + 'static, + elem: impl Parser + Clone + 'static, +) -> EParser> { + start + .ignore_then(space.clone()) + .then( + elem.clone() + .then(space.clone()) + .then_ignore(separator) + .then(space.clone()) + .repeated(), + ) + .then(elem.then(space).or_not()) + .then_ignore(end) + .map_with_span(|((s0, first_elems), last_elem), span| { + let mut space_before_elem = s0; + let mut elems = vec![]; + for ((elem, s1), s2) in first_elems { + elems.push((space_before_elem, elem, s1)); + space_before_elem = s2; + } + let trailing = if let Some((elem, s1)) = last_elem { + elems.push((space_before_elem, elem, s1)); + None + } else { + Some(space_before_elem) + }; + BoundedSeparated { + elems, + trailing, + span, + } + }) + .boxed() +} diff --git a/src/pretty/basic.rs b/src/pretty/basic.rs index b6812b0..5d4ae8e 100644 --- a/src/pretty/basic.rs +++ b/src/pretty/basic.rs @@ -1,6 +1,8 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; -use crate::ast::{Ident, Separated}; +use crate::ast::{BoundedSeparated, Ident, Separated}; + +use super::NEST_DEPTH; impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Ident { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { @@ -45,3 +47,32 @@ impl Separated { } } } + +impl BoundedSeparated { + pub fn pretty<'a, D, FE>( + self, + allocator: &'a D, + start: DocBuilder<'a, D>, + end: DocBuilder<'a, D>, + separator: DocBuilder<'a, D>, + elem_pretty: FE, + ) -> DocBuilder<'a, D> + where + D: DocAllocator<'a>, + D::Doc: Clone, + FE: Fn(E) -> DocBuilder<'a, D>, + { + allocator + .intersperse( + self.elems + .into_iter() + .map(|(s0, elem, s1)| allocator.line().append(elem_pretty(elem))), + separator.clone(), + ) + .append(self.trailing.map(|s| separator)) + .nest(NEST_DEPTH) + .append(allocator.line()) + .enclose(start, end) + .group() + } +} From e3fa3500d4b4fb7638fda34477b26f32d58f14f7 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 23:37:36 +0100 Subject: [PATCH 03/29] Switch TableLit and Program to BoundedSeparated --- src/ast/lit.rs | 11 +++-------- src/ast/program.rs | 8 +++----- src/desugar/basic.rs | 25 ++++++++++++++++++++++++- src/desugar/call.rs | 19 ++++++++----------- src/desugar/lit.rs | 17 ++--------------- src/desugar/program.rs | 20 ++++---------------- src/parser/basic.rs | 8 ++++---- src/parser/lit.rs | 24 +++++++++--------------- src/parser/program.rs | 22 +++++++++------------- src/pretty/call.rs | 6 +++++- src/pretty/expr.rs | 6 +++++- src/pretty/field.rs | 6 +++++- src/pretty/func_def.rs | 6 +++++- src/pretty/lit.rs | 38 ++++++++++++++++++++++---------------- src/pretty/program.rs | 35 ++++++++++++++++++----------------- src/pretty/table_constr.rs | 12 ++++++++++-- src/pretty/table_destr.rs | 6 +++++- src/pretty/var.rs | 6 +++++- 18 files changed, 146 insertions(+), 129 deletions(-) diff --git a/src/ast/lit.rs b/src/ast/lit.rs index 63ced41..61bb9e1 100644 --- a/src/ast/lit.rs +++ b/src/ast/lit.rs @@ -3,7 +3,7 @@ use std::fmt; use crate::builtin::Builtin; use crate::span::{HasSpan, Span}; -use super::{Expr, Ident, Separated, Space}; +use super::{BoundedSeparated, Expr, Ident, Space}; #[derive(Clone)] pub enum NumLitStr { @@ -129,16 +129,11 @@ impl HasSpan for TableLitElem { /// /// Structure: `'{ s0 elems s1 }` #[derive(Debug, Clone)] -pub struct TableLit { - pub s0: Space, - pub elems: Separated, - pub s1: Space, - pub span: Span, -} +pub struct TableLit(pub BoundedSeparated); impl HasSpan for TableLit { fn span(&self) -> Span { - self.span + self.0.span() } } diff --git a/src/ast/program.rs b/src/ast/program.rs index 2020225..a77abf4 100644 --- a/src/ast/program.rs +++ b/src/ast/program.rs @@ -1,6 +1,6 @@ use crate::span::{HasSpan, Span}; -use super::{Expr, Separated, Space, TableLitElem}; +use super::{BoundedSeparated, Expr, Space, TableLitElem}; #[derive(Debug, Clone)] pub enum Program { @@ -12,12 +12,10 @@ pub enum Program { span: Span, }, - /// Structure: `s0 module s1 elems s2` + /// Structure: `s0 module elems` Module { s0: Space, - s1: Space, - elems: Separated, - s2: Space, + elems: BoundedSeparated, span: Span, }, } diff --git a/src/desugar/basic.rs b/src/desugar/basic.rs index ba2fde0..1b0f4fc 100644 --- a/src/desugar/basic.rs +++ b/src/desugar/basic.rs @@ -1,4 +1,4 @@ -use crate::ast::Separated; +use crate::ast::{BoundedSeparated, Separated}; impl Separated { pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { @@ -34,3 +34,26 @@ impl Separated { } } } + +impl BoundedSeparated { + pub fn desugar(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { + let mut desugared = false; + let mut elems = vec![]; + for (s0, elem, s1) in self.elems { + if desugared { + elems.push((s0, elem, s1)); + } else { + let (elem, elem_desugared) = desugar_elem(elem); + desugared = desugared || elem_desugared; + elems.push((s0, elem, s1)); + } + } + + let new = Self { + elems, + trailing: self.trailing, + span: self.span, + }; + (new, desugared) + } +} diff --git a/src/desugar/call.rs b/src/desugar/call.rs index 690f99e..70cd2c4 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -1,4 +1,4 @@ -use crate::ast::{Call, Expr, Ident, Lit, Separated, Space, TableLit, TableLitElem}; +use crate::ast::{BoundedSeparated, Call, Expr, Ident, Lit, Space, TableLit, TableLitElem}; // TODO Add span for just the parentheses to ast, or limit span to parentheses @@ -29,18 +29,15 @@ impl Call { value: arg, span, }; - let elems = Separated::NonEmpty { - first_elem: call, - last_elems: vec![((Space::empty(span), Space::empty(span)), arg)], + let elems = vec![ + (s0, call, Space::empty(span)), + (Space::empty(span), arg, s2), + ]; + let new = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { + elems, trailing: None, span, - }; - let new = Expr::Lit(Lit::Table(TableLit { - s0, - elems, - s1: s2, - span, - })); + }))); (new, true) } diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs index 348c3c7..4f32a38 100644 --- a/src/desugar/lit.rs +++ b/src/desugar/lit.rs @@ -31,21 +31,8 @@ impl TableLitElem { impl TableLit { pub fn desugar(self) -> (Self, bool) { - let Self { - s0, - elems, - s1, - span, - } = self; - - let (elems, desugared) = elems.desugar_elem(|e| e.desugar()); - let new = Self { - s0, - elems, - s1, - span, - }; - (new, desugared) + let (elems, desugared) = self.0.desugar(|e| e.desugar()); + (Self(elems), desugared) } } diff --git a/src/desugar/program.rs b/src/desugar/program.rs index 7960cbc..50b11eb 100644 --- a/src/desugar/program.rs +++ b/src/desugar/program.rs @@ -9,24 +9,12 @@ impl Program { (new, desugared) } - Self::Module { - s0, - s1, - elems, - s2, - span, - } => { - // `s0 module s1 elems s2` - // -> `s0 '{ s1 elems s2 } empty` - let table = TableLit { - s0: s1, - elems, - s1: s2, - span, - }; + Self::Module { s0, elems, span } => { + // `s0 module elems` + // -> `s0 table` let new = Self::Expr { s0, - expr: Expr::Lit(Lit::Table(table)), + expr: Expr::Lit(Lit::Table(TableLit(elems))), s1: Space::empty(span), span, }; diff --git a/src/parser/basic.rs b/src/parser/basic.rs index 300e953..2c8254d 100644 --- a/src/parser/basic.rs +++ b/src/parser/basic.rs @@ -83,11 +83,11 @@ pub fn separated_by( .boxed() } -pub fn bounded_separated( +pub fn bounded_separated( space: impl Parser + Clone + 'static, - start: impl Parser + 'static, - end: impl Parser + 'static, - separator: impl Parser + 'static, + start: impl Parser + 'static, + end: impl Parser + 'static, + separator: impl Parser + 'static, elem: impl Parser + Clone + 'static, ) -> EParser> { start diff --git a/src/parser/lit.rs b/src/parser/lit.rs index 0bdf12a..6b09982 100644 --- a/src/parser/lit.rs +++ b/src/parser/lit.rs @@ -7,7 +7,7 @@ use crate::ast::{ }; use crate::builtin::Builtin; -use super::basic::{separated_by, EParser, Error}; +use super::basic::{bounded_separated, EParser, Error}; fn builtin_lit() -> impl Parser { just('\'').ignore_then(choice(( @@ -154,20 +154,14 @@ fn table_lit( space: EParser, table_lit_elem: EParser, ) -> impl Parser { - let separator = space.clone().then_ignore(just(',')).then(space.clone()); - let trailing_separator = space.clone().then_ignore(just(',')); - - space - .clone() - .then(separated_by(table_lit_elem, separator, trailing_separator)) - .then(space) - .delimited_by(just("'{"), just('}')) - .map_with_span(|((s0, elems), s1), span| TableLit { - s0, - elems, - s1, - span, - }) + bounded_separated( + space, + just("'{").to(()), + just('}').to(()), + just(',').to(()), + table_lit_elem, + ) + .map(TableLit) } pub fn lit(space: EParser, table_lit_elem: EParser) -> EParser { diff --git a/src/parser/program.rs b/src/parser/program.rs index 0b46f94..96c3cab 100644 --- a/src/parser/program.rs +++ b/src/parser/program.rs @@ -4,7 +4,7 @@ use chumsky::prelude::*; use crate::ast::{Expr, Program, Space, TableLitElem}; -use super::basic::{separated_by, EParser}; +use super::basic::{bounded_separated, EParser}; pub fn program( space: EParser, @@ -17,21 +17,17 @@ pub fn program( .then(space.clone()) .map_with_span(|((s0, expr), s1), span| Program::Expr { s0, expr, s1, span }); - let separator = space.clone().then_ignore(just(',')).then(space.clone()); - let trailing_separator = space.clone().then_ignore(just(',')); let module = space .clone() .then_ignore(text::keyword("module")) - .then(space.clone()) - .then(separated_by(table_lit_elem, separator, trailing_separator)) - .then(space.clone()) - .map_with_span(|(((s0, s1), elems), s2), span| Program::Module { - s0, - s1, - elems, - s2, - span, - }); + .then(bounded_separated( + space, + empty(), + empty(), + just(',').to(()), + table_lit_elem, + )) + .map_with_span(|(s0, elems), span| Program::Module { s0, elems, span }); module.or(lit).boxed() } diff --git a/src/pretty/call.rs b/src/pretty/call.rs index 84d2b5b..6cf26fc 100644 --- a/src/pretty/call.rs +++ b/src/pretty/call.rs @@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::Call; -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Call { +impl<'a, D> Pretty<'a, D> for Call +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Arg { diff --git a/src/pretty/expr.rs b/src/pretty/expr.rs index 7919963..ddf7634 100644 --- a/src/pretty/expr.rs +++ b/src/pretty/expr.rs @@ -22,7 +22,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for BinOp { } } -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Expr { +impl<'a, D> Pretty<'a, D> for Expr +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Lit(lit) => lit.pretty(allocator), diff --git a/src/pretty/field.rs b/src/pretty/field.rs index ce5b28f..eb547f0 100644 --- a/src/pretty/field.rs +++ b/src/pretty/field.rs @@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::Field; -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Field { +impl<'a, D> Pretty<'a, D> for Field +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Access { diff --git a/src/pretty/func_def.rs b/src/pretty/func_def.rs index 6fd8140..dce23e6 100644 --- a/src/pretty/func_def.rs +++ b/src/pretty/func_def.rs @@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::FuncDef; -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for FuncDef { +impl<'a, D> Pretty<'a, D> for FuncDef +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::AnonNoArg { diff --git a/src/pretty/lit.rs b/src/pretty/lit.rs index 45dd034..84f3055 100644 --- a/src/pretty/lit.rs +++ b/src/pretty/lit.rs @@ -2,8 +2,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::{Lit, NumLit, StringLit, StringLitElem, TableLit, TableLitElem}; -use super::NEST_DEPTH; - impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for NumLit { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { allocator.text(format!("{self:?}")) @@ -32,7 +30,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for StringLit { } } -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableLitElem { +impl<'a, D> Pretty<'a, D> for TableLitElem +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Positional(expr) => expr.pretty(allocator), @@ -50,23 +52,27 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableLitElem { } } -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableLit { +impl<'a, D> Pretty<'a, D> for TableLit +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - self.elems - .pretty( - allocator, - |e| allocator.line().append(e.pretty(allocator)), - |(s0, s1)| allocator.text(","), - |s| allocator.text(","), - ) - .nest(NEST_DEPTH) - .append(allocator.line()) - .enclose(allocator.text("'{"), allocator.text("}")) - .group() + self.0.pretty( + allocator, + allocator.text("'{"), + allocator.text("}"), + allocator.text(","), + |e| e.pretty(allocator), + ) } } -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Lit { +impl<'a, D> Pretty<'a, D> for Lit +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Nil(_) => allocator.text("nil"), diff --git a/src/pretty/program.rs b/src/pretty/program.rs index 20c5cb1..1ff7863 100644 --- a/src/pretty/program.rs +++ b/src/pretty/program.rs @@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::Program; -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Program { +impl<'a, D> Pretty<'a, D> for Program +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Expr { @@ -11,22 +15,19 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Program { s1, span: _, } => expr.pretty(allocator), - Self::Module { - s0, - s1, - elems, - s2, - span: _, - } => allocator - .text("module") - .append(allocator.line()) - .append(allocator.line()) - .append(elems.pretty( - allocator, - |e| e.pretty(allocator), - |(s0, s1)| allocator.text(",").append(allocator.line()), - |s| allocator.text(","), - )), + + Self::Module { s0, elems, span: _ } => { + allocator.text("module").append(allocator.line()).append( + allocator + .intersperse( + elems.elems.into_iter().map(|(s0, elem, s1)| { + allocator.line().append(elem.pretty(allocator)) + }), + allocator.text(","), + ) + .append(elems.trailing.map(|s| allocator.text(","))), + ) + } } } } diff --git a/src/pretty/table_constr.rs b/src/pretty/table_constr.rs index 5c9a058..704ab3e 100644 --- a/src/pretty/table_constr.rs +++ b/src/pretty/table_constr.rs @@ -4,7 +4,11 @@ use crate::ast::{TableConstr, TableConstrElem}; use super::NEST_DEPTH; -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableConstrElem { +impl<'a, D> Pretty<'a, D> for TableConstrElem +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Lit(lit) => lit.pretty(allocator), @@ -25,7 +29,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableConstrElem { } } -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableConstr { +impl<'a, D> Pretty<'a, D> for TableConstr +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { self.elems .pretty( diff --git a/src/pretty/table_destr.rs b/src/pretty/table_destr.rs index 50fab7b..795bfa2 100644 --- a/src/pretty/table_destr.rs +++ b/src/pretty/table_destr.rs @@ -38,7 +38,11 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TablePattern { } } -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TableDestr { +impl<'a, D> Pretty<'a, D> for TableDestr +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { // TODO Handle spaces self.local diff --git a/src/pretty/var.rs b/src/pretty/var.rs index a3b5418..662b34e 100644 --- a/src/pretty/var.rs +++ b/src/pretty/var.rs @@ -2,7 +2,11 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::Var; -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Var { +impl<'a, D> Pretty<'a, D> for Var +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { Self::Access { From 0e9cfd67c2b7b8ba28d6a64083d2b360a0516435 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 23:54:40 +0100 Subject: [PATCH 04/29] Switch TablConstr to BoundedSeparated --- src/ast/lit.rs | 2 - src/ast/table_constr.rs | 13 ++----- src/desugar/field.rs | 77 +++++++++++++++++++------------------- src/desugar/var.rs | 46 +++++++++++------------ src/parser/table_constr.rs | 26 +++++-------- src/pretty/table_constr.rs | 20 ++++------ 6 files changed, 82 insertions(+), 102 deletions(-) diff --git a/src/ast/lit.rs b/src/ast/lit.rs index 61bb9e1..ee486ef 100644 --- a/src/ast/lit.rs +++ b/src/ast/lit.rs @@ -126,8 +126,6 @@ impl HasSpan for TableLitElem { } /// `'{ a, foo: b }` -/// -/// Structure: `'{ s0 elems s1 }` #[derive(Debug, Clone)] pub struct TableLit(pub BoundedSeparated); diff --git a/src/ast/table_constr.rs b/src/ast/table_constr.rs index d347ce1..0e16ae6 100644 --- a/src/ast/table_constr.rs +++ b/src/ast/table_constr.rs @@ -1,6 +1,6 @@ use crate::span::{HasSpan, Span}; -use super::{Expr, Separated, Space, TableLitElem}; +use super::{BoundedSeparated, Expr, Space, TableLitElem}; #[derive(Debug, Clone)] pub enum TableConstrElem { @@ -31,18 +31,11 @@ impl HasSpan for TableConstrElem { } /// `{ a, b, foo: c, [d]: e }` -/// -/// Structure: `{ s0 elems s1 }` #[derive(Debug, Clone)] -pub struct TableConstr { - pub s0: Space, - pub elems: Separated, - pub s1: Space, - pub span: Span, -} +pub struct TableConstr(pub BoundedSeparated); impl HasSpan for TableConstr { fn span(&self) -> Span { - self.span + self.0.span() } } diff --git a/src/desugar/field.rs b/src/desugar/field.rs index 7618326..496cd44 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -1,5 +1,5 @@ use crate::ast::{ - Call, Expr, Field, Line, Lit, Separated, Space, StringLit, StringLitElem, TableConstr, + BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, StringLitElem, TableConstr, TableConstrElem, TableLitElem, }; use crate::builtin::Builtin; @@ -17,25 +17,26 @@ impl Field { } => { // ` expr s0 [ s1 index s2 ]` // -> `'get s0 { expr, s1 index s2 }` - let elems = Separated::NonEmpty { - first_elem: TableConstrElem::Lit(TableLitElem::Positional(expr)), - last_elems: vec![( - (Space::empty(span), s1), + let elems = vec![ + ( + Space::empty(span), + TableConstrElem::Lit(TableLitElem::Positional(expr)), + Space::empty(span), + ), + ( + s1, TableConstrElem::Lit(TableLitElem::Positional(index)), - )], - trailing: None, - span, - }; - let constr = TableConstr { - s0: Space::empty(span), - elems, - s1: s2, - span, - }; + s2, + ), + ]; let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Get, span))), s0, - constr, + constr: TableConstr(BoundedSeparated { + elems, + trailing: None, + span, + }), span, }); (new, true) @@ -54,31 +55,31 @@ impl Field { } => { // `expr s0 [ s1 index s2 ] s3 = s4 value` // -> `'set s0 { expr, s1 index s2, s3 s4 value }` - let elems = Separated::NonEmpty { - first_elem: TableConstrElem::Lit(TableLitElem::Positional(expr)), - last_elems: vec![ - ( - (Space::empty(span), s1), - TableConstrElem::Lit(TableLitElem::Positional(index)), - ), - ( - (s2, s3.then_line(Line::Empty).then(s4)), - TableConstrElem::Lit(TableLitElem::Positional(value)), - ), - ], - trailing: None, - span, - }; - let constr = TableConstr { - s0: Space::empty(span), - elems, - s1: Space::empty(span), - span, - }; + let elems = vec![ + ( + Space::empty(span), + TableConstrElem::Lit(TableLitElem::Positional(expr)), + Space::empty(span), + ), + ( + s1, + TableConstrElem::Lit(TableLitElem::Positional(index)), + s2, + ), + ( + s3.then_line(Line::Empty).then(s4), + TableConstrElem::Lit(TableLitElem::Positional(value)), + Space::empty(span), + ), + ]; let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Set, span))), s0, - constr, + constr: TableConstr(BoundedSeparated { + elems, + trailing: None, + span, + }), span, }); (new, true) diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 887d115..7cb5268 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -1,5 +1,5 @@ use crate::ast::{ - Call, Expr, Field, Line, Lit, Separated, Space, StringLit, StringLitElem, TableConstr, + BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, StringLitElem, TableConstr, TableConstrElem, TableLitElem, Var, }; use crate::builtin::Builtin; @@ -83,31 +83,31 @@ impl Var { s1: Space::empty(span), span, }); - let elems = Separated::NonEmpty { - first_elem: TableConstrElem::Lit(TableLitElem::Positional(Box::new(scope))), - last_elems: vec![ - ( - (Space::empty(span), local.then_line(Line::Empty).then(s0)), - TableConstrElem::Lit(TableLitElem::Positional(index)), - ), - ( - (s1, s2.then_line(Line::Empty).then(s3)), - TableConstrElem::Lit(TableLitElem::Positional(value)), - ), - ], - trailing: None, - span, - }; - let constr = TableConstr { - s0: Space::empty(span), - elems, - s1: Space::empty(span), - span, - }; + let elems = vec![ + ( + Space::empty(span), + TableConstrElem::Lit(TableLitElem::Positional(Box::new(scope))), + Space::empty(span), + ), + ( + local.then_line(Line::Empty).then(s0), + TableConstrElem::Lit(TableLitElem::Positional(index)), + s1, + ), + ( + s2.then_line(Line::Empty).then(s3), + TableConstrElem::Lit(TableLitElem::Positional(value)), + Space::empty(span), + ), + ]; let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::SetRaw, span))), s0: Space::empty(span), - constr, + constr: TableConstr(BoundedSeparated { + elems, + trailing: None, + span, + }), span, }); (new, true) diff --git a/src/parser/table_constr.rs b/src/parser/table_constr.rs index fd6aefd..65abbcb 100644 --- a/src/parser/table_constr.rs +++ b/src/parser/table_constr.rs @@ -4,7 +4,7 @@ use chumsky::prelude::*; use crate::ast::{Expr, Space, TableConstr, TableConstrElem, TableLitElem}; -use super::basic::{separated_by, EParser, Error}; +use super::basic::{bounded_separated, EParser, Error}; fn table_constr_elem( space: EParser, @@ -43,19 +43,13 @@ pub fn table_constr( expr: EParser, ) -> EParser { let elem = table_constr_elem(space.clone(), table_lit_elem, expr); - let separator = space.clone().then_ignore(just(',')).then(space.clone()); - let trailing_separator = space.clone().then_ignore(just(',')); - - space - .clone() - .then(separated_by(elem, separator, trailing_separator)) - .then(space) - .delimited_by(just('{'), just('}')) - .map_with_span(|((s0, elems), s1), span| TableConstr { - s0, - elems, - s1, - span, - }) - .boxed() + bounded_separated( + space, + just('{').to(()), + just('}').to(()), + just(',').to(()), + elem, + ) + .map(TableConstr) + .boxed() } diff --git a/src/pretty/table_constr.rs b/src/pretty/table_constr.rs index 704ab3e..3b3fdb1 100644 --- a/src/pretty/table_constr.rs +++ b/src/pretty/table_constr.rs @@ -2,8 +2,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::{TableConstr, TableConstrElem}; -use super::NEST_DEPTH; - impl<'a, D> Pretty<'a, D> for TableConstrElem where D: DocAllocator<'a>, @@ -35,16 +33,12 @@ where D::Doc: Clone, { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - self.elems - .pretty( - allocator, - |e| allocator.line().append(e.pretty(allocator)), - |(s0, s1)| allocator.text(","), - |s| allocator.text(","), - ) - .nest(NEST_DEPTH) - .append(allocator.line()) - .braces() - .group() + self.0.pretty( + allocator, + allocator.text("{"), + allocator.text("}"), + allocator.text(","), + |e| e.pretty(allocator), + ) } } From 198f56226eac52c1e7610831360add869f627921 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 23:57:58 +0100 Subject: [PATCH 05/29] Switch TablePattern to BoundedSeparated --- src/ast/table_destr.rs | 11 +++-------- src/parser/table_destr.rs | 26 ++++++++++---------------- src/pretty/table_destr.rs | 26 ++++++++++++-------------- 3 files changed, 25 insertions(+), 38 deletions(-) diff --git a/src/ast/table_destr.rs b/src/ast/table_destr.rs index eb88dcb..6b24d8f 100644 --- a/src/ast/table_destr.rs +++ b/src/ast/table_destr.rs @@ -1,6 +1,6 @@ use crate::span::{HasSpan, Span}; -use super::{Expr, Ident, Separated, Space}; +use super::{BoundedSeparated, Expr, Ident, Space}; // TODO Make table patterns recursive @@ -34,16 +34,11 @@ impl HasSpan for TablePatternElem { /// /// Structure: `{ s0 elems s1 }` #[derive(Debug, Clone)] -pub struct TablePattern { - pub s0: Space, - pub elems: Separated, - pub s1: Space, - pub span: Span, -} +pub struct TablePattern(pub BoundedSeparated); impl HasSpan for TablePattern { fn span(&self) -> Span { - self.span + self.0.span() } } diff --git a/src/parser/table_destr.rs b/src/parser/table_destr.rs index 4fb5eda..0504513 100644 --- a/src/parser/table_destr.rs +++ b/src/parser/table_destr.rs @@ -4,7 +4,7 @@ use chumsky::prelude::*; use crate::ast::{Expr, Ident, Space, TableDestr, TablePattern, TablePatternElem}; -use super::basic::{separated_by, EParser, Error}; +use super::basic::{bounded_separated, EParser, Error}; fn table_pattern_elem( space: EParser, @@ -31,21 +31,15 @@ fn table_pattern_elem( pub fn table_pattern(space: EParser, ident: EParser) -> EParser { let elem = table_pattern_elem(space.clone(), ident); - let separator = space.clone().then_ignore(just(',')).then(space.clone()); - let trailing_separator = space.clone().then_ignore(just(',')); - - space - .clone() - .then(separated_by(elem, separator, trailing_separator)) - .then(space) - .delimited_by(just('{'), just('}')) - .map_with_span(|((s0, elems), s1), span| TablePattern { - s0, - elems, - s1, - span, - }) - .boxed() + bounded_separated( + space, + just('{').to(()), + just('}').to(()), + just(',').to(()), + elem, + ) + .map(TablePattern) + .boxed() } pub fn table_destr( diff --git a/src/pretty/table_destr.rs b/src/pretty/table_destr.rs index 795bfa2..777d0ae 100644 --- a/src/pretty/table_destr.rs +++ b/src/pretty/table_destr.rs @@ -2,8 +2,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; use crate::ast::{TableDestr, TablePattern, TablePatternElem}; -use super::NEST_DEPTH; - impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TablePatternElem { fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { match self { @@ -22,19 +20,19 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TablePatternElem { } } -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TablePattern { +impl<'a, D> Pretty<'a, D> for TablePattern +where + D: DocAllocator<'a>, + D::Doc: Clone, +{ fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - self.elems - .pretty( - allocator, - |e| allocator.line().append(e.pretty(allocator)), - |(s0, s1)| allocator.text(","), - |s| allocator.text(","), - ) - .nest(NEST_DEPTH) - .append(allocator.line()) - .braces() - .group() + self.0.pretty( + allocator, + allocator.text("{"), + allocator.text("}"), + allocator.text(","), + |e| e.pretty(allocator), + ) } } From 94ea1969336448bbd24f6f25e42c2d3a0655a11d Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 00:00:43 +0100 Subject: [PATCH 06/29] Remove Separated --- src/ast/basic.rs | 20 -------------------- src/desugar/basic.rs | 37 +------------------------------------ src/parser/basic.rs | 23 +---------------------- src/pretty/basic.rs | 40 +--------------------------------------- 4 files changed, 3 insertions(+), 117 deletions(-) diff --git a/src/ast/basic.rs b/src/ast/basic.rs index 9790f8c..5056f21 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -77,26 +77,6 @@ impl HasSpan for Ident { } } -#[derive(Debug, Clone)] -pub enum Separated { - Empty(Span), - NonEmpty { - first_elem: E, - last_elems: Vec<(S1, E)>, - trailing: Option, - span: Span, - }, -} - -impl HasSpan for Separated { - fn span(&self) -> Span { - match self { - Self::Empty(span) => *span, - Self::NonEmpty { span, .. } => *span, - } - } -} - #[derive(Debug, Clone)] pub struct BoundedSeparated { pub elems: Vec<(Space, E, Space)>, diff --git a/src/desugar/basic.rs b/src/desugar/basic.rs index 1b0f4fc..156445f 100644 --- a/src/desugar/basic.rs +++ b/src/desugar/basic.rs @@ -1,39 +1,4 @@ -use crate::ast::{BoundedSeparated, Separated}; - -impl Separated { - pub fn desugar_elem(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { - match self { - Self::Empty(span) => (Self::Empty(span), false), - - Self::NonEmpty { - first_elem, - last_elems, - trailing, - span, - } => { - let (new_first_elem, mut desugared) = desugar_elem(first_elem); - let mut new_last_elems = vec![]; - for (separator, elem) in last_elems { - if desugared { - new_last_elems.push((separator, elem)); - } else { - let (elem, elem_desugared) = desugar_elem(elem); - desugared = desugared || elem_desugared; - new_last_elems.push((separator, elem)); - } - } - - let new = Self::NonEmpty { - first_elem: new_first_elem, - last_elems: new_last_elems, - trailing, - span, - }; - (new, desugared) - } - } - } -} +use crate::ast::BoundedSeparated; impl BoundedSeparated { pub fn desugar(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { diff --git a/src/parser/basic.rs b/src/parser/basic.rs index 2c8254d..9ca8d09 100644 --- a/src/parser/basic.rs +++ b/src/parser/basic.rs @@ -3,7 +3,7 @@ use chumsky::prelude::*; use chumsky::text::Character; -use crate::ast::{BoundedSeparated, Ident, Line, Separated, Space}; +use crate::ast::{BoundedSeparated, Ident, Line, Space}; use crate::span::Span; pub type Error = Simple; @@ -62,27 +62,6 @@ pub fn local(space: EParser) -> EParser> { // This function is more of a utility function. Because of this and to keep the // code nicer, I have decided that the rules specified in the `parser` module // don't apply to it. -pub fn separated_by( - elem: impl Parser + Clone + 'static, - separator: impl Parser + 'static, - trailing_separator: impl Parser + 'static, -) -> EParser> { - elem.clone() - .then(separator.then(elem).repeated()) - .then(trailing_separator.or_not()) - .or_not() - .map_with_span(|s, span| match s { - Some(((first_elem, last_elems), trailing)) => Separated::NonEmpty { - first_elem, - last_elems, - trailing, - span, - }, - None => Separated::Empty(span), - }) - .boxed() -} - pub fn bounded_separated( space: impl Parser + Clone + 'static, start: impl Parser + 'static, diff --git a/src/pretty/basic.rs b/src/pretty/basic.rs index 5d4ae8e..632007c 100644 --- a/src/pretty/basic.rs +++ b/src/pretty/basic.rs @@ -1,6 +1,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; -use crate::ast::{BoundedSeparated, Ident, Separated}; +use crate::ast::{BoundedSeparated, Ident}; use super::NEST_DEPTH; @@ -10,44 +10,6 @@ impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Ident { } } -impl Separated { - pub fn pretty<'a, D, FE, FS1, FS2>( - self, - allocator: &'a D, - elem_to_doc: FE, - separator_to_doc: FS1, - trailing_separator_to_doc: FS2, - ) -> DocBuilder<'a, D> - where - D: DocAllocator<'a>, - FE: Fn(E) -> DocBuilder<'a, D>, - FS1: Fn(S1) -> DocBuilder<'a, D>, - FS2: Fn(S2) -> DocBuilder<'a, D>, - { - match self { - Self::Empty(_) => allocator.nil(), - Self::NonEmpty { - first_elem, - last_elems, - trailing, - span: _span, - } => elem_to_doc(first_elem) - .append( - allocator.concat( - last_elems - .into_iter() - .map(|(s, e)| separator_to_doc(s).append(elem_to_doc(e))), - ), - ) - .append( - trailing - .map(trailing_separator_to_doc) - .unwrap_or_else(|| allocator.nil()), - ), - } - } -} - impl BoundedSeparated { pub fn pretty<'a, D, FE>( self, From 74d1f640b5ab620d19062cf889dd839349166e47 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 09:21:44 +0100 Subject: [PATCH 07/29] Fix pretty printing of empty BoundedSeparated --- src/pretty/basic.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pretty/basic.rs b/src/pretty/basic.rs index 632007c..c8c8d8f 100644 --- a/src/pretty/basic.rs +++ b/src/pretty/basic.rs @@ -1,6 +1,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; -use crate::ast::{BoundedSeparated, Ident}; +use crate::ast::{BoundedSeparated, Ident, Space}; use super::NEST_DEPTH; @@ -24,6 +24,7 @@ impl BoundedSeparated { D::Doc: Clone, FE: Fn(E) -> DocBuilder<'a, D>, { + let elems_empty = self.elems.is_empty(); allocator .intersperse( self.elems @@ -31,7 +32,7 @@ impl BoundedSeparated { .map(|(s0, elem, s1)| allocator.line().append(elem_pretty(elem))), separator.clone(), ) - .append(self.trailing.map(|s| separator)) + .append(self.trailing.filter(|_| !elems_empty).map(|s| separator)) .nest(NEST_DEPTH) .append(allocator.line()) .enclose(start, end) From af6c171eb4afcdc02f66a01884572b5a55eba072 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 09:44:29 +0100 Subject: [PATCH 08/29] Desugar table constructors --- src/desugar.rs | 1 + src/desugar/basic.rs | 22 ++++++++++++++- src/desugar/expr.rs | 6 ++-- src/desugar/table_constr.rs | 55 +++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) 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 156445f..55526cf 100644 --- a/src/desugar/basic.rs +++ b/src/desugar/basic.rs @@ -1,4 +1,4 @@ -use crate::ast::BoundedSeparated; +use crate::ast::{BoundedSeparated, Space}; impl BoundedSeparated { pub fn desugar(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { @@ -21,4 +21,24 @@ impl BoundedSeparated { }; (new, desugared) } + + pub fn remove_map( + self, + f: impl Fn(E) -> Result, + ) -> (BoundedSeparated, Vec<(Space, E2, Space)>) { + let mut kept = vec![]; + let mut removed = vec![]; + for (s0, elem, s1) in self.elems { + match f(elem) { + Ok(elem) => kept.push((s0, elem, s1)), + Err(elem) => removed.push((s0, elem, s1)), + } + } + let new = BoundedSeparated { + elems: kept, + trailing: self.trailing, + span: self.span, + }; + (new, removed) + } } diff --git a/src/desugar/expr.rs b/src/desugar/expr.rs index 0c8e569..5f7cb02 100644 --- a/src/desugar/expr.rs +++ b/src/desugar/expr.rs @@ -11,10 +11,10 @@ impl Expr { Self::Call(call) => call.desugar(), Self::Field(field) => field.desugar(), Self::Var(var) => var.desugar(), + Self::TableConstr(constr) => constr.desugar(), - Self::TableConstr(constr) => (Self::TableConstr(constr), false), // TODO Implement - Self::TableDestr(destr) => (Self::TableDestr(destr), false), // TODO Implement - Self::FuncDef(def) => (Self::FuncDef(def), false), // TODO Implement + Self::TableDestr(destr) => (Self::TableDestr(destr), false), // TODO Implement + Self::FuncDef(def) => (Self::FuncDef(def), false), // TODO Implement Self::Paren { s0, diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs new file mode 100644 index 0000000..aa37214 --- /dev/null +++ b/src/desugar/table_constr.rs @@ -0,0 +1,55 @@ +use crate::ast::{ + BoundedSeparated, Expr, Field, Ident, Line, Lit, Space, TableConstr, TableConstrElem, TableLit, + TableLitElem, +}; +use crate::span::HasSpan; + +impl TableConstr { + pub fn desugar(self) -> (Expr, bool) { + let span = self.span(); + + let (elems, setters) = self.0.remove_map(|e| match e { + TableConstrElem::Lit(lit) => Ok(lit), + TableConstrElem::Indexed { + s0, + index, + s1, + s2, + s3, + value, + span, + } => Err((s0, index, s1, s2, s3, value, span)), + }); + + let raw_elem = TableLitElem::Named { + name: Ident::new("raw", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: Box::new(Expr::Lit(Lit::Table(TableLit(elems)))), + span, + }; + let mut expr = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { + elems: vec![(Space::empty(span), raw_elem, Space::empty(span))], + trailing: None, + span, + }))); + + // `sl [ s0 index s1 ] s2 = s3 value sr` + // -> `expr s0 [ s1 index s2 ] s3 = s4 s5 value` + for (s0, (s1, index, s2, s3, s4, value, span), s5) in setters { + expr = Expr::Field(Field::Assign { + expr: Box::new(expr), + s0, + s1, + index, + s2, + s3, + s4: s4.then_line(Line::Empty).then(s5), + value, + span, + }); + } + + (expr, true) + } +} From d4797c5894f7f226d429e1a6c0031c115240c2ab Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 10:31:58 +0100 Subject: [PATCH 09/29] Simplify creating string literal from ident --- src/ast/lit.rs | 9 +++++++++ src/desugar/field.rs | 16 ++++------------ src/desugar/var.rs | 16 ++++------------ 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/ast/lit.rs b/src/ast/lit.rs index ee486ef..16c7263 100644 --- a/src/ast/lit.rs +++ b/src/ast/lit.rs @@ -93,6 +93,15 @@ pub struct StringLit { pub span: Span, } +impl StringLit { + pub fn from_ident(ident: Ident) -> Self { + Self { + elems: vec![StringLitElem::Plain(ident.name)], + span: ident.span, + } + } +} + impl HasSpan for StringLit { fn span(&self) -> Span { self.span diff --git a/src/desugar/field.rs b/src/desugar/field.rs index 496cd44..30dfc5b 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -1,6 +1,6 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, StringLitElem, TableConstr, - TableConstrElem, TableLitElem, + BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, TableConstr, TableConstrElem, + TableLitElem, }; use crate::builtin::Builtin; @@ -94,15 +94,11 @@ impl Field { } => { // `expr s0 . s1 ident´ // -> `expr s0 [ s1 ident_str ]` - let ident_str = Expr::Lit(Lit::String(StringLit { - elems: vec![StringLitElem::Plain(ident.name)], - span: ident.span, - })); let new = Expr::Field(Self::Access { expr, s0, s1, - index: Box::new(ident_str), + index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), s2: Space::empty(span), span, }); @@ -121,15 +117,11 @@ impl Field { } => { // `expr s0 . s1 ident s2 = s3 value` // -> `expr s0 [ s1 ident_str ] s2 = s3 value` - let ident_str = Expr::Lit(Lit::String(StringLit { - elems: vec![StringLitElem::Plain(ident.name)], - span: ident.span, - })); let new = Expr::Field(Self::Assign { expr, s0, s1, - index: Box::new(ident_str), + index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), s2: Space::empty(span), s3: s2, s4: s3, diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 7cb5268..2ea1997 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -1,6 +1,6 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, StringLitElem, TableConstr, - TableConstrElem, TableLitElem, Var, + BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, TableConstr, TableConstrElem, + TableLitElem, Var, }; use crate::builtin::Builtin; use crate::span::HasSpan; @@ -117,13 +117,9 @@ impl Var { // `name` // -> `[ name_str ]` let span = name.span(); - let name_str = Expr::Lit(Lit::String(StringLit { - elems: vec![StringLitElem::Plain(name.name)], - span, - })); let new = Expr::Var(Self::Access { s0: Space::empty(span), - index: Box::new(name_str), + index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(name)))), s1: Space::empty(span), span, }); @@ -140,14 +136,10 @@ impl Var { } => { // `local name s0 = s1 value` // -> `local [ name_str ] s0 = s1 value` - let name_str = Expr::Lit(Lit::String(StringLit { - elems: vec![StringLitElem::Plain(name.name)], - span: name.span, - })); let new = Expr::Var(Self::Assign { local, s0: Space::empty(span), - index: Box::new(name_str), + index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(name)))), s1: Space::empty(span), s2: s0, s3: s1, From 830ffa92c49f58507bc5ca591d03a1e3bda325f8 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 10:32:27 +0100 Subject: [PATCH 10/29] Desugar table destructuring --- src/desugar.rs | 1 + src/desugar/basic.rs | 14 +++++++ src/desugar/expr.rs | 4 +- src/desugar/table_destr.rs | 81 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/desugar/table_destr.rs diff --git a/src/desugar.rs b/src/desugar.rs index db66687..e1d23c1 100644 --- a/src/desugar.rs +++ b/src/desugar.rs @@ -5,4 +5,5 @@ mod field; mod lit; mod program; mod table_constr; +mod table_destr; mod var; diff --git a/src/desugar/basic.rs b/src/desugar/basic.rs index 55526cf..6f9ec72 100644 --- a/src/desugar/basic.rs +++ b/src/desugar/basic.rs @@ -22,6 +22,20 @@ impl BoundedSeparated { (new, desugared) } + pub fn map(self, f: impl Fn(E) -> E2) -> BoundedSeparated { + let elems = self + .elems + .into_iter() + .map(|(s0, e, s1)| (s0, f(e), s1)) + .collect::>(); + + BoundedSeparated { + elems, + trailing: self.trailing, + span: self.span, + } + } + pub fn remove_map( self, f: impl Fn(E) -> Result, diff --git a/src/desugar/expr.rs b/src/desugar/expr.rs index 5f7cb02..7a8a197 100644 --- a/src/desugar/expr.rs +++ b/src/desugar/expr.rs @@ -12,9 +12,9 @@ impl Expr { Self::Field(field) => field.desugar(), Self::Var(var) => var.desugar(), Self::TableConstr(constr) => constr.desugar(), + Self::TableDestr(destr) => destr.desugar(), - Self::TableDestr(destr) => (Self::TableDestr(destr), false), // TODO Implement - Self::FuncDef(def) => (Self::FuncDef(def), false), // TODO Implement + Self::FuncDef(def) => (Self::FuncDef(def), false), // TODO Implement Self::Paren { s0, diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs new file mode 100644 index 0000000..7152010 --- /dev/null +++ b/src/desugar/table_destr.rs @@ -0,0 +1,81 @@ +use crate::ast::{ + BoundedSeparated, Call, Expr, Ident, Lit, Space, StringLit, TableConstr, TableConstrElem, + TableDestr, TableLitElem, TablePattern, TablePatternElem, +}; +use crate::builtin::Builtin; + +fn pattern_to_constr(pattern: TablePattern) -> TableConstr { + TableConstr(pattern.0.map(|e| match e { + TablePatternElem::Positional(ident) => TableConstrElem::Lit(TableLitElem::Positional( + Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + )), + + TablePatternElem::Named { + name, + s0, + s1, + ident, + span, + } => TableConstrElem::Lit(TableLitElem::Named { + name, + s0, + s1, + value: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + span, + }), + })) +} + +impl TableDestr { + pub fn desugar(self) -> (Expr, bool) { + let Self { + local, + pattern, + s0, + s1, + value, + span, + } = self; + + let mut elems = vec![ + ( + Space::empty(span), + TableConstrElem::Lit(TableLitElem::Positional(Box::new(Expr::TableConstr( + pattern_to_constr(pattern), + )))), + s0, + ), + ( + s1, + TableConstrElem::Lit(TableLitElem::Positional(value)), + Space::empty(span), + ), + ]; + if let Some(local) = local { + elems.push(( + Space::empty(span), + TableConstrElem::Lit(TableLitElem::Named { + name: Ident::new("local", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: Box::new(Expr::Lit(Lit::Bool(true, span))), + span, + }), + local, + )) + } + + let constr = TableConstr(BoundedSeparated { + elems, + trailing: None, + span, + }); + let new = Expr::Call(Call::Constr { + expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Destructure, span))), + s0: Space::empty(span), + constr, + span, + }); + (new, true) + } +} From d6a0bbf2af77e2d521a88c1cd3603148e98d03e9 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 12:56:09 +0100 Subject: [PATCH 11/29] Desugar simple anonymous function definitions --- src/desugar.rs | 1 + src/desugar/expr.rs | 3 +- src/desugar/func_def.rs | 161 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 src/desugar/func_def.rs diff --git a/src/desugar.rs b/src/desugar.rs index e1d23c1..2be2a3f 100644 --- a/src/desugar.rs +++ b/src/desugar.rs @@ -2,6 +2,7 @@ mod basic; mod call; mod expr; mod field; +mod func_def; mod lit; mod program; mod table_constr; diff --git a/src/desugar/expr.rs b/src/desugar/expr.rs index 7a8a197..01c6862 100644 --- a/src/desugar/expr.rs +++ b/src/desugar/expr.rs @@ -13,8 +13,7 @@ impl Expr { Self::Var(var) => var.desugar(), Self::TableConstr(constr) => constr.desugar(), Self::TableDestr(destr) => destr.desugar(), - - Self::FuncDef(def) => (Self::FuncDef(def), false), // TODO Implement + Self::FuncDef(def) => def.desugar(), Self::Paren { s0, diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs new file mode 100644 index 0000000..7a6b362 --- /dev/null +++ b/src/desugar/func_def.rs @@ -0,0 +1,161 @@ +use crate::ast::{ + BoundedSeparated, Call, Expr, FuncDef, Ident, Lit, Space, TableConstr, TableConstrElem, + TableLit, TableLitElem, Var, +}; +use crate::builtin::Builtin; + +impl FuncDef { + pub fn desugar(self) -> (Expr, bool) { + match self { + Self::AnonNoArg { + s0, + s1, + s2, + body, + span, + } => { + // `function s0 ( s1 ) s2 body` + // -> `{ '{ quote: body }, scope: 'scope() }` + let quote = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { + elems: vec![( + Space::empty(span), + TableLitElem::Named { + name: Ident::new("quote", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: body, + span, + }, + Space::empty(span), + )], + trailing: None, + span, + }))); + let scope = Expr::Call(Call::NoArg { + expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + s0: Space::empty(span), + s1: Space::empty(span), + span, + }); + let new = Expr::TableConstr(TableConstr(BoundedSeparated { + elems: vec![ + ( + Space::empty(span), + TableConstrElem::Lit(TableLitElem::Positional(Box::new(quote))), + Space::empty(span), + ), + ( + Space::empty(span), + TableConstrElem::Lit(TableLitElem::Named { + name: Ident::new("scope", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: Box::new(scope), + span, + }), + Space::empty(span), + ), + ], + trailing: None, + span, + })); + (new, true) + } + + Self::AnonArg { + s0, + s1, + arg, + s2, + s3, + body, + span, + } => { + // `function s0 ( s1 arg s2 ) s3 body` + // -> `function ( ) '{ local arg = 'arg(), body }` + let arg_call = Expr::Call(Call::NoArg { + expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Arg, span))), + s0: Space::empty(span), + s1: Space::empty(span), + span, + }); + let arg_assign = Expr::Var(Var::AssignIdent { + local: Some(Space::empty(span)), + name: arg, + s0: Space::empty(span), + s1: Space::empty(span), + value: Box::new(arg_call), + span, + }); + let body_elems = vec![ + ( + Space::empty(span), + TableLitElem::Positional(Box::new(arg_assign)), + Space::empty(span), + ), + ( + Space::empty(span), + TableLitElem::Positional(body), + Space::empty(span), + ), + ]; + let body = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { + elems: body_elems, + trailing: None, + span, + }))); + let new = Expr::FuncDef(Self::AnonNoArg { + s0: Space::empty(span), + s1: Space::empty(span), + s2: Space::empty(span), + body: Box::new(body), + span, + }); + (new, true) + } + + Self::AnonDestr { + s0, + pattern, + s1, + body, + span, + } => todo!(), + + Self::NamedNoArg { + local, + s0, + name, + s1, + s2, + s3, + body, + span, + } => todo!(), + + Self::NamedArg { + local, + s0, + name, + s1, + s2, + arg, + s3, + s4, + body, + span, + } => todo!(), + + Self::NamedDestr { + local, + s0, + name, + s1, + pattern, + s2, + body, + span, + } => todo!(), + } + } +} From c769d9e16f6dd25409f7f8ac6833f465b57b33d7 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 14:44:15 +0100 Subject: [PATCH 12/29] Simplify creating BoundedSeparated Along with this comes the decision to no longer track whitespace and comments across desugarings in most cases. The main reason for this decision is that not having to track whitespace simplifies the code and reasoning necessary. While implementing desugarings, I also realized that the current comment model doesn't let me accurately track whitespace across desugarings. I'm fairly sure I haven't yet found a good model for whitespace and comments. Once I find one, adding pretty printing support for those should hopefully be easy though. --- src/ast/basic.rs | 16 +++++++ src/desugar/call.rs | 26 +++-------- src/desugar/field.rs | 78 ++++++++++--------------------- src/desugar/func_def.rs | 92 ++++++++++++------------------------- src/desugar/table_constr.rs | 8 ++-- src/desugar/table_destr.rs | 50 +++++++------------- src/desugar/var.rs | 45 ++++++------------ 7 files changed, 110 insertions(+), 205 deletions(-) diff --git a/src/ast/basic.rs b/src/ast/basic.rs index 5056f21..3528b7d 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -89,3 +89,19 @@ impl HasSpan for BoundedSeparated { self.span } } + +impl BoundedSeparated { + pub fn new(span: Span) -> Self { + Self { + elems: vec![], + trailing: None, + span, + } + } + + pub fn then(mut self, elem: E) -> Self { + self.elems + .push((Space::empty(self.span), elem, Space::empty(self.span))); + self + } +} diff --git a/src/desugar/call.rs b/src/desugar/call.rs index 70cd2c4..b09b7a3 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -7,14 +7,12 @@ impl Call { match self { Self::Arg { expr, - s0, - s1, + s0: _, + s1: _, arg, - s2, + s2: _, span, } => { - // `expr s0 ( s1 arg s2 )` - // -> `'{ s0 call: expr, arg: s1 arg s2 }` let call = TableLitElem::Named { name: Ident::new("call", span), s0: Space::empty(span), @@ -25,25 +23,17 @@ impl Call { let arg = TableLitElem::Named { name: Ident::new("arg", span), s0: Space::empty(span), - s1, + s1: Space::empty(span), value: arg, span, }; - let elems = vec![ - (s0, call, Space::empty(span)), - (Space::empty(span), arg, s2), - ]; - let new = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { - elems, - trailing: None, - span, - }))); + let new = Expr::Lit(Lit::Table(TableLit( + BoundedSeparated::new(span).then(call).then(arg), + ))); (new, true) } Self::NoArg { expr, s0, s1, span } => { - // `expr s0 ( s1 )` - // -> `expr s0 ( s1 nil )` let new = Expr::Call(Self::Arg { expr, s0, @@ -61,8 +51,6 @@ impl Call { constr, span, } => { - // `expr s0 {..}` - // -> `expr s0 ( {..} )` let new = Expr::Call(Self::Arg { expr, s0, diff --git a/src/desugar/field.rs b/src/desugar/field.rs index 30dfc5b..84005b7 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -1,5 +1,5 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, TableConstr, TableConstrElem, + BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstr, TableConstrElem, TableLitElem, }; use crate::builtin::Builtin; @@ -9,34 +9,21 @@ impl Field { match self { Self::Access { expr, - s0, - s1, + s0: _, + s1: _, index, - s2, + s2: _, span, } => { - // ` expr s0 [ s1 index s2 ]` - // -> `'get s0 { expr, s1 index s2 }` - let elems = vec![ - ( - Space::empty(span), - TableConstrElem::Lit(TableLitElem::Positional(expr)), - Space::empty(span), - ), - ( - s1, - TableConstrElem::Lit(TableLitElem::Positional(index)), - s2, - ), - ]; + let constr = TableConstr( + BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) + .then(TableConstrElem::Lit(TableLitElem::Positional(index))), + ); let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Get, span))), - s0, - constr: TableConstr(BoundedSeparated { - elems, - trailing: None, - span, - }), + s0: Space::empty(span), + constr, span, }); (new, true) @@ -44,42 +31,25 @@ impl Field { Self::Assign { expr, - s0, - s1, + s0: _, + s1: _, index, - s2, - s3, - s4, + s2: _, + s3: _, + s4: _, value, span, } => { - // `expr s0 [ s1 index s2 ] s3 = s4 value` - // -> `'set s0 { expr, s1 index s2, s3 s4 value }` - let elems = vec![ - ( - Space::empty(span), - TableConstrElem::Lit(TableLitElem::Positional(expr)), - Space::empty(span), - ), - ( - s1, - TableConstrElem::Lit(TableLitElem::Positional(index)), - s2, - ), - ( - s3.then_line(Line::Empty).then(s4), - TableConstrElem::Lit(TableLitElem::Positional(value)), - Space::empty(span), - ), - ]; + let constr = TableConstr( + BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) + .then(TableConstrElem::Lit(TableLitElem::Positional(index))) + .then(TableConstrElem::Lit(TableLitElem::Positional(value))), + ); let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Set, span))), - s0, - constr: TableConstr(BoundedSeparated { - elems, - trailing: None, - span, - }), + s0: Space::empty(span), + constr, span, }); (new, true) diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index 7a6b362..4f3c396 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -8,66 +8,46 @@ impl FuncDef { pub fn desugar(self) -> (Expr, bool) { match self { Self::AnonNoArg { - s0, - s1, - s2, + s0: _, + s1: _, + s2: _, body, span, } => { - // `function s0 ( s1 ) s2 body` - // -> `{ '{ quote: body }, scope: 'scope() }` - let quote = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { - elems: vec![( - Space::empty(span), - TableLitElem::Named { - name: Ident::new("quote", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: body, - span, - }, - Space::empty(span), - )], - trailing: None, + let quote = TableLit(BoundedSeparated::new(span).then(TableLitElem::Named { + name: Ident::new("quote", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: body, span, - }))); + })); + let quote = Box::new(Expr::Lit(Lit::Table(quote))); let scope = Expr::Call(Call::NoArg { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), s0: Space::empty(span), s1: Space::empty(span), span, }); - let new = Expr::TableConstr(TableConstr(BoundedSeparated { - elems: vec![ - ( - Space::empty(span), - TableConstrElem::Lit(TableLitElem::Positional(Box::new(quote))), - Space::empty(span), - ), - ( - Space::empty(span), - TableConstrElem::Lit(TableLitElem::Named { - name: Ident::new("scope", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: Box::new(scope), - span, - }), - Space::empty(span), - ), - ], - trailing: None, - span, - })); + let new = Expr::TableConstr(TableConstr( + BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(quote))) + .then(TableConstrElem::Lit(TableLitElem::Named { + name: Ident::new("scope", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: Box::new(scope), + span, + })), + )); (new, true) } Self::AnonArg { - s0, - s1, + s0: _, + s1: _, arg, - s2, - s3, + s2: _, + s3: _, body, span, } => { @@ -87,28 +67,14 @@ impl FuncDef { value: Box::new(arg_call), span, }); - let body_elems = vec![ - ( - Space::empty(span), - TableLitElem::Positional(Box::new(arg_assign)), - Space::empty(span), - ), - ( - Space::empty(span), - TableLitElem::Positional(body), - Space::empty(span), - ), - ]; - let body = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { - elems: body_elems, - trailing: None, - span, - }))); + let body = BoundedSeparated::new(span) + .then(TableLitElem::Positional(Box::new(arg_assign))) + .then(TableLitElem::Positional(body)); let new = Expr::FuncDef(Self::AnonNoArg { s0: Space::empty(span), s1: Space::empty(span), s2: Space::empty(span), - body: Box::new(body), + body: Box::new(Expr::Lit(Lit::Table(TableLit(body)))), span, }); (new, true) diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs index aa37214..2bb4eff 100644 --- a/src/desugar/table_constr.rs +++ b/src/desugar/table_constr.rs @@ -28,11 +28,9 @@ impl TableConstr { value: Box::new(Expr::Lit(Lit::Table(TableLit(elems)))), span, }; - let mut expr = Expr::Lit(Lit::Table(TableLit(BoundedSeparated { - elems: vec![(Space::empty(span), raw_elem, Space::empty(span))], - trailing: None, - span, - }))); + let mut expr = Expr::Lit(Lit::Table(TableLit( + BoundedSeparated::new(span).then(raw_elem), + ))); // `sl [ s0 index s1 ] s2 = s3 value sr` // -> `expr s0 [ s1 index s2 ] s3 = s4 s5 value` diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index 7152010..8d68a00 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -31,49 +31,31 @@ impl TableDestr { let Self { local, pattern, - s0, - s1, + s0: _, + s1: _, value, span, } = self; - let mut elems = vec![ - ( - Space::empty(span), - TableConstrElem::Lit(TableLitElem::Positional(Box::new(Expr::TableConstr( - pattern_to_constr(pattern), - )))), - s0, - ), - ( - s1, - TableConstrElem::Lit(TableLitElem::Positional(value)), - Space::empty(span), - ), - ]; - if let Some(local) = local { - elems.push(( - Space::empty(span), - TableConstrElem::Lit(TableLitElem::Named { - name: Ident::new("local", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: Box::new(Expr::Lit(Lit::Bool(true, span))), - span, - }), - local, - )) + let mut constr = BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(Box::new( + Expr::TableConstr(pattern_to_constr(pattern)), + )))) + .then(TableConstrElem::Lit(TableLitElem::Positional(value))); + if local.is_some() { + constr = constr.then(TableConstrElem::Lit(TableLitElem::Named { + name: Ident::new("local", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: Box::new(Expr::Lit(Lit::Bool(true, span))), + span, + })); } - let constr = TableConstr(BoundedSeparated { - elems, - trailing: None, - span, - }); let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Destructure, span))), s0: Space::empty(span), - constr, + constr: TableConstr(constr), span, }); (new, true) diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 2ea1997..7019702 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -1,5 +1,5 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Line, Lit, Space, StringLit, TableConstr, TableConstrElem, + BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstr, TableConstrElem, TableLitElem, Var, }; use crate::builtin::Builtin; @@ -66,48 +66,33 @@ impl Var { } Self::Assign { - local: Some(local), - s0, + local: Some(_), + s0: _, index, - s1, - s2, - s3, + s1: _, + s2: _, + s3: _, value, span, } => { - // `local [ s0 index s1 ] s2 = s3 value` - // --> `'setraw { 'scope(), local s0 index s1, s2 s3 value }` let scope = Expr::Call(Call::NoArg { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), s0: Space::empty(span), s1: Space::empty(span), span, }); - let elems = vec![ - ( - Space::empty(span), - TableConstrElem::Lit(TableLitElem::Positional(Box::new(scope))), - Space::empty(span), - ), - ( - local.then_line(Line::Empty).then(s0), - TableConstrElem::Lit(TableLitElem::Positional(index)), - s1, - ), - ( - s2.then_line(Line::Empty).then(s3), - TableConstrElem::Lit(TableLitElem::Positional(value)), - Space::empty(span), - ), - ]; + let constr = TableConstr( + BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(Box::new( + scope, + )))) + .then(TableConstrElem::Lit(TableLitElem::Positional(index))) + .then(TableConstrElem::Lit(TableLitElem::Positional(value))), + ); let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::SetRaw, span))), s0: Space::empty(span), - constr: TableConstr(BoundedSeparated { - elems, - trailing: None, - span, - }), + constr, span, }); (new, true) From 5a977e6dde78cf0d26347fa4bac35b17eb2682b2 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 15:21:29 +0100 Subject: [PATCH 13/29] Simplify creating TableLit and TableConstr --- src/ast/basic.rs | 14 +++++++++++++ src/desugar/call.rs | 8 ++++---- src/desugar/field.rs | 23 +++++++++------------ src/desugar/func_def.rs | 31 +++++++++++++++------------- src/desugar/lit.rs | 2 +- src/desugar/program.rs | 4 ++-- src/desugar/table_constr.rs | 10 ++++----- src/desugar/table_destr.rs | 41 ++++++++++++++++++++----------------- src/desugar/var.rs | 18 ++++++++-------- 9 files changed, 83 insertions(+), 68 deletions(-) diff --git a/src/ast/basic.rs b/src/ast/basic.rs index 3528b7d..ee6428a 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -2,6 +2,8 @@ use std::fmt; use crate::span::{HasSpan, Span}; +use super::{TableConstr, TableConstrElem, TableLit, TableLitElem}; + #[derive(Clone)] pub enum Line { Empty, @@ -105,3 +107,15 @@ impl BoundedSeparated { self } } + +impl BoundedSeparated { + pub fn table_lit(self) -> TableLit { + TableLit(self) + } +} + +impl BoundedSeparated { + pub fn table_constr(self) -> TableConstr { + TableConstr(self) + } +} diff --git a/src/desugar/call.rs b/src/desugar/call.rs index b09b7a3..bef48b1 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -1,4 +1,4 @@ -use crate::ast::{BoundedSeparated, Call, Expr, Ident, Lit, Space, TableLit, TableLitElem}; +use crate::ast::{BoundedSeparated, Call, Expr, Ident, Lit, Space, TableLitElem}; // TODO Add span for just the parentheses to ast, or limit span to parentheses @@ -27,9 +27,9 @@ impl Call { value: arg, span, }; - let new = Expr::Lit(Lit::Table(TableLit( - BoundedSeparated::new(span).then(call).then(arg), - ))); + let new = Expr::Lit(Lit::Table( + BoundedSeparated::new(span).then(call).then(arg).table_lit(), + )); (new, true) } diff --git a/src/desugar/field.rs b/src/desugar/field.rs index 84005b7..c429f87 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -1,6 +1,5 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstr, TableConstrElem, - TableLitElem, + BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem, TableLitElem, }; use crate::builtin::Builtin; @@ -15,11 +14,10 @@ impl Field { s2: _, span, } => { - let constr = TableConstr( - BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) - .then(TableConstrElem::Lit(TableLitElem::Positional(index))), - ); + let constr = BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) + .then(TableConstrElem::Lit(TableLitElem::Positional(index))) + .table_constr(); let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Get, span))), s0: Space::empty(span), @@ -40,12 +38,11 @@ impl Field { value, span, } => { - let constr = TableConstr( - BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) - .then(TableConstrElem::Lit(TableLitElem::Positional(index))) - .then(TableConstrElem::Lit(TableLitElem::Positional(value))), - ); + let constr = BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) + .then(TableConstrElem::Lit(TableLitElem::Positional(index))) + .then(TableConstrElem::Lit(TableLitElem::Positional(value))) + .table_constr(); let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Set, span))), s0: Space::empty(span), diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index 4f3c396..1b370eb 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -1,6 +1,5 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, FuncDef, Ident, Lit, Space, TableConstr, TableConstrElem, - TableLit, TableLitElem, Var, + BoundedSeparated, Call, Expr, FuncDef, Ident, Lit, Space, TableConstrElem, TableLitElem, Var, }; use crate::builtin::Builtin; @@ -14,13 +13,15 @@ impl FuncDef { body, span, } => { - let quote = TableLit(BoundedSeparated::new(span).then(TableLitElem::Named { - name: Ident::new("quote", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: body, - span, - })); + let quote = BoundedSeparated::new(span) + .then(TableLitElem::Named { + name: Ident::new("quote", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: body, + span, + }) + .table_lit(); let quote = Box::new(Expr::Lit(Lit::Table(quote))); let scope = Expr::Call(Call::NoArg { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), @@ -28,7 +29,7 @@ impl FuncDef { s1: Space::empty(span), span, }); - let new = Expr::TableConstr(TableConstr( + let new = Expr::TableConstr( BoundedSeparated::new(span) .then(TableConstrElem::Lit(TableLitElem::Positional(quote))) .then(TableConstrElem::Lit(TableLitElem::Named { @@ -37,8 +38,9 @@ impl FuncDef { s1: Space::empty(span), value: Box::new(scope), span, - })), - )); + })) + .table_constr(), + ); (new, true) } @@ -69,12 +71,13 @@ impl FuncDef { }); let body = BoundedSeparated::new(span) .then(TableLitElem::Positional(Box::new(arg_assign))) - .then(TableLitElem::Positional(body)); + .then(TableLitElem::Positional(body)) + .table_lit(); let new = Expr::FuncDef(Self::AnonNoArg { s0: Space::empty(span), s1: Space::empty(span), s2: Space::empty(span), - body: Box::new(Expr::Lit(Lit::Table(TableLit(body)))), + body: Box::new(Expr::Lit(Lit::Table(body))), span, }); (new, true) diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs index 4f32a38..f88efa6 100644 --- a/src/desugar/lit.rs +++ b/src/desugar/lit.rs @@ -32,7 +32,7 @@ impl TableLitElem { impl TableLit { pub fn desugar(self) -> (Self, bool) { let (elems, desugared) = self.0.desugar(|e| e.desugar()); - (Self(elems), desugared) + (elems.table_lit(), desugared) } } diff --git a/src/desugar/program.rs b/src/desugar/program.rs index 50b11eb..73a3bda 100644 --- a/src/desugar/program.rs +++ b/src/desugar/program.rs @@ -1,4 +1,4 @@ -use crate::ast::{Expr, Lit, Program, Space, TableLit}; +use crate::ast::{Expr, Lit, Program, Space}; impl Program { pub fn desugar(self) -> (Self, bool) { @@ -14,7 +14,7 @@ impl Program { // -> `s0 table` let new = Self::Expr { s0, - expr: Expr::Lit(Lit::Table(TableLit(elems))), + expr: Expr::Lit(Lit::Table(elems.table_lit())), s1: Space::empty(span), span, }; diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs index 2bb4eff..42123b1 100644 --- a/src/desugar/table_constr.rs +++ b/src/desugar/table_constr.rs @@ -1,5 +1,5 @@ use crate::ast::{ - BoundedSeparated, Expr, Field, Ident, Line, Lit, Space, TableConstr, TableConstrElem, TableLit, + BoundedSeparated, Expr, Field, Ident, Line, Lit, Space, TableConstr, TableConstrElem, TableLitElem, }; use crate::span::HasSpan; @@ -25,12 +25,12 @@ impl TableConstr { name: Ident::new("raw", span), s0: Space::empty(span), s1: Space::empty(span), - value: Box::new(Expr::Lit(Lit::Table(TableLit(elems)))), + value: Box::new(Expr::Lit(Lit::Table(elems.table_lit()))), span, }; - let mut expr = Expr::Lit(Lit::Table(TableLit( - BoundedSeparated::new(span).then(raw_elem), - ))); + let mut expr = Expr::Lit(Lit::Table( + BoundedSeparated::new(span).then(raw_elem).table_lit(), + )); // `sl [ s0 index s1 ] s2 = s3 value sr` // -> `expr s0 [ s1 index s2 ] s3 = s4 s5 value` diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index 8d68a00..831464b 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -5,25 +5,28 @@ use crate::ast::{ use crate::builtin::Builtin; fn pattern_to_constr(pattern: TablePattern) -> TableConstr { - TableConstr(pattern.0.map(|e| match e { - TablePatternElem::Positional(ident) => TableConstrElem::Lit(TableLitElem::Positional( - Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), - )), + pattern + .0 + .map(|e| match e { + TablePatternElem::Positional(ident) => TableConstrElem::Lit(TableLitElem::Positional( + Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + )), - TablePatternElem::Named { - name, - s0, - s1, - ident, - span, - } => TableConstrElem::Lit(TableLitElem::Named { - name, - s0, - s1, - value: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), - span, - }), - })) + TablePatternElem::Named { + name, + s0, + s1, + ident, + span, + } => TableConstrElem::Lit(TableLitElem::Named { + name, + s0, + s1, + value: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + span, + }), + }) + .table_constr() } impl TableDestr { @@ -55,7 +58,7 @@ impl TableDestr { let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Destructure, span))), s0: Space::empty(span), - constr: TableConstr(constr), + constr: constr.table_constr(), span, }); (new, true) diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 7019702..39af1e5 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -1,6 +1,5 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstr, TableConstrElem, - TableLitElem, Var, + BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem, TableLitElem, Var, }; use crate::builtin::Builtin; use crate::span::HasSpan; @@ -81,14 +80,13 @@ impl Var { s1: Space::empty(span), span, }); - let constr = TableConstr( - BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(Box::new( - scope, - )))) - .then(TableConstrElem::Lit(TableLitElem::Positional(index))) - .then(TableConstrElem::Lit(TableLitElem::Positional(value))), - ); + let constr = BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(Box::new( + scope, + )))) + .then(TableConstrElem::Lit(TableLitElem::Positional(index))) + .then(TableConstrElem::Lit(TableLitElem::Positional(value))) + .table_constr(); let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::SetRaw, span))), s0: Space::empty(span), From 42369628b69e8ef16df5631041a1a29bc10a27f3 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 15:26:51 +0100 Subject: [PATCH 14/29] Simplify boxing Expr --- src/ast/expr.rs | 6 ++++++ src/desugar/call.rs | 4 ++-- src/desugar/field.rs | 8 ++++---- src/desugar/func_def.rs | 14 +++++++------- src/desugar/lit.rs | 4 ++-- src/desugar/table_constr.rs | 4 ++-- src/desugar/table_destr.rs | 14 +++++++------- src/desugar/var.rs | 22 +++++++++++----------- src/parser/expr.rs | 10 +++++----- src/parser/func_def.rs | 12 ++++++------ src/parser/lit.rs | 4 ++-- src/parser/prefix.rs | 2 +- src/parser/suffix.rs | 12 ++++++------ src/parser/table_constr.rs | 4 ++-- src/parser/table_destr.rs | 2 +- src/parser/var.rs | 8 ++++---- 16 files changed, 68 insertions(+), 62 deletions(-) diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 9b10502..d0fa1ff 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -242,3 +242,9 @@ impl HasSpan for Expr { } } } + +impl Expr { + pub fn boxed(self) -> Box { + Box::new(self) + } +} diff --git a/src/desugar/call.rs b/src/desugar/call.rs index bef48b1..ec6ab89 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -38,7 +38,7 @@ impl Call { expr, s0, s1, - arg: Box::new(Expr::Lit(Lit::Nil(span))), + arg: Expr::Lit(Lit::Nil(span)).boxed(), s2: Space::empty(span), span, }); @@ -55,7 +55,7 @@ impl Call { expr, s0, s1: Space::empty(span), - arg: Box::new(Expr::TableConstr(constr)), + arg: Expr::TableConstr(constr).boxed(), s2: Space::empty(span), span, }); diff --git a/src/desugar/field.rs b/src/desugar/field.rs index c429f87..7bbba62 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -19,7 +19,7 @@ impl Field { .then(TableConstrElem::Lit(TableLitElem::Positional(index))) .table_constr(); let new = Expr::Call(Call::Constr { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Get, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Get, span)).boxed(), s0: Space::empty(span), constr, span, @@ -44,7 +44,7 @@ impl Field { .then(TableConstrElem::Lit(TableLitElem::Positional(value))) .table_constr(); let new = Expr::Call(Call::Constr { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Set, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Set, span)).boxed(), s0: Space::empty(span), constr, span, @@ -65,7 +65,7 @@ impl Field { expr, s0, s1, - index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + index: Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), s2: Space::empty(span), span, }); @@ -88,7 +88,7 @@ impl Field { expr, s0, s1, - index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + index: Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), s2: Space::empty(span), s3: s2, s4: s3, diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index 1b370eb..a40c88d 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -22,9 +22,9 @@ impl FuncDef { span, }) .table_lit(); - let quote = Box::new(Expr::Lit(Lit::Table(quote))); + let quote = Expr::Lit(Lit::Table(quote)).boxed(); let scope = Expr::Call(Call::NoArg { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), s0: Space::empty(span), s1: Space::empty(span), span, @@ -36,7 +36,7 @@ impl FuncDef { name: Ident::new("scope", span), s0: Space::empty(span), s1: Space::empty(span), - value: Box::new(scope), + value: scope.boxed(), span, })) .table_constr(), @@ -56,7 +56,7 @@ impl FuncDef { // `function s0 ( s1 arg s2 ) s3 body` // -> `function ( ) '{ local arg = 'arg(), body }` let arg_call = Expr::Call(Call::NoArg { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Arg, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Arg, span)).boxed(), s0: Space::empty(span), s1: Space::empty(span), span, @@ -66,18 +66,18 @@ impl FuncDef { name: arg, s0: Space::empty(span), s1: Space::empty(span), - value: Box::new(arg_call), + value: arg_call.boxed(), span, }); let body = BoundedSeparated::new(span) - .then(TableLitElem::Positional(Box::new(arg_assign))) + .then(TableLitElem::Positional(arg_assign.boxed())) .then(TableLitElem::Positional(body)) .table_lit(); let new = Expr::FuncDef(Self::AnonNoArg { s0: Space::empty(span), s1: Space::empty(span), s2: Space::empty(span), - body: Box::new(Expr::Lit(Lit::Table(body))), + body: Expr::Lit(Lit::Table(body)).boxed(), span, }); (new, true) diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs index f88efa6..9a94278 100644 --- a/src/desugar/lit.rs +++ b/src/desugar/lit.rs @@ -5,7 +5,7 @@ impl TableLitElem { match self { Self::Positional(expr) => { let (expr, desugared) = expr.desugar(); - (Self::Positional(Box::new(expr)), desugared) + (Self::Positional(expr.boxed()), desugared) } Self::Named { @@ -20,7 +20,7 @@ impl TableLitElem { name, s0, s1, - value: Box::new(value), + value: value.boxed(), span, }; (new, desugared) diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs index 42123b1..d4e3b68 100644 --- a/src/desugar/table_constr.rs +++ b/src/desugar/table_constr.rs @@ -25,7 +25,7 @@ impl TableConstr { name: Ident::new("raw", span), s0: Space::empty(span), s1: Space::empty(span), - value: Box::new(Expr::Lit(Lit::Table(elems.table_lit()))), + value: Expr::Lit(Lit::Table(elems.table_lit())).boxed(), span, }; let mut expr = Expr::Lit(Lit::Table( @@ -36,7 +36,7 @@ impl TableConstr { // -> `expr s0 [ s1 index s2 ] s3 = s4 s5 value` for (s0, (s1, index, s2, s3, s4, value, span), s5) in setters { expr = Expr::Field(Field::Assign { - expr: Box::new(expr), + expr: expr.boxed(), s0, s1, index, diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index 831464b..6428a3b 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -9,7 +9,7 @@ fn pattern_to_constr(pattern: TablePattern) -> TableConstr { .0 .map(|e| match e { TablePatternElem::Positional(ident) => TableConstrElem::Lit(TableLitElem::Positional( - Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), )), TablePatternElem::Named { @@ -22,7 +22,7 @@ fn pattern_to_constr(pattern: TablePattern) -> TableConstr { name, s0, s1, - value: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(ident)))), + value: Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), span, }), }) @@ -41,22 +41,22 @@ impl TableDestr { } = self; let mut constr = BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(Box::new( - Expr::TableConstr(pattern_to_constr(pattern)), - )))) + .then(TableConstrElem::Lit(TableLitElem::Positional( + Expr::TableConstr(pattern_to_constr(pattern)).boxed(), + ))) .then(TableConstrElem::Lit(TableLitElem::Positional(value))); if local.is_some() { constr = constr.then(TableConstrElem::Lit(TableLitElem::Named { name: Ident::new("local", span), s0: Space::empty(span), s1: Space::empty(span), - value: Box::new(Expr::Lit(Lit::Bool(true, span))), + value: Expr::Lit(Lit::Bool(true, span)).boxed(), span, })); } let new = Expr::Call(Call::Constr { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Destructure, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Destructure, span)).boxed(), s0: Space::empty(span), constr: constr.table_constr(), span, diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 39af1e5..821860d 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -16,13 +16,13 @@ impl Var { // `[ s0 index s1 ]` // -> `'scope()[ s0 index s1 ]` let scope = Expr::Call(Call::NoArg { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), s0: Space::empty(span), s1: Space::empty(span), span, }); let new = Expr::Field(Field::Access { - expr: Box::new(scope), + expr: scope.boxed(), s0: Space::empty(span), s1: s0, index, @@ -45,13 +45,13 @@ impl Var { // `[ s0 index s1 ] s2 = s3 value` // -> `'scope()[ s0 index s1 ] s2 = s3 value` let scope = Expr::Call(Call::NoArg { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), s0: Space::empty(span), s1: Space::empty(span), span, }); let new = Expr::Field(Field::Assign { - expr: Box::new(scope), + expr: scope.boxed(), s0: Space::empty(span), s1: s0, index, @@ -75,20 +75,20 @@ impl Var { span, } => { let scope = Expr::Call(Call::NoArg { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Scope, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), s0: Space::empty(span), s1: Space::empty(span), span, }); let constr = BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(Box::new( - scope, - )))) + .then(TableConstrElem::Lit(TableLitElem::Positional( + scope.boxed(), + ))) .then(TableConstrElem::Lit(TableLitElem::Positional(index))) .then(TableConstrElem::Lit(TableLitElem::Positional(value))) .table_constr(); let new = Expr::Call(Call::Constr { - expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::SetRaw, span))), + expr: Expr::Lit(Lit::Builtin(Builtin::SetRaw, span)).boxed(), s0: Space::empty(span), constr, span, @@ -102,7 +102,7 @@ impl Var { let span = name.span(); let new = Expr::Var(Self::Access { s0: Space::empty(span), - index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(name)))), + index: Expr::Lit(Lit::String(StringLit::from_ident(name))).boxed(), s1: Space::empty(span), span, }); @@ -122,7 +122,7 @@ impl Var { let new = Expr::Var(Self::Assign { local, s0: Space::empty(span), - index: Box::new(Expr::Lit(Lit::String(StringLit::from_ident(name)))), + index: Expr::Lit(Lit::String(StringLit::from_ident(name))).boxed(), s1: Space::empty(span), s2: s0, s3: s1, diff --git a/src/parser/expr.rs b/src/parser/expr.rs index 3bae445..bd2b373 100644 --- a/src/parser/expr.rs +++ b/src/parser/expr.rs @@ -18,7 +18,7 @@ fn atom_paren( .then_ignore(just(')')) .map_with_span(|((s0, inner), s1), span| Expr::Paren { s0, - inner: Box::new(inner), + inner: inner.boxed(), s1, span, }) @@ -63,11 +63,11 @@ fn left_assoc( over.then(op_over.repeated()) .foldl(|left, (s0, op, s1, right)| Expr::BinOp { span: left.span().join(right.span()), - left: Box::new(left), + left: left.boxed(), s0, op, s1, - right: Box::new(right), + right: right.boxed(), }) .boxed() } @@ -89,11 +89,11 @@ fn right_assoc( .then(over) .foldr(|(left, s0, op, s1), right| Expr::BinOp { span: left.span().join(right.span()), - left: Box::new(left), + left: left.boxed(), s0, op, s1, - right: Box::new(right), + right: right.boxed(), }) .boxed() } diff --git a/src/parser/func_def.rs b/src/parser/func_def.rs index 54765f1..3bb273d 100644 --- a/src/parser/func_def.rs +++ b/src/parser/func_def.rs @@ -19,7 +19,7 @@ fn func_def_anon_no_arg( s0, s1, s2, - body: Box::new(body), + body: body.boxed(), span, }) } @@ -45,7 +45,7 @@ fn func_def_anon_arg( arg, s2, s3, - body: Box::new(body), + body: body.boxed(), span, }, ) @@ -65,7 +65,7 @@ fn func_def_anon_destr( s0, pattern, s1, - body: Box::new(body), + body: body.boxed(), span, }) } @@ -94,7 +94,7 @@ fn func_def_named_no_arg( s1, s2, s3, - body: Box::new(body), + body: body.boxed(), span, }, ) @@ -128,7 +128,7 @@ fn func_def_named_arg( arg, s3, s4, - body: Box::new(body), + body: body.boxed(), span, }, ) @@ -157,7 +157,7 @@ fn func_def_named_destr( s1, pattern, s2, - body: Box::new(body), + body: body.boxed(), span, } }) diff --git a/src/parser/lit.rs b/src/parser/lit.rs index 6b09982..e368684 100644 --- a/src/parser/lit.rs +++ b/src/parser/lit.rs @@ -132,7 +132,7 @@ pub fn table_lit_elem( ) -> EParser { let positional = expr .clone() - .map(|value| TableLitElem::Positional(Box::new(value))); + .map(|value| TableLitElem::Positional(value.boxed())); let named = ident .then(space.clone()) @@ -143,7 +143,7 @@ pub fn table_lit_elem( name, s0, s1, - value: Box::new(value), + value: value.boxed(), span, }); diff --git a/src/parser/prefix.rs b/src/parser/prefix.rs index ddae0bd..f53c78f 100644 --- a/src/parser/prefix.rs +++ b/src/parser/prefix.rs @@ -17,7 +17,7 @@ enum Prefix { impl Prefix { fn into_expr(self, span: Span, expr: Expr) -> Expr { - let expr = Box::new(expr); + let expr = expr.boxed(); match self { Self::Neg { minus, s0 } => Expr::Neg { minus, diff --git a/src/parser/suffix.rs b/src/parser/suffix.rs index cb02008..d519c13 100644 --- a/src/parser/suffix.rs +++ b/src/parser/suffix.rs @@ -57,7 +57,7 @@ enum Suffix { impl Suffix { fn into_expr(self, span: Span, expr: Expr) -> Expr { - let expr = Box::new(expr); + let expr = expr.boxed(); match self { Self::CallArg { s0, s1, arg, s2 } => Expr::Call(Call::Arg { expr, @@ -143,7 +143,7 @@ fn suffix_call_arg( .map(|(((s0, s1), arg), s2)| Suffix::CallArg { s0, s1, - arg: Box::new(arg), + arg: arg.boxed(), s2, }) } @@ -180,7 +180,7 @@ fn suffix_field_access( .map(|(((s0, s1), index), s2)| Suffix::FieldAccess { s0, s1, - index: Box::new(index), + index: index.boxed(), s2, }) } @@ -204,11 +204,11 @@ fn suffix_field_assign( |((((((s0, s1), index), s2), s3), s4), value)| Suffix::FieldAssign { s0, s1, - index: Box::new(index), + index: index.boxed(), s2, s3, s4, - value: Box::new(value), + value: value.boxed(), }, ) } @@ -246,7 +246,7 @@ fn suffix_field_assign_ident( ident, s2, s3, - value: Box::new(value), + value: value.boxed(), }, ) } diff --git a/src/parser/table_constr.rs b/src/parser/table_constr.rs index 65abbcb..b294329 100644 --- a/src/parser/table_constr.rs +++ b/src/parser/table_constr.rs @@ -25,11 +25,11 @@ fn table_constr_elem( .map_with_span( |(((((s0, index), s1), s2), s3), value), span| TableConstrElem::Indexed { s0, - index: Box::new(index), + index: index.boxed(), s1, s2, s3, - value: Box::new(value), + value: value.boxed(), span, }, ); diff --git a/src/parser/table_destr.rs b/src/parser/table_destr.rs index 0504513..c215a19 100644 --- a/src/parser/table_destr.rs +++ b/src/parser/table_destr.rs @@ -59,7 +59,7 @@ pub fn table_destr( pattern, s0, s1, - value: Box::new(value), + value: value.boxed(), span, }) .boxed() diff --git a/src/parser/var.rs b/src/parser/var.rs index 80722e1..c5806dc 100644 --- a/src/parser/var.rs +++ b/src/parser/var.rs @@ -14,7 +14,7 @@ fn var_access(space: EParser, expr: EParser) -> impl Parser Date: Tue, 22 Nov 2022 15:48:47 +0100 Subject: [PATCH 15/29] Simplify creating Expr --- src/ast/call.rs | 6 ++++ src/ast/field.rs | 6 ++++ src/ast/func_def.rs | 6 ++++ src/ast/lit.rs | 6 ++++ src/ast/table_constr.rs | 6 ++++ src/ast/table_destr.rs | 6 ++++ src/ast/var.rs | 6 ++++ src/desugar/call.rs | 21 +++++++------ src/desugar/field.rs | 32 ++++++++++---------- src/desugar/func_def.rs | 53 ++++++++++++++++---------------- src/desugar/program.rs | 2 +- src/desugar/table_constr.rs | 11 ++++--- src/desugar/table_destr.rs | 16 +++++----- src/desugar/var.rs | 60 ++++++++++++++++++------------------- src/parser/suffix.rs | 38 +++++++++++++++-------- 15 files changed, 163 insertions(+), 112 deletions(-) diff --git a/src/ast/call.rs b/src/ast/call.rs index 547e1f1..adbbf68 100644 --- a/src/ast/call.rs +++ b/src/ast/call.rs @@ -46,3 +46,9 @@ impl HasSpan for Call { } } } + +impl Call { + pub fn expr(self) -> Expr { + Expr::Call(self) + } +} diff --git a/src/ast/field.rs b/src/ast/field.rs index 1972686..44561b4 100644 --- a/src/ast/field.rs +++ b/src/ast/field.rs @@ -67,3 +67,9 @@ impl HasSpan for Field { } } } + +impl Field { + pub fn expr(self) -> Expr { + Expr::Field(self) + } +} diff --git a/src/ast/func_def.rs b/src/ast/func_def.rs index e1e89ad..373fa4d 100644 --- a/src/ast/func_def.rs +++ b/src/ast/func_def.rs @@ -99,3 +99,9 @@ impl HasSpan for FuncDef { } } } + +impl FuncDef { + pub fn expr(self) -> Expr { + Expr::FuncDef(self) + } +} diff --git a/src/ast/lit.rs b/src/ast/lit.rs index 16c7263..091c82a 100644 --- a/src/ast/lit.rs +++ b/src/ast/lit.rs @@ -198,3 +198,9 @@ impl HasSpan for Lit { } } } + +impl Lit { + pub fn expr(self) -> Expr { + Expr::Lit(self) + } +} diff --git a/src/ast/table_constr.rs b/src/ast/table_constr.rs index 0e16ae6..679dd74 100644 --- a/src/ast/table_constr.rs +++ b/src/ast/table_constr.rs @@ -39,3 +39,9 @@ impl HasSpan for TableConstr { self.0.span() } } + +impl TableConstr { + pub fn expr(self) -> Expr { + Expr::TableConstr(self) + } +} diff --git a/src/ast/table_destr.rs b/src/ast/table_destr.rs index 6b24d8f..0aa4b5e 100644 --- a/src/ast/table_destr.rs +++ b/src/ast/table_destr.rs @@ -61,3 +61,9 @@ impl HasSpan for TableDestr { self.span } } + +impl TableDestr { + pub fn expr(self) -> Expr { + Expr::TableDestr(self) + } +} diff --git a/src/ast/var.rs b/src/ast/var.rs index 6ec6026..ce53d63 100644 --- a/src/ast/var.rs +++ b/src/ast/var.rs @@ -56,3 +56,9 @@ impl HasSpan for Var { } } } + +impl Var { + pub fn expr(self) -> Expr { + Expr::Var(self) + } +} diff --git a/src/desugar/call.rs b/src/desugar/call.rs index ec6ab89..162036b 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -27,22 +27,21 @@ impl Call { value: arg, span, }; - let new = Expr::Lit(Lit::Table( - BoundedSeparated::new(span).then(call).then(arg).table_lit(), - )); + let new = + Lit::Table(BoundedSeparated::new(span).then(call).then(arg).table_lit()).expr(); (new, true) } Self::NoArg { expr, s0, s1, span } => { - let new = Expr::Call(Self::Arg { + let new = Self::Arg { expr, s0, s1, - arg: Expr::Lit(Lit::Nil(span)).boxed(), + arg: Lit::Nil(span).expr().boxed(), s2: Space::empty(span), span, - }); - (new, true) + }; + (new.expr(), true) } Self::Constr { @@ -51,15 +50,15 @@ impl Call { constr, span, } => { - let new = Expr::Call(Self::Arg { + let new = Self::Arg { expr, s0, s1: Space::empty(span), - arg: Expr::TableConstr(constr).boxed(), + arg: constr.expr().boxed(), s2: Space::empty(span), span, - }); - (new, true) + }; + (new.expr(), true) } } } diff --git a/src/desugar/field.rs b/src/desugar/field.rs index 7bbba62..cc7f601 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -18,13 +18,13 @@ impl Field { .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) .then(TableConstrElem::Lit(TableLitElem::Positional(index))) .table_constr(); - let new = Expr::Call(Call::Constr { - expr: Expr::Lit(Lit::Builtin(Builtin::Get, span)).boxed(), + let new = Call::Constr { + expr: Lit::Builtin(Builtin::Get, span).expr().boxed(), s0: Space::empty(span), constr, span, - }); - (new, true) + }; + (new.expr(), true) } Self::Assign { @@ -43,13 +43,13 @@ impl Field { .then(TableConstrElem::Lit(TableLitElem::Positional(index))) .then(TableConstrElem::Lit(TableLitElem::Positional(value))) .table_constr(); - let new = Expr::Call(Call::Constr { - expr: Expr::Lit(Lit::Builtin(Builtin::Set, span)).boxed(), + let new = Call::Constr { + expr: Lit::Builtin(Builtin::Set, span).expr().boxed(), s0: Space::empty(span), constr, span, - }); - (new, true) + }; + (new.expr(), true) } Self::AccessIdent { @@ -61,15 +61,15 @@ impl Field { } => { // `expr s0 . s1 ident´ // -> `expr s0 [ s1 ident_str ]` - let new = Expr::Field(Self::Access { + let new = Self::Access { expr, s0, s1, - index: Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), + index: Lit::String(StringLit::from_ident(ident)).expr().boxed(), s2: Space::empty(span), span, - }); - (new, true) + }; + (new.expr(), true) } Self::AssignIdent { @@ -84,18 +84,18 @@ impl Field { } => { // `expr s0 . s1 ident s2 = s3 value` // -> `expr s0 [ s1 ident_str ] s2 = s3 value` - let new = Expr::Field(Self::Assign { + let new = Self::Assign { expr, s0, s1, - index: Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), + index: Lit::String(StringLit::from_ident(ident)).expr().boxed(), s2: Space::empty(span), s3: s2, s4: s3, value, span, - }); - (new, true) + }; + (new.expr(), true) } } } diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index a40c88d..fd2a6bc 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -22,25 +22,24 @@ impl FuncDef { span, }) .table_lit(); - let quote = Expr::Lit(Lit::Table(quote)).boxed(); - let scope = Expr::Call(Call::NoArg { - expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), + let quote = Lit::Table(quote).expr().boxed(); + let scope = Call::NoArg { + expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), s0: Space::empty(span), s1: Space::empty(span), span, - }); - let new = Expr::TableConstr( - BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(quote))) - .then(TableConstrElem::Lit(TableLitElem::Named { - name: Ident::new("scope", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: scope.boxed(), - span, - })) - .table_constr(), - ); + }; + let new = BoundedSeparated::new(span) + .then(TableConstrElem::Lit(TableLitElem::Positional(quote))) + .then(TableConstrElem::Lit(TableLitElem::Named { + name: Ident::new("scope", span), + s0: Space::empty(span), + s1: Space::empty(span), + value: scope.expr().boxed(), + span, + })) + .table_constr() + .expr(); (new, true) } @@ -55,32 +54,32 @@ impl FuncDef { } => { // `function s0 ( s1 arg s2 ) s3 body` // -> `function ( ) '{ local arg = 'arg(), body }` - let arg_call = Expr::Call(Call::NoArg { - expr: Expr::Lit(Lit::Builtin(Builtin::Arg, span)).boxed(), + let arg_call = Call::NoArg { + expr: Lit::Builtin(Builtin::Arg, span).expr().boxed(), s0: Space::empty(span), s1: Space::empty(span), span, - }); - let arg_assign = Expr::Var(Var::AssignIdent { + }; + let arg_assign = Var::AssignIdent { local: Some(Space::empty(span)), name: arg, s0: Space::empty(span), s1: Space::empty(span), - value: arg_call.boxed(), + value: arg_call.expr().boxed(), span, - }); + }; let body = BoundedSeparated::new(span) - .then(TableLitElem::Positional(arg_assign.boxed())) + .then(TableLitElem::Positional(arg_assign.expr().boxed())) .then(TableLitElem::Positional(body)) .table_lit(); - let new = Expr::FuncDef(Self::AnonNoArg { + let new = Self::AnonNoArg { s0: Space::empty(span), s1: Space::empty(span), s2: Space::empty(span), - body: Expr::Lit(Lit::Table(body)).boxed(), + body: Lit::Table(body).expr().boxed(), span, - }); - (new, true) + }; + (new.expr(), true) } Self::AnonDestr { diff --git a/src/desugar/program.rs b/src/desugar/program.rs index 73a3bda..d972273 100644 --- a/src/desugar/program.rs +++ b/src/desugar/program.rs @@ -14,7 +14,7 @@ impl Program { // -> `s0 table` let new = Self::Expr { s0, - expr: Expr::Lit(Lit::Table(elems.table_lit())), + expr: Lit::Table(elems.table_lit()).expr(), s1: Space::empty(span), span, }; diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs index d4e3b68..f74c432 100644 --- a/src/desugar/table_constr.rs +++ b/src/desugar/table_constr.rs @@ -25,17 +25,15 @@ impl TableConstr { name: Ident::new("raw", span), s0: Space::empty(span), s1: Space::empty(span), - value: Expr::Lit(Lit::Table(elems.table_lit())).boxed(), + value: Lit::Table(elems.table_lit()).expr().boxed(), span, }; - let mut expr = Expr::Lit(Lit::Table( - BoundedSeparated::new(span).then(raw_elem).table_lit(), - )); + let mut expr = Lit::Table(BoundedSeparated::new(span).then(raw_elem).table_lit()).expr(); // `sl [ s0 index s1 ] s2 = s3 value sr` // -> `expr s0 [ s1 index s2 ] s3 = s4 s5 value` for (s0, (s1, index, s2, s3, s4, value, span), s5) in setters { - expr = Expr::Field(Field::Assign { + expr = Field::Assign { expr: expr.boxed(), s0, s1, @@ -45,7 +43,8 @@ impl TableConstr { s4: s4.then_line(Line::Empty).then(s5), value, span, - }); + } + .expr(); } (expr, true) diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index 6428a3b..c07c400 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -9,7 +9,7 @@ fn pattern_to_constr(pattern: TablePattern) -> TableConstr { .0 .map(|e| match e { TablePatternElem::Positional(ident) => TableConstrElem::Lit(TableLitElem::Positional( - Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), + Lit::String(StringLit::from_ident(ident)).expr().boxed(), )), TablePatternElem::Named { @@ -22,7 +22,7 @@ fn pattern_to_constr(pattern: TablePattern) -> TableConstr { name, s0, s1, - value: Expr::Lit(Lit::String(StringLit::from_ident(ident))).boxed(), + value: Lit::String(StringLit::from_ident(ident)).expr().boxed(), span, }), }) @@ -42,7 +42,7 @@ impl TableDestr { let mut constr = BoundedSeparated::new(span) .then(TableConstrElem::Lit(TableLitElem::Positional( - Expr::TableConstr(pattern_to_constr(pattern)).boxed(), + pattern_to_constr(pattern).expr().boxed(), ))) .then(TableConstrElem::Lit(TableLitElem::Positional(value))); if local.is_some() { @@ -50,17 +50,17 @@ impl TableDestr { name: Ident::new("local", span), s0: Space::empty(span), s1: Space::empty(span), - value: Expr::Lit(Lit::Bool(true, span)).boxed(), + value: Lit::Bool(true, span).expr().boxed(), span, })); } - let new = Expr::Call(Call::Constr { - expr: Expr::Lit(Lit::Builtin(Builtin::Destructure, span)).boxed(), + let new = Call::Constr { + expr: Lit::Builtin(Builtin::Destructure, span).expr().boxed(), s0: Space::empty(span), constr: constr.table_constr(), span, - }); - (new, true) + }; + (new.expr(), true) } } diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 821860d..b77aa34 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -15,21 +15,21 @@ impl Var { } => { // `[ s0 index s1 ]` // -> `'scope()[ s0 index s1 ]` - let scope = Expr::Call(Call::NoArg { - expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), + let scope = Call::NoArg { + expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), s0: Space::empty(span), s1: Space::empty(span), span, - }); - let new = Expr::Field(Field::Access { - expr: scope.boxed(), + }; + let new = Field::Access { + expr: scope.expr().boxed(), s0: Space::empty(span), s1: s0, index, s2: s1, span, - }); - (new, true) + }; + (new.expr(), true) } Self::Assign { @@ -44,14 +44,14 @@ impl Var { } => { // `[ s0 index s1 ] s2 = s3 value` // -> `'scope()[ s0 index s1 ] s2 = s3 value` - let scope = Expr::Call(Call::NoArg { - expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), + let scope = Call::NoArg { + expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), s0: Space::empty(span), s1: Space::empty(span), span, - }); - let new = Expr::Field(Field::Assign { - expr: scope.boxed(), + }; + let new = Field::Assign { + expr: scope.expr().boxed(), s0: Space::empty(span), s1: s0, index, @@ -60,8 +60,8 @@ impl Var { s4: s3, value, span, - }); - (new, true) + }; + (new.expr(), true) } Self::Assign { @@ -74,39 +74,39 @@ impl Var { value, span, } => { - let scope = Expr::Call(Call::NoArg { - expr: Expr::Lit(Lit::Builtin(Builtin::Scope, span)).boxed(), + let scope = Call::NoArg { + expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), s0: Space::empty(span), s1: Space::empty(span), span, - }); + }; let constr = BoundedSeparated::new(span) .then(TableConstrElem::Lit(TableLitElem::Positional( - scope.boxed(), + scope.expr().boxed(), ))) .then(TableConstrElem::Lit(TableLitElem::Positional(index))) .then(TableConstrElem::Lit(TableLitElem::Positional(value))) .table_constr(); - let new = Expr::Call(Call::Constr { - expr: Expr::Lit(Lit::Builtin(Builtin::SetRaw, span)).boxed(), + let new = Call::Constr { + expr: Lit::Builtin(Builtin::SetRaw, span).expr().boxed(), s0: Space::empty(span), constr, span, - }); - (new, true) + }; + (new.expr(), true) } Self::AccessIdent(name) => { // `name` // -> `[ name_str ]` let span = name.span(); - let new = Expr::Var(Self::Access { + let new = Self::Access { s0: Space::empty(span), - index: Expr::Lit(Lit::String(StringLit::from_ident(name))).boxed(), + index: Lit::String(StringLit::from_ident(name)).expr().boxed(), s1: Space::empty(span), span, - }); - (new, true) + }; + (new.expr(), true) } Self::AssignIdent { @@ -119,17 +119,17 @@ impl Var { } => { // `local name s0 = s1 value` // -> `local [ name_str ] s0 = s1 value` - let new = Expr::Var(Self::Assign { + let new = Self::Assign { local, s0: Space::empty(span), - index: Expr::Lit(Lit::String(StringLit::from_ident(name))).boxed(), + index: Lit::String(StringLit::from_ident(name)).expr().boxed(), s1: Space::empty(span), s2: s0, s3: s1, value, span, - }); - (new, true) + }; + (new.expr(), true) } } } diff --git a/src/parser/suffix.rs b/src/parser/suffix.rs index d519c13..ca25830 100644 --- a/src/parser/suffix.rs +++ b/src/parser/suffix.rs @@ -59,29 +59,36 @@ impl Suffix { fn into_expr(self, span: Span, expr: Expr) -> Expr { let expr = expr.boxed(); match self { - Self::CallArg { s0, s1, arg, s2 } => Expr::Call(Call::Arg { + Self::CallArg { s0, s1, arg, s2 } => Call::Arg { expr, s0, s1, arg, s2, span, - }), - Self::CallNoArg { s0, s1 } => Expr::Call(Call::NoArg { expr, s0, s1, span }), - Self::CallConstr { s0, constr } => Expr::Call(Call::Constr { + } + .expr(), + + Self::CallNoArg { s0, s1 } => Call::NoArg { expr, s0, s1, span }.expr(), + + Self::CallConstr { s0, constr } => Call::Constr { expr, s0, constr, span, - }), - Self::FieldAccess { s0, s1, index, s2 } => Expr::Field(Field::Access { + } + .expr(), + + Self::FieldAccess { s0, s1, index, s2 } => Field::Access { expr, s0, s1, index, s2, span, - }), + } + .expr(), + Self::FieldAssign { s0, s1, @@ -90,7 +97,7 @@ impl Suffix { s3, s4, value, - } => Expr::Field(Field::Assign { + } => Field::Assign { expr, s0, s1, @@ -100,14 +107,18 @@ impl Suffix { s4, value, span, - }), - Self::FieldAccessIdent { s0, s1, ident } => Expr::Field(Field::AccessIdent { + } + .expr(), + + Self::FieldAccessIdent { s0, s1, ident } => Field::AccessIdent { expr, s0, s1, ident, span, - }), + } + .expr(), + Self::FieldAssignIdent { s0, s1, @@ -115,7 +126,7 @@ impl Suffix { s2, s3, value, - } => Expr::Field(Field::AssignIdent { + } => Field::AssignIdent { expr, s0, s1, @@ -124,7 +135,8 @@ impl Suffix { s3, value, span, - }), + } + .expr(), } } } From 45caafdc382c82d882a20316c412ffabfed7cc2f Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 16:29:31 +0100 Subject: [PATCH 16/29] Simplify creating Lit --- src/ast/lit.rs | 16 ++++++++++++++++ src/desugar/call.rs | 8 ++++++-- src/desugar/field.rs | 4 ++-- src/desugar/func_def.rs | 4 ++-- src/desugar/program.rs | 4 ++-- src/desugar/table_constr.rs | 8 ++++++-- src/desugar/table_destr.rs | 4 ++-- src/desugar/var.rs | 4 ++-- 8 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/ast/lit.rs b/src/ast/lit.rs index 091c82a..d3c69cd 100644 --- a/src/ast/lit.rs +++ b/src/ast/lit.rs @@ -53,6 +53,12 @@ impl HasSpan for NumLit { } } +impl NumLit { + pub fn lit(self) -> Lit { + Lit::Num(self) + } +} + #[derive(Clone)] pub enum StringLitElem { /// Normal unescaped characters @@ -100,6 +106,10 @@ impl StringLit { span: ident.span, } } + + pub fn lit(self) -> Lit { + Lit::String(self) + } } impl HasSpan for StringLit { @@ -144,6 +154,12 @@ impl HasSpan for TableLit { } } +impl TableLit { + pub fn lit(self) -> Lit { + Lit::Table(self) + } +} + #[derive(Clone)] pub enum Lit { /// `nil` diff --git a/src/desugar/call.rs b/src/desugar/call.rs index 162036b..4a84fcf 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -27,8 +27,12 @@ impl Call { value: arg, span, }; - let new = - Lit::Table(BoundedSeparated::new(span).then(call).then(arg).table_lit()).expr(); + let new = BoundedSeparated::new(span) + .then(call) + .then(arg) + .table_lit() + .lit() + .expr(); (new, true) } diff --git a/src/desugar/field.rs b/src/desugar/field.rs index cc7f601..f66a482 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -65,7 +65,7 @@ impl Field { expr, s0, s1, - index: Lit::String(StringLit::from_ident(ident)).expr().boxed(), + index: StringLit::from_ident(ident).lit().expr().boxed(), s2: Space::empty(span), span, }; @@ -88,7 +88,7 @@ impl Field { expr, s0, s1, - index: Lit::String(StringLit::from_ident(ident)).expr().boxed(), + index: StringLit::from_ident(ident).lit().expr().boxed(), s2: Space::empty(span), s3: s2, s4: s3, diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index fd2a6bc..ecbb1b4 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -22,7 +22,7 @@ impl FuncDef { span, }) .table_lit(); - let quote = Lit::Table(quote).expr().boxed(); + let quote = quote.lit().expr().boxed(); let scope = Call::NoArg { expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), s0: Space::empty(span), @@ -76,7 +76,7 @@ impl FuncDef { s0: Space::empty(span), s1: Space::empty(span), s2: Space::empty(span), - body: Lit::Table(body).expr().boxed(), + body: body.lit().expr().boxed(), span, }; (new.expr(), true) diff --git a/src/desugar/program.rs b/src/desugar/program.rs index d972273..615998b 100644 --- a/src/desugar/program.rs +++ b/src/desugar/program.rs @@ -1,4 +1,4 @@ -use crate::ast::{Expr, Lit, Program, Space}; +use crate::ast::{Program, Space}; impl Program { pub fn desugar(self) -> (Self, bool) { @@ -14,7 +14,7 @@ impl Program { // -> `s0 table` let new = Self::Expr { s0, - expr: Lit::Table(elems.table_lit()).expr(), + expr: elems.table_lit().lit().expr(), s1: Space::empty(span), span, }; diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs index f74c432..8fa183d 100644 --- a/src/desugar/table_constr.rs +++ b/src/desugar/table_constr.rs @@ -25,10 +25,14 @@ impl TableConstr { name: Ident::new("raw", span), s0: Space::empty(span), s1: Space::empty(span), - value: Lit::Table(elems.table_lit()).expr().boxed(), + value: elems.table_lit().lit().expr().boxed(), span, }; - let mut expr = Lit::Table(BoundedSeparated::new(span).then(raw_elem).table_lit()).expr(); + let mut expr = BoundedSeparated::new(span) + .then(raw_elem) + .table_lit() + .lit() + .expr(); // `sl [ s0 index s1 ] s2 = s3 value sr` // -> `expr s0 [ s1 index s2 ] s3 = s4 s5 value` diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index c07c400..cbd053b 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -9,7 +9,7 @@ fn pattern_to_constr(pattern: TablePattern) -> TableConstr { .0 .map(|e| match e { TablePatternElem::Positional(ident) => TableConstrElem::Lit(TableLitElem::Positional( - Lit::String(StringLit::from_ident(ident)).expr().boxed(), + StringLit::from_ident(ident).lit().expr().boxed(), )), TablePatternElem::Named { @@ -22,7 +22,7 @@ fn pattern_to_constr(pattern: TablePattern) -> TableConstr { name, s0, s1, - value: Lit::String(StringLit::from_ident(ident)).expr().boxed(), + value: StringLit::from_ident(ident).lit().expr().boxed(), span, }), }) diff --git a/src/desugar/var.rs b/src/desugar/var.rs index b77aa34..ffad828 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -102,7 +102,7 @@ impl Var { let span = name.span(); let new = Self::Access { s0: Space::empty(span), - index: Lit::String(StringLit::from_ident(name)).expr().boxed(), + index: StringLit::from_ident(name).lit().expr().boxed(), s1: Space::empty(span), span, }; @@ -122,7 +122,7 @@ impl Var { let new = Self::Assign { local, s0: Space::empty(span), - index: Lit::String(StringLit::from_ident(name)).expr().boxed(), + index: StringLit::from_ident(name).lit().expr().boxed(), s1: Space::empty(span), s2: s0, s3: s1, From c191486864add7a349db221c7a433a67b1b35637 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 16:35:16 +0100 Subject: [PATCH 17/29] Simplify creating TableLitElem --- src/ast/lit.rs | 12 ++++++++++++ src/desugar/call.rs | 18 ++---------------- src/desugar/func_def.rs | 18 +++++------------- src/desugar/table_constr.rs | 16 ++++++---------- src/desugar/table_destr.rs | 10 ++++------ 5 files changed, 29 insertions(+), 45 deletions(-) diff --git a/src/ast/lit.rs b/src/ast/lit.rs index d3c69cd..44df7ac 100644 --- a/src/ast/lit.rs +++ b/src/ast/lit.rs @@ -144,6 +144,18 @@ impl HasSpan for TableLitElem { } } +impl TableLitElem { + pub fn named(name: Ident, value: Box, span: Span) -> Self { + Self::Named { + name, + s0: Space::empty(span), + s1: Space::empty(span), + value, + span, + } + } +} + /// `'{ a, foo: b }` #[derive(Debug, Clone)] pub struct TableLit(pub BoundedSeparated); diff --git a/src/desugar/call.rs b/src/desugar/call.rs index 4a84fcf..b5155d1 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -13,23 +13,9 @@ impl Call { s2: _, span, } => { - let call = TableLitElem::Named { - name: Ident::new("call", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: expr, - span, - }; - let arg = TableLitElem::Named { - name: Ident::new("arg", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: arg, - span, - }; let new = BoundedSeparated::new(span) - .then(call) - .then(arg) + .then(TableLitElem::named(Ident::new("call", span), expr, span)) + .then(TableLitElem::named(Ident::new("arg", span), arg, span)) .table_lit() .lit() .expr(); diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index ecbb1b4..86e3ad8 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -14,13 +14,7 @@ impl FuncDef { span, } => { let quote = BoundedSeparated::new(span) - .then(TableLitElem::Named { - name: Ident::new("quote", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: body, - span, - }) + .then(TableLitElem::named(Ident::new("quote", span), body, span)) .table_lit(); let quote = quote.lit().expr().boxed(); let scope = Call::NoArg { @@ -31,13 +25,11 @@ impl FuncDef { }; let new = BoundedSeparated::new(span) .then(TableConstrElem::Lit(TableLitElem::Positional(quote))) - .then(TableConstrElem::Lit(TableLitElem::Named { - name: Ident::new("scope", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: scope.expr().boxed(), + .then(TableConstrElem::Lit(TableLitElem::named( + Ident::new("scope", span), + scope.expr().boxed(), span, - })) + ))) .table_constr() .expr(); (new, true) diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs index 8fa183d..cfa1c04 100644 --- a/src/desugar/table_constr.rs +++ b/src/desugar/table_constr.rs @@ -1,6 +1,5 @@ use crate::ast::{ - BoundedSeparated, Expr, Field, Ident, Line, Lit, Space, TableConstr, TableConstrElem, - TableLitElem, + BoundedSeparated, Expr, Field, Ident, Line, TableConstr, TableConstrElem, TableLitElem, }; use crate::span::HasSpan; @@ -21,15 +20,12 @@ impl TableConstr { } => Err((s0, index, s1, s2, s3, value, span)), }); - let raw_elem = TableLitElem::Named { - name: Ident::new("raw", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: elems.table_lit().lit().expr().boxed(), - span, - }; let mut expr = BoundedSeparated::new(span) - .then(raw_elem) + .then(TableLitElem::named( + Ident::new("raw", span), + elems.table_lit().lit().expr().boxed(), + span, + )) .table_lit() .lit() .expr(); diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index cbd053b..fb1e070 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -46,13 +46,11 @@ impl TableDestr { ))) .then(TableConstrElem::Lit(TableLitElem::Positional(value))); if local.is_some() { - constr = constr.then(TableConstrElem::Lit(TableLitElem::Named { - name: Ident::new("local", span), - s0: Space::empty(span), - s1: Space::empty(span), - value: Lit::Bool(true, span).expr().boxed(), + constr = constr.then(TableConstrElem::Lit(TableLitElem::named( + Ident::new("local", span), + Lit::Bool(true, span).expr().boxed(), span, - })); + ))); } let new = Call::Constr { From 58106c4c5a5c5fdc030defe5fe79d4a5903b377e Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 16:43:24 +0100 Subject: [PATCH 18/29] Simplify creating TableConstrElem --- src/ast/table_constr.rs | 24 +++++++++++++++++++++++- src/desugar/field.rs | 14 ++++++-------- src/desugar/func_def.rs | 12 +++++++----- src/desugar/lit.rs | 2 +- src/desugar/table_destr.rs | 16 ++++++++-------- src/desugar/var.rs | 10 ++++------ src/pretty/basic.rs | 2 +- 7 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/ast/table_constr.rs b/src/ast/table_constr.rs index 679dd74..52696a4 100644 --- a/src/ast/table_constr.rs +++ b/src/ast/table_constr.rs @@ -1,6 +1,6 @@ use crate::span::{HasSpan, Span}; -use super::{BoundedSeparated, Expr, Space, TableLitElem}; +use super::{BoundedSeparated, Expr, Ident, Space, TableLitElem}; #[derive(Debug, Clone)] pub enum TableConstrElem { @@ -30,6 +30,28 @@ impl HasSpan for TableConstrElem { } } +impl TableConstrElem { + pub fn positional(value: Box) -> Self { + Self::Lit(TableLitElem::Positional(value)) + } + + pub fn named(name: Ident, value: Box, span: Span) -> Self { + Self::Lit(TableLitElem::named(name, value, span)) + } + + pub fn indexed(index: Box, value: Box, span: Span) -> Self { + Self::Indexed { + s0: Space::empty(span), + index, + s1: Space::empty(span), + s2: Space::empty(span), + s3: Space::empty(span), + value, + span, + } + } +} + /// `{ a, b, foo: c, [d]: e }` #[derive(Debug, Clone)] pub struct TableConstr(pub BoundedSeparated); diff --git a/src/desugar/field.rs b/src/desugar/field.rs index f66a482..caf1cdc 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -1,6 +1,4 @@ -use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem, TableLitElem, -}; +use crate::ast::{BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem}; use crate::builtin::Builtin; impl Field { @@ -15,8 +13,8 @@ impl Field { span, } => { let constr = BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) - .then(TableConstrElem::Lit(TableLitElem::Positional(index))) + .then(TableConstrElem::positional(expr)) + .then(TableConstrElem::positional(index)) .table_constr(); let new = Call::Constr { expr: Lit::Builtin(Builtin::Get, span).expr().boxed(), @@ -39,9 +37,9 @@ impl Field { span, } => { let constr = BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(expr))) - .then(TableConstrElem::Lit(TableLitElem::Positional(index))) - .then(TableConstrElem::Lit(TableLitElem::Positional(value))) + .then(TableConstrElem::positional(expr)) + .then(TableConstrElem::positional(index)) + .then(TableConstrElem::positional(value)) .table_constr(); let new = Call::Constr { expr: Lit::Builtin(Builtin::Set, span).expr().boxed(), diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index 86e3ad8..5ac4eb2 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -15,8 +15,10 @@ impl FuncDef { } => { let quote = BoundedSeparated::new(span) .then(TableLitElem::named(Ident::new("quote", span), body, span)) - .table_lit(); - let quote = quote.lit().expr().boxed(); + .table_lit() + .lit() + .expr() + .boxed(); let scope = Call::NoArg { expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), s0: Space::empty(span), @@ -24,12 +26,12 @@ impl FuncDef { span, }; let new = BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional(quote))) - .then(TableConstrElem::Lit(TableLitElem::named( + .then(TableConstrElem::positional(quote)) + .then(TableConstrElem::named( Ident::new("scope", span), scope.expr().boxed(), span, - ))) + )) .table_constr() .expr(); (new, true) diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs index 9a94278..a514ef9 100644 --- a/src/desugar/lit.rs +++ b/src/desugar/lit.rs @@ -41,7 +41,7 @@ impl Lit { match self { Self::Table(table) => { let (table, desugared) = table.desugar(); - (Self::Table(table), desugared) + (table.lit(), desugared) } lit => (lit, false), diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index fb1e070..5981dfa 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -8,9 +8,9 @@ fn pattern_to_constr(pattern: TablePattern) -> TableConstr { pattern .0 .map(|e| match e { - TablePatternElem::Positional(ident) => TableConstrElem::Lit(TableLitElem::Positional( - StringLit::from_ident(ident).lit().expr().boxed(), - )), + TablePatternElem::Positional(ident) => { + TableConstrElem::positional(StringLit::from_ident(ident).lit().expr().boxed()) + } TablePatternElem::Named { name, @@ -41,16 +41,16 @@ impl TableDestr { } = self; let mut constr = BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional( + .then(TableConstrElem::positional( pattern_to_constr(pattern).expr().boxed(), - ))) - .then(TableConstrElem::Lit(TableLitElem::Positional(value))); + )) + .then(TableConstrElem::positional(value)); if local.is_some() { - constr = constr.then(TableConstrElem::Lit(TableLitElem::named( + constr = constr.then(TableConstrElem::named( Ident::new("local", span), Lit::Bool(true, span).expr().boxed(), span, - ))); + )); } let new = Call::Constr { diff --git a/src/desugar/var.rs b/src/desugar/var.rs index ffad828..053e5d1 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -1,5 +1,5 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem, TableLitElem, Var, + BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem, Var, }; use crate::builtin::Builtin; use crate::span::HasSpan; @@ -81,11 +81,9 @@ impl Var { span, }; let constr = BoundedSeparated::new(span) - .then(TableConstrElem::Lit(TableLitElem::Positional( - scope.expr().boxed(), - ))) - .then(TableConstrElem::Lit(TableLitElem::Positional(index))) - .then(TableConstrElem::Lit(TableLitElem::Positional(value))) + .then(TableConstrElem::positional(scope.expr().boxed())) + .then(TableConstrElem::positional(index)) + .then(TableConstrElem::positional(value)) .table_constr(); let new = Call::Constr { expr: Lit::Builtin(Builtin::SetRaw, span).expr().boxed(), diff --git a/src/pretty/basic.rs b/src/pretty/basic.rs index c8c8d8f..abc55ee 100644 --- a/src/pretty/basic.rs +++ b/src/pretty/basic.rs @@ -1,6 +1,6 @@ use pretty::{DocAllocator, DocBuilder, Pretty}; -use crate::ast::{BoundedSeparated, Ident, Space}; +use crate::ast::{BoundedSeparated, Ident}; use super::NEST_DEPTH; From 78d08968eb84a459be9536399d9372e563bb5532 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 16:45:29 +0100 Subject: [PATCH 19/29] Move BoundedSeparated helper functions into ast --- src/ast/basic.rs | 34 ++++++++++++++++++++++++++++++++++ src/desugar/basic.rs | 36 +----------------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/ast/basic.rs b/src/ast/basic.rs index ee6428a..867bcf1 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -106,6 +106,40 @@ impl BoundedSeparated { .push((Space::empty(self.span), elem, Space::empty(self.span))); self } + + pub fn map(self, f: impl Fn(E) -> E2) -> BoundedSeparated { + let elems = self + .elems + .into_iter() + .map(|(s0, e, s1)| (s0, f(e), s1)) + .collect::>(); + + BoundedSeparated { + elems, + trailing: self.trailing, + span: self.span, + } + } + + pub fn remove_map( + self, + f: impl Fn(E) -> Result, + ) -> (BoundedSeparated, Vec<(Space, E2, Space)>) { + let mut kept = vec![]; + let mut removed = vec![]; + for (s0, elem, s1) in self.elems { + match f(elem) { + Ok(elem) => kept.push((s0, elem, s1)), + Err(elem) => removed.push((s0, elem, s1)), + } + } + let new = BoundedSeparated { + elems: kept, + trailing: self.trailing, + span: self.span, + }; + (new, removed) + } } impl BoundedSeparated { diff --git a/src/desugar/basic.rs b/src/desugar/basic.rs index 6f9ec72..156445f 100644 --- a/src/desugar/basic.rs +++ b/src/desugar/basic.rs @@ -1,4 +1,4 @@ -use crate::ast::{BoundedSeparated, Space}; +use crate::ast::BoundedSeparated; impl BoundedSeparated { pub fn desugar(self, desugar_elem: impl Fn(E) -> (E, bool)) -> (Self, bool) { @@ -21,38 +21,4 @@ impl BoundedSeparated { }; (new, desugared) } - - pub fn map(self, f: impl Fn(E) -> E2) -> BoundedSeparated { - let elems = self - .elems - .into_iter() - .map(|(s0, e, s1)| (s0, f(e), s1)) - .collect::>(); - - BoundedSeparated { - elems, - trailing: self.trailing, - span: self.span, - } - } - - pub fn remove_map( - self, - f: impl Fn(E) -> Result, - ) -> (BoundedSeparated, Vec<(Space, E2, Space)>) { - let mut kept = vec![]; - let mut removed = vec![]; - for (s0, elem, s1) in self.elems { - match f(elem) { - Ok(elem) => kept.push((s0, elem, s1)), - Err(elem) => removed.push((s0, elem, s1)), - } - } - let new = BoundedSeparated { - elems: kept, - trailing: self.trailing, - span: self.span, - }; - (new, removed) - } } From 009be99aaa84038b02665f06f0398623ca03e828 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 16:55:27 +0100 Subject: [PATCH 20/29] Simplify creating Call --- src/ast/call.rs | 29 +++++++++++++++++++++++++++++ src/desugar/call.rs | 29 ++++++++++------------------- src/desugar/field.rs | 14 ++++++-------- src/desugar/func_def.rs | 26 ++++++-------------------- src/desugar/table_destr.rs | 13 ++++++------- src/desugar/var.rs | 32 ++++++-------------------------- 6 files changed, 63 insertions(+), 80 deletions(-) diff --git a/src/ast/call.rs b/src/ast/call.rs index adbbf68..6a9d13e 100644 --- a/src/ast/call.rs +++ b/src/ast/call.rs @@ -48,6 +48,35 @@ impl HasSpan for Call { } impl Call { + pub fn arg(base: Box, arg: Box, span: Span) -> Self { + Self::Arg { + expr: base, + s0: Space::empty(span), + s1: Space::empty(span), + arg, + s2: Space::empty(span), + span, + } + } + + pub fn no_arg(base: Box, span: Span) -> Self { + Self::NoArg { + expr: base, + s0: Space::empty(span), + s1: Space::empty(span), + span, + } + } + + pub fn constr(base: Box, constr: TableConstr, span: Span) -> Self { + Self::Constr { + expr: base, + s0: Space::empty(span), + constr, + span, + } + } + pub fn expr(self) -> Expr { Expr::Call(self) } diff --git a/src/desugar/call.rs b/src/desugar/call.rs index b5155d1..361bbf5 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -1,4 +1,4 @@ -use crate::ast::{BoundedSeparated, Call, Expr, Ident, Lit, Space, TableLitElem}; +use crate::ast::{BoundedSeparated, Call, Expr, Ident, Lit, TableLitElem}; // TODO Add span for just the parentheses to ast, or limit span to parentheses @@ -22,32 +22,23 @@ impl Call { (new, true) } - Self::NoArg { expr, s0, s1, span } => { - let new = Self::Arg { - expr, - s0, - s1, - arg: Lit::Nil(span).expr().boxed(), - s2: Space::empty(span), - span, - }; + Self::NoArg { + expr, + s0: _, + s1: _, + span, + } => { + let new = Self::arg(expr, Lit::Nil(span).expr().boxed(), span); (new.expr(), true) } Self::Constr { expr, - s0, + s0: _, constr, span, } => { - let new = Self::Arg { - expr, - s0, - s1: Space::empty(span), - arg: constr.expr().boxed(), - s2: Space::empty(span), - span, - }; + let new = Self::arg(expr, constr.expr().boxed(), span); (new.expr(), true) } } diff --git a/src/desugar/field.rs b/src/desugar/field.rs index caf1cdc..1c8f948 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -16,12 +16,11 @@ impl Field { .then(TableConstrElem::positional(expr)) .then(TableConstrElem::positional(index)) .table_constr(); - let new = Call::Constr { - expr: Lit::Builtin(Builtin::Get, span).expr().boxed(), - s0: Space::empty(span), + let new = Call::constr( + Lit::Builtin(Builtin::Get, span).expr().boxed(), constr, span, - }; + ); (new.expr(), true) } @@ -41,12 +40,11 @@ impl Field { .then(TableConstrElem::positional(index)) .then(TableConstrElem::positional(value)) .table_constr(); - let new = Call::Constr { - expr: Lit::Builtin(Builtin::Set, span).expr().boxed(), - s0: Space::empty(span), + let new = Call::constr( + Lit::Builtin(Builtin::Set, span).expr().boxed(), constr, span, - }; + ); (new.expr(), true) } diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index 5ac4eb2..93bdb04 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -15,26 +15,17 @@ impl FuncDef { } => { let quote = BoundedSeparated::new(span) .then(TableLitElem::named(Ident::new("quote", span), body, span)) - .table_lit() - .lit() - .expr() - .boxed(); - let scope = Call::NoArg { - expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), - s0: Space::empty(span), - s1: Space::empty(span), - span, - }; + .table_lit(); + let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); let new = BoundedSeparated::new(span) - .then(TableConstrElem::positional(quote)) + .then(TableConstrElem::positional(Box::new(quote.lit().expr()))) .then(TableConstrElem::named( Ident::new("scope", span), scope.expr().boxed(), span, )) - .table_constr() - .expr(); - (new, true) + .table_constr(); + (new.expr(), true) } Self::AnonArg { @@ -48,12 +39,7 @@ impl FuncDef { } => { // `function s0 ( s1 arg s2 ) s3 body` // -> `function ( ) '{ local arg = 'arg(), body }` - let arg_call = Call::NoArg { - expr: Lit::Builtin(Builtin::Arg, span).expr().boxed(), - s0: Space::empty(span), - s1: Space::empty(span), - span, - }; + let arg_call = Call::no_arg(Lit::Builtin(Builtin::Arg, span).expr().boxed(), span); let arg_assign = Var::AssignIdent { local: Some(Space::empty(span)), name: arg, diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs index 5981dfa..2216977 100644 --- a/src/desugar/table_destr.rs +++ b/src/desugar/table_destr.rs @@ -1,6 +1,6 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, Ident, Lit, Space, StringLit, TableConstr, TableConstrElem, - TableDestr, TableLitElem, TablePattern, TablePatternElem, + BoundedSeparated, Call, Expr, Ident, Lit, StringLit, TableConstr, TableConstrElem, TableDestr, + TableLitElem, TablePattern, TablePatternElem, }; use crate::builtin::Builtin; @@ -53,12 +53,11 @@ impl TableDestr { )); } - let new = Call::Constr { - expr: Lit::Builtin(Builtin::Destructure, span).expr().boxed(), - s0: Space::empty(span), - constr: constr.table_constr(), + let new = Call::constr( + Lit::Builtin(Builtin::Destructure, span).expr().boxed(), + constr.table_constr(), span, - }; + ); (new.expr(), true) } } diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 053e5d1..fc1b221 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -13,14 +13,7 @@ impl Var { s1, span, } => { - // `[ s0 index s1 ]` - // -> `'scope()[ s0 index s1 ]` - let scope = Call::NoArg { - expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), - s0: Space::empty(span), - s1: Space::empty(span), - span, - }; + let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); let new = Field::Access { expr: scope.expr().boxed(), s0: Space::empty(span), @@ -42,14 +35,7 @@ impl Var { value, span, } => { - // `[ s0 index s1 ] s2 = s3 value` - // -> `'scope()[ s0 index s1 ] s2 = s3 value` - let scope = Call::NoArg { - expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), - s0: Space::empty(span), - s1: Space::empty(span), - span, - }; + let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); let new = Field::Assign { expr: scope.expr().boxed(), s0: Space::empty(span), @@ -74,23 +60,17 @@ impl Var { value, span, } => { - let scope = Call::NoArg { - expr: Lit::Builtin(Builtin::Scope, span).expr().boxed(), - s0: Space::empty(span), - s1: Space::empty(span), - span, - }; + let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); let constr = BoundedSeparated::new(span) .then(TableConstrElem::positional(scope.expr().boxed())) .then(TableConstrElem::positional(index)) .then(TableConstrElem::positional(value)) .table_constr(); - let new = Call::Constr { - expr: Lit::Builtin(Builtin::SetRaw, span).expr().boxed(), - s0: Space::empty(span), + let new = Call::constr( + Lit::Builtin(Builtin::SetRaw, span).expr().boxed(), constr, span, - }; + ); (new.expr(), true) } From 6f7683ad1e7b594bc4107411b71abcd840451302 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 17:06:56 +0100 Subject: [PATCH 21/29] Simplify creating Field --- src/ast/field.rs | 48 +++++++++++++++++++++++++++++++++++++ src/desugar/call.rs | 6 ++--- src/desugar/field.rs | 38 ++++++++++------------------- src/desugar/table_constr.rs | 29 +++++++--------------- src/desugar/var.rs | 33 +++++++------------------ 5 files changed, 79 insertions(+), 75 deletions(-) diff --git a/src/ast/field.rs b/src/ast/field.rs index 44561b4..09beccd 100644 --- a/src/ast/field.rs +++ b/src/ast/field.rs @@ -69,6 +69,54 @@ impl HasSpan for Field { } impl Field { + pub fn access(base: Box, index: Box, span: Span) -> Self { + Self::Access { + expr: base, + s0: Space::empty(span), + s1: Space::empty(span), + index, + s2: Space::empty(span), + span, + } + } + + pub fn assign(base: Box, index: Box, value: Box, span: Span) -> Self { + Self::Assign { + expr: base, + s0: Space::empty(span), + s1: Space::empty(span), + index, + s2: Space::empty(span), + s3: Space::empty(span), + s4: Space::empty(span), + value, + span, + } + } + + pub fn access_ident(base: Box, ident: Ident, span: Span) -> Self { + Self::AccessIdent { + expr: base, + s0: Space::empty(span), + s1: Space::empty(span), + ident, + span, + } + } + + pub fn assign_ident(base: Box, ident: Ident, value: Box, span: Span) -> Self { + Self::AssignIdent { + expr: base, + s0: Space::empty(span), + s1: Space::empty(span), + ident, + s2: Space::empty(span), + s3: Space::empty(span), + value, + span, + } + } + pub fn expr(self) -> Expr { Expr::Field(self) } diff --git a/src/desugar/call.rs b/src/desugar/call.rs index 361bbf5..c231875 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -16,10 +16,8 @@ impl Call { let new = BoundedSeparated::new(span) .then(TableLitElem::named(Ident::new("call", span), expr, span)) .then(TableLitElem::named(Ident::new("arg", span), arg, span)) - .table_lit() - .lit() - .expr(); - (new, true) + .table_lit(); + (new.lit().expr(), true) } Self::NoArg { diff --git a/src/desugar/field.rs b/src/desugar/field.rs index 1c8f948..3c269e2 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -1,4 +1,4 @@ -use crate::ast::{BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem}; +use crate::ast::{BoundedSeparated, Call, Expr, Field, Lit, StringLit, TableConstrElem}; use crate::builtin::Builtin; impl Field { @@ -50,47 +50,35 @@ impl Field { Self::AccessIdent { expr, - s0, - s1, + s0: _, + s1: _, ident, span, } => { - // `expr s0 . s1 ident´ - // -> `expr s0 [ s1 ident_str ]` - let new = Self::Access { + let new = Self::access( expr, - s0, - s1, - index: StringLit::from_ident(ident).lit().expr().boxed(), - s2: Space::empty(span), + StringLit::from_ident(ident).lit().expr().boxed(), span, - }; + ); (new.expr(), true) } Self::AssignIdent { expr, - s0, - s1, + s0: _, + s1: _, ident, - s2, - s3, + s2: _, + s3: _, value, span, } => { - // `expr s0 . s1 ident s2 = s3 value` - // -> `expr s0 [ s1 ident_str ] s2 = s3 value` - let new = Self::Assign { + let new = Self::assign( expr, - s0, - s1, - index: StringLit::from_ident(ident).lit().expr().boxed(), - s2: Space::empty(span), - s3: s2, - s4: s3, + StringLit::from_ident(ident).lit().expr().boxed(), value, span, - }; + ); (new.expr(), true) } } diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs index cfa1c04..263d9d4 100644 --- a/src/desugar/table_constr.rs +++ b/src/desugar/table_constr.rs @@ -1,5 +1,5 @@ use crate::ast::{ - BoundedSeparated, Expr, Field, Ident, Line, TableConstr, TableConstrElem, TableLitElem, + BoundedSeparated, Expr, Field, Ident, TableConstr, TableConstrElem, TableLitElem, }; use crate::span::HasSpan; @@ -10,14 +10,14 @@ impl TableConstr { let (elems, setters) = self.0.remove_map(|e| match e { TableConstrElem::Lit(lit) => Ok(lit), TableConstrElem::Indexed { - s0, + s0: _, index, - s1, - s2, - s3, + s1: _, + s2: _, + s3: _, value, span, - } => Err((s0, index, s1, s2, s3, value, span)), + } => Err((index, value, span)), }); let mut expr = BoundedSeparated::new(span) @@ -30,21 +30,8 @@ impl TableConstr { .lit() .expr(); - // `sl [ s0 index s1 ] s2 = s3 value sr` - // -> `expr s0 [ s1 index s2 ] s3 = s4 s5 value` - for (s0, (s1, index, s2, s3, s4, value, span), s5) in setters { - expr = Field::Assign { - expr: expr.boxed(), - s0, - s1, - index, - s2, - s3, - s4: s4.then_line(Line::Empty).then(s5), - value, - span, - } - .expr(); + for (_, (index, value, span), _) in setters { + expr = Field::assign(expr.boxed(), index, value, span).expr(); } (expr, true) diff --git a/src/desugar/var.rs b/src/desugar/var.rs index fc1b221..9062ee6 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -8,45 +8,28 @@ impl Var { pub fn desugar(self) -> (Expr, bool) { match self { Self::Access { - s0, + s0: _, index, - s1, + s1: _, span, } => { let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); - let new = Field::Access { - expr: scope.expr().boxed(), - s0: Space::empty(span), - s1: s0, - index, - s2: s1, - span, - }; + let new = Field::access(scope.expr().boxed(), index, span); (new.expr(), true) } Self::Assign { local: None, - s0, + s0: _, index, - s1, - s2, - s3, + s1: _, + s2: _, + s3: _, value, span, } => { let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); - let new = Field::Assign { - expr: scope.expr().boxed(), - s0: Space::empty(span), - s1: s0, - index, - s2: s1, - s3: s2, - s4: s3, - value, - span, - }; + let new = Field::assign(scope.expr().boxed(), index, value, span); (new.expr(), true) } From 40c28d9496e3b70571c9ece9698a1b2c1f5e8211 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 17:14:52 +0100 Subject: [PATCH 22/29] Simplify creating Var --- src/ast/var.rs | 45 +++++++++++++++++++++++++++++++++++++++++ src/desugar/expr.rs | 2 +- src/desugar/func_def.rs | 11 +--------- src/desugar/var.rs | 31 ++++++++-------------------- 4 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/ast/var.rs b/src/ast/var.rs index ce53d63..d5f0eab 100644 --- a/src/ast/var.rs +++ b/src/ast/var.rs @@ -58,6 +58,51 @@ impl HasSpan for Var { } impl Var { + pub fn access(index: Box, span: Span) -> Self { + Self::Access { + s0: Space::empty(span), + index, + s1: Space::empty(span), + span, + } + } + + pub fn assign(local: bool, index: Box, value: Box, span: Span) -> Self { + let local = if local { + Some(Space::empty(span)) + } else { + None + }; + + Self::Assign { + local, + s0: Space::empty(span), + index, + s1: Space::empty(span), + s2: Space::empty(span), + s3: Space::empty(span), + value, + span, + } + } + + pub fn assign_ident(local: bool, name: Ident, value: Box, span: Span) -> Self { + let local = if local { + Some(Space::empty(span)) + } else { + None + }; + + Self::AssignIdent { + local, + name, + s0: Space::empty(span), + s1: Space::empty(span), + value, + span, + } + } + pub fn expr(self) -> Expr { Expr::Var(self) } diff --git a/src/desugar/expr.rs b/src/desugar/expr.rs index 01c6862..7b3cc26 100644 --- a/src/desugar/expr.rs +++ b/src/desugar/expr.rs @@ -5,7 +5,7 @@ impl Expr { match self { Self::Lit(lit) => { let (lit, desugared) = lit.desugar(); - (Self::Lit(lit), desugared) + (lit.expr(), desugared) } Self::Call(call) => call.desugar(), diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index 93bdb04..2eb5586 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -37,17 +37,8 @@ impl FuncDef { body, span, } => { - // `function s0 ( s1 arg s2 ) s3 body` - // -> `function ( ) '{ local arg = 'arg(), body }` let arg_call = Call::no_arg(Lit::Builtin(Builtin::Arg, span).expr().boxed(), span); - let arg_assign = Var::AssignIdent { - local: Some(Space::empty(span)), - name: arg, - s0: Space::empty(span), - s1: Space::empty(span), - value: arg_call.expr().boxed(), - span, - }; + let arg_assign = Var::assign_ident(true, arg, arg_call.expr().boxed(), span); let body = BoundedSeparated::new(span) .then(TableLitElem::Positional(arg_assign.expr().boxed())) .then(TableLitElem::Positional(body)) diff --git a/src/desugar/var.rs b/src/desugar/var.rs index 9062ee6..0ab0a76 100644 --- a/src/desugar/var.rs +++ b/src/desugar/var.rs @@ -1,6 +1,4 @@ -use crate::ast::{ - BoundedSeparated, Call, Expr, Field, Lit, Space, StringLit, TableConstrElem, Var, -}; +use crate::ast::{BoundedSeparated, Call, Expr, Field, Lit, StringLit, TableConstrElem, Var}; use crate::builtin::Builtin; use crate::span::HasSpan; @@ -58,38 +56,25 @@ impl Var { } Self::AccessIdent(name) => { - // `name` - // -> `[ name_str ]` let span = name.span(); - let new = Self::Access { - s0: Space::empty(span), - index: StringLit::from_ident(name).lit().expr().boxed(), - s1: Space::empty(span), - span, - }; + let new = Self::access(StringLit::from_ident(name).lit().expr().boxed(), span); (new.expr(), true) } Self::AssignIdent { local, name, - s0, - s1, + s0: _, + s1: _, value, span, } => { - // `local name s0 = s1 value` - // -> `local [ name_str ] s0 = s1 value` - let new = Self::Assign { - local, - s0: Space::empty(span), - index: StringLit::from_ident(name).lit().expr().boxed(), - s1: Space::empty(span), - s2: s0, - s3: s1, + let new = Self::assign( + local.is_some(), + StringLit::from_ident(name).lit().expr().boxed(), value, span, - }; + ); (new.expr(), true) } } From 26dc3c3469d3fde0a6088f3fe3496d160340bd80 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 17:27:06 +0100 Subject: [PATCH 23/29] Desugar all function definitions --- src/ast/func_def.rs | 32 ++++++++++++++++++++ src/ast/table_destr.rs | 17 +++++++++++ src/desugar/func_def.rs | 66 +++++++++++++++++++++++++++++------------ 3 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/ast/func_def.rs b/src/ast/func_def.rs index 373fa4d..5cdd210 100644 --- a/src/ast/func_def.rs +++ b/src/ast/func_def.rs @@ -101,6 +101,38 @@ impl HasSpan for FuncDef { } impl FuncDef { + pub fn anon_no_arg(body: Box, span: Span) -> Self { + Self::AnonNoArg { + s0: Space::empty(span), + s1: Space::empty(span), + s2: Space::empty(span), + body, + span, + } + } + + pub fn anon_arg(arg: Ident, body: Box, span: Span) -> Self { + Self::AnonArg { + s0: Space::empty(span), + s1: Space::empty(span), + arg, + s2: Space::empty(span), + s3: Space::empty(span), + body, + span, + } + } + + pub fn anon_destr(pattern: TablePattern, body: Box, span: Span) -> Self { + Self::AnonDestr { + s0: Space::empty(span), + pattern, + s1: Space::empty(span), + body, + span, + } + } + pub fn expr(self) -> Expr { Expr::FuncDef(self) } diff --git a/src/ast/table_destr.rs b/src/ast/table_destr.rs index 0aa4b5e..d94b4eb 100644 --- a/src/ast/table_destr.rs +++ b/src/ast/table_destr.rs @@ -63,6 +63,23 @@ impl HasSpan for TableDestr { } impl TableDestr { + pub fn new(local: bool, pattern: TablePattern, value: Box, span: Span) -> Self { + let local = if local { + Some(Space::empty(span)) + } else { + None + }; + + Self { + local, + pattern, + s0: Space::empty(span), + s1: Space::empty(span), + value, + span, + } + } + pub fn expr(self) -> Expr { Expr::TableDestr(self) } diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs index 2eb5586..2a549d1 100644 --- a/src/desugar/func_def.rs +++ b/src/desugar/func_def.rs @@ -1,5 +1,6 @@ use crate::ast::{ - BoundedSeparated, Call, Expr, FuncDef, Ident, Lit, Space, TableConstrElem, TableLitElem, Var, + BoundedSeparated, Call, Expr, FuncDef, Ident, Lit, Space, TableConstrElem, TableDestr, + TableLitElem, Var, }; use crate::builtin::Builtin; @@ -54,47 +55,74 @@ impl FuncDef { } Self::AnonDestr { - s0, + s0: _, pattern, - s1, + s1: _, body, span, - } => todo!(), + } => { + let arg_call = Call::no_arg(Lit::Builtin(Builtin::Arg, span).expr().boxed(), span); + let arg_destr = TableDestr::new(true, pattern, arg_call.expr().boxed(), span); + let body = BoundedSeparated::new(span) + .then(TableLitElem::Positional(arg_destr.expr().boxed())) + .then(TableLitElem::Positional(body)) + .table_lit(); + let new = Self::AnonNoArg { + s0: Space::empty(span), + s1: Space::empty(span), + s2: Space::empty(span), + body: body.lit().expr().boxed(), + span, + }; + (new.expr(), true) + } Self::NamedNoArg { local, - s0, + s0: _, name, - s1, - s2, - s3, + s1: _, + s2: _, + s3: _, body, span, - } => todo!(), + } => { + let anon = Self::anon_no_arg(body, span); + let new = Var::assign_ident(local.is_some(), name, anon.expr().boxed(), span); + (new.expr(), true) + } Self::NamedArg { local, - s0, + s0: _, name, - s1, - s2, + s1: _, + s2: _, arg, - s3, - s4, + s3: _, + s4: _, body, span, - } => todo!(), + } => { + let anon = Self::anon_arg(arg, body, span); + let new = Var::assign_ident(local.is_some(), name, anon.expr().boxed(), span); + (new.expr(), true) + } Self::NamedDestr { local, - s0, + s0: _, name, - s1, + s1: _, pattern, - s2, + s2: _, body, span, - } => todo!(), + } => { + let anon = Self::anon_destr(pattern, body, span); + let new = Var::assign_ident(local.is_some(), name, anon.expr().boxed(), span); + (new.expr(), true) + } } } } From f8fa04425913b1523b5c6ce4ef18235f260ef324 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 17:39:02 +0100 Subject: [PATCH 24/29] Desugar all expressions --- src/builtin.rs | 30 ++++++++++++++++ src/desugar/expr.rs | 87 +++++++++++++++++++++------------------------ 2 files changed, 71 insertions(+), 46 deletions(-) diff --git a/src/builtin.rs b/src/builtin.rs index f0e504d..6ef18c8 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -12,6 +12,21 @@ pub enum Builtin { Scope, Arg, Destructure, + Neg, + Not, + Mul, + Div, + Mod, + Add, + Sub, + Eq, + Ne, + Gt, + Ge, + Lt, + Le, + And, + Or, } impl fmt::Debug for Builtin { @@ -26,6 +41,21 @@ impl fmt::Debug for Builtin { Self::Scope => write!(f, "'scope"), Self::Arg => write!(f, "'arg"), Self::Destructure => write!(f, "'destructure"), + Self::Neg => write!(f, "'neg"), + Self::Not => write!(f, "'not"), + Self::Mul => write!(f, "'mul"), + Self::Div => write!(f, "'div"), + Self::Mod => write!(f, "'mod"), + Self::Add => write!(f, "'add"), + Self::Sub => write!(f, "'sub"), + Self::Eq => write!(f, "'eq"), + Self::Ne => write!(f, "'ne"), + Self::Gt => write!(f, "'gt"), + Self::Ge => write!(f, "'ge"), + Self::Lt => write!(f, "'lt"), + Self::Le => write!(f, "'le"), + Self::And => write!(f, "'and"), + Self::Or => write!(f, "'or"), } } } diff --git a/src/desugar/expr.rs b/src/desugar/expr.rs index 7b3cc26..b7f4b08 100644 --- a/src/desugar/expr.rs +++ b/src/desugar/expr.rs @@ -1,4 +1,5 @@ -use crate::ast::Expr; +use crate::ast::{BinOp, BoundedSeparated, Call, Expr, Lit, TableConstrElem}; +use crate::builtin::Builtin; impl Expr { pub fn desugar(self) -> (Self, bool) { @@ -16,68 +17,62 @@ impl Expr { Self::FuncDef(def) => def.desugar(), Self::Paren { - s0, + s0: _, inner, - s1, - span, - } => ( - Self::Paren { - s0, - inner, - s1, - span, - }, - false, - ), // TODO Implement + s1: _, + span: _, + } => (*inner, true), Self::Neg { minus, - s0, + s0: _, expr, span, - } => ( - Self::Neg { - minus, - s0, - expr, - span, - }, - false, - ), // TODO Implement + } => { + let new = Call::arg(Lit::Builtin(Builtin::Neg, minus).expr().boxed(), expr, span); + (new.expr(), true) + } Self::Not { not, - s0, + s0: _, expr, span, - } => ( - Self::Not { - not, - s0, - expr, - span, - }, - false, - ), // TODO Implement + } => { + let new = Call::arg(Lit::Builtin(Builtin::Not, not).expr().boxed(), expr, span); + (new.expr(), true) + } Self::BinOp { left, - s0, + s0: _, op, - s1, + s1: _, right, span, - } => ( - Self::BinOp { - left, - s0, - op, - s1, - right, - span, - }, - false, - ), // TODO Implement + } => { + let builtin = match op { + BinOp::Mul => Builtin::Mul, + BinOp::Div => Builtin::Div, + BinOp::Mod => Builtin::Mod, + BinOp::Add => Builtin::Add, + BinOp::Sub => Builtin::Sub, + BinOp::Eq => Builtin::Eq, + BinOp::Neq => Builtin::Ne, + BinOp::Gt => Builtin::Gt, + BinOp::Ge => Builtin::Ge, + BinOp::Lt => Builtin::Lt, + BinOp::Le => Builtin::Le, + BinOp::And => Builtin::And, + BinOp::Or => Builtin::Or, + }; + let constr = BoundedSeparated::new(span) + .then(TableConstrElem::positional(left)) + .then(TableConstrElem::positional(right)) + .table_constr(); + let new = Call::constr(Lit::Builtin(builtin, span).expr().boxed(), constr, span); + (new.expr(), true) + } } } } From 39099037a5763cebbce47dbee963df6510200c51 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 17:39:56 +0100 Subject: [PATCH 25/29] Remove unused functions --- src/ast/basic.rs | 11 ----------- src/ast/field.rs | 23 ----------------------- src/ast/lit.rs | 6 ------ src/ast/table_constr.rs | 12 ------------ 4 files changed, 52 deletions(-) diff --git a/src/ast/basic.rs b/src/ast/basic.rs index 867bcf1..8a722c3 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -39,17 +39,6 @@ impl Space { span, } } - - pub fn then(mut self, other: Self) -> Self { - self.lines.extend(other.lines); - self.span = self.span.join(other.span); - self - } - - pub fn then_line(mut self, line: Line) -> Self { - self.lines.push(line); - self - } } #[derive(Clone)] diff --git a/src/ast/field.rs b/src/ast/field.rs index 09beccd..5afd98f 100644 --- a/src/ast/field.rs +++ b/src/ast/field.rs @@ -94,29 +94,6 @@ impl Field { } } - pub fn access_ident(base: Box, ident: Ident, span: Span) -> Self { - Self::AccessIdent { - expr: base, - s0: Space::empty(span), - s1: Space::empty(span), - ident, - span, - } - } - - pub fn assign_ident(base: Box, ident: Ident, value: Box, span: Span) -> Self { - Self::AssignIdent { - expr: base, - s0: Space::empty(span), - s1: Space::empty(span), - ident, - s2: Space::empty(span), - s3: Space::empty(span), - value, - span, - } - } - pub fn expr(self) -> Expr { Expr::Field(self) } diff --git a/src/ast/lit.rs b/src/ast/lit.rs index 44df7ac..ecd166c 100644 --- a/src/ast/lit.rs +++ b/src/ast/lit.rs @@ -53,12 +53,6 @@ impl HasSpan for NumLit { } } -impl NumLit { - pub fn lit(self) -> Lit { - Lit::Num(self) - } -} - #[derive(Clone)] pub enum StringLitElem { /// Normal unescaped characters diff --git a/src/ast/table_constr.rs b/src/ast/table_constr.rs index 52696a4..38c409d 100644 --- a/src/ast/table_constr.rs +++ b/src/ast/table_constr.rs @@ -38,18 +38,6 @@ impl TableConstrElem { pub fn named(name: Ident, value: Box, span: Span) -> Self { Self::Lit(TableLitElem::named(name, value, span)) } - - pub fn indexed(index: Box, value: Box, span: Span) -> Self { - Self::Indexed { - s0: Space::empty(span), - index, - s1: Space::empty(span), - s2: Space::empty(span), - s3: Space::empty(span), - value, - span, - } - } } /// `{ a, b, foo: c, [d]: e }` From 736174d470e188899d5c1911049c3fb7eee154dc Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 17:49:12 +0100 Subject: [PATCH 26/29] Desugar away named nil in table literals --- src/desugar/lit.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs index a514ef9..f5942b5 100644 --- a/src/desugar/lit.rs +++ b/src/desugar/lit.rs @@ -1,4 +1,4 @@ -use crate::ast::{Lit, TableLit, TableLitElem}; +use crate::ast::{Expr, Lit, TableLit, TableLitElem}; impl TableLitElem { pub fn desugar(self) -> (Self, bool) { @@ -32,7 +32,17 @@ impl TableLitElem { impl TableLit { pub fn desugar(self) -> (Self, bool) { let (elems, desugared) = self.0.desugar(|e| e.desugar()); - (elems.table_lit(), desugared) + if desugared { + (elems.table_lit(), true) + } else { + let (elems, removed) = elems.remove_map(|e| match e { + TableLitElem::Named { value, .. } if matches!(*value, Expr::Lit(Lit::Nil(_))) => { + Err(()) + } + e => Ok(e), + }); + (elems.table_lit(), !removed.is_empty()) + } } } From f6c9835e29896e03b65e49eda97d3dd660d737af Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 21:50:20 +0100 Subject: [PATCH 27/29] Hide warnings in pretty module for now --- src/pretty.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pretty.rs b/src/pretty.rs index 20844f6..cb1d34f 100644 --- a/src/pretty.rs +++ b/src/pretty.rs @@ -1,3 +1,6 @@ +// TODO Remove this and print whitespace and comments properly +#![allow(unused_variables)] + use pretty::{Pretty, RcAllocator}; mod basic; From af4311ba98d40d7bdbabfbcd5d51784b2909bc17 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 21:56:50 +0100 Subject: [PATCH 28/29] Remove named nils as early as possible --- src/desugar/lit.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs index f5942b5..3b6fd80 100644 --- a/src/desugar/lit.rs +++ b/src/desugar/lit.rs @@ -31,17 +31,17 @@ impl TableLitElem { impl TableLit { pub fn desugar(self) -> (Self, bool) { - let (elems, desugared) = self.0.desugar(|e| e.desugar()); - if desugared { - (elems.table_lit(), true) + let (elems, removed) = self.0.remove_map(|e| match e { + TableLitElem::Named { value, .. } if matches!(*value, Expr::Lit(Lit::Nil(_))) => { + Err(()) + } + e => Ok(e), + }); + if removed.is_empty() { + let (elems, desugared) = elems.desugar(|e| e.desugar()); + (elems.table_lit(), desugared) } else { - let (elems, removed) = elems.remove_map(|e| match e { - TableLitElem::Named { value, .. } if matches!(*value, Expr::Lit(Lit::Nil(_))) => { - Err(()) - } - e => Ok(e), - }); - (elems.table_lit(), !removed.is_empty()) + (elems.table_lit(), true) } } } From 802d776f2959e8c4eb72ce78fc1a99b7e7a8be60 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 23:13:08 +0100 Subject: [PATCH 29/29] Include trailing newline in pretty print output --- src/main.rs | 2 +- src/pretty.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index a40fedc..0ac0aed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,7 +80,7 @@ fn main() -> anyhow::Result<()> { .parse(stream) .map_err(|e| anyhow!("{e:?}"))?; - println!("{}", pretty::pretty_to_string(program, 100)); + print!("{}", pretty::pretty_to_string(program, 100)); } Command::Desugar { diff --git a/src/pretty.rs b/src/pretty.rs index cb1d34f..0c91c87 100644 --- a/src/pretty.rs +++ b/src/pretty.rs @@ -21,5 +21,7 @@ pub fn pretty_to_string>(p: P, width: usize) -> p.pretty(&RcAllocator) .render(width, &mut out) .expect("p could not be rendered"); - String::from_utf8(out).expect("p created non-utf8 string") + let mut s = String::from_utf8(out).expect("p created non-utf8 string"); + s.push('\n'); + s }