rustc: Implement explicit global scope resolution via leading "::"; add a test case

This commit is contained in:
Patrick Walton 2011-07-11 16:01:46 -07:00
parent 99a95b3613
commit 05390b4b38
8 changed files with 70 additions and 31 deletions

View File

@ -228,7 +228,8 @@ fn mk_test_desc_rec(&test_ctxt cx, ast::ident[] path) -> @ast::expr {
ident = "name",
expr = @name_expr));
let ast::path fn_path = nospan(rec(idents = path,
let ast::path fn_path = nospan(rec(global = false,
idents = path,
types = ~[]));
let ast::expr fn_expr = rec(id = cx.next_node_id(),
@ -280,7 +281,8 @@ fn mk_main(&test_ctxt cx) -> @ast::item {
fn mk_test_main_call(&test_ctxt cx) -> @ast::expr {
let ast::path test_path = nospan(rec(idents = ~["tests"],
let ast::path test_path = nospan(rec(global = false,
idents = ~["tests"],
types = ~[]));
let ast::expr_ test_path_expr_ = ast::expr_path(test_path);
@ -295,7 +297,8 @@ fn mk_test_main_call(&test_ctxt cx) -> @ast::expr {
node = test_call_expr_,
span = rec(lo=0u, hi=0u));
let ast::path test_main_path = nospan(rec(idents = ~["std",
let ast::path test_main_path = nospan(rec(global = false,
idents = ~["std",
"test",
"test_main"],
types = ~[]));

View File

@ -91,7 +91,7 @@ fn parse_path(@pstate st, str_def sd) -> ast::path {
case (?c) {
if (c == '(') {
ret respan(rec(lo=0u, hi=0u),
rec(idents=idents, types=~[]));
rec(global=false, idents=idents, types=~[]));
}
else {
idents += ~[parse_ident_(st, sd, is_last)];

View File

@ -44,7 +44,7 @@ export def_map;
// (FIXME See https://github.com/graydon/rust/issues/358 for the reason this
// isn't a const.)
tag scope {
scope_crate(@ast::crate);
scope_crate;
scope_item(@ast::item);
scope_fn(ast::fn_decl, ast::ty_param[]);
scope_native_item(@ast::native_item);
@ -154,7 +154,7 @@ fn map_crate(&@env e, &@ast::crate c) {
@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::visit_crate(*c, cons(scope_crate, @nil),
visit::mk_vt(v_map_mod));
// Register the top-level mod
@ -199,7 +199,7 @@ fn map_crate(&@env e, &@ast::crate c) {
@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::visit_crate(*c, cons(scope_crate, @nil),
visit::mk_vt(v_link_glob));
fn link_glob(@env e, &@ast::view_item vi, &scopes sc, &vt[scopes] v) {
fn find_mod(@env e, scopes sc) -> @indexed_mod {
@ -253,7 +253,7 @@ fn resolve_names(&@env e, &@ast::crate c) {
visit_constr=bind walk_constr(e, _, _, _),
visit_fn=bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
with *visit::default_visitor());
visit::visit_crate(*c, cons(scope_crate(c), @nil), visit::mk_vt(v));
visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v));
e.sess.abort_if_errors();
fn walk_expr(@env e, &@ast::expr exp, &scopes sc, &vt[scopes] v) {
@ -261,8 +261,8 @@ fn resolve_names(&@env e, &@ast::crate c) {
alt (exp.node) {
case (ast::expr_path(?p)) {
maybe_insert(e, exp.id,
lookup_path_strict(*e, sc, exp.span,
p.node.idents, ns_value));
lookup_path_strict(*e, sc, exp.span, p.node,
ns_value));
}
case (_) { }
}
@ -272,16 +272,16 @@ fn resolve_names(&@env e, &@ast::crate c) {
alt (t.node) {
case (ast::ty_path(?p, ?id)) {
maybe_insert(e, id,
lookup_path_strict(*e, sc, t.span,
p.node.idents, ns_type));
lookup_path_strict(*e, sc, t.span, p.node,
ns_type));
}
case (_) { }
}
}
fn walk_constr(@env e, &@ast::constr c, &scopes sc, &vt[scopes] v) {
maybe_insert(e, c.node.id,
lookup_path_strict(*e, sc, c.span,
c.node.path.node.idents, ns_value));
lookup_path_strict(*e, sc, c.span, c.node.path.node,
ns_value));
}
fn walk_arm(@env e, &ast::arm a, &scopes sc, &vt[scopes] v) {
for (@ast::pat p in a.pats) { walk_pat(*e, sc, p); }
@ -291,8 +291,7 @@ fn resolve_names(&@env e, &@ast::crate c) {
alt (pat.node) {
case (ast::pat_tag(?p, ?children)) {
auto fnd =
lookup_path_strict(e, sc, p.span, p.node.idents,
ns_value);
lookup_path_strict(e, sc, p.span, p.node, ns_value);
if (option::is_some(fnd)) {
alt (option::get(fnd)) {
case (ast::def_variant(?did, ?vid)) {
@ -396,7 +395,7 @@ fn follow_import(&env e, &scopes sc, &ident[] path, &span sp)
fn resolve_constr(@env e, node_id id, &@ast::constr c, &scopes sc,
&vt[scopes] v) {
auto new_def =
lookup_path_strict(*e, sc, c.span, c.node.path.node.idents, ns_value);
lookup_path_strict(*e, sc, c.span, c.node.path.node, ns_value);
if (option::is_some(new_def)) {
alt (option::get(new_def)) {
case (ast::def_fn(?pred_id, ast::pure_fn)) {
@ -543,16 +542,26 @@ fn mk_unresolved_msg(&ident id, &str kind) -> str {
}
// Lookup helpers
fn lookup_path_strict(&env e, &scopes sc, &span sp, &ident[] idents,
fn lookup_path_strict(&env e, &scopes sc, &span sp, &ast::path_ pth,
namespace ns) -> option::t[def] {
auto n_idents = ivec::len(idents);
auto n_idents = ivec::len(pth.idents);
auto headns = if (n_idents == 1u) { ns } else { ns_module };
auto dcur = lookup_in_scope_strict(e, sc, sp, idents.(0), headns);
auto first_scope;
if (pth.global) {
first_scope = list::cons(scope_crate, @list::nil);
} else {
first_scope = sc;
}
auto dcur = lookup_in_scope_strict(e, first_scope, sp, pth.idents.(0),
headns);
auto i = 1u;
while (i < n_idents && option::is_some(dcur)) {
auto curns = if (n_idents == i + 1u) { ns } else { ns_module };
dcur = lookup_in_mod_strict(e, option::get(dcur),
sp, idents.(i), curns, outside);
sp, pth.idents.(i), curns, outside);
i += 1u;
}
ret dcur;
@ -592,7 +601,7 @@ fn lookup_in_scope(&env e, scopes sc, &span sp, &ident name, namespace ns) ->
fn in_scope(&env e, &span sp, &ident name, &scope s, namespace ns) ->
option::t[def] {
alt (s) {
case (scope_crate(?c)) {
case (scope_crate) {
ret lookup_in_local_mod(e, -1, sp, name, ns, inside);
}
case (scope_item(?it)) {

View File

@ -16,7 +16,7 @@ type fn_ident = option::t[ident];
// FIXME: with typestate constraint, could say
// idents and types are the same length, and are
// non-empty
type path_ = rec(ident[] idents, (@ty)[] types);
type path_ = rec(bool global, ident[] idents, (@ty)[] types);
type path = spanned[path_];

View File

@ -63,7 +63,7 @@ fn pieces_to_expr(&ext_ctxt cx, span sp, vec[piece] pieces,
}
fn make_path_expr(&ext_ctxt cx, span sp, &ast::ident[] idents)
-> @ast::expr {
auto path = rec(idents=idents, types=~[]);
auto path = rec(global=false, idents=idents, types=~[]);
auto sp_path = rec(node=path, span=sp);
auto pathexpr = ast::expr_path(sp_path);
ret @rec(id=cx.next_id(), node=pathexpr, span=sp);

View File

@ -499,7 +499,8 @@ fn noop_fold_ident(&ident i, ast_fold fld) -> ident {
}
fn noop_fold_path(&path_ p, ast_fold fld) -> path_ {
ret rec(idents=ivec::map(fld.fold_ident, p.idents),
ret rec(global=p.global,
idents=ivec::map(fld.fold_ident, p.idents),
types=ivec::map(fld.fold_ty, p.types));
}

View File

@ -421,7 +421,8 @@ fn parse_ty_postfix(@ast::ty orig_t, &parser p) -> @ast::ty {
auto hi = p.get_hi_pos();
ret @spanned(lo, hi,
ast::ty_path(spanned(lo, hi,
rec(idents=pth.node.idents,
rec(global=pth.node.global,
idents=pth.node.idents,
types=seq_ivec)),
ann));
}
@ -556,7 +557,7 @@ fn parse_ty(&parser p) -> @ast::ty {
auto typ = parse_ty(p);
t = typ.node;
hi = typ.span.hi;
} else if (is_ident(p.peek())) {
} else if (p.peek() == token::MOD_SEP || is_ident(p.peek())) {
auto path = parse_path(p);
t = ast::ty_path(path, p.get_id());
hi = path.span.hi;
@ -673,6 +674,14 @@ fn is_ident(token::token t) -> bool {
fn parse_path(&parser p) -> ast::path {
auto lo = p.get_lo_pos();
auto hi = lo;
auto global;
if (p.peek() == token::MOD_SEP) {
global = true; p.bump();
} else {
global = false;
}
let ast::ident[] ids = ~[];
while (true) {
alt (p.peek()) {
@ -686,7 +695,7 @@ fn parse_path(&parser p) -> ast::path {
}
}
hi = p.get_hi_pos();
ret spanned(lo, hi, rec(idents=ids, types=~[]));
ret spanned(lo, hi, rec(global=global, idents=ids, types=~[]));
}
fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
@ -701,7 +710,9 @@ fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
for (@ast::ty typ in seq.node) { seq_ivec += ~[typ]; }
auto hi = p.get_hi_pos();
path = spanned(lo, hi, rec(idents=path.node.idents, types=seq_ivec));
path = spanned(lo, hi, rec(global=path.node.global,
idents=path.node.idents,
types=seq_ivec));
}
ret path;
}
@ -975,8 +986,9 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
parse_expr, p);
hi = es.span.hi;
ex = ast::expr_call(f, es.node);
} else if (is_ident(p.peek()) && !is_word(p, "true") &&
!is_word(p, "false")) {
} else if (p.peek() == token::MOD_SEP ||
(is_ident(p.peek()) && !is_word(p, "true") &&
!is_word(p, "false"))) {
check_bad_word(p);
auto pth = parse_path_and_ty_param_substs(p);
hi = pth.span.hi;

View File

@ -0,0 +1,14 @@
// xfail-stage0
fn f() -> int { ret 1; }
mod foo {
fn f() -> int { ret 2; }
fn g() {
assert (f() == 2);
assert (::f() == 1);
}
}
fn main() { ret foo::g(); }