diff --git a/src/libfourcc/lib.rs b/src/libfourcc/lib.rs index 267b0592d76..50cdd6cedc2 100644 --- a/src/libfourcc/lib.rs +++ b/src/libfourcc/lib.rs @@ -57,7 +57,7 @@ use syntax::ast::Name; use syntax::attr::contains; use syntax::codemap::{Span, mk_sp}; use syntax::ext::base; -use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr}; +use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr}; use syntax::ext::build::AstBuilder; use syntax::parse; use syntax::parse::token; @@ -73,7 +73,7 @@ pub fn macro_registrar(register: |Name, SyntaxExtension|) { None)); } -pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { +pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult { let (expr, endian) = parse_tts(cx, tts); let little = match endian { @@ -101,12 +101,12 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> } _ => { cx.span_err(expr.span, "unsupported literal in fourcc!"); - return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32))); + return base::DummyResult::expr(sp) } }, _ => { cx.span_err(expr.span, "non-literal in fourcc!"); - return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32))); + return base::DummyResult::expr(sp) } }; @@ -126,7 +126,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> }; } let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32)); - MRExpr(e) + MacExpr::new(e) } struct Ident { diff --git a/src/libhexfloat/lib.rs b/src/libhexfloat/lib.rs index 9f2f417080f..e65b84091e5 100644 --- a/src/libhexfloat/lib.rs +++ b/src/libhexfloat/lib.rs @@ -53,7 +53,7 @@ use syntax::ast; use syntax::ast::Name; use syntax::codemap::{Span, mk_sp}; use syntax::ext::base; -use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr}; +use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr}; use syntax::ext::build::AstBuilder; use syntax::parse; use syntax::parse::token; @@ -97,7 +97,7 @@ fn hex_float_lit_err(s: &str) -> Option<(uint, ~str)> { } } -pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { +pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult { let (expr, ty_lit) = parse_tts(cx, tts); let ty = match ty_lit { @@ -121,12 +121,12 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> } _ => { cx.span_err(expr.span, "unsupported literal in hexfloat!"); - return base::MacResult::dummy_expr(sp); + return base::DummyResult::expr(sp); } }, _ => { cx.span_err(expr.span, "non-literal in hexfloat!"); - return base::MacResult::dummy_expr(sp); + return base::DummyResult::expr(sp); } }; @@ -137,7 +137,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1); let span = syntax::codemap::mk_sp(pos,pos); cx.span_err(span, format!("invalid hex float literal in hexfloat!: {}", err_str)); - return base::MacResult::dummy_expr(sp); + return base::DummyResult::expr(sp); } _ => () } @@ -147,7 +147,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> None => ast::LitFloatUnsuffixed(s), Some (ty) => ast::LitFloat(s, ty) }; - MRExpr(cx.expr_lit(sp, lit)) + MacExpr::new(cx.expr_lit(sp, lit)) } struct Ident { diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 9371f817ac8..efefe885acb 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -45,7 +45,7 @@ impl State { static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"]; pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { let mut p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.iter() @@ -72,7 +72,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) "inline assembly must be a string literal.") { Some((s, st)) => (s, st), // let compilation continue - None => return MacResult::dummy_expr(sp), + None => return DummyResult::expr(sp), }; asm = s; asm_str_style = Some(style); @@ -210,7 +210,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) inputs.push((token::intern_and_get_ident(i.to_str()), out)); } - MRExpr(@ast::Expr { + MacExpr::new(@ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprInlineAsm(ast::InlineAsm { asm: token::intern_and_get_ident(asm.get()), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 3bf1ed95f38..90bde60621d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -50,19 +50,19 @@ pub trait MacroExpander { ecx: &mut ExtCtxt, span: Span, token_tree: &[ast::TokenTree]) - -> MacResult; + -> ~MacResult; } pub type MacroExpanderFn = fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree]) - -> MacResult; + -> ~MacResult; impl MacroExpander for BasicMacroExpander { fn expand(&self, ecx: &mut ExtCtxt, span: Span, token_tree: &[ast::TokenTree]) - -> MacResult { + -> ~MacResult { (self.expander)(ecx, span, token_tree) } } @@ -78,7 +78,7 @@ pub trait IdentMacroExpander { sp: Span, ident: ast::Ident, token_tree: Vec ) - -> MacResult; + -> ~MacResult; } impl IdentMacroExpander for BasicIdentMacroExpander { @@ -87,62 +87,130 @@ impl IdentMacroExpander for BasicIdentMacroExpander { sp: Span, ident: ast::Ident, token_tree: Vec ) - -> MacResult { + -> ~MacResult { (self.expander)(cx, sp, ident, token_tree) } } pub type IdentMacroExpanderFn = - fn(&mut ExtCtxt, Span, ast::Ident, Vec ) -> MacResult; + fn(&mut ExtCtxt, Span, ast::Ident, Vec ) -> ~MacResult; pub type MacroCrateRegistrationFun = fn(|ast::Name, SyntaxExtension|); -pub trait AnyMacro { - fn make_expr(&self) -> @ast::Expr; - fn make_items(&self) -> SmallVector<@ast::Item>; - fn make_stmt(&self) -> @ast::Stmt; +/// The result of a macro expansion. The return values of the various +/// methods are spliced into the AST at the callsite of the macro (or +/// just into the compiler's internal macro table, for `make_def`). +pub trait MacResult { + /// Define a new macro. + fn make_def(&self) -> Option { + None + } + /// Create an expression. + fn make_expr(&self) -> Option<@ast::Expr> { + None + } + /// Create zero or more items. + fn make_items(&self) -> Option> { + None + } + + /// Create a statement. + /// + /// By default this attempts to create an expression statement, + /// returning None if that fails. + fn make_stmt(&self) -> Option<@ast::Stmt> { + self.make_expr() + .map(|e| @codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID))) + } } - -pub enum MacResult { - MRExpr(@ast::Expr), - MRItem(@ast::Item), - MRAny(~AnyMacro:), - MRDef(MacroDef), +/// A convenience type for macros that return a single expression. +pub struct MacExpr { + e: @ast::Expr } -impl MacResult { - /// Create an empty expression MacResult; useful for satisfying - /// type signatures after emitting a non-fatal error (which stop - /// compilation well before the validity (or otherwise)) of the - /// expression are checked. - pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr { +impl MacExpr { + pub fn new(e: @ast::Expr) -> ~MacResult { + ~MacExpr { e: e } as ~MacResult + } +} +impl MacResult for MacExpr { + fn make_expr(&self) -> Option<@ast::Expr> { + Some(self.e) + } +} +/// A convenience type for macros that return a single item. +pub struct MacItem { + i: @ast::Item +} +impl MacItem { + pub fn new(i: @ast::Item) -> ~MacResult { + ~MacItem { i: i } as ~MacResult + } +} +impl MacResult for MacItem { + fn make_items(&self) -> Option> { + Some(SmallVector::one(self.i)) + } + fn make_stmt(&self) -> Option<@ast::Stmt> { + Some(@codemap::respan( + self.i.span, + ast::StmtDecl( + @codemap::respan(self.i.span, ast::DeclItem(self.i)), + ast::DUMMY_NODE_ID))) + } +} + +/// Fill-in macro expansion result, to allow compilation to continue +/// after hitting errors. +pub struct DummyResult { + expr_only: bool, + span: Span +} + +impl DummyResult { + /// Create a default MacResult that can be anything. + /// + /// Use this as a return value after hitting any errors and + /// calling `span_err`. + pub fn any(sp: Span) -> ~MacResult { + ~DummyResult { expr_only: false, span: sp } as ~MacResult + } + + /// Create a default MacResult that can only be an expression. + /// + /// Use this for macros that must expand to an expression, so even + /// if an error is encountered internally, the user will recieve + /// an error that they also used it in the wrong place. + pub fn expr(sp: Span) -> ~MacResult { + ~DummyResult { expr_only: true, span: sp } as ~MacResult + } + + /// A plain dummy expression. + pub fn raw_expr(sp: Span) -> @ast::Expr { @ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)), span: sp, } } - pub fn dummy_expr(sp: codemap::Span) -> MacResult { - MRExpr(MacResult::raw_dummy_expr(sp)) - } - pub fn dummy_any(sp: codemap::Span) -> MacResult { - MRAny(~DummyMacResult { sp: sp }) - } } -struct DummyMacResult { - sp: codemap::Span -} -impl AnyMacro for DummyMacResult { - fn make_expr(&self) -> @ast::Expr { - MacResult::raw_dummy_expr(self.sp) + +impl MacResult for DummyResult { + fn make_expr(&self) -> Option<@ast::Expr> { + Some(DummyResult::raw_expr(self.span)) } - fn make_items(&self) -> SmallVector<@ast::Item> { - SmallVector::zero() + fn make_items(&self) -> Option> { + if self.expr_only { + None + } else { + Some(SmallVector::zero()) + } } - fn make_stmt(&self) -> @ast::Stmt { - @codemap::respan(self.sp, - ast::StmtExpr(MacResult::raw_dummy_expr(self.sp), ast::DUMMY_NODE_ID)) + fn make_stmt(&self) -> Option<@ast::Stmt> { + Some(@codemap::respan(self.span, + ast::StmtExpr(DummyResult::raw_expr(self.span), + ast::DUMMY_NODE_ID))) } } diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs index ba6ad4888e2..f4680b27084 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -18,10 +18,10 @@ use ext::build::AstBuilder; use std::char; -pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { +pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult { // Gather all argument expressions let exprs = match get_exprs_from_tts(cx, sp, tts) { - None => return MacResult::dummy_expr(sp), + None => return DummyResult::expr(sp), Some(e) => e, }; let mut bytes = Vec::new(); @@ -74,5 +74,5 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> } let e = cx.expr_vec_slice(sp, bytes); - MRExpr(e) + MacExpr::new(e) } diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs index d83a386554e..8cd899738bf 100644 --- a/src/libsyntax/ext/cfg.rs +++ b/src/libsyntax/ext/cfg.rs @@ -26,7 +26,7 @@ use parse::token::InternedString; use parse::token; use parse; -pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { +pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult { let mut p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.iter() @@ -47,5 +47,5 @@ pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::M let matches_cfg = attr::test_cfg(cx.cfg().as_slice(), in_cfg.iter().map(|&x| x)); let e = cx.expr_bool(sp, matches_cfg); - MRExpr(e) + MacExpr::new(e) } diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs index 1db65e3b9e4..123271c5b5e 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -19,10 +19,10 @@ use std::strbuf::StrBuf; pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, sp: codemap::Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { let es = match base::get_exprs_from_tts(cx, sp, tts) { Some(e) => e, - None => return base::MacResult::dummy_expr(sp) + None => return base::DummyResult::expr(sp) }; let mut accumulator = StrBuf::new(); for e in es.move_iter() { @@ -57,7 +57,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, } } } - base::MRExpr(cx.expr_str( + base::MacExpr::new(cx.expr_str( sp, token::intern_and_get_ident(accumulator.into_owned()))) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index a5faa693982..9513c15c3d0 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -19,7 +19,7 @@ use parse::token::{str_to_ident}; use std::strbuf::StrBuf; pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { let mut res_str = StrBuf::new(); for (i, e) in tts.iter().enumerate() { if i & 1 == 1 { @@ -27,7 +27,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ast::TTTok(_, token::COMMA) => (), _ => { cx.span_err(sp, "concat_idents! expecting comma."); - return MacResult::dummy_expr(sp); + return DummyResult::expr(sp); } } } else { @@ -37,7 +37,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } _ => { cx.span_err(sp, "concat_idents! requires ident args."); - return MacResult::dummy_expr(sp); + return DummyResult::expr(sp); } } } @@ -61,5 +61,5 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ), span: sp, }; - MRExpr(e) + MacExpr::new(e) } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index ecf63c8257d..7229f5c1df9 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -24,9 +24,9 @@ use parse::token; use std::os; pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { - None => return MacResult::dummy_expr(sp), + None => return DummyResult::expr(sp), Some(v) => v }; @@ -56,24 +56,24 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) s)))) } }; - MRExpr(e) + MacExpr::new(e) } pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { let exprs = match get_exprs_from_tts(cx, sp, tts) { Some(ref exprs) if exprs.len() == 0 => { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return MacResult::dummy_expr(sp); + return DummyResult::expr(sp); } - None => return MacResult::dummy_expr(sp), + None => return DummyResult::expr(sp), Some(exprs) => exprs }; let var = match expr_to_str(cx, *exprs.get(0), "expected string literal") { - None => return MacResult::dummy_expr(sp), + None => return DummyResult::expr(sp), Some((v, _style)) => v }; let msg = match exprs.len() { @@ -84,13 +84,13 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } 2 => { match expr_to_str(cx, *exprs.get(1), "expected string literal") { - None => return MacResult::dummy_expr(sp), + None => return DummyResult::expr(sp), Some((s, _style)) => s } } _ => { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return MacResult::dummy_expr(sp); + return DummyResult::expr(sp); } }; @@ -101,5 +101,5 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s)) }; - MRExpr(e) + MacExpr::new(e) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1cff1d0f295..d73cb3856f9 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -52,7 +52,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { format!("expected macro name without module \ separators")); // let compilation continue - return MacResult::raw_dummy_expr(e.span); + return DummyResult::raw_expr(e.span); } let extname = pth.segments.get(0).identifier; let extnamestr = token::get_ident(extname); @@ -65,7 +65,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { extnamestr.get())); // let compilation continue - return MacResult::raw_dummy_expr(e.span); + return DummyResult::raw_expr(e.span); } Some(&NormalTT(ref expandfun, exp_span)) => { fld.cx.bt_push(ExpnInfo { @@ -88,10 +88,9 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { let expanded = match expandfun.expand(fld.cx, mac_span.call_site, - marked_before.as_slice()) { - MRExpr(e) => e, - MRAny(any_macro) => any_macro.make_expr(), - _ => { + marked_before.as_slice()).make_expr() { + Some(e) => e, + None => { fld.cx.span_err( pth.span, format!( @@ -99,7 +98,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { extnamestr.get() ) ); - return MacResult::raw_dummy_expr(e.span); + return DummyResult::raw_expr(e.span); } }; @@ -112,7 +111,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { format!("'{}' is not a tt-style macro", extnamestr.get()) ); - return MacResult::raw_dummy_expr(e.span); + return DummyResult::raw_expr(e.span); } }; @@ -430,25 +429,8 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) } }; - let items = match expanded { - MRItem(it) => { - mark_item(it,fm).move_iter() - .flat_map(|i| fld.fold_item(i).move_iter()) - .collect() - } - MRExpr(_) => { - fld.cx.span_err(pth.span, - format!("expr macro in item position: {}", - extnamestr.get())); - return SmallVector::zero(); - } - MRAny(any_macro) => { - any_macro.make_items().move_iter() - .flat_map(|i| mark_item(i, fm).move_iter()) - .flat_map(|i| fld.fold_item(i).move_iter()) - .collect() - } - MRDef(MacroDef { name, ext }) => { + let items = match expanded.make_def() { + Some(MacroDef { name, ext }) => { // yikes... no idea how to apply the mark to this. I'm afraid // we're going to have to wait-and-see on this one. fld.extsbox.insert(intern(name), ext); @@ -458,6 +440,22 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) SmallVector::zero() } } + None => { + match expanded.make_items() { + Some(items) => { + items.move_iter() + .flat_map(|i| mark_item(i, fm).move_iter()) + .flat_map(|i| fld.fold_item(i).move_iter()) + .collect() + } + None => { + fld.cx.span_err(pth.span, + format!("expr macro in item position: {}", + extnamestr.get())); + return SmallVector::zero(); + } + } + } }; fld.cx.bt_pop(); return items; @@ -593,15 +591,9 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { let expanded = match expandfun.expand(fld.cx, mac_span.call_site, - marked_tts.as_slice()) { - MRExpr(e) => { - @codemap::Spanned { - node: StmtExpr(e, ast::DUMMY_NODE_ID), - span: e.span, - } - } - MRAny(any_macro) => any_macro.make_stmt(), - _ => { + marked_tts.as_slice()).make_stmt() { + Some(stmt) => stmt, + None => { fld.cx.span_err(pth.span, format!("non-stmt macro in stmt pos: {}", extnamestr)); diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 411bf921dd2..41c74ce9ae5 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -16,11 +16,11 @@ use ext::base; use ext::build::AstBuilder; pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt, sp: Span, - _tts: &[ast::TokenTree]) -> base::MacResult { + _tts: &[ast::TokenTree]) -> ~base::MacResult { ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead"); ecx.parse_sess.span_diagnostic.span_note(sp, "see http://static.rust-lang.org/doc/master/std/fmt/index.html \ for documentation"); - base::MRExpr(ecx.expr_uint(sp, 2)) + base::MacExpr::new(ecx.expr_uint(sp, 2)) } diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index cc0f26dcc2f..86c7ae28ac2 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -806,14 +806,14 @@ impl<'a, 'b> Context<'a, 'b> { } pub fn expand_args(ecx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { match parse_args(ecx, sp, tts) { (extra, Some((efmt, args, order, names))) => { - MRExpr(expand_preparsed_format_args(ecx, sp, extra, efmt, args, + MacExpr::new(expand_preparsed_format_args(ecx, sp, extra, efmt, args, order, names)) } - (_, None) => MRExpr(ecx.expr_uint(sp, 2)) + (_, None) => MacExpr::new(ecx.expr_uint(sp, 2)) } } @@ -845,7 +845,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, efmt, "format argument must be a string literal.") { Some((fmt, _)) => fmt, - None => return MacResult::raw_dummy_expr(sp) + None => return DummyResult::raw_expr(sp) }; let mut parser = parse::Parser::new(fmt.get()); @@ -863,7 +863,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, match parser.errors.shift() { Some(error) => { cx.ecx.span_err(efmt.span, "invalid format string: " + error); - return MacResult::raw_dummy_expr(sp); + return DummyResult::raw_expr(sp); } None => {} } diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs index c9e444a9b8c..666bc486fbf 100644 --- a/src/libsyntax/ext/log_syntax.rs +++ b/src/libsyntax/ext/log_syntax.rs @@ -18,12 +18,12 @@ use std::rc::Rc; pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, sp: codemap::Span, tt: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { cx.print_backtrace(); println!("{}", print::pprust::tt_to_str(&ast::TTDelim( Rc::new(tt.iter().map(|x| (*x).clone()).collect())))); // any so that `log_syntax` can be invoked as an expression and item. - base::MacResult::dummy_any(sp) + base::DummyResult::any(sp) } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 6f8656f494d..7664d089149 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -289,53 +289,53 @@ pub mod rt { pub fn expand_quote_tokens(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { let (cx_expr, expr) = expand_tts(cx, sp, tts); let expanded = expand_wrapper(cx, sp, cx_expr, expr); - base::MRExpr(expanded) + base::MacExpr::new(expanded) } pub fn expand_quote_expr(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts); - base::MRExpr(expanded) + base::MacExpr::new(expanded) } pub fn expand_quote_item(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { let e_attrs = cx.expr_vec_ng(sp); let expanded = expand_parse_call(cx, sp, "parse_item", vec!(e_attrs), tts); - base::MRExpr(expanded) + base::MacExpr::new(expanded) } pub fn expand_quote_pat(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { let e_refutable = cx.expr_lit(sp, ast::LitBool(true)); let expanded = expand_parse_call(cx, sp, "parse_pat", vec!(e_refutable), tts); - base::MRExpr(expanded) + base::MacExpr::new(expanded) } pub fn expand_quote_ty(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { let e_param_colons = cx.expr_lit(sp, ast::LitBool(false)); let expanded = expand_parse_call(cx, sp, "parse_ty", vec!(e_param_colons), tts); - base::MRExpr(expanded) + base::MacExpr::new(expanded) } pub fn expand_quote_stmt(cx: &mut ExtCtxt, sp: Span, - tts: &[ast::TokenTree]) -> base::MacResult { + tts: &[ast::TokenTree]) -> ~base::MacResult { let e_attrs = cx.expr_vec_ng(sp); let expanded = expand_parse_call(cx, sp, "parse_stmt", vec!(e_attrs), tts); - base::MRExpr(expanded) + base::MacExpr::new(expanded) } fn ids_ext(strs: Vec<~str> ) -> Vec { diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 008532bcafe..7f1d8172255 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -29,63 +29,63 @@ use std::str; /* line!(): expands to the current line number */ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { base::check_zero_tts(cx, sp, tts, "line!"); let topmost = topmost_expn_info(cx.backtrace().unwrap()); let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo); - base::MRExpr(cx.expr_uint(topmost.call_site, loc.line)) + base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.line)) } /* col!(): expands to the current column number */ pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { base::check_zero_tts(cx, sp, tts, "col!"); let topmost = topmost_expn_info(cx.backtrace().unwrap()); let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo); - base::MRExpr(cx.expr_uint(topmost.call_site, loc.col.to_uint())) + base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.col.to_uint())) } /* file!(): expands to the current filename */ /* The filemap (`loc.file`) contains a bunch more information we could spit * out if we wanted. */ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { base::check_zero_tts(cx, sp, tts, "file!"); let topmost = topmost_expn_info(cx.backtrace().unwrap()); let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo); let filename = token::intern_and_get_ident(loc.file.name); - base::MRExpr(cx.expr_str(topmost.call_site, filename)) + base::MacExpr::new(cx.expr_str(topmost.call_site, filename)) } pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { let s = pprust::tts_to_str(tts); - base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(s))) + base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(s))) } pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { base::check_zero_tts(cx, sp, tts, "module_path!"); let string = cx.mod_path() .iter() .map(|x| token::get_ident(*x).get().to_str()) .collect::>() .connect("::"); - base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(string))) + base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(string))) } // include! : parse the given file as an expr // This is generally a bad idea because it's going to behave // unhygienically. pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { let file = match get_single_str_from_tts(cx, sp, tts, "include!") { Some(f) => f, - None => return MacResult::dummy_expr(sp), + None => return DummyResult::expr(sp), }; // The file will be added to the code map by the parser let mut p = @@ -95,21 +95,21 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) sp, &Path::new(file)), sp); - base::MRExpr(p.parse_expr()) + base::MacExpr::new(p.parse_expr()) } // include_str! : read the given file, insert it as a literal string expr pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { Some(f) => f, - None => return MacResult::dummy_expr(sp) + None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, &Path::new(file)); let bytes = match File::open(&file).read_to_end() { Err(e) => { cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e)); - return MacResult::dummy_expr(sp); + return DummyResult::expr(sp); } Ok(bytes) => bytes, }; @@ -121,31 +121,31 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let interned = token::intern_and_get_ident(src); cx.codemap().new_filemap(filename, src.to_owned()); - base::MRExpr(cx.expr_str(sp, interned)) + base::MacExpr::new(cx.expr_str(sp, interned)) } None => { cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display())); - return MacResult::dummy_expr(sp); + return DummyResult::expr(sp); } } } pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> base::MacResult + -> ~base::MacResult { let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") { Some(f) => f, - None => return MacResult::dummy_expr(sp) + None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, &Path::new(file)); match File::open(&file).read_to_end() { Err(e) => { cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e)); - return MacResult::dummy_expr(sp); + return DummyResult::expr(sp); } Ok(bytes) => { let bytes = bytes.iter().map(|x| *x).collect(); - base::MRExpr(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes)))) + base::MacExpr::new(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes)))) } } } diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index 173cf4c9ad9..d428251604c 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -17,7 +17,7 @@ use parse::token::{keywords, is_keyword}; pub fn expand_trace_macros(cx: &mut ExtCtxt, sp: Span, tt: &[ast::TokenTree]) - -> base::MacResult { + -> ~base::MacResult { match tt { [ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => { cx.set_trace_macros(true); @@ -28,5 +28,5 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt, _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"), } - base::MacResult::dummy_any(sp) + base::DummyResult::any(sp) } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index d4a883a63eb..279544d106e 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -12,7 +12,7 @@ use ast::{Ident, Matcher_, Matcher, MatchTok, MatchNonterminal, MatchSeq}; use ast::{TTDelim}; use ast; use codemap::{Span, Spanned, DUMMY_SP}; -use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef}; +use ext::base::{ExtCtxt, MacResult, MacroDef}; use ext::base::{NormalTT, MacroExpander}; use ext::base; use ext::tt::macro_parser::{Success, Error, Failure}; @@ -57,13 +57,13 @@ impl<'a> ParserAnyMacro<'a> { } } -impl<'a> AnyMacro for ParserAnyMacro<'a> { - fn make_expr(&self) -> @ast::Expr { +impl<'a> MacResult for ParserAnyMacro<'a> { + fn make_expr(&self) -> Option<@ast::Expr> { let ret = self.parser.borrow_mut().parse_expr(); self.ensure_complete_parse(true); - ret + Some(ret) } - fn make_items(&self) -> SmallVector<@ast::Item> { + fn make_items(&self) -> Option> { let mut ret = SmallVector::zero(); loop { let mut parser = self.parser.borrow_mut(); @@ -74,13 +74,13 @@ impl<'a> AnyMacro for ParserAnyMacro<'a> { } } self.ensure_complete_parse(false); - ret + Some(ret) } - fn make_stmt(&self) -> @ast::Stmt { + fn make_stmt(&self) -> Option<@ast::Stmt> { let attrs = self.parser.borrow_mut().parse_outer_attributes(); let ret = self.parser.borrow_mut().parse_stmt(attrs); self.ensure_complete_parse(true); - ret + Some(ret) } } @@ -95,7 +95,7 @@ impl MacroExpander for MacroRulesMacroExpander { cx: &mut ExtCtxt, sp: Span, arg: &[ast::TokenTree]) - -> MacResult { + -> ~MacResult { generic_extension(cx, sp, self.name, @@ -105,6 +105,15 @@ impl MacroExpander for MacroRulesMacroExpander { } } +struct MacroRulesDefiner { + def: RefCell> +} +impl MacResult for MacroRulesDefiner { + fn make_def(&self) -> Option { + Some(self.def.borrow_mut().take().expect("MacroRulesDefiner expanded twice")) + } +} + // Given `lhses` and `rhses`, this is the new macro we create fn generic_extension(cx: &ExtCtxt, sp: Span, @@ -112,7 +121,7 @@ fn generic_extension(cx: &ExtCtxt, arg: &[ast::TokenTree], lhses: &[Rc], rhses: &[Rc]) - -> MacResult { + -> ~MacResult { if cx.trace_macros() { println!("{}! \\{ {} \\}", token::get_ident(name), @@ -160,9 +169,9 @@ fn generic_extension(cx: &ExtCtxt, let p = Parser(cx.parse_sess(), cx.cfg(), ~trncbr); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. - return MRAny(~ParserAnyMacro { + return ~ParserAnyMacro { parser: RefCell::new(p), - }) + } as ~MacResult } Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { best_fail_spot = sp; @@ -184,7 +193,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt, sp: Span, name: Ident, arg: Vec ) - -> base::MacResult { + -> ~base::MacResult { // these spans won't matter, anyways fn ms(m: Matcher_) -> Matcher { Spanned { @@ -236,8 +245,10 @@ pub fn add_new_extension(cx: &mut ExtCtxt, rhses: rhses, }; - return MRDef(MacroDef { - name: token::get_ident(name).to_str(), - ext: NormalTT(exp, Some(sp)) - }); + ~MacroRulesDefiner { + def: RefCell::new(Some(MacroDef { + name: token::get_ident(name).to_str(), + ext: NormalTT(exp, Some(sp)) + })) + } as ~MacResult } diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index 5864f839352..070bb6dfcb7 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -35,11 +35,11 @@ pub fn macro_registrar(register: |Name, SyntaxExtension|) { register(token::intern("into_foo"), ItemModifier(expand_into_foo)); } -fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> MacResult { +fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> ~MacResult { if !tts.is_empty() { cx.span_fatal(sp, "make_a_1 takes no arguments"); } - MRExpr(quote_expr!(cx, 1i)) + MacExpr::new(quote_expr!(cx, 1i)) } fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: @MetaItem, it: @Item)