"import module::*;" now works.
This commit is contained in:
parent
22953f52fa
commit
40fe44d23e
6 changed files with 177 additions and 55 deletions
|
@ -1,4 +1,3 @@
|
|||
import std::map::hashmap;
|
||||
import std::option;
|
||||
import std::str;
|
||||
import std::vec;
|
||||
|
|
|
@ -76,17 +76,11 @@ tag mod_index_entry {
|
|||
type mod_index = hashmap[ident,list[mod_index_entry]];
|
||||
|
||||
type indexed_mod = rec(option::t[ast::_mod] m,
|
||||
mod_index index, vec[@i_m] glob_imports);
|
||||
mod_index index, vec[def] glob_imports);
|
||||
/* 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.*/
|
||||
// It should be safe to use index to memoize lookups of globbed names.
|
||||
|
||||
//FIXME: this only exists because we can't yet write recursive types unless
|
||||
//the recursion passes through a tag.
|
||||
tag i_m {
|
||||
i_m(indexed_mod);
|
||||
}
|
||||
|
||||
type crate_map = hashmap[uint,ast::crate_num];
|
||||
|
||||
type def_map = hashmap[uint,def];
|
||||
|
@ -144,7 +138,7 @@ fn map_crate(&@env e, &ast::crate c) {
|
|||
// 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[@i_m]()));
|
||||
glob_imports=vec::empty[def]()));
|
||||
walk::walk_crate(index_names, c);
|
||||
|
||||
fn index_vi(@env e, @mutable list[scope] sc, &@ast::view_item i) {
|
||||
|
@ -161,13 +155,13 @@ fn map_crate(&@env e, &ast::crate c) {
|
|||
case (ast::item_mod(_, ?md, ?defid)) {
|
||||
e.mod_map.insert(defid._1,
|
||||
@rec(m=some(md), index=index_mod(md),
|
||||
glob_imports=vec::empty[@i_m]()));
|
||||
glob_imports=vec::empty[def]()));
|
||||
}
|
||||
case (ast::item_native_mod(_, ?nmd, ?defid)) {
|
||||
e.mod_map.insert(defid._1,
|
||||
@rec(m=none[ast::_mod],
|
||||
index=index_nmod(nmd),
|
||||
glob_imports=vec::empty[@i_m]()));
|
||||
glob_imports=vec::empty[def]()));
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
|
@ -370,10 +364,8 @@ fn pop_env_for_arm(@mutable list[scope] sc, &ast::arm p) {
|
|||
*sc = std::list::cdr(*sc);
|
||||
}
|
||||
|
||||
|
||||
//HERE
|
||||
fn follow_import(&env e, &list[scope] sc, vec[ident] path, &span sp)
|
||||
-> @i_m {
|
||||
-> def {
|
||||
auto path_len = vec::len(path);
|
||||
auto dcur = lookup_in_scope_strict(e, sc, sp, path.(0), ns_module);
|
||||
auto i = 1u;
|
||||
|
@ -385,13 +377,8 @@ fn follow_import(&env e, &list[scope] sc, vec[ident] path, &span sp)
|
|||
}
|
||||
|
||||
alt (dcur) {
|
||||
case (ast::def_mod(?def_id)) {
|
||||
//TODO: is this sane?
|
||||
ret @i_m(*e.mod_map.get(def_id._1));
|
||||
}
|
||||
case (ast::def_native_mod(?def_id)) {
|
||||
ret @i_m(*e.mod_map.get(def_id._1));
|
||||
}
|
||||
case (ast::def_mod(?def_id)) { ret dcur; }
|
||||
case (ast::def_native_mod(?def_id)) { ret dcur; }
|
||||
case (_) {
|
||||
e.sess.span_err(sp, str::connect(path, "::")
|
||||
+ " does not name a module.");
|
||||
|
@ -430,9 +417,12 @@ fn resolve_import(&env e, &@ast::view_item it, &list[scope] sc) {
|
|||
while (true) {
|
||||
if (i == n_idents - 1u) {
|
||||
register(e, defid, it.span, end_id,
|
||||
lookup_in_mod(e, dcur, end_id, ns_value, outside),
|
||||
lookup_in_mod(e, dcur, end_id, ns_type, outside),
|
||||
lookup_in_mod(e, dcur, end_id, ns_module, outside));
|
||||
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));
|
||||
break;
|
||||
} else {
|
||||
dcur = lookup_in_mod_strict(e, dcur, it.span, ids.(i),
|
||||
|
@ -526,12 +516,12 @@ fn def_is_obj_field(&def d) -> bool {
|
|||
|
||||
fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
|
||||
-> option::t[def] {
|
||||
fn in_scope(&env e, &ident id, &scope s, namespace ns)
|
||||
fn in_scope(&env e, &span sp, &ident id, &scope s, namespace ns)
|
||||
-> option::t[def] {
|
||||
alt (s) {
|
||||
case (scope_crate(?c)) {
|
||||
auto defid = tup(ast::local_crate, -1);
|
||||
ret lookup_in_local_mod(e, defid, id, ns, inside);
|
||||
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
|
||||
}
|
||||
case (scope_item(?it)) {
|
||||
alt (it.node) {
|
||||
|
@ -547,10 +537,10 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
|
|||
}
|
||||
}
|
||||
case (ast::item_mod(_, _, ?defid)) {
|
||||
ret lookup_in_local_mod(e, defid, id, ns, inside);
|
||||
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
|
||||
}
|
||||
case (ast::item_native_mod(_, ?m, ?defid)) {
|
||||
ret lookup_in_local_native_mod(e, defid, id, ns);
|
||||
ret lookup_in_local_native_mod(e, defid, sp, id, ns);
|
||||
}
|
||||
case (ast::item_ty(_, _, ?ty_params, _, _)) {
|
||||
if (ns == ns_type) {
|
||||
|
@ -599,7 +589,7 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
|
|||
ret none[def];
|
||||
}
|
||||
case (cons[scope](?hd, ?tl)) {
|
||||
auto fnd = in_scope(e, id, hd, ns);
|
||||
auto fnd = in_scope(e, sp, id, hd, ns);
|
||||
if (!option::is_none(fnd)) {
|
||||
auto df = option::get(fnd);
|
||||
if ((left_fn && def_is_local(df)) ||
|
||||
|
@ -618,6 +608,7 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
|
|||
}
|
||||
}
|
||||
e.sess.bug("reached unreachable code in lookup_in_scope"); // sigh
|
||||
fail;
|
||||
}
|
||||
|
||||
fn lookup_in_ty_params(&ident id, &vec[ast::ty_param] ty_params)
|
||||
|
@ -764,7 +755,7 @@ fn found_def_item(&@ast::item i, namespace ns) -> option::t[def] {
|
|||
|
||||
fn lookup_in_mod_strict(&env e, def m, &span sp, &ident id,
|
||||
namespace ns, dir dr) -> def {
|
||||
alt (lookup_in_mod(e, m, id, ns, dr)) {
|
||||
alt (lookup_in_mod(e, m, sp, id, ns, dr)) {
|
||||
case (none[def]) {
|
||||
unresolved(e, sp, id, ns_name(ns));
|
||||
fail;
|
||||
|
@ -775,10 +766,10 @@ fn lookup_in_mod_strict(&env e, def m, &span sp, &ident id,
|
|||
}
|
||||
}
|
||||
|
||||
fn lookup_in_mod(&env e, def m, &ident id, namespace ns, dir dr)
|
||||
fn lookup_in_mod(&env e, def m, &span sp, &ident id, namespace ns, dir dr)
|
||||
-> option::t[def] {
|
||||
auto defid = ast::def_id_of_def(m);
|
||||
if (defid._0 != ast::local_crate) { // Not in this crate
|
||||
if (defid._0 != ast::local_crate) { // examining a mod. in an ext. crate
|
||||
auto cached = e.ext_cache.find(tup(defid,id,ns));
|
||||
if (!option::is_none(cached)) { ret cached; }
|
||||
auto path = [id];
|
||||
|
@ -793,10 +784,10 @@ fn lookup_in_mod(&env e, def m, &ident id, namespace ns, dir dr)
|
|||
}
|
||||
alt (m) {
|
||||
case (ast::def_mod(?defid)) {
|
||||
ret lookup_in_local_mod(e, defid, id, ns, dr);
|
||||
ret lookup_in_local_mod(e, defid, sp, id, ns, dr);
|
||||
}
|
||||
case (ast::def_native_mod(?defid)) {
|
||||
ret lookup_in_local_native_mod(e, defid, id, ns);
|
||||
ret lookup_in_local_native_mod(e, defid, sp, id, ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -811,7 +802,7 @@ fn found_view_item(&env e, @ast::view_item vi, namespace ns)
|
|||
ret lookup_import(e, defid, ns);
|
||||
}
|
||||
case (ast::view_item_import_glob(_, ?defid)) {
|
||||
ret none[def]; //TODO: think about this. Is it correct?
|
||||
ret none[def]; //will be handled in the fallback glob pass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -834,29 +825,53 @@ fn lookup_import(&env e, def_id defid, namespace ns) -> option::t[def] {
|
|||
fail;
|
||||
}
|
||||
|
||||
fn lookup_in_local_mod(&env e, def_id defid, &ident id, namespace ns,
|
||||
dir dr) -> option::t[def] {
|
||||
fn lookup_in_local_mod(&env e, def_id defid, &span sp, &ident id,
|
||||
namespace ns, dir dr) -> option::t[def] {
|
||||
auto info = e.mod_map.get(defid._1);
|
||||
auto found = info.index.find(id);
|
||||
if (option::is_none(found) ||
|
||||
(dr == outside && !ast::is_exported(id, option::get(info.m)))) {
|
||||
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];
|
||||
ret none[def]; // name is not visible
|
||||
}
|
||||
auto lst = option::get(found);
|
||||
while (true) {
|
||||
alt (lst) {
|
||||
case (nil[mod_index_entry]) {
|
||||
ret none[def];
|
||||
}
|
||||
case (cons[mod_index_entry](?hd, ?tl)) {
|
||||
auto found = lookup_in_mie(e, hd, ns);
|
||||
if (!option::is_none(found)) { ret found; }
|
||||
lst = *tl;
|
||||
alt(info.index.find(id)) {
|
||||
case (none[list[mod_index_entry]]) { }
|
||||
case (some[list[mod_index_entry]](?lst)) {
|
||||
while (true) {
|
||||
alt (lst) {
|
||||
case (nil[mod_index_entry]) { break; }
|
||||
case (cons[mod_index_entry](?hd, ?tl)) {
|
||||
auto found = lookup_in_mie(e, hd, ns);
|
||||
if (!option::is_none(found)) { ret found; }
|
||||
lst = *tl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
e.sess.bug("reached unreachable code in lookup_in_regular_mod"); // sigh
|
||||
// not local or explicitly imported; try globs:
|
||||
ret lookup_glob_in_mod(e, info, sp, id, ns, dr);
|
||||
}
|
||||
|
||||
fn lookup_glob_in_mod(&env e, @indexed_mod info, &span sp, &ident id,
|
||||
namespace ns, dir dr) -> option::t[def] {
|
||||
fn l_i_m(&env e, &def d, &span sp, &ident id, namespace ns, dir dr)
|
||||
-> option::t[def] {
|
||||
ret lookup_in_mod(e, d, sp, id, ns, dr);
|
||||
}
|
||||
auto matches = vec::filter_map
|
||||
(bind l_i_m(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 d in matches) {
|
||||
e.sess.span_note(sp, "'" + id + "' is defined at " +
|
||||
util::common::istr(ast::def_id_of_def(d)._1));
|
||||
}
|
||||
e.sess.span_err(sp, "'" + id + "' is glob-imported from" +
|
||||
" multiple different modules.");
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_in_mie(&env e, &mod_index_entry mie, namespace ns)
|
||||
|
@ -899,9 +914,9 @@ fn lookup_in_mie(&env e, &mod_index_entry mie, namespace ns)
|
|||
ret none[def];
|
||||
}
|
||||
|
||||
fn lookup_in_local_native_mod(&env e, def_id defid, &ident id, namespace ns)
|
||||
-> option::t[def] {
|
||||
ret lookup_in_local_mod(e, defid, id, ns, inside);
|
||||
fn lookup_in_local_native_mod(&env e, def_id defid, &span sp, &ident id,
|
||||
namespace ns) -> option::t[def] {
|
||||
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
|
||||
}
|
||||
|
||||
|
||||
|
|
24
src/test/compile-fail/import-glob-0.rs
Normal file
24
src/test/compile-fail/import-glob-0.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
mod module_of_many_things {
|
||||
export f1, f2, f4;
|
||||
fn f1() {
|
||||
log "f1";
|
||||
}
|
||||
fn f2() {
|
||||
log "f2";
|
||||
}
|
||||
fn f3() {
|
||||
log "f3";
|
||||
}
|
||||
fn f4() {
|
||||
log "f4";
|
||||
}
|
||||
}
|
||||
|
||||
import module_of_many_things::*;
|
||||
|
||||
fn main() {
|
||||
f1();
|
||||
f2();
|
||||
f3();
|
||||
f4();
|
||||
}
|
49
src/test/run-pass/import-glob-0.rs
Normal file
49
src/test/run-pass/import-glob-0.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
import module_of_many_things::*;
|
||||
import dug::too::greedily::and::too::deep::*;
|
||||
|
||||
mod module_of_many_things {
|
||||
export f1;
|
||||
export f2;
|
||||
export f4;
|
||||
fn f1() {
|
||||
log "f1";
|
||||
}
|
||||
fn f2() {
|
||||
log "f2";
|
||||
}
|
||||
fn f3() {
|
||||
log "f3";
|
||||
}
|
||||
fn f4() {
|
||||
log "f4";
|
||||
}
|
||||
}
|
||||
|
||||
mod dug {
|
||||
mod too {
|
||||
mod greedily {
|
||||
mod and {
|
||||
mod too {
|
||||
mod deep {
|
||||
fn nameless_fear() {
|
||||
log "Boo!";
|
||||
}
|
||||
fn also_redstone() {
|
||||
log "Whatever.";
|
||||
}
|
||||
fn f1() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
f1();
|
||||
f2();
|
||||
f4();
|
||||
nameless_fear();
|
||||
also_redstone();
|
||||
}
|
26
src/test/run-pass/import-glob-1.rs
Normal file
26
src/test/run-pass/import-glob-1.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
import a1:b1::word_traveler;
|
||||
|
||||
mod a1 { //
|
||||
mod b1 { //
|
||||
import a2::b1::*; // <-\
|
||||
} // |
|
||||
mod b2 { // |
|
||||
import a2::b2::*; // <-\ -\ |
|
||||
} // | | |
|
||||
} // | | |
|
||||
// | | |
|
||||
mod a2 { // | | |
|
||||
native mod b1 { // | | |
|
||||
import a1::b2::*; // | <-/ -/
|
||||
} // |
|
||||
mod b2 { // |
|
||||
fn word_traveler() { // |
|
||||
log "ahoy!"; // -/
|
||||
} //
|
||||
} //
|
||||
} //
|
||||
|
||||
|
||||
fn main() {
|
||||
word_traveler();
|
||||
}
|
9
src/test/run-pass/import-glob-crate.rs
Normal file
9
src/test/run-pass/import-glob-crate.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
use std;
|
||||
import std::vec::*;
|
||||
|
||||
fn main() {
|
||||
auto v = empty[int]();
|
||||
v += [4,2];
|
||||
assert(reversed(v) == [2,4]);
|
||||
}
|
Loading…
Reference in a new issue