about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-05-13 15:17:24 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-05-13 17:20:39 +0200
commiteb419fd8c78f907f1a5cd20f5e71009ba37ef7e9 (patch)
tree924709adb23c244bb06f23bde47dff88b48eb20e
parent1a12a7b04b5c279b897dda998e946085883d9cf9 (diff)
Extend crate format to allow multiple definitions for a single name
The type/value namespace distinction pretty much works now. Module
namespace is up next.
-rw-r--r--src/comp/front/creader.rs133
-rw-r--r--src/comp/middle/metadata.rs16
-rw-r--r--src/comp/middle/resolve.rs48
-rw-r--r--src/comp/middle/ty.rs1
4 files changed, 85 insertions, 113 deletions
diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs
index 03b5cb1ee32..023ede50865 100644
--- a/src/comp/front/creader.rs
+++ b/src/comp/front/creader.rs
@@ -34,11 +34,6 @@ type env = @rec(
     mutable int next_crate_num
 );
 
-tag resolve_result {
-    rr_ok(ast::def_id);
-    rr_not_found(ast::ident);
-}
-
 // Type decoding
 
 // Compact string representation for ty::t values. API ty_str & parse_from_str
@@ -282,7 +277,7 @@ fn parse_def_id(vec[u8] buf) -> ast::def_id {
 }
 
 fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash)
-    -> option::t[ebml::doc] {
+    -> vec[ebml::doc] {
     auto index = ebml::get_doc(d, metadata::tag_index);
     auto table = ebml::get_doc(index, metadata::tag_index_table);
 
@@ -290,18 +285,12 @@ fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash)
     auto pos = ebml::be_uint_from_bytes(d.data, hash_pos, 4u);
     auto bucket = ebml::doc_at(d.data, pos);
     // Awkward logic because we can't ret from foreach yet
-    auto result = option::none[ebml::doc];
+    let vec[ebml::doc] result = vec();
     auto belt = metadata::tag_index_buckets_bucket_elt;
     for each (ebml::doc elt in ebml::tagged_docs(bucket, belt)) {
-        alt (result) {
-            case (option::none[ebml::doc]) {
-                auto pos = ebml::be_uint_from_bytes(elt.data, elt.start, 4u);
-                if (eq_fn(_vec::slice[u8](elt.data, elt.start+4u, elt.end))) {
-                    result = option::some[ebml::doc]
-                        (ebml::doc_at(d.data, pos));
-                }
-            }
-            case (_) {}
+        auto pos = ebml::be_uint_from_bytes(elt.data, elt.start, 4u);
+        if (eq_fn(_vec::slice[u8](elt.data, elt.start+4u, elt.end))) {
+            _vec::push(result, ebml::doc_at(d.data, pos));
         }
     }
     ret result;
@@ -309,7 +298,7 @@ fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash)
 
 // Given a path and serialized crate metadata, returns the ID of the
 // definition the path refers to.
-fn resolve_path(vec[ast::ident] path, vec[u8] data) -> resolve_result {
+fn resolve_path(vec[ast::ident] path, vec[u8] data) -> vec[ast::def_id] {
     fn eq_item(vec[u8] data, str s) -> bool {
         ret _str::eq(_str::unsafe_from_bytes(data), s);
     }
@@ -317,15 +306,12 @@ fn resolve_path(vec[ast::ident] path, vec[u8] data) -> resolve_result {
     auto md = ebml::new_doc(data);
     auto paths = ebml::get_doc(md, metadata::tag_paths);
     auto eqer = bind eq_item(_, s);
-    alt (lookup_hash(paths, eqer, metadata::hash_path(s))) {
-        case (option::some[ebml::doc](?d)) {
-            auto did_doc = ebml::get_doc(d, metadata::tag_def_id);
-            ret rr_ok(parse_def_id(ebml::doc_data(did_doc)));
-        }
-        case (option::none[ebml::doc]) {
-            ret rr_not_found(s);
-        }
+    let vec[ast::def_id] result = vec();
+    for (ebml::doc doc in lookup_hash(paths, eqer, metadata::hash_path(s))) {
+        auto did_doc = ebml::get_doc(doc, metadata::tag_def_id);
+        _vec::push(result, parse_def_id(ebml::doc_data(did_doc)));
     }
+    ret result;
 }
 
 fn maybe_find_item(int item_id, &ebml::doc items) -> option::t[ebml::doc] {
@@ -333,13 +319,16 @@ fn maybe_find_item(int item_id, &ebml::doc items) -> option::t[ebml::doc] {
         ret ebml::be_uint_from_bytes(bytes, 0u, 4u) as int == item_id;
     }
     auto eqer = bind eq_item(_, item_id);
-    ret lookup_hash(items, eqer, metadata::hash_def_num(item_id));
+    auto found = lookup_hash(items, eqer, metadata::hash_def_num(item_id));
+    if (_vec::len(found) == 0u) {
+        ret option::none[ebml::doc];
+    } else {
+        ret option::some[ebml::doc](found.(0));
+    }
 }
 
 fn find_item(int item_id, &ebml::doc items) -> ebml::doc {
-    alt (maybe_find_item(item_id, items)) {
-        case (option::some[ebml::doc](?d)) {ret d;}
-    }
+    ret option::get(maybe_find_item(item_id, items));
 }
 
 // Looks up an item in the given metadata and returns an ebml doc pointing
@@ -478,67 +467,49 @@ fn read_crates(session::session sess,
 
 
 fn kind_has_type_params(u8 kind_ch) -> bool {
-    // FIXME: It'd be great if we had u8 char literals.
-    if (kind_ch == ('c' as u8))      { ret false; }
-    else if (kind_ch == ('f' as u8)) { ret true;  }
-    else if (kind_ch == ('F' as u8)) { ret true;  }
-    else if (kind_ch == ('y' as u8)) { ret true;  }
-    else if (kind_ch == ('o' as u8)) { ret true;  }
-    else if (kind_ch == ('t' as u8)) { ret true;  }
-    else if (kind_ch == ('T' as u8)) { ret false;  }
-    else if (kind_ch == ('m' as u8)) { ret false; }
-    else if (kind_ch == ('n' as u8)) { ret false; }
-    else if (kind_ch == ('v' as u8)) { ret true;  }
-    else {
-        log_err #fmt("kind_has_type_params(): unknown kind char: %d",
-                     kind_ch as int);
-        fail;
-    }
+    ret alt (kind_ch as char) {
+        case ('c') { false } case ('f') { true  } case ('F') { true  }
+        case ('y') { true  } case ('o') { true  } case ('t') { true  }
+        case ('T') { false } case ('m') { false } case ('n') { false }
+        case ('v') { true  }
+    };
 }
 
-
 // Crate metadata queries
 
-fn lookup_def(session::session sess, int cnum, vec[ast::ident] path)
-        -> option::t[ast::def] {
+fn lookup_defs(session::session sess, int cnum, vec[ast::ident] path)
+    -> vec[ast::def] {
     auto data = sess.get_external_crate(cnum).data;
 
-    auto did;
-    alt (resolve_path(path, data)) {
-        case (rr_ok(?di)) { did = di; }
-        case (rr_not_found(?name)) {
-            ret none[ast::def];
-        }
-    }
+    ret _vec::map(bind lookup_def(cnum, data, _),
+                  resolve_path(path, data));
+}
 
+// FIXME doesn't yet handle re-exported externals
+fn lookup_def(int cnum, vec[u8] data, &ast::def_id did) -> ast::def {
     auto item = lookup_item(did._1, data);
     auto kind_ch = item_kind(item);
 
     did = tup(cnum, did._1);
 
-    // FIXME: It'd be great if we had u8 char literals.
-    auto def;
-    if (kind_ch == ('c' as u8))         { def = ast::def_const(did);      }
-    else if (kind_ch == ('f' as u8))    { def = ast::def_fn(did);         }
-    else if (kind_ch == ('F' as u8))    { def = ast::def_native_fn(did);  }
-    else if (kind_ch == ('y' as u8))    { def = ast::def_ty(did);         }
-    else if (kind_ch == ('o' as u8))    { def = ast::def_obj(did);        }
-    else if (kind_ch == ('T' as u8))    { def = ast::def_native_ty(did);  }
-    else if (kind_ch == ('t' as u8)) {
+    auto def = alt (kind_ch as char) {
+        case ('c') { ast::def_const(did) }
+        case ('f') { ast::def_fn(did) }
+        case ('F') { ast::def_native_fn(did) }
+        case ('y') { ast::def_ty(did) }
+        case ('o') { ast::def_obj(did) }
+        case ('T') { ast::def_native_ty(did) }
         // We treat references to tags as references to types.
-        def = ast::def_ty(did);
-    } else if (kind_ch == ('m' as u8))  { def = ast::def_mod(did);        }
-    else if (kind_ch == ('n' as u8))    { def = ast::def_native_mod(did); }
-    else if (kind_ch == ('v' as u8)) {
-        auto tid = variant_tag_id(item);
-        tid = tup(cnum, tid._1);
-        def = ast::def_variant(tid, did);
-    } else {
-        log_err #fmt("lookup_def(): unknown kind char: %d", kind_ch as int);
-        fail;
-    }
-
-    ret some[ast::def](def);
+        case ('t') { ast::def_ty(did) }
+        case ('m') { ast::def_mod(did) }
+        case ('n') { ast::def_native_mod(did) }
+        case ('v') {
+            auto tid = variant_tag_id(item);
+            tid = tup(cnum, tid._1);
+            ast::def_variant(tid, did)
+        }
+    };
+    ret def;
 }
 
 fn get_type(session::session sess, ty::ctxt tcx, ast::def_id def)
@@ -563,8 +534,7 @@ fn get_type(session::session sess, ty::ctxt tcx, ast::def_id def)
 fn get_symbol(session::session sess, ast::def_id def) -> str {
     auto external_crate_id = def._0;
     auto data = sess.get_external_crate(external_crate_id).data;
-    auto item = lookup_item(def._1, data);
-    ret item_symbol(item);
+    ret item_symbol(lookup_item(def._1, data));
 }
 
 fn get_tag_variants(session::session sess, ty::ctxt tcx, ast::def_id def)
@@ -636,9 +606,8 @@ fn list_crate_metadata(vec[u8] bytes, io::writer out) {
 }
 
 fn describe_def(&ebml::doc items, ast::def_id id) -> str {
-    if (id._0 != 0) {ret "external";}
-    auto item = find_item(id._1, items);
-    ret item_kind_to_str(item_kind(item));
+    if (id._0 != 0) { ret "external"; }
+    ret item_kind_to_str(item_kind(find_item(id._1, items)));
 }
 
 fn item_kind_to_str(u8 kind) -> str {
diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs
index e10f2e7319e..b307842412d 100644
--- a/src/comp/middle/metadata.rs
+++ b/src/comp/middle/metadata.rs
@@ -37,7 +37,6 @@ const uint tag_items_data_item_type = 0x0cu;
 const uint tag_items_data_item_symbol = 0x0du;
 const uint tag_items_data_item_variant = 0x0eu;
 const uint tag_items_data_item_tag_id = 0x0fu;
-const uint tag_items_data_item_obj_type_id = 0x10u;
 
 const uint tag_index = 0x11u;
 const uint tag_index_buckets = 0x12u;
@@ -165,7 +164,7 @@ mod Encode {
             }
             case (ty::ty_char) {w.write_char('c');}
             case (ty::ty_str) {w.write_char('s');}
-            case (ty::ty_tag(?def,?tys)) { // TODO restore def_id
+            case (ty::ty_tag(?def,?tys)) {
                 w.write_str("t[");
                 w.write_str(cx.ds(def));
                 w.write_char('|');
@@ -387,7 +386,12 @@ fn encode_module_item_paths(&ebml::writer ebml_w,
                 ebml::start_tag(ebml_w, tag_paths_data_item);
                 encode_name(ebml_w, id);
                 encode_def_id(ebml_w, odid.ctor);
-                encode_obj_type_id(ebml_w, odid.ty);
+                ebml::end_tag(ebml_w);
+
+                add_to_index(ebml_w, path, index, id);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, id);
+                encode_def_id(ebml_w, odid.ty);
                 ebml::end_tag(ebml_w);
             }
         }
@@ -459,11 +463,6 @@ fn encode_tag_id(&ebml::writer ebml_w, &ast::def_id id) {
     ebml::end_tag(ebml_w);
 }
 
-fn encode_obj_type_id(&ebml::writer ebml_w, &ast::def_id id) {
-    ebml::start_tag(ebml_w, tag_items_data_item_obj_type_id);
-    ebml_w.writer.write(_str::bytes(def_to_str(id)));
-    ebml::end_tag(ebml_w);
-}
 
 
 fn encode_tag_variant_info(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
@@ -550,6 +549,7 @@ fn encode_info_for_item(@trans::crate_ctxt cx, &ebml::writer ebml_w,
             encode_symbol(cx, ebml_w, odid.ctor);
             ebml::end_tag(ebml_w);
 
+            index += vec(tup(odid.ty._1, ebml_w.writer.tell()));
             ebml::start_tag(ebml_w, tag_items_data_item);
             encode_def_id(ebml_w, odid.ty);
             encode_kind(ebml_w, 'y' as u8);
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 93ce248ba4c..ad1a5fe926a 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -47,16 +47,22 @@ tag import_state {
     resolved(option::t[def] /* value */, option::t[def] /* type */);
 }
 
-type ext_hash = hashmap[tup(def_id,str),def];
+type ext_hash = hashmap[tup(def_id,str,namespace),def];
 fn new_ext_hash() -> ext_hash {
-    fn hash(&tup(def_id,str) v) -> uint {
-        ret _str::hash(v._1) + util::common::hash_def(v._0);
-    }
-    fn eq(&tup(def_id,str) v1, &tup(def_id,str) v2) -> bool {
+    fn hash(&tup(def_id,str,namespace) v) -> uint {
+        ret _str::hash(v._1) + util::common::hash_def(v._0) + (alt (v._2) {
+            case (ns_value) { 1u }
+            case (ns_type) { 2u }
+            case (ns_module) { 3u }
+        });
+    }
+    fn eq(&tup(def_id,str,namespace) v1,
+          &tup(def_id,str,namespace) v2) -> bool {
         ret util::common::def_eq(v1._0, v2._0) &&
-            _str::eq(v1._1, v2._1);
+            _str::eq(v1._1, v2._1) &&
+            v1._2 == v2._2;
     }
-    ret std::map::mk_hashmap[tup(def_id,str),def](hash, eq);
+    ret std::map::mk_hashmap[tup(def_id,str,namespace),def](hash, eq);
 }
 
 tag mod_index_entry {
@@ -509,7 +515,7 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
             }
             case (cons[scope](?hd, ?tl)) {
                 auto fnd = in_scope(e, id, hd, ns);
-                if (fnd != none[def]) {
+                if (!option::is_none(fnd)) {
                     auto df = option::get(fnd);
                     if ((left_fn && def_is_local(df)) ||
                         (left_fn_level2 && def_is_obj_field(df))) {
@@ -550,7 +556,7 @@ fn lookup_in_pat(&ident id, &ast::pat pat) -> option::t[def] {
         case (ast::pat_tag(_, ?pats, _)) {
             for (@ast::pat p in pats) {
                 auto found = lookup_in_pat(id, *p);
-                if (found != none[def]) { ret found; }
+                if (!option::is_none(found)) { ret found; }
             }
         }
     }
@@ -617,7 +623,7 @@ fn lookup_in_block(&ident id, &ast::block_ b, namespace ns)
                             case (_) {
                                 if (_str::eq(ast::item_ident(it), id)) {
                                     auto found = found_def_item(it, ns);
-                                    if (found != none[def]) { ret found; }
+                                    if (!option::is_none(found)) { ret found; }
                                 }
                             }
                         }
@@ -676,17 +682,15 @@ fn lookup_in_mod(&env e, def m, &ident id, namespace ns, dir dr)
     -> option::t[def] {
     auto defid = ast::def_id_of_def(m);
     if (defid._0 != ast::local_crate) { // Not in this crate
-        auto cached = e.ext_cache.find(tup(defid,id));
-        if (cached != none[def] && check_def_by_ns(option::get(cached), ns)) {
-            ret cached;
-        }
+        auto cached = e.ext_cache.find(tup(defid,id,ns));
+        if (!option::is_none(cached)) { ret cached; }
         auto path = vec(id);
         if (defid._1 != -1) {
             path = e.ext_map.get(defid) + path;
         }
         auto fnd = lookup_external(e, defid._0, path, ns);
-        if (fnd != none[def]) {
-            e.ext_cache.insert(tup(defid,id), option::get(fnd));
+        if (!option::is_none(fnd)) {
+            e.ext_cache.insert(tup(defid,id,ns), option::get(fnd));
         }
         ret fnd;
     }
@@ -728,8 +732,8 @@ fn lookup_import(&env e, def_id defid, namespace ns) -> option::t[def] {
     }
 }
 
-fn lookup_in_regular_mod(&env e, def_id defid, &ident id, namespace ns, dir dr)
-    -> option::t[def] {
+fn lookup_in_regular_mod(&env e, def_id defid, &ident id, namespace ns,
+                         dir dr) -> option::t[def] {
     auto info = e.mod_map.get(defid._1);
     auto found = info.index.find(id);
     if (option::is_none(found) || 
@@ -935,13 +939,11 @@ fn check_def_by_ns(def d, namespace ns) -> bool {
 
 fn lookup_external(&env e, int cnum, vec[ident] ids, namespace ns)
     -> option::t[def] {
-    auto found = creader::lookup_def(e.sess, cnum, ids);
-    if (found != none[def]) {
-        auto d = option::get(found);
-        if (!check_def_by_ns(d, ns)) { ret none[def]; }
+    for (def d in creader::lookup_defs(e.sess, cnum, ids)) {
         e.ext_map.insert(ast::def_id_of_def(d), ids);
+        if (check_def_by_ns(d, ns)) { ret some(d); }
     }
-    ret found;
+    ret none[def];
 }
 
 // Local Variables:
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 42bd68af6e2..ccbbeed07b1 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -1929,6 +1929,7 @@ mod Unify {
             } else if (actual_input.mode == mo_either) {
                 result_mode = expected_input.mode;
             } else if (expected_input.mode != actual_input.mode) {
+                // FIXME this is the wrong error
                 ret fn_common_res_err(ures_err(terr_arg_count,
                                                expected, actual));
             } else {