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-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);
|
|
|
|
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-05-09 12:40:09 +02:00
|
|
|
tag import_state {
|
2011-05-26 17:33:33 -07:00
|
|
|
todo(@ast::view_item, list[scope]); // 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-05-09 12:40:09 +02:00
|
|
|
map_crate(e, *crate);
|
|
|
|
resolve_imports(*e);
|
2011-05-18 22:23:19 +02:00
|
|
|
check_for_collisions(e, *crate);
|
2011-05-13 10:51:36 +02:00
|
|
|
resolve_names(e, *crate);
|
|
|
|
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-05-12 17:24:54 +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-05-09 12:40:09 +02:00
|
|
|
auto cell = @mutable nil[scope];
|
2011-05-20 15:56:23 -07:00
|
|
|
auto index_names =
|
|
|
|
rec(visit_crate_pre = bind push_env_for_crate(cell, _),
|
|
|
|
visit_crate_post = bind pop_env_for_crate(cell, _),
|
|
|
|
visit_view_item_pre = bind index_vi(e, cell, _),
|
|
|
|
visit_item_pre = bind index_i(e, cell, _),
|
|
|
|
visit_item_post = bind pop_env_for_item(cell, _)
|
|
|
|
with walk::default_visitor());
|
2011-05-11 16:30:48 +02:00
|
|
|
// 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-20 15:56:23 -07:00
|
|
|
walk::walk_crate(index_names, c);
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-05-20 15:56:23 -07:00
|
|
|
fn index_vi(@env e, @mutable list[scope] sc, &@ast::view_item i) {
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (i.node) {
|
|
|
|
case (ast::view_item_import(_, ?ids, ?defid)) {
|
2011-06-06 20:23:35 +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-05-20 15:56:23 -07:00
|
|
|
fn index_i(@env e, @mutable list[scope] sc, &@ast::item i) {
|
2011-05-13 10:51:36 +02:00
|
|
|
push_env_for_item(sc, i);
|
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.
|
|
|
|
cell = @mutable nil[scope];
|
2011-05-25 10:10:30 -07:00
|
|
|
auto link_globs =
|
2011-05-20 15:56:23 -07:00
|
|
|
rec(visit_crate_pre = bind push_env_for_crate(cell, _),
|
|
|
|
visit_crate_post = bind pop_env_for_crate(cell, _),
|
2011-05-25 10:10:30 -07:00
|
|
|
visit_view_item_pre = bind link_glob(e, cell, _),
|
|
|
|
visit_item_pre = bind push_env_for_item(cell, _),
|
2011-05-20 15:56:23 -07:00
|
|
|
visit_item_post = bind pop_env_for_item(cell, _)
|
|
|
|
with walk::default_visitor());
|
|
|
|
walk::walk_crate(link_globs, c);
|
2011-05-25 10:10:30 -07:00
|
|
|
|
|
|
|
fn link_glob(@env e, @mutable list[scope] sc, &@ast::view_item vi) {
|
|
|
|
fn find_mod(@env e, list[scope] sc) -> @indexed_mod {
|
|
|
|
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-05-25 10:10:30 -07:00
|
|
|
find_mod(e, *sc).glob_imports
|
2011-06-06 20:23:35 +02:00
|
|
|
+= [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-05-13 10:51:36 +02:00
|
|
|
fn resolve_names(&@env e, &ast::crate c) {
|
|
|
|
auto cell = @mutable nil[scope];
|
|
|
|
auto v = rec(visit_crate_pre = bind push_env_for_crate(cell, _),
|
|
|
|
visit_crate_post = bind pop_env_for_crate(cell, _),
|
|
|
|
visit_item_pre = bind push_env_for_item(cell, _),
|
|
|
|
visit_item_post = bind pop_env_for_item(cell, _),
|
|
|
|
visit_method_pre = bind push_env_for_method(cell, _),
|
|
|
|
visit_method_post = bind pop_env_for_method(cell, _),
|
|
|
|
visit_native_item_pre = bind push_env_for_n_item(cell, _),
|
|
|
|
visit_native_item_post = bind pop_env_for_n_item(cell, _),
|
|
|
|
visit_block_pre = bind push_env_for_block(cell, _),
|
|
|
|
visit_block_post = bind pop_env_for_block(cell, _),
|
|
|
|
visit_arm_pre = bind walk_arm(e, cell, _),
|
|
|
|
visit_arm_post = bind pop_env_for_arm(cell, _),
|
|
|
|
visit_expr_pre = bind walk_expr(e, cell, _),
|
|
|
|
visit_expr_post = bind pop_env_for_expr(cell, _),
|
|
|
|
visit_ty_pre = bind walk_ty(e, cell, _)
|
|
|
|
with walk::default_visitor());
|
|
|
|
walk::walk_crate(v, c);
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
fn walk_expr(@env e, @mutable list[scope] sc, &@ast::expr exp) {
|
|
|
|
push_env_for_expr(sc, exp);
|
|
|
|
alt (exp.node) {
|
|
|
|
case (ast::expr_path(?p, ?a)) {
|
2011-06-06 20:23:35 +02:00
|
|
|
auto df = lookup_path_strict(*e, {*sc}, exp.span,
|
|
|
|
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-05-13 10:51:36 +02:00
|
|
|
fn walk_ty(@env e, @mutable list[scope] sc, &@ast::ty t) {
|
|
|
|
alt (t.node) {
|
|
|
|
case (ast::ty_path(?p, ?a)) {
|
2011-06-06 20:23:35 +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-05-13 10:51:36 +02:00
|
|
|
fn walk_arm(@env e, @mutable list[scope] sc, &ast::arm a) {
|
2011-06-06 20:23:35 +02:00
|
|
|
walk_pat(*e, {*sc}, a.pat);
|
2011-05-13 10:51:36 +02:00
|
|
|
push_env_for_arm(sc, a);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 10:51:36 +02:00
|
|
|
fn walk_pat(&env e, &list[scope] sc, &@ast::pat pat) {
|
|
|
|
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-05-13 10:51:36 +02:00
|
|
|
// Helpers for tracking scope during a walk
|
|
|
|
|
|
|
|
fn push_env_for_crate(@mutable list[scope] sc, &ast::crate c) {
|
|
|
|
*sc = cons[scope](scope_crate(@c), @*sc);
|
|
|
|
}
|
|
|
|
fn pop_env_for_crate(@mutable list[scope] sc, &ast::crate c) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn push_env_for_item(@mutable list[scope] sc, &@ast::item i) {
|
|
|
|
*sc = cons[scope](scope_item(i), @*sc);
|
|
|
|
}
|
|
|
|
fn pop_env_for_item(@mutable list[scope] sc, &@ast::item i) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn push_env_for_method(@mutable list[scope] sc, &@ast::method m) {
|
2011-05-16 18:21:22 -07:00
|
|
|
let vec[ast::ty_param] tp = [];
|
2011-05-13 10:51:36 +02:00
|
|
|
let @ast::item i = @rec(node=ast::item_fn(m.node.ident,
|
|
|
|
m.node.meth,
|
|
|
|
tp,
|
|
|
|
m.node.id,
|
|
|
|
m.node.ann),
|
|
|
|
span=m.span);
|
|
|
|
*sc = cons[scope](scope_item(i), @*sc);
|
|
|
|
}
|
|
|
|
fn pop_env_for_method(@mutable list[scope] sc, &@ast::method m) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn push_env_for_n_item(@mutable list[scope] sc, &@ast::native_item i) {
|
|
|
|
*sc = cons[scope](scope_native_item(i), @*sc);
|
|
|
|
}
|
|
|
|
fn pop_env_for_n_item(@mutable list[scope] sc, &@ast::native_item i) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn push_env_for_block(@mutable list[scope] sc, &ast::block b) {
|
|
|
|
*sc = cons[scope](scope_block(b), @*sc);
|
|
|
|
}
|
|
|
|
fn pop_env_for_block(@mutable list[scope] sc, &ast::block b) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn push_env_for_expr(@mutable list[scope] sc, &@ast::expr x) {
|
|
|
|
alt (x.node) {
|
|
|
|
case (ast::expr_for(?d, _, _, _)) {
|
|
|
|
*sc = cons[scope](scope_loop(d), @*sc);
|
2011-01-18 15:23:11 -05:00
|
|
|
}
|
2011-05-13 10:51:36 +02:00
|
|
|
case (ast::expr_for_each(?d, _, _, _)) {
|
|
|
|
*sc = cons[scope](scope_loop(d), @*sc);
|
2011-01-25 17:54:38 -05:00
|
|
|
}
|
2011-05-13 10:51:36 +02:00
|
|
|
case (_) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn pop_env_for_expr(@mutable list[scope] sc, &@ast::expr x) {
|
|
|
|
alt (x.node) {
|
|
|
|
case (ast::expr_for(?d, _, _, _)) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
case (ast::expr_for_each(?d, _, _, _)) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
2011-05-13 10:51:36 +02:00
|
|
|
case (_) {}
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
fn push_env_for_arm(@mutable list[scope] sc, &ast::arm p) {
|
|
|
|
*sc = cons[scope](scope_arm(p), @*sc);
|
|
|
|
}
|
|
|
|
fn pop_env_for_arm(@mutable list[scope] sc, &ast::arm p) {
|
2011-06-06 20:23:35 +02:00
|
|
|
*sc = std::list::cdr({*sc});
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
|
2011-05-20 15:56:23 -07:00
|
|
|
fn follow_import(&env e, &list[scope] 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-05-12 17:24:54 +02:00
|
|
|
fn resolve_import(&env e, &@ast::view_item it, &list[scope] 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-05-12 13:25:18 +02:00
|
|
|
fn lookup_path_strict(&env e, &list[scope] sc, &span sp, vec[ident] idents,
|
|
|
|
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-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_scope_strict(&env e, list[scope] 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) {
|
|
|
|
case (scope_item(?it)) {
|
|
|
|
alt (it.node) {
|
|
|
|
case (ast::item_fn(_, _, _, _, _)) { true }
|
|
|
|
case (_) { false }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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-05-13 13:34:59 +02:00
|
|
|
fn lookup_in_scope(&env e, list[scope] 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_fn(_, ?f, ?ty_params, _, _)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret lookup_in_fn(id, f.decl, ty_params, ns);
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
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-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-05-26 17:33:33 -07:00
|
|
|
if (dr == outside && !ast::is_exported(id, option::get(info.m))) {
|
|
|
|
// if we're in a native mod, then dr==inside, so info.m is some _mod
|
|
|
|
ret none[def]; // name is not visible
|
|
|
|
}
|
2011-05-23 18:52:55 -07:00
|
|
|
alt(info.index.find(id)) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (none) { }
|
|
|
|
case (some(?lst)) {
|
2011-05-23 18:52:55 -07:00
|
|
|
while (true) {
|
2011-06-06 20:23:35 +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) {
|
|
|
|
e.sess.span_note(e.ast_map.get
|
|
|
|
(ast::def_id_of_def(match)).span,
|
|
|
|
"'" + id + "' is defined here.");
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
auto v = rec(visit_item_pre = bind check_item(e, _),
|
|
|
|
visit_block_pre = bind check_block(e, _),
|
|
|
|
visit_arm_pre = bind check_arm(e, _)
|
2011-05-18 22:23:19 +02:00
|
|
|
with walk::default_visitor());
|
|
|
|
walk::walk_crate(v, c);
|
|
|
|
}
|
|
|
|
|
2011-05-19 11:37:17 -07: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-06 20:23:35 +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-05-19 21:46:51 +02:00
|
|
|
fn check_item(@env e, &@ast::item i) {
|
|
|
|
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 (_) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_arm(@env e, &ast::arm a) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_block(@env e, &ast::block b) {
|
|
|
|
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:
|