diff --git a/Cargo.lock b/Cargo.lock index 53d7c73..d5cd11a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,15 +120,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - [[package]] name = "getrandom" version = "0.2.8" @@ -155,15 +146,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "libc" version = "0.2.137" @@ -251,24 +233,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "strsim" version = "0.10.0" @@ -294,21 +258,6 @@ dependencies = [ "chumsky", "clap", "pretty", - "tempfile", -] - -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2e725f7..3a7b52e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,3 @@ anyhow = "1.0.66" chumsky = "0.8.0" clap = { version = "4.0.26", features = ["derive", "deprecated"] } pretty = "0.11.3" -tempfile = "3.3.0" diff --git a/src/ast/basic.rs b/src/ast/basic.rs index 8a722c3..1194111 100644 --- a/src/ast/basic.rs +++ b/src/ast/basic.rs @@ -2,8 +2,6 @@ use std::fmt; use crate::span::{HasSpan, Span}; -use super::{TableConstr, TableConstrElem, TableLit, TableLitElem}; - #[derive(Clone)] pub enum Line { Empty, @@ -32,30 +30,12 @@ impl HasSpan for Space { } } -impl Space { - pub fn empty(span: Span) -> Self { - Self { - lines: vec![], - span, - } - } -} - #[derive(Clone)] pub struct Ident { pub name: String, pub span: Span, } -impl Ident { - pub fn new(name: S, span: Span) -> Self { - Self { - name: name.to_string(), - span, - } - } -} - impl fmt::Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "i#{}", self.name) @@ -69,76 +49,21 @@ impl HasSpan for Ident { } #[derive(Debug, Clone)] -pub struct BoundedSeparated { - pub elems: Vec<(Space, E, Space)>, - pub trailing: Option, - pub span: Span, +pub enum Separated { + Empty(Span), + NonEmpty { + first_elem: E, + last_elems: Vec<(S1, E)>, + trailing: Option, + span: Span, + }, } -impl HasSpan for BoundedSeparated { +impl HasSpan for Separated { fn span(&self) -> Span { - self.span - } -} - -impl BoundedSeparated { - pub fn new(span: Span) -> Self { - Self { - elems: vec![], - trailing: None, - span, + match self { + Separated::Empty(span) => *span, + Separated::NonEmpty { span, .. } => *span, } } - - pub fn then(mut self, elem: E) -> Self { - self.elems - .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 { - pub fn table_lit(self) -> TableLit { - TableLit(self) - } -} - -impl BoundedSeparated { - pub fn table_constr(self) -> TableConstr { - TableConstr(self) - } } diff --git a/src/ast/call.rs b/src/ast/call.rs index 6a9d13e..10f82e8 100644 --- a/src/ast/call.rs +++ b/src/ast/call.rs @@ -40,44 +40,9 @@ pub enum Call { impl HasSpan for Call { fn span(&self) -> Span { match self { - Self::Arg { span, .. } => *span, - Self::NoArg { span, .. } => *span, - Self::Constr { span, .. } => *span, + Call::Arg { span, .. } => *span, + Call::NoArg { span, .. } => *span, + Call::Constr { span, .. } => *span, } } } - -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/ast/expr.rs b/src/ast/expr.rs index d0fa1ff..522f2f1 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -4,30 +4,18 @@ use crate::span::{HasSpan, Span}; use super::{Call, Field, FuncDef, Lit, Space, TableConstr, TableDestr, Var}; -// Warning: If you change these precedences and associativities, you need to -// update the parser and pretty-printer as well. - -// Warning: Operators at the same precedence must also have the same -// associativity. - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Assoc { - Left, - Right, -} - #[derive(Debug, Clone, Copy)] pub enum BinOp { + /// `+` + Add, + /// `-` + Sub, /// `*` Mul, /// `/` Div, /// `%` Mod, - /// `+` - Add, - /// `-` - Sub, /// `==` Eq, /// `!=` @@ -46,36 +34,6 @@ pub enum BinOp { Or, } -impl BinOp { - /// The higher the precedence, the more strongly the operator binds. - pub fn precedence(self) -> u8 { - match self { - Self::Mul | Self::Div | Self::Mod => 4, - Self::Add | Self::Sub => 3, - Self::Eq | Self::Neq | Self::Gt | Self::Ge | Self::Lt | Self::Le => 2, - Self::And => 1, - Self::Or => 0, - } - } - - pub fn assoc(self) -> Assoc { - match self { - Self::Mul - | Self::Div - | Self::Mod - | Self::Add - | Self::Sub - | Self::Eq - | Self::Neq - | Self::Gt - | Self::Ge - | Self::Lt - | Self::Le => Assoc::Left, - Self::And | Self::Or => Assoc::Right, - } - } -} - #[derive(Clone)] pub enum Expr { Lit(Lit), @@ -228,23 +186,17 @@ impl fmt::Debug for Expr { impl HasSpan for Expr { fn span(&self) -> Span { match self { - Self::Lit(lit) => lit.span(), - Self::Call(call) => call.span(), - Self::Field(field) => field.span(), - Self::Var(var) => var.span(), - Self::TableConstr(constr) => constr.span(), - Self::TableDestr(destr) => destr.span(), - Self::FuncDef(def) => def.span(), - Self::Paren { span, .. } => *span, - Self::Neg { span, .. } => *span, - Self::Not { span, .. } => *span, - Self::BinOp { span, .. } => *span, + Expr::Lit(lit) => lit.span(), + Expr::Call(call) => call.span(), + Expr::Field(field) => field.span(), + Expr::Var(var) => var.span(), + Expr::TableConstr(constr) => constr.span(), + Expr::TableDestr(destr) => destr.span(), + Expr::FuncDef(def) => def.span(), + Expr::Paren { span, .. } => *span, + Expr::Neg { span, .. } => *span, + Expr::Not { span, .. } => *span, + Expr::BinOp { span, .. } => *span, } } } - -impl Expr { - pub fn boxed(self) -> Box { - Box::new(self) - } -} diff --git a/src/ast/field.rs b/src/ast/field.rs index 5afd98f..c8c10b4 100644 --- a/src/ast/field.rs +++ b/src/ast/field.rs @@ -60,41 +60,10 @@ pub enum Field { impl HasSpan for Field { fn span(&self) -> Span { match self { - Self::Access { span, .. } => *span, - Self::Assign { span, .. } => *span, - Self::AccessIdent { span, .. } => *span, - Self::AssignIdent { span, .. } => *span, + Field::Access { span, .. } => *span, + Field::Assign { span, .. } => *span, + Field::AccessIdent { span, .. } => *span, + Field::AssignIdent { span, .. } => *span, } } } - -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 expr(self) -> Expr { - Expr::Field(self) - } -} diff --git a/src/ast/func_def.rs b/src/ast/func_def.rs index 5cdd210..3ce0b34 100644 --- a/src/ast/func_def.rs +++ b/src/ast/func_def.rs @@ -90,50 +90,12 @@ pub enum FuncDef { impl HasSpan for FuncDef { fn span(&self) -> Span { match self { - Self::AnonNoArg { span, .. } => *span, - Self::AnonArg { span, .. } => *span, - Self::AnonDestr { span, .. } => *span, - Self::NamedNoArg { span, .. } => *span, - Self::NamedArg { span, .. } => *span, - Self::NamedDestr { span, .. } => *span, + FuncDef::AnonNoArg { span, .. } => *span, + FuncDef::AnonArg { span, .. } => *span, + FuncDef::AnonDestr { span, .. } => *span, + FuncDef::NamedNoArg { span, .. } => *span, + FuncDef::NamedArg { span, .. } => *span, + FuncDef::NamedDestr { span, .. } => *span, } } } - -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/lit.rs b/src/ast/lit.rs index ecd166c..c079955 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::{BoundedSeparated, Expr, Ident, Space}; +use super::{Expr, Ident, Separated, Space}; #[derive(Clone)] pub enum NumLitStr { @@ -93,19 +93,6 @@ 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, - } - } - - pub fn lit(self) -> Lit { - Lit::String(self) - } -} - impl HasSpan for StringLit { fn span(&self) -> Span { self.span @@ -132,37 +119,26 @@ pub enum TableLitElem { impl HasSpan for TableLitElem { fn span(&self) -> Span { match self { - Self::Positional(value) => value.span(), - Self::Named { span, .. } => *span, - } - } -} - -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, + TableLitElem::Positional(value) => value.span(), + TableLitElem::Named { span, .. } => *span, } } } /// `'{ a, foo: b }` +/// +/// Structure: `'{ s0 elems s1 }` #[derive(Debug, Clone)] -pub struct TableLit(pub BoundedSeparated); +pub struct TableLit { + pub s0: Space, + pub elems: Separated, + pub s1: Space, + pub span: Span, +} impl HasSpan for TableLit { fn span(&self) -> Span { - self.0.span() - } -} - -impl TableLit { - pub fn lit(self) -> Lit { - Lit::Table(self) + self.span } } @@ -211,18 +187,12 @@ impl fmt::Debug for Lit { impl HasSpan for Lit { fn span(&self) -> Span { match self { - Self::Nil(span) => *span, - Self::Bool(_, span) => *span, - Self::Builtin(_, span) => *span, - Self::Num(n) => n.span(), - Self::String(s) => s.span(), - Self::Table(t) => t.span(), + Lit::Nil(span) => *span, + Lit::Bool(_, span) => *span, + Lit::Builtin(_, span) => *span, + Lit::Num(n) => n.span(), + Lit::String(s) => s.span(), + Lit::Table(t) => t.span(), } } } - -impl Lit { - pub fn expr(self) -> Expr { - Expr::Lit(self) - } -} diff --git a/src/ast/program.rs b/src/ast/program.rs index a77abf4..1a219f5 100644 --- a/src/ast/program.rs +++ b/src/ast/program.rs @@ -1,6 +1,6 @@ use crate::span::{HasSpan, Span}; -use super::{BoundedSeparated, Expr, Space, TableLitElem}; +use super::{Expr, Separated, Space, TableLitElem}; #[derive(Debug, Clone)] pub enum Program { @@ -12,10 +12,12 @@ pub enum Program { span: Span, }, - /// Structure: `s0 module elems` + /// Structure: `s0 module s1 elems s2` Module { s0: Space, - elems: BoundedSeparated, + s1: Space, + elems: Separated, + s2: Space, span: Span, }, } @@ -23,8 +25,8 @@ pub enum Program { impl HasSpan for Program { fn span(&self) -> Span { match self { - Self::Expr { span, .. } => *span, - Self::Module { span, .. } => *span, + Program::Expr { span, .. } => *span, + Program::Module { span, .. } => *span, } } } diff --git a/src/ast/table_constr.rs b/src/ast/table_constr.rs index 38c409d..741a30c 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, Ident, Space, TableLitElem}; +use super::{Expr, Separated, Space, TableLitElem}; #[derive(Debug, Clone)] pub enum TableConstrElem { @@ -24,34 +24,25 @@ pub enum TableConstrElem { impl HasSpan for TableConstrElem { fn span(&self) -> Span { match self { - Self::Lit(lit) => lit.span(), - Self::Indexed { span, .. } => *span, + TableConstrElem::Lit(lit) => lit.span(), + TableConstrElem::Indexed { span, .. } => *span, } } } -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)) - } -} - /// `{ a, b, foo: c, [d]: e }` +/// +/// Structure: `{ s0 elems s1 }` #[derive(Debug, Clone)] -pub struct TableConstr(pub BoundedSeparated); +pub struct TableConstr { + pub s0: Space, + pub elems: Separated, + pub s1: Space, + pub span: Span, +} impl HasSpan for TableConstr { fn span(&self) -> Span { - self.0.span() - } -} - -impl TableConstr { - pub fn expr(self) -> Expr { - Expr::TableConstr(self) + self.span } } diff --git a/src/ast/table_destr.rs b/src/ast/table_destr.rs index d94b4eb..9cbf46a 100644 --- a/src/ast/table_destr.rs +++ b/src/ast/table_destr.rs @@ -1,6 +1,6 @@ use crate::span::{HasSpan, Span}; -use super::{BoundedSeparated, Expr, Ident, Space}; +use super::{Expr, Ident, Separated, Space}; // TODO Make table patterns recursive @@ -24,21 +24,26 @@ pub enum TablePatternElem { impl HasSpan for TablePatternElem { fn span(&self) -> Span { match self { - Self::Positional(ident) => ident.span(), - Self::Named { span, .. } => *span, + TablePatternElem::Positional(ident) => ident.span(), + TablePatternElem::Named { span, .. } => *span, } } } /// `{ foo, bar: baz }` -/// +/// /// Structure: `{ s0 elems s1 }` #[derive(Debug, Clone)] -pub struct TablePattern(pub BoundedSeparated); +pub struct TablePattern { + pub s0: Space, + pub elems: Separated, + pub s1: Space, + pub span: Span, +} impl HasSpan for TablePattern { fn span(&self) -> Span { - self.0.span() + self.span } } @@ -61,26 +66,3 @@ impl HasSpan for TableDestr { self.span } } - -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/ast/var.rs b/src/ast/var.rs index d5f0eab..bc32e7a 100644 --- a/src/ast/var.rs +++ b/src/ast/var.rs @@ -49,61 +49,10 @@ pub enum Var { impl HasSpan for Var { fn span(&self) -> Span { match self { - Self::Access { span, .. } => *span, - Self::Assign { span, .. } => *span, - Self::AccessIdent(ident) => ident.span(), - Self::AssignIdent { span, .. } => *span, + Var::Access { span, .. } => *span, + Var::Assign { span, .. } => *span, + Var::AccessIdent(ident) => ident.span(), + Var::AssignIdent { span, .. } => *span, } } } - -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/builtin.rs b/src/builtin.rs index 6ef18c8..f0e504d 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -12,21 +12,6 @@ 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 { @@ -41,21 +26,6 @@ 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.rs b/src/desugar.rs deleted file mode 100644 index 2be2a3f..0000000 --- a/src/desugar.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod basic; -mod call; -mod expr; -mod field; -mod func_def; -mod lit; -mod program; -mod table_constr; -mod table_destr; -mod var; diff --git a/src/desugar/basic.rs b/src/desugar/basic.rs deleted file mode 100644 index 156445f..0000000 --- a/src/desugar/basic.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::ast::BoundedSeparated; - -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 deleted file mode 100644 index c231875..0000000 --- a/src/desugar/call.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::ast::{BoundedSeparated, Call, Expr, Ident, Lit, TableLitElem}; - -// TODO Add span for just the parentheses to ast, or limit span to parentheses - -impl Call { - pub fn desugar(self) -> (Expr, bool) { - match self { - Self::Arg { - expr, - s0: _, - s1: _, - arg, - s2: _, - span, - } => { - 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(); - (new.lit().expr(), true) - } - - Self::NoArg { - expr, - s0: _, - s1: _, - span, - } => { - let new = Self::arg(expr, Lit::Nil(span).expr().boxed(), span); - (new.expr(), true) - } - - Self::Constr { - expr, - s0: _, - constr, - span, - } => { - let new = Self::arg(expr, constr.expr().boxed(), span); - (new.expr(), true) - } - } - } -} diff --git a/src/desugar/expr.rs b/src/desugar/expr.rs deleted file mode 100644 index b7f4b08..0000000 --- a/src/desugar/expr.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::ast::{BinOp, BoundedSeparated, Call, Expr, Lit, TableConstrElem}; -use crate::builtin::Builtin; - -impl Expr { - pub fn desugar(self) -> (Self, bool) { - match self { - Self::Lit(lit) => { - let (lit, desugared) = lit.desugar(); - (lit.expr(), desugared) - } - - Self::Call(call) => call.desugar(), - Self::Field(field) => field.desugar(), - Self::Var(var) => var.desugar(), - Self::TableConstr(constr) => constr.desugar(), - Self::TableDestr(destr) => destr.desugar(), - Self::FuncDef(def) => def.desugar(), - - Self::Paren { - s0: _, - inner, - s1: _, - span: _, - } => (*inner, true), - - Self::Neg { - minus, - s0: _, - expr, - span, - } => { - let new = Call::arg(Lit::Builtin(Builtin::Neg, minus).expr().boxed(), expr, span); - (new.expr(), true) - } - - Self::Not { - not, - s0: _, - expr, - span, - } => { - let new = Call::arg(Lit::Builtin(Builtin::Not, not).expr().boxed(), expr, span); - (new.expr(), true) - } - - Self::BinOp { - left, - s0: _, - op, - s1: _, - right, - span, - } => { - 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) - } - } - } -} diff --git a/src/desugar/field.rs b/src/desugar/field.rs deleted file mode 100644 index 3c269e2..0000000 --- a/src/desugar/field.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::ast::{BoundedSeparated, Call, Expr, Field, Lit, StringLit, TableConstrElem}; -use crate::builtin::Builtin; - -impl Field { - pub fn desugar(self) -> (Expr, bool) { - match self { - Self::Access { - expr, - s0: _, - s1: _, - index, - s2: _, - span, - } => { - let constr = BoundedSeparated::new(span) - .then(TableConstrElem::positional(expr)) - .then(TableConstrElem::positional(index)) - .table_constr(); - let new = Call::constr( - Lit::Builtin(Builtin::Get, span).expr().boxed(), - constr, - span, - ); - (new.expr(), true) - } - - Self::Assign { - expr, - s0: _, - s1: _, - index, - s2: _, - s3: _, - s4: _, - value, - span, - } => { - let constr = BoundedSeparated::new(span) - .then(TableConstrElem::positional(expr)) - .then(TableConstrElem::positional(index)) - .then(TableConstrElem::positional(value)) - .table_constr(); - let new = Call::constr( - Lit::Builtin(Builtin::Set, span).expr().boxed(), - constr, - span, - ); - (new.expr(), true) - } - - Self::AccessIdent { - expr, - s0: _, - s1: _, - ident, - span, - } => { - let new = Self::access( - expr, - StringLit::from_ident(ident).lit().expr().boxed(), - span, - ); - (new.expr(), true) - } - - Self::AssignIdent { - expr, - s0: _, - s1: _, - ident, - s2: _, - s3: _, - value, - span, - } => { - let new = Self::assign( - expr, - StringLit::from_ident(ident).lit().expr().boxed(), - value, - span, - ); - (new.expr(), true) - } - } - } -} diff --git a/src/desugar/func_def.rs b/src/desugar/func_def.rs deleted file mode 100644 index 2a549d1..0000000 --- a/src/desugar/func_def.rs +++ /dev/null @@ -1,128 +0,0 @@ -use crate::ast::{ - BoundedSeparated, Call, Expr, FuncDef, Ident, Lit, Space, TableConstrElem, TableDestr, - TableLitElem, Var, -}; -use crate::builtin::Builtin; - -impl FuncDef { - pub fn desugar(self) -> (Expr, bool) { - match self { - Self::AnonNoArg { - s0: _, - s1: _, - s2: _, - body, - span, - } => { - let quote = BoundedSeparated::new(span) - .then(TableLitElem::named(Ident::new("quote", span), body, span)) - .table_lit(); - let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); - let new = BoundedSeparated::new(span) - .then(TableConstrElem::positional(Box::new(quote.lit().expr()))) - .then(TableConstrElem::named( - Ident::new("scope", span), - scope.expr().boxed(), - span, - )) - .table_constr(); - (new.expr(), true) - } - - Self::AnonArg { - s0: _, - s1: _, - arg, - s2: _, - s3: _, - body, - span, - } => { - let arg_call = Call::no_arg(Lit::Builtin(Builtin::Arg, span).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)) - .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::AnonDestr { - s0: _, - pattern, - s1: _, - body, - span, - } => { - 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: _, - name, - s1: _, - s2: _, - s3: _, - body, - span, - } => { - 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: _, - name, - s1: _, - s2: _, - arg, - s3: _, - s4: _, - body, - span, - } => { - 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: _, - name, - s1: _, - pattern, - s2: _, - body, - span, - } => { - let anon = Self::anon_destr(pattern, body, span); - let new = Var::assign_ident(local.is_some(), name, anon.expr().boxed(), span); - (new.expr(), true) - } - } - } -} diff --git a/src/desugar/lit.rs b/src/desugar/lit.rs deleted file mode 100644 index 3b6fd80..0000000 --- a/src/desugar/lit.rs +++ /dev/null @@ -1,60 +0,0 @@ -use crate::ast::{Expr, Lit, TableLit, TableLitElem}; - -impl TableLitElem { - pub fn desugar(self) -> (Self, bool) { - match self { - Self::Positional(expr) => { - let (expr, desugared) = expr.desugar(); - (Self::Positional(expr.boxed()), desugared) - } - - Self::Named { - name, - s0, - s1, - value, - span, - } => { - let (value, desugared) = value.desugar(); - let new = Self::Named { - name, - s0, - s1, - value: value.boxed(), - span, - }; - (new, desugared) - } - } - } -} - -impl TableLit { - pub fn desugar(self) -> (Self, bool) { - 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 { - (elems.table_lit(), true) - } - } -} - -impl Lit { - pub fn desugar(self) -> (Self, bool) { - match self { - Self::Table(table) => { - let (table, desugared) = table.desugar(); - (table.lit(), desugared) - } - - lit => (lit, false), - } - } -} diff --git a/src/desugar/program.rs b/src/desugar/program.rs deleted file mode 100644 index 615998b..0000000 --- a/src/desugar/program.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::ast::{Program, Space}; - -impl Program { - pub fn desugar(self) -> (Self, bool) { - match self { - Self::Expr { s0, expr, s1, span } => { - let (expr, desugared) = expr.desugar(); - let new = Self::Expr { s0, expr, s1, span }; - (new, desugared) - } - - Self::Module { s0, elems, span } => { - // `s0 module elems` - // -> `s0 table` - let new = Self::Expr { - s0, - expr: elems.table_lit().lit().expr(), - s1: Space::empty(span), - span, - }; - (new, true) - } - } - } -} diff --git a/src/desugar/table_constr.rs b/src/desugar/table_constr.rs deleted file mode 100644 index 263d9d4..0000000 --- a/src/desugar/table_constr.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::ast::{ - BoundedSeparated, Expr, Field, Ident, TableConstr, TableConstrElem, 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((index, value, span)), - }); - - let mut expr = BoundedSeparated::new(span) - .then(TableLitElem::named( - Ident::new("raw", span), - elems.table_lit().lit().expr().boxed(), - span, - )) - .table_lit() - .lit() - .expr(); - - for (_, (index, value, span), _) in setters { - expr = Field::assign(expr.boxed(), index, value, span).expr(); - } - - (expr, true) - } -} diff --git a/src/desugar/table_destr.rs b/src/desugar/table_destr.rs deleted file mode 100644 index 2216977..0000000 --- a/src/desugar/table_destr.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::ast::{ - BoundedSeparated, Call, Expr, Ident, Lit, StringLit, TableConstr, TableConstrElem, TableDestr, - TableLitElem, TablePattern, TablePatternElem, -}; -use crate::builtin::Builtin; - -fn pattern_to_constr(pattern: TablePattern) -> TableConstr { - pattern - .0 - .map(|e| match e { - TablePatternElem::Positional(ident) => { - TableConstrElem::positional(StringLit::from_ident(ident).lit().expr().boxed()) - } - - TablePatternElem::Named { - name, - s0, - s1, - ident, - span, - } => TableConstrElem::Lit(TableLitElem::Named { - name, - s0, - s1, - value: StringLit::from_ident(ident).lit().expr().boxed(), - span, - }), - }) - .table_constr() -} - -impl TableDestr { - pub fn desugar(self) -> (Expr, bool) { - let Self { - local, - pattern, - s0: _, - s1: _, - value, - span, - } = self; - - let mut constr = BoundedSeparated::new(span) - .then(TableConstrElem::positional( - pattern_to_constr(pattern).expr().boxed(), - )) - .then(TableConstrElem::positional(value)); - if local.is_some() { - constr = constr.then(TableConstrElem::named( - Ident::new("local", span), - Lit::Bool(true, span).expr().boxed(), - span, - )); - } - - 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 deleted file mode 100644 index 0ab0a76..0000000 --- a/src/desugar/var.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::ast::{BoundedSeparated, Call, Expr, Field, Lit, StringLit, TableConstrElem, Var}; -use crate::builtin::Builtin; -use crate::span::HasSpan; - -impl Var { - pub fn desugar(self) -> (Expr, bool) { - match self { - Self::Access { - s0: _, - index, - s1: _, - span, - } => { - let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); - let new = Field::access(scope.expr().boxed(), index, span); - (new.expr(), true) - } - - Self::Assign { - local: None, - s0: _, - index, - s1: _, - s2: _, - s3: _, - value, - span, - } => { - let scope = Call::no_arg(Lit::Builtin(Builtin::Scope, span).expr().boxed(), span); - let new = Field::assign(scope.expr().boxed(), index, value, span); - (new.expr(), true) - } - - Self::Assign { - local: Some(_), - s0: _, - index, - s1: _, - s2: _, - s3: _, - value, - 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( - Lit::Builtin(Builtin::SetRaw, span).expr().boxed(), - constr, - span, - ); - (new.expr(), true) - } - - Self::AccessIdent(name) => { - let span = name.span(); - let new = Self::access(StringLit::from_ident(name).lit().expr().boxed(), span); - (new.expr(), true) - } - - Self::AssignIdent { - local, - name, - s0: _, - s1: _, - value, - span, - } => { - let new = Self::assign( - local.is_some(), - StringLit::from_ident(name).lit().expr().boxed(), - value, - span, - ); - (new.expr(), true) - } - } - } -} diff --git a/src/main.rs b/src/main.rs index 0ac0aed..ee5f73a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,30 +1,11 @@ -#![deny(unsafe_code)] -// Rustc lint groups -#![warn(future_incompatible)] -#![warn(rust_2018_idioms)] -// Rustc lints -#![warn(noop_method_call)] -#![warn(single_use_lifetimes)] -#![warn(trivial_numeric_casts)] -#![warn(unused_crate_dependencies)] -#![warn(unused_extern_crates)] -#![warn(unused_import_braces)] -#![warn(unused_lifetimes)] -#![warn(unused_qualifications)] -// Clippy lints -#![warn(clippy::use_self)] - -use std::io::Write; +use std::fs; use std::path::PathBuf; -use std::{fs, process}; -use anyhow::anyhow; use chumsky::Parser as _; use clap::Parser; mod ast; mod builtin; -mod desugar; mod parser; mod pretty; mod span; @@ -33,19 +14,8 @@ mod value; #[derive(Parser)] enum Command { - Parse { - file: PathBuf, - }, - Pretty { - file: PathBuf, - }, - Desugar { - file: PathBuf, - #[arg(long, short, default_value = "diff")] - difftool: String, - #[arg(long, short = 'a')] - diffarg: Vec, - }, + Parse { file: PathBuf }, + Pretty { file: PathBuf }, } #[derive(Parser)] @@ -72,54 +42,21 @@ fn main() -> anyhow::Result<()> { } } } - Command::Pretty { file } => { let content = fs::read_to_string(&file)?; let stream = span::stream_from_str(&content); - let program = parser::parser() - .parse(stream) - .map_err(|e| anyhow!("{e:?}"))?; - - print!("{}", pretty::pretty_to_string(program, 100)); - } - - Command::Desugar { - file, - difftool, - diffarg, - } => { - let content = fs::read_to_string(&file)?; - let stream = span::stream_from_str(&content); - let mut program = parser::parser() - .parse(stream) - .map_err(|e| anyhow!("{e:?}"))?; - - let mut builder = tempfile::Builder::new(); - builder.suffix(".tada"); - - let mut prev = builder.tempfile()?; - prev.write_all(pretty::pretty_to_string(program.clone(), 100).as_bytes())?; - prev.flush()?; - - loop { - let (new_program, desugared) = program.desugar(); - program = new_program; - if !desugared { - break; + match parser::parser().parse(stream) { + Ok(program) => { + let mut out = vec![]; + program.to_doc().render(100, &mut out)?; + println!("{}", String::from_utf8(out)?); + } + Err(errs) => { + eprintln!("Parsing failed"); + for err in errs { + eprintln!("{err:?}"); + } } - - let mut cur = builder.tempfile()?; - cur.write_all(pretty::pretty_to_string(program.clone(), 100).as_bytes())?; - cur.flush()?; - - process::Command::new(&difftool) - .args(&diffarg) - .arg(prev.path()) - .arg(cur.path()) - .spawn()? - .wait()?; - - prev = cur; } } } diff --git a/src/parser.rs b/src/parser.rs index ea6fa99..1650d97 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -18,7 +18,7 @@ mod basic; mod expr; -mod func_def; +mod func_defs; mod lit; mod prefix; mod program; @@ -52,7 +52,7 @@ pub fn parser() -> impl Parser { table_pattern.clone(), expr.clone(), ); - let func_def = func_def::func_def( + let func_def = func_defs::func_def( space.clone(), ident.clone(), local, diff --git a/src/parser/basic.rs b/src/parser/basic.rs index 9ca8d09..2a65c68 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, Space}; +use crate::ast::{Ident, Line, Separated, Space}; use crate::span::Span; pub type Error = Simple; @@ -62,42 +62,23 @@ 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 bounded_separated( - space: impl Parser + Clone + 'static, - start: impl Parser + 'static, - end: impl Parser + 'static, - separator: impl Parser + 'static, +pub fn separated_by( 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, + 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() } diff --git a/src/parser/expr.rs b/src/parser/expr.rs index bd2b373..3bae445 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: inner.boxed(), + inner: Box::new(inner), 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: left.boxed(), + left: Box::new(left), s0, op, s1, - right: right.boxed(), + right: Box::new(right), }) .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: left.boxed(), + left: Box::new(left), s0, op, s1, - right: right.boxed(), + right: Box::new(right), }) .boxed() } diff --git a/src/parser/func_def.rs b/src/parser/func_defs.rs similarity index 94% rename from src/parser/func_def.rs rename to src/parser/func_defs.rs index 3bb273d..e290b95 100644 --- a/src/parser/func_def.rs +++ b/src/parser/func_defs.rs @@ -1,3 +1,5 @@ +// TODO Rename this module to func_def for consistency + use chumsky::prelude::*; use crate::ast::{Expr, FuncDef, Ident, Space, TablePattern}; @@ -19,7 +21,7 @@ fn func_def_anon_no_arg( s0, s1, s2, - body: body.boxed(), + body: Box::new(body), span, }) } @@ -45,7 +47,7 @@ fn func_def_anon_arg( arg, s2, s3, - body: body.boxed(), + body: Box::new(body), span, }, ) @@ -65,7 +67,7 @@ fn func_def_anon_destr( s0, pattern, s1, - body: body.boxed(), + body: Box::new(body), span, }) } @@ -94,7 +96,7 @@ fn func_def_named_no_arg( s1, s2, s3, - body: body.boxed(), + body: Box::new(body), span, }, ) @@ -128,7 +130,7 @@ fn func_def_named_arg( arg, s3, s4, - body: body.boxed(), + body: Box::new(body), span, }, ) @@ -157,7 +159,7 @@ fn func_def_named_destr( s1, pattern, s2, - body: body.boxed(), + body: Box::new(body), span, } }) diff --git a/src/parser/lit.rs b/src/parser/lit.rs index e368684..0bdf12a 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::{bounded_separated, EParser, Error}; +use super::basic::{separated_by, EParser, Error}; fn builtin_lit() -> impl Parser { just('\'').ignore_then(choice(( @@ -132,7 +132,7 @@ pub fn table_lit_elem( ) -> EParser { let positional = expr .clone() - .map(|value| TableLitElem::Positional(value.boxed())); + .map(|value| TableLitElem::Positional(Box::new(value))); let named = ident .then(space.clone()) @@ -143,7 +143,7 @@ pub fn table_lit_elem( name, s0, s1, - value: value.boxed(), + value: Box::new(value), span, }); @@ -154,14 +154,20 @@ fn table_lit( space: EParser, table_lit_elem: EParser, ) -> impl Parser { - bounded_separated( - space, - just("'{").to(()), - just('}').to(()), - just(',').to(()), - table_lit_elem, - ) - .map(TableLit) + 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, + }) } pub fn lit(space: EParser, table_lit_elem: EParser) -> EParser { diff --git a/src/parser/prefix.rs b/src/parser/prefix.rs index f53c78f..ddae0bd 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 = expr.boxed(); + let expr = Box::new(expr); match self { Self::Neg { minus, s0 } => Expr::Neg { minus, diff --git a/src/parser/program.rs b/src/parser/program.rs index 96c3cab..0b46f94 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::{bounded_separated, EParser}; +use super::basic::{separated_by, EParser}; pub fn program( space: EParser, @@ -17,17 +17,21 @@ 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(bounded_separated( - space, - empty(), - empty(), - just(',').to(()), - table_lit_elem, - )) - .map_with_span(|(s0, elems), span| Program::Module { s0, elems, span }); + .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, + }); module.or(lit).boxed() } diff --git a/src/parser/suffix.rs b/src/parser/suffix.rs index ca25830..6c10491 100644 --- a/src/parser/suffix.rs +++ b/src/parser/suffix.rs @@ -57,39 +57,32 @@ enum Suffix { impl Suffix { fn into_expr(self, span: Span, expr: Expr) -> Expr { - let expr = expr.boxed(); + let expr = Box::new(expr); match self { - Self::CallArg { s0, s1, arg, s2 } => Call::Arg { + Suffix::CallArg { s0, s1, arg, s2 } => Expr::Call(Call::Arg { expr, s0, s1, arg, s2, span, - } - .expr(), - - Self::CallNoArg { s0, s1 } => Call::NoArg { expr, s0, s1, span }.expr(), - - Self::CallConstr { s0, constr } => Call::Constr { + }), + Suffix::CallNoArg { s0, s1 } => Expr::Call(Call::NoArg { expr, s0, s1, span }), + Suffix::CallConstr { s0, constr } => Expr::Call(Call::Constr { expr, s0, constr, span, - } - .expr(), - - Self::FieldAccess { s0, s1, index, s2 } => Field::Access { + }), + Suffix::FieldAccess { s0, s1, index, s2 } => Expr::Field(Field::Access { expr, s0, s1, index, s2, span, - } - .expr(), - - Self::FieldAssign { + }), + Suffix::FieldAssign { s0, s1, index, @@ -97,7 +90,7 @@ impl Suffix { s3, s4, value, - } => Field::Assign { + } => Expr::Field(Field::Assign { expr, s0, s1, @@ -107,26 +100,22 @@ impl Suffix { s4, value, span, - } - .expr(), - - Self::FieldAccessIdent { s0, s1, ident } => Field::AccessIdent { + }), + Suffix::FieldAccessIdent { s0, s1, ident } => Expr::Field(Field::AccessIdent { expr, s0, s1, ident, span, - } - .expr(), - - Self::FieldAssignIdent { + }), + Suffix::FieldAssignIdent { s0, s1, ident, s2, s3, value, - } => Field::AssignIdent { + } => Expr::Field(Field::AssignIdent { expr, s0, s1, @@ -135,8 +124,7 @@ impl Suffix { s3, value, span, - } - .expr(), + }), } } } @@ -155,7 +143,7 @@ fn suffix_call_arg( .map(|(((s0, s1), arg), s2)| Suffix::CallArg { s0, s1, - arg: arg.boxed(), + arg: Box::new(arg), s2, }) } @@ -192,7 +180,7 @@ fn suffix_field_access( .map(|(((s0, s1), index), s2)| Suffix::FieldAccess { s0, s1, - index: index.boxed(), + index: Box::new(index), s2, }) } @@ -216,11 +204,11 @@ fn suffix_field_assign( |((((((s0, s1), index), s2), s3), s4), value)| Suffix::FieldAssign { s0, s1, - index: index.boxed(), + index: Box::new(index), s2, s3, s4, - value: value.boxed(), + value: Box::new(value), }, ) } @@ -258,7 +246,7 @@ fn suffix_field_assign_ident( ident, s2, s3, - value: value.boxed(), + value: Box::new(value), }, ) } diff --git a/src/parser/table_constr.rs b/src/parser/table_constr.rs index b294329..fd6aefd 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::{bounded_separated, EParser, Error}; +use super::basic::{separated_by, EParser, Error}; fn table_constr_elem( space: EParser, @@ -25,11 +25,11 @@ fn table_constr_elem( .map_with_span( |(((((s0, index), s1), s2), s3), value), span| TableConstrElem::Indexed { s0, - index: index.boxed(), + index: Box::new(index), s1, s2, s3, - value: value.boxed(), + value: Box::new(value), span, }, ); @@ -43,13 +43,19 @@ pub fn table_constr( expr: EParser, ) -> EParser { let elem = table_constr_elem(space.clone(), table_lit_elem, expr); - bounded_separated( - space, - just('{').to(()), - just('}').to(()), - just(',').to(()), - elem, - ) - .map(TableConstr) - .boxed() + 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() } diff --git a/src/parser/table_destr.rs b/src/parser/table_destr.rs index c215a19..4fb5eda 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::{bounded_separated, EParser, Error}; +use super::basic::{separated_by, EParser, Error}; fn table_pattern_elem( space: EParser, @@ -31,15 +31,21 @@ fn table_pattern_elem( pub fn table_pattern(space: EParser, ident: EParser) -> EParser { let elem = table_pattern_elem(space.clone(), ident); - bounded_separated( - space, - just('{').to(()), - just('}').to(()), - just(',').to(()), - elem, - ) - .map(TablePattern) - .boxed() + 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() } pub fn table_destr( @@ -59,7 +65,7 @@ pub fn table_destr( pattern, s0, s1, - value: value.boxed(), + value: Box::new(value), span, }) .boxed() diff --git a/src/parser/var.rs b/src/parser/var.rs index c5806dc..80722e1 100644 --- a/src/parser/var.rs +++ b/src/parser/var.rs @@ -14,7 +14,7 @@ fn var_access(space: EParser, expr: EParser) -> impl Parser>(p: P, width: usize) -> String { - let mut out = vec![]; - p.pretty(&RcAllocator) - .render(width, &mut out) - .expect("p could not be rendered"); - let mut s = String::from_utf8(out).expect("p created non-utf8 string"); - s.push('\n'); - s -} diff --git a/src/pretty/basic.rs b/src/pretty/basic.rs index abc55ee..c3e6dcc 100644 --- a/src/pretty/basic.rs +++ b/src/pretty/basic.rs @@ -1,41 +1,86 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; +use std::mem; -use crate::ast::{BoundedSeparated, Ident}; +use pretty::{DocAllocator, DocBuilder, Pretty, RcAllocator, RcDoc}; -use super::NEST_DEPTH; +use crate::ast::{Ident, Line, Space}; -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for Ident { - fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - allocator.text(self.name) +pub enum Group<'a> { + EmptyLine, + CommentBlock(Vec<&'a str>), +} + +/// Group comments and deduplicate empty lines +fn group_comments(lines: &[Line]) -> Vec { + let mut result = vec![]; + + let mut current_block = vec![]; + let mut last_line_was_empty = false; + for line in lines { + match line { + Line::Empty if last_line_was_empty => {} + Line::Empty => { + last_line_was_empty = true; + if !current_block.is_empty() { + result.push(Group::CommentBlock(mem::take(&mut current_block))); + } + result.push(Group::EmptyLine); + } + Line::Comment(comment) => { + last_line_was_empty = false; + current_block.push(comment); + } + } + } + + if !current_block.is_empty() { + result.push(Group::CommentBlock(current_block)); + } + + result +} + +fn remove_leading_empty_line(groups: &mut Vec) { + if let Some(Group::EmptyLine) = groups.first() { + groups.remove(0); } } -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>, - { - let elems_empty = self.elems.is_empty(); - allocator - .intersperse( - self.elems - .into_iter() - .map(|(s0, elem, s1)| allocator.line().append(elem_pretty(elem))), - separator.clone(), - ) - .append(self.trailing.filter(|_| !elems_empty).map(|s| separator)) - .nest(NEST_DEPTH) - .append(allocator.line()) - .enclose(start, end) - .group() +fn remove_trailing_empty_line(groups: &mut Vec) { + if let Some(Group::EmptyLine) = groups.last() { + groups.pop(); + } +} + +fn comment_group_to_doc(comment: Vec<&str>) -> RcDoc { + RcAllocator + .concat(comment.into_iter().map(|c| { + RcDoc::text("# ") + .append(RcDoc::text(c)) + .append(RcDoc::hardline()) + })) + .indent(0) + .into_doc() +} + +impl Space { + /// Format as document for inline use, prefering nil if possible. + pub fn to_doc_inline_nospace(&self) -> RcDoc { + RcDoc::nil() + } + + /// Format as document, prefering a single space if possible. + pub fn to_doc_inline_space(&self) -> RcDoc { + RcDoc::space() + } + + /// Format as document, prefering a newline if possible. + pub fn to_doc_newline(&self) -> RcDoc { + RcDoc::line() + } +} + +impl Ident { + pub fn to_doc(&self) -> RcDoc { + RcDoc::text(&self.name) } } diff --git a/src/pretty/call.rs b/src/pretty/call.rs deleted file mode 100644 index 6cf26fc..0000000 --- a/src/pretty/call.rs +++ /dev/null @@ -1,36 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::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 { - expr, - s0, - s1, - arg, - s2, - span: _, - } => expr - .pretty(allocator) - .append(arg.pretty(allocator).parens()), - Self::NoArg { - expr, - s0, - s1, - span: _, - } => expr.pretty(allocator).append(allocator.nil().parens()), - Self::Constr { - expr, - s0, - constr, - span: _, - } => expr.pretty(allocator).append(constr.pretty(allocator)), - } - } -} diff --git a/src/pretty/expr.rs b/src/pretty/expr.rs deleted file mode 100644 index ddf7634..0000000 --- a/src/pretty/expr.rs +++ /dev/null @@ -1,131 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::{Assoc, BinOp, Expr, Field, Var}; - -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for BinOp { - fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - allocator.text(match self { - Self::Mul => "*", - Self::Div => "/", - Self::Mod => "%", - Self::Add => "+", - Self::Sub => "-", - Self::Eq => "==", - Self::Neq => "!=", - Self::Gt => ">", - Self::Ge => ">=", - Self::Lt => "<", - Self::Le => "<=", - Self::And => "and", - Self::Or => "or", - }) - } -} - -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), - Self::Call(call) => call.pretty(allocator), - Self::Field(field) => field.pretty(allocator), - Self::Var(var) => var.pretty(allocator), - Self::TableConstr(constr) => constr.pretty(allocator), - Self::TableDestr(destr) => destr.pretty(allocator), - Self::FuncDef(def) => def.pretty(allocator), - Self::Paren { - s0, - inner, - s1, - span: _, - } => inner.pretty(allocator).parens(), - - Self::Neg { - minus: _, - s0, - expr, - span: _, - } => { - let parenthesize = matches!(*expr, Self::BinOp { .. }); - let inner = expr.pretty(allocator); - allocator - .text("-") - .append(if parenthesize { inner.parens() } else { inner }) - } - - Self::Not { - not: _, - s0, - expr, - span: _, - } => { - let parenthesize = matches!(*expr, Self::BinOp { .. }); - let inner = expr.pretty(allocator); - allocator - .text("not ") - .append(if parenthesize { inner.parens() } else { inner }) - } - - // TODO Add newlines and group properly - Self::BinOp { - left, - s0, - op, - s1, - right, - span: _, - } => { - // If we're left-associative, then the left subexpression can be - // at the same precedence and the right subexpression must be at - // a higher precedence. - - // If we're right-associative, then the left subexpression must - // be at a higher precedence and the right subexpression can be - // at the same precedence. - - // Minimum precedence that the left subexpression can be at - // without requiring parentheses. - let min_left_prec = match op.assoc() { - Assoc::Left => op.precedence(), - Assoc::Right => op.precedence() + 1, - }; - - // Minimum precedence that the right subexpression can be at - // without requiring parentheses. - let min_right_prec = match op.assoc() { - Assoc::Left => op.precedence() + 1, - Assoc::Right => op.precedence(), - }; - - let left_paren = match *left { - // These end with an arbitrary expression on the right. If - // we don't add parentheses, we'll be assimilated into that - // expression. - Self::Field(Field::Assign { .. } | Field::AssignIdent { .. }) => true, - Self::Var(Var::Assign { .. } | Var::AssignIdent { .. }) => true, - - Self::BinOp { op, .. } if op.precedence() < min_left_prec => true, - - _ => false, - }; - - let right_paren = - matches!(*right, Self::BinOp { op, .. } if op.precedence() < min_right_prec); - - let left = left.pretty(allocator); - let left = if left_paren { left.parens() } else { left }; - - let right = right.pretty(allocator); - let right = if right_paren { right.parens() } else { right }; - - left.append(allocator.space()) - .append(op.pretty(allocator)) - .append(allocator.space()) - .append(right) - } - } - } -} diff --git a/src/pretty/field.rs b/src/pretty/field.rs deleted file mode 100644 index eb547f0..0000000 --- a/src/pretty/field.rs +++ /dev/null @@ -1,68 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::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 { - expr, - s0, - s1, - index, - s2, - span: _, - } => expr - .pretty(allocator) - .append(index.pretty(allocator).brackets()), - Self::Assign { - expr, - s0, - s1, - index, - s2, - s3, - s4, - value, - span: _, - } => expr - .pretty(allocator) - .append(index.pretty(allocator).brackets()) - .append(allocator.text(" = ")) - .append(value.pretty(allocator)), - Self::AccessIdent { - expr, - s0, - s1, - ident, - span: _, - } => expr - .pretty(allocator) - .append(allocator.line_()) - .append(allocator.text(".")) - .append(ident.pretty(allocator)) - .group(), - Self::AssignIdent { - expr, - s0, - s1, - ident, - s2, - s3, - value, - span: _, - } => expr - .pretty(allocator) - .append(allocator.line_()) - .append(allocator.text(".")) - .append(ident.pretty(allocator)) - .append(allocator.text(" = ")) - .append(value.pretty(allocator)) - .group(), - } - } -} diff --git a/src/pretty/func_def.rs b/src/pretty/func_def.rs deleted file mode 100644 index dce23e6..0000000 --- a/src/pretty/func_def.rs +++ /dev/null @@ -1,102 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::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 { - s0, - s1, - s2, - body, - span: _, - } => allocator.text("function() ").append(body.pretty(allocator)), - - Self::AnonArg { - s0, - s1, - arg, - s2, - s3, - body, - span: _, - } => allocator - .text("function") - .append(arg.pretty(allocator).parens()) - .append(allocator.space()) - .append(body.pretty(allocator)), - - Self::AnonDestr { - s0, - pattern, - s1, - body, - span: _, - } => allocator - .text("function") - .append(pattern.pretty(allocator)) - .append(allocator.space()) - .append(body.pretty(allocator)), - - Self::NamedNoArg { - local, - s0, - name, - s1, - s2, - s3, - body, - span: _, - } => local - .map(|s| allocator.text("local ")) - .unwrap_or_else(|| allocator.nil()) - .append(allocator.text("function ")) - .append(name) - .append(allocator.text("() ")) - .append(body.pretty(allocator)), - - Self::NamedArg { - local, - s0, - name, - s1, - s2, - arg, - s3, - s4, - body, - span: _, - } => local - .map(|s| allocator.text("local ")) - .unwrap_or_else(|| allocator.nil()) - .append(allocator.text("function ")) - .append(name) - .append(arg.pretty(allocator).parens()) - .append(allocator.space()) - .append(body.pretty(allocator)), - - Self::NamedDestr { - local, - s0, - name, - s1, - pattern, - s2, - body, - span: _, - } => local - .map(|s| allocator.text("local ")) - .unwrap_or_else(|| allocator.nil()) - .append(allocator.text("function ")) - .append(name) - .append(pattern.pretty(allocator)) - .append(allocator.space()) - .append(body.pretty(allocator)), - } - } -} diff --git a/src/pretty/lit.rs b/src/pretty/lit.rs deleted file mode 100644 index 84f3055..0000000 --- a/src/pretty/lit.rs +++ /dev/null @@ -1,87 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::{Lit, NumLit, StringLit, StringLitElem, TableLit, TableLitElem}; - -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for NumLit { - fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - allocator.text(format!("{self:?}")) - } -} - -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for StringLitElem { - fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - match self { - Self::Plain(str) => allocator.text(str), - Self::Unicode(char) => allocator.text(format!("\\u{{{:x}}}", char as u32)), - Self::Backslash => allocator.text("\\\\"), - Self::DoubleQuote => allocator.text("\\\""), - Self::Tab => allocator.text("\\t"), - Self::CarriageReturn => allocator.text("\\r"), - Self::Newline => allocator.text("\\n"), - } - } -} - -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for StringLit { - fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - allocator - .concat(self.elems.into_iter().map(|e| e.pretty(allocator))) - .enclose(allocator.text("\""), allocator.text("\"")) - } -} - -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), - Self::Named { - name, - s0, - s1, - value, - span: _, - } => name - .pretty(allocator) - .append(allocator.text(": ")) - .append(value.pretty(allocator)), - } - } -} - -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.0.pretty( - allocator, - allocator.text("'{"), - allocator.text("}"), - allocator.text(","), - |e| e.pretty(allocator), - ) - } -} - -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"), - Self::Bool(false, _) => allocator.text("false"), - Self::Bool(true, _) => allocator.text("true"), - Self::Builtin(builtin, _) => allocator.text(format!("{builtin:?}")), - Self::Num(num) => num.pretty(allocator), - Self::String(string) => string.pretty(allocator), - Self::Table(table) => table.pretty(allocator), - } - } -} diff --git a/src/pretty/program.rs b/src/pretty/program.rs index 1ff7863..60a5ca0 100644 --- a/src/pretty/program.rs +++ b/src/pretty/program.rs @@ -1,33 +1,23 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; +use pretty::RcDoc; use crate::ast::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> { +impl Program { + pub fn to_doc(&self) -> RcDoc { match self { - Self::Expr { + Program::Expr { s0, expr, s1, span: _, - } => expr.pretty(allocator), - - 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(","))), - ) - } + } => RcDoc::nil(), + Program::Module { + s0, + s1, + elems, + s2, + span: _, + } => RcDoc::text("module"), } } } diff --git a/src/pretty/table_constr.rs b/src/pretty/table_constr.rs deleted file mode 100644 index 3b3fdb1..0000000 --- a/src/pretty/table_constr.rs +++ /dev/null @@ -1,44 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::{TableConstr, 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), - Self::Indexed { - s0, - index, - s1, - s2, - s3, - value, - span: _, - } => index - .pretty(allocator) - .brackets() - .append(allocator.text(": ")) - .append(value.pretty(allocator)), - } - } -} - -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.0.pretty( - allocator, - allocator.text("{"), - allocator.text("}"), - allocator.text(","), - |e| e.pretty(allocator), - ) - } -} diff --git a/src/pretty/table_destr.rs b/src/pretty/table_destr.rs deleted file mode 100644 index 777d0ae..0000000 --- a/src/pretty/table_destr.rs +++ /dev/null @@ -1,53 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::{TableDestr, TablePattern, TablePatternElem}; - -impl<'a, D: DocAllocator<'a>> Pretty<'a, D> for TablePatternElem { - fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D> { - match self { - Self::Positional(ident) => ident.pretty(allocator), - Self::Named { - name, - s0, - s1, - ident, - span: _, - } => name - .pretty(allocator) - .append(allocator.text(": ")) - .append(ident.pretty(allocator)), - } - } -} - -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.0.pretty( - allocator, - allocator.text("{"), - allocator.text("}"), - allocator.text(","), - |e| e.pretty(allocator), - ) - } -} - -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 - .map(|s| allocator.text("local ")) - .unwrap_or_else(|| allocator.nil()) - .append(self.pattern.pretty(allocator)) - .append(allocator.text(" = ")) - .append(self.value.pretty(allocator)) - } -} diff --git a/src/pretty/var.rs b/src/pretty/var.rs deleted file mode 100644 index 662b34e..0000000 --- a/src/pretty/var.rs +++ /dev/null @@ -1,49 +0,0 @@ -use pretty::{DocAllocator, DocBuilder, Pretty}; - -use crate::ast::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 { - s0, - index, - s1, - span: _, - } => index.pretty(allocator).brackets(), - Self::Assign { - local, - s0, - index, - s1, - s2, - s3, - value, - span: _, - } => local - .map(|s| allocator.text("local ")) - .unwrap_or_else(|| allocator.nil()) - .append(index.pretty(allocator).brackets()) - .append(allocator.text(" = ")) - .append(value.pretty(allocator)), - Self::AccessIdent(ident) => ident.pretty(allocator), - Self::AssignIdent { - local, - name, - s0, - s1, - value, - span: _, - } => local - .map(|s| allocator.text("local ")) - .unwrap_or_else(|| allocator.nil()) - .append(name.pretty(allocator)) - .append(allocator.text(" = ")) - .append(value.pretty(allocator)), - } - } -}