diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 17 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/attr.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/codemap.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/diagnostics/macros.rs | 31 | ||||
| -rw-r--r-- | src/libsyntax/diagnostics/plugin.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 63 | ||||
| -rw-r--r-- | src/libsyntax/ext/mtwt.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/quote.rs | 122 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 151 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 42 |
13 files changed, 294 insertions, 190 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 98d858babb1..d4860766d47 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -31,6 +31,7 @@ pub use self::Lit_::*; pub use self::LitIntType::*; pub use self::LocalSource::*; pub use self::Mac_::*; +pub use self::MacStmtStyle::*; pub use self::MatchSource::*; pub use self::MetaItem_::*; pub use self::Method_::*; @@ -615,8 +616,20 @@ pub enum Stmt_ { /// Expr with trailing semi-colon (may have any type): StmtSemi(P<Expr>, NodeId), - /// bool: is there a trailing semi-colon? - StmtMac(Mac, bool), + StmtMac(Mac, MacStmtStyle), +} + +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub enum MacStmtStyle { + /// The macro statement had a trailing semicolon, e.g. `foo! { ... };` + /// `foo!(...);`, `foo![...];` + MacStmtWithSemicolon, + /// The macro statement had braces; e.g. foo! { ... } + MacStmtWithBraces, + /// The macro statement had parentheses or brackets and no semicolon; e.g. + /// `foo!(...)`. All of these will end up being converted into macro + /// expressions. + MacStmtWithoutBraces, } /// Where a local declaration came from: either a true `let ... = diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 2e097d45515..aaa172633be 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -753,16 +753,20 @@ macro_rules! mf_method{ impl PostExpansionMethod for Method { - mf_method!(pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident) - mf_method!(pe_generics,&'a ast::Generics, - MethDecl(_,ref generics,_,_,_,_,_,_),generics) - mf_method!(pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi) - mf_method!(pe_explicit_self,&'a ast::ExplicitSelf, - MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self) - mf_method!(pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety) - mf_method!(pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl) - mf_method!(pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body) - mf_method!(pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis) + mf_method! { pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident } + mf_method! { + pe_generics,&'a ast::Generics, + MethDecl(_,ref generics,_,_,_,_,_,_),generics + } + mf_method! { pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi } + mf_method! { + pe_explicit_self,&'a ast::ExplicitSelf, + MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self + } + mf_method! { pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety } + mf_method! { pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl } + mf_method! { pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body } + mf_method! { pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis } } #[cfg(test)] diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 8248eae4b8c..598da6a5df0 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -29,7 +29,7 @@ use std::cell::{RefCell, Cell}; use std::collections::BitvSet; use std::collections::HashSet; -thread_local!(static USED_ATTRS: RefCell<BitvSet> = RefCell::new(BitvSet::new())) +thread_local! { static USED_ATTRS: RefCell<BitvSet> = RefCell::new(BitvSet::new()) } pub fn mark_used(attr: &Attribute) { let AttrId(id) = attr.node.id; @@ -169,7 +169,7 @@ pub fn mk_word_item(name: InternedString) -> P<MetaItem> { P(dummy_spanned(MetaWord(name))) } -thread_local!(static NEXT_ATTR_ID: Cell<uint> = Cell::new(0)) +thread_local! { static NEXT_ATTR_ID: Cell<uint> = Cell::new(0) } pub fn mk_attr_id() -> AttrId { let id = NEXT_ATTR_ID.with(|slot| { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 592fdd7207c..17cafc2441f 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -329,7 +329,7 @@ impl FileMap { // the new charpos must be > the last one (or it's the first one). let mut lines = self.lines.borrow_mut(); let line_len = lines.len(); - assert!(line_len == 0 || ((*lines)[line_len - 1] < pos)) + assert!(line_len == 0 || ((*lines)[line_len - 1] < pos)); lines.push(pos); } diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index b4bf793d4e1..3107508a96a 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -11,44 +11,45 @@ #![macro_escape] #[macro_export] -macro_rules! register_diagnostic( - ($code:tt, $description:tt) => (__register_diagnostic!($code, $description)); - ($code:tt) => (__register_diagnostic!($code)) -) +macro_rules! register_diagnostic { + ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); + ($code:tt) => (__register_diagnostic! { $code }) +} #[macro_export] -macro_rules! span_err( +macro_rules! span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ __diagnostic_used!($code); $session.span_err_with_code($span, format!($($message)*).as_slice(), stringify!($code)) }) -) +} #[macro_export] -macro_rules! span_warn( +macro_rules! span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ __diagnostic_used!($code); $session.span_warn_with_code($span, format!($($message)*).as_slice(), stringify!($code)) }) -) +} #[macro_export] -macro_rules! span_note( +macro_rules! span_note { ($session:expr, $span:expr, $($message:tt)*) => ({ ($session).span_note($span, format!($($message)*).as_slice()) }) -) +} #[macro_export] -macro_rules! span_help( +macro_rules! span_help { ($session:expr, $span:expr, $($message:tt)*) => ({ ($session).span_help($span, format!($($message)*).as_slice()) }) -) +} #[macro_export] -macro_rules! register_diagnostics( +macro_rules! register_diagnostics { ($($code:tt),*) => ( - $(register_diagnostic!($code))* + $(register_diagnostic! { $code })* ) -) +} + diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index cb2a1f8acd8..bcce5538314 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -18,12 +18,16 @@ use ext::build::AstBuilder; use parse::token; use ptr::P; -thread_local!(static REGISTERED_DIAGNOSTICS: RefCell<HashMap<Name, Option<Name>>> = { - RefCell::new(HashMap::new()) -}) -thread_local!(static USED_DIAGNOSTICS: RefCell<HashMap<Name, Span>> = { - RefCell::new(HashMap::new()) -}) +thread_local! { + static REGISTERED_DIAGNOSTICS: RefCell<HashMap<Name, Option<Name>>> = { + RefCell::new(HashMap::new()) + } +} +thread_local! { + static USED_DIAGNOSTICS: RefCell<HashMap<Name, Span>> = { + RefCell::new(HashMap::new()) + } +} fn with_registered_diagnostics<T, F>(f: F) -> T where F: FnOnce(&mut HashMap<Name, Option<Name>>) -> T, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e280e6e4491..20c8ff20b71 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -11,7 +11,8 @@ use self::Either::*; use ast::{Block, Crate, DeclLocal, ExprMac, PatMac}; use ast::{Local, Ident, MacInvocTT}; -use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi}; +use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac}; +use ast::{StmtExpr, StmtSemi}; use ast::TokenTree; use ast; use ext::mtwt; @@ -354,7 +355,7 @@ fn expand_loop_block(loop_block: P<Block>, // eval $e with a new exts frame. // must be a macro so that $e isn't evaluated too early. -macro_rules! with_exts_frame ( +macro_rules! with_exts_frame { ($extsboxexpr:expr,$macros_escape:expr,$e:expr) => ({$extsboxexpr.push_frame(); $extsboxexpr.info().macros_escape = $macros_escape; @@ -362,7 +363,7 @@ macro_rules! with_exts_frame ( $extsboxexpr.pop_frame(); result }) -) +} // When we enter a module, record it, for the sake of `module!` pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander) @@ -636,8 +637,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) // I don't understand why this returns a vector... it looks like we're // half done adding machinery to allow macros to expand into multiple statements. fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> { - let (mac, semi) = match s.node { - StmtMac(mac, semi) => (mac, semi), + let (mac, style) = match s.node { + StmtMac(mac, style) => (mac, style), _ => return expand_non_macro_stmt(s, fld) }; let expanded_stmt = match expand_mac_invoc(mac, s.span, @@ -653,7 +654,7 @@ fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> { let fully_expanded = fld.fold_stmt(expanded_stmt); fld.cx.bt_pop(); - if semi { + if style == MacStmtWithSemicolon { fully_expanded.into_iter().map(|s| s.map(|Spanned {node, span}| { Spanned { node: match node { @@ -1324,7 +1325,7 @@ mod test { // make sure that macros can't escape fns #[should_fail] #[test] fn macros_cant_escape_fns_test () { - let src = "fn bogus() {macro_rules! z (() => (3+4))}\ + let src = "fn bogus() {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1338,7 +1339,7 @@ mod test { // make sure that macros can't escape modules #[should_fail] #[test] fn macros_cant_escape_mods_test () { - let src = "mod foo {macro_rules! z (() => (3+4))}\ + let src = "mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1350,7 +1351,7 @@ mod test { // macro_escape modules should allow macros to escape #[test] fn macros_can_escape_flattened_mods_test () { - let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\ + let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1402,13 +1403,13 @@ mod test { #[test] fn macro_tokens_should_match(){ expand_crate_str( - "macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_string()); + "macro_rules! m((a)=>(13)) ;fn main(){m!(a);}".to_string()); } // should be able to use a bound identifier as a literal in a macro definition: #[test] fn self_macro_parsing(){ expand_crate_str( - "macro_rules! foo ((zz) => (287u;)) + "macro_rules! foo ((zz) => (287u;)); fn f(zz : int) {foo!(zz);}".to_string() ); } @@ -1451,16 +1452,16 @@ mod test { ("fn main () {let x: int = 13;x;}", vec!(vec!(0)), false), // the use of b after the + should be renamed, the other one not: - ("macro_rules! f (($x:ident) => (b + $x)) fn a() -> int { let b = 13; f!(b)}", + ("macro_rules! f (($x:ident) => (b + $x)); fn a() -> int { let b = 13; f!(b)}", vec!(vec!(1)), false), // the b before the plus should not be renamed (requires marks) - ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})) fn a() -> int { f!(b)}", + ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})); fn a() -> int { f!(b)}", vec!(vec!(1)), false), // the marks going in and out of letty should cancel, allowing that $x to // capture the one following the semicolon. // this was an awesome test case, and caught a *lot* of bugs. - ("macro_rules! letty(($x:ident) => (let $x = 15;)) - macro_rules! user(($x:ident) => ({letty!($x); $x})) + ("macro_rules! letty(($x:ident) => (let $x = 15;)); + macro_rules! user(($x:ident) => ({letty!($x); $x})); fn main() -> int {user!(z)}", vec!(vec!(0)), false) ); @@ -1488,7 +1489,7 @@ mod test { #[test] fn issue_6994(){ run_renaming_test( &("macro_rules! g (($x:ident) => - ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)})) + ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)})); fn a(){g!(z)}", vec!(vec!(0)),false), 0) @@ -1498,7 +1499,7 @@ mod test { // fn z() {match 8 {x_1 => {match 9 {x_2 | x_2 if x_2 == x_1 => x_2 + x_1}}}} #[test] fn issue_9384(){ run_renaming_test( - &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}})) + &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}})); fn z() {match 8 {x => bad_macro!(x)}}", // NB: the third "binding" is the repeat of the second one. vec!(vec!(1,3),vec!(0,2),vec!(0,2)), @@ -1511,8 +1512,8 @@ mod test { // fn main(){let g1_1 = 13; g1_1}} #[test] fn pat_expand_issue_15221(){ run_renaming_test( - &("macro_rules! inner ( ($e:pat ) => ($e)) - macro_rules! outer ( ($e:pat ) => (inner!($e))) + &("macro_rules! inner ( ($e:pat ) => ($e)); + macro_rules! outer ( ($e:pat ) => (inner!($e))); fn main() { let outer!(g) = 13; g;}", vec!(vec!(0)), true), @@ -1527,8 +1528,8 @@ mod test { // method expands to fn get_x(&self_0, x_1:int) {self_0 + self_2 + x_3 + x_1} #[test] fn method_arg_hygiene(){ run_renaming_test( - &("macro_rules! inject_x (()=>(x)) - macro_rules! inject_self (()=>(self)) + &("macro_rules! inject_x (()=>(x)); + macro_rules! inject_self (()=>(self)); struct A; impl A{fn get_x(&self, x: int) {self + inject_self!() + inject_x!() + x;} }", vec!(vec!(0),vec!(3)), @@ -1542,8 +1543,8 @@ mod test { run_renaming_test( &("struct A; macro_rules! add_method (($T:ty) => - (impl $T { fn thingy(&self) {self;} })) - add_method!(A)", + (impl $T { fn thingy(&self) {self;} })); + add_method!(A);", vec!(vec!(0)), true), 0) @@ -1553,7 +1554,7 @@ mod test { // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};} #[test] fn issue_9383(){ run_renaming_test( - &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex })) + &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex })); fn q(x:int) { bad_macro!(x); }", vec!(vec!(1),vec!(0)),true), 0) @@ -1563,7 +1564,7 @@ mod test { // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);} #[test] fn closure_arg_hygiene(){ run_renaming_test( - &("macro_rules! inject_x (()=>(x)) + &("macro_rules! inject_x (()=>(x)); fn f(){(|x : int| {(inject_x!() + x)})(3);}", vec!(vec!(1)), true), @@ -1573,9 +1574,9 @@ mod test { // macro_rules in method position. Sadly, unimplemented. #[test] fn macro_in_method_posn(){ expand_crate_str( - "macro_rules! my_method (() => (fn thirteen(&self) -> int {13})) + "macro_rules! my_method (() => (fn thirteen(&self) -> int {13})); struct A; - impl A{ my_method!()} + impl A{ my_method!(); } fn f(){A.thirteen;}".to_string()); } @@ -1586,7 +1587,7 @@ mod test { &("macro_rules! item { ($i:item) => {$i}} struct Entries; macro_rules! iterator_impl { - () => { item!( impl Entries { fn size_hint(&self) { self;}})}} + () => { item!( impl Entries { fn size_hint(&self) { self;}});}} iterator_impl! { }", vec!(vec!(0)), true), 0) @@ -1666,9 +1667,9 @@ mod test { } #[test] fn fmt_in_macro_used_inside_module_macro() { - let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string())) -macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}})) -foo_module!() + let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string())); +macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}})); +foo_module!(); ".to_string(); let cr = expand_crate_str(crate_str); // find the xx binding diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index a4e06aeaf63..33936e6213f 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -108,7 +108,7 @@ pub fn apply_renames(renames: &RenameList, ctxt: SyntaxContext) -> SyntaxContext pub fn with_sctable<T, F>(op: F) -> T where F: FnOnce(&SCTable) -> T, { - thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal()) + thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal()); SCTABLE_KEY.with(move |slot| op(slot)) } @@ -174,7 +174,7 @@ fn with_resolve_table_mut<T, F>(op: F) -> T where { thread_local!(static RESOLVE_TABLE_KEY: RefCell<ResolveTable> = { RefCell::new(HashMap::new()) - }) + }); RESOLVE_TABLE_KEY.with(move |slot| op(&mut *slot.borrow_mut())) } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 45752499ad5..14e13feac98 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -100,7 +100,7 @@ pub mod rt { fn to_source_with_hygiene(&self) -> String; } - macro_rules! impl_to_source( + macro_rules! impl_to_source { (P<$t:ty>, $pp:ident) => ( impl ToSource for P<$t> { fn to_source(&self) -> String { @@ -125,7 +125,7 @@ pub mod rt { } } ); - ) + } fn slice_to_source<'a, T: ToSource>(sep: &'static str, xs: &'a [T]) -> String { xs.iter() @@ -144,7 +144,7 @@ pub mod rt { .to_string() } - macro_rules! impl_to_source_slice( + macro_rules! impl_to_source_slice { ($t:ty, $sep:expr) => ( impl ToSource for [$t] { fn to_source(&self) -> String { @@ -158,7 +158,7 @@ pub mod rt { } } ) - ) + } impl ToSource for ast::Ident { fn to_source(&self) -> String { @@ -172,18 +172,18 @@ pub mod rt { } } - impl_to_source!(ast::Ty, ty_to_string) - impl_to_source!(ast::Block, block_to_string) - impl_to_source!(ast::Arg, arg_to_string) - impl_to_source!(Generics, generics_to_string) - impl_to_source!(P<ast::Item>, item_to_string) - impl_to_source!(P<ast::Method>, method_to_string) - impl_to_source!(P<ast::Stmt>, stmt_to_string) - impl_to_source!(P<ast::Expr>, expr_to_string) - impl_to_source!(P<ast::Pat>, pat_to_string) - impl_to_source!(ast::Arm, arm_to_string) - impl_to_source_slice!(ast::Ty, ", ") - impl_to_source_slice!(P<ast::Item>, "\n\n") + impl_to_source! { ast::Ty, ty_to_string } + impl_to_source! { ast::Block, block_to_string } + impl_to_source! { ast::Arg, arg_to_string } + impl_to_source! { Generics, generics_to_string } + impl_to_source! { P<ast::Item>, item_to_string } + impl_to_source! { P<ast::Method>, method_to_string } + impl_to_source! { P<ast::Stmt>, stmt_to_string } + impl_to_source! { P<ast::Expr>, expr_to_string } + impl_to_source! { P<ast::Pat>, pat_to_string } + impl_to_source! { ast::Arm, arm_to_string } + impl_to_source_slice! { ast::Ty, ", " } + impl_to_source_slice! { P<ast::Item>, "\n\n" } impl ToSource for ast::Attribute_ { fn to_source(&self) -> String { @@ -244,7 +244,7 @@ pub mod rt { } } - macro_rules! impl_to_source_int( + macro_rules! impl_to_source_int { (signed, $t:ty, $tag:ident) => ( impl ToSource for $t { fn to_source(&self) -> String { @@ -272,23 +272,23 @@ pub mod rt { } } ); - ) + } - impl_to_source_int!(signed, int, TyI) - impl_to_source_int!(signed, i8, TyI8) - impl_to_source_int!(signed, i16, TyI16) - impl_to_source_int!(signed, i32, TyI32) - impl_to_source_int!(signed, i64, TyI64) + impl_to_source_int! { signed, int, TyI } + impl_to_source_int! { signed, i8, TyI8 } + impl_to_source_int! { signed, i16, TyI16 } + impl_to_source_int! { signed, i32, TyI32 } + impl_to_source_int! { signed, i64, TyI64 } - impl_to_source_int!(unsigned, uint, TyU) - impl_to_source_int!(unsigned, u8, TyU8) - impl_to_source_int!(unsigned, u16, TyU16) - impl_to_source_int!(unsigned, u32, TyU32) - impl_to_source_int!(unsigned, u64, TyU64) + impl_to_source_int! { unsigned, uint, TyU } + impl_to_source_int! { unsigned, u8, TyU8 } + impl_to_source_int! { unsigned, u16, TyU16 } + impl_to_source_int! { unsigned, u32, TyU32 } + impl_to_source_int! { unsigned, u64, TyU64 } // Alas ... we write these out instead. All redundant. - macro_rules! impl_to_tokens( + macro_rules! impl_to_tokens { ($t:ty) => ( impl ToTokens for $t { fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> { @@ -296,9 +296,9 @@ pub mod rt { } } ) - ) + } - macro_rules! impl_to_tokens_lifetime( + macro_rules! impl_to_tokens_lifetime { ($t:ty) => ( impl<'a> ToTokens for $t { fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> { @@ -306,36 +306,36 @@ pub mod rt { } } ) - ) - - impl_to_tokens!(ast::Ident) - impl_to_tokens!(P<ast::Item>) - impl_to_tokens!(P<ast::Pat>) - impl_to_tokens!(ast::Arm) - impl_to_tokens!(P<ast::Method>) - impl_to_tokens_lifetime!(&'a [P<ast::Item>]) - impl_to_tokens!(ast::Ty) - impl_to_tokens_lifetime!(&'a [ast::Ty]) - impl_to_tokens!(Generics) - impl_to_tokens!(P<ast::Stmt>) - impl_to_tokens!(P<ast::Expr>) - impl_to_tokens!(ast::Block) - impl_to_tokens!(ast::Arg) - impl_to_tokens!(ast::Attribute_) - impl_to_tokens_lifetime!(&'a str) - impl_to_tokens!(()) - impl_to_tokens!(char) - impl_to_tokens!(bool) - impl_to_tokens!(int) - impl_to_tokens!(i8) - impl_to_tokens!(i16) - impl_to_tokens!(i32) - impl_to_tokens!(i64) - impl_to_tokens!(uint) - impl_to_tokens!(u8) - impl_to_tokens!(u16) - impl_to_tokens!(u32) - impl_to_tokens!(u64) + } + + impl_to_tokens! { ast::Ident } + impl_to_tokens! { P<ast::Item> } + impl_to_tokens! { P<ast::Pat> } + impl_to_tokens! { ast::Arm } + impl_to_tokens! { P<ast::Method> } + impl_to_tokens_lifetime! { &'a [P<ast::Item>] } + impl_to_tokens! { ast::Ty } + impl_to_tokens_lifetime! { &'a [ast::Ty] } + impl_to_tokens! { Generics } + impl_to_tokens! { P<ast::Stmt> } + impl_to_tokens! { P<ast::Expr> } + impl_to_tokens! { ast::Block } + impl_to_tokens! { ast::Arg } + impl_to_tokens! { ast::Attribute_ } + impl_to_tokens_lifetime! { &'a str } + impl_to_tokens! { () } + impl_to_tokens! { char } + impl_to_tokens! { bool } + impl_to_tokens! { int } + impl_to_tokens! { i8 } + impl_to_tokens! { i16 } + impl_to_tokens! { i32 } + impl_to_tokens! { i64 } + impl_to_tokens! { uint } + impl_to_tokens! { u8 } + impl_to_tokens! { u16 } + impl_to_tokens! { u32 } + impl_to_tokens! { u64 } pub trait ExtParseUtils { fn parse_item(&self, s: String) -> P<ast::Item>; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 7d2acd08d94..10860ee5e01 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1485,7 +1485,7 @@ mod test { } // maybe add to expand.rs... - macro_rules! assert_pred ( + macro_rules! assert_pred { ($pred:expr, $predname:expr, $a:expr , $b:expr) => ( { let pred_val = $pred; @@ -1497,7 +1497,7 @@ mod test { } } ) - ) + } // make sure idents get transformed everywhere #[test] fn ident_transformation () { @@ -1523,6 +1523,6 @@ mod test { matches_codepattern, "matches_codepattern", pprust::to_string(|s| fake_print_crate(s, &folded_crate)), - "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))".to_string()); + "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string()); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6e3cfe5854a..c234c172fd8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -40,9 +40,10 @@ use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitStr, LitInt, Local, LocalLet}; +use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces}; use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchNormal}; use ast::{Method, MutTy, BiMul, Mutability}; -use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot}; +use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; use ast::{PolyTraitRef}; @@ -132,7 +133,7 @@ enum ItemOrViewItem { /// macro expansion). Placement of these is not as complex as I feared it would /// be. The important thing is to make sure that lookahead doesn't balk at /// `token::Interpolated` tokens. -macro_rules! maybe_whole_expr ( +macro_rules! maybe_whole_expr { ($p:expr) => ( { let found = match $p.token { @@ -170,10 +171,10 @@ macro_rules! maybe_whole_expr ( } } ) -) +} /// As maybe_whole_expr, but for things other than expressions -macro_rules! maybe_whole ( +macro_rules! maybe_whole { ($p:expr, $constructor:ident) => ( { let found = match ($p).token { @@ -252,7 +253,7 @@ macro_rules! maybe_whole ( } } ) -) +} fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>) @@ -3708,21 +3709,32 @@ impl<'a> Parser<'a> { ); let hi = self.span.hi; + let style = if delim == token::Brace { + MacStmtWithBraces + } else { + MacStmtWithoutBraces + }; + if id.name == token::special_idents::invalid.name { - if self.check(&token::Dot) { - let span = self.span; - let token_string = self.this_token_to_string(); - self.span_err(span, - format!("expected statement, found `{}`", - token_string).as_slice()); - let mac_span = mk_sp(lo, hi); - self.span_help(mac_span, "try parenthesizing this macro invocation"); - self.abort_if_errors(); - } - P(spanned(lo, hi, StmtMac( - spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT)), false))) + P(spanned(lo, + hi, + StmtMac(spanned(lo, + hi, + MacInvocTT(pth, tts, EMPTY_CTXT)), + style))) } else { // if it has a special ident, it's definitely an item + // + // Require a semicolon or braces. + if style != MacStmtWithBraces { + if !self.eat(&token::Semi) { + let last_span = self.last_span; + self.span_err(last_span, + "macros that expand to items must \ + either be surrounded with braces or \ + followed by a semicolon"); + } + } P(spanned(lo, hi, StmtDecl( P(spanned(lo, hi, DeclItem( self.mk_item( @@ -3731,7 +3743,6 @@ impl<'a> Parser<'a> { Inherited, Vec::new(/*no attrs*/))))), ast::DUMMY_NODE_ID))) } - } else { let found_attrs = !item_attrs.is_empty(); let item_err = Parser::expected_item_err(item_attrs.as_slice()); @@ -3851,43 +3862,46 @@ impl<'a> Parser<'a> { attributes_box = Vec::new(); stmt.and_then(|Spanned {node, span}| match node { StmtExpr(e, stmt_id) => { - // expression without semicolon - if classify::expr_requires_semi_to_be_stmt(&*e) { - // Just check for errors and recover; do not eat semicolon yet. - self.commit_stmt(&[], &[token::Semi, - token::CloseDelim(token::Brace)]); - } - + self.handle_expression_like_statement(e, + stmt_id, + span, + &mut stmts, + &mut expr); + } + StmtMac(macro, MacStmtWithoutBraces) => { + // statement macro without braces; might be an + // expr depending on whether a semicolon follows match self.token { token::Semi => { - self.bump(); - let span_with_semi = Span { - lo: span.lo, - hi: self.last_span.hi, - expn_id: span.expn_id, - }; stmts.push(P(Spanned { - node: StmtSemi(e, stmt_id), - span: span_with_semi, + node: StmtMac(macro, + MacStmtWithSemicolon), + span: span, })); - } - token::CloseDelim(token::Brace) => { - expr = Some(e); + self.bump(); } _ => { - stmts.push(P(Spanned { - node: StmtExpr(e, stmt_id), - span: span - })); + let e = self.mk_mac_expr(span.lo, + span.hi, + macro.node); + let e = + self.parse_dot_or_call_expr_with(e); + self.handle_expression_like_statement( + e, + ast::DUMMY_NODE_ID, + span, + &mut stmts, + &mut expr); } } } - StmtMac(m, semi) => { + StmtMac(m, style) => { // statement macro; might be an expr match self.token { token::Semi => { stmts.push(P(Spanned { - node: StmtMac(m, true), + node: StmtMac(m, + MacStmtWithSemicolon), span: span, })); self.bump(); @@ -3902,7 +3916,7 @@ impl<'a> Parser<'a> { } _ => { stmts.push(P(Spanned { - node: StmtMac(m, semi), + node: StmtMac(m, style), span: span })); } @@ -3941,6 +3955,43 @@ impl<'a> Parser<'a> { }) } + fn handle_expression_like_statement( + &mut self, + e: P<Expr>, + stmt_id: NodeId, + span: Span, + stmts: &mut Vec<P<Stmt>>, + last_block_expr: &mut Option<P<Expr>>) { + // expression without semicolon + if classify::expr_requires_semi_to_be_stmt(&*e) { + // Just check for errors and recover; do not eat semicolon yet. + self.commit_stmt(&[], + &[token::Semi, token::CloseDelim(token::Brace)]); + } + + match self.token { + token::Semi => { + self.bump(); + let span_with_semi = Span { + lo: span.lo, + hi: self.last_span.hi, + expn_id: span.expn_id, + }; + stmts.push(P(Spanned { + node: StmtSemi(e, stmt_id), + span: span_with_semi, + })); + } + token::CloseDelim(token::Brace) => *last_block_expr = Some(e), + _ => { + stmts.push(P(Spanned { + node: StmtExpr(e, stmt_id), + span: span + })); + } + } + } + // Parses a sequence of bounds if a `:` is found, // otherwise returns empty list. fn parse_colon_then_ty_param_bounds(&mut self) @@ -4591,6 +4642,9 @@ impl<'a> Parser<'a> { let m: ast::Mac = codemap::Spanned { node: m_, span: mk_sp(self.span.lo, self.span.hi) }; + if delim != token::Brace { + self.expect(&token::Semi) + } (ast::MethMac(m), self.span.hi, attrs) } else { let unsafety = self.parse_unsafety(); @@ -5747,6 +5801,17 @@ impl<'a> Parser<'a> { let m: ast::Mac = codemap::Spanned { node: m, span: mk_sp(self.span.lo, self.span.hi) }; + + if delim != token::Brace { + if !self.eat(&token::Semi) { + let last_span = self.last_span; + self.span_err(last_span, + "macros that expand to items must either \ + be surrounded with braces or followed by \ + a semicolon"); + } + } + let item_ = ItemMac(m); let last_span = self.last_span; let item = self.mk_item(lo, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 1bdcd73d847..641239f1f8b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -570,7 +570,7 @@ pub type IdentInterner = StrInterner; pub fn get_ident_interner() -> Rc<IdentInterner> { thread_local!(static KEY: Rc<::parse::token::IdentInterner> = { Rc::new(mk_fresh_ident_interner()) - }) + }); KEY.with(|k| k.clone()) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index cbbfcfef72e..1dd61a5ce19 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -409,12 +409,12 @@ pub fn arg_to_string(arg: &ast::Arg) -> String { } pub fn mac_to_string(arg: &ast::Mac) -> String { - $to_string(|s| s.print_mac(arg)) + $to_string(|s| s.print_mac(arg, ::parse::token::Paren)) } } } -thing_to_string_impls!(to_string) +thing_to_string_impls! { to_string } // FIXME (Issue #16472): the whole `with_hygiene` mod should go away // after we revise the syntax::ext::quote::ToToken impls to go directly @@ -437,7 +437,7 @@ pub mod with_hygiene { }) } - thing_to_string_impls!(to_string_hyg) + thing_to_string_impls! { to_string_hyg } } pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String { @@ -992,6 +992,7 @@ impl<'a> State<'a> { try!(self.popen()); try!(self.print_tts(tts.as_slice())); try!(self.pclose()); + try!(word(&mut self.s, ";")); try!(self.end()); } } @@ -1258,6 +1259,7 @@ impl<'a> State<'a> { try!(self.popen()); try!(self.print_tts(tts.as_slice())); try!(self.pclose()); + try!(word(&mut self.s, ";")); self.end() } } @@ -1330,11 +1332,16 @@ impl<'a> State<'a> { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ";")); } - ast::StmtMac(ref mac, semi) => { + ast::StmtMac(ref mac, style) => { try!(self.space_if_not_bol()); - try!(self.print_mac(mac)); - if semi { - try!(word(&mut self.s, ";")); + let delim = match style { + ast::MacStmtWithBraces => token::Brace, + _ => token::Paren + }; + try!(self.print_mac(mac, delim)); + match style { + ast::MacStmtWithBraces => {} + _ => try!(word(&mut self.s, ";")), } } } @@ -1461,15 +1468,24 @@ impl<'a> State<'a> { self.print_else(elseopt) } - pub fn print_mac(&mut self, m: &ast::Mac) -> IoResult<()> { + pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) + -> IoResult<()> { match m.node { // I think it's reasonable to hide the ctxt here: ast::MacInvocTT(ref pth, ref tts, _) => { try!(self.print_path(pth, false)); try!(word(&mut self.s, "!")); - try!(self.popen()); + match delim { + token::Paren => try!(self.popen()), + token::Bracket => try!(word(&mut self.s, "[")), + token::Brace => try!(self.bopen()), + } try!(self.print_tts(tts.as_slice())); - self.pclose() + match delim { + token::Paren => self.pclose(), + token::Bracket => word(&mut self.s, "]"), + token::Brace => self.bclose(m.span), + } } } } @@ -1817,7 +1833,7 @@ impl<'a> State<'a> { })); try!(self.pclose()); } - ast::ExprMac(ref m) => try!(self.print_mac(m)), + ast::ExprMac(ref m) => try!(self.print_mac(m, token::Paren)), ast::ExprParen(ref e) => { try!(self.popen()); try!(self.print_expr(&**e)); @@ -2098,7 +2114,7 @@ impl<'a> State<'a> { |s, p| s.print_pat(&**p))); try!(word(&mut self.s, "]")); } - ast::PatMac(ref m) => try!(self.print_mac(m)), + ast::PatMac(ref m) => try!(self.print_mac(m, token::Paren)), } self.ann.post(self, NodePat(pat)) } @@ -2187,7 +2203,7 @@ impl<'a> State<'a> { try!(self.nbsp()); try!(self.print_ident(name)); try!(self.print_generics(generics)); - try!(self.print_fn_args_and_ret(decl, opt_explicit_self)) + try!(self.print_fn_args_and_ret(decl, opt_explicit_self)); self.print_where_clause(generics) } |
