Desugar from the outside in

This commit is contained in:
Joscha 2022-11-21 14:35:10 +01:00
parent ebc48fff5a
commit 290cef06cb
5 changed files with 62 additions and 165 deletions

View file

@ -37,6 +37,17 @@ impl Space {
span, 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)] #[derive(Clone)]

View file

@ -13,44 +13,20 @@ impl Call {
s2, s2,
span, span,
} => { } => {
let (expr, desugared) = expr.desugar(); // `expr s0 ( s1 arg s2 )`
if desugared { // -> `'{ s0 call: expr, arg: s1 arg s2 }`
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);
}
let call = TableLitElem::Named { let call = TableLitElem::Named {
name: Ident::new("call", span), name: Ident::new("call", span),
s0: Space::empty(span), s0: Space::empty(span),
s1: Space::empty(span), s1: Space::empty(span),
value: Box::new(expr), value: expr,
span, span,
}; };
let arg = TableLitElem::Named { let arg = TableLitElem::Named {
name: Ident::new("arg", span), name: Ident::new("arg", span),
s0: Space::empty(span), s0: Space::empty(span),
s1: Space::empty(span), s1,
value: Box::new(arg), value: arg,
span, span,
}; };
let elems = Separated::NonEmpty { let elems = Separated::NonEmpty {
@ -60,32 +36,22 @@ impl Call {
span, span,
}; };
let new = Expr::Lit(Lit::Table(TableLit { let new = Expr::Lit(Lit::Table(TableLit {
s0: Space::empty(span), s0,
elems, elems,
s1: Space::empty(span), s1: s2,
span, span,
})); }));
(new, true) (new, true)
} }
Self::NoArg { expr, s0, s1, span } => { Self::NoArg { expr, s0, s1, span } => {
let (expr, desugared) = expr.desugar(); // `expr s0 ( s1 )`
if desugared { // -> `expr s0 ( s1 nil )`
let new = Expr::Call(Self::NoArg {
expr: Box::new(expr),
s0,
s1,
span,
});
return (new, true);
}
let arg = Expr::Lit(Lit::Nil(span));
let new = Expr::Call(Self::Arg { let new = Expr::Call(Self::Arg {
expr: Box::new(expr), expr,
s0, s0,
s1, s1,
arg: Box::new(arg), arg: Box::new(Expr::Lit(Lit::Nil(span))),
s2: Space::empty(span), s2: Space::empty(span),
span, span,
}); });
@ -98,23 +64,13 @@ impl Call {
constr, constr,
span, span,
} => { } => {
let (expr, desugared) = expr.desugar(); // `expr s0 {..}`
if desugared { // -> `expr s0 ( {..} )`
let new = Expr::Call(Self::Constr {
expr: Box::new(expr),
s0,
constr,
span,
});
return (new, true);
}
let arg = Expr::TableConstr(constr);
let new = Expr::Call(Self::Arg { let new = Expr::Call(Self::Arg {
expr: Box::new(expr), expr,
s0, s0,
s1: Space::empty(span), s1: Space::empty(span),
arg: Box::new(arg), arg: Box::new(Expr::TableConstr(constr)),
s2: Space::empty(span), s2: Space::empty(span),
span, span,
}); });

View file

@ -1,5 +1,5 @@
use crate::ast::{ 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; use crate::builtin::Builtin;
@ -14,37 +14,13 @@ impl Field {
s2, s2,
span, span,
} => { } => {
let (expr, desugared) = expr.desugar(); // ` expr s0 [ s1 index s2 ]`
if desugared { // -> `'get s0 { expr, s1 index s2 }`
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);
}
let elems = Separated::NonEmpty { let elems = Separated::NonEmpty {
first_elem: TableConstrElem::Lit(TableLitElem::Positional(Box::new(expr))), first_elem: TableConstrElem::Lit(TableLitElem::Positional(expr)),
last_elems: vec![( last_elems: vec![(
(Space::empty(span), Space::empty(span)), (Space::empty(span), s1),
TableConstrElem::Lit(TableLitElem::Positional(Box::new(index))), TableConstrElem::Lit(TableLitElem::Positional(index)),
)], )],
trailing: None, trailing: None,
span, span,
@ -52,12 +28,12 @@ impl Field {
let constr = TableConstr { let constr = TableConstr {
s0: Space::empty(span), s0: Space::empty(span),
elems, elems,
s1: Space::empty(span), s1: s2,
span, span,
}; };
let new = Expr::Call(Call::Constr { let new = Expr::Call(Call::Constr {
expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Get, span))), expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Get, span))),
s0: Space::empty(span), s0,
constr, constr,
span, span,
}); });
@ -75,64 +51,18 @@ impl Field {
value, value,
span, span,
} => { } => {
let (expr, desugared) = expr.desugar(); // `expr s0 [ s1 index s2 ] s3 = s4 value`
if desugared { // -> `'set s0 { expr, s1 index s2, s3 s4 value }`
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);
}
let elems = Separated::NonEmpty { let elems = Separated::NonEmpty {
first_elem: TableConstrElem::Lit(TableLitElem::Positional(Box::new(expr))), first_elem: TableConstrElem::Lit(TableLitElem::Positional(expr)),
last_elems: vec![ last_elems: vec![
( (
(Space::empty(span), Space::empty(span)), (Space::empty(span), s1),
TableConstrElem::Lit(TableLitElem::Positional(Box::new(index))), TableConstrElem::Lit(TableLitElem::Positional(index)),
), ),
( (
(Space::empty(span), Space::empty(span)), (s2, s3.then_line(Line::Empty).then(s4)),
TableConstrElem::Lit(TableLitElem::Positional(Box::new(value))), TableConstrElem::Lit(TableLitElem::Positional(value)),
), ),
], ],
trailing: None, trailing: None,
@ -146,7 +76,7 @@ impl Field {
}; };
let new = Expr::Call(Call::Constr { let new = Expr::Call(Call::Constr {
expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Set, span))), expr: Box::new(Expr::Lit(Lit::Builtin(Builtin::Set, span))),
s0: Space::empty(span), s0,
constr, constr,
span, span,
}); });

View file

@ -7,6 +7,7 @@ impl TableLitElem {
let (expr, desugared) = expr.desugar(); let (expr, desugared) = expr.desugar();
(Self::Positional(Box::new(expr)), desugared) (Self::Positional(Box::new(expr)), desugared)
} }
Self::Named { Self::Named {
name, name,
s0, s0,
@ -30,12 +31,19 @@ impl TableLitElem {
impl TableLit { impl TableLit {
pub fn desugar(self) -> (Self, bool) { pub fn desugar(self) -> (Self, bool) {
let (elems, desugared) = self.elems.desugar_elem(|e| e.desugar()); let Self {
let new = Self { s0,
s0: self.s0,
elems, elems,
s1: self.s1, s1,
span: self.span, span,
} = self;
let (elems, desugared) = elems.desugar_elem(|e| e.desugar());
let new = Self {
s0,
elems,
s1,
span,
}; };
(new, desugared) (new, desugared)
} }
@ -48,6 +56,7 @@ impl Lit {
let (table, desugared) = table.desugar(); let (table, desugared) = table.desugar();
(Self::Table(table), desugared) (Self::Table(table), desugared)
} }
lit => (lit, false), lit => (lit, false),
} }
} }

View file

@ -5,7 +5,8 @@ impl Program {
match self { match self {
Self::Expr { s0, expr, s1, span } => { Self::Expr { s0, expr, s1, span } => {
let (expr, desugared) = expr.desugar(); let (expr, desugared) = expr.desugar();
(Self::Expr { s0, expr, s1, span }, desugared) let new = Self::Expr { s0, expr, s1, span };
(new, desugared)
} }
Self::Module { Self::Module {
@ -15,28 +16,18 @@ impl Program {
s2, s2,
span, span,
} => { } => {
let (elems, desugared) = elems.desugar_elem(|e| e.desugar()); // `s0 module s1 elems s2`
if desugared { // -> `s0 '{ s1 elems s2 } empty`
let new = Self::Module {
s0,
s1,
elems,
s2,
span,
};
return (new, true);
}
let table = TableLit { let table = TableLit {
s0: s1, s0: s1,
elems, elems,
s1: Space::empty(span), s1: s2,
span, span,
}; };
let new = Self::Expr { let new = Self::Expr {
s0, s0,
expr: Expr::Lit(Lit::Table(table)), expr: Expr::Lit(Lit::Table(table)),
s1: s2, s1: Space::empty(span),
span, span,
}; };
(new, true) (new, true)