parent
03f6060e80
commit
e98286b594
@ -70,7 +70,8 @@ fn fold_block(cfg: ast::crate_cfg, b: ast::blk_, fld: fold::ast_fold) ->
|
||||
ast::blk_ {
|
||||
let filter = bind filter_stmt(cfg, _);
|
||||
let filtered_stmts = vec::filter_map(filter, b.stmts);
|
||||
ret {stmts: vec::map(fld.fold_stmt, filtered_stmts),
|
||||
ret {view_items: b.view_items,
|
||||
stmts: vec::map(fld.fold_stmt, filtered_stmts),
|
||||
expr: option::map(fld.fold_expr, b.expr),
|
||||
id: b.id,
|
||||
rules: b.rules};
|
||||
|
@ -348,6 +348,7 @@ fn mk_test_wrapper(cx: test_ctxt,
|
||||
};
|
||||
|
||||
let wrapper_body: ast::blk = nospan({
|
||||
view_items: [],
|
||||
stmts: [@call_stmt],
|
||||
expr: option::none,
|
||||
id: cx.next_node_id(),
|
||||
|
@ -37,7 +37,6 @@ tag scope {
|
||||
scope_fn(ast::fn_decl, ast::proto, [ast::ty_param]);
|
||||
scope_native_item(@ast::native_item);
|
||||
scope_loop(@ast::local); // there's only 1 decl per loop.
|
||||
|
||||
scope_block(ast::blk, @mutable uint, @mutable uint);
|
||||
scope_arm(ast::arm);
|
||||
}
|
||||
@ -105,6 +104,7 @@ type env =
|
||||
ast_map: ast_map::map,
|
||||
imports: hashmap<ast::node_id, import_state>,
|
||||
mod_map: hashmap<ast::node_id, @indexed_mod>,
|
||||
block_map: hashmap<ast::node_id, [glob_imp_def]>,
|
||||
ext_map: hashmap<def_id, [ident]>,
|
||||
ext_cache: ext_hash,
|
||||
used_imports: {mutable track: bool,
|
||||
@ -124,11 +124,12 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
|
||||
{def_map: def_map, ext_map: ext_map} {
|
||||
let e =
|
||||
@{cstore: sess.get_cstore(),
|
||||
def_map: new_int_hash::<def>(),
|
||||
def_map: new_int_hash(),
|
||||
ast_map: amap,
|
||||
imports: new_int_hash::<import_state>(),
|
||||
mod_map: new_int_hash::<@indexed_mod>(),
|
||||
ext_map: new_def_hash::<[ident]>(),
|
||||
imports: new_int_hash(),
|
||||
mod_map: new_int_hash(),
|
||||
block_map: new_int_hash(),
|
||||
ext_map: new_def_hash(),
|
||||
ext_cache: new_ext_hash(),
|
||||
used_imports: {mutable track: false, mutable data: []},
|
||||
mutable reported: [],
|
||||
@ -149,14 +150,14 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
|
||||
// resolve through them.
|
||||
fn map_crate(e: @env, c: @ast::crate) {
|
||||
// First, find all the modules, and index the names that they contain
|
||||
|
||||
let v_map_mod =
|
||||
@{visit_view_item: bind index_vi(e, _, _, _),
|
||||
visit_item: bind index_i(e, _, _, _)
|
||||
with *visit::default_visitor::<scopes>()};
|
||||
visit_item: bind index_i(e, _, _, _),
|
||||
visit_block: visit_block_with_scope
|
||||
with *visit::default_visitor::<scopes>()};
|
||||
visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v_map_mod));
|
||||
// Register the top-level mod
|
||||
|
||||
// Register the top-level mod
|
||||
e.mod_map.insert(-1,
|
||||
@{m: some(c.node.module),
|
||||
index: index_mod(c.node.module),
|
||||
@ -200,38 +201,36 @@ fn map_crate(e: @env, c: @ast::crate) {
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
// Next, assemble the links for globbed imports.
|
||||
|
||||
// Next, assemble the links for globbed imports.
|
||||
let v_link_glob =
|
||||
@{visit_view_item: bind link_glob(e, _, _, _),
|
||||
visit_block: visit_block_with_scope,
|
||||
visit_item: visit_item_with_scope
|
||||
with *visit::default_visitor::<scopes>()};
|
||||
with *visit::default_visitor::<scopes>()};
|
||||
visit::visit_crate(*c, cons(scope_crate, @nil),
|
||||
visit::mk_vt(v_link_glob));
|
||||
fn link_glob(e: @env, vi: @ast::view_item, sc: scopes, _v: vt<scopes>) {
|
||||
fn find_mod(e: @env, sc: scopes) -> @indexed_mod {
|
||||
alt sc {
|
||||
cons(scope_item(i), tl) {
|
||||
alt i.node {
|
||||
ast::item_mod(_) | ast::item_native_mod(_) {
|
||||
ret e.mod_map.get(i.id);
|
||||
}
|
||||
_ { be find_mod(e, *tl); }
|
||||
}
|
||||
}
|
||||
_ {
|
||||
ret e.mod_map.get(-1); //top-level
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
alt vi.node {
|
||||
//if it really is a glob import, that is
|
||||
ast::view_item_import_glob(path, _) {
|
||||
let imp = follow_import(*e, sc, path, vi.span);
|
||||
if option::is_some(imp) {
|
||||
find_mod(e, sc).glob_imports +=
|
||||
[{def: option::get(imp), item: vi}];
|
||||
let glob = {def: option::get(imp), item: vi};;
|
||||
alt sc {
|
||||
cons(scope_item(i), _) {
|
||||
e.mod_map.get(i.id).glob_imports += [glob];
|
||||
}
|
||||
cons(scope_block(b, _, _), _) {
|
||||
let globs = alt e.block_map.find(b.node.id) {
|
||||
some(globs) { globs + [glob] } none. { [glob] }
|
||||
};
|
||||
e.block_map.insert(b.node.id, globs);
|
||||
}
|
||||
nil. {
|
||||
e.mod_map.get(-1).glob_imports += [glob];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { }
|
||||
@ -370,6 +369,7 @@ fn visit_fn_with_scope(e: @env, f: ast::_fn, tp: [ast::ty_param], sp: span,
|
||||
fn visit_block_with_scope(b: ast::blk, sc: scopes, v: vt<scopes>) {
|
||||
let pos = @mutable 0u, loc = @mutable 0u;
|
||||
let block_sc = cons(scope_block(b, pos, loc), @sc);
|
||||
for vi in b.node.view_items { v.visit_view_item(vi, block_sc, v); }
|
||||
for stmt in b.node.stmts {
|
||||
v.visit_stmt(stmt, block_sc, v);;
|
||||
*pos += 1u;;
|
||||
@ -426,9 +426,8 @@ fn follow_import(e: env, sc: scopes, path: [ident], sp: span) ->
|
||||
alt option::get(dcur) {
|
||||
ast::def_mod(_) | ast::def_native_mod(_) { ret dcur; }
|
||||
_ {
|
||||
e.sess.span_err(sp,
|
||||
str::connect(path, "::") +
|
||||
" does not name a module.");
|
||||
e.sess.span_err(sp, str::connect(path, "::") +
|
||||
" does not name a module.");
|
||||
ret none;
|
||||
}
|
||||
}
|
||||
@ -678,7 +677,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
||||
}
|
||||
}
|
||||
scope_block(b, pos, loc) {
|
||||
ret lookup_in_block(name, b.node, *pos, *loc, ns);
|
||||
ret lookup_in_block(e, name, sp, b.node, *pos, *loc, ns);
|
||||
}
|
||||
scope_arm(a) {
|
||||
if ns == ns_value {
|
||||
@ -793,8 +792,8 @@ fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param],
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_in_block(name: ident, b: ast::blk_, pos: uint, loc_pos: uint,
|
||||
ns: namespace) -> option::t<def> {
|
||||
fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
|
||||
loc_pos: uint, ns: namespace) -> option::t<def> {
|
||||
let i = vec::len(b.stmts);
|
||||
while i > 0u {
|
||||
i -= 1u;
|
||||
@ -849,7 +848,30 @@ fn lookup_in_block(name: ident, b: ast::blk_, pos: uint, loc_pos: uint,
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
ret none::<def>;
|
||||
for vi in b.view_items {
|
||||
alt vi.node {
|
||||
ast::view_item_import(ident, _, id) {
|
||||
if name == ident { ret lookup_import(e, local_def(id), ns); }
|
||||
}
|
||||
ast::view_item_import_from(mod_path, idents, id) {
|
||||
for ident in idents {
|
||||
if name == ident.node.name {
|
||||
ret lookup_import(e, local_def(ident.node.id), ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::view_item_import_glob(_, _) {
|
||||
alt e.block_map.find(b.id) {
|
||||
some(globs) {
|
||||
let found = lookup_in_globs(e, globs, sp, name, ns, inside);
|
||||
if found != none { ret found; }
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret none;
|
||||
}
|
||||
|
||||
fn found_def_item(i: @ast::item, ns: namespace) -> option::t<def> {
|
||||
@ -991,57 +1013,51 @@ fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not local or explicitly imported; try globs:
|
||||
ret lookup_glob_in_mod(e, info, sp, id, ns, outside);
|
||||
}
|
||||
|
||||
fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
|
||||
wanted_ns: namespace, dr: dir) -> option::t<def> {
|
||||
fn per_ns(e: env, info: @indexed_mod, sp: span, id: ident, ns: namespace,
|
||||
dr: dir) -> option::t<def> {
|
||||
|
||||
fn lookup_in_mod_(e: env, def: glob_imp_def, sp: span, name: ident,
|
||||
ns: namespace, dr: dir) -> option::t<glob_imp_def> {
|
||||
alt lookup_in_mod(e, def.def, sp, name, ns, dr) {
|
||||
option::some(d) { option::some({def: d, item: def.item}) }
|
||||
option::none. { option::none }
|
||||
}
|
||||
}
|
||||
|
||||
let matches =
|
||||
vec::filter_map(bind lookup_in_mod_(e, _, sp, id, ns, dr),
|
||||
{ info.glob_imports });
|
||||
if vec::len(matches) == 0u {
|
||||
ret none;
|
||||
} else if vec::len(matches) == 1u {
|
||||
ret some(matches[0].def);
|
||||
} else {
|
||||
for match: glob_imp_def in matches {
|
||||
let sp = match.item.span;
|
||||
e.sess.span_note(sp, #fmt["'%s' is imported here", id]);
|
||||
}
|
||||
e.sess.span_fatal(sp,
|
||||
"'" + id + "' is glob-imported from" +
|
||||
" multiple different modules.");
|
||||
fn lookup_in_globs(e: env, globs: [glob_imp_def], sp: span, id: ident,
|
||||
ns: namespace, dr: dir) -> option::t<def> {
|
||||
fn lookup_in_mod_(e: env, def: glob_imp_def, sp: span, name: ident,
|
||||
ns: namespace, dr: dir) -> option::t<glob_imp_def> {
|
||||
alt lookup_in_mod(e, def.def, sp, name, ns, dr) {
|
||||
option::some(d) { option::some({def: d, item: def.item}) }
|
||||
option::none. { option::none }
|
||||
}
|
||||
}
|
||||
let matches =
|
||||
vec::filter_map(bind lookup_in_mod_(e, _, sp, id, ns, dr),
|
||||
{ globs });
|
||||
if vec::len(matches) == 0u {
|
||||
ret none;
|
||||
} else if vec::len(matches) == 1u {
|
||||
ret some(matches[0].def);
|
||||
} else {
|
||||
for match: glob_imp_def in matches {
|
||||
let sp = match.item.span;
|
||||
e.sess.span_note(sp, #fmt["'%s' is imported here", id]);
|
||||
}
|
||||
e.sess.span_fatal(sp, "'" + id + "' is glob-imported from" +
|
||||
" multiple different modules.");
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
|
||||
wanted_ns: namespace, dr: dir) -> option::t<def> {
|
||||
// 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));
|
||||
let val = per_ns(e, info, sp, id, ns_value, dr);
|
||||
let typ = per_ns(e, info, sp, id, ns_type, dr);
|
||||
let md = per_ns(e, info, sp, id, ns_module, dr);
|
||||
let val = lookup_in_globs(e, info.glob_imports, sp, id, ns_value, dr);
|
||||
let typ = lookup_in_globs(e, info.glob_imports, sp, id, ns_type, dr);
|
||||
let md = lookup_in_globs(e, info.glob_imports, sp, id, ns_module, dr);
|
||||
info.glob_imported_names.insert(id, resolved(val, typ, md, id, sp));
|
||||
}
|
||||
alt info.glob_imported_names.get(id) {
|
||||
todo(_, _, _, _, _) { e.sess.bug("Shouldn't've put a todo in."); }
|
||||
resolving(sp) {
|
||||
ret none::<def>; //circularity is okay in import globs
|
||||
|
||||
}
|
||||
//circularity is okay in import globs
|
||||
resolving(sp) { ret none::<def>; }
|
||||
resolved(val, typ, md, _, _) {
|
||||
ret alt wanted_ns {
|
||||
ns_value. { val }
|
||||
|
@ -76,9 +76,8 @@ tag meta_item_ {
|
||||
|
||||
type blk = spanned<blk_>;
|
||||
|
||||
type blk_ =
|
||||
{stmts: [@stmt], expr: option::t<@expr>, id: node_id,
|
||||
rules: blk_check_mode};
|
||||
type blk_ = {view_items: [@view_item], stmts: [@stmt], expr: option::t<@expr>,
|
||||
id: node_id, rules: blk_check_mode};
|
||||
|
||||
type pat = {id: node_id, node: pat_, span: span};
|
||||
|
||||
|
@ -199,7 +199,7 @@ fn block_from_expr(e: @expr) -> blk {
|
||||
|
||||
fn default_block(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) ->
|
||||
blk_ {
|
||||
ret {stmts: stmts1, expr: expr1, id: id1, rules: default_blk};
|
||||
{view_items: [], stmts: stmts1, expr: expr1, id: id1, rules: default_blk}
|
||||
}
|
||||
|
||||
fn obj_field_from_anon_obj_field(f: anon_obj_field) -> obj_field {
|
||||
|
@ -247,7 +247,8 @@ fn noop_fold_method(m: method_, fld: ast_fold) -> method_ {
|
||||
|
||||
|
||||
fn noop_fold_block(b: blk_, fld: ast_fold) -> blk_ {
|
||||
ret {stmts: vec::map(fld.fold_stmt, b.stmts),
|
||||
ret {view_items: vec::map(fld.fold_view_item, b.view_items),
|
||||
stmts: vec::map(fld.fold_stmt, b.stmts),
|
||||
expr: option::map(fld.fold_expr, b.expr),
|
||||
id: b.id,
|
||||
rules: b.rules};
|
||||
|
@ -1697,8 +1697,8 @@ fn parse_block_no_value(p: parser) -> ast::blk {
|
||||
// necessary, and this should take a qualifier.
|
||||
// some blocks start with "#{"...
|
||||
fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
|
||||
let stmts: [@ast::stmt] = [];
|
||||
let expr: option::t<@ast::expr> = none;
|
||||
let view_items = [], stmts = [], expr = none;
|
||||
while is_word(p, "import") { view_items += [parse_view_item(p)]; }
|
||||
while p.peek() != token::RBRACE {
|
||||
alt p.peek() {
|
||||
token::SEMI. {
|
||||
@ -1736,7 +1736,8 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
|
||||
}
|
||||
let hi = p.get_hi_pos();
|
||||
p.bump();
|
||||
let bloc = {stmts: stmts, expr: expr, id: p.get_id(), rules: s};
|
||||
let bloc = {view_items: view_items, stmts: stmts, expr: expr,
|
||||
id: p.get_id(), rules: s};
|
||||
ret spanned(lo, hi, bloc);
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,8 @@ fn visit_fn<E>(f: _fn, _tp: [ty_param], _sp: span, _i: fn_ident, _id: node_id,
|
||||
}
|
||||
|
||||
fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
|
||||
for s: @stmt in b.node.stmts { v.visit_stmt(s, e, v); }
|
||||
for vi in b.node.view_items { v.visit_view_item(vi, e, v); }
|
||||
for s in b.node.stmts { v.visit_stmt(s, e, v); }
|
||||
visit_expr_opt(b.node.expr, e, v);
|
||||
}
|
||||
|
||||
|
11
src/test/run-pass/import-in-block.rs
Normal file
11
src/test/run-pass/import-in-block.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use std;
|
||||
|
||||
fn main() {
|
||||
import std::vec;
|
||||
import vec::to_mut;
|
||||
log vec::len(to_mut([1, 2]));
|
||||
{
|
||||
import vec::*;
|
||||
log len([2]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user