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](_,_),