diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 5999388ee12ce..8507298d773d3 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -232,6 +232,8 @@ tag expr_ { expr_block(block, 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); + expr_recv(@expr /* TODO: @expr|is_lval */, @expr, ann); expr_field(@expr, ident, ann); expr_index(@expr, @expr, ann); expr_path(path, option.t[def], ann); @@ -242,6 +244,8 @@ tag expr_ { expr_be(@expr); expr_log(@expr); expr_check_expr(@expr); + expr_port(ann); + expr_chan(@expr, ann); } type lit = spanned[lit_]; @@ -274,6 +278,8 @@ tag ty_ { ty_str; ty_box(@ty); ty_vec(@ty); + ty_port(@ty); + ty_chan(@ty); ty_tup(vec[@ty]); ty_rec(vec[ty_field]); ty_fn(proto, vec[ty_arg], @ty); // TODO: effect diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 45cec0c0d2337..997992c542ad3 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -429,6 +429,22 @@ impure fn parse_ty(parser p) -> @ast.ty { t = parse_ty_obj(p, hi); } + case (token.PORT) { + p.bump(); + expect(p, token.LBRACKET); + t = ast.ty_port(parse_ty(p)); + hi = p.get_span(); + expect(p, token.RBRACKET); + } + + case (token.CHAN) { + p.bump(); + expect(p, token.LBRACKET); + t = ast.ty_chan(parse_ty(p)); + hi = p.get_span(); + expect(p, token.RBRACKET); + } + case (token.IDENT(_)) { t = ast.ty_path(parse_path(p, GREEDY), none[ast.def]); } @@ -799,6 +815,23 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { } } + case (token.PORT) { + p.bump(); + expect(p, token.LPAREN); + expect(p, token.RPAREN); + hi = p.get_span(); + ex = ast.expr_port(ast.ann_none); + } + + case (token.CHAN) { + p.bump(); + expect(p, token.LPAREN); + auto e = parse_expr(p); + hi = e.span; + expect(p, token.RPAREN); + ex = ast.expr_chan(e, ast.ann_none); + } + case (_) { auto lit = parse_lit(p); hi = lit.span; @@ -1080,6 +1113,18 @@ impure fn parse_assign_expr(parser p) -> @ast.expr { ret @spanned(lo, rhs.span, ast.expr_assign_op(aop, lhs, rhs, ast.ann_none)); } + case (token.SEND) { + p.bump(); + auto rhs = parse_expr(p); + ret @spanned(lo, rhs.span, + ast.expr_send(lhs, rhs, ast.ann_none)); + } + case (token.LARROW) { + p.bump(); + auto rhs = parse_expr(p); + ret @spanned(lo, rhs.span, + ast.expr_recv(lhs, rhs, ast.ann_none)); + } case (_) { /* fall through */ } } ret lhs; diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 17a2a2ca37424..8de857495c6e0 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -67,6 +67,8 @@ type ast_fold[ENV] = &option.t[def] d) -> @ty) fold_ty_path, (fn(&ENV e, &span sp, @ty t) -> @ty) fold_ty_mutable, + (fn(&ENV e, &span sp, @ty t) -> @ty) fold_ty_chan, + (fn(&ENV e, &span sp, @ty t) -> @ty) fold_ty_port, // Expr folds. (fn(&ENV e, &span sp, @@ -141,6 +143,12 @@ type ast_fold[ENV] = @expr lhs, @expr rhs, ann a) -> @expr) fold_expr_assign_op, + (fn(&ENV e, &span sp, + @expr lhs, @expr rhs, ann a) -> @expr) fold_expr_send, + + (fn(&ENV e, &span sp, + @expr lhs, @expr rhs, ann a) -> @expr) fold_expr_recv, + (fn(&ENV e, &span sp, @expr e, ident i, ann a) -> @expr) fold_expr_field, @@ -177,6 +185,13 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, @expr e) -> @expr) fold_expr_check_expr, + (fn(&ENV e, &span sp, + ann a) -> @expr) fold_expr_port, + + (fn(&ENV e, &span sp, + @expr e, ann a) -> @expr) fold_expr_chan, + + // Decl folds. (fn(&ENV e, &span sp, @ast.local local) -> @decl) fold_decl_local, @@ -386,6 +401,16 @@ fn fold_ty[ENV](&ENV env, ast_fold[ENV] fld, @ty t) -> @ty { case (ast.ty_fn(?proto, ?inputs, ?output)) { ret fold_ty_fn(env_, fld, t.span, proto, inputs, output); } + + case (ast.ty_chan(?ty)) { + auto ty_ = fold_ty(env, fld, ty); + ret fld.fold_ty_chan(env_, t.span, ty_); + } + + case (ast.ty_port(?ty)) { + auto ty_ = fold_ty(env, fld, ty); + ret fld.fold_ty_port(env_, t.span, ty_); + } } } @@ -640,6 +665,18 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_assign_op(env_, e.span, op, llhs, rrhs, t); } + case (ast.expr_send(?lhs, ?rhs, ?t)) { + auto llhs = fold_expr(env_, fld, lhs); + auto rrhs = fold_expr(env_, fld, rhs); + ret fld.fold_expr_send(env_, e.span, llhs, rrhs, t); + } + + case (ast.expr_recv(?lhs, ?rhs, ?t)) { + auto llhs = fold_expr(env_, fld, lhs); + auto rrhs = fold_expr(env_, fld, rhs); + ret fld.fold_expr_recv(env_, e.span, llhs, rrhs, t); + } + case (ast.expr_field(?e, ?i, ?t)) { auto ee = fold_expr(env_, fld, e); ret fld.fold_expr_field(env_, e.span, ee, i, t); @@ -705,6 +742,14 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_check_expr(env_, e.span, ee); } + case (ast.expr_port(?t)) { + ret fld.fold_expr_port(env_, e.span, t); + } + + case (ast.expr_chan(?x, ?t)) { + auto ee = fold_expr(env_, fld, x); + ret fld.fold_expr_chan(env_, e.span, ee, t); + } } fail; @@ -1083,6 +1128,13 @@ fn identity_fold_ty_mutable[ENV](&ENV env, &span sp, @ty t) -> @ty { ret @respan(sp, ast.ty_mutable(t)); } +fn identity_fold_ty_chan[ENV](&ENV env, &span sp, @ty t) -> @ty { + ret @respan(sp, ast.ty_chan(t)); +} + +fn identity_fold_ty_port[ENV](&ENV env, &span sp, @ty t) -> @ty { + ret @respan(sp, ast.ty_port(t)); +} // Expr identities. @@ -1186,6 +1238,16 @@ fn identity_fold_expr_assign_op[ENV](&ENV env, &span sp, ast.binop op, ret @respan(sp, ast.expr_assign_op(op, lhs, rhs, a)); } +fn identity_fold_expr_send[ENV](&ENV e, &span sp, + @expr lhs, @expr rhs, ann a) -> @expr { + ret @respan(sp, ast.expr_send(lhs, rhs, a)); +} + +fn identity_fold_expr_recv[ENV](&ENV e, &span sp, + @expr lhs, @expr rhs, ann a) -> @expr { + ret @respan(sp, ast.expr_recv(lhs, rhs, a)); +} + fn identity_fold_expr_field[ENV](&ENV env, &span sp, @expr e, ident i, ann a) -> @expr { ret @respan(sp, ast.expr_field(e, i, a)); @@ -1236,6 +1298,13 @@ fn identity_fold_expr_check_expr[ENV](&ENV e, &span sp, @expr x) -> @expr { ret @respan(sp, ast.expr_check_expr(x)); } +fn identity_fold_expr_port[ENV](&ENV e, &span sp, ann a) -> @expr { + ret @respan(sp, ast.expr_port(a)); +} + +fn identity_fold_expr_chan[ENV](&ENV e, &span sp, @expr x, ann a) -> @expr { + ret @respan(sp, ast.expr_chan(x, a)); +} // Decl identities. @@ -1473,6 +1542,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_,_), fold_ty_path = bind identity_fold_ty_path[ENV](_,_,_,_), fold_ty_mutable = bind identity_fold_ty_mutable[ENV](_,_,_), + fold_ty_chan = bind identity_fold_ty_chan[ENV](_,_,_), + fold_ty_port = bind identity_fold_ty_port[ENV](_,_,_), fold_expr_vec = bind identity_fold_expr_vec[ENV](_,_,_,_), fold_expr_tup = bind identity_fold_expr_tup[ENV](_,_,_,_), @@ -1495,6 +1566,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_assign = bind identity_fold_expr_assign[ENV](_,_,_,_,_), fold_expr_assign_op = bind identity_fold_expr_assign_op[ENV](_,_,_,_,_,_), + fold_expr_send = bind identity_fold_expr_send[ENV](_,_,_,_,_), + fold_expr_recv = bind identity_fold_expr_recv[ENV](_,_,_,_,_), fold_expr_field = bind identity_fold_expr_field[ENV](_,_,_,_,_), fold_expr_index = bind identity_fold_expr_index[ENV](_,_,_,_,_), fold_expr_path = bind identity_fold_expr_path[ENV](_,_,_,_,_), @@ -1506,6 +1579,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_log = bind identity_fold_expr_log[ENV](_,_,_), fold_expr_check_expr = bind identity_fold_expr_check_expr[ENV](_,_,_), + fold_expr_port = bind identity_fold_expr_port[ENV](_,_,_), + fold_expr_chan = bind identity_fold_expr_chan[ENV](_,_,_,_), fold_decl_local = bind identity_fold_decl_local[ENV](_,_,_), fold_decl_item = bind identity_fold_decl_item[ENV](_,_,_), diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index bd3e3263820b8..0999e416d4f63 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -38,6 +38,8 @@ tag sty { ty_tag(ast.def_id, vec[@t]); ty_box(@t); ty_vec(@t); + ty_port(@t); + ty_chan(@t); ty_tup(vec[@t]); ty_rec(vec[field]); ty_fn(ast.proto, vec[arg], @t); // TODO: effect @@ -146,17 +148,19 @@ fn ty_to_str(&@t typ) -> str { } alt (typ.struct) { - case (ty_native) { s = "native"; } - case (ty_nil) { s = "()"; } - case (ty_bool) { s = "bool"; } - case (ty_int) { s = "int"; } - case (ty_uint) { s = "uint"; } - case (ty_machine(?tm)) { s = common.ty_mach_to_str(tm); } - case (ty_char) { s = "char"; } - case (ty_str) { s = "str"; } - case (ty_box(?t)) { s = "@" + ty_to_str(t); } - case (ty_vec(?t)) { s = "vec[" + ty_to_str(t) + "]"; } - case (ty_type) { s = "type"; } + case (ty_native) { s = "native"; } + case (ty_nil) { s = "()"; } + case (ty_bool) { s = "bool"; } + case (ty_int) { s = "int"; } + case (ty_uint) { s = "uint"; } + case (ty_machine(?tm)) { s = common.ty_mach_to_str(tm); } + case (ty_char) { s = "char"; } + case (ty_str) { s = "str"; } + case (ty_box(?t)) { s = "@" + ty_to_str(t); } + case (ty_vec(?t)) { s = "vec[" + ty_to_str(t) + "]"; } + case (ty_port(?t)) { s = "port[" + ty_to_str(t) + "]"; } + case (ty_chan(?t)) { s = "chan[" + ty_to_str(t) + "]"; } + case (ty_type) { s = "type"; } case (ty_tup(?elems)) { auto f = ty_to_str; @@ -240,6 +244,12 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { case (ty_vec(?subty)) { ret rewrap(ty, ty_vec(fold_ty(fld, subty))); } + case (ty_port(?subty)) { + ret rewrap(ty, ty_port(fold_ty(fld, subty))); + } + case (ty_chan(?subty)) { + ret rewrap(ty, ty_chan(fold_ty(fld, subty))); + } case (ty_tag(?tid, ?subtys)) { let vec[@t] new_subtys = vec(); for (@t subty in subtys) { @@ -1159,6 +1169,52 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } + case (ty.ty_port(?expected_sub)) { + alt (actual.struct) { + case (ty.ty_port(?actual_sub)) { + auto result = unify_step(bindings, + expected_sub, + actual_sub, + handler); + alt (result) { + case (ures_ok(?result_sub)) { + ret ures_ok(plain_ty(ty.ty_port(result_sub))); + } + case (_) { + ret result; + } + } + } + + case (_) { + ret ures_err(terr_mismatch, expected, actual); + } + } + } + + case (ty.ty_chan(?expected_sub)) { + alt (actual.struct) { + case (ty.ty_chan(?actual_sub)) { + auto result = unify_step(bindings, + expected_sub, + actual_sub, + handler); + alt (result) { + case (ures_ok(?result_sub)) { + ret ures_ok(plain_ty(ty.ty_chan(result_sub))); + } + case (_) { + ret result; + } + } + } + + case (_) { + ret ures_err(terr_mismatch, expected, actual); + } + } + } + case (ty.ty_tup(?expected_elems)) { alt (actual.struct) { case (ty.ty_tup(?actual_elems)) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 7dfe918c065be..6b826f1b21b2f 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -308,6 +308,15 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { case (ast.ty_str) { sty = ty.ty_str; } case (ast.ty_box(?t)) { sty = ty.ty_box(ast_ty_to_ty(getter, t)); } case (ast.ty_vec(?t)) { sty = ty.ty_vec(ast_ty_to_ty(getter, t)); } + + case (ast.ty_port(?t)) { + sty = ty.ty_port(ast_ty_to_ty(getter, t)); + } + + case (ast.ty_chan(?t)) { + sty = ty.ty_chan(ast_ty_to_ty(getter, t)); + } + case (ast.ty_tup(?fields)) { let vec[@ty.t] flds = vec(); for (@ast.ty field in fields) { @@ -1387,6 +1396,28 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, case (ast.expr_put(_)) { e_1 = e.node; } case (ast.expr_be(_)) { e_1 = e.node; } case (ast.expr_check_expr(_)) { e_1 = e.node; } + + case (ast.expr_port(?ann)) { + auto t = demand(fcx, e.span, expected, ann_to_type(ann)); + e_1 = ast.expr_port(ast.ann_type(t, none[vec[@ty.t]])); + } + + case (ast.expr_chan(?es, ?ann)) { + auto t = demand(fcx, e.span, expected, ann_to_type(ann)); + let @ast.expr es_1; + alt (t.struct) { + case (ty.ty_chan(?subty)) { + auto pt = plain_ty(ty.ty_port(subty)); + es_1 = demand_expr(fcx, pt, es); + } + case (_) { + log "chan expr doesn't have a chan type!"; + fail; + } + } + e_1 = ast.expr_chan(es_1, ast.ann_type(t, none[vec[@ty.t]])); + } + case (_) { fcx.ccx.sess.unimpl("type unification for expression variant"); fail; @@ -1613,6 +1644,21 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ret tup(f_1, args_1); } + // A generic function for checking assignment expressions + fn check_assignment(&@fn_ctxt fcx, @ast.expr lhs, @ast.expr rhs) + -> tup(@ast.expr, @ast.expr, ast.ann) { + auto lhs_0 = check_expr(fcx, lhs); + auto rhs_0 = check_expr(fcx, rhs); + auto lhs_t0 = expr_ty(lhs_0); + auto rhs_t0 = expr_ty(rhs_0); + + auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0); + auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0); + + auto ann = ast.ann_type(rhs_t0, none[vec[@ty.t]]); + ret tup(lhs_1, rhs_1, ann); + } + alt (expr.node) { case (ast.expr_lit(?lit, _)) { auto typ = check_lit(lit); @@ -1767,32 +1813,66 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (ast.expr_assign(?lhs, ?rhs, _)) { + auto checked = check_assignment(fcx, lhs, rhs); + auto newexpr = ast.expr_assign(checked._0, + checked._1, + checked._2); + ret @fold.respan[ast.expr_](expr.span, newexpr); + } + + case (ast.expr_assign_op(?op, ?lhs, ?rhs, _)) { + auto checked = check_assignment(fcx, lhs, rhs); + auto newexpr = ast.expr_assign_op(op, + checked._0, + checked._1, + checked._2); + ret @fold.respan[ast.expr_](expr.span, newexpr); + } + + case (ast.expr_send(?lhs, ?rhs, _)) { auto lhs_0 = check_expr(fcx, lhs); auto rhs_0 = check_expr(fcx, rhs); - auto lhs_t0 = expr_ty(lhs_0); - auto rhs_t0 = expr_ty(rhs_0); - - auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0); - auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0); + auto rhs_t = expr_ty(rhs_0); + + auto chan_t = plain_ty(ty.ty_chan(rhs_t)); + auto lhs_1 = demand_expr(fcx, chan_t, lhs_0); + auto item_t; + alt (expr_ty(lhs_1).struct) { + case (ty.ty_chan(?it)) { + item_t = it; + } + case (_) { + fail; + } + } + auto rhs_1 = demand_expr(fcx, item_t, rhs_0); - auto ann = ast.ann_type(rhs_t0, none[vec[@ty.t]]); - ret @fold.respan[ast.expr_](expr.span, - ast.expr_assign(lhs_1, rhs_1, ann)); + auto ann = ast.ann_type(chan_t, none[vec[@ty.t]]); + auto newexpr = ast.expr_send(lhs_1, rhs_1, ann); + ret @fold.respan[ast.expr_](expr.span, newexpr); } - case (ast.expr_assign_op(?op, ?lhs, ?rhs, _)) { + case (ast.expr_recv(?lhs, ?rhs, _)) { auto lhs_0 = check_expr(fcx, lhs); auto rhs_0 = check_expr(fcx, rhs); - auto lhs_t0 = expr_ty(lhs_0); - auto rhs_t0 = expr_ty(rhs_0); - - auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0); - auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0); + auto lhs_t1 = expr_ty(lhs_0); + + auto port_t = plain_ty(ty.ty_port(lhs_t1)); + auto rhs_1 = demand_expr(fcx, port_t, rhs_0); + auto item_t; + alt (expr_ty(rhs_0).struct) { + case (ty.ty_port(?it)) { + item_t = it; + } + case (_) { + fail; + } + } + auto lhs_1 = demand_expr(fcx, item_t, lhs_0); - auto ann = ast.ann_type(rhs_t0, none[vec[@ty.t]]); - ret @fold.respan[ast.expr_](expr.span, - ast.expr_assign_op(op, lhs_1, rhs_1, - ann)); + auto ann = ast.ann_type(item_t, none[vec[@ty.t]]); + auto newexpr = ast.expr_recv(lhs_1, rhs_1, ann); + ret @fold.respan[ast.expr_](expr.span, newexpr); } case (ast.expr_if(?cond, ?thn, ?elifs, ?elsopt, _)) { @@ -2257,6 +2337,31 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } + case (ast.expr_port(_)) { + auto t = next_ty_var(fcx.ccx); + auto pt = plain_ty(ty.ty_port(t)); + auto ann = ast.ann_type(pt, none[vec[@ty.t]]); + ret @fold.respan[ast.expr_](expr.span, ast.expr_port(ann)); + } + + case (ast.expr_chan(?x, _)) { + auto expr_1 = check_expr(fcx, x); + auto port_t = expr_ty(expr_1); + alt (port_t.struct) { + case (ty.ty_port(?subtype)) { + auto ct = plain_ty(ty.ty_chan(subtype)); + auto ann = ast.ann_type(ct, none[vec[@ty.t]]); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_chan(expr_1, ann)); + } + case (_) { + fcx.ccx.sess.span_err(expr.span, + "bad port type: " + + ty_to_str(port_t)); + } + } + } + case (_) { fcx.ccx.sess.unimpl("expr type in typeck.check_expr"); // TODO