sopts.target_triple,
sopts.addl_lib_search_paths);
ret session::session(target_cfg, sopts, cstore,
- @{cm: codemap::new_codemap(), mutable next_id: 0},
+ @{cm: codemap::new_codemap(), mutable next_id: 1},
none, 0u, filesearch, false);
}
import syntax::ast;
import middle::ty;
-import option;
+import option::{some, none};
import driver::session;
export get_symbol;
export get_type_param_count;
export lookup_defs;
export get_tag_variants;
+export get_impls_for_mod;
+export get_impl_methods;
export get_type;
fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> str {
let cstore = tcx.sess.get_cstore();
let cnum = def.crate;
let cdata = cstore::get_crate_data(cstore, cnum).data;
- let resolver = bind translate_def_id(tcx.sess, cnum, _);
+ let resolver = bind translate_def_id(cstore, cnum, _);
ret decoder::get_tag_variants(cdata, def, tcx, resolver)
}
+fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id,
+ name: option::t<ast::ident>)
+ -> [@middle::resolve::_impl] {
+ let cdata = cstore::get_crate_data(cstore, def.crate).data;
+ let result = [];
+ for did in decoder::get_impls_for_mod(cdata, def.node, def.crate) {
+ let nm = decoder::lookup_item_name(cdata, did.node);
+ if alt name { some(n) { n == nm } none. { true } } {
+ result += [@{did: did,
+ ident: nm,
+ methods: decoder::lookup_impl_methods(
+ cdata, did.node, did.crate)}];
+ }
+ }
+ result
+}
+
+fn get_impl_methods(cstore: cstore::cstore, def: ast::def_id)
+ -> [@middle::resolve::method_info] {
+ let cdata = cstore::get_crate_data(cstore, def.crate).data;
+ decoder::lookup_impl_methods(cdata, def.node, def.crate)
+}
+
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_kinds_and_ty {
let cstore = tcx.sess.get_cstore();
let cnum = def.crate;
let cdata = cstore::get_crate_data(cstore, cnum).data;
- let resolver = bind translate_def_id(tcx.sess, cnum, _);
+ let resolver = bind translate_def_id(cstore, cnum, _);
decoder::get_type(cdata, def, tcx, resolver)
}
// external crates - if those types further refer to types in other crates
// then we must translate the crate number from that encoded in the external
// crate to the correct local crate number.
-fn translate_def_id(sess: session::session, searched_crate: ast::crate_num,
+fn translate_def_id(cstore: cstore::cstore, searched_crate: ast::crate_num,
def_id: ast::def_id) -> ast::def_id {
let ext_cnum = def_id.crate;
assert (searched_crate != ast::local_crate);
assert (ext_cnum != ast::local_crate);
- let cstore = sess.get_cstore();
let cmeta = cstore::get_crate_data(cstore, searched_crate);
let local_cnum =
alt cmeta.cnum_map.find(ext_cnum) {
option::some(n) { n }
- option::none. { sess.bug("didn't find a crate in the cnum_map") }
+ option::none. { fail "didn't find a crate in the cnum_map"; }
};
ret {crate: local_cnum, node: node_id};
export get_type_param_count;
export get_type_param_kinds;
export lookup_def;
+export lookup_item_name;
export resolve_path;
export get_crate_attributes;
export list_crate_metadata;
export get_crate_deps;
export get_crate_hash;
export external_resolver;
-
+export get_impls_for_mod;
+export lookup_impl_methods;
// A function that takes a def_id relative to the crate being searched and
// returns a def_id relative to the compilation environment, i.e. if we hit a
// def_id for an item defined in another crate, somebody needs to figure out
ret ks;
}
+fn item_ty_param_count(item: ebml::doc) -> uint {
+ let n = 0u;
+ let tp = tag_items_data_item_ty_param_kinds;
+ ebml::tagged_docs(item, tp) {|p|
+ n += ebml::vint_at(ebml::doc_data(p), 0u).val;
+ }
+ n
+}
+
fn tag_variant_ids(item: ebml::doc, this_cnum: ast::crate_num) ->
[ast::def_id] {
let ids: [ast::def_id] = [];
ret result;
}
+fn item_name(item: ebml::doc) -> ast::ident {
+ let name = ebml::get_doc(item, tag_paths_data_name);
+ str::unsafe_from_bytes(ebml::doc_data(name))
+}
+
+fn lookup_item_name(data: @[u8], id: ast::node_id) -> ast::ident {
+ item_name(lookup_item(id, data))
+}
+
// FIXME doesn't yet handle renamed re-exported externals
fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
ast::def {
}
fn get_type_param_count(data: @[u8], id: ast::node_id) -> uint {
- ret vec::len(get_type_param_kinds(data, id));
+ item_ty_param_count(lookup_item(id, data))
}
fn get_type_param_kinds(data: @[u8], id: ast::node_id) -> [ast::kind] {
ret infos;
}
+fn get_impls_for_mod(data: @[u8], node: ast::node_id, cnum: ast::crate_num)
+ -> [ast::def_id] {
+ let mod_item = lookup_item(node, data), result = [];
+ ebml::tagged_docs(mod_item, tag_mod_impl) {|doc|
+ let did = parse_def_id(ebml::doc_data(doc));
+ result += [{crate: cnum with did}];
+ }
+ result
+}
+
+fn lookup_impl_methods(data: @[u8], node: ast::node_id, cnum: ast::crate_num)
+ -> [@middle::resolve::method_info] {
+ let impl_item = lookup_item(node, data), rslt = [];
+ let base_tps = item_ty_param_count(impl_item);
+ ebml::tagged_docs(impl_item, tag_impl_method) {|doc|
+ let m_did = parse_def_id(ebml::doc_data(doc));
+ let mth_item = lookup_item(m_did.node, data);
+ rslt += [@{did: {crate: cnum, node: m_did.node},
+ n_tps: item_ty_param_count(mth_item) - base_tps,
+ ident: item_name(mth_item)}];
+ }
+ rslt
+}
+
+
fn family_has_type_params(fam_ch: u8) -> bool {
ret alt fam_ch as char {
'c' { false }
'm' { false }
'n' { false }
'v' { true }
+ 'i' { true }
};
}
}
}
+fn encode_info_for_mod(ebml_w: ebml::writer, md: _mod,
+ id: node_id) {
+ ebml::start_tag(ebml_w, tag_items_data_item);
+ encode_def_id(ebml_w, local_def(id));
+ encode_family(ebml_w, 'm' as u8);
+ for i in md.items {
+ alt i.node {
+ item_impl(_, _, _) {
+ if ast_util::is_exported(i.ident, md) {
+ ebml::start_tag(ebml_w, tag_mod_impl);
+ ebml_w.writer.write(str::bytes(def_to_str(local_def(i.id))));
+ ebml::end_tag(ebml_w);
+ }
+ }
+ _ {}
+ }
+ }
+ ebml::end_tag(ebml_w);
+}
+
fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
&index: [entry<int>]) {
alt item.node {
ebml::end_tag(ebml_w);
}
item_mod(m) {
- ebml::start_tag(ebml_w, tag_items_data_item);
- encode_def_id(ebml_w, local_def(item.id));
- encode_family(ebml_w, 'm' as u8);
- for i in m.items {
- alt i.node {
- item_impl(_, _, _) {
- ebml::start_tag(ebml_w, tag_mod_impl);
- ebml_w.writer.write(str::bytes(def_to_str(local_def(i.id))));
- ebml::end_tag(ebml_w);
- }
- _ {}
- }
- }
- ebml::end_tag(ebml_w);
+ encode_info_for_mod(ebml_w, m, item.id);
}
item_native_mod(_) {
ebml::start_tag(ebml_w, tag_items_data_item);
item_impl(tps, _, methods) {
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
- encode_family(ebml_w, 'I' as u8);
+ encode_family(ebml_w, 'i' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
+ encode_name(ebml_w, item.ident);
for m in methods {
ebml::start_tag(ebml_w, tag_impl_method);
ebml_w.writer.write(str::bytes(def_to_str(local_def(m.node.id))));
index += [{val: m.node.id, pos: ebml_w.writer.tell()}];
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(m.node.id));
- encode_family(ebml_w, 'i' as u8);
+ encode_family(ebml_w, 'f' as u8);
+ encode_inlineness(ebml_w, 'n' as u8);
encode_type_param_kinds(ebml_w, tps + m.node.tps);
encode_type(ecx, ebml_w,
node_id_to_monotype(ecx.ccx.tcx, m.node.id));
+ encode_name(ebml_w, m.node.ident);
encode_symbol(ecx, ebml_w, m.node.id);
ebml::end_tag(ebml_w);
}
ebml::end_tag(ebml_w);
}
-fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer) ->
- [entry<int>] {
+fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
+ crate_mod: _mod) -> [entry<int>] {
let index: [entry<int>] = [];
ebml::start_tag(ebml_w, tag_items_data);
+ index += [{val: crate_node_id, pos: ebml_w.writer.tell()}];
+ encode_info_for_mod(ebml_w, crate_mod, crate_node_id);
ecx.ccx.ast_map.items {|key, val|
alt val {
middle::ast_map::node_item(i) {
// Encode and index the items.
ebml::start_tag(ebml_w, tag_items);
- let items_index = encode_info_for_items(ecx, ebml_w);
+ let items_index = encode_info_for_items(ecx, ebml_w, crate.node.module);
let items_buckets = create_index(items_index, hash_node_id);
encode_index(ebml_w, items_buckets, write_int);
ebml::end_tag(ebml_w);
node_item(@item);
node_obj_ctor(@item);
node_native_item(@native_item);
+ node_method(@method);
node_expr(@expr);
// Locals are numbered, because the alias analysis needs to know in which
// order they are introduced.
cx.map.insert(i.id, node_item(i));
alt i.node {
item_obj(_, _, ctor_id) { cx.map.insert(ctor_id, node_obj_ctor(i)); }
+ item_impl(_, _, ms) {
+ for m in ms { cx.map.insert(m.node.id, node_method(m)); }
+ }
_ { }
}
}
import syntax::print::pprust::*;
export resolve_crate;
-export def_map, ext_map, exp_map, impl_map, iscopes;
+export def_map, ext_map, exp_map, impl_map;
+export _impl, iscopes, method_info;
// Resolving happens in two passes. The first pass collects defids of all
// (internal) imports and modules, so that they can be looked up when needed,
resolved(option::t<def>, /* value */
option::t<def>, /* type */
option::t<def>, /* module */
- @[@ast::item],
+ @[@_impl], /* impls */
/* used for reporting unused import warning */
ast::ident, codemap::span);
}
type ext_map = hashmap<def_id, [ident]>;
type exp_map = hashmap<str, def>;
type impl_map = hashmap<node_id, iscopes>;
+type impl_cache = hashmap<def_id, @[@_impl]>;
type env =
{cstore: cstore::cstore,
block_map: hashmap<ast::node_id, [glob_imp_def]>,
ext_map: ext_map,
impl_map: impl_map,
+ impl_cache: impl_cache,
ext_cache: ext_hash,
used_imports: {mutable track: bool,
mutable data: [ast::node_id]},
block_map: new_int_hash(),
ext_map: new_def_hash(),
impl_map: new_int_hash(),
+ impl_cache: new_def_hash(),
ext_cache: new_ext_hash(),
used_imports: {mutable track: false, mutable data: []},
mutable reported: [],
ids: [ast::ident], sp: codemap::span, sc: scopes) {
fn register(e: env, id: node_id, cx: ctxt, sp: codemap::span,
name: ast::ident, lookup: block(namespace) -> option::t<def>,
- impls: [@ast::item]) {
+ impls: [@_impl]) {
let val = lookup(ns_value), typ = lookup(ns_type),
md = lookup(ns_module);
if is_none(val) && is_none(typ) && is_none(md) &&
if !is_none(cached) { ret cached; }
let path = [name];
if defid.node != ast::crate_node_id {
- path = e.ext_map.get(defid) + path;
+ path = e.ext_map.get(defid) + path;
}
let fnd = lookup_external(e, defid.crate, path, ns);
if !is_none(fnd) {
// Impl resolution
+type method_info = {did: def_id, n_tps: uint, ident: ast::ident};
+type _impl = {did: def_id, ident: ast::ident, methods: [@method_info]};
+type iscopes = list<@[@_impl]>;
+
fn resolve_impls(e: @env, c: @ast::crate) {
visit::visit_crate(*c, nil, visit::mk_vt(@{
visit_block: bind visit_block_with_impl_scope(e, _, _, _),
}
fn find_impls_in_view_item(e: env, vi: @ast::view_item,
- &impls: [@ast::item], sc: iscopes) {
+ &impls: [@_impl], sc: iscopes) {
alt vi.node {
- ast::view_item_import(_, pt, id) {
+ ast::view_item_import(name, pt, id) {
let found = [];
if vec::len(*pt) == 1u {
list::iter(sc) {|level|
if vec::len(found) > 0u { ret; }
for imp in *level {
- if imp.ident == pt[0] { found += [imp]; }
+ if imp.ident == pt[0] {
+ found += [@{ident: name with *imp}];
+ }
}
if vec::len(found) > 0u { impls += found; }
}
} else {
alt e.imports.get(id) {
- resolved(_, _, _, is, _, _) { impls += *is; }
+ resolved(_, _, _, is, _, _) {
+ for i in *is { impls += [@{ident: name with *i}]; }
+ }
}
}
}
}
}
-fn find_impls_in_item(i: @ast::item, &impls: [@ast::item],
+fn find_impls_in_item(i: @ast::item, &impls: [@_impl],
name: option::t<ident>,
ck_exports: option::t<ast::_mod>) {
alt i.node {
- ast::item_impl(_, _, _) {
+ ast::item_impl(_, _, mthds) {
if alt name { some(n) { n == i.ident } _ { true } } &&
alt ck_exports { some(m) { is_exported(i.ident, m) } _ { true } } {
- impls += [i];
+ impls += [@{did: local_def(i.id),
+ ident: i.ident,
+ methods: vec::map({|m| @{did: local_def(m.node.id),
+ n_tps: vec::len(m.node.tps),
+ ident: m.node.ident}},
+ mthds)}];
}
}
_ {}
}
}
-// FIXME[impl] external importing of impls
-fn find_impls_in_mod(e: env, m: def, &impls: [@ast::item],
+// FIXME[impl] we should probably cache this
+fn find_impls_in_mod(e: env, m: def, &impls: [@_impl],
name: option::t<ident>) {
alt m {
ast::def_mod(defid) {
- if defid.crate == ast::local_crate {
- let md = option::get(e.mod_map.get(defid.node).m);
- for i in md.items {
- find_impls_in_item(i, impls, name, some(md));
+ alt e.impl_cache.find(defid) {
+ some(v) { impls += *v; }
+ none. {
+ let found = [];
+ if defid.crate == ast::local_crate {
+ let md = option::get(e.mod_map.get(defid.node).m);
+ for i in md.items {
+ find_impls_in_item(i, found, name, some(md));
+ }
+ } else {
+ found = csearch::get_impls_for_mod(e.cstore, defid, name);
}
+ impls += found;
+ e.impl_cache.insert(defid, @found);
+ }
}
}
_ {}
}
}
-type iscopes = list<@[@ast::item]>;
-
fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
v: vt<iscopes>) {
let impls = [];
// FIXME[impl] notice/resolve conflicts
fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
name: ast::ident, ty: ty::t)
- -> option::t<{method: @ast::method, ids: [int]}> {
+ -> option::t<{method: @resolve::method_info, ids: [int]}> {
let result = none;
std::list::iter(isc) {|impls|
- for im in *impls {
- alt im.node {
- ast::item_impl(tps, slf, mthds) {
- let self_ty = ast_ty_to_ty_crate(fcx.ccx, slf);
- let tp_count = vec::len(tps);
- let {ids, ty: self_ty} = if tp_count > 0u {
- bind_params_in_type(ast_util::dummy_sp(), fcx.ccx.tcx,
- bind next_ty_var_id(fcx), self_ty,
- tp_count)
- } else { {ids: [], ty: self_ty} };
- // FIXME[impl] Don't unify in the current fcx, use
- // scratch context
- alt unify::unify(fcx, ty, self_ty) {
- ures_ok(_) {
- for m in mthds {
- if m.node.ident == name {
- result = some({method: m, ids: ids});
- ret;
- }
- }
+ for @{did, methods, _} in *impls {
+ let (n_tps, self_ty) = if did.crate == ast::local_crate {
+ alt fcx.ccx.tcx.items.get(did.node) {
+ ast_map::node_item(@{node: ast::item_impl(tps, st, _), _}) {
+ (vec::len(tps), ast_ty_to_ty_crate(fcx.ccx, st))
}
- _ {}
+ }
+ } else {
+ let tpt = csearch::get_type(fcx.ccx.tcx, did);
+ (vec::len(tpt.kinds), tpt.ty)
+ };
+ let {ids, ty: self_ty} = if n_tps > 0u {
+ bind_params_in_type(ast_util::dummy_sp(), fcx.ccx.tcx,
+ bind next_ty_var_id(fcx), self_ty, n_tps)
+ } else { {ids: [], ty: self_ty} };
+ // FIXME[impl] Don't unify in the current fcx, use
+ // scratch context
+ alt unify::unify(fcx, ty, self_ty) {
+ ures_ok(_) {
+ for m in methods {
+ if m.ident == name {
+ result = some({method: m, ids: ids});
+ ret;
+ }
}
}
+ _ {}
}
}
}
let iscope = fcx.ccx.impl_map.get(expr.id);
alt lookup_method(fcx, iscope, field, base_t) {
some({method, ids}) {
- let mt = ty_of_method(fcx.ccx.tcx, m_check, method), ids = ids;
- let fty = ty::mk_fn(fcx.ccx.tcx, mt.proto, mt.inputs,
- mt.output, mt.cf, mt.constrs);
- let tp_count = vec::len(method.node.tps);
- if tp_count > 0u {
+ let fty = if method.did.crate == ast::local_crate {
+ alt tcx.items.get(method.did.node) {
+ ast_map::node_method(m) {
+ let mt = ty_of_method(tcx, m_check, m);
+ ty::mk_fn(tcx, mt.proto, mt.inputs,
+ mt.output, mt.cf, mt.constrs)
+ }
+ }
+ } else { csearch::get_type(tcx, method.did).ty };
+ let ids = ids;
+ if method.n_tps > 0u {
let b = bind_params_in_type(expr.span, tcx,
bind next_ty_var_id(fcx),
- fty, tp_count);
+ fty, method.n_tps);
ids += b.ids;
fty = b.ty;
}
let substs = vec::map(ids, {|id| ty::mk_var(tcx, id)});
write::ty_fixup(fcx, id, {substs: some(substs), ty: fty});
- fcx.ccx.method_map.insert(id, local_def(method.node.id));
+ fcx.ccx.method_map.insert(id, method.did);
}
_ {
base_t = do_autoderef(fcx, expr.span, base_t);