Looping
diff --git a/src/expr.rs b/src/expr.rs
index 55aa3f8..e3a022c 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -367,10 +367,8 @@
             expr_if
             |
             expr_while
-            // TODO: WhileLet
-            // TODO: ForLoop
-            // TODO: Loop
-            // TODO: ForLoop
+            |
+            expr_for_loop
             |
             expr_loop
             |
@@ -542,24 +540,26 @@
 
     named!(and_ascription -> Ty, preceded!(punct!(":"), ty));
 
-    enum IfCond {
+    enum Cond {
         Let(Pat, Expr),
         Expr(Expr),
     }
 
+    named!(cond -> Cond, alt!(
+        do_parse!(
+            keyword!("let") >>
+            pat: pat >>
+            punct!("=") >>
+            value: expr >>
+            (Cond::Let(pat, value))
+        )
+        |
+        map!(expr, Cond::Expr)
+    ));
+
     named!(expr_if -> Expr, do_parse!(
         keyword!("if") >>
-        cond: alt!(
-            do_parse!(
-                keyword!("let") >>
-                pat: pat >>
-                punct!("=") >>
-                value: expr >>
-                (IfCond::Let(pat, value))
-            )
-            |
-            map!(expr, IfCond::Expr)
-        ) >>
+        cond: cond >>
         punct!("{") >>
         then_block: within_block >>
         punct!("}") >>
@@ -579,7 +579,7 @@
             )
         )) >>
         (match cond {
-            IfCond::Let(pat, expr) => Expr::IfLet(
+            Cond::Let(pat, expr) => Expr::IfLet(
                 Box::new(pat),
                 Box::new(expr),
                 Block {
@@ -587,7 +587,7 @@
                 },
                 else_block.map(Box::new),
             ),
-            IfCond::Expr(cond) => Expr::If(
+            Cond::Expr(cond) => Expr::If(
                 Box::new(cond),
                 Block {
                     stmts: then_block,
@@ -597,6 +597,16 @@
         })
     ));
 
+    named!(expr_for_loop -> Expr, do_parse!(
+        lbl: option!(terminated!(label, punct!(":"))) >>
+        keyword!("for") >>
+        pat: pat >>
+        keyword!("in") >>
+        expr: expr >>
+        loop_block: block >>
+        (Expr::ForLoop(Box::new(pat), Box::new(expr), loop_block, lbl))
+    ));
+
     named!(expr_loop -> Expr, do_parse!(
         lbl: option!(terminated!(label, punct!(":"))) >>
         keyword!("loop") >>
@@ -671,13 +681,21 @@
     named!(expr_while -> Expr, do_parse!(
         lbl: option!(terminated!(label, punct!(":"))) >>
         keyword!("while") >>
-        cond: expr >>
+        cond: cond >>
         while_block: block >>
-        (Expr::While(
-            Box::new(cond),
-            while_block,
-            lbl,
-        ))
+        (match cond {
+            Cond::Let(pat, expr) => Expr::WhileLet(
+                Box::new(pat),
+                Box::new(expr),
+                while_block,
+                lbl,
+            ),
+            Cond::Expr(cond) => Expr::While(
+                Box::new(cond),
+                while_block,
+                lbl,
+            ),
+        })
     ));
 
     named!(expr_continue -> Expr, do_parse!(
@@ -862,8 +880,15 @@
     impl ToTokens for Expr {
         fn to_tokens(&self, tokens: &mut Tokens) {
             match *self {
-                Expr::Box(ref _inner) => unimplemented!(),
-                Expr::Vec(ref _inner) => unimplemented!(),
+                Expr::Box(ref inner) => {
+                    tokens.append("box");
+                    inner.to_tokens(tokens);
+                }
+                Expr::Vec(ref tys) => {
+                    tokens.append("[");
+                    tokens.append_separated(tys, ",");
+                    tokens.append("]");
+                }
                 Expr::Call(ref func, ref args) => {
                     func.to_tokens(tokens);
                     tokens.append("(");
@@ -933,10 +958,46 @@
                         else_block.to_tokens(tokens);
                     }
                 }
-                Expr::While(ref _cond, ref _body, ref _label) => unimplemented!(),
-                Expr::WhileLet(ref _pat, ref _expr, ref _body, ref _label) => unimplemented!(),
-                Expr::ForLoop(ref _pat, ref _expr, ref _body, ref _label) => unimplemented!(),
-                Expr::Loop(ref _body, ref _label) => unimplemented!(),
+                Expr::While(ref cond, ref body, ref label) => {
+                    if let Some(ref label) = *label {
+                        label.to_tokens(tokens);
+                        tokens.append(":");
+                    }
+                    tokens.append("while");
+                    cond.to_tokens(tokens);
+                    body.to_tokens(tokens);
+                }
+                Expr::WhileLet(ref pat, ref expr, ref body, ref label) => {
+                    if let Some(ref label) = *label {
+                        label.to_tokens(tokens);
+                        tokens.append(":");
+                    }
+                    tokens.append("while");
+                    tokens.append("let");
+                    pat.to_tokens(tokens);
+                    tokens.append("=");
+                    expr.to_tokens(tokens);
+                    body.to_tokens(tokens);
+                }
+                Expr::ForLoop(ref pat, ref expr, ref body, ref label) => {
+                    if let Some(ref label) = *label {
+                        label.to_tokens(tokens);
+                        tokens.append(":");
+                    }
+                    tokens.append("for");
+                    pat.to_tokens(tokens);
+                    tokens.append("in");
+                    expr.to_tokens(tokens);
+                    body.to_tokens(tokens);
+                }
+                Expr::Loop(ref body, ref label) => {
+                    if let Some(ref label) = *label {
+                        label.to_tokens(tokens);
+                        tokens.append(":");
+                    }
+                    tokens.append("loop");
+                    body.to_tokens(tokens);
+                }
                 Expr::Match(ref expr, ref arms) => {
                     tokens.append("match");
                     expr.to_tokens(tokens);
@@ -984,12 +1045,40 @@
                     rules.to_tokens(tokens);
                     block.to_tokens(tokens);
                 }
-                Expr::Assign(ref _var, ref _expr) => unimplemented!(),
-                Expr::AssignOp(_op, ref _var, ref _expr) => unimplemented!(),
-                Expr::Field(ref _expr, ref _field) => unimplemented!(),
-                Expr::TupField(ref _expr, _field) => unimplemented!(),
-                Expr::Index(ref _expr, ref _index) => unimplemented!(),
-                Expr::Range(ref _from, ref _to, _limits) => unimplemented!(),
+                Expr::Assign(ref var, ref expr) => {
+                    var.to_tokens(tokens);
+                    tokens.append("=");
+                    expr.to_tokens(tokens);
+                }
+                Expr::AssignOp(op, ref var, ref expr) => {
+                    var.to_tokens(tokens);
+                    tokens.append(op.assign_op());
+                    expr.to_tokens(tokens);
+                }
+                Expr::Field(ref expr, ref field) => {
+                    expr.to_tokens(tokens);
+                    tokens.append(".");
+                    field.to_tokens(tokens);
+                }
+                Expr::TupField(ref expr, field) => {
+                    expr.to_tokens(tokens);
+                    tokens.append(".");
+                    tokens.append(&field.to_string());
+                }
+                Expr::Index(ref expr, ref index) => {
+                    expr.to_tokens(tokens);
+                    tokens.append("[");
+                    index.to_tokens(tokens);
+                    tokens.append("]");
+                }
+                Expr::Range(ref from, ref to, limits) => {
+                    from.to_tokens(tokens);
+                    match limits {
+                        RangeLimits::HalfOpen => tokens.append(".."),
+                        RangeLimits::Closed => tokens.append("..."),
+                    }
+                    to.to_tokens(tokens);
+                }
                 Expr::Path(None, ref path) => {
                     path.to_tokens(tokens);
                 }
@@ -1065,38 +1154,66 @@
         }
     }
 
+    impl BinOp {
+        fn op(&self) -> &'static str {
+            match *self {
+                BinOp::Add => "+",
+                BinOp::Sub => "-",
+                BinOp::Mul => "*",
+                BinOp::Div => "/",
+                BinOp::Rem => "%",
+                BinOp::And => "&&",
+                BinOp::Or => "||",
+                BinOp::BitXor => "^",
+                BinOp::BitAnd => "&",
+                BinOp::BitOr => "|",
+                BinOp::Shl => "<<",
+                BinOp::Shr => ">>",
+                BinOp::Eq => "==",
+                BinOp::Lt => "<",
+                BinOp::Le => "<=",
+                BinOp::Ne => "!=",
+                BinOp::Ge => ">=",
+                BinOp::Gt => ">",
+            }
+        }
+
+        fn assign_op(&self) -> &'static str {
+            match *self {
+                BinOp::Add => "+=",
+                BinOp::Sub => "-=",
+                BinOp::Mul => "*=",
+                BinOp::Div => "/=",
+                BinOp::Rem => "%=",
+                BinOp::BitXor => "^=",
+                BinOp::BitAnd => "&=",
+                BinOp::BitOr => "|=",
+                BinOp::Shl => "<<=",
+                BinOp::Shr => ">>=",
+                _ => panic!("bad assignment operator"),
+            }
+        }
+    }
+
     impl ToTokens for BinOp {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append(self.op());
+        }
+    }
+
+    impl UnOp {
+        fn op(&self) -> &'static str {
             match *self {
-                BinOp::Add => tokens.append("+"),
-                BinOp::Sub => tokens.append("-"),
-                BinOp::Mul => tokens.append("*"),
-                BinOp::Div => tokens.append("/"),
-                BinOp::Rem => tokens.append("%"),
-                BinOp::And => tokens.append("&&"),
-                BinOp::Or => tokens.append("||"),
-                BinOp::BitXor => tokens.append("^"),
-                BinOp::BitAnd => tokens.append("&"),
-                BinOp::BitOr => tokens.append("|"),
-                BinOp::Shl => tokens.append("<<"),
-                BinOp::Shr => tokens.append(">>"),
-                BinOp::Eq => tokens.append("=="),
-                BinOp::Lt => tokens.append("<"),
-                BinOp::Le => tokens.append("<="),
-                BinOp::Ne => tokens.append("!="),
-                BinOp::Ge => tokens.append(">="),
-                BinOp::Gt => tokens.append(">"),
+                UnOp::Deref => "*",
+                UnOp::Not => "!",
+                UnOp::Neg => "-",
             }
         }
     }
 
     impl ToTokens for UnOp {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            match *self {
-                UnOp::Deref => tokens.append("*"),
-                UnOp::Not => tokens.append("!"),
-                UnOp::Neg => tokens.append("-"),
-            }
+            tokens.append(self.op());
         }
     }
 
diff --git a/tests/cases/function.rs b/tests/cases/function.rs
index 38cd72b..d80e29f 100644
--- a/tests/cases/function.rs
+++ b/tests/cases/function.rs
@@ -36,6 +36,24 @@
     };
 }
 
+fn looping() {
+    loop {
+        print(a);
+    };
+
+    while true {
+        print(a);
+    };
+
+    while let a = true {
+        print(a);
+    };
+
+    for a in b {
+        print(a);
+    };
+}
+
 fn item() {
     struct S;