about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2011-03-10 22:58:55 -0500
committerGraydon Hoare <graydon@mozilla.com>2011-03-14 16:41:46 -0700
commit7464237256990c4a346cbaaa7ce3d2d9e8fe8d5c (patch)
treea15721e61a7ba9fa223bed4ff0cb2a17cb8640f5 /src/comp
parenta3cca65f6d77d9d7d27b3ace84da4730030ffd59 (diff)
Add folding and type checking for ports and chans
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/front/ast.rs4
-rw-r--r--src/comp/middle/fold.rs53
-rw-r--r--src/comp/middle/ty.rs54
-rw-r--r--src/comp/middle/typeck.rs56
4 files changed, 165 insertions, 2 deletions
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index edc9c4a25c0..d768f93552a 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -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;
diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs
index bb2af12194e..320033cdc8c 100644
--- a/src/comp/middle/fold.rs
+++ b/src/comp/middle/fold.rs
@@ -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](_,_,_),
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index bd3e3263820..73b519ba3dd 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
@@ -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)) {
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 7dfe918c065..78524c2d4b2 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;
@@ -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