Epic refactor of doom, redux

This commit is contained in:
Chris Wong 2015-02-06 15:43:53 +13:00
parent 47e73c4bca
commit f080ee7da1
2 changed files with 25 additions and 18 deletions
maud_macros/src

View file

@ -199,8 +199,8 @@ impl<'cx, 's, 'i, 'r> Parser<'cx, 's, 'i, 'r> {
if let [ref tt @ eq!(), ..] = self.input { if let [ref tt @ eq!(), ..] = self.input {
// Toggle the attribute based on a boolean expression // Toggle the attribute based on a boolean expression
self.shift(1); self.shift(1);
let expr = self.splice(tt.get_span()); let cond = self.splice(tt.get_span());
self.render.attribute_empty_if(name.as_str(), expr); self.render.attribute_empty_if(name.as_str(), cond);
} else { } else {
// Write the attribute unconditionally // Write the attribute unconditionally
self.render.attribute_empty(name.as_str()); self.render.attribute_empty(name.as_str());

View file

@ -20,6 +20,7 @@ pub struct Renderer<'cx, 's: 'cx> {
} }
impl<'cx, 's> Renderer<'cx, 's> { impl<'cx, 's> Renderer<'cx, 's> {
/// Create a new `Renderer` using the given extension context.
pub fn new(cx: &'cx ExtCtxt<'s>) -> Renderer<'cx, 's> { pub fn new(cx: &'cx ExtCtxt<'s>) -> Renderer<'cx, 's> {
Renderer { Renderer {
cx: cx, cx: cx,
@ -28,6 +29,16 @@ impl<'cx, 's> Renderer<'cx, 's> {
} }
} }
/// Create a new `Renderer` under the same context as `self`.
pub fn fork(&self) -> Renderer<'cx, 's> {
Renderer {
cx: self.cx,
stmts: vec![],
w: self.w,
}
}
/// Reify the `Renderer` into a block of markup.
pub fn into_expr(self) -> P<Expr> { pub fn into_expr(self) -> P<Expr> {
let Renderer { cx, stmts, w } = self; let Renderer { cx, stmts, w } = self;
quote_expr!(cx, quote_expr!(cx,
@ -37,16 +48,10 @@ impl<'cx, 's> Renderer<'cx, 's> {
})) }))
} }
fn make_stmts<F>(&self, f: F) -> Vec<P<Stmt>> where /// Reify the `Renderer` into a raw list of statements.
F: FnOnce(&mut Renderer<'cx, 's>) pub fn into_stmts(self) -> Vec<P<Stmt>> {
{ let Renderer { stmts, .. } = self;
let mut render = Renderer { stmts
cx: self.cx,
stmts: vec![],
w: self.w,
};
f(&mut render);
render.stmts
} }
/// Push an expression statement, also wrapping it with `try!`. /// Push an expression statement, also wrapping it with `try!`.
@ -102,17 +107,19 @@ impl<'cx, 's> Renderer<'cx, 's> {
self.write(name); self.write(name);
} }
pub fn attribute_empty_if(&mut self, name: &str, expr: P<Expr>) { pub fn attribute_empty_if(&mut self, name: &str, cond: P<Expr>) {
// Silence "unnecessary parentheses" warnings // Silence "unnecessary parentheses" warnings
let expr = match expr.node { let cond = match cond.node {
ExprParen(ref inner) => inner.clone(), ExprParen(ref inner) => inner.clone(),
_ => expr.clone(), _ => cond.clone(),
}; };
let stmts = self.make_stmts(|r| { let body = {
let mut r = self.fork();
r.write(" "); r.write(" ");
r.write(name); r.write(name);
}); r.into_stmts()
let stmt = quote_stmt!(self.cx, if $expr { $stmts }); };
let stmt = quote_stmt!(self.cx, if $cond { $body });
self.stmts.push(stmt); self.stmts.push(stmt);
} }