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.
This commit is contained in:
parent
de57a22b9a
commit
ab5bbd3c17
4 changed files with 72 additions and 141 deletions
|
@ -38,91 +38,63 @@ pub struct MacroDef {
|
||||||
pub type ItemDecorator =
|
pub type ItemDecorator =
|
||||||
fn(&ExtCtxt, Span, @ast::MetaItem, ~[@ast::Item]) -> ~[@ast::Item];
|
fn(&ExtCtxt, Span, @ast::MetaItem, ~[@ast::Item]) -> ~[@ast::Item];
|
||||||
|
|
||||||
pub struct SyntaxExpanderTT {
|
pub struct BasicMacroExpander {
|
||||||
expander: SyntaxExpanderTTExpander,
|
expander: MacroExpanderFn,
|
||||||
span: Option<Span>
|
span: Option<Span>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SyntaxExpanderTTTrait {
|
pub trait MacroExpander {
|
||||||
fn expand(&self,
|
fn expand(&self,
|
||||||
ecx: &mut ExtCtxt,
|
ecx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
token_tree: &[ast::TokenTree],
|
token_tree: &[ast::TokenTree])
|
||||||
context: ast::SyntaxContext)
|
|
||||||
-> MacResult;
|
-> MacResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SyntaxExpanderTTFunNoCtxt =
|
pub type MacroExpanderFn =
|
||||||
fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
|
fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
|
||||||
-> MacResult;
|
-> MacResult;
|
||||||
|
|
||||||
enum SyntaxExpanderTTExpander {
|
impl MacroExpander for BasicMacroExpander {
|
||||||
SyntaxExpanderTTExpanderWithoutContext(SyntaxExpanderTTFunNoCtxt),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SyntaxExpanderTTTrait for SyntaxExpanderTT {
|
|
||||||
fn expand(&self,
|
fn expand(&self,
|
||||||
ecx: &mut ExtCtxt,
|
ecx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
token_tree: &[ast::TokenTree],
|
token_tree: &[ast::TokenTree])
|
||||||
_: ast::SyntaxContext)
|
|
||||||
-> MacResult {
|
-> MacResult {
|
||||||
match self.expander {
|
(self.expander)(ecx, span, token_tree)
|
||||||
SyntaxExpanderTTExpanderWithoutContext(f) => {
|
|
||||||
f(ecx, span, token_tree)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SyntaxExpanderTTItemExpander {
|
pub struct BasicIdentMacroExpander {
|
||||||
SyntaxExpanderTTItemExpanderWithContext(SyntaxExpanderTTItemFun),
|
expander: IdentMacroExpanderFn,
|
||||||
SyntaxExpanderTTItemExpanderWithoutContext(SyntaxExpanderTTItemFunNoCtxt),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SyntaxExpanderTTItem {
|
|
||||||
expander: SyntaxExpanderTTItemExpander,
|
|
||||||
span: Option<Span>
|
span: Option<Span>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SyntaxExpanderTTItemTrait {
|
pub trait IdentMacroExpander {
|
||||||
fn expand(&self,
|
fn expand(&self,
|
||||||
cx: &mut ExtCtxt,
|
cx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
ident: ast::Ident,
|
ident: ast::Ident,
|
||||||
token_tree: ~[ast::TokenTree],
|
token_tree: ~[ast::TokenTree])
|
||||||
context: ast::SyntaxContext)
|
|
||||||
-> MacResult;
|
-> MacResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyntaxExpanderTTItemTrait for SyntaxExpanderTTItem {
|
impl IdentMacroExpander for BasicIdentMacroExpander {
|
||||||
fn expand(&self,
|
fn expand(&self,
|
||||||
cx: &mut ExtCtxt,
|
cx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
ident: ast::Ident,
|
ident: ast::Ident,
|
||||||
token_tree: ~[ast::TokenTree],
|
token_tree: ~[ast::TokenTree])
|
||||||
context: ast::SyntaxContext)
|
|
||||||
-> MacResult {
|
-> MacResult {
|
||||||
match self.expander {
|
(self.expander)(cx, sp, ident, token_tree)
|
||||||
SyntaxExpanderTTItemExpanderWithContext(fun) => {
|
|
||||||
fun(cx, sp, ident, token_tree, context)
|
|
||||||
}
|
|
||||||
SyntaxExpanderTTItemExpanderWithoutContext(fun) => {
|
|
||||||
fun(cx, sp, ident, token_tree)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SyntaxExpanderTTItemFun =
|
pub type IdentMacroExpanderFn =
|
||||||
fn(&mut ExtCtxt, Span, ast::Ident, ~[ast::TokenTree], ast::SyntaxContext)
|
|
||||||
-> MacResult;
|
|
||||||
|
|
||||||
pub type SyntaxExpanderTTItemFunNoCtxt =
|
|
||||||
fn(&mut ExtCtxt, Span, ast::Ident, ~[ast::TokenTree]) -> MacResult;
|
fn(&mut ExtCtxt, Span, ast::Ident, ~[ast::TokenTree]) -> MacResult;
|
||||||
|
|
||||||
pub type MacroCrateRegistrationFun =
|
pub type MacroCrateRegistrationFun =
|
||||||
extern "Rust" fn(|ast::Name, SyntaxExtension|);
|
fn(|ast::Name, SyntaxExtension|);
|
||||||
|
|
||||||
pub trait AnyMacro {
|
pub trait AnyMacro {
|
||||||
fn make_expr(&self) -> @ast::Expr;
|
fn make_expr(&self) -> @ast::Expr;
|
||||||
|
@ -153,7 +125,7 @@ pub enum SyntaxExtension {
|
||||||
ItemDecorator(ItemDecorator),
|
ItemDecorator(ItemDecorator),
|
||||||
|
|
||||||
// Token-tree expanders
|
// Token-tree expanders
|
||||||
NormalTT(~SyntaxExpanderTTTrait:'static, Option<Span>),
|
NormalTT(~MacroExpander:'static, Option<Span>),
|
||||||
|
|
||||||
// An IdentTT is a macro that has an
|
// An IdentTT is a macro that has an
|
||||||
// identifier in between the name of the
|
// identifier in between the name of the
|
||||||
|
@ -163,7 +135,7 @@ pub enum SyntaxExtension {
|
||||||
|
|
||||||
// perhaps macro_rules! will lose its odd special identifier argument,
|
// perhaps macro_rules! will lose its odd special identifier argument,
|
||||||
// and this can go away also
|
// and this can go away also
|
||||||
IdentTT(~SyntaxExpanderTTItemTrait:'static, Option<Span>),
|
IdentTT(~IdentMacroExpander:'static, Option<Span>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BlockInfo {
|
pub struct BlockInfo {
|
||||||
|
@ -192,102 +164,100 @@ pub type RenameList = ~[(ast::Ident,Name)];
|
||||||
// AST nodes into full ASTs
|
// AST nodes into full ASTs
|
||||||
pub fn syntax_expander_table() -> SyntaxEnv {
|
pub fn syntax_expander_table() -> SyntaxEnv {
|
||||||
// utility function to simplify creating NormalTT syntax extensions
|
// utility function to simplify creating NormalTT syntax extensions
|
||||||
fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt)
|
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
|
||||||
-> SyntaxExtension {
|
NormalTT(~BasicMacroExpander {
|
||||||
NormalTT(~SyntaxExpanderTT{
|
expander: f,
|
||||||
expander: SyntaxExpanderTTExpanderWithoutContext(f),
|
span: None,
|
||||||
span: None,
|
},
|
||||||
},
|
None)
|
||||||
None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut syntax_expanders = SyntaxEnv::new();
|
let mut syntax_expanders = SyntaxEnv::new();
|
||||||
syntax_expanders.insert(intern(&"macro_rules"),
|
syntax_expanders.insert(intern(&"macro_rules"),
|
||||||
IdentTT(~SyntaxExpanderTTItem {
|
IdentTT(~BasicIdentMacroExpander {
|
||||||
expander: SyntaxExpanderTTItemExpanderWithContext(
|
expander: ext::tt::macro_rules::add_new_extension,
|
||||||
ext::tt::macro_rules::add_new_extension),
|
|
||||||
span: None,
|
span: None,
|
||||||
},
|
},
|
||||||
None));
|
None));
|
||||||
syntax_expanders.insert(intern(&"fmt"),
|
syntax_expanders.insert(intern(&"fmt"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::fmt::expand_syntax_ext));
|
ext::fmt::expand_syntax_ext));
|
||||||
syntax_expanders.insert(intern(&"format_args"),
|
syntax_expanders.insert(intern(&"format_args"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::format::expand_args));
|
ext::format::expand_args));
|
||||||
syntax_expanders.insert(intern(&"env"),
|
syntax_expanders.insert(intern(&"env"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::env::expand_env));
|
ext::env::expand_env));
|
||||||
syntax_expanders.insert(intern(&"option_env"),
|
syntax_expanders.insert(intern(&"option_env"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::env::expand_option_env));
|
ext::env::expand_option_env));
|
||||||
syntax_expanders.insert(intern("bytes"),
|
syntax_expanders.insert(intern("bytes"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::bytes::expand_syntax_ext));
|
ext::bytes::expand_syntax_ext));
|
||||||
syntax_expanders.insert(intern("concat_idents"),
|
syntax_expanders.insert(intern("concat_idents"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::concat_idents::expand_syntax_ext));
|
ext::concat_idents::expand_syntax_ext));
|
||||||
syntax_expanders.insert(intern("concat"),
|
syntax_expanders.insert(intern("concat"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::concat::expand_syntax_ext));
|
ext::concat::expand_syntax_ext));
|
||||||
syntax_expanders.insert(intern(&"log_syntax"),
|
syntax_expanders.insert(intern(&"log_syntax"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::log_syntax::expand_syntax_ext));
|
ext::log_syntax::expand_syntax_ext));
|
||||||
syntax_expanders.insert(intern(&"deriving"),
|
syntax_expanders.insert(intern(&"deriving"),
|
||||||
ItemDecorator(ext::deriving::expand_meta_deriving));
|
ItemDecorator(ext::deriving::expand_meta_deriving));
|
||||||
|
|
||||||
// Quasi-quoting expanders
|
// Quasi-quoting expanders
|
||||||
syntax_expanders.insert(intern(&"quote_tokens"),
|
syntax_expanders.insert(intern(&"quote_tokens"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::quote::expand_quote_tokens));
|
ext::quote::expand_quote_tokens));
|
||||||
syntax_expanders.insert(intern(&"quote_expr"),
|
syntax_expanders.insert(intern(&"quote_expr"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::quote::expand_quote_expr));
|
ext::quote::expand_quote_expr));
|
||||||
syntax_expanders.insert(intern(&"quote_ty"),
|
syntax_expanders.insert(intern(&"quote_ty"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::quote::expand_quote_ty));
|
ext::quote::expand_quote_ty));
|
||||||
syntax_expanders.insert(intern(&"quote_item"),
|
syntax_expanders.insert(intern(&"quote_item"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::quote::expand_quote_item));
|
ext::quote::expand_quote_item));
|
||||||
syntax_expanders.insert(intern(&"quote_pat"),
|
syntax_expanders.insert(intern(&"quote_pat"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::quote::expand_quote_pat));
|
ext::quote::expand_quote_pat));
|
||||||
syntax_expanders.insert(intern(&"quote_stmt"),
|
syntax_expanders.insert(intern(&"quote_stmt"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::quote::expand_quote_stmt));
|
ext::quote::expand_quote_stmt));
|
||||||
|
|
||||||
syntax_expanders.insert(intern(&"line"),
|
syntax_expanders.insert(intern(&"line"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_line));
|
ext::source_util::expand_line));
|
||||||
syntax_expanders.insert(intern(&"col"),
|
syntax_expanders.insert(intern(&"col"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_col));
|
ext::source_util::expand_col));
|
||||||
syntax_expanders.insert(intern(&"file"),
|
syntax_expanders.insert(intern(&"file"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_file));
|
ext::source_util::expand_file));
|
||||||
syntax_expanders.insert(intern(&"stringify"),
|
syntax_expanders.insert(intern(&"stringify"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_stringify));
|
ext::source_util::expand_stringify));
|
||||||
syntax_expanders.insert(intern(&"include"),
|
syntax_expanders.insert(intern(&"include"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_include));
|
ext::source_util::expand_include));
|
||||||
syntax_expanders.insert(intern(&"include_str"),
|
syntax_expanders.insert(intern(&"include_str"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_include_str));
|
ext::source_util::expand_include_str));
|
||||||
syntax_expanders.insert(intern(&"include_bin"),
|
syntax_expanders.insert(intern(&"include_bin"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_include_bin));
|
ext::source_util::expand_include_bin));
|
||||||
syntax_expanders.insert(intern(&"module_path"),
|
syntax_expanders.insert(intern(&"module_path"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::source_util::expand_mod));
|
ext::source_util::expand_mod));
|
||||||
syntax_expanders.insert(intern(&"asm"),
|
syntax_expanders.insert(intern(&"asm"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::asm::expand_asm));
|
ext::asm::expand_asm));
|
||||||
syntax_expanders.insert(intern(&"cfg"),
|
syntax_expanders.insert(intern(&"cfg"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::cfg::expand_cfg));
|
ext::cfg::expand_cfg));
|
||||||
syntax_expanders.insert(intern(&"trace_macros"),
|
syntax_expanders.insert(intern(&"trace_macros"),
|
||||||
builtin_normal_tt_no_ctxt(
|
builtin_normal_expander(
|
||||||
ext::trace_macros::expand_trace_macros));
|
ext::trace_macros::expand_trace_macros));
|
||||||
syntax_expanders
|
syntax_expanders
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use ast::{Local, Ident, MacInvocTT};
|
||||||
use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi};
|
use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi};
|
||||||
use ast::{TokenTree};
|
use ast::{TokenTree};
|
||||||
use ast;
|
use ast;
|
||||||
use ast_util::{mtwt_outer_mark, new_rename, new_mark};
|
use ast_util::{new_rename, new_mark};
|
||||||
use ext::build::AstBuilder;
|
use ext::build::AstBuilder;
|
||||||
use attr;
|
use attr;
|
||||||
use attr::AttrMetaMethods;
|
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
|
// for the other three macro invocation chunks of code
|
||||||
// in this file.
|
// in this file.
|
||||||
// Token-tree macros:
|
// Token-tree macros:
|
||||||
MacInvocTT(ref pth, ref tts, ctxt) => {
|
MacInvocTT(ref pth, ref tts, _) => {
|
||||||
if pth.segments.len() > 1u {
|
if pth.segments.len() > 1u {
|
||||||
fld.cx.span_err(
|
fld.cx.span_err(
|
||||||
pth.span,
|
pth.span,
|
||||||
|
@ -77,7 +77,6 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||||
let fm = fresh_mark();
|
let fm = fresh_mark();
|
||||||
// mark before:
|
// mark before:
|
||||||
let marked_before = mark_tts(*tts,fm);
|
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
|
// The span that we pass to the expanders we want to
|
||||||
// be the root of the call stack. That's the most
|
// 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,
|
let expanded = match expandfun.expand(fld.cx,
|
||||||
mac_span.call_site,
|
mac_span.call_site,
|
||||||
marked_before,
|
marked_before) {
|
||||||
marked_ctxt) {
|
|
||||||
MRExpr(e) => e,
|
MRExpr(e) => e,
|
||||||
MRAny(any_macro) => any_macro.make_expr(),
|
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.
|
// logic as for expression-position macro invocations.
|
||||||
pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
|
pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
|
||||||
-> SmallVector<@ast::Item> {
|
-> SmallVector<@ast::Item> {
|
||||||
let (pth, tts, ctxt) = match it.node {
|
let (pth, tts) = match it.node {
|
||||||
ItemMac(codemap::Spanned {
|
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")
|
_ => 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:
|
// mark before expansion:
|
||||||
let marked_before = mark_tts(tts,fm);
|
let marked_before = mark_tts(tts,fm);
|
||||||
let marked_ctxt = new_mark(fm,ctxt);
|
expander.expand(fld.cx, it.span, marked_before)
|
||||||
expander.expand(fld.cx, it.span, marked_before, marked_ctxt)
|
|
||||||
}
|
}
|
||||||
Some(&IdentTT(ref expander, span)) => {
|
Some(&IdentTT(ref expander, span)) => {
|
||||||
if it.ident.name == parse::token::special_idents::invalid.name {
|
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:
|
// mark before expansion:
|
||||||
let marked_tts = mark_tts(tts,fm);
|
let marked_tts = mark_tts(tts,fm);
|
||||||
let marked_ctxt = new_mark(fm,ctxt);
|
expander.expand(fld.cx, it.span, it.ident, marked_tts)
|
||||||
expander.expand(fld.cx, it.span, it.ident, marked_tts, marked_ctxt)
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
fld.cx.span_err(it.span, format!("{}! is not legal in item position", extnamestr));
|
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> {
|
pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
|
||||||
// why the copying here and not in expand_expr?
|
// why the copying here and not in expand_expr?
|
||||||
// looks like classic changed-in-only-one-place
|
// 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) => {
|
StmtMac(ref mac, semi) => {
|
||||||
match mac.node {
|
match mac.node {
|
||||||
MacInvocTT(ref pth, ref tts, ctxt) => {
|
MacInvocTT(ref pth, ref tts, _) => {
|
||||||
(pth, (*tts).clone(), semi, ctxt)
|
(pth, (*tts).clone(), semi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +494,6 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
|
||||||
let fm = fresh_mark();
|
let fm = fresh_mark();
|
||||||
// mark before expansion:
|
// mark before expansion:
|
||||||
let marked_tts = mark_tts(tts,fm);
|
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,
|
// See the comment in expand_expr for why we want the original span,
|
||||||
// not the current mac.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,
|
let expanded = match expandfun.expand(fld.cx,
|
||||||
mac_span.call_site,
|
mac_span.call_site,
|
||||||
marked_tts,
|
marked_tts) {
|
||||||
marked_ctxt) {
|
|
||||||
MRExpr(e) => {
|
MRExpr(e) => {
|
||||||
@codemap::Spanned {
|
@codemap::Spanned {
|
||||||
node: StmtExpr(e, ast::DUMMY_NODE_ID),
|
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)
|
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 {
|
fn original_span(cx: &ExtCtxt) -> @codemap::ExpnInfo {
|
||||||
let mut relevant_info = cx.backtrace();
|
let mut relevant_info = cx.backtrace();
|
||||||
let mut einfo = relevant_info.unwrap();
|
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]
|
#[test]
|
||||||
fn renaming () {
|
fn renaming () {
|
||||||
let item_ast = string_to_crate(@"fn f() -> int { a }");
|
let item_ast = string_to_crate(@"fn f() -> int { a }");
|
||||||
|
|
|
@ -13,7 +13,7 @@ use ast::{TTDelim};
|
||||||
use ast;
|
use ast;
|
||||||
use codemap::{Span, Spanned, DUMMY_SP};
|
use codemap::{Span, Spanned, DUMMY_SP};
|
||||||
use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
|
use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
|
||||||
use ext::base::{NormalTT, SyntaxExpanderTTTrait};
|
use ext::base::{NormalTT, MacroExpander};
|
||||||
use ext::base;
|
use ext::base;
|
||||||
use ext::tt::macro_parser::{Success, Error, Failure};
|
use ext::tt::macro_parser::{Success, Error, Failure};
|
||||||
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
|
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
|
||||||
|
@ -87,18 +87,17 @@ impl AnyMacro for ParserAnyMacro {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MacroRulesSyntaxExpanderTTFun {
|
struct MacroRulesMacroExpander {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
lhses: @~[@NamedMatch],
|
lhses: @~[@NamedMatch],
|
||||||
rhses: @~[@NamedMatch],
|
rhses: @~[@NamedMatch],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun {
|
impl MacroExpander for MacroRulesMacroExpander {
|
||||||
fn expand(&self,
|
fn expand(&self,
|
||||||
cx: &mut ExtCtxt,
|
cx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
arg: &[ast::TokenTree],
|
arg: &[ast::TokenTree])
|
||||||
_: ast::SyntaxContext)
|
|
||||||
-> MacResult {
|
-> MacResult {
|
||||||
generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses)
|
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,
|
pub fn add_new_extension(cx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
name: Ident,
|
name: Ident,
|
||||||
arg: ~[ast::TokenTree],
|
arg: ~[ast::TokenTree])
|
||||||
_: ast::SyntaxContext)
|
|
||||||
-> base::MacResult {
|
-> base::MacResult {
|
||||||
// these spans won't matter, anyways
|
// these spans won't matter, anyways
|
||||||
fn ms(m: Matcher_) -> Matcher {
|
fn ms(m: Matcher_) -> Matcher {
|
||||||
|
@ -224,7 +222,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
|
||||||
_ => cx.span_bug(sp, "wrong-structured rhs")
|
_ => cx.span_bug(sp, "wrong-structured rhs")
|
||||||
};
|
};
|
||||||
|
|
||||||
let exp = ~MacroRulesSyntaxExpanderTTFun {
|
let exp = ~MacroRulesMacroExpander {
|
||||||
name: name,
|
name: name,
|
||||||
lhses: lhses,
|
lhses: lhses,
|
||||||
rhses: rhses,
|
rhses: rhses,
|
||||||
|
|
|
@ -27,8 +27,8 @@ macro_rules! unexported_macro (() => (3))
|
||||||
#[macro_registrar]
|
#[macro_registrar]
|
||||||
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
||||||
register(token::intern("make_a_1"),
|
register(token::intern("make_a_1"),
|
||||||
NormalTT(~SyntaxExpanderTT {
|
NormalTT(~BasicMacroExpander {
|
||||||
expander: SyntaxExpanderTTExpanderWithoutContext(expand_make_a_1),
|
expander: expand_make_a_1,
|
||||||
span: None,
|
span: None,
|
||||||
},
|
},
|
||||||
None));
|
None));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue