about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-06-24 18:10:40 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-06-25 21:15:11 +0200
commit61fc12d0d0d1b8acb7472bfc6223882b32acd3d2 (patch)
treef608c6036509602785bf35a7f879bf15560d4d1b /src/comp/middle
parent781a265b88f7fc3c8c406b327e8a548e742d6224 (diff)
Partial implementation of resources
Non-copyability is not enforced yet, and something is still flaky with
dropping of the internal value, so don't actually use them yet. I'm
merging this in so that I don't have to keep merging against new
patches.
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/metadata.rs35
-rw-r--r--src/comp/middle/resolve.rs15
-rw-r--r--src/comp/middle/trans.rs50
-rw-r--r--src/comp/middle/tstate/pre_post_conditions.rs9
-rw-r--r--src/comp/middle/ty.rs24
-rw-r--r--src/comp/middle/typeck.rs25
-rw-r--r--src/comp/middle/visit.rs3
-rw-r--r--src/comp/middle/walk.rs3
8 files changed, 152 insertions, 12 deletions
diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs
index b9f4ed5c2fb..ae59a208fa3 100644
--- a/src/comp/middle/metadata.rs
+++ b/src/comp/middle/metadata.rs
@@ -231,6 +231,12 @@ mod encode {
                 }
                 w.write_char(']');
             }
+            case (ty::ty_res(?def, ?ty)) {
+                w.write_char('r');
+                w.write_str(cx.ds(def));
+                w.write_char('|');
+                enc_ty(w, cx, ty);
+            }
             case (ty::ty_var(?id)) {
                 w.write_char('X');
                 w.write_str(common::istr(id));
@@ -393,6 +399,18 @@ fn encode_module_item_paths(&ebml::writer ebml_w, &_mod module,
                 encode_def_id(ebml_w, local_def(it.id));
                 ebml::end_tag(ebml_w);
             }
+            case (item_res(_, _, ?tps, ?ctor_id)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(ctor_id));
+                ebml::end_tag(ebml_w);
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                ebml::end_tag(ebml_w);
+            }
             case (item_tag(?variants, ?tps)) {
                 add_to_index(ebml_w, path, index, it.ident);
                 ebml::start_tag(ebml_w, tag_paths_data_item);
@@ -553,6 +571,23 @@ fn encode_info_for_item(@trans::crate_ctxt cx, &ebml::writer ebml_w,
             encode_tag_variant_info(cx, ebml_w, item.id, variants, index,
                                     tps);
         }
+        case (item_res(_, _, ?tps, ?ctor_id)) {
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(ctor_id));
+            encode_kind(ebml_w, 'f' as u8);
+            encode_type_param_count(ebml_w, tps);
+            auto fn_ty = trans::node_id_type(cx, item.id);
+            encode_type(cx, ebml_w, fn_ty);
+            encode_symbol(cx, ebml_w, ctor_id);
+            ebml::end_tag(ebml_w);
+            index += [tup(item.id, ebml_w.writer.tell())];
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 'y' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty));
+            ebml::end_tag(ebml_w);
+        }
         case (item_obj(_, ?tps, ?ctor_id)) {
             ebml::start_tag(ebml_w, tag_items_data_item);
             encode_def_id(ebml_w, local_def(ctor_id));
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 3ecb81267c1..b9f6c604996 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -819,6 +819,14 @@ fn found_def_item(&@ast::item i, namespace ns) -> option::t[def] {
                 ret some(ast::def_ty(local_def(i.id)));
             }
         }
+        case (ast::item_res(_, _, _, ?ctor_id)) {
+            alt (ns) {
+                case (ns_value) { ret some(ast::def_fn(local_def(ctor_id),
+                                                       ast::impure_fn)); }
+                case (ns_type) { ret some(ast::def_ty(local_def(i.id))); }
+                case (_) { }
+            }
+        }
         case (ast::item_tag(_, _)) {
             if (ns == ns_type) {
                 ret some(ast::def_ty(local_def(i.id)));
@@ -1085,6 +1093,9 @@ fn index_mod(&ast::_mod md) -> mod_index {
             case (ast::item_ty(_, _)) {
                 add_to_index(index, it.ident, mie_item(it));
             }
+            case (ast::item_res(_, _, _, _)) {
+                add_to_index(index, it.ident, mie_item(it));
+            }
             case (ast::item_tag(?variants, _)) {
                 add_to_index(index, it.ident, mie_item(it));
                 let uint variant_idx = 0u;
@@ -1282,6 +1293,10 @@ fn check_block(@env e, &ast::block b, &() x, &vt[()] v) {
                             case (ast::item_ty(_, _)) {
                                 add_name(types, it.span, it.ident);
                             }
+                            case (ast::item_res(_, _, _, _)) {
+                                add_name(types, it.span, it.ident);
+                                add_name(values, it.span, it.ident);
+                            }
                             case (ast::item_obj(_, _, _)) {
                                 add_name(types, it.span, it.ident);
                                 add_name(values, it.span, it.ident);
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 59f7dd84073..3a67296e86d 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -881,6 +881,9 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
             abs_pair = llvm::LLVMResolveTypeHandle(th.llth);
             llty = abs_pair;
         }
+        case (ty::ty_res(_, ?sub)) {
+            ret type_of_inner(cx, sp, sub);
+        }
         case (ty::ty_var(_)) {
             cx.tcx.sess.span_fatal(sp, "trans::type_of called on ty_var");
         }
@@ -1217,6 +1220,7 @@ fn simplify_type(&@crate_ctxt ccx, &ty::t typ) -> ty::t {
                                     ty::mk_imm_box(ccx.tcx,
                                                    ty::mk_nil(ccx.tcx))]);
             }
+            case (ty::ty_res(_, ?sub)) { ret simplify_type(ccx, sub);}
             case (_) { ret typ; }
         }
     }
@@ -2064,7 +2068,7 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
         case (ty::ty_vec(_)) { decr_refcnt_maybe_free(cx, v0, v0, t) }
         case (ty::ty_ivec(?tm)) {
             auto v1;
-            if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, tm.ty)) {
+            if (ty::type_has_dynamic_size(ccx.tcx, tm.ty)) {
                 v1 = cx.build.PointerCast(v0, T_ptr(T_opaque_ivec()));
             } else {
                 v1 = v0;
@@ -2082,6 +2086,18 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
                 cx.build.GEP(v0, [C_int(0), C_int(abi::obj_field_box)]);
             decr_refcnt_maybe_free(cx, box_cell, v0, t)
         }
+        case (ty::ty_res(?did, ?inner)) {
+            auto dtor = alt (ccx.ast_map.get(did._1)) {
+                case (ast_map::node_item(?i)) {
+                    alt (i.node) {
+                        case (ast::item_res(?dtor, _, _, _)) { dtor }
+                    }
+                }
+            };
+            cx.fcx.llargs.insert(dtor.decl.inputs.(0).id, v0);
+            auto rs = trans_block(cx, dtor.body, return);
+            drop_ty(rs.bcx, v0, inner)
+        }
         case (ty::ty_fn(_, _, _, _, _)) {
             auto box_cell =
                 cx.build.GEP(v0, [C_int(0), C_int(abi::fn_field_box)]);
@@ -2549,6 +2565,10 @@ fn iter_structural_ty_full(&@block_ctxt cx, ValueRef av, ValueRef bv,
                 i += 1;
             }
         }
+        case (ty::ty_res(_, ?inner)) {
+            f(r.bcx, load_if_immediate(r.bcx, av, inner),
+              load_if_immediate(r.bcx, bv, inner), inner);
+        }
         case (ty::ty_tag(?tid, ?tps)) {
             auto variants = ty::tag_variants(cx.fcx.lcx.ccx.tcx, tid);
             auto n_variants = vec::len[ty::variant_info](variants);
@@ -4633,12 +4653,10 @@ fn lval_generic_fn(&@block_ctxt cx, &ty::ty_param_count_and_ty tpt,
     auto lv;
     if (cx.fcx.lcx.ccx.sess.get_targ_crate_num() == fn_id._0) {
         // Internal reference.
-
         assert (cx.fcx.lcx.ccx.fn_pairs.contains_key(fn_id._1));
         lv = lval_val(cx, cx.fcx.lcx.ccx.fn_pairs.get(fn_id._1));
     } else {
         // External reference.
-
         lv = trans_external_path(cx, fn_id, tpt);
     }
     auto tys = ty::node_id_to_type_params(cx.fcx.lcx.ccx.tcx, id);
@@ -7621,6 +7639,26 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
     finish_fn(fcx, lltop);
 }
 
+fn trans_res(@local_ctxt cx, &span sp, &ast::_fn f, ast::node_id ctor_id,
+             &vec[ast::ty_param] ty_params) {
+    auto llctor_decl = cx.ccx.item_ids.get(ctor_id);
+    auto fcx = new_fn_ctxt(cx, sp, llctor_decl);
+    auto ret_ty = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
+    create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty_self_pair],
+                              ret_ty, f.decl.inputs, ty_params);
+    auto bcx = new_top_block_ctxt(fcx);
+    auto lltop = bcx.llbb;
+    auto self_ty = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
+    auto llself_ty = type_of(cx.ccx, sp, self_ty);
+    auto arg_ty = arg_tys_of_fn(cx.ccx, ctor_id).(0).ty;
+    auto arg = load_if_immediate
+        (bcx, fcx.llargs.get(f.decl.inputs.(0).id), arg_ty);
+    bcx = copy_val(bcx, INIT, fcx.llretptr, arg, arg_ty).bcx;
+    bcx.build.RetVoid();
+    finish_fn(fcx, lltop);
+}
+
+
 fn trans_tag_variant(@local_ctxt cx, ast::node_id tag_id,
                      &ast::variant variant, int index,
                      &vec[ast::ty_param] ty_params) {
@@ -7729,6 +7767,9 @@ fn trans_item(@local_ctxt cx, &ast::item item) {
                      with *extend_path(cx, item.ident));
             trans_obj(sub_cx, item.span, ob, ctor_id, tps);
         }
+        case (ast::item_res(?decl, _, ?tps, ?ctor_id)) {
+            trans_res(cx, item.span, decl, ctor_id, tps);
+        }
         case (ast::item_mod(?m)) {
             auto sub_cx =
                 @rec(path=cx.path + [item.ident],
@@ -8062,6 +8103,9 @@ fn collect_item_2(&@crate_ctxt ccx, &@ast::item i, &vec[str] pt,
                 ccx.obj_methods.insert(m.node.id, ());
             }
         }
+        case (ast::item_res(?decl, _, ?tps, ?ctor_id)) {
+            decl_fn_and_pair(ccx, i.span, new_pt, "res_ctor", tps, ctor_id);
+        }
         case (_) { }
     }
 }
diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs
index 4455f09bdc2..e5eaadbb283 100644
--- a/src/comp/middle/tstate/pre_post_conditions.rs
+++ b/src/comp/middle/tstate/pre_post_conditions.rs
@@ -119,7 +119,7 @@ fn find_pre_post_item(&crate_ctxt ccx, &item i) {
                     ccx=ccx);
             find_pre_post_expr(fake_fcx, e);
         }
-        case (item_fn(?f, ?ps)) {
+        case (item_fn(?f, _)) {
             assert (ccx.fm.contains_key(i.id));
             auto fcx =
                 rec(enclosing=ccx.fm.get(i.id),
@@ -132,6 +132,13 @@ fn find_pre_post_item(&crate_ctxt ccx, &item i) {
         case (item_native_mod(?nm)) { find_pre_post_native_mod(nm); }
         case (item_ty(_, _)) { ret; }
         case (item_tag(_, _)) { ret; }
+        case (item_res(?dtor, ?dtor_id, _, _)) {
+            auto fcx = rec(enclosing=ccx.fm.get(dtor_id),
+                           id=dtor_id,
+                           name=i.ident,
+                           ccx=ccx);
+            find_pre_post_fn(fcx, dtor);
+        }
         case (item_obj(?o, _, _)) { find_pre_post_obj(ccx, o); }
     }
 }
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index de36d441838..0d5948eed6a 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -78,6 +78,7 @@ export mk_native;
 export mk_native_fn;
 export mk_nil;
 export mk_obj;
+export mk_res;
 export mk_param;
 export mk_port;
 export mk_ptr;
@@ -134,6 +135,7 @@ export ty_machine;
 export ty_native;
 export ty_nil;
 export ty_obj;
+export ty_res;
 export ty_param;
 export ty_port;
 export ty_ptr;
@@ -263,14 +265,12 @@ tag sty {
     ty_fn(ast::proto, vec[arg], t, controlflow, vec[@constr_def]);
     ty_native_fn(ast::native_abi, vec[arg], t);
     ty_obj(vec[method]);
+    ty_res(def_id, t);
     ty_var(int); // type variable
-
     ty_param(uint); // fn/tag type param
-
     ty_type;
     ty_native;
     // TODO: ty_fn_arg(t), for a possibly-aliased function argument
-
 }
 
 type constr_def = spanned[constr_general[uint]];
@@ -492,6 +492,7 @@ fn mk_raw_ty(&ctxt cx, &sty st, &option::t[str] cname) -> raw_t {
                                  m.output);
             }
         }
+        case (ty_res(_, ?tt)) { derive_flags_t(cx, has_params, has_vars, tt);}
     }
     ret rec(struct=st,
             cname=cname,
@@ -598,6 +599,10 @@ fn mk_obj(&ctxt cx, &vec[method] meths) -> t {
     ret gen_ty(cx, ty_obj(meths));
 }
 
+fn mk_res(&ctxt cx, &ast::def_id did, &t inner) -> t {
+    ret gen_ty(cx, ty_res(did, inner));
+}
+
 fn mk_var(&ctxt cx, int v) -> t { ret gen_ty(cx, ty_var(v)); }
 
 fn mk_param(&ctxt cx, uint n) -> t { ret gen_ty(cx, ty_param(n)); }
@@ -679,6 +684,7 @@ fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
                 walk_ty(cx, walker, m.output);
             }
         }
+        case (ty_res(_, ?sub)) { walk_ty(cx, walker, sub); }
         case (ty_var(_)) {/* no-op */ }
         case (ty_param(_)) {/* no-op */ }
     }
@@ -811,6 +817,9 @@ fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
             }
             ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
         }
+        case (ty_res(?did, ?subty)) {
+            ty = copy_cname(cx, mk_res(cx, did, fold_ty(cx, fld, subty)), ty);
+        }
         case (ty_var(?id)) {
             alt (fld) {
                 case (fm_var(?folder)) { ty = folder(id); }
@@ -880,6 +889,7 @@ fn type_is_structural(&ctxt cx, &t ty) -> bool {
         case (ty_tag(_, _)) { ret true; }
         case (ty_fn(_, _, _, _, _)) { ret true; }
         case (ty_obj(_)) { ret true; }
+        case (ty_res(_, _)) { ret true; }
         case (ty_ivec(_)) { ret true; }
         case (ty_istr) { ret true; }
         case (_) { ret false; }
@@ -1091,6 +1101,7 @@ fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
         case (ty_fn(_,_,_,_,_)) { ret false; }
         case (ty_native_fn(_,_,_)) { ret false; }
         case (ty_obj(_)) { ret false; }
+        case (ty_res(_, ?sub)) { ret type_has_dynamic_size(cx, sub); }
         case (ty_var(_)) { fail "ty_var in type_has_dynamic_size()"; }
         case (ty_param(_)) { ret true; }
         case (ty_type) { ret false; }
@@ -1196,6 +1207,7 @@ fn type_owns_heap_mem(&ctxt cx, &t ty) -> bool {
                 if (type_owns_heap_mem(cx, f.mt.ty)) { result = true; }
             }
         }
+        case (ty_res(_, ?inner)) { result = type_owns_heap_mem(cx, inner); }
 
         case (ty_ptr(_)) { result = false; }
         case (ty_port(_)) { result = false; }
@@ -1289,9 +1301,8 @@ fn hash_type_structure(&sty st) -> uint {
             for (field f in fields) { h += h << 5u + hash_ty(f.mt.ty); }
             ret h;
         }
-        case (
-             // ???
-             ty_fn(_, ?args, ?rty, _, _)) {
+        // ???
+        case (ty_fn(_, ?args, ?rty, _, _)) {
             ret hash_fn(27u, args, rty);
         }
         case (ty_native_fn(_, ?args, ?rty)) { ret hash_fn(28u, args, rty); }
@@ -1306,6 +1317,7 @@ fn hash_type_structure(&sty st) -> uint {
         case (ty_native) { ret 33u; }
         case (ty_bot) { ret 34u; }
         case (ty_ptr(?mt)) { ret hash_subty(35u, mt.ty); }
+        case (ty_res(?did, ?sub)) { ret hash_subty(hash_def(18u, did), sub); }
     }
 }
 
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 353eb3997df..4ad7400dc99 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -526,8 +526,7 @@ mod collect {
         auto methods = get_obj_method_types(cx, obj_info);
         auto t_obj = ty::mk_obj(cx.tcx, ty::sort_methods(methods));
         t_obj = ty::rename(cx.tcx, t_obj, id);
-        auto ty_param_count = vec::len[ast::ty_param](ty_params);
-        ret tup(ty_param_count, t_obj);
+        ret tup(vec::len(ty_params), t_obj);
     }
     fn ty_of_obj_ctor(@ctxt cx, &ast::ident id, &ast::_obj obj_info,
                       ast::node_id ctor_id, &vec[ast::ty_param] ty_params) ->
@@ -579,6 +578,13 @@ mod collect {
                 cx.tcx.tcache.insert(local_def(it.id), tpt);
                 ret tpt;
             }
+            case (ast::item_res(?f, _, ?tps, _)) {
+                auto t_arg = ty_of_arg(cx, f.decl.inputs.(0));
+                auto t_res = tup(vec::len(tps), ty::mk_res
+                                 (cx.tcx, local_def(it.id), t_arg.ty));
+                cx.tcx.tcache.insert(local_def(it.id), t_res);
+                ret t_res;
+            }
             case (ast::item_tag(_, ?tps)) {
                 // Create a new generic polytype.
 
@@ -729,6 +735,18 @@ mod collect {
                     }
                 }
             }
+            case (ast::item_res(?f, ?dtor_id, ?tps, ?ctor_id)) {
+                auto t_arg = ty_of_arg(cx, f.decl.inputs.(0));
+                auto t_res = ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty);
+                auto t_ctor = ty::mk_fn(cx.tcx, ast::proto_fn, [t_arg],
+                                        t_res, ast::return, []);
+                auto t_dtor = ty::mk_fn(cx.tcx, ast::proto_fn, [t_arg],
+                                        ty::mk_nil(cx.tcx), ast::return, []);
+                write::ty_only(cx.tcx, ctor_id, t_ctor);
+                cx.tcx.tcache.insert(local_def(ctor_id),
+                                     tup(vec::len(tps), t_ctor));
+                write::ty_only(cx.tcx, dtor_id, t_dtor);
+            }
             case (_) {
                 // This call populates the type cache with the converted type
                 // of the item in passing. All we have to do here is to write
@@ -2337,6 +2355,9 @@ fn check_item(@crate_ctxt ccx, &@ast::item it) {
         case (ast::item_fn(?f, _)) {
             check_fn(ccx, f.decl, f.proto, f.body, it.id);
         }
+        case (ast::item_res(?f, ?dtor_id, _, _)) {
+            check_fn(ccx, f.decl, f.proto, f.body, dtor_id);
+        }
         case (ast::item_obj(?ob, _, _)) {
             // We're entering an object, so gather up the info we need.
 
diff --git a/src/comp/middle/visit.rs b/src/comp/middle/visit.rs
index 48abf3f7a80..53efe81c4a2 100644
--- a/src/comp/middle/visit.rs
+++ b/src/comp/middle/visit.rs
@@ -115,6 +115,9 @@ fn visit_item[E](&@item i, &E e, &vt[E] v) {
             }
         }
         case (item_ty(?t, _)) { vt(v).visit_ty(t, e, v); }
+        case (item_res(?f, ?dtor_id, ?tps, _)) {
+            vt(v).visit_fn(f, tps, i.span, i.ident, dtor_id, e, v);
+        }
         case (item_tag(?variants, _)) {
             for (variant vr in variants) {
                 for (variant_arg va in vr.node.args) {
diff --git a/src/comp/middle/walk.rs b/src/comp/middle/walk.rs
index d2e9343a33d..821a00ad450 100644
--- a/src/comp/middle/walk.rs
+++ b/src/comp/middle/walk.rs
@@ -105,6 +105,9 @@ fn walk_item(&ast_visitor v, @ast::item i) {
         case (ast::item_mod(?m)) { walk_mod(v, m); }
         case (ast::item_native_mod(?nm)) { walk_native_mod(v, nm); }
         case (ast::item_ty(?t, _)) { walk_ty(v, t); }
+        case (ast::item_res(?f, ?dtor_id, _, _)) {
+            walk_fn(v, f, i.span, some(i.ident), dtor_id);
+        }
         case (ast::item_tag(?variants, _)) {
             for (ast::variant vr in variants) {
                 for (ast::variant_arg va in vr.node.args) {