From b3cda0a3c637aae1cdaa9cb9e34dcb9f24ba9e8e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Mar 2011 20:50:05 -0400 Subject: [PATCH 1/4] Add test for local declarations with receive. XFAIL in rustc. --- Makefile.in | 1 + src/test/run-pass/decl-with-recv.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/test/run-pass/decl-with-recv.rs diff --git a/Makefile.in b/Makefile.in index 129b46a81a08f..df3fe0f972f4f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -652,6 +652,7 @@ TEST_XFAILS_STAGE0 := $(FLOAT_XFAILS) \ clone-with-exterior.rs \ comm.rs \ constrained-type.rs \ + decl-with-recv.rs \ destructor-ordering.rs \ iter-ret.rs \ lazychan.rs \ 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); +} From e980c590cf8069134d213ced9759c316d96a2627 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Mar 2011 21:04:29 -0400 Subject: [PATCH 2/4] Refactor ast.local to make room for initialization via recv --- src/comp/front/ast.rs | 10 +++++++++- src/comp/front/parser.rs | 7 ++++--- src/comp/middle/fold.rs | 10 ++++++---- src/comp/middle/trans.rs | 4 ++-- src/comp/middle/typeck.rs | 11 ++++++----- src/comp/pretty/pprust.rs | 4 ++-- 6 files changed, 29 insertions(+), 17 deletions(-) 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..23b4a9366fce4 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1364,13 +1364,14 @@ impure fn parse_expr_inner(parser p) -> @ast.expr { } } -impure fn parse_initializer(parser p) -> option.t[@ast.expr] { +impure fn parse_initializer(parser p) -> option.t[ast.initializer] { if (p.peek() == token.EQ) { p.bump(); - ret some(parse_expr(p)); + ret some(rec(op = ast.init_assign, + expr = parse_expr(p))); } - ret none[@ast.expr]; + ret none[ast.initializer]; } impure fn parse_pat(parser p) -> @ast.pat { diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index a1b7761201bac..b59a1f3b990a4 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 initopt = none[ast.initializer]; alt (local.ty) { case (some[@ast.ty](?t)) { ty_ = some[@ast.ty](fold_ty(env, fld, t)); @@ -445,12 +445,14 @@ 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 init_ = rec(expr = fold_expr(env, fld, init.expr) + with init); + initopt = some[ast.initializer](init_); } case (_) { /* fall through */ } } - let @ast.local local_ = @rec(ty=ty_, init=init_ with *local); + let @ast.local local_ = @rec(ty=ty_, init=initopt with *local); ret fld.fold_decl_local(env_, d.span, local_); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a65bb284121f8..5c7c8ff7c796f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4869,8 +4869,8 @@ 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); + case (some[ast.initializer](?init)) { + auto sub = trans_expr(bcx, init.expr); bcx = copy_ty(sub.bcx, INIT, llptr, sub.val, ty).bcx; } case (_) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 47ef81c1952a6..a381ae931ceae 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -2404,17 +2404,18 @@ 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 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..22124511cfed6 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -561,10 +561,10 @@ 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); + print_expr(s, init.expr); } case (_) {} } From 38cb578e40f4920b4ff7347df202c371443a488d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Mar 2011 21:54:19 -0400 Subject: [PATCH 3/4] Implement local declarations with receive. Un-XFAIL decl-with-recv.rs. --- Makefile.in | 1 - src/comp/front/parser.rs | 20 ++++++++++++++------ src/comp/middle/fold.rs | 9 ++++----- src/comp/middle/trans.rs | 30 +++++++++++++++++++++++------- src/comp/middle/typeck.rs | 11 ++++++++++- 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/Makefile.in b/Makefile.in index df3fe0f972f4f..129b46a81a08f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -652,7 +652,6 @@ TEST_XFAILS_STAGE0 := $(FLOAT_XFAILS) \ clone-with-exterior.rs \ comm.rs \ constrained-type.rs \ - decl-with-recv.rs \ destructor-ordering.rs \ iter-ret.rs \ lazychan.rs \ diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 23b4a9366fce4..a903124d5f214 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1365,13 +1365,21 @@ impure fn parse_expr_inner(parser p) -> @ast.expr { } impure fn parse_initializer(parser p) -> option.t[ast.initializer] { - if (p.peek() == token.EQ) { - p.bump(); - ret some(rec(op = ast.init_assign, - expr = parse_expr(p))); + 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.initializer]; } impure fn parse_pat(parser p) -> @ast.pat { diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index b59a1f3b990a4..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 initopt = none[ast.initializer]; + auto init_ = none[ast.initializer]; alt (local.ty) { case (some[@ast.ty](?t)) { ty_ = some[@ast.ty](fold_ty(env, fld, t)); @@ -446,13 +446,12 @@ fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl { } alt (local.init) { case (some[ast.initializer](?init)) { - auto init_ = rec(expr = fold_expr(env, fld, init.expr) - with init); - initopt = some[ast.initializer](init_); + auto e = fold_expr(env, fld, init.expr); + init_ = some[ast.initializer](rec(expr = e with init)); } case (_) { /* fall through */ } } - let @ast.local local_ = @rec(ty=ty_, init=initopt with *local); + let @ast.local local_ = @rec(ty=ty_, init=init_ with *local); ret fld.fold_decl_local(env_, d.span, local_); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5c7c8ff7c796f..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 { @@ -4870,8 +4879,15 @@ fn init_local(@block_ctxt cx, @ast.local local) -> result { alt (local.init) { case (some[ast.initializer](?init)) { - auto sub = trans_expr(bcx, init.expr); - bcx = copy_ty(sub.bcx, INIT, llptr, sub.val, ty).bcx; + 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 a381ae931ceae..1130920222e16 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -2409,7 +2409,16 @@ fn check_decl_local(&@fn_ctxt fcx, &@ast.decl decl) -> @ast.decl { 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); + 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); } From 53f183ebb0bb860b2fd4f239a4073357aa11c0b2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Mar 2011 23:03:12 -0400 Subject: [PATCH 4/4] Update pretty printer for ports, channels, send and receive --- src/comp/front/parser.rs | 2 ++ src/comp/pretty/pprust.rs | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index a903124d5f214..80130ebf679fa 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1621,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/pretty/pprust.rs b/src/comp/pretty/pprust.rs index 22124511cfed6..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); } @@ -563,7 +588,14 @@ impure fn print_decl(ps s, @ast.decl decl) { alt (loc.init) { case (option.some[ast.initializer](?init)) { space(s); - wrd1(s, "="); + alt (init.op) { + case (ast.init_assign) { + wrd1(s, "="); + } + case (ast.init_recv) { + wrd1(s, "<-"); + } + } print_expr(s, init.expr); } case (_) {}