From 290cef06cbe4ddace38b2b090edef4d4c8d9583c Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 21 Nov 2022 14:35:10 +0100 Subject: [PATCH] Desugar from the outside in --- src/ast/basic.rs | 11 +++++ src/desugar/call.rs | 74 ++++++------------------------ src/desugar/field.rs | 102 +++++++---------------------------------- src/desugar/lit.rs | 19 ++++++-- src/desugar/program.rs | 21 +++------ 5 files changed, 62 insertions(+), 165 deletions(-) diff --git a/src/ast/basic.rs b/src/ast/basic.rs index e78a9bf..b9e5df0 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -37,6 +37,17 @@ 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/desugar/call.rs b/src/desugar/call.rs index 339c956..690f99e 100644 --- a/src/desugar/call.rs +++ b/src/desugar/call.rs @@ -13,44 +13,20 @@ impl Call { s2, span, } => { - let (expr, desugared) = expr.desugar(); - if desugared { - let new = Expr::Call(Self::Arg { - expr: Box::new(expr), - s0, - s1, - arg, - s2, - span, - }); - return (new, true); - } - - let (arg, desugared) = arg.desugar(); - if desugared { - let new = Expr::Call(Self::Arg { - expr: Box::new(expr), - s0, - s1, - arg: Box::new(arg), - s2, - span, - }); - return (new, true); - } - + // `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), s1: Space::empty(span), - value: Box::new(expr), + value: expr, span, }; let arg = TableLitElem::Named { name: Ident::new("arg", span), s0: Space::empty(span), - s1: Space::empty(span), - value: Box::new(arg), + s1, + value: arg, span, }; let elems = Separated::NonEmpty { @@ -60,32 +36,22 @@ impl Call { span, }; let new = Expr::Lit(Lit::Table(TableLit { - s0: Space::empty(span), + s0, elems, - s1: Space::empty(span), + s1: s2, span, })); (new, true) } Self::NoArg { expr, s0, s1, span } => { - let (expr, desugared) = expr.desugar(); - if desugared { - let new = Expr::Call(Self::NoArg { - expr: Box::new(expr), - s0, - s1, - span, - }); - return (new, true); - } - - let arg = Expr::Lit(Lit::Nil(span)); + // `expr s0 ( s1 )` + // -> `expr s0 ( s1 nil )` let new = Expr::Call(Self::Arg { - expr: Box::new(expr), + expr, s0, s1, - arg: Box::new(arg), + arg: Box::new(Expr::Lit(Lit::Nil(span))), s2: Space::empty(span), span, }); @@ -98,23 +64,13 @@ impl Call { constr, span, } => { - let (expr, desugared) = expr.desugar(); - if desugared { - let new = Expr::Call(Self::Constr { - expr: Box::new(expr), - s0, - constr, - span, - }); - return (new, true); - } - - let arg = Expr::TableConstr(constr); + // `expr s0 {..}` + // -> `expr s0 ( {..} )` let new = Expr::Call(Self::Arg { - expr: Box::new(expr), + expr, s0, s1: Space::empty(span), - arg: Box::new(arg), + arg: Box::new(Expr::TableConstr(constr)), s2: Space::empty(span), span, }); diff --git a/src/desugar/field.rs b/src/desugar/field.rs index 31df828..8a8b9c2 100644 --- a/src/desugar/field.rs +++ b/src/desugar/field.rs @@ -1,5 +1,5 @@ use crate::ast::{ - Call, Expr, Field, Lit, Separated, Space, TableConstr, TableConstrElem, TableLitElem, + Call, Expr, Field, Line, Lit, Separated, Space, TableConstr, TableConstrElem, TableLitElem, }; use crate::builtin::Builtin; @@ -14,37 +14,13 @@ impl Field { s2, span, } => { - let (expr, desugared) = expr.desugar(); - if desugared { - let new = Expr::Field(Self::Access { - expr: Box::new(expr), - s0, - s1, - index, - s2, - span, - }); - return (new, true); - } - - let (index, desugared) = index.desugar(); - if desugared { - let new = Expr::Field(Self::Access { - expr: Box::new(expr), - s0, - s1, - index: Box::new(index), - s2, - span, - }); - return (new, true); - } - + // ` expr s0 [ s1 index s2 ]` + // -> `'get s0 { expr, s1 index s2 }` let elems = Separated::NonEmpty { - first_elem: TableConstrElem::Lit(TableLitElem::Positional(Box::new(expr))), + first_elem: TableConstrElem::Lit(TableLitElem::Positional(expr)), last_elems: vec![( - (Space::empty(span), Space::empty(span)), - TableConstrElem::Lit(TableLitElem::Positional(Box::new(index))), + (Space::empty(span), s1), + TableConstrElem::Lit(TableLitElem::Positional(index)), )], trailing: None, span, @@ -52,12 +28,12 @@ impl Field { let constr = TableConstr { s0: Space::empty(span), elems, - s1: Space::empty(span), + s1: s2, span, }; let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Get, span))), - s0: Space::empty(span), + s0, constr, span, }); @@ -75,64 +51,18 @@ impl Field { value, span, } => { - let (expr, desugared) = expr.desugar(); - if desugared { - let new = Expr::Field(Self::Assign { - expr: Box::new(expr), - s0, - s1, - index, - s2, - s3, - s4, - value, - span, - }); - return (new, true); - } - - let (index, desugared) = index.desugar(); - if desugared { - let new = Expr::Field(Self::Assign { - expr: Box::new(expr), - s0, - s1, - index: Box::new(index), - s2, - s3, - s4, - value, - span, - }); - return (new, true); - } - - let (value, desugared) = value.desugar(); - if desugared { - let new = Expr::Field(Self::Assign { - expr: Box::new(expr), - s0, - s1, - index: Box::new(index), - s2, - s3, - s4, - value: Box::new(value), - span, - }); - return (new, true); - } - + // `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(Box::new(expr))), + first_elem: TableConstrElem::Lit(TableLitElem::Positional(expr)), last_elems: vec![ ( - (Space::empty(span), Space::empty(span)), - TableConstrElem::Lit(TableLitElem::Positional(Box::new(index))), + (Space::empty(span), s1), + TableConstrElem::Lit(TableLitElem::Positional(index)), ), ( - (Space::empty(span), Space::empty(span)), - TableConstrElem::Lit(TableLitElem::Positional(Box::new(value))), + (s2, s3.then_line(Line::Empty).then(s4)), + TableConstrElem::Lit(TableLitElem::Positional(value)), ), ], trailing: None, @@ -146,7 +76,7 @@ impl Field { }; let new = Expr::Call(Call::Constr { expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Set, span))), - s0: Space::empty(span), + s0, constr, span, }); diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs index 56c9e0f..348c3c7 100644 --- a/src/desugar/lit.rs +++ b/src/desugar/lit.rs @@ -7,6 +7,7 @@ impl TableLitElem { let (expr, desugared) = expr.desugar(); (Self::Positional(Box::new(expr)), desugared) } + Self::Named { name, s0, @@ -30,12 +31,19 @@ impl TableLitElem { impl TableLit { pub fn desugar(self) -> (Self, bool) { - let (elems, desugared) = self.elems.desugar_elem(|e| e.desugar()); - let new = Self { - s0: self.s0, + let Self { + s0, elems, - s1: self.s1, - span: self.span, + s1, + span, + } = self; + + let (elems, desugared) = elems.desugar_elem(|e| e.desugar()); + let new = Self { + s0, + elems, + s1, + span, }; (new, desugared) } @@ -48,6 +56,7 @@ impl Lit { let (table, desugared) = table.desugar(); (Self::Table(table), desugared) } + lit => (lit, false), } } diff --git a/src/desugar/program.rs b/src/desugar/program.rs index a529b07..7960cbc 100644 --- a/src/desugar/program.rs +++ b/src/desugar/program.rs @@ -5,7 +5,8 @@ impl Program { match self { Self::Expr { s0, expr, s1, span } => { let (expr, desugared) = expr.desugar(); - (Self::Expr { s0, expr, s1, span }, desugared) + let new = Self::Expr { s0, expr, s1, span }; + (new, desugared) } Self::Module { @@ -15,28 +16,18 @@ impl Program { s2, span, } => { - let (elems, desugared) = elems.desugar_elem(|e| e.desugar()); - if desugared { - let new = Self::Module { - s0, - s1, - elems, - s2, - span, - }; - return (new, true); - } - + // `s0 module s1 elems s2` + // -> `s0 '{ s1 elems s2 } empty` let table = TableLit { s0: s1, elems, - s1: Space::empty(span), + s1: s2, span, }; let new = Self::Expr { s0, expr: Expr::Lit(Lit::Table(table)), - s1: s2, + s1: Space::empty(span), span, }; (new, true)