From f080ee7da1c47d067d48dc2f8e35317aaab770df Mon Sep 17 00:00:00 2001
From: Chris Wong <lambda.fairy@gmail.com>
Date: Fri, 6 Feb 2015 15:43:53 +1300
Subject: [PATCH] Epic refactor of doom, redux

---
 maud_macros/src/parse.rs  |  4 ++--
 maud_macros/src/render.rs | 39 +++++++++++++++++++++++----------------
 2 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs
index 052c363..4fce3d0 100644
--- a/maud_macros/src/parse.rs
+++ b/maud_macros/src/parse.rs
@@ -199,8 +199,8 @@ impl<'cx, 's, 'i, 'r> Parser<'cx, 's, 'i, 'r> {
                 if let [ref tt @ eq!(), ..] = self.input {
                     // Toggle the attribute based on a boolean expression
                     self.shift(1);
-                    let expr = self.splice(tt.get_span());
-                    self.render.attribute_empty_if(name.as_str(), expr);
+                    let cond = self.splice(tt.get_span());
+                    self.render.attribute_empty_if(name.as_str(), cond);
                 } else {
                     // Write the attribute unconditionally
                     self.render.attribute_empty(name.as_str());
diff --git a/maud_macros/src/render.rs b/maud_macros/src/render.rs
index ffed877..2ecfd9a 100644
--- a/maud_macros/src/render.rs
+++ b/maud_macros/src/render.rs
@@ -20,6 +20,7 @@ pub struct Renderer<'cx, 's: 'cx> {
 }
 
 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> {
         Renderer {
             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> {
         let Renderer { cx, stmts, w } = self;
         quote_expr!(cx,
@@ -37,16 +48,10 @@ impl<'cx, 's> Renderer<'cx, 's> {
             }))
     }
 
-    fn make_stmts<F>(&self, f: F) -> Vec<P<Stmt>> where
-        F: FnOnce(&mut Renderer<'cx, 's>)
-    {
-        let mut render = Renderer {
-            cx: self.cx,
-            stmts: vec![],
-            w: self.w,
-        };
-        f(&mut render);
-        render.stmts
+    /// Reify the `Renderer` into a raw list of statements.
+    pub fn into_stmts(self) -> Vec<P<Stmt>> {
+        let Renderer { stmts, .. } = self;
+        stmts
     }
 
     /// Push an expression statement, also wrapping it with `try!`.
@@ -102,17 +107,19 @@ impl<'cx, 's> Renderer<'cx, 's> {
         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
-        let expr = match expr.node {
+        let cond = match cond.node {
             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(name);
-        });
-        let stmt = quote_stmt!(self.cx, if $expr { $stmts });
+            r.into_stmts()
+        };
+        let stmt = quote_stmt!(self.cx, if $cond { $body });
         self.stmts.push(stmt);
     }