Add folding and type checking for ports and chans

This commit is contained in:
Brian Anderson 2011-03-10 22:58:55 -05:00 committed by Graydon Hoare
parent a3cca65f6d
commit 7464237256
4 changed files with 165 additions and 2 deletions

View File

@ -278,12 +278,12 @@ 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
ty_obj(vec[ty_method]);
ty_chan(@ty);
ty_port(@ty);
ty_path(path, option.t[def]);
ty_mutable(@ty);
ty_type;

View File

@ -179,6 +179,18 @@ 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,
(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,
// Decl folds.
(fn(&ENV e, &span sp,
@ast.local local) -> @decl) fold_decl_local,
@ -717,6 +729,26 @@ 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);
}
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);
}
}
fail;
@ -1255,6 +1287,23 @@ 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));
}
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));
}
// Decl identities.
@ -1527,6 +1576,10 @@ 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_expr_send = bind identity_fold_expr_send[ENV](_,_,_,_,_),
fold_expr_recv = bind identity_fold_expr_recv[ENV](_,_,_,_,_),
fold_decl_local = bind identity_fold_decl_local[ENV](_,_,_),
fold_decl_item = bind identity_fold_decl_item[ENV](_,_,_),

View File

@ -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
@ -240,6 +242,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 +1167,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)) {

View File

@ -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;
@ -2257,6 +2288,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