diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index aa4ed1e771b..5af9fa8b1c7 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -89,12 +89,18 @@ tag expr_ {
     expr_binary(binop, @expr, @expr);
     expr_unary(unop, @expr);
     expr_lit(@lit);
-    expr_name(name, option[referent]);
-    expr_field(@expr, ident);
-    expr_index(@expr, @expr);
     expr_cast(@expr, @ty);
     expr_if(@expr, block, option[block]);
     expr_block(block);
+    expr_assign(@lval, @expr);
+    expr_lval(@lval);
+}
+
+type lval = spanned[lval_];
+tag lval_ {
+    lval_field(@expr, ident);
+    lval_index(@expr, @expr);
+    lval_name(name, option[referent]);
 }
 
 type lit = spanned[lit_];
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index d731bf70305..d6968a5b958 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -238,6 +238,25 @@ io fn parse_possibly_mutable_expr(parser p) -> tup(bool, @ast.expr) {
     ret tup(mut, parse_expr(p));
 }
 
+io fn parse_lval(parser p) -> option[@ast.lval] {
+    auto lo = p.get_span();
+
+    alt (p.peek()) {
+        case (token.IDENT(?i)) {
+            auto n = parse_name(p, i);
+            auto hi = n.span;
+            auto lval = ast.lval_name(n, none[ast.referent]);
+            ret some(@spanned(lo, hi, lval));
+        }
+
+        case (_) {
+            ret none[@ast.lval];
+        }
+    }
+
+    fail;
+}
+
 io fn parse_bottom_expr(parser p) -> @ast.expr {
 
     auto lo = p.get_span();
@@ -297,21 +316,22 @@ io fn parse_bottom_expr(parser p) -> @ast.expr {
             ex = ast.expr_rec(es.node);
         }
 
-        case (token.IDENT(?i)) {
-            auto n = parse_name(p, i);
-            hi = n.span;
-            ex = ast.expr_name(n, none[ast.referent]);
-        }
-
         case (_) {
-            alt (parse_lit(p)) {
-                case (some[ast.lit](?lit)) {
-                    hi = lit.span;
-                    ex = ast.expr_lit(@lit);
+            alt (parse_lval(p)) {
+                case (some[@ast.lval](?lval)) {
+                    hi = lval.span;
+                    ex = ast.expr_lval(lval);
                 }
-                case (none[ast.lit]) {
-                    p.err("expecting expression");
-                    fail;
+                case (none[@ast.lval]) {
+                    alt (parse_lit(p)) {
+                        case (some[ast.lit](?lit)) {
+                            hi = lit.span;
+                            ex = ast.expr_lit(@lit);
+                        }
+                        case (none[ast.lit]) {
+                            p.err("expecting expression");
+                        }
+                    }
                 }
             }
         }
@@ -332,13 +352,15 @@ io fn parse_path_expr(parser p) -> @ast.expr {
                     case (token.IDENT(?i)) {
                         hi = p.get_span();
                         p.bump();
-                        e = @spanned(lo, hi, ast.expr_field(e, i));
+                        auto lv = @spanned(lo, hi, ast.lval_field(e, i));
+                        e = @spanned(lo, hi, ast.expr_lval(lv));
                     }
 
                     case (token.LPAREN) {
                         auto ix = parse_bottom_expr(p);
                         hi = ix.span;
-                        e = @spanned(lo, hi, ast.expr_index(e, ix));
+                        auto lv = @spanned(lo, hi, ast.lval_index(e, ix));
+                        e = @spanned(lo, hi, ast.expr_lval(lv));
                     }
                 }
             }
diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs
index 5445d3c1784..a43eb1ac384 100644
--- a/src/comp/middle/fold.rs
+++ b/src/comp/middle/fold.rs
@@ -13,6 +13,7 @@ import front.ast.ident;
 import front.ast.name;
 import front.ast.ty;
 import front.ast.expr;
+import front.ast.lval;
 import front.ast.stmt;
 import front.ast.block;
 import front.ast.item;
@@ -65,16 +66,6 @@ type ast_fold[ENV] =
      (fn(&ENV e, &span sp,
          @ast.lit) -> @expr)                      fold_expr_lit,
 
-     (fn(&ENV e, &span sp,
-         &name n,
-         &option[referent] r) -> @expr)           fold_expr_name,
-
-     (fn(&ENV e, &span sp,
-         @expr e, ident i) -> @expr)              fold_expr_field,
-
-     (fn(&ENV e, &span sp,
-         @expr e, @expr ix) -> @expr)             fold_expr_index,
-
      (fn(&ENV e, &span sp,
          @expr cond, block thn,
          &option[block] els) -> @expr)            fold_expr_if,
@@ -82,6 +73,22 @@ type ast_fold[ENV] =
      (fn(&ENV e, &span sp,
          block blk) -> @expr)                     fold_expr_block,
 
+     (fn(&ENV e, &span sp,
+         @lval lhs, @expr rhs) -> @expr)          fold_expr_assign,
+
+     (fn(&ENV e, &span sp,
+         @lval lv) -> @expr)                      fold_expr_lval,
+
+     // Lvalue folds.
+     (fn(&ENV e, &span sp,
+         @expr e, ident i) -> @lval)              fold_lval_field,
+
+     (fn(&ENV e, &span sp,
+         @expr e, @expr ix) -> @lval)             fold_lval_index,
+
+     (fn(&ENV e, &span sp,
+         &name n,
+         &option[referent] r) -> @lval)           fold_lval_name,
 
      // Decl folds.
      (fn(&ENV e, &span sp,
@@ -131,6 +138,7 @@ type ast_fold[ENV] =
      (fn(&ENV e, @ast.crate c) -> ENV) update_env_for_crate,
      (fn(&ENV e, @item i) -> ENV) update_env_for_item,
      (fn(&ENV e, @stmt s) -> ENV) update_env_for_stmt,
+     (fn(&ENV e, @lval l) -> ENV) update_env_for_lval,
      (fn(&ENV e, @expr x) -> ENV) update_env_for_expr,
      (fn(&ENV e, @ty t) -> ENV) update_env_for_ty,
 
@@ -156,6 +164,33 @@ fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl {
     ret d;
 }
 
+fn fold_lval[ENV](&ENV env, ast_fold[ENV] fld, @lval lv) -> @lval {
+    let ENV env_ = fld.update_env_for_lval(env, lv);
+
+    if (!fld.keep_going(env_)) {
+        ret lv;
+    }
+
+    alt (lv.node) {
+        case (ast.lval_field(?e, ?i)) {
+            auto ee = fold_expr(env_, fld, e);
+            ret fld.fold_lval_field(env_, lv.span, ee, i);
+        }
+
+        case (ast.lval_index(?e, ?ix)) {
+            auto ee = fold_expr(env_, fld, e);
+            auto iix = fold_expr(env_, fld, ix);
+            ret fld.fold_lval_index(env_, lv.span, ee, iix);
+        }
+
+        case (ast.lval_name(?n, ?r)) {
+            ret fld.fold_lval_name(env_, lv.span, n, r);
+        }
+    }
+
+    fail;   // shoudn't be reached
+}
+
 fn fold_exprs[ENV](&ENV env, ast_fold[ENV] fld, vec[@expr] e) -> vec[@expr] {
     let operator[@expr, @expr] fe = bind fold_expr[ENV](env, fld, _);
     ret _vec.map[@expr, @expr](fe, e);
@@ -220,22 +255,6 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
             ret fld.fold_expr_lit(env_, e.span, lit);
         }
 
-        case (ast.expr_name(?n, ?r)) {
-            auto nn = fold_expr_name(env_, fld, n, r);
-            ret fld.fold_expr_name(env_, e.span, nn._0, nn._1);
-        }
-
-        case (ast.expr_field(?e, ?i)) {
-            auto ee = fold_expr(env_, fld, e);
-            ret fld.fold_expr_field(env_, e.span, ee, i);
-        }
-
-        case (ast.expr_index(?e, ?i)) {
-            auto ee = fold_expr(env_, fld, e);
-            auto ii = fold_expr(env_, fld, i);
-            ret fld.fold_expr_index(env_, e.span, ee, ii);
-        }
-
         case (ast.expr_if(?cnd, ?thn, ?els)) {
             auto ccnd = fold_expr(env_, fld, cnd);
             auto tthn = fold_block(env_, fld, thn);
@@ -252,6 +271,17 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
             auto bb = fold_block(env_, fld, b);
             ret fld.fold_expr_block(env_, e.span, bb);
         }
+
+        case (ast.expr_assign(?lhs, ?rhs)) {
+            auto llhs = fold_lval(env_, fld, lhs);
+            auto rrhs = fold_expr(env_, fld, rhs);
+            ret fld.fold_expr_assign(env_, e.span, llhs, rrhs);
+        }
+
+        case (ast.expr_lval(?lv)) {
+            auto llv = fold_lval(env_, fld, lv);
+            ret fld.fold_expr_lval(env_, e.span, llv);
+        }
     }
 
     ret e;
@@ -462,21 +492,6 @@ fn identity_fold_expr_lit[ENV](&ENV env, &span sp, @ast.lit lit) -> @expr {
     ret @respan(sp, ast.expr_lit(lit));
 }
 
-fn identity_fold_expr_name[ENV](&ENV env, &span sp, &name n,
-                          &option[referent] r) -> @expr {
-    ret @respan(sp, ast.expr_name(n, r));
-}
-
-fn identity_fold_expr_field[ENV](&ENV env, &span sp,
-                                 @expr e, ident i) -> @expr {
-    ret @respan(sp, ast.expr_field(e, i));
-}
-
-fn identity_fold_expr_index[ENV](&ENV env, &span sp,
-                                 @expr e, @expr ix) -> @expr {
-    ret @respan(sp, ast.expr_index(e, ix));
-}
-
 fn identity_fold_expr_if[ENV](&ENV env, &span sp,
                               @expr cond, block thn,
                               &option[block] els) -> @expr {
@@ -487,6 +502,33 @@ fn identity_fold_expr_block[ENV](&ENV env, &span sp, block blk) -> @expr {
     ret @respan(sp, ast.expr_block(blk));
 }
 
+fn identity_fold_expr_assign[ENV](&ENV env, &span sp,
+                                  @lval lhs, @expr rhs) -> @expr {
+    ret @respan(sp, ast.expr_assign(lhs, rhs));
+}
+
+fn identity_fold_expr_lval[ENV](&ENV env, &span sp, @lval lv) -> @expr {
+    ret @respan(sp, ast.expr_lval(lv));
+}
+
+
+// Lvalue identities.
+
+fn identity_fold_lval_field[ENV](&ENV env, &span sp,
+                                 @expr e, ident i) -> @lval {
+    ret @respan(sp, ast.lval_field(e, i));
+}
+
+fn identity_fold_lval_index[ENV](&ENV env, &span sp,
+                                 @expr e, @expr ix) -> @lval {
+    ret @respan(sp, ast.lval_index(e, ix));
+}
+
+fn identity_fold_lval_name[ENV](&ENV env, &span sp,
+                                &name n, &option[referent] r) -> @lval {
+    ret @respan(sp, ast.lval_name(n, r));
+}
+
 
 // Decl identities.
 
@@ -575,6 +617,10 @@ fn identity_update_env_for_stmt[ENV](&ENV e, @stmt s) -> ENV {
     ret e;
 }
 
+fn identity_update_env_for_lval[ENV](&ENV e, @lval l) -> ENV {
+    ret e;
+}
+
 fn identity_update_env_for_expr[ENV](&ENV e, @expr x) -> ENV {
     ret e;
 }
@@ -613,11 +659,14 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
          fold_expr_binary = bind identity_fold_expr_binary[ENV](_,_,_,_,_),
          fold_expr_unary  = bind identity_fold_expr_unary[ENV](_,_,_,_),
          fold_expr_lit    = bind identity_fold_expr_lit[ENV](_,_,_),
-         fold_expr_name   = bind identity_fold_expr_name[ENV](_,_,_,_),
-         fold_expr_field  = bind identity_fold_expr_field[ENV](_,_,_,_),
-         fold_expr_index  = bind identity_fold_expr_index[ENV](_,_,_,_),
          fold_expr_if     = bind identity_fold_expr_if[ENV](_,_,_,_,_),
          fold_expr_block  = bind identity_fold_expr_block[ENV](_,_,_),
+         fold_expr_assign = bind identity_fold_expr_assign[ENV](_,_,_,_),
+         fold_expr_lval   = bind identity_fold_expr_lval[ENV](_,_,_),
+
+         fold_lval_field  = bind identity_fold_lval_field[ENV](_,_,_,_),
+         fold_lval_index  = bind identity_fold_lval_index[ENV](_,_,_,_),
+         fold_lval_name   = bind identity_fold_lval_name[ENV](_,_,_,_),
 
          fold_decl_local  = bind identity_fold_decl_local[ENV](_,_,_,_,_),
          fold_decl_item   = bind identity_fold_decl_item[ENV](_,_,_,_),
@@ -639,6 +688,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
          update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_),
          update_env_for_item = bind identity_update_env_for_item[ENV](_,_),
          update_env_for_stmt = bind identity_update_env_for_stmt[ENV](_,_),
+         update_env_for_lval = bind identity_update_env_for_lval[ENV](_,_),
          update_env_for_expr = bind identity_update_env_for_expr[ENV](_,_),
          update_env_for_ty = bind identity_update_env_for_ty[ENV](_,_),