From cb8ecd79849160d8cff2eff8b070efd7f9a3b9a7 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 29 Aug 2012 12:22:05 -0700 Subject: [PATCH] Allow extern mods to be anonymous extern mod { f(); } is now allowed, and puts f in the enclosing scope. (Requires a link_name attribute to be really useful...) --- src/libsyntax/ast.rs | 11 ++++++++++- src/libsyntax/fold.rs | 3 ++- src/libsyntax/parse/parser.rs | 13 +++++++++---- src/libsyntax/parse/token.rs | 4 ++-- src/libsyntax/print/pprust.rs | 5 ++++- src/rustc/front/config.rs | 1 + src/rustc/middle/resolve3.rs | 28 +++++++++++++++++----------- src/test/run-pass/anon-extern-mod.rs | 9 +++++++++ 8 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 src/test/run-pass/anon-extern-mod.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a9df28abeba7..b04a55629d29 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -656,9 +656,14 @@ enum foreign_abi { foreign_abi_stdcall, } +// Foreign mods can be named or anonymous +#[auto_serialize] +enum foreign_mod_sort { named, anonymous } + #[auto_serialize] type foreign_mod = - {view_items: ~[@view_item], + {sort: foreign_mod_sort, + view_items: ~[@view_item], items: ~[@foreign_item]}; #[auto_serialize] @@ -775,6 +780,10 @@ type struct_def = { dtor: Option }; +/* + FIXME (#3300): Should allow items to be anonymous. Right now + we just use dummy names for anon items. + */ #[auto_serialize] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 2006ccf639c0..7375eb49aed1 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -554,7 +554,8 @@ fn noop_fold_mod(m: _mod, fld: ast_fold) -> _mod { } fn noop_fold_foreign_mod(nm: foreign_mod, fld: ast_fold) -> foreign_mod { - return {view_items: vec::map(nm.view_items, |x| fld.fold_view_item(x)), + return {sort: nm.sort, + view_items: vec::map(nm.view_items, |x| fld.fold_view_item(x)), items: vec::map(nm.items, |x| fld.fold_foreign_item(x))} } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8bc78a535485..f9a9a8261e9c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2890,7 +2890,8 @@ struct parser { } } - fn parse_foreign_mod_items(+first_item_attrs: ~[attribute]) -> + fn parse_foreign_mod_items(sort: ast::foreign_mod_sort, + +first_item_attrs: ~[attribute]) -> foreign_mod { // Shouldn't be any view items since we've already parsed an item attr let {attrs_remaining, view_items, items: _} = @@ -2905,7 +2906,7 @@ struct parser { initial_attrs = ~[]; vec::push(items, self.parse_foreign_item(attrs)); } - return {view_items: view_items, + return {sort: sort, view_items: view_items, items: items}; } @@ -2919,12 +2920,16 @@ struct parser { } else { self.expect_keyword(~"module"); } - let ident = self.parse_ident(); + let (sort, ident) = match self.token { + token::IDENT(*) => (ast::named, self.parse_ident()), + _ => (ast::anonymous, + token::special_idents::clownshoes_foreign_mod) + }; // extern mod { ... } if items_allowed && self.eat(token::LBRACE) { let extra_attrs = self.parse_inner_attrs_and_next(); - let m = self.parse_foreign_mod_items(extra_attrs.next); + let m = self.parse_foreign_mod_items(sort, extra_attrs.next); self.expect(token::RBRACE); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_foreign_mod(m), visibility, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 846a7e7c88e2..ae1c829b3fbb 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -319,7 +319,7 @@ mod special_idents { const blk : ident = 30u; const static : ident = 31u; const intrinsic : ident = 32u; - + const clownshoes_foreign_mod: ident = 33; } type ident_interner = util::interner::interner<@~str>; @@ -343,7 +343,7 @@ fn mk_ident_interner() -> ident_interner { @~"str", @~"ty_visitor", @~"arg", @~"descrim", @~"__rust_abi", @~"__rust_stack_shim", @~"tydesc", @~"dtor", @~"main", @~"", @~"blk", @~"static", - @~"intrinsic"]; + @~"intrinsic", @~"__foreign_mod__"]; let rv = interner::mk_prefill::<@~str>(|x| str::hash(*x), |x,y| str::eq(*x, *y), init_vec); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3465ca205659..f24226d9edc3 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -469,7 +469,10 @@ fn print_item(s: ps, &&item: @ast::item) { ast::item_foreign_mod(nmod) => { head(s, ~"extern"); word_nbsp(s, ~"mod"); - print_ident(s, item.ident); + match nmod.sort { + ast::named => print_ident(s, item.ident), + ast::anonymous => {} + } nbsp(s); bopen(s); print_foreign_mod(s, nmod, item.attrs); diff --git a/src/rustc/front/config.rs b/src/rustc/front/config.rs index 9c0f30468fc9..50ed5f6132ca 100644 --- a/src/rustc/front/config.rs +++ b/src/rustc/front/config.rs @@ -75,6 +75,7 @@ fn fold_foreign_mod(cx: ctxt, nm: ast::foreign_mod, let filtered_view_items = vec::filter_map( nm.view_items, view_item_filter); return { + sort: nm.sort, view_items: vec::map(filtered_view_items, |x| fld.fold_view_item(x)), items: filtered_items }; diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs index 1115e92a9de3..33260e1fe6f6 100644 --- a/src/rustc/middle/resolve3.rs +++ b/src/rustc/middle/resolve3.rs @@ -41,7 +41,7 @@ import syntax::ast::{ty_int, ty_param, ty_path, ty_str, ty_u, ty_u16, ty_u32}; import syntax::ast::{ty_u64, ty_u8, ty_uint, variant, view_item}; import syntax::ast::{view_item_export, view_item_import, view_item_use}; import syntax::ast::{view_path_glob, view_path_list, view_path_simple}; -import syntax::ast::{visibility}; +import syntax::ast::{visibility, anonymous, named}; import syntax::ast_util::{def_id_of_def, dummy_sp, local_def, new_def_hash}; import syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method}; import syntax::attr::{attr_metas, contains_name}; @@ -866,19 +866,25 @@ struct Resolver { visit_mod(module_, sp, item.id, new_parent, visitor); } - item_foreign_mod(*) => { - let (name_bindings, new_parent) = self.add_child(atom, parent, - ~[ModuleNS], sp); + item_foreign_mod(fm) => { + let new_parent = match fm.sort { + named => { + let (name_bindings, new_parent) = self.add_child(atom, + parent, ~[ModuleNS], sp); - let parent_link = self.get_parent_link(new_parent, atom); - let def_id = { crate: 0, node: item.id }; - (*name_bindings).define_module(parent_link, Some(def_id), - sp); + let parent_link = self.get_parent_link(new_parent, atom); + let def_id = { crate: 0, node: item.id }; + (*name_bindings).define_module(parent_link, Some(def_id), + sp); - let new_parent = - ModuleReducedGraphParent((*name_bindings).get_module()); + ModuleReducedGraphParent((*name_bindings).get_module()) + } + // For anon foreign mods, the contents just go in the + // current scope + anonymous => parent + }; - visit_item(item, new_parent, visitor); + visit_item(item, new_parent, visitor); } // These items live in the value namespace. diff --git a/src/test/run-pass/anon-extern-mod.rs b/src/test/run-pass/anon-extern-mod.rs new file mode 100644 index 000000000000..168a3ccc59b2 --- /dev/null +++ b/src/test/run-pass/anon-extern-mod.rs @@ -0,0 +1,9 @@ +#[abi = "cdecl"] +#[link_name = "rustrt"] +extern mod { + fn last_os_error() -> ~str; +} + +fn main() { + last_os_error(); +} \ No newline at end of file