diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 349f887a2f93c..0d70c993b3b69 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -194,10 +194,18 @@ tag stmt_ { stmt_crate_directive(@crate_directive); } +tag init_op { + init_assign; + init_recv; +} + +type initializer = rec(init_op op, + @expr expr); + type local = rec(option.t[@ty] ty, bool infer, ident ident, - option.t[@expr] init, + option.t[initializer] init, def_id id, ann ann); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 063bc0e178fb1..80130ebf679fa 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1364,13 +1364,22 @@ impure fn parse_expr_inner(parser p) -> @ast.expr { } } -impure fn parse_initializer(parser p) -> option.t[@ast.expr] { - if (p.peek() == token.EQ) { - p.bump(); - ret some(parse_expr(p)); +impure fn parse_initializer(parser p) -> option.t[ast.initializer] { + alt (p.peek()) { + case (token.EQ) { + p.bump(); + ret some(rec(op = ast.init_assign, + expr = parse_expr(p))); + } + case (token.LARROW) { + p.bump(); + ret some(rec(op = ast.init_recv, + expr = parse_expr(p))); + } + case (_) { + ret none[ast.initializer]; + } } - - ret none[@ast.expr]; } impure fn parse_pat(parser p) -> @ast.pat { @@ -1612,6 +1621,8 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_assign(_,_,_)) { ret true; } case (ast.expr_assign_op(_,_,_,_)) { ret true; } + case (ast.expr_send(_,_,_)) { ret true; } + case (ast.expr_recv(_,_,_)) { ret true; } case (ast.expr_field(_,_,_)) { ret true; } case (ast.expr_index(_,_,_)) { ret true; } case (ast.expr_path(_,_,_)) { ret true; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index a1b7761201bac..9525e58b324c0 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -437,7 +437,7 @@ fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl { alt (d.node) { case (ast.decl_local(?local)) { auto ty_ = none[@ast.ty]; - auto init_ = none[@ast.expr]; + auto init_ = none[ast.initializer]; alt (local.ty) { case (some[@ast.ty](?t)) { ty_ = some[@ast.ty](fold_ty(env, fld, t)); @@ -445,8 +445,9 @@ fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl { case (_) { /* fall through */ } } alt (local.init) { - case (some[@ast.expr](?e)) { - init_ = some[@ast.expr](fold_expr(env, fld, e)); + case (some[ast.initializer](?init)) { + auto e = fold_expr(env, fld, init.expr); + init_ = some[ast.initializer](rec(expr = e with init)); } case (_) { /* fall through */ } } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a65bb284121f8..0acbb7e1461fc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4839,22 +4839,31 @@ fn trans_recv(@block_ctxt cx, @ast.expr lhs, @ast.expr rhs, auto data = trans_lval(bcx, lhs); check (data.is_mem); bcx = data.res.bcx; + auto unit_ty = node_ann_type(bcx.fcx.ccx, ann); + + // FIXME: calculate copy init-ness in typestate. + ret recv_val(bcx, data.res.val, rhs, unit_ty, DROP_EXISTING); + } + +fn recv_val(@block_ctxt cx, ValueRef lhs, @ast.expr rhs, + @ty.t unit_ty, copy_action action) -> result { + + auto bcx = cx; auto prt = trans_expr(bcx, rhs); bcx = prt.bcx; auto sub = trans_upcall(bcx, "upcall_recv", - vec(vp2i(bcx, data.res.val), + vec(vp2i(bcx, lhs), vp2i(bcx, prt.val))); bcx = sub.bcx; - auto unit_ty = node_ann_type(cx.fcx.ccx, ann); - auto data_load = load_scalar_or_boxed(bcx, data.res.val, unit_ty); - auto cp = copy_ty(bcx, DROP_EXISTING, data.res.val, data_load, unit_ty); + auto data_load = load_scalar_or_boxed(bcx, lhs, unit_ty); + auto cp = copy_ty(bcx, action, lhs, data_load, unit_ty); bcx = cp.bcx; // TODO: Any cleanup need to be done here? - ret res(bcx, data.res.val); + ret res(bcx, lhs); } fn init_local(@block_ctxt cx, @ast.local local) -> result { @@ -4869,9 +4878,16 @@ fn init_local(@block_ctxt cx, @ast.local local) -> result { vec(clean(bind drop_slot(_, llptr, ty))); alt (local.init) { - case (some[@ast.expr](?e)) { - auto sub = trans_expr(bcx, e); - bcx = copy_ty(sub.bcx, INIT, llptr, sub.val, ty).bcx; + case (some[ast.initializer](?init)) { + alt (init.op) { + case (ast.init_assign) { + auto sub = trans_expr(bcx, init.expr); + bcx = copy_ty(sub.bcx, INIT, llptr, sub.val, ty).bcx; + } + case (ast.init_recv) { + bcx = recv_val(bcx, llptr, init.expr, ty, INIT).bcx; + } + } } case (_) { if (middle.ty.type_has_dynamic_size(ty)) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 47ef81c1952a6..1130920222e16 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -2404,17 +2404,27 @@ fn check_decl_local(&@fn_ctxt fcx, &@ast.decl decl) -> @ast.decl { } } - auto init = local.init; + auto initopt = local.init; alt (local.init) { - case (some[@ast.expr](?expr)) { - auto expr_0 = check_expr(fcx, expr); + case (some[ast.initializer](?init)) { + auto expr_0 = check_expr(fcx, init.expr); auto lty = plain_ty(ty.ty_local(local.id)); - auto expr_1 = demand_expr(fcx, lty, expr_0); - init = some[@ast.expr](expr_1); + auto expr_1; + alt (init.op) { + case (ast.init_assign) { + expr_1 = demand_expr(fcx, lty, expr_0); + } + case (ast.init_recv) { + auto port_ty = plain_ty(ty.ty_port(lty)); + expr_1 = demand_expr(fcx, port_ty, expr_0); + } + } + auto init_0 = rec(expr = expr_1 with init); + initopt = some[ast.initializer](init_0); } case (_) { /* fall through */ } } - auto local_1 = @rec(init = init with *local); + auto local_1 = @rec(init = initopt with *local); ret @rec(node=ast.decl_local(local_1) with *decl); } diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index 0e30ced131da6..8c00c98419b57 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -78,6 +78,8 @@ impure fn print_type(ps s, &@ast.ty ty) { case (ast.ty_str) {wrd(s, "str");} case (ast.ty_box(?mt)) {wrd(s, "@"); print_mt(s, mt);} case (ast.ty_vec(?mt)) {wrd(s, "vec["); print_mt(s, mt); wrd(s, "]");} + case (ast.ty_port(?t)) {wrd(s, "port["); print_type(s, t); wrd(s, "]");} + case (ast.ty_chan(?t)) {wrd(s, "chan["); print_type(s, t); wrd(s, "]");} case (ast.ty_type) {wrd(s, "type");} case (ast.ty_tup(?elts)) { wrd(s, "tup"); @@ -481,6 +483,18 @@ impure fn print_expr(ps s, &@ast.expr expr) { wrd1(s, "="); print_expr(s, rhs); } + case (ast.expr_send(?lhs, ?rhs, _)) { + print_expr(s, lhs); + space(s); + wrd1(s, "<|"); + print_expr(s, rhs); + } + case (ast.expr_recv(?lhs, ?rhs, _)) { + print_expr(s, lhs); + space(s); + wrd1(s, "<-"); + print_expr(s, rhs); + } case (ast.expr_field(?expr,?id,_)) { print_expr(s, expr); wrd(s, "."); @@ -541,6 +555,17 @@ impure fn print_expr(ps s, &@ast.expr expr) { } // TODO: extension 'body' } + case (ast.expr_port(_)) { + wrd(s, "port"); + popen(s); + pclose(s); + } + case (ast.expr_chan(?expr, _)) { + wrd(s, "chan"); + popen(s); + print_expr(s, expr); + pclose(s); + } } end(s); } @@ -561,10 +586,17 @@ impure fn print_decl(ps s, @ast.decl decl) { } wrd(s, loc.ident); alt (loc.init) { - case (option.some[@ast.expr](?init)) { + case (option.some[ast.initializer](?init)) { space(s); - wrd1(s, "="); - print_expr(s, init); + alt (init.op) { + case (ast.init_assign) { + wrd1(s, "="); + } + case (ast.init_recv) { + wrd1(s, "<-"); + } + } + print_expr(s, init.expr); } case (_) {} } diff --git a/src/test/run-pass/decl-with-recv.rs b/src/test/run-pass/decl-with-recv.rs new file mode 100644 index 0000000000000..7698ee01aea8b --- /dev/null +++ b/src/test/run-pass/decl-with-recv.rs @@ -0,0 +1,14 @@ +// -*- rust -*- + +impure fn main() { + let port[int] po = port(); + let chan[int] ch = chan(po); + + ch <| 10; + let int i <- po; + check (i == 10); + + ch <| 11; + auto j <- po; + check (j == 11); +}