Add folding and type checking for ports and chans
This commit is contained in:
parent
a3cca65f6d
commit
7464237256
@ -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;
|
||||
|
@ -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](_,_,_),
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user