From ab5bbd3c17e435b00d3ffaf820972b13779a9a46 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 25 Jan 2014 13:34:26 -0800 Subject: [PATCH] Simplify and rename macro API Now that procedural macros can be implemented outside of the compiler, it's more important to have a reasonable API to work with. Here are the basic changes: * Rename SyntaxExpanderTTTrait to MacroExpander, SyntaxExpanderTT to BasicMacroExpander, etc. I think "procedural macro" is the right term for these now, right? The other option would be SynExtExpander or something like that. * Stop passing the SyntaxContext to extensions. This was only ever used by macro_rules, which doesn't even use it anymore. I can't think of a context in which an external extension would need it, and removal allows the API to be significantly simpler - no more SyntaxExpanderTTItemExpanderWithoutContext wrappers to worry about. --- src/libsyntax/ext/base.rs | 134 ++++++++++--------------- src/libsyntax/ext/expand.rs | 61 +++-------- src/libsyntax/ext/tt/macro_rules.rs | 14 ++- src/test/auxiliary/macro_crate_test.rs | 4 +- 4 files changed, 72 insertions(+), 141 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 2c817365390..adf1eabf9d9 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -38,91 +38,63 @@ pub struct MacroDef { pub type ItemDecorator = fn(&ExtCtxt, Span, @ast::MetaItem, ~[@ast::Item]) -> ~[@ast::Item]; -pub struct SyntaxExpanderTT { - expander: SyntaxExpanderTTExpander, +pub struct BasicMacroExpander { + expander: MacroExpanderFn, span: Option } -pub trait SyntaxExpanderTTTrait { +pub trait MacroExpander { fn expand(&self, ecx: &mut ExtCtxt, span: Span, - token_tree: &[ast::TokenTree], - context: ast::SyntaxContext) + token_tree: &[ast::TokenTree]) -> MacResult; } -pub type SyntaxExpanderTTFunNoCtxt = +pub type MacroExpanderFn = fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree]) -> MacResult; -enum SyntaxExpanderTTExpander { - SyntaxExpanderTTExpanderWithoutContext(SyntaxExpanderTTFunNoCtxt), -} - -impl SyntaxExpanderTTTrait for SyntaxExpanderTT { +impl MacroExpander for BasicMacroExpander { fn expand(&self, ecx: &mut ExtCtxt, span: Span, - token_tree: &[ast::TokenTree], - _: ast::SyntaxContext) + token_tree: &[ast::TokenTree]) -> MacResult { - match self.expander { - SyntaxExpanderTTExpanderWithoutContext(f) => { - f(ecx, span, token_tree) - } - } + (self.expander)(ecx, span, token_tree) } } -enum SyntaxExpanderTTItemExpander { - SyntaxExpanderTTItemExpanderWithContext(SyntaxExpanderTTItemFun), - SyntaxExpanderTTItemExpanderWithoutContext(SyntaxExpanderTTItemFunNoCtxt), -} - -pub struct SyntaxExpanderTTItem { - expander: SyntaxExpanderTTItemExpander, +pub struct BasicIdentMacroExpander { + expander: IdentMacroExpanderFn, span: Option } -pub trait SyntaxExpanderTTItemTrait { +pub trait IdentMacroExpander { fn expand(&self, cx: &mut ExtCtxt, sp: Span, ident: ast::Ident, - token_tree: ~[ast::TokenTree], - context: ast::SyntaxContext) + token_tree: ~[ast::TokenTree]) -> MacResult; } -impl SyntaxExpanderTTItemTrait for SyntaxExpanderTTItem { +impl IdentMacroExpander for BasicIdentMacroExpander { fn expand(&self, cx: &mut ExtCtxt, sp: Span, ident: ast::Ident, - token_tree: ~[ast::TokenTree], - context: ast::SyntaxContext) + token_tree: ~[ast::TokenTree]) -> MacResult { - match self.expander { - SyntaxExpanderTTItemExpanderWithContext(fun) => { - fun(cx, sp, ident, token_tree, context) - } - SyntaxExpanderTTItemExpanderWithoutContext(fun) => { - fun(cx, sp, ident, token_tree) - } - } + (self.expander)(cx, sp, ident, token_tree) } } -pub type SyntaxExpanderTTItemFun = - fn(&mut ExtCtxt, Span, ast::Ident, ~[ast::TokenTree], ast::SyntaxContext) - -> MacResult; - -pub type SyntaxExpanderTTItemFunNoCtxt = +pub type IdentMacroExpanderFn = fn(&mut ExtCtxt, Span, ast::Ident, ~[ast::TokenTree]) -> MacResult; pub type MacroCrateRegistrationFun = - extern "Rust" fn(|ast::Name, SyntaxExtension|); + fn(|ast::Name, SyntaxExtension|); pub trait AnyMacro { fn make_expr(&self) -> @ast::Expr; @@ -153,7 +125,7 @@ pub enum SyntaxExtension { ItemDecorator(ItemDecorator), // Token-tree expanders - NormalTT(~SyntaxExpanderTTTrait:'static, Option), + NormalTT(~MacroExpander:'static, Option), // An IdentTT is a macro that has an // identifier in between the name of the @@ -163,7 +135,7 @@ pub enum SyntaxExtension { // perhaps macro_rules! will lose its odd special identifier argument, // and this can go away also - IdentTT(~SyntaxExpanderTTItemTrait:'static, Option), + IdentTT(~IdentMacroExpander:'static, Option), } pub struct BlockInfo { @@ -192,102 +164,100 @@ pub type RenameList = ~[(ast::Ident,Name)]; // AST nodes into full ASTs pub fn syntax_expander_table() -> SyntaxEnv { // utility function to simplify creating NormalTT syntax extensions - fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt) - -> SyntaxExtension { - NormalTT(~SyntaxExpanderTT{ - expander: SyntaxExpanderTTExpanderWithoutContext(f), - span: None, - }, - None) + fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension { + NormalTT(~BasicMacroExpander { + expander: f, + span: None, + }, + None) } let mut syntax_expanders = SyntaxEnv::new(); syntax_expanders.insert(intern(&"macro_rules"), - IdentTT(~SyntaxExpanderTTItem { - expander: SyntaxExpanderTTItemExpanderWithContext( - ext::tt::macro_rules::add_new_extension), + IdentTT(~BasicIdentMacroExpander { + expander: ext::tt::macro_rules::add_new_extension, span: None, }, None)); syntax_expanders.insert(intern(&"fmt"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::fmt::expand_syntax_ext)); syntax_expanders.insert(intern(&"format_args"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::format::expand_args)); syntax_expanders.insert(intern(&"env"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::env::expand_env)); syntax_expanders.insert(intern(&"option_env"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::env::expand_option_env)); syntax_expanders.insert(intern("bytes"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::bytes::expand_syntax_ext)); syntax_expanders.insert(intern("concat_idents"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::concat_idents::expand_syntax_ext)); syntax_expanders.insert(intern("concat"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::concat::expand_syntax_ext)); syntax_expanders.insert(intern(&"log_syntax"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::log_syntax::expand_syntax_ext)); syntax_expanders.insert(intern(&"deriving"), ItemDecorator(ext::deriving::expand_meta_deriving)); // Quasi-quoting expanders syntax_expanders.insert(intern(&"quote_tokens"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::quote::expand_quote_tokens)); syntax_expanders.insert(intern(&"quote_expr"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::quote::expand_quote_expr)); syntax_expanders.insert(intern(&"quote_ty"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::quote::expand_quote_ty)); syntax_expanders.insert(intern(&"quote_item"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::quote::expand_quote_item)); syntax_expanders.insert(intern(&"quote_pat"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::quote::expand_quote_pat)); syntax_expanders.insert(intern(&"quote_stmt"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::quote::expand_quote_stmt)); syntax_expanders.insert(intern(&"line"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_line)); syntax_expanders.insert(intern(&"col"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_col)); syntax_expanders.insert(intern(&"file"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_file)); syntax_expanders.insert(intern(&"stringify"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_stringify)); syntax_expanders.insert(intern(&"include"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_include)); syntax_expanders.insert(intern(&"include_str"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_include_str)); syntax_expanders.insert(intern(&"include_bin"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_include_bin)); syntax_expanders.insert(intern(&"module_path"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::source_util::expand_mod)); syntax_expanders.insert(intern(&"asm"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::asm::expand_asm)); syntax_expanders.insert(intern(&"cfg"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::cfg::expand_cfg)); syntax_expanders.insert(intern(&"trace_macros"), - builtin_normal_tt_no_ctxt( + builtin_normal_expander( ext::trace_macros::expand_trace_macros)); syntax_expanders } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 43a5b01698b..cd87819917a 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -13,7 +13,7 @@ use ast::{Local, Ident, MacInvocTT}; use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi}; use ast::{TokenTree}; use ast; -use ast_util::{mtwt_outer_mark, new_rename, new_mark}; +use ast_util::{new_rename, new_mark}; use ext::build::AstBuilder; use attr; use attr::AttrMetaMethods; @@ -44,7 +44,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { // for the other three macro invocation chunks of code // in this file. // Token-tree macros: - MacInvocTT(ref pth, ref tts, ctxt) => { + MacInvocTT(ref pth, ref tts, _) => { if pth.segments.len() > 1u { fld.cx.span_err( pth.span, @@ -77,7 +77,6 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { let fm = fresh_mark(); // mark before: let marked_before = mark_tts(*tts,fm); - let marked_ctxt = new_mark(fm, ctxt); // The span that we pass to the expanders we want to // be the root of the call stack. That's the most @@ -87,8 +86,7 @@ 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, - marked_ctxt) { + marked_before) { MRExpr(e) => e, MRAny(any_macro) => any_macro.make_expr(), _ => { @@ -286,12 +284,12 @@ pub fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { // logic as for expression-position macro invocations. pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) -> SmallVector<@ast::Item> { - let (pth, tts, ctxt) = match it.node { + let (pth, tts) = match it.node { ItemMac(codemap::Spanned { - node: MacInvocTT(ref pth, ref tts, ctxt), + node: MacInvocTT(ref pth, ref tts, _), .. }) => { - (pth, (*tts).clone(), ctxt) + (pth, (*tts).clone()) } _ => fld.cx.span_bug(it.span, "invalid item macro invocation") }; @@ -325,8 +323,7 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) }); // mark before expansion: let marked_before = mark_tts(tts,fm); - let marked_ctxt = new_mark(fm,ctxt); - expander.expand(fld.cx, it.span, marked_before, marked_ctxt) + expander.expand(fld.cx, it.span, marked_before) } Some(&IdentTT(ref expander, span)) => { if it.ident.name == parse::token::special_idents::invalid.name { @@ -344,8 +341,7 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) }); // mark before expansion: let marked_tts = mark_tts(tts,fm); - let marked_ctxt = new_mark(fm,ctxt); - expander.expand(fld.cx, it.span, it.ident, marked_tts, marked_ctxt) + expander.expand(fld.cx, it.span, it.ident, marked_tts) } _ => { fld.cx.span_err(it.span, format!("{}! is not legal in item position", extnamestr)); @@ -464,11 +460,11 @@ fn load_extern_macros(crate: &ast::ViewItem, fld: &mut MacroExpander) { pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { // why the copying here and not in expand_expr? // looks like classic changed-in-only-one-place - let (pth, tts, semi, ctxt) = match s.node { + let (pth, tts, semi) = match s.node { StmtMac(ref mac, semi) => { match mac.node { - MacInvocTT(ref pth, ref tts, ctxt) => { - (pth, (*tts).clone(), semi, ctxt) + MacInvocTT(ref pth, ref tts, _) => { + (pth, (*tts).clone(), semi) } } } @@ -498,7 +494,6 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { let fm = fresh_mark(); // mark before expansion: let marked_tts = mark_tts(tts,fm); - let marked_ctxt = new_mark(fm,ctxt); // See the comment in expand_expr for why we want the original span, // not the current mac.span. @@ -506,8 +501,7 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { let expanded = match expandfun.expand(fld.cx, mac_span.call_site, - marked_tts, - marked_ctxt) { + marked_tts) { MRExpr(e) => { @codemap::Spanned { node: StmtExpr(e, ast::DUMMY_NODE_ID), @@ -923,15 +917,6 @@ pub fn replace_ctxts(expr : @ast::Expr, ctxt : SyntaxContext) -> @ast::Expr { fun_to_ctxt_folder(@Repainter{ctxt:ctxt}).fold_expr(expr) } -// take the mark from the given ctxt (that has a mark at the outside), -// and apply it to everything in the token trees, thereby cancelling -// that mark. -pub fn mtwt_cancel_outer_mark(tts: &[ast::TokenTree], ctxt: ast::SyntaxContext) - -> ~[ast::TokenTree] { - let outer_mark = mtwt_outer_mark(ctxt); - mark_tts(tts,outer_mark) -} - fn original_span(cx: &ExtCtxt) -> @codemap::ExpnInfo { let mut relevant_info = cx.backtrace(); let mut einfo = relevant_info.unwrap(); @@ -1090,28 +1075,6 @@ mod test { } } - #[test] fn cancel_outer_mark_test(){ - let invalid_name = token::special_idents::invalid.name; - let ident_str = @"x"; - let tts = string_to_tts(ident_str); - let fm = fresh_mark(); - let marked_once = fold::fold_tts(tts,&mut new_mark_folder(fm)); - assert_eq!(marked_once.len(),1); - let marked_once_ctxt = - match marked_once[0] { - ast::TTTok(_,token::IDENT(id,_)) => id.ctxt, - _ => fail!(format!("unexpected shape for marked tts: {:?}",marked_once[0])) - }; - assert_eq!(mtwt_marksof(marked_once_ctxt,invalid_name),~[fm]); - let remarked = mtwt_cancel_outer_mark(marked_once,marked_once_ctxt); - assert_eq!(remarked.len(),1); - match remarked[0] { - ast::TTTok(_,token::IDENT(id,_)) => - assert_eq!(mtwt_marksof(id.ctxt,invalid_name),~[]), - _ => fail!(format!("unexpected shape for marked tts: {:?}",remarked[0])) - } - } - #[test] fn renaming () { let item_ast = string_to_crate(@"fn f() -> int { a }"); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index facbee135ed..aabd9c694f7 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -13,7 +13,7 @@ use ast::{TTDelim}; use ast; use codemap::{Span, Spanned, DUMMY_SP}; use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef}; -use ext::base::{NormalTT, SyntaxExpanderTTTrait}; +use ext::base::{NormalTT, MacroExpander}; use ext::base; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; @@ -87,18 +87,17 @@ impl AnyMacro for ParserAnyMacro { } } -struct MacroRulesSyntaxExpanderTTFun { +struct MacroRulesMacroExpander { name: Ident, lhses: @~[@NamedMatch], rhses: @~[@NamedMatch], } -impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun { +impl MacroExpander for MacroRulesMacroExpander { fn expand(&self, cx: &mut ExtCtxt, sp: Span, - arg: &[ast::TokenTree], - _: ast::SyntaxContext) + arg: &[ast::TokenTree]) -> MacResult { generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses) } @@ -175,8 +174,7 @@ fn generic_extension(cx: &ExtCtxt, pub fn add_new_extension(cx: &mut ExtCtxt, sp: Span, name: Ident, - arg: ~[ast::TokenTree], - _: ast::SyntaxContext) + arg: ~[ast::TokenTree]) -> base::MacResult { // these spans won't matter, anyways fn ms(m: Matcher_) -> Matcher { @@ -224,7 +222,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt, _ => cx.span_bug(sp, "wrong-structured rhs") }; - let exp = ~MacroRulesSyntaxExpanderTTFun { + let exp = ~MacroRulesMacroExpander { name: name, lhses: lhses, rhses: rhses, diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index 0892f0ba735..e5bf8574366 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -27,8 +27,8 @@ macro_rules! unexported_macro (() => (3)) #[macro_registrar] pub fn macro_registrar(register: |Name, SyntaxExtension|) { register(token::intern("make_a_1"), - NormalTT(~SyntaxExpanderTT { - expander: SyntaxExpanderTTExpanderWithoutContext(expand_make_a_1), + NormalTT(~BasicMacroExpander { + expander: expand_make_a_1, span: None, }, None));