Desugar from the outside in
This commit is contained in:
parent
ebc48fff5a
commit
290cef06cb
5 changed files with 62 additions and 165 deletions
|
|
@ -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)]
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue