bind middle::ast_map::map_crate(*crate));
time(time_passes, "external crate/lib resolution",
bind creader::read_crates(sess, *crate));
- let {def_map: def_map, ext_map: ext_map} =
+ let {def_map: def_map, ext_map: ext_map, exp_map: exp_map} =
time(time_passes, "resolution",
bind resolve::resolve_crate(sess, ast_map, crate));
let freevars =
let (llmod, link_meta) =
time(time_passes, "translation",
bind trans::trans_crate(sess, crate, ty_cx,
- outputs.obj_filename, ast_map,
+ outputs.obj_filename, exp_map, ast_map,
mut_map, copy_map, last_uses));
time(time_passes, "LLVM passes",
bind link::write::run_passes(sess, llmod, outputs.obj_filename));
ppm_typed. {
crate = syntax::ext::expand::expand_crate(sess, crate);
let amap = middle::ast_map::map_crate(*crate);
- let {def_map: def_map, ext_map: ext_map} =
+ let {def_map: def_map, ext_map: ext_map, exp_map: _exp_map} =
resolve::resolve_crate(sess, amap, crate);
let freevars = freevars::annotate_freevars(def_map, crate);
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, amap, freevars);
fn lookup_defs(cstore: cstore::cstore, cnum: ast::crate_num,
path: [ast::ident]) -> [ast::def] {
- let cdata = cstore::get_crate_data(cstore, cnum).data;
- ret decoder::lookup_defs(cdata, cnum, path);
+ let result = [];
+ for (c, data, def) in resolve_path(cstore, cnum, path) {
+ result += [decoder::lookup_def(c, data, def)];
+ }
+ ret result;
+}
+
+fn resolve_path(cstore: cstore::cstore, cnum: ast::crate_num,
+ path: [ast::ident]) ->
+ [(ast::crate_num, @[u8], ast::def_id)] {
+ let cm = cstore::get_crate_data(cstore, cnum);
+ log #fmt("resolve_path %s in crates[%d]:%s",
+ str::connect(path, "::"), cnum, cm.name);
+ let result = [];
+ for def in decoder::resolve_path(path, cm.data) {
+ if def.crate == ast::local_crate {
+ result += [(cnum, cm.data, def)];
+ } else {
+ if cm.cnum_map.contains_key(def.crate) {
+ // This reexport is itself a reexport from anther crate
+ let next_cnum = cm.cnum_map.get(def.crate);
+ let next_cm_data = cstore::get_crate_data(cstore, next_cnum);
+ result += [(next_cnum, next_cm_data.data, def)];
+ }
+ }
+ }
+ ret result;
}
fn get_tag_variants(tcx: ty::ctxt, def: ast::def_id) -> [ty::variant_info] {
export get_type;
export get_type_param_count;
export get_type_param_kinds;
-export lookup_defs;
+export lookup_def;
+export resolve_path;
export get_crate_attributes;
export list_crate_metadata;
export crate_dep;
ret result;
}
-// Crate metadata queries
-fn lookup_defs(data: @[u8], cnum: ast::crate_num, path: [ast::ident]) ->
- [ast::def] {
- ret vec::map(bind lookup_def(cnum, data, _), resolve_path(path, data));
-}
-
-// FIXME doesn't yet handle re-exported externals
+// FIXME doesn't yet handle renamed re-exported externals
fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
ast::def {
let item = lookup_item(did_.node, data);
}
}
-fn encode_item_paths(ebml_w: ebml::writer, crate: @crate) -> [entry<str>] {
+fn encode_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt, crate: @crate)
+ -> [entry<str>] {
let index: [entry<str>] = [];
let path: [str] = [];
ebml::start_tag(ebml_w, tag_paths);
encode_module_item_paths(ebml_w, crate.node.module, path, index);
+ encode_reexport_paths(ebml_w, ecx, index);
ebml::end_tag(ebml_w);
ret index;
}
+fn encode_reexport_paths(ebml_w: ebml::writer,
+ ecx: @encode_ctxt, &index: [entry<str>]) {
+ ecx.ccx.exp_map.items {|path, def|
+ index += [{val: path, pos: ebml_w.writer.tell()}];
+ ebml::start_tag(ebml_w, tag_paths_data_item);
+ encode_name(ebml_w, path);
+ encode_def_id(ebml_w, ast_util::def_id_of_def(def));
+ ebml::end_tag(ebml_w);
+ }
+}
+
// Item info table encoding
fn encode_family(ebml_w: ebml::writer, c: u8) {
// Encode and index the paths.
ebml::start_tag(ebml_w, tag_paths);
- let paths_index = encode_item_paths(ebml_w, crate);
+ let paths_index = encode_item_paths(ebml_w, ecx, crate);
let paths_buckets = create_index(paths_index, hash_path);
encode_index(ebml_w, paths_buckets, write_str);
ebml::end_tag(ebml_w);
import std::list;
import std::map::hashmap;
import std::list::{list, nil, cons};
-import option::{some, none, is_none};
+import option::{some, none, is_none, is_some};
import syntax::print::pprust::*;
export resolve_crate;
export def_map;
export ext_map;
+export exp_map;
// 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,
type def_map = hashmap<node_id, def>;
type ext_map = hashmap<def_id, [ident]>;
+type exp_map = hashmap<str, def>;
type env =
{cstore: cstore::cstore,
def_map: def_map,
ast_map: ast_map::map,
imports: hashmap<ast::node_id, import_state>,
+ exp_map: exp_map,
mod_map: hashmap<ast::node_id, @indexed_mod>,
block_map: hashmap<ast::node_id, [glob_imp_def]>,
- ext_map: hashmap<def_id, [ident]>,
+ ext_map: ext_map,
ext_cache: ext_hash,
used_imports: {mutable track: bool,
mutable data: [ast::node_id]},
tag namespace { ns_value; ns_type; ns_module; }
fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
- {def_map: def_map, ext_map: ext_map} {
+ {def_map: def_map, ext_map: ext_map, exp_map: exp_map} {
let e =
@{cstore: sess.get_cstore(),
def_map: new_int_hash(),
ast_map: amap,
imports: new_int_hash(),
+ exp_map: new_str_hash(),
mod_map: new_int_hash(),
block_map: new_int_hash(),
ext_map: new_def_hash(),
map_crate(e, crate);
resolve_imports(*e);
check_for_collisions(e, *crate);
- check_bad_exports(e);
+ check_exports(e);
resolve_names(e, crate);
if sess.get_opts().warn_unused_imports {
check_unused_imports(e);
}
- ret {def_map: e.def_map, ext_map: e.ext_map};
+ ret {def_map: e.def_map, ext_map: e.ext_map, exp_map: e.exp_map};
}
// Locate all modules and imports and index them, so that the next passes can
for elt: T in elts { add_name(ch, sp, id(elt)); }
}
-fn check_bad_exports(e: @env) {
- fn lookup_glob_any(e: env, info: @indexed_mod, sp: span, ident: ident) ->
- bool {
- ret !option::is_none(lookup_glob_in_mod(e, info, sp, ident, ns_module,
- inside)) ||
- !option::is_none(lookup_glob_in_mod(e, info, sp, ident,
- ns_value, inside)) ||
- !option::is_none(lookup_glob_in_mod(e, info, sp, ident,
- ns_type, inside));
+fn check_exports(e: @env) {
+ fn lookup_glob_any(e: @env, info: @indexed_mod, sp: span, path: str,
+ ident: ident) -> bool {
+ let lookup =
+ bind lookup_glob_in_mod(*e, info, sp, ident, _, inside);
+ let (m, v, t) = (lookup(ns_module),
+ lookup(ns_value),
+ lookup(ns_type));
+ maybe_add_reexport(e, path + ident, m);
+ maybe_add_reexport(e, path + ident, v);
+ maybe_add_reexport(e, path + ident, t);
+ ret is_some(m) || is_some(v) || is_some(t);
+ }
+
+ fn maybe_add_reexport(e: @env, path: str, def: option::t<def>) {
+ if option::is_some(def) {
+ e.exp_map.insert(path, option::get(def));
+ }
+ }
+
+ fn check_export(e: @env, ident: str, val: @indexed_mod, vi: @view_item) {
+ if val.index.contains_key(ident) {
+ let xs = val.index.get(ident);
+ list::iter(xs) {|x|
+ alt x {
+ mie_import_ident(id, _) {
+ alt e.imports.get(id) {
+ resolved(v, t, m, rid, _) {
+ maybe_add_reexport(e, val.path + rid, v);
+ maybe_add_reexport(e, val.path + rid, t);
+ maybe_add_reexport(e, val.path + rid, m);
+ }
+ _ { }
+ }
+ }
+ _ { }
+ }
+ }
+ } else if lookup_glob_any(e, val, vi.span, val.path, ident) {
+ // do nothing
+ } else {
+ e.sess.span_warn(vi.span,
+ #fmt("exported item %s is not defined", ident));
+ }
}
e.mod_map.values {|val|
alt vi.node {
ast::view_item_export(idents, _) {
for ident in idents {
- if !val.index.contains_key(ident) &&
- !lookup_glob_any(*e, val, vi.span, ident) {
- e.sess.span_warn(vi.span,
- "exported item " + ident +
- " is not defined");
- }
+ check_export(e, ident, val, vi);
}
}
_ { }
import option::{some, none};
import driver::session;
import front::attr;
-import middle::{ty, gc};
+import middle::{ty, gc, resolve};
import middle::freevars::*;
import back::{link, abi, upcall};
import syntax::{ast, ast_util};
}
fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
- output: str, amap: ast_map::map, mut_map: mut::mut_map,
- copy_map: alias::copy_map, last_uses: last_use::last_uses)
+ output: str, emap: resolve::exp_map, amap: ast_map::map,
+ mut_map: mut::mut_map, copy_map: alias::copy_map,
+ last_uses: last_use::last_uses)
-> (ModuleRef, link::link_meta) {
let sha = std::sha1::mk_sha1();
let link_meta = link::build_link_meta(sess, *crate, output, sha);
intrinsics: intrinsics,
item_ids: new_int_hash::<ValueRef>(),
ast_map: amap,
+ exp_map: emap,
item_symbols: new_int_hash::<str>(),
mutable main_fn: none::<ValueRef>,
link_meta: link_meta,
intrinsics: hashmap<str, ValueRef>,
item_ids: hashmap<ast::node_id, ValueRef>,
ast_map: ast_map::map,
+ exp_map: hashmap<str, ast::def>,
item_symbols: hashmap<ast::node_id, str>,
mutable main_fn: option::t<ValueRef>,
link_meta: link::link_meta,