diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index a27de4b969f..abfea16b2ad 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -257,6 +257,7 @@ tag expr_ { expr_do_while(block, @expr, ann); expr_alt(@expr, vec[arm], ann); expr_block(block, ann); + expr_move(@expr /* TODO: @expr|is_lval */, @expr, ann); expr_assign(@expr /* TODO: @expr|is_lval */, @expr, ann); expr_assign_op(binop, @expr /* TODO: @expr|is_lval */, @expr, ann); expr_send(@expr /* TODO: @expr|is_lval */, @expr, ann); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index ecfd881a613..01cf64f3739 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1251,6 +1251,12 @@ fn parse_assign_expr(&parser p) -> @ast::expr { ret @spanned(lo, rhs.span.hi, ast::expr_assign_op(aop, lhs, rhs, p.get_ann())); } + case (token::LARROW) { + p.bump(); + auto rhs = parse_expr(p); + ret @spanned(lo, rhs.span.hi, + ast::expr_move(lhs, rhs, p.get_ann())); + } case (token::SEND) { p.bump(); auto rhs = parse_expr(p); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 18d4999297b..35ff93593a9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5500,6 +5500,18 @@ fn trans_expr_out(&@block_ctxt cx, &@ast::expr e, out_method output) ret res(next_cx, sub.val); } + case (ast::expr_move(?dst, ?src, ?ann)) { + auto lhs_res = trans_lval(cx, dst); + assert (lhs_res.is_mem); + *(lhs_res.res.bcx) = rec(sp=src.span with *(lhs_res.res.bcx)); + auto rhs_res = trans_expr(lhs_res.res.bcx, src); + auto t = node_ann_type(cx.fcx.lcx.ccx, ann); + // FIXME: calculate copy init-ness in typestate. + // FIXME: do all of the special move stuff + ret copy_ty(rhs_res.bcx, DROP_EXISTING, + lhs_res.res.val, rhs_res.val, t); + } + case (ast::expr_assign(?dst, ?src, ?ann)) { auto lhs_res = trans_lval(cx, dst); assert (lhs_res.is_mem); diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index fc449de7148..5a0485e1c79 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -109,6 +109,7 @@ import front::ast::expr_rec; import front::ast::expr_if; import front::ast::expr_binary; import front::ast::expr_unary; +import front::ast::expr_move; import front::ast::expr_assign; import front::ast::expr_assign_op; import front::ast::expr_while; @@ -362,6 +363,17 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { vec::plus_option[@expr](es, maybe_base); find_pre_post_exprs(fcx, es, a); } + case (expr_move(?lhs, ?rhs, ?a)) { + // FIXME: this needs to deinitialize the rhs + alt (lhs.node) { + case (expr_path(?p, ?a_lhs)) { + gen_if_local(fcx, lhs, rhs, a, a_lhs); + } + case (_) { + find_pre_post_exprs(fcx, [lhs, rhs], a); + } + } + } case (expr_assign(?lhs, ?rhs, ?a)) { alt (lhs.node) { case (expr_path(?p, ?a_lhs)) { diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index 77231200e8d..16739fdcbad 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -119,6 +119,7 @@ import front::ast::expr_rec; import front::ast::expr_if; import front::ast::expr_binary; import front::ast::expr_unary; +import front::ast::expr_move; import front::ast::expr_assign; import front::ast::expr_assign_op; import front::ast::expr_while; @@ -329,6 +330,32 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { } ret changed; } + case (expr_move(?lhs, ?rhs, ?a)) { + // FIXME: this needs to deinitialize the rhs + extend_prestate_ann(fcx.ccx, a, pres); + + alt (lhs.node) { + case (expr_path(?p, ?a_lhs)) { + // assignment to local var + changed = pure_exp(fcx.ccx, a_lhs, pres) || changed; + changed = find_pre_post_state_expr(fcx, pres, rhs) + || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, rhs)) || changed; + changed = gen_if_local(fcx, a_lhs, a)|| changed; + } + case (_) { + // assignment to something that must already have been init'd + changed = find_pre_post_state_expr(fcx, pres, lhs) + || changed; + changed = find_pre_post_state_expr(fcx, + expr_poststate(fcx.ccx, lhs), rhs) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, rhs)) || changed; + } + } + ret changed; + } case (expr_assign(?lhs, ?rhs, ?a)) { extend_prestate_ann(fcx.ccx, a, pres); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 7dd1c5d28cb..f936d7513e5 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1767,6 +1767,7 @@ fn expr_ann(&@ast::expr e) -> ast::ann { case (ast::expr_do_while(_,_,?a)) { ret a; } case (ast::expr_alt(_,_,?a)) { ret a; } case (ast::expr_block(_,?a)) { ret a; } + case (ast::expr_move(_,_,?a)) { ret a; } case (ast::expr_assign(_,_,?a)) { ret a; } case (ast::expr_assign_op(_,_,_,?a)) { ret a; } case (ast::expr_send(_,_,?a)) { ret a; } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 589105867bd..13d7204a714 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1388,6 +1388,13 @@ mod pushdown { write::ty_only_fixup(scx, ann.id, t); pushdown_block(scx, t, bloc); } + case (ast::expr_move(?lhs_0, ?rhs_0, ?ann)) { + auto t = demand::autoderef(scx, e.span, expected, + ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk); + pushdown_expr(scx, expected, lhs_0); + pushdown_expr(scx, expected, rhs_0); + write::ty_only_fixup(scx, ann.id, t); + } case (ast::expr_assign(?lhs_0, ?rhs_0, ?ann)) { auto t = demand::autoderef(scx, e.span, expected, ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk); @@ -2106,6 +2113,11 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) { write::nil_ty(scx.fcx.ccx.tcx, a.id); } + case (ast::expr_move(?lhs, ?rhs, ?a)) { + require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span); + check_assignment(scx, lhs, rhs, a); + } + case (ast::expr_assign(?lhs, ?rhs, ?a)) { require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span); check_assignment(scx, lhs, rhs, a); diff --git a/src/comp/middle/walk.rs b/src/comp/middle/walk.rs index 1cec06cd9f8..f0cb9bb5b44 100644 --- a/src/comp/middle/walk.rs +++ b/src/comp/middle/walk.rs @@ -394,6 +394,10 @@ fn walk_expr(&ast_visitor v, @ast::expr e) { walk_expr(v, a); walk_expr(v, b); } + case (ast::expr_move(?a, ?b, _)) { + walk_expr(v, a); + walk_expr(v, b); + } case (ast::expr_assign_op(_, ?a, ?b, _)) { walk_expr(v, a); walk_expr(v, b); diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index dfe6cc3a75a..af6896fd96f 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -690,6 +690,12 @@ fn print_expr(&ps s, &@ast::expr expr) { ibox(s.s, 0u); print_block(s, block); } + case (ast::expr_move(?lhs,?rhs,_)) { + print_expr(s, lhs); + space(s.s); + wrd1(s, "<-"); + print_expr(s, rhs); + } case (ast::expr_assign(?lhs,?rhs,_)) { print_expr(s, lhs); space(s.s);