2011-05-12 17:24:54 +02:00
|
|
|
import front::ast;
|
|
|
|
import front::ast::ident;
|
|
|
|
import front::ast::def;
|
|
|
|
import front::ast::def_id;
|
|
|
|
import front::ast::ann;
|
|
|
|
import front::creader;
|
|
|
|
import driver::session::session;
|
|
|
|
import util::common::new_def_hash;
|
|
|
|
import util::common::new_int_hash;
|
|
|
|
import util::common::new_uint_hash;
|
|
|
|
import util::common::new_str_hash;
|
|
|
|
import util::common::span;
|
2011-05-14 19:02:30 -07:00
|
|
|
import middle::tstate::ann::ts_ann;
|
2011-06-09 15:50:26 +02:00
|
|
|
import visit::vt;
|
2011-05-12 17:24:54 +02:00
|
|
|
import std::map::hashmap;
|
2011-05-25 10:10:30 -07:00
|
|
|
import std::list;
|
2011-05-12 17:24:54 +02:00
|
|
|
import std::list::list;
|
|
|
|
import std::list::nil;
|
|
|
|
import std::list::cons;
|
|
|
|
import std::option;
|
|
|
|
import std::option::some;
|
|
|
|
import std::option::none;
|
2011-05-17 20:41:41 +02:00
|
|
|
import std::str;
|
|
|
|
import std::vec;
|
2010-10-06 18:36:28 -07:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
// 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,
|
|
|
|
// and then uses this information to resolve the imports. The second pass
|
|
|
|
// locates all names (in expressions, types, and alt patterns) and resolves
|
|
|
|
// them, storing the resulting def in the AST nodes.
|
|
|
|
|
2011-05-11 16:30:48 +02:00
|
|
|
// This module internally uses -1 as a def_id for the top_level module in a
|
|
|
|
// crate. The parser doesn't assign a def_id to this module.
|
|
|
|
// (FIXME See https://github.com/graydon/rust/issues/358 for the reason this
|
|
|
|
// isn't a const.)
|
|
|
|
|
2010-10-18 14:37:30 -07:00
|
|
|
tag scope {
|
2011-05-12 17:24:54 +02:00
|
|
|
scope_crate(@ast::crate);
|
|
|
|
scope_item(@ast::item);
|
2011-06-09 15:50:26 +02:00
|
|
|
scope_fn(ast::fn_decl, vec[ast::ty_param]);
|
2011-05-12 17:24:54 +02:00
|
|
|
scope_native_item(@ast::native_item);
|
|
|
|
scope_loop(@ast::decl); // there's only 1 decl per loop.
|
|
|
|
scope_block(ast::block);
|
|
|
|
scope_arm(ast::arm);
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
type scopes = list[scope];
|
2010-10-18 14:37:30 -07:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
tag import_state {
|
2011-06-09 15:50:26 +02:00
|
|
|
todo(@ast::view_item, scopes); // only used for explicit imports
|
2011-05-09 12:40:09 +02:00
|
|
|
resolving(span);
|
2011-05-13 16:46:20 +02:00
|
|
|
resolved(option::t[def] /* value */,
|
|
|
|
option::t[def] /* type */,
|
|
|
|
option::t[def] /* module */);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-11 12:21:09 +02:00
|
|
|
|
2011-05-13 15:17:24 +02:00
|
|
|
type ext_hash = hashmap[tup(def_id,str,namespace),def];
|
2011-05-11 12:21:09 +02:00
|
|
|
fn new_ext_hash() -> ext_hash {
|
2011-05-13 15:17:24 +02:00
|
|
|
fn hash(&tup(def_id,str,namespace) v) -> uint {
|
2011-05-17 20:41:41 +02:00
|
|
|
ret str::hash(v._1) + util::common::hash_def(v._0) + (alt (v._2) {
|
2011-05-13 15:17:24 +02:00
|
|
|
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 {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret util::common::def_eq(v1._0, v2._0) &&
|
2011-05-17 20:41:41 +02:00
|
|
|
str::eq(v1._1, v2._1) &&
|
2011-05-13 15:17:24 +02:00
|
|
|
v1._2 == v2._2;
|
2011-05-11 12:21:09 +02:00
|
|
|
}
|
2011-05-13 15:17:24 +02:00
|
|
|
ret std::map::mk_hashmap[tup(def_id,str,namespace),def](hash, eq);
|
2011-05-11 12:21:09 +02:00
|
|
|
}
|
|
|
|
|
2011-05-11 16:30:48 +02:00
|
|
|
tag mod_index_entry {
|
2011-05-12 17:24:54 +02:00
|
|
|
mie_view_item(@ast::view_item);
|
|
|
|
mie_item(@ast::item);
|
2011-05-19 11:37:17 -07:00
|
|
|
mie_native_item(@ast::native_item);
|
2011-05-12 17:24:54 +02:00
|
|
|
mie_tag_variant(@ast::item /* tag item */, uint /* variant index */);
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-13 13:34:59 +02:00
|
|
|
type mod_index = hashmap[ident,list[mod_index_entry]];
|
2011-05-20 15:56:23 -07:00
|
|
|
|
|
|
|
type indexed_mod = rec(option::t[ast::_mod] m,
|
2011-05-26 17:33:33 -07:00
|
|
|
mod_index index, vec[def] glob_imports,
|
|
|
|
hashmap[str,import_state] glob_imported_names);
|
2011-05-19 11:37:17 -07:00
|
|
|
/* native modules can't contain tags, and we don't store their ASTs because we
|
|
|
|
only need to look at them to determine exports, which they can't control.*/
|
2011-05-20 15:56:23 -07:00
|
|
|
// It should be safe to use index to memoize lookups of globbed names.
|
|
|
|
|
2011-05-26 17:16:54 -07:00
|
|
|
type crate_map = hashmap[uint,ast::crate_num];
|
2011-05-11 16:30:48 +02:00
|
|
|
|
2011-05-12 13:25:18 +02:00
|
|
|
type def_map = hashmap[uint,def];
|
|
|
|
|
2011-05-26 17:16:54 -07:00
|
|
|
type env = rec(crate_map crate_map,
|
|
|
|
def_map def_map,
|
2011-05-25 11:55:48 -07:00
|
|
|
hashmap[def_id,@ast::item] ast_map,
|
2011-05-12 17:24:54 +02:00
|
|
|
hashmap[ast::def_num,import_state] imports,
|
|
|
|
hashmap[ast::def_num,@indexed_mod] mod_map,
|
2011-05-11 12:21:09 +02:00
|
|
|
hashmap[def_id,vec[ident]] ext_map,
|
|
|
|
ext_hash ext_cache,
|
2011-05-09 12:40:09 +02:00
|
|
|
session sess);
|
|
|
|
|
|
|
|
// Used to distinguish between lookups from outside and from inside modules,
|
|
|
|
// since export restrictions should only be applied for the former.
|
|
|
|
tag dir { inside; outside; }
|
2010-10-07 18:34:22 -07:00
|
|
|
|
2011-03-30 17:23:25 -07:00
|
|
|
tag namespace {
|
|
|
|
ns_value;
|
|
|
|
ns_type;
|
2011-05-13 16:46:20 +02:00
|
|
|
ns_module;
|
2011-03-30 17:23:25 -07:00
|
|
|
}
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
fn resolve_crate(session sess, @ast::crate crate) -> def_map {
|
2011-05-26 17:16:54 -07:00
|
|
|
auto e = @rec(crate_map = new_uint_hash[ast::crate_num](),
|
|
|
|
def_map = new_uint_hash[def](),
|
2011-05-25 11:55:48 -07:00
|
|
|
ast_map = new_def_hash[@ast::item](),
|
2011-05-12 13:25:18 +02:00
|
|
|
imports = new_int_hash[import_state](),
|
2011-05-11 16:30:48 +02:00
|
|
|
mod_map = new_int_hash[@indexed_mod](),
|
2011-05-09 12:40:09 +02:00
|
|
|
ext_map = new_def_hash[vec[ident]](),
|
2011-05-11 12:21:09 +02:00
|
|
|
ext_cache = new_ext_hash(),
|
2011-05-09 12:40:09 +02:00
|
|
|
sess = sess);
|
2011-05-26 17:16:54 -07:00
|
|
|
creader::read_crates(sess, e.crate_map, *crate);
|
2011-06-09 15:50:26 +02:00
|
|
|
map_crate(e, crate);
|
2011-05-09 12:40:09 +02:00
|
|
|
resolve_imports(*e);
|
2011-05-18 22:23:19 +02:00
|
|
|
check_for_collisions(e, *crate);
|
2011-06-09 15:50:26 +02:00
|
|
|
resolve_names(e, crate);
|
2011-05-13 10:51:36 +02:00
|
|
|
ret e.def_map;
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
|
|
|
|
2011-05-20 15:56:23 -07:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
// Locate all modules and imports and index them, so that the next passes can
|
|
|
|
// resolve through them.
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn map_crate(&@env e, &@ast::crate c) {
|
2011-05-20 15:56:23 -07:00
|
|
|
// First, find all the modules, and index the names that they contain
|
2011-06-09 15:50:26 +02:00
|
|
|
auto v_map_mod =
|
|
|
|
@rec(visit_view_item = bind index_vi(e, _, _, _),
|
|
|
|
visit_item = bind index_i(e, _, _, _)
|
|
|
|
with *visit::default_visitor[scopes]());
|
|
|
|
visit::visit_crate(*c, cons(scope_crate(c), @nil),
|
|
|
|
visit::vtor(v_map_mod));
|
|
|
|
// Register the top-level mod
|
2011-05-19 11:37:17 -07:00
|
|
|
e.mod_map.insert(-1, @rec(m=some(c.node.module),
|
2011-05-20 15:56:23 -07:00
|
|
|
index=index_mod(c.node.module),
|
2011-05-26 17:33:33 -07:00
|
|
|
glob_imports=vec::empty[def](),
|
|
|
|
glob_imported_names
|
|
|
|
=new_str_hash[import_state]()));
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn index_vi(@env e, &@ast::view_item i, &scopes sc, &vt[scopes] v) {
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (i.node) {
|
|
|
|
case (ast::view_item_import(_, ?ids, ?defid)) {
|
2011-06-09 15:50:26 +02:00
|
|
|
e.imports.insert(defid._1, todo(i, sc));
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
|
|
|
|
fn index_i(@env e, &@ast::item i, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit_item_with_scope(i, sc, v);
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (i.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_mod(_, ?md, ?defid)) {
|
2011-05-20 15:56:23 -07:00
|
|
|
e.mod_map.insert(defid._1,
|
|
|
|
@rec(m=some(md), index=index_mod(md),
|
2011-05-26 17:33:33 -07:00
|
|
|
glob_imports=vec::empty[def](),
|
|
|
|
glob_imported_names
|
|
|
|
=new_str_hash[import_state]()));
|
2011-05-25 11:55:48 -07:00
|
|
|
e.ast_map.insert(defid, i);
|
2011-01-18 15:23:11 -05:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_native_mod(_, ?nmd, ?defid)) {
|
2011-05-20 15:56:23 -07:00
|
|
|
e.mod_map.insert(defid._1,
|
|
|
|
@rec(m=none[ast::_mod],
|
|
|
|
index=index_nmod(nmd),
|
2011-05-26 17:33:33 -07:00
|
|
|
glob_imports=vec::empty[def](),
|
|
|
|
glob_imported_names
|
|
|
|
=new_str_hash[import_state]()));
|
2011-05-25 11:55:48 -07:00
|
|
|
e.ast_map.insert(defid, i);
|
|
|
|
}
|
|
|
|
case (ast::item_const(_, _, _, ?defid, _)) {
|
|
|
|
e.ast_map.insert(defid, i);
|
|
|
|
}
|
|
|
|
case (ast::item_fn(_, _, _, ?defid, _)) {
|
|
|
|
e.ast_map.insert(defid, i);
|
|
|
|
}
|
|
|
|
case (ast::item_ty(_, _, _, ?defid, _)) {
|
|
|
|
e.ast_map.insert(defid, i);
|
|
|
|
}
|
|
|
|
case (ast::item_tag(_, _, _, ?defid, _)) {
|
|
|
|
e.ast_map.insert(defid, i);
|
|
|
|
}
|
|
|
|
case (ast::item_obj(_, _, _, ?obj_def_ids, _)) {
|
|
|
|
e.ast_map.insert(obj_def_ids.ty, i);
|
|
|
|
e.ast_map.insert(obj_def_ids.ctor, i);
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
|
|
|
|
// Next, assemble the links for globbed imports.
|
2011-06-09 15:50:26 +02:00
|
|
|
auto v_link_glob =
|
|
|
|
@rec(visit_view_item = bind link_glob(e, _, _, _),
|
|
|
|
visit_item = visit_item_with_scope
|
|
|
|
with *visit::default_visitor[scopes]());
|
|
|
|
visit::visit_crate(*c, cons(scope_crate(c), @nil),
|
|
|
|
visit::vtor(v_link_glob));
|
2011-05-25 10:10:30 -07:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn link_glob(@env e, &@ast::view_item vi, &scopes sc, &vt[scopes] v) {
|
|
|
|
fn find_mod(@env e, scopes sc) -> @indexed_mod {
|
2011-05-25 10:10:30 -07:00
|
|
|
alt (sc) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (cons(scope_item(?i), ?tl)) {
|
2011-05-25 10:10:30 -07:00
|
|
|
alt(i.node) {
|
|
|
|
case (ast::item_mod(_, _, ?defid)) {
|
|
|
|
ret e.mod_map.get(defid._1);
|
|
|
|
}
|
|
|
|
case (ast::item_native_mod(_, _, ?defid)) {
|
|
|
|
ret e.mod_map.get(defid._1);
|
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
be find_mod(e, *tl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
ret e.mod_map.get(-1); //top-level
|
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
|
|
|
}
|
2011-05-25 10:10:30 -07:00
|
|
|
|
2011-05-20 15:56:23 -07:00
|
|
|
alt (vi.node) {
|
|
|
|
//if it really is a glob import, that is
|
|
|
|
case (ast::view_item_import_glob(?path, _)) {
|
2011-06-09 15:50:26 +02:00
|
|
|
find_mod(e, sc).glob_imports
|
|
|
|
+= [follow_import(*e, sc, path, vi.span)];
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-01-18 15:23:11 -05:00
|
|
|
}
|
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
fn resolve_imports(&env e) {
|
2011-05-12 17:24:54 +02:00
|
|
|
for each (@tup(ast::def_num, import_state) it in e.imports.items()) {
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (it._1) {
|
|
|
|
case (todo(?item, ?sc)) {
|
|
|
|
resolve_import(e, item, sc);
|
2011-03-29 17:01:27 -07:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
case (resolved(_, _, _)) {}
|
2011-03-29 17:01:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn resolve_names(&@env e, &@ast::crate c) {
|
|
|
|
auto v = @rec(visit_native_item = visit_native_item_with_scope,
|
|
|
|
visit_item = visit_item_with_scope,
|
|
|
|
visit_block = visit_block_with_scope,
|
|
|
|
visit_arm = bind walk_arm(e, _, _, _),
|
|
|
|
visit_expr = bind walk_expr(e, _, _, _),
|
|
|
|
visit_ty = bind walk_ty(e, _, _, _),
|
2011-06-10 19:12:42 -07:00
|
|
|
visit_fn = visit_fn_with_scope,
|
|
|
|
visit_constr = bind walk_constr(e, _, _, _)
|
2011-06-09 15:50:26 +02:00
|
|
|
with *visit::default_visitor());
|
|
|
|
visit::visit_crate(*c, cons(scope_crate(c), @nil),
|
|
|
|
visit::vtor(v));
|
|
|
|
|
|
|
|
fn walk_expr(@env e, &@ast::expr exp, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit_expr_with_scope(exp, sc, v);
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (exp.node) {
|
|
|
|
case (ast::expr_path(?p, ?a)) {
|
2011-06-09 15:50:26 +02:00
|
|
|
auto df = lookup_path_strict(*e, sc, exp.span,
|
2011-06-06 20:23:35 +02:00
|
|
|
p.node.idents, ns_value);
|
2011-05-17 11:30:11 -07:00
|
|
|
e.def_map.insert(a.id, df);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-10 19:12:42 -07:00
|
|
|
|
|
|
|
fn walk_constr(@env e, &@ast::constr c, &scopes sc, &vt[scopes] v) {
|
|
|
|
auto new_def = lookup_path_strict(*e, sc, c.span,
|
|
|
|
c.node.path.node.idents,
|
|
|
|
ns_value);
|
|
|
|
e.def_map.insert(c.node.ann.id, new_def);
|
|
|
|
}
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn walk_ty(@env e, &@ast::ty t, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_ty(t, sc, v);
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (t.node) {
|
|
|
|
case (ast::ty_path(?p, ?a)) {
|
2011-06-09 15:50:26 +02:00
|
|
|
auto new_def = lookup_path_strict(*e, sc, t.span,
|
2011-05-13 10:51:36 +02:00
|
|
|
p.node.idents, ns_type);
|
2011-05-17 11:30:11 -07:00
|
|
|
e.def_map.insert(a.id, new_def);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn walk_arm(@env e, &ast::arm a, &scopes sc, &vt[scopes] v) {
|
|
|
|
walk_pat(*e, sc, a.pat);
|
|
|
|
visit_arm_with_scope(a, sc, v);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn walk_pat(&env e, &scopes sc, &@ast::pat pat) {
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (pat.node) {
|
|
|
|
case (ast::pat_tag(?p, ?children, ?a)) {
|
|
|
|
auto fnd = lookup_path_strict(e, sc, p.span, p.node.idents,
|
|
|
|
ns_value);
|
|
|
|
alt (fnd) {
|
|
|
|
case (ast::def_variant(?did, ?vid)) {
|
2011-05-17 11:30:11 -07:00
|
|
|
e.def_map.insert(a.id, fnd);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
e.sess.span_err(p.span, "not a tag variant: " +
|
A revised, improved alias-checker
The old system tried to ensure that the location an alias pointed at
would retain its type. That turned out to not be strong enough in the
face of aliases to the inside of tags.
The new system instead proves that values pointed to by aliases are
not replaced (or invalidated in some other way) at all. It knows of
two sufficient conditions for this, and tries to prove at least of
them:
A) The alias is 'immutably rooted' in a local, and this local is not
reassigned for the lifetime of the alias. Immutably rooted means
the alias refers to the local itself, or to something reachable
from the local through immutable dereferencing.
B) No value whose type might include the type of the 'inner mutable
element' of the thing the alias refers to (for example, the box in
rec(mutable x = @mutable int)) is from the outer scope is accessed
for the lifetime of the alias. This means for functions, no other
argument types may include the alias's inner mutable type. For alt,
for each, and for, it means the body does not refer to any locals
originating from outside their scope that include this type.
The lifetime of an alias in an alt, for each, or for body is defined
as the range from its definition to its last use, not to the point
where it goes out of scope. This makes working around these
restrictions somewhat less annoying. For example, you can assign to
your alt-ed value you don't refer to any bindings afterwards.
2011-06-07 11:20:51 +02:00
|
|
|
ast::path_name(p));
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (@ast::pat child in children) {
|
|
|
|
walk_pat(e, sc, child);
|
|
|
|
}
|
2011-01-13 23:19:42 -05:00
|
|
|
}
|
2011-05-13 10:51:36 +02:00
|
|
|
case (_) {}
|
2011-01-13 23:19:42 -05:00
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-01-18 15:23:11 -05:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
// Visit helper functions
|
2011-05-13 10:51:36 +02:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_item_with_scope(&@ast::item i, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_item(i, cons(scope_item(i), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_native_item_with_scope(&@ast::native_item ni,
|
|
|
|
&scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_native_item(ni, cons(scope_native_item(ni), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_fn_with_scope(&ast::_fn f, &vec[ast::ty_param] tp, &span sp,
|
|
|
|
&ident name, &def_id d_id, &ann a,
|
|
|
|
&scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_fn(f, tp, sp, name, d_id, a,
|
|
|
|
cons(scope_fn(f.decl, tp), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_block_with_scope(&ast::block b, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_block(b, cons(scope_block(b), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_arm_with_scope(&ast::arm a, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_arm(a, cons(scope_arm(a), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_expr_with_scope(&@ast::expr x, &scopes sc, &vt[scopes] v) {
|
|
|
|
auto new_sc = alt (x.node) {
|
2011-05-13 10:51:36 +02:00
|
|
|
case (ast::expr_for(?d, _, _, _)) {
|
2011-06-09 15:50:26 +02:00
|
|
|
cons[scope](scope_loop(d), @sc)
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
case (ast::expr_for_each(?d, _, _, _)) {
|
2011-06-09 15:50:26 +02:00
|
|
|
cons[scope](scope_loop(d), @sc)
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
case (_) { sc }
|
|
|
|
};
|
|
|
|
visit::visit_expr(x, new_sc, v);
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn follow_import(&env e, &scopes sc, vec[ident] path, &span sp)
|
2011-05-23 18:52:55 -07:00
|
|
|
-> def {
|
2011-05-20 15:56:23 -07:00
|
|
|
auto path_len = vec::len(path);
|
|
|
|
auto dcur = lookup_in_scope_strict(e, sc, sp, path.(0), ns_module);
|
|
|
|
auto i = 1u;
|
|
|
|
while (true) {
|
|
|
|
if (i == path_len) { break; }
|
|
|
|
dcur = lookup_in_mod_strict(e, dcur, sp, path.(i),
|
|
|
|
ns_module, outside);
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
|
|
|
|
alt (dcur) {
|
2011-05-23 18:52:55 -07:00
|
|
|
case (ast::def_mod(?def_id)) { ret dcur; }
|
|
|
|
case (ast::def_native_mod(?def_id)) { ret dcur; }
|
2011-05-20 15:56:23 -07:00
|
|
|
case (_) {
|
|
|
|
e.sess.span_err(sp, str::connect(path, "::")
|
|
|
|
+ " does not name a module.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
// Import resolution
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn resolve_import(&env e, &@ast::view_item it, &scopes sc) {
|
2011-05-09 12:40:09 +02:00
|
|
|
auto defid; auto ids;
|
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::view_item_import(_, ?_ids, ?_defid)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
defid = _defid; ids = _ids;
|
2010-10-18 18:19:16 -07:00
|
|
|
}
|
|
|
|
}
|
2011-05-11 13:06:43 +02:00
|
|
|
e.imports.insert(defid._1, resolving(it.span));
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-05-17 20:41:41 +02:00
|
|
|
auto n_idents = vec::len(ids);
|
2011-05-09 12:40:09 +02:00
|
|
|
auto end_id = ids.(n_idents - 1u);
|
|
|
|
|
|
|
|
if (n_idents == 1u) {
|
2011-05-24 20:58:38 +02:00
|
|
|
auto next_sc = std::list::cdr(sc);
|
2011-05-09 12:40:09 +02:00
|
|
|
register(e, defid, it.span, end_id,
|
2011-05-24 20:58:38 +02:00
|
|
|
lookup_in_scope(e, next_sc, it.span, end_id, ns_value),
|
|
|
|
lookup_in_scope(e, next_sc, it.span, end_id, ns_type),
|
|
|
|
lookup_in_scope(e, next_sc, it.span, end_id, ns_module));
|
2011-05-09 12:40:09 +02:00
|
|
|
} else {
|
2011-05-13 16:46:20 +02:00
|
|
|
auto dcur = lookup_in_scope_strict(e, sc, it.span, ids.(0),
|
|
|
|
ns_module);
|
2011-05-09 12:40:09 +02:00
|
|
|
auto i = 1u;
|
|
|
|
while (true) {
|
|
|
|
if (i == n_idents - 1u) {
|
|
|
|
register(e, defid, it.span, end_id,
|
2011-05-23 18:52:55 -07:00
|
|
|
lookup_in_mod(e, dcur, it.span, end_id, ns_value,
|
|
|
|
outside),
|
|
|
|
lookup_in_mod(e, dcur, it.span, end_id, ns_type,
|
|
|
|
outside),
|
|
|
|
lookup_in_mod(e, dcur, it.span, end_id, ns_module,
|
|
|
|
outside));
|
2011-05-09 12:40:09 +02:00
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
dcur = lookup_in_mod_strict(e, dcur, it.span, ids.(i),
|
2011-05-13 16:46:20 +02:00
|
|
|
ns_module, outside);
|
2011-05-09 12:40:09 +02:00
|
|
|
i += 1u;
|
2011-02-07 15:07:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-13 13:34:59 +02:00
|
|
|
fn register(&env e, def_id defid, &span sp, &ident id,
|
2011-05-13 16:46:20 +02:00
|
|
|
&option::t[def] val, &option::t[def] typ,
|
|
|
|
&option::t[def] md) {
|
|
|
|
if (option::is_none(val) && option::is_none(typ) &&
|
|
|
|
option::is_none(md)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
unresolved(e, sp, id, "import");
|
2011-01-01 13:13:00 -05:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
e.imports.insert(defid._1, resolved(val, typ, md));
|
2011-01-01 13:13:00 -05:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-01-01 13:13:00 -05:00
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
// Utilities
|
2011-05-09 12:40:09 +02:00
|
|
|
|
|
|
|
fn ns_name(namespace ns) -> str {
|
|
|
|
alt (ns) {
|
|
|
|
case (ns_type) { ret "typename"; }
|
|
|
|
case (ns_value) { ret "name"; }
|
2011-05-13 16:46:20 +02:00
|
|
|
case (ns_module) { ret "modulename"; }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-05 00:11:17 -04:00
|
|
|
fn unresolved(&env e, &span sp, &ident id, &str kind) -> ! {
|
2011-05-09 12:40:09 +02:00
|
|
|
e.sess.span_err(sp, "unresolved " + kind + ": " + id);
|
|
|
|
}
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
// Lookup helpers
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn lookup_path_strict(&env e, &scopes sc, &span sp, vec[ident] idents,
|
2011-05-12 13:25:18 +02:00
|
|
|
namespace ns) -> def {
|
2011-05-17 20:41:41 +02:00
|
|
|
auto n_idents = vec::len(idents);
|
2011-05-13 16:46:20 +02:00
|
|
|
auto headns = if (n_idents == 1u) { ns } else { ns_module };
|
|
|
|
auto dcur = lookup_in_scope_strict(e, sc, sp, idents.(0), headns);
|
2011-05-12 13:25:18 +02:00
|
|
|
auto i = 1u;
|
|
|
|
while (i < n_idents) {
|
2011-05-13 16:46:20 +02:00
|
|
|
auto curns = if (n_idents == i + 1u) { ns } else { ns_module };
|
|
|
|
dcur = lookup_in_mod_strict(e, dcur, sp, idents.(i), curns, outside);
|
2011-05-12 13:25:18 +02:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret dcur;
|
|
|
|
}
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn lookup_in_scope_strict(&env e, scopes sc, &span sp, &ident id,
|
2011-05-09 12:40:09 +02:00
|
|
|
namespace ns) -> def {
|
2011-05-13 11:57:58 +02:00
|
|
|
alt (lookup_in_scope(e, sc, sp, id, ns)) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (none) {
|
2011-05-09 12:40:09 +02:00
|
|
|
unresolved(e, sp, id, ns_name(ns));
|
|
|
|
}
|
2011-05-31 00:39:19 -04:00
|
|
|
case (some(?d)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret d;
|
2011-03-11 17:10:11 -05:00
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-03-11 17:10:11 -05:00
|
|
|
|
2011-05-13 11:57:58 +02:00
|
|
|
fn scope_is_fn(&scope sc) -> bool {
|
|
|
|
ret alt (sc) {
|
2011-06-09 15:50:26 +02:00
|
|
|
case (scope_fn(_, _)) { true }
|
2011-05-13 11:57:58 +02:00
|
|
|
case (scope_native_item(_)) { true }
|
|
|
|
case (_) { false }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
fn def_is_local(&def d) -> bool {
|
|
|
|
ret alt (d) {
|
|
|
|
case (ast::def_arg(_)) { true }
|
|
|
|
case (ast::def_local(_)) { true }
|
|
|
|
case (ast::def_binding(_)) { true }
|
|
|
|
case (_) { false }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
fn def_is_obj_field(&def d) -> bool {
|
|
|
|
ret alt (d) {
|
|
|
|
case (ast::def_obj_field(_)) { true }
|
|
|
|
case (_) { false }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn lookup_in_scope(&env e, scopes sc, &span sp, &ident id, namespace ns)
|
2011-05-12 17:24:54 +02:00
|
|
|
-> option::t[def] {
|
2011-05-23 18:52:55 -07:00
|
|
|
fn in_scope(&env e, &span sp, &ident id, &scope s, namespace ns)
|
2011-05-12 17:24:54 +02:00
|
|
|
-> option::t[def] {
|
2011-05-25 10:10:30 -07:00
|
|
|
//not recursing through globs
|
|
|
|
|
2010-10-18 14:37:30 -07:00
|
|
|
alt (s) {
|
|
|
|
case (scope_crate(?c)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
auto defid = tup(ast::local_crate, -1);
|
2011-05-26 17:33:33 -07:00
|
|
|
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
|
|
|
case (scope_item(?it)) {
|
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_obj(_, ?ob, ?ty_params, _, _)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret lookup_in_obj(id, ob, ty_params, ns);
|
2010-12-30 15:27:52 -08:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_tag(_, _, ?ty_params, _, _)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_type) {
|
|
|
|
ret lookup_in_ty_params(id, ty_params);
|
2011-02-14 13:36:20 -08:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_mod(_, _, ?defid)) {
|
2011-05-26 17:33:33 -07:00
|
|
|
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_native_mod(_, ?m, ?defid)) {
|
2011-05-26 17:33:33 -07:00
|
|
|
ret lookup_in_local_native_mod(e, defid, sp, id, ns);
|
2011-02-07 15:07:27 -05:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_ty(_, _, ?ty_params, _, _)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_type) {
|
|
|
|
ret lookup_in_ty_params(id, ty_params);
|
2011-01-19 16:13:33 -05:00
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
case (_) {}
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
|
|
|
}
|
2011-02-10 14:32:22 -05:00
|
|
|
case (scope_native_item(?it)) {
|
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::native_item_fn(_, _, ?decl, ?ty_params, _, _)){
|
2011-05-09 12:40:09 +02:00
|
|
|
ret lookup_in_fn(id, decl, ty_params, ns);
|
2011-02-10 14:32:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
case (scope_fn(?decl, ?ty_params)) {
|
|
|
|
ret lookup_in_fn(id, decl, ty_params, ns);
|
|
|
|
}
|
2011-01-20 15:17:26 -08:00
|
|
|
case (scope_loop(?d)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_value) {
|
|
|
|
alt (d.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::decl_local(?local)) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(local.ident, id)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_local(local.id));
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-01-20 15:17:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-10-18 18:19:16 -07:00
|
|
|
case (scope_block(?b)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret lookup_in_block(id, b.node, ns);
|
2010-10-18 18:19:16 -07:00
|
|
|
}
|
2010-12-10 18:08:32 -08:00
|
|
|
case (scope_arm(?a)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_value) {
|
2011-05-11 15:26:36 +02:00
|
|
|
ret lookup_in_pat(id, *a.pat);
|
2010-12-10 18:08:32 -08:00
|
|
|
}
|
|
|
|
}
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
ret none[def];
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
|
|
|
|
2011-05-13 11:57:58 +02:00
|
|
|
auto left_fn = false;
|
|
|
|
// Used to determine whether obj fields are in scope
|
|
|
|
auto left_fn_level2 = false;
|
2011-05-09 12:40:09 +02:00
|
|
|
while (true) {
|
2011-06-06 20:23:35 +02:00
|
|
|
alt ({sc}) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (nil) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret none[def];
|
|
|
|
}
|
2011-05-31 00:39:19 -04:00
|
|
|
case (cons(?hd, ?tl)) {
|
2011-05-23 18:52:55 -07:00
|
|
|
auto fnd = in_scope(e, sp, id, hd, ns);
|
2011-05-13 15:17:24 +02:00
|
|
|
if (!option::is_none(fnd)) {
|
2011-05-13 11:57:58 +02:00
|
|
|
auto df = option::get(fnd);
|
|
|
|
if ((left_fn && def_is_local(df)) ||
|
|
|
|
(left_fn_level2 && def_is_obj_field(df))) {
|
2011-05-13 13:34:59 +02:00
|
|
|
e.sess.span_err
|
|
|
|
(sp, "attempted dynamic environment-capture");
|
2011-05-13 11:57:58 +02:00
|
|
|
}
|
|
|
|
ret fnd;
|
|
|
|
}
|
|
|
|
if (left_fn) { left_fn_level2 = true; }
|
|
|
|
if (ns == ns_value && !left_fn) {
|
|
|
|
left_fn = scope_is_fn(hd);
|
2011-01-17 16:17:09 -05:00
|
|
|
}
|
2011-05-13 11:57:58 +02:00
|
|
|
sc = *tl;
|
2011-01-17 16:17:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-20 14:17:59 -07:00
|
|
|
e.sess.bug("reached unreachable code in lookup_in_scope"); // sigh
|
2010-10-18 16:15:25 -07:00
|
|
|
}
|
|
|
|
|
2011-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_ty_params(&ident id, &vec[ast::ty_param] ty_params)
|
2011-05-12 17:24:54 +02:00
|
|
|
-> option::t[def] {
|
2011-05-09 12:40:09 +02:00
|
|
|
auto i = 0u;
|
2011-05-12 17:24:54 +02:00
|
|
|
for (ast::ty_param tp in ty_params) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(tp, id)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_ty_arg(i));
|
2010-12-12 16:47:37 -08:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
i += 1u;
|
2010-12-12 16:47:37 -08:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
ret none[def];
|
|
|
|
}
|
2010-12-12 16:47:37 -08:00
|
|
|
|
2011-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_pat(&ident id, &ast::pat pat) -> option::t[def] {
|
2011-05-11 15:26:36 +02:00
|
|
|
alt (pat.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::pat_bind(?name, ?defid, _)) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(name, id)) { ret some(ast::def_binding(defid)); }
|
2011-05-11 15:26:36 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::pat_wild(_)) {}
|
|
|
|
case (ast::pat_lit(_, _)) {}
|
|
|
|
case (ast::pat_tag(_, ?pats, _)) {
|
|
|
|
for (@ast::pat p in pats) {
|
2011-05-11 15:26:36 +02:00
|
|
|
auto found = lookup_in_pat(id, *p);
|
2011-05-13 15:17:24 +02:00
|
|
|
if (!option::is_none(found)) { ret found; }
|
2011-05-11 15:26:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret none[def];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_fn(&ident id, &ast::fn_decl decl, &vec[ast::ty_param] ty_params,
|
2011-05-12 17:24:54 +02:00
|
|
|
namespace ns) -> option::t[def] {
|
2011-05-13 16:46:20 +02:00
|
|
|
alt (ns) {
|
|
|
|
case (ns_value) {
|
|
|
|
for (ast::arg a in decl.inputs) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(a.ident, id)) {
|
2011-05-13 16:46:20 +02:00
|
|
|
ret some(ast::def_arg(a.id));
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
ret none[def];
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
case (ns_type) {
|
|
|
|
ret lookup_in_ty_params(id, ty_params);
|
|
|
|
}
|
|
|
|
case (_) { ret none[def]; }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2010-12-12 16:47:37 -08:00
|
|
|
}
|
|
|
|
|
2011-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_obj(&ident id, &ast::_obj ob, &vec[ast::ty_param] ty_params,
|
2011-05-12 17:24:54 +02:00
|
|
|
namespace ns) -> option::t[def] {
|
2011-05-13 16:46:20 +02:00
|
|
|
alt (ns) {
|
|
|
|
case (ns_value) {
|
|
|
|
for (ast::obj_field f in ob.fields) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(f.ident, id)) {
|
2011-05-13 16:46:20 +02:00
|
|
|
ret some(ast::def_obj_field(f.id));
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
ret none[def];
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
case (ns_type) {
|
|
|
|
ret lookup_in_ty_params(id, ty_params);
|
|
|
|
}
|
|
|
|
case (_) { ret none[def]; }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
2011-01-13 17:42:28 -08:00
|
|
|
|
2011-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_block(&ident id, &ast::block_ b, namespace ns)
|
2011-05-12 17:24:54 +02:00
|
|
|
-> option::t[def] {
|
|
|
|
for (@ast::stmt st in b.stmts) {
|
2011-05-11 15:10:24 +02:00
|
|
|
alt (st.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::stmt_decl(?d,_)) {
|
2011-05-11 15:10:24 +02:00
|
|
|
alt (d.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::decl_local(?loc)) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (ns == ns_value && str::eq(id, loc.ident)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_local(loc.id));
|
2011-05-11 15:10:24 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::decl_item(?it)) {
|
2011-05-11 15:10:24 +02:00
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_tag(?name, ?variants, _,
|
2011-05-11 15:10:24 +02:00
|
|
|
?defid, _)) {
|
|
|
|
if (ns == ns_type) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(name, id)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_ty(defid));
|
2011-05-11 15:10:24 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
} else if (ns == ns_value) {
|
2011-05-12 17:24:54 +02:00
|
|
|
for (ast::variant v in variants) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(v.node.name, id)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_variant(
|
2011-05-11 15:10:24 +02:00
|
|
|
defid, v.node.id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {
|
2011-05-17 20:41:41 +02:00
|
|
|
if (str::eq(ast::item_ident(it), id)) {
|
2011-05-11 15:10:24 +02:00
|
|
|
auto found = found_def_item(it, ns);
|
2011-05-13 16:46:20 +02:00
|
|
|
if (!option::is_none(found)) {ret found;}
|
2011-05-11 15:10:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-11 15:10:24 +02:00
|
|
|
case (_) {}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ret none[def];
|
|
|
|
}
|
2010-10-18 14:37:30 -07:00
|
|
|
|
2011-05-19 21:46:51 +02:00
|
|
|
fn found_def_item(&@ast::item i, namespace ns) -> option::t[def] {
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (i.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_const(_, _, _, ?defid, _)) {
|
|
|
|
if (ns == ns_value) { ret some(ast::def_const(defid)); }
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_fn(_, _, _, ?defid, _)) {
|
|
|
|
if (ns == ns_value) { ret some(ast::def_fn(defid)); }
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_mod(_, _, ?defid)) {
|
2011-05-13 16:46:20 +02:00
|
|
|
if (ns == ns_module) { ret some(ast::def_mod(defid)); }
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_native_mod(_, _, ?defid)) {
|
2011-05-13 16:46:20 +02:00
|
|
|
if (ns == ns_module) { ret some(ast::def_native_mod(defid)); }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_ty(_, _, _, ?defid, _)) {
|
|
|
|
if (ns == ns_type) { ret some(ast::def_ty(defid)); }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_tag(_, _, _, ?defid, _)) {
|
|
|
|
if (ns == ns_type) { ret some(ast::def_ty(defid)); }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_obj(_, _, _, ?odid, _)) {
|
2011-05-13 16:46:20 +02:00
|
|
|
alt (ns) {
|
|
|
|
case (ns_value) { ret some(ast::def_obj(odid.ctor)); }
|
|
|
|
case (ns_type) { ret some(ast::def_obj(odid.ty)); }
|
|
|
|
case (_) { }
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
case (_) { }
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
ret none[def];
|
2010-10-07 18:34:22 -07:00
|
|
|
}
|
|
|
|
|
2011-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_mod_strict(&env e, def m, &span sp, &ident id,
|
2011-05-09 12:40:09 +02:00
|
|
|
namespace ns, dir dr) -> def {
|
2011-05-23 18:52:55 -07:00
|
|
|
alt (lookup_in_mod(e, m, sp, id, ns, dr)) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (none) {
|
2011-05-09 12:40:09 +02:00
|
|
|
unresolved(e, sp, id, ns_name(ns));
|
|
|
|
}
|
2011-05-31 00:39:19 -04:00
|
|
|
case (some(?d)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret d;
|
|
|
|
}
|
|
|
|
}
|
2011-03-29 17:01:27 -07:00
|
|
|
}
|
|
|
|
|
2011-05-23 18:52:55 -07:00
|
|
|
fn lookup_in_mod(&env e, def m, &span sp, &ident id, namespace ns, dir dr)
|
2011-05-12 17:24:54 +02:00
|
|
|
-> option::t[def] {
|
2011-05-26 17:33:33 -07:00
|
|
|
auto defid = ast::def_id_of_def(m);
|
|
|
|
if (defid._0 != ast::local_crate) {
|
|
|
|
// examining a module in an external crate
|
|
|
|
auto cached = e.ext_cache.find(tup(defid,id,ns));
|
|
|
|
if (!option::is_none(cached)) { ret cached; }
|
|
|
|
auto path = [id];
|
|
|
|
if (defid._1 != -1) {
|
|
|
|
path = e.ext_map.get(defid) + path;
|
|
|
|
}
|
|
|
|
auto fnd = lookup_external(e, defid._0, path, ns);
|
|
|
|
if (!option::is_none(fnd)) {
|
|
|
|
e.ext_cache.insert(tup(defid,id,ns), option::get(fnd));
|
|
|
|
}
|
|
|
|
ret fnd;
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (m) {
|
2011-05-26 17:33:33 -07:00
|
|
|
case (ast::def_mod(?defid)) {
|
|
|
|
ret lookup_in_local_mod(e, defid, sp, id, ns, dr);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-26 17:33:33 -07:00
|
|
|
case (ast::def_native_mod(?defid)) {
|
|
|
|
ret lookup_in_local_native_mod(e, defid, sp, id, ns);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
|
|
|
|
2011-05-12 17:24:54 +02:00
|
|
|
fn found_view_item(&env e, @ast::view_item vi, namespace ns)
|
|
|
|
-> option::t[def] {
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (vi.node) {
|
2011-05-26 17:16:54 -07:00
|
|
|
case (ast::view_item_use(_, _, _, ?ann)) {
|
|
|
|
ret some(ast::def_mod(tup(e.crate_map.get(ann.id), -1)));
|
2011-01-20 15:17:26 -08:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::view_item_import(_, _, ?defid)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret lookup_import(e, defid, ns);
|
2011-02-14 18:17:31 -08:00
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
case (ast::view_item_import_glob(_, ?defid)) {
|
2011-05-23 18:52:55 -07:00
|
|
|
ret none[def]; //will be handled in the fallback glob pass
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
2011-01-20 15:17:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
fn lookup_import(&env e, def_id defid, namespace ns) -> option::t[def] {
|
|
|
|
alt (e.imports.get(defid._1)) {
|
|
|
|
case (todo(?item, ?sc)) {
|
|
|
|
resolve_import(e, item, sc);
|
|
|
|
ret lookup_import(e, defid, ns);
|
|
|
|
}
|
|
|
|
case (resolving(?sp)) {
|
2011-05-24 20:58:38 +02:00
|
|
|
e.sess.span_err(sp, "cyclic import");
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
case (resolved(?val, ?typ, ?md)) {
|
2011-05-13 10:51:36 +02:00
|
|
|
ret alt (ns) { case (ns_value) { val }
|
2011-05-13 16:46:20 +02:00
|
|
|
case (ns_type) { typ }
|
|
|
|
case (ns_module) { md } };
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-25 10:10:30 -07:00
|
|
|
|
2011-05-26 17:33:33 -07:00
|
|
|
fn lookup_in_local_native_mod(&env e, def_id defid, &span sp,
|
2011-05-25 10:10:30 -07:00
|
|
|
&ident id, namespace ns) -> option::t[def] {
|
2011-05-26 17:33:33 -07:00
|
|
|
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
|
2011-05-25 10:10:30 -07:00
|
|
|
}
|
|
|
|
|
2011-05-26 17:33:33 -07:00
|
|
|
fn lookup_in_local_mod(&env e, def_id defid, &span sp,
|
2011-05-25 10:10:30 -07:00
|
|
|
&ident id, namespace ns, dir dr) -> option::t[def] {
|
2011-05-11 16:30:48 +02:00
|
|
|
auto info = e.mod_map.get(defid._1);
|
2011-06-10 12:02:57 +02:00
|
|
|
if (dr == outside && !ast::is_exported(id, option::get(info.m))) {
|
2011-05-26 17:33:33 -07:00
|
|
|
// if we're in a native mod, then dr==inside, so info.m is some _mod
|
|
|
|
ret none[def]; // name is not visible
|
2011-06-10 12:02:57 +02:00
|
|
|
}
|
2011-05-23 18:52:55 -07:00
|
|
|
alt(info.index.find(id)) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (none) { }
|
2011-06-10 12:02:57 +02:00
|
|
|
case (some(?lst_)) {
|
|
|
|
auto lst = lst_;
|
2011-05-23 18:52:55 -07:00
|
|
|
while (true) {
|
2011-06-10 12:02:57 +02:00
|
|
|
alt (lst) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (nil) { break; }
|
|
|
|
case (cons(?hd, ?tl)) {
|
2011-05-23 18:52:55 -07:00
|
|
|
auto found = lookup_in_mie(e, hd, ns);
|
|
|
|
if (!option::is_none(found)) { ret found; }
|
|
|
|
lst = *tl;
|
|
|
|
}
|
|
|
|
}
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-23 18:52:55 -07:00
|
|
|
// not local or explicitly imported; try globs:
|
2011-05-26 17:33:33 -07:00
|
|
|
ret lookup_glob_in_mod(e, info, sp, id, ns, dr);
|
2011-05-23 18:52:55 -07:00
|
|
|
}
|
|
|
|
|
2011-05-26 17:33:33 -07:00
|
|
|
fn lookup_glob_in_mod(&env e, @indexed_mod info, &span sp,
|
|
|
|
&ident id, namespace wanted_ns, dir dr)
|
|
|
|
-> option::t[def] {
|
|
|
|
fn per_ns(&env e, @indexed_mod info, &span sp, &ident id,
|
|
|
|
namespace ns, dir dr) -> option::t[def] {
|
|
|
|
fn l_i_m_r(&env e, &def m, &span sp, &ident id,
|
|
|
|
namespace ns, dir dr) -> option::t[def] {
|
|
|
|
be lookup_in_mod(e, m, sp, id, ns, dr);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto matches = vec::filter_map[def, def]
|
|
|
|
(bind l_i_m_r(e, _, sp, id, ns, dr),
|
|
|
|
info.glob_imports);
|
|
|
|
if (vec::len(matches) == 0u) {
|
|
|
|
ret none[def];
|
|
|
|
} else if (vec::len(matches) == 1u){
|
|
|
|
ret some[def](matches.(0));
|
|
|
|
} else {
|
|
|
|
for (def match in matches) {
|
2011-06-09 10:02:48 -07:00
|
|
|
alt (e.ast_map.find(ast::def_id_of_def(match))) {
|
|
|
|
case (some(?it)) {
|
|
|
|
e.sess.span_note(it.span,
|
|
|
|
"'" + id + "' is defined here.");
|
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
e.sess.bug("Internal error: imports and matches "
|
|
|
|
+ "don't agree");
|
|
|
|
}
|
|
|
|
}
|
2011-05-26 17:33:33 -07:00
|
|
|
}
|
|
|
|
e.sess.span_err(sp, "'" + id + "' is glob-imported from" +
|
|
|
|
" multiple different modules.");
|
|
|
|
}
|
2011-05-23 18:52:55 -07:00
|
|
|
}
|
2011-05-26 17:33:33 -07:00
|
|
|
// since we don't know what names we have in advance,
|
|
|
|
// absence takes the place of todo()
|
|
|
|
if(!info.glob_imported_names.contains_key(id)) {
|
|
|
|
info.glob_imported_names.insert(id, resolving(sp));
|
|
|
|
auto val = per_ns(e, info, sp, id, ns_value, dr);
|
|
|
|
auto typ = per_ns(e, info, sp, id, ns_type, dr);
|
|
|
|
auto md = per_ns(e, info, sp, id, ns_module, dr);
|
|
|
|
info.glob_imported_names.insert(id, resolved(val, typ, md));
|
|
|
|
}
|
|
|
|
alt (info.glob_imported_names.get(id)) {
|
|
|
|
case (todo(_,_)) { e.sess.bug("Shouldn't've put a todo in."); }
|
|
|
|
case (resolving(?sp)) {
|
|
|
|
ret none[def]; //circularity is okay in import globs
|
|
|
|
}
|
|
|
|
case (resolved(?val, ?typ, ?md)) {
|
|
|
|
ret alt (wanted_ns) { case (ns_value) { val }
|
|
|
|
case (ns_type) { typ }
|
|
|
|
case (ns_module) { md } };
|
2011-05-25 11:55:48 -07:00
|
|
|
}
|
2011-05-23 18:52:55 -07:00
|
|
|
}
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn lookup_in_mie(&env e, &mod_index_entry mie, namespace ns)
|
|
|
|
-> option::t[def] {
|
|
|
|
alt (mie) {
|
2011-05-11 16:30:48 +02:00
|
|
|
case (mie_view_item(?view_item)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret found_view_item(e, view_item, ns);
|
|
|
|
}
|
2011-05-11 16:30:48 +02:00
|
|
|
case (mie_item(?item)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret found_def_item(item, ns);
|
|
|
|
}
|
2011-05-11 16:30:48 +02:00
|
|
|
case (mie_tag_variant(?item, ?variant_idx)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (item.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_tag(_, ?variants, _, ?tid, _)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_value) {
|
|
|
|
auto vid = variants.(variant_idx).node.id;
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_variant(tid, vid));
|
2011-05-09 12:40:09 +02:00
|
|
|
} else {
|
|
|
|
ret none[def];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
2011-05-19 11:37:17 -07:00
|
|
|
case (mie_native_item(?native_item)) {
|
|
|
|
alt (native_item.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::native_item_ty(_, ?id)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_type) {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_native_ty(id));
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::native_item_fn(_, _, _, _, ?id, _)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_value) {
|
2011-05-12 17:24:54 +02:00
|
|
|
ret some(ast::def_native_fn(id));
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
|
|
|
ret none[def];
|
2011-01-18 15:23:11 -05:00
|
|
|
}
|
|
|
|
|
2011-05-19 11:37:17 -07:00
|
|
|
|
|
|
|
|
2011-05-11 16:30:48 +02:00
|
|
|
// Module indexing
|
|
|
|
|
2011-05-20 15:56:23 -07:00
|
|
|
fn add_to_index(&hashmap[ident,list[mod_index_entry]] index, &ident id,
|
|
|
|
&mod_index_entry ent) {
|
2011-05-13 13:34:59 +02:00
|
|
|
alt (index.find(id)) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (none) {
|
2011-05-20 15:56:23 -07:00
|
|
|
index.insert(id, cons(ent, @nil[mod_index_entry]));
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
2011-05-31 00:39:19 -04:00
|
|
|
case (some(?prev)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
index.insert(id, cons(ent, @prev));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-12 17:24:54 +02:00
|
|
|
fn index_mod(&ast::_mod md) -> mod_index {
|
2011-05-13 13:34:59 +02:00
|
|
|
auto index = new_str_hash[list[mod_index_entry]]();
|
2011-05-11 16:30:48 +02:00
|
|
|
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::view_item it in md.view_items) {
|
2011-05-11 16:30:48 +02:00
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case(ast::view_item_use(?id, _, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_view_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case(ast::view_item_import(?def_ident,_,_)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, def_ident, mie_view_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-25 10:10:30 -07:00
|
|
|
//globbed imports have to be resolved lazily.
|
|
|
|
case(ast::view_item_import_glob(_,_)) {}
|
2011-05-12 17:24:54 +02:00
|
|
|
case(ast::view_item_export(_)) {}
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::item it in md.items) {
|
2011-05-11 16:30:48 +02:00
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_const(?id, _, _, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_fn(?id, _, _, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_mod(?id, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_native_mod(?id, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_ty(?id, _, _, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_tag(?id, ?variants, _, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
let uint variant_idx = 0u;
|
2011-05-12 17:24:54 +02:00
|
|
|
for (ast::variant v in variants) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, v.node.name,
|
|
|
|
mie_tag_variant(it, variant_idx));
|
2011-05-11 16:30:48 +02:00
|
|
|
variant_idx += 1u;
|
|
|
|
}
|
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::item_obj(?id, _, _, _, _)) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, id, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret index;
|
|
|
|
}
|
|
|
|
|
2011-05-19 11:37:17 -07:00
|
|
|
fn index_nmod(&ast::native_mod md) -> mod_index {
|
|
|
|
auto index = new_str_hash[list[mod_index_entry]]();
|
2011-05-11 16:30:48 +02:00
|
|
|
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::view_item it in md.view_items) {
|
2011-05-11 16:30:48 +02:00
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case(ast::view_item_import(?def_ident,_,_)) {
|
2011-05-19 11:37:17 -07:00
|
|
|
add_to_index(index, def_ident, mie_view_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-25 10:10:30 -07:00
|
|
|
case(ast::view_item_import_glob(_,_)) {}
|
2011-05-12 17:24:54 +02:00
|
|
|
case(ast::view_item_export(_)) {}
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::native_item it in md.items) {
|
2011-05-11 16:30:48 +02:00
|
|
|
alt (it.node) {
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::native_item_ty(?id, _)) {
|
2011-05-19 11:37:17 -07:00
|
|
|
add_to_index(index, id, mie_native_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::native_item_fn(?id, _, _, _, _, _)) {
|
2011-05-19 11:37:17 -07:00
|
|
|
add_to_index(index, id, mie_native_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret index;
|
|
|
|
}
|
|
|
|
|
|
|
|
// External lookups
|
|
|
|
|
2011-05-13 16:46:20 +02:00
|
|
|
fn ns_for_def(def d) -> namespace {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret alt (d) {
|
2011-05-13 16:46:20 +02:00
|
|
|
case (ast::def_fn(?id)) { ns_value }
|
|
|
|
case (ast::def_obj(?id)) { ns_value }
|
|
|
|
case (ast::def_obj_field(?id)) { ns_value }
|
|
|
|
case (ast::def_mod(?id)) { ns_module }
|
|
|
|
case (ast::def_native_mod(?id)) { ns_module }
|
|
|
|
case (ast::def_const(?id)) { ns_value }
|
|
|
|
case (ast::def_arg(?id)) { ns_value }
|
|
|
|
case (ast::def_local(?id)) { ns_value }
|
|
|
|
case (ast::def_variant(_, ?id)) { ns_value }
|
|
|
|
case (ast::def_ty(?id)) { ns_type }
|
|
|
|
case (ast::def_binding(?id)) { ns_type }
|
|
|
|
case (ast::def_use(?id)) { ns_module }
|
|
|
|
case (ast::def_native_ty(?id)) { ns_type }
|
|
|
|
case (ast::def_native_fn(?id)) { ns_value }
|
2011-05-09 12:40:09 +02:00
|
|
|
};
|
2010-10-07 18:34:22 -07:00
|
|
|
}
|
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
fn lookup_external(&env e, int cnum, vec[ident] ids, namespace ns)
|
2011-05-12 17:24:54 +02:00
|
|
|
-> option::t[def] {
|
2011-05-13 15:17:24 +02:00
|
|
|
for (def d in creader::lookup_defs(e.sess, cnum, ids)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
e.ext_map.insert(ast::def_id_of_def(d), ids);
|
2011-05-13 16:46:20 +02:00
|
|
|
if (ns == ns_for_def(d)) { ret some(d); }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 15:17:24 +02:00
|
|
|
ret none[def];
|
2011-05-11 12:21:09 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-05-18 22:23:19 +02:00
|
|
|
// Collision detection
|
|
|
|
|
|
|
|
fn check_for_collisions(&@env e, &ast::crate c) {
|
2011-05-19 21:46:51 +02:00
|
|
|
// Module indices make checking those relatively simple -- just check each
|
|
|
|
// name for multiple entities in the same namespace.
|
2011-05-18 22:23:19 +02:00
|
|
|
for each (@tup(ast::def_num, @indexed_mod) m in e.mod_map.items()) {
|
|
|
|
for each (@tup(ident, list[mod_index_entry]) name in
|
|
|
|
m._1.index.items()) {
|
2011-05-19 11:37:17 -07:00
|
|
|
check_mod_name(*e, name._0, name._1);
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
2011-05-19 21:46:51 +02:00
|
|
|
|
|
|
|
// Other scopes have to be checked the hard way.
|
2011-06-09 15:50:26 +02:00
|
|
|
auto v = @rec(visit_item = bind check_item(e, _, _, _),
|
|
|
|
visit_block = bind check_block(e, _, _, _),
|
|
|
|
visit_arm = bind check_arm(e, _, _, _)
|
|
|
|
with *visit::default_visitor());
|
|
|
|
visit::visit_crate(c, (), visit::vtor(v));
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
|
2011-06-10 12:02:57 +02:00
|
|
|
fn check_mod_name(&env e, &ident name, list[mod_index_entry] entries) {
|
2011-05-18 22:23:19 +02:00
|
|
|
auto saw_mod = false; auto saw_type = false; auto saw_value = false;
|
|
|
|
|
|
|
|
fn dup(&env e, &span sp, &str word, &ident name) {
|
|
|
|
e.sess.span_err(sp, "duplicate definition of " + word + name);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (true) {
|
2011-06-10 12:02:57 +02:00
|
|
|
alt (entries) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (cons(?entry, ?rest)) {
|
2011-05-19 11:37:17 -07:00
|
|
|
if (!option::is_none(lookup_in_mie(e, entry, ns_value))) {
|
|
|
|
if (saw_value) { dup(e, mie_span(entry), "", name); }
|
2011-05-18 22:23:19 +02:00
|
|
|
else { saw_value = true; }
|
|
|
|
}
|
2011-05-19 11:37:17 -07:00
|
|
|
if (!option::is_none(lookup_in_mie(e, entry, ns_type))) {
|
|
|
|
if (saw_type) { dup(e, mie_span(entry), "type ", name); }
|
2011-05-18 22:23:19 +02:00
|
|
|
else { saw_type = true; }
|
|
|
|
}
|
2011-05-19 11:37:17 -07:00
|
|
|
if (!option::is_none(lookup_in_mie(e, entry, ns_module))) {
|
|
|
|
if (saw_mod) { dup(e, mie_span(entry), "module ", name); }
|
2011-05-18 22:23:19 +02:00
|
|
|
else { saw_mod = true; }
|
|
|
|
}
|
|
|
|
entries = *rest;
|
|
|
|
}
|
2011-05-31 00:39:19 -04:00
|
|
|
case (nil) { break; }
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn mie_span(&mod_index_entry mie) -> span {
|
|
|
|
alt (mie) {
|
|
|
|
case (mie_view_item(?item)) { ret item.span; }
|
|
|
|
case (mie_item(?item)) { ret item.span; }
|
|
|
|
case (mie_tag_variant(?item, _)) { ret item.span; }
|
2011-05-19 11:37:17 -07:00
|
|
|
case (mie_native_item(?item)) { ret item.span; }
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn check_item(@env e, &@ast::item i, &() x, &vt[()] v) {
|
|
|
|
visit::visit_item(i, x, v);
|
2011-05-19 21:46:51 +02:00
|
|
|
alt (i.node) {
|
|
|
|
case (ast::item_fn(_, ?f, ?ty_params, _, _)) {
|
|
|
|
check_fn(*e, i.span, f);
|
|
|
|
ensure_unique(*e, i.span, ty_params, ident_id, "type parameter");
|
|
|
|
}
|
|
|
|
case (ast::item_obj(_, ?ob, ?ty_params, _, _)) {
|
|
|
|
fn field_name(&ast::obj_field field) -> ident {
|
|
|
|
ret field.ident;
|
|
|
|
}
|
|
|
|
ensure_unique(*e, i.span, ob.fields, field_name, "object field");
|
|
|
|
for (@ast::method m in ob.methods) {
|
|
|
|
check_fn(*e, m.span, m.node.meth);
|
|
|
|
}
|
|
|
|
ensure_unique(*e, i.span, ty_params, ident_id, "type parameter");
|
|
|
|
}
|
|
|
|
case (ast::item_tag(_, _, ?ty_params, _, _)) {
|
|
|
|
ensure_unique(*e, i.span, ty_params, ident_id, "type parameter");
|
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn check_arm(@env e, &ast::arm a, &() x, &vt[()] v) {
|
|
|
|
visit::visit_arm(a, x, v);
|
2011-05-19 21:46:51 +02:00
|
|
|
fn walk_pat(checker ch, &@ast::pat p) {
|
|
|
|
alt (p.node) {
|
|
|
|
case (ast::pat_bind(?name, _, _)) {
|
|
|
|
add_name(ch, p.span, name);
|
|
|
|
}
|
|
|
|
case (ast::pat_tag(_, ?children, _)) {
|
|
|
|
for (@ast::pat child in children) {
|
|
|
|
walk_pat(ch, child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
walk_pat(checker(*e, "binding"), a.pat);
|
|
|
|
}
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn check_block(@env e, &ast::block b, &() x, &vt[()] v) {
|
|
|
|
visit::visit_block(b, x, v);
|
|
|
|
|
2011-05-19 21:46:51 +02:00
|
|
|
auto values = checker(*e, "value");
|
|
|
|
auto types = checker(*e, "type");
|
|
|
|
auto mods = checker(*e, "module");
|
|
|
|
|
|
|
|
for (@ast::stmt st in b.node.stmts) {
|
|
|
|
alt (st.node) {
|
|
|
|
case (ast::stmt_decl(?d,_)) {
|
|
|
|
alt (d.node) {
|
|
|
|
case (ast::decl_local(?loc)) {
|
|
|
|
add_name(values, d.span, loc.ident);
|
|
|
|
}
|
|
|
|
case (ast::decl_item(?it)) {
|
|
|
|
alt (it.node) {
|
|
|
|
case (ast::item_tag(?name, ?variants, _, _, _)) {
|
|
|
|
add_name(types, it.span, name);
|
|
|
|
for (ast::variant v in variants) {
|
|
|
|
add_name(values, v.span, v.node.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ast::item_const(?name, _, _, _, _)) {
|
|
|
|
add_name(values, it.span, name);
|
|
|
|
}
|
|
|
|
case (ast::item_fn(?name, _, _, _, _)) {
|
|
|
|
add_name(values, it.span, name);
|
|
|
|
}
|
|
|
|
case (ast::item_mod(?name, _, _)) {
|
|
|
|
add_name(mods, it.span, name);
|
|
|
|
}
|
|
|
|
case (ast::item_native_mod(?name, _, _)) {
|
|
|
|
add_name(mods, it.span, name);
|
|
|
|
}
|
|
|
|
case (ast::item_ty(?name, _, _, _, _)) {
|
|
|
|
add_name(types, it.span, name);
|
|
|
|
}
|
|
|
|
case (ast::item_obj(?name, _, _, _, _)) {
|
|
|
|
add_name(types, it.span, name);
|
|
|
|
add_name(values, it.span, name);
|
|
|
|
}
|
|
|
|
case (_) { }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_fn(&env e, &span sp, &ast::_fn f) {
|
|
|
|
fn arg_name(&ast::arg a) -> ident {
|
|
|
|
ret a.ident;
|
|
|
|
}
|
|
|
|
ensure_unique(e, sp, f.decl.inputs, arg_name, "argument");
|
|
|
|
}
|
|
|
|
|
|
|
|
type checker = @rec(mutable vec[ident] seen,
|
|
|
|
str kind,
|
|
|
|
session sess);
|
|
|
|
fn checker(&env e, str kind) -> checker {
|
|
|
|
let vec[ident] seen = [];
|
|
|
|
ret @rec(mutable seen=seen, kind=kind, sess=e.sess);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_name(&checker ch, &span sp, &ident id) {
|
|
|
|
for (ident s in ch.seen) {
|
|
|
|
if (str::eq(s, id)) {
|
|
|
|
ch.sess.span_err(sp, "duplicate " + ch.kind + " name: " + id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vec::push(ch.seen, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ident_id(&ident i) -> ident { ret i; }
|
|
|
|
|
|
|
|
fn ensure_unique[T](&env e, &span sp, &vec[T] elts, fn (&T) -> ident id,
|
|
|
|
&str kind) {
|
|
|
|
auto ch = checker(e, kind);
|
|
|
|
for (T elt in elts) {
|
|
|
|
add_name(ch, sp, id(elt));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-07 18:34:22 -07:00
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
2011-03-25 15:07:27 -07:00
|
|
|
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
2010-10-07 18:34:22 -07:00
|
|
|
// End:
|