diff options
| author | Marijn Haverbeke <[email protected]> | 2011-05-13 15:17:24 +0200 |
|---|---|---|
| committer | Marijn Haverbeke <[email protected]> | 2011-05-13 17:20:39 +0200 |
| commit | eb419fd8c78f907f1a5cd20f5e71009ba37ef7e9 (patch) | |
| tree | 924709adb23c244bb06f23bde47dff88b48eb20e | |
| parent | Make module indices hold a list of items (diff) | |
| download | rust-eb419fd8c78f907f1a5cd20f5e71009ba37ef7e9.tar.xz rust-eb419fd8c78f907f1a5cd20f5e71009ba37ef7e9.zip | |
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.rs | 133 | ||||
| -rw-r--r-- | src/comp/middle/metadata.rs | 16 | ||||
| -rw-r--r-- | src/comp/middle/resolve.rs | 48 | ||||
| -rw-r--r-- | src/comp/middle/ty.rs | 1 |
4 files changed, 85 insertions, 113 deletions
diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index 03b5cb1e..023ede50 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 e10f2e73..b3078424 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 93ce248b..ad1a5fe9 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 42bd68af..ccbbeed0 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 { |