From af6c171eb4afcdc02f66a01884572b5a55eba072 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 22 Nov 2022 09:44:29 +0100 Subject: [PATCH] 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) + } +}