Switch resolve pass to use visit.rs rather than walk.rs
This commit is contained in:
parent
d8516178e5
commit
4ab862a50d
@ -11,6 +11,7 @@ import util::common::new_uint_hash;
|
||||
import util::common::new_str_hash;
|
||||
import util::common::span;
|
||||
import middle::tstate::ann::ts_ann;
|
||||
import visit::vt;
|
||||
import std::map::hashmap;
|
||||
import std::list;
|
||||
import std::list::list;
|
||||
@ -36,14 +37,16 @@ import std::vec;
|
||||
tag scope {
|
||||
scope_crate(@ast::crate);
|
||||
scope_item(@ast::item);
|
||||
scope_fn(ast::fn_decl, vec[ast::ty_param]);
|
||||
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);
|
||||
}
|
||||
type scopes = list[scope];
|
||||
|
||||
tag import_state {
|
||||
todo(@ast::view_item, list[scope]); // only used for explicit imports
|
||||
todo(@ast::view_item, scopes); // only used for explicit imports
|
||||
resolving(span);
|
||||
resolved(option::t[def] /* value */,
|
||||
option::t[def] /* type */,
|
||||
@ -116,10 +119,10 @@ fn resolve_crate(session sess, @ast::crate crate) -> def_map {
|
||||
ext_cache = new_ext_hash(),
|
||||
sess = sess);
|
||||
creader::read_crates(sess, e.crate_map, *crate);
|
||||
map_crate(e, *crate);
|
||||
map_crate(e, crate);
|
||||
resolve_imports(*e);
|
||||
check_for_collisions(e, *crate);
|
||||
resolve_names(e, *crate);
|
||||
resolve_names(e, crate);
|
||||
ret e.def_map;
|
||||
}
|
||||
|
||||
@ -127,36 +130,32 @@ fn resolve_crate(session sess, @ast::crate crate) -> def_map {
|
||||
// Locate all modules and imports and index them, so that the next passes can
|
||||
// resolve through them.
|
||||
|
||||
fn map_crate(&@env e, &ast::crate c) {
|
||||
|
||||
fn map_crate(&@env e, &@ast::crate c) {
|
||||
// First, find all the modules, and index the names that they contain
|
||||
|
||||
auto cell = @mutable nil[scope];
|
||||
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());
|
||||
// Register the top-level mod
|
||||
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
|
||||
e.mod_map.insert(-1, @rec(m=some(c.node.module),
|
||||
index=index_mod(c.node.module),
|
||||
glob_imports=vec::empty[def](),
|
||||
glob_imported_names
|
||||
=new_str_hash[import_state]()));
|
||||
walk::walk_crate(index_names, c);
|
||||
|
||||
fn index_vi(@env e, @mutable list[scope] sc, &@ast::view_item i) {
|
||||
fn index_vi(@env e, &@ast::view_item i, &scopes sc, &vt[scopes] v) {
|
||||
alt (i.node) {
|
||||
case (ast::view_item_import(_, ?ids, ?defid)) {
|
||||
e.imports.insert(defid._1, todo(i, {*sc}));
|
||||
e.imports.insert(defid._1, todo(i, sc));
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
fn index_i(@env e, @mutable list[scope] sc, &@ast::item i) {
|
||||
push_env_for_item(sc, i);
|
||||
|
||||
fn index_i(@env e, &@ast::item i, &scopes sc, &vt[scopes] v) {
|
||||
visit_item_with_scope(i, sc, v);
|
||||
alt (i.node) {
|
||||
case (ast::item_mod(_, ?md, ?defid)) {
|
||||
e.mod_map.insert(defid._1,
|
||||
@ -195,18 +194,15 @@ fn map_crate(&@env e, &ast::crate c) {
|
||||
}
|
||||
|
||||
// Next, assemble the links for globbed imports.
|
||||
cell = @mutable nil[scope];
|
||||
auto link_globs =
|
||||
rec(visit_crate_pre = bind push_env_for_crate(cell, _),
|
||||
visit_crate_post = bind pop_env_for_crate(cell, _),
|
||||
visit_view_item_pre = bind link_glob(e, cell, _),
|
||||
visit_item_pre = bind push_env_for_item(cell, _),
|
||||
visit_item_post = bind pop_env_for_item(cell, _)
|
||||
with walk::default_visitor());
|
||||
walk::walk_crate(link_globs, c);
|
||||
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));
|
||||
|
||||
fn link_glob(@env e, @mutable list[scope] sc, &@ast::view_item vi) {
|
||||
fn find_mod(@env e, list[scope] sc) -> @indexed_mod {
|
||||
fn link_glob(@env e, &@ast::view_item vi, &scopes sc, &vt[scopes] v) {
|
||||
fn find_mod(@env e, scopes sc) -> @indexed_mod {
|
||||
alt (sc) {
|
||||
case (cons(scope_item(?i), ?tl)) {
|
||||
alt(i.node) {
|
||||
@ -230,8 +226,8 @@ fn map_crate(&@env e, &ast::crate c) {
|
||||
alt (vi.node) {
|
||||
//if it really is a glob import, that is
|
||||
case (ast::view_item_import_glob(?path, _)) {
|
||||
find_mod(e, *sc).glob_imports
|
||||
+= [follow_import(*e, {*sc}, path, vi.span)];
|
||||
find_mod(e, sc).glob_imports
|
||||
+= [follow_import(*e, sc, path, vi.span)];
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
@ -251,52 +247,45 @@ fn resolve_imports(&env e) {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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, _, _, _),
|
||||
visit_fn = visit_fn_with_scope
|
||||
with *visit::default_visitor());
|
||||
visit::visit_crate(*c, cons(scope_crate(c), @nil),
|
||||
visit::vtor(v));
|
||||
|
||||
fn walk_expr(@env e, @mutable list[scope] sc, &@ast::expr exp) {
|
||||
push_env_for_expr(sc, exp);
|
||||
fn walk_expr(@env e, &@ast::expr exp, &scopes sc, &vt[scopes] v) {
|
||||
visit_expr_with_scope(exp, sc, v);
|
||||
alt (exp.node) {
|
||||
case (ast::expr_path(?p, ?a)) {
|
||||
auto df = lookup_path_strict(*e, {*sc}, exp.span,
|
||||
auto df = lookup_path_strict(*e, sc, exp.span,
|
||||
p.node.idents, ns_value);
|
||||
e.def_map.insert(a.id, df);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
fn walk_ty(@env e, @mutable list[scope] sc, &@ast::ty t) {
|
||||
fn walk_ty(@env e, &@ast::ty t, &scopes sc, &vt[scopes] v) {
|
||||
visit::visit_ty(t, sc, v);
|
||||
alt (t.node) {
|
||||
case (ast::ty_path(?p, ?a)) {
|
||||
auto new_def = lookup_path_strict(*e, {*sc}, t.span,
|
||||
auto new_def = lookup_path_strict(*e, sc, t.span,
|
||||
p.node.idents, ns_type);
|
||||
e.def_map.insert(a.id, new_def);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
fn walk_arm(@env e, @mutable list[scope] sc, &ast::arm a) {
|
||||
walk_pat(*e, {*sc}, a.pat);
|
||||
push_env_for_arm(sc, a);
|
||||
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);
|
||||
}
|
||||
fn walk_pat(&env e, &list[scope] sc, &@ast::pat pat) {
|
||||
fn walk_pat(&env e, &scopes 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,
|
||||
@ -319,81 +308,42 @@ fn resolve_names(&@env e, &ast::crate c) {
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers for tracking scope during a walk
|
||||
// Visit helper functions
|
||||
|
||||
fn push_env_for_crate(@mutable list[scope] sc, &ast::crate c) {
|
||||
*sc = cons[scope](scope_crate(@c), @*sc);
|
||||
fn visit_item_with_scope(&@ast::item i, &scopes sc, &vt[scopes] v) {
|
||||
visit::visit_item(i, cons(scope_item(i), @sc), v);
|
||||
}
|
||||
fn pop_env_for_crate(@mutable list[scope] sc, &ast::crate c) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
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);
|
||||
}
|
||||
|
||||
fn push_env_for_item(@mutable list[scope] sc, &@ast::item i) {
|
||||
*sc = cons[scope](scope_item(i), @*sc);
|
||||
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);
|
||||
}
|
||||
fn pop_env_for_item(@mutable list[scope] sc, &@ast::item i) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
fn visit_block_with_scope(&ast::block b, &scopes sc, &vt[scopes] v) {
|
||||
visit::visit_block(b, cons(scope_block(b), @sc), v);
|
||||
}
|
||||
|
||||
fn push_env_for_method(@mutable list[scope] sc, &@ast::method m) {
|
||||
let vec[ast::ty_param] tp = [];
|
||||
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 visit_arm_with_scope(&ast::arm a, &scopes sc, &vt[scopes] v) {
|
||||
visit::visit_arm(a, cons(scope_arm(a), @sc), v);
|
||||
}
|
||||
fn pop_env_for_method(@mutable list[scope] sc, &@ast::method m) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
}
|
||||
|
||||
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) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
}
|
||||
|
||||
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) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
}
|
||||
|
||||
fn push_env_for_expr(@mutable list[scope] sc, &@ast::expr x) {
|
||||
alt (x.node) {
|
||||
fn visit_expr_with_scope(&@ast::expr x, &scopes sc, &vt[scopes] v) {
|
||||
auto new_sc = alt (x.node) {
|
||||
case (ast::expr_for(?d, _, _, _)) {
|
||||
*sc = cons[scope](scope_loop(d), @*sc);
|
||||
cons[scope](scope_loop(d), @sc)
|
||||
}
|
||||
case (ast::expr_for_each(?d, _, _, _)) {
|
||||
*sc = cons[scope](scope_loop(d), @*sc);
|
||||
cons[scope](scope_loop(d), @sc)
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
fn pop_env_for_expr(@mutable list[scope] sc, &@ast::expr x) {
|
||||
alt (x.node) {
|
||||
case (ast::expr_for(?d, _, _, _)) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
}
|
||||
case (ast::expr_for_each(?d, _, _, _)) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
case (_) { sc }
|
||||
};
|
||||
visit::visit_expr(x, new_sc, v);
|
||||
}
|
||||
|
||||
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) {
|
||||
*sc = std::list::cdr({*sc});
|
||||
}
|
||||
|
||||
fn follow_import(&env e, &list[scope] sc, vec[ident] path, &span sp)
|
||||
fn follow_import(&env e, &scopes sc, vec[ident] path, &span sp)
|
||||
-> def {
|
||||
auto path_len = vec::len(path);
|
||||
auto dcur = lookup_in_scope_strict(e, sc, sp, path.(0), ns_module);
|
||||
@ -420,7 +370,7 @@ fn follow_import(&env e, &list[scope] sc, vec[ident] path, &span sp)
|
||||
|
||||
// Import resolution
|
||||
|
||||
fn resolve_import(&env e, &@ast::view_item it, &list[scope] sc) {
|
||||
fn resolve_import(&env e, &@ast::view_item it, &scopes sc) {
|
||||
auto defid; auto ids;
|
||||
alt (it.node) {
|
||||
case (ast::view_item_import(_, ?_ids, ?_defid)) {
|
||||
@ -487,7 +437,7 @@ fn unresolved(&env e, &span sp, &ident id, &str kind) -> ! {
|
||||
|
||||
// Lookup helpers
|
||||
|
||||
fn lookup_path_strict(&env e, &list[scope] sc, &span sp, vec[ident] idents,
|
||||
fn lookup_path_strict(&env e, &scopes sc, &span sp, vec[ident] idents,
|
||||
namespace ns) -> def {
|
||||
auto n_idents = vec::len(idents);
|
||||
auto headns = if (n_idents == 1u) { ns } else { ns_module };
|
||||
@ -501,7 +451,7 @@ fn lookup_path_strict(&env e, &list[scope] sc, &span sp, vec[ident] idents,
|
||||
ret dcur;
|
||||
}
|
||||
|
||||
fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, &ident id,
|
||||
fn lookup_in_scope_strict(&env e, scopes sc, &span sp, &ident id,
|
||||
namespace ns) -> def {
|
||||
alt (lookup_in_scope(e, sc, sp, id, ns)) {
|
||||
case (none) {
|
||||
@ -515,12 +465,7 @@ fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, &ident id,
|
||||
|
||||
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_fn(_, _)) { true }
|
||||
case (scope_native_item(_)) { true }
|
||||
case (_) { false }
|
||||
};
|
||||
@ -541,7 +486,7 @@ fn def_is_obj_field(&def d) -> bool {
|
||||
};
|
||||
}
|
||||
|
||||
fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
|
||||
fn lookup_in_scope(&env e, scopes sc, &span sp, &ident id, namespace ns)
|
||||
-> option::t[def] {
|
||||
fn in_scope(&env e, &span sp, &ident id, &scope s, namespace ns)
|
||||
-> option::t[def] {
|
||||
@ -554,9 +499,6 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
|
||||
}
|
||||
case (scope_item(?it)) {
|
||||
alt (it.node) {
|
||||
case (ast::item_fn(_, ?f, ?ty_params, _, _)) {
|
||||
ret lookup_in_fn(id, f.decl, ty_params, ns);
|
||||
}
|
||||
case (ast::item_obj(_, ?ob, ?ty_params, _, _)) {
|
||||
ret lookup_in_obj(id, ob, ty_params, ns);
|
||||
}
|
||||
@ -586,6 +528,9 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
|
||||
}
|
||||
}
|
||||
}
|
||||
case (scope_fn(?decl, ?ty_params)) {
|
||||
ret lookup_in_fn(id, decl, ty_params, ns);
|
||||
}
|
||||
case (scope_loop(?d)) {
|
||||
if (ns == ns_value) {
|
||||
alt (d.node) {
|
||||
@ -1118,11 +1063,11 @@ fn check_for_collisions(&@env e, &ast::crate c) {
|
||||
}
|
||||
|
||||
// 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, _)
|
||||
with walk::default_visitor());
|
||||
walk::walk_crate(v, c);
|
||||
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));
|
||||
}
|
||||
|
||||
fn check_mod_name(&env e, &ident name, &list[mod_index_entry] entries) {
|
||||
@ -1164,7 +1109,8 @@ fn mie_span(&mod_index_entry mie) -> span {
|
||||
}
|
||||
|
||||
|
||||
fn check_item(@env e, &@ast::item i) {
|
||||
fn check_item(@env e, &@ast::item i, &() x, &vt[()] v) {
|
||||
visit::visit_item(i, x, v);
|
||||
alt (i.node) {
|
||||
case (ast::item_fn(_, ?f, ?ty_params, _, _)) {
|
||||
check_fn(*e, i.span, f);
|
||||
@ -1187,7 +1133,8 @@ fn check_item(@env e, &@ast::item i) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_arm(@env e, &ast::arm a) {
|
||||
fn check_arm(@env e, &ast::arm a, &() x, &vt[()] v) {
|
||||
visit::visit_arm(a, x, v);
|
||||
fn walk_pat(checker ch, &@ast::pat p) {
|
||||
alt (p.node) {
|
||||
case (ast::pat_bind(?name, _, _)) {
|
||||
@ -1204,7 +1151,9 @@ fn check_arm(@env e, &ast::arm a) {
|
||||
walk_pat(checker(*e, "binding"), a.pat);
|
||||
}
|
||||
|
||||
fn check_block(@env e, &ast::block b) {
|
||||
fn check_block(@env e, &ast::block b, &() x, &vt[()] v) {
|
||||
visit::visit_block(b, x, v);
|
||||
|
||||
auto values = checker(*e, "value");
|
||||
auto types = checker(*e, "type");
|
||||
auto mods = checker(*e, "module");
|
||||
|
Loading…
x
Reference in New Issue
Block a user