diff options
| author | bors <bors@rust-lang.org> | 2013-09-23 19:20:58 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-09-23 19:20:58 -0700 |
| commit | d062de8aa48083439237cb338b38c25306bf6c94 (patch) | |
| tree | 1ced905a1f2255a3f5207ed6c70fbe5e80cf4b41 /src/libsyntax | |
| parent | 348d8446739f9633897a3d728d265ee6ac59c8fb (diff) | |
| parent | 3b1d3e5bf8e2f288147fd879b37bc5e6f8c5528f (diff) | |
| download | rust-d062de8aa48083439237cb338b38c25306bf6c94.tar.gz rust-d062de8aa48083439237cb338b38c25306bf6c94.zip | |
auto merge of #9310 : pcwalton/rust/at-fn, r=pcwalton
r? @brson
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast_util.rs | 93 | ||||
| -rw-r--r-- | src/libsyntax/diagnostic.rs | 79 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 239 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 30 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 489 | ||||
| -rw-r--r-- | src/libsyntax/ext/fmt.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 141 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 1455 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 58 |
10 files changed, 1390 insertions, 1198 deletions
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f0f86911f50..ac88fc835d5 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -12,7 +12,6 @@ use ast::*; use ast; use ast_util; use codemap::{Span, dummy_sp}; -use fold; use opt_vec; use parse::token; use visit::Visitor; @@ -371,21 +370,6 @@ pub fn empty_generics() -> Generics { ty_params: opt_vec::Empty} } -/////////////////////////////////////////////////////////////////////////// -// Assigning node ids - -fn node_id_assigner(next_id: @fn() -> ast::NodeId) -> @fold::ast_fold { - let precursor = @fold::AstFoldFns { - new_id: |old_id| { - assert_eq!(old_id, ast::DUMMY_NODE_ID); - next_id() - }, - ..*fold::default_ast_fold() - }; - - fold::make_fold(precursor) -} - // ______________________________________________________________________ // Enumerating the IDs which appear in an AST @@ -413,18 +397,22 @@ impl id_range { } } -pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool) +pub fn id_visitor(operation: @IdVisitingOperation, pass_through_items: bool) -> @mut Visitor<()> { let visitor = @mut IdVisitor { - visit_callback: vfn, + operation: operation, pass_through_items: pass_through_items, visited_outermost: false, }; visitor as @mut Visitor<()> } +pub trait IdVisitingOperation { + fn visit_id(&self, node_id: NodeId); +} + pub struct IdVisitor { - visit_callback: @fn(NodeId), + operation: @IdVisitingOperation, pass_through_items: bool, visited_outermost: bool, } @@ -432,10 +420,10 @@ pub struct IdVisitor { impl IdVisitor { fn visit_generics_helper(&self, generics: &Generics) { for type_parameter in generics.ty_params.iter() { - (self.visit_callback)(type_parameter.id) + self.operation.visit_id(type_parameter.id) } for lifetime in generics.lifetimes.iter() { - (self.visit_callback)(lifetime.id) + self.operation.visit_id(lifetime.id) } } } @@ -446,26 +434,26 @@ impl Visitor<()> for IdVisitor { _: Span, node_id: NodeId, env: ()) { - (self.visit_callback)(node_id); + self.operation.visit_id(node_id); visit::walk_mod(self, module, env) } fn visit_view_item(&mut self, view_item: &view_item, env: ()) { match view_item.node { view_item_extern_mod(_, _, _, node_id) => { - (self.visit_callback)(node_id) + self.operation.visit_id(node_id) } view_item_use(ref view_paths) => { for view_path in view_paths.iter() { match view_path.node { view_path_simple(_, _, node_id) | view_path_glob(_, node_id) => { - (self.visit_callback)(node_id) + self.operation.visit_id(node_id) } view_path_list(_, ref paths, node_id) => { - (self.visit_callback)(node_id); + self.operation.visit_id(node_id); for path in paths.iter() { - (self.visit_callback)(path.node.id) + self.operation.visit_id(path.node.id) } } } @@ -476,7 +464,7 @@ impl Visitor<()> for IdVisitor { } fn visit_foreign_item(&mut self, foreign_item: @foreign_item, env: ()) { - (self.visit_callback)(foreign_item.id); + self.operation.visit_id(foreign_item.id); visit::walk_foreign_item(self, foreign_item, env) } @@ -489,11 +477,11 @@ impl Visitor<()> for IdVisitor { } } - (self.visit_callback)(item.id); + self.operation.visit_id(item.id); match item.node { item_enum(ref enum_definition, _) => { for variant in enum_definition.variants.iter() { - (self.visit_callback)(variant.node.id) + self.operation.visit_id(variant.node.id) } } _ => {} @@ -505,22 +493,22 @@ impl Visitor<()> for IdVisitor { } fn visit_local(&mut self, local: @Local, env: ()) { - (self.visit_callback)(local.id); + self.operation.visit_id(local.id); visit::walk_local(self, local, env) } fn visit_block(&mut self, block: &Block, env: ()) { - (self.visit_callback)(block.id); + self.operation.visit_id(block.id); visit::walk_block(self, block, env) } fn visit_stmt(&mut self, statement: @Stmt, env: ()) { - (self.visit_callback)(ast_util::stmt_id(statement)); + self.operation.visit_id(ast_util::stmt_id(statement)); visit::walk_stmt(self, statement, env) } fn visit_pat(&mut self, pattern: @Pat, env: ()) { - (self.visit_callback)(pattern.id); + self.operation.visit_id(pattern.id); visit::walk_pat(self, pattern, env) } @@ -529,17 +517,17 @@ impl Visitor<()> for IdVisitor { { let optional_callee_id = expression.get_callee_id(); for callee_id in optional_callee_id.iter() { - (self.visit_callback)(*callee_id) + self.operation.visit_id(*callee_id) } } - (self.visit_callback)(expression.id); + self.operation.visit_id(expression.id); visit::walk_expr(self, expression, env) } fn visit_ty(&mut self, typ: &Ty, env: ()) { - (self.visit_callback)(typ.id); + self.operation.visit_id(typ.id); match typ.node { - ty_path(_, _, id) => (self.visit_callback)(id), + ty_path(_, _, id) => self.operation.visit_id(id), _ => {} } visit::walk_ty(self, typ, env) @@ -565,21 +553,21 @@ impl Visitor<()> for IdVisitor { } } - (self.visit_callback)(node_id); + self.operation.visit_id(node_id); match *function_kind { visit::fk_item_fn(_, generics, _, _) => { self.visit_generics_helper(generics) } visit::fk_method(_, generics, method) => { - (self.visit_callback)(method.self_id); + self.operation.visit_id(method.self_id); self.visit_generics_helper(generics) } visit::fk_anon(_) | visit::fk_fn_block => {} } for argument in function_declaration.inputs.iter() { - (self.visit_callback)(argument.id) + self.operation.visit_id(argument.id) } visit::walk_fn(self, @@ -599,25 +587,36 @@ impl Visitor<()> for IdVisitor { } fn visit_struct_field(&mut self, struct_field: @struct_field, env: ()) { - (self.visit_callback)(struct_field.node.id); + self.operation.visit_id(struct_field.node.id); visit::walk_struct_field(self, struct_field, env) } } -pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) { +pub fn visit_ids_for_inlined_item(item: &inlined_item, + operation: @IdVisitingOperation) { let mut id_visitor = IdVisitor { - visit_callback: vfn, + operation: operation, pass_through_items: true, visited_outermost: false, }; item.accept((), &mut id_visitor); } -pub fn compute_id_range(visit_ids_fn: &fn(@fn(NodeId))) -> id_range { - let result = @mut id_range::max(); - do visit_ids_fn |id| { - result.add(id); +struct IdRangeComputingVisitor { + result: @mut id_range, +} + +impl IdVisitingOperation for IdRangeComputingVisitor { + fn visit_id(&self, id: NodeId) { + self.result.add(id) } +} + +pub fn compute_id_range(visit_ids_fn: &fn(@IdVisitingOperation)) -> id_range { + let result = @mut id_range::max(); + visit_ids_fn(@IdRangeComputingVisitor { + result: result, + } as @IdVisitingOperation); *result } diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 5e9714ca5b2..aa06e1bee41 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -15,9 +15,12 @@ use std::io; use std::local_data; use extra::term; -pub type Emitter = @fn(cmsp: Option<(@codemap::CodeMap, Span)>, - msg: &str, - lvl: level); +pub trait Emitter { + fn emit(&self, + cmsp: Option<(@codemap::CodeMap, Span)>, + msg: &str, + lvl: level); +} // a handler deals with errors; certain errors // (fatal, bug, unimpl) may cause immediate exit, @@ -55,7 +58,7 @@ pub trait span_handler { struct HandlerT { err_count: uint, - emit: Emitter, + emit: @Emitter, } struct CodemapT { @@ -91,11 +94,11 @@ impl span_handler for CodemapT { impl handler for HandlerT { fn fatal(@mut self, msg: &str) -> ! { - (self.emit)(None, msg, fatal); + self.emit.emit(None, msg, fatal); fail!(); } fn err(@mut self, msg: &str) { - (self.emit)(None, msg, error); + self.emit.emit(None, msg, error); self.bump_err_count(); } fn bump_err_count(@mut self) { @@ -120,10 +123,10 @@ impl handler for HandlerT { self.fatal(s); } fn warn(@mut self, msg: &str) { - (self.emit)(None, msg, warning); + self.emit.emit(None, msg, warning); } fn note(@mut self, msg: &str) { - (self.emit)(None, msg, note); + self.emit.emit(None, msg, note); } fn bug(@mut self, msg: &str) -> ! { self.fatal(ice_msg(msg)); @@ -135,7 +138,7 @@ impl handler for HandlerT { cmsp: Option<(@codemap::CodeMap, Span)>, msg: &str, lvl: level) { - (self.emit)(cmsp, msg, lvl); + self.emit.emit(cmsp, msg, lvl); } } @@ -145,19 +148,22 @@ pub fn ice_msg(msg: &str) -> ~str { pub fn mk_span_handler(handler: @mut handler, cm: @codemap::CodeMap) -> @mut span_handler { - @mut CodemapT { handler: handler, cm: cm } as @mut span_handler + @mut CodemapT { + handler: handler, + cm: cm, + } as @mut span_handler } -pub fn mk_handler(emitter: Option<Emitter>) -> @mut handler { - let emit: Emitter = match emitter { +pub fn mk_handler(emitter: Option<@Emitter>) -> @mut handler { + let emit: @Emitter = match emitter { Some(e) => e, - None => { - let emit: Emitter = |cmsp, msg, t| emit(cmsp, msg, t); - emit - } + None => @DefaultEmitter as @Emitter }; - @mut HandlerT { err_count: 0, emit: emit } as @mut handler + @mut HandlerT { + err_count: 0, + emit: emit, + } as @mut handler } #[deriving(Eq)] @@ -230,31 +236,30 @@ fn print_diagnostic(topic: &str, lvl: level, msg: &str) { print_maybe_styled(fmt!("%s\n", msg), term::attr::Bold); } -pub fn collect(messages: @mut ~[~str]) - -> @fn(Option<(@codemap::CodeMap, Span)>, &str, level) { - let f: @fn(Option<(@codemap::CodeMap, Span)>, &str, level) = - |_o, msg: &str, _l| { messages.push(msg.to_str()); }; - f -} +pub struct DefaultEmitter; -pub fn emit(cmsp: Option<(@codemap::CodeMap, Span)>, msg: &str, lvl: level) { - match cmsp { - Some((cm, sp)) => { - let sp = cm.adjust_span(sp); - let ss = cm.span_to_str(sp); - let lines = cm.span_to_lines(sp); - print_diagnostic(ss, lvl, msg); - highlight_lines(cm, sp, lvl, lines); - print_macro_backtrace(cm, sp); - } - None => { - print_diagnostic("", lvl, msg); - } +impl Emitter for DefaultEmitter { + fn emit(&self, + cmsp: Option<(@codemap::CodeMap, Span)>, + msg: &str, + lvl: level) { + match cmsp { + Some((cm, sp)) => { + let sp = cm.adjust_span(sp); + let ss = cm.span_to_str(sp); + let lines = cm.span_to_lines(sp); + print_diagnostic(ss, lvl, msg); + highlight_lines(cm, sp, lvl, lines); + print_macro_backtrace(cm, sp); + } + None => print_diagnostic("", lvl, msg), + } } } fn highlight_lines(cm: @codemap::CodeMap, - sp: Span, lvl: level, + sp: Span, + lvl: level, lines: @codemap::FileLines) { let fm = lines.file; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 2bcfafc3bb4..48eb9a350f1 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -33,62 +33,120 @@ pub struct MacroDef { ext: SyntaxExtension } -// No context arg for an Item Decorator macro, simply because -// adding it would require adding a ctxt field to all items. -// we could do this if it turns out to be useful. - -pub type ItemDecoratorFun = @fn(@ExtCtxt, - Span, - @ast::MetaItem, - ~[@ast::item]) - -> ~[@ast::item]; - -pub type SyntaxExpanderTTFun = @fn(@ExtCtxt, - Span, - &[ast::token_tree], - ast::SyntaxContext) - -> MacResult; - -pub type SyntaxExpanderTTItemFun = @fn(@ExtCtxt, - Span, - ast::Ident, - ~[ast::token_tree], - ast::SyntaxContext) - -> MacResult; - -// oog... in order to make the presentation of builtin_normal_tt_no_ctxt -// and builtin_ident_tt_no_ctxt palatable, we need one-off types for -// functions that don't consume a ctxt: - -pub type SyntaxExpanderTTFunNoCtxt = @fn(@ExtCtxt, - Span, - &[ast::token_tree]) - -> MacResult; - -pub type SyntaxExpanderTTItemFunNoCtxt = @fn(@ExtCtxt, - Span, - ast::Ident, - ~[ast::token_tree]) - -> MacResult; +pub type ItemDecorator = extern "Rust" fn(@ExtCtxt, + Span, + @ast::MetaItem, + ~[@ast::item]) + -> ~[@ast::item]; + +pub struct SyntaxExpanderTT { + expander: SyntaxExpanderTTExpander, + span: Option<Span> +} + +pub trait SyntaxExpanderTTTrait { + fn expand(&self, + ecx: @ExtCtxt, + span: Span, + token_tree: &[ast::token_tree], + context: ast::SyntaxContext) + -> MacResult; +} + +pub type SyntaxExpanderTTFunNoCtxt = + extern "Rust" fn(ecx: @ExtCtxt, + span: codemap::Span, + token_tree: &[ast::token_tree]) + -> MacResult; + +enum SyntaxExpanderTTExpander { + SyntaxExpanderTTExpanderWithoutContext(SyntaxExpanderTTFunNoCtxt), +} + +impl SyntaxExpanderTTTrait for SyntaxExpanderTT { + fn expand(&self, + ecx: @ExtCtxt, + span: Span, + token_tree: &[ast::token_tree], + _: ast::SyntaxContext) + -> MacResult { + match self.expander { + SyntaxExpanderTTExpanderWithoutContext(f) => { + f(ecx, span, token_tree) + } + } + } +} +enum SyntaxExpanderTTItemExpander { + SyntaxExpanderTTItemExpanderWithContext(SyntaxExpanderTTItemFun), + SyntaxExpanderTTItemExpanderWithoutContext(SyntaxExpanderTTItemFunNoCtxt), +} +pub struct SyntaxExpanderTTItem { + expander: SyntaxExpanderTTItemExpander, + span: Option<Span> +} + +pub trait SyntaxExpanderTTItemTrait { + fn expand(&self, + cx: @ExtCtxt, + sp: Span, + ident: ast::Ident, + token_tree: ~[ast::token_tree], + context: ast::SyntaxContext) + -> MacResult; +} + +impl SyntaxExpanderTTItemTrait for SyntaxExpanderTTItem { + fn expand(&self, + cx: @ExtCtxt, + sp: Span, + ident: ast::Ident, + token_tree: ~[ast::token_tree], + context: ast::SyntaxContext) + -> MacResult { + match self.expander { + SyntaxExpanderTTItemExpanderWithContext(fun) => { + fun(cx, sp, ident, token_tree, context) + } + SyntaxExpanderTTItemExpanderWithoutContext(fun) => { + fun(cx, sp, ident, token_tree) + } + } + } +} + +pub type SyntaxExpanderTTItemFun = extern "Rust" fn(@ExtCtxt, + Span, + ast::Ident, + ~[ast::token_tree], + ast::SyntaxContext) + -> MacResult; + +pub type SyntaxExpanderTTItemFunNoCtxt = + extern "Rust" fn(@ExtCtxt, Span, ast::Ident, ~[ast::token_tree]) + -> MacResult; + +pub trait AnyMacro { + fn make_expr(&self) -> @ast::Expr; + fn make_item(&self) -> Option<@ast::item>; + fn make_stmt(&self) -> @ast::Stmt; +} pub enum MacResult { MRExpr(@ast::Expr), MRItem(@ast::item), - MRAny(@fn() -> @ast::Expr, - @fn() -> Option<@ast::item>, - @fn() -> @ast::Stmt), - MRDef(MacroDef) + MRAny(@AnyMacro), + MRDef(MacroDef), } pub enum SyntaxExtension { - // #[auto_encode] and such - ItemDecorator(ItemDecoratorFun), + ItemDecorator(ItemDecorator), // Token-tree expanders - NormalTT(SyntaxExpanderTTFun, Option<Span>), + NormalTT(@SyntaxExpanderTTTrait, Option<Span>), // An IdentTT is a macro that has an // identifier in between the name of the @@ -98,7 +156,7 @@ pub enum SyntaxExtension { // perhaps macro_rules! will lose its odd special identifier argument, // and this can go away also - IdentTT(SyntaxExpanderTTItemFun, Option<Span>), + IdentTT(@SyntaxExpanderTTItemTrait, Option<Span>), } @@ -133,16 +191,22 @@ type RenameList = ~[(ast::Ident,Name)]; // AST nodes into full ASTs pub fn syntax_expander_table() -> SyntaxEnv { // utility function to simplify creating NormalTT syntax extensions - // that ignore their contexts - fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt) -> @Transformer { - let wrapped_expander : SyntaxExpanderTTFun = |a,b,c,_d|{f(a,b,c)}; - @SE(NormalTT(wrapped_expander, None)) + fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt) + -> @Transformer { + @SE(NormalTT(@SyntaxExpanderTT{ + expander: SyntaxExpanderTTExpanderWithoutContext(f), + span: None, + } as @SyntaxExpanderTTTrait, + None)) } // utility function to simplify creating IdentTT syntax extensions // that ignore their contexts fn builtin_item_tt_no_ctxt(f: SyntaxExpanderTTItemFunNoCtxt) -> @Transformer { - let wrapped_expander : SyntaxExpanderTTItemFun = |a,b,c,d,_e|{f(a,b,c,d)}; - @SE(IdentTT(wrapped_expander, None)) + @SE(IdentTT(@SyntaxExpanderTTItem { + expander: SyntaxExpanderTTItemExpanderWithoutContext(f), + span: None, + } as @SyntaxExpanderTTItemTrait, + None)) } let mut syntax_expanders = HashMap::new(); // NB identifier starts with space, and can't conflict with legal idents @@ -152,11 +216,18 @@ pub fn syntax_expander_table() -> SyntaxEnv { pending_renames : @mut ~[] })); syntax_expanders.insert(intern(&"macro_rules"), - @SE(IdentTT(ext::tt::macro_rules::add_new_extension, None))); + @SE(IdentTT(@SyntaxExpanderTTItem { + expander: SyntaxExpanderTTItemExpanderWithContext( + ext::tt::macro_rules::add_new_extension), + span: None, + } as @SyntaxExpanderTTItemTrait, + None))); syntax_expanders.insert(intern(&"fmt"), - builtin_normal_tt_no_ctxt(ext::fmt::expand_syntax_ext)); + builtin_normal_tt_no_ctxt( + ext::fmt::expand_syntax_ext)); syntax_expanders.insert(intern(&"format_args"), - builtin_normal_tt_no_ctxt(ext::format::expand_args)); + builtin_normal_tt_no_ctxt( + ext::format::expand_args)); syntax_expanders.insert( intern(&"auto_encode"), @SE(ItemDecorator(ext::auto_encode::expand_auto_encode))); @@ -164,67 +235,77 @@ pub fn syntax_expander_table() -> SyntaxEnv { intern(&"auto_decode"), @SE(ItemDecorator(ext::auto_encode::expand_auto_decode))); syntax_expanders.insert(intern(&"env"), - builtin_normal_tt_no_ctxt(ext::env::expand_env)); + builtin_normal_tt_no_ctxt( + ext::env::expand_env)); syntax_expanders.insert(intern(&"option_env"), - builtin_normal_tt_no_ctxt(ext::env::expand_option_env)); + builtin_normal_tt_no_ctxt( + ext::env::expand_option_env)); syntax_expanders.insert(intern("bytes"), - builtin_normal_tt_no_ctxt(ext::bytes::expand_syntax_ext)); + builtin_normal_tt_no_ctxt( + ext::bytes::expand_syntax_ext)); syntax_expanders.insert(intern("concat_idents"), builtin_normal_tt_no_ctxt( - ext::concat_idents::expand_syntax_ext)); + ext::concat_idents::expand_syntax_ext)); syntax_expanders.insert(intern(&"log_syntax"), builtin_normal_tt_no_ctxt( - ext::log_syntax::expand_syntax_ext)); + ext::log_syntax::expand_syntax_ext)); syntax_expanders.insert(intern(&"deriving"), @SE(ItemDecorator( ext::deriving::expand_meta_deriving))); // Quasi-quoting expanders syntax_expanders.insert(intern(&"quote_tokens"), - builtin_normal_tt_no_ctxt( - ext::quote::expand_quote_tokens)); + builtin_normal_tt_no_ctxt( + ext::quote::expand_quote_tokens)); syntax_expanders.insert(intern(&"quote_expr"), - builtin_normal_tt_no_ctxt(ext::quote::expand_quote_expr)); + builtin_normal_tt_no_ctxt( + ext::quote::expand_quote_expr)); syntax_expanders.insert(intern(&"quote_ty"), - builtin_normal_tt_no_ctxt(ext::quote::expand_quote_ty)); + builtin_normal_tt_no_ctxt( + ext::quote::expand_quote_ty)); syntax_expanders.insert(intern(&"quote_item"), - builtin_normal_tt_no_ctxt(ext::quote::expand_quote_item)); + builtin_normal_tt_no_ctxt( + ext::quote::expand_quote_item)); syntax_expanders.insert(intern(&"quote_pat"), - builtin_normal_tt_no_ctxt(ext::quote::expand_quote_pat)); + builtin_normal_tt_no_ctxt( + ext::quote::expand_quote_pat)); syntax_expanders.insert(intern(&"quote_stmt"), - builtin_normal_tt_no_ctxt(ext::quote::expand_quote_stmt)); + builtin_normal_tt_no_ctxt( + ext::quote::expand_quote_stmt)); syntax_expanders.insert(intern(&"line"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_line)); + ext::source_util::expand_line)); syntax_expanders.insert(intern(&"col"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_col)); + ext::source_util::expand_col)); syntax_expanders.insert(intern(&"file"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_file)); + ext::source_util::expand_file)); syntax_expanders.insert(intern(&"stringify"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_stringify)); + ext::source_util::expand_stringify)); syntax_expanders.insert(intern(&"include"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_include)); + ext::source_util::expand_include)); syntax_expanders.insert(intern(&"include_str"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_include_str)); + ext::source_util::expand_include_str)); syntax_expanders.insert(intern(&"include_bin"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_include_bin)); + ext::source_util::expand_include_bin)); syntax_expanders.insert(intern(&"module_path"), builtin_normal_tt_no_ctxt( - ext::source_util::expand_mod)); + ext::source_util::expand_mod)); syntax_expanders.insert(intern(&"asm"), - builtin_normal_tt_no_ctxt(ext::asm::expand_asm)); + builtin_normal_tt_no_ctxt( + ext::asm::expand_asm)); syntax_expanders.insert(intern(&"cfg"), - builtin_normal_tt_no_ctxt(ext::cfg::expand_cfg)); - syntax_expanders.insert( - intern(&"trace_macros"), - builtin_normal_tt_no_ctxt(ext::trace_macros::expand_trace_macros)); + builtin_normal_tt_no_ctxt( + ext::cfg::expand_cfg)); + syntax_expanders.insert(intern(&"trace_macros"), + builtin_normal_tt_no_ctxt( + ext::trace_macros::expand_trace_macros)); MapChain::new(~syntax_expanders) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 889c2a5976e..ba2342d7827 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -15,6 +15,7 @@ use ast_util; use codemap::{Span, respan, dummy_sp}; use ext::base::ExtCtxt; use ext::quote::rt::*; +use fold; use opt_vec; use opt_vec::OptVec; @@ -862,3 +863,32 @@ impl AstBuilder for @ExtCtxt { ast::view_path_glob(self.path(sp, path), ast::DUMMY_NODE_ID))]) } } + +struct Duplicator { + cx: @ExtCtxt, +} + +impl fold::ast_fold for Duplicator { + fn new_id(&self, _: NodeId) -> NodeId { + ast::DUMMY_NODE_ID + } +} + +pub trait Duplicate { + // + // Duplication functions + // + // These functions just duplicate AST nodes. + // + + fn duplicate(&self, cx: @ExtCtxt) -> Self; +} + +impl Duplicate for @ast::Expr { + fn duplicate(&self, cx: @ExtCtxt) -> @ast::Expr { + let folder = @Duplicator { + cx: cx, + } as @fold::ast_fold; + folder.fold_expr(*self) + } +} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 82d452bc734..004a889fb4d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -10,7 +10,7 @@ use ast::{Block, Crate, DeclLocal, Expr_, ExprMac, SyntaxContext}; use ast::{Local, Ident, mac_invoc_tt}; -use ast::{item_mac, Mrk, Stmt_, StmtDecl, StmtMac, StmtExpr, StmtSemi}; +use ast::{item_mac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi}; use ast::{token_tree}; use ast; use ast_util::{mtwt_outer_mark, new_rename, new_mark}; @@ -21,6 +21,7 @@ use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan}; use ext::base::*; use fold::*; +use opt_vec; use parse; use parse::{parse_item_from_source_str}; use parse::token; @@ -32,12 +33,10 @@ use std::vec; pub fn expand_expr(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, - e: &Expr_, - span: Span, - fld: @ast_fold, - orig: @fn(&Expr_, Span, @ast_fold) -> (Expr_, Span)) - -> (Expr_, Span) { - match *e { + e: @ast::Expr, + fld: &MacroExpander) + -> @ast::Expr { + match e.node { // expr_mac should really be expr_ext or something; it's the // entry-point for all syntax extensions. ExprMac(ref mac) => { @@ -66,7 +65,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, } Some(@SE(NormalTT(expandfun, exp_span))) => { cx.bt_push(ExpnInfo { - call_site: span, + call_site: e.span, callee: NameAndSpan { name: extnamestr, span: exp_span, @@ -84,10 +83,12 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, let mac_span = original_span(cx); let expanded = - match expandfun(cx, mac_span.call_site, - marked_before, marked_ctxt) { + match expandfun.expand(cx, + mac_span.call_site, + marked_before, + marked_ctxt) { MRExpr(e) => e, - MRAny(expr_maker,_,_) => expr_maker(), + MRAny(any_macro) => any_macro.make_expr(), _ => { cx.span_fatal( pth.span, @@ -101,12 +102,19 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, // mark after: let marked_after = mark_expr(expanded,fm); - //keep going, outside-in + // Keep going, outside-in. + // + // XXX(pcwalton): Is it necessary to clone the + // node here? let fully_expanded = fld.fold_expr(marked_after).node.clone(); cx.bt_pop(); - (fully_expanded, span) + @ast::Expr { + id: ast::DUMMY_NODE_ID, + node: fully_expanded, + span: e.span, + } } _ => { cx.span_fatal( @@ -125,8 +133,48 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, ast::ExprForLoop(src_pat, src_expr, ref src_loop_block, opt_ident) => { // Expand any interior macros etc. // NB: we don't fold pats yet. Curious. - let src_expr = fld.fold_expr(src_expr); - let src_loop_block = fld.fold_block(src_loop_block); + let src_expr = fld.fold_expr(src_expr).clone(); + let src_loop_block = fld.fold_block(src_loop_block).clone(); + + let span = e.span; + + pub fn mk_expr(_: @ExtCtxt, span: Span, node: Expr_) + -> @ast::Expr { + @ast::Expr { + id: ast::DUMMY_NODE_ID, + node: node, + span: span, + } + } + + fn mk_block(_: @ExtCtxt, + stmts: &[@ast::Stmt], + expr: Option<@ast::Expr>, + span: Span) + -> ast::Block { + ast::Block { + view_items: ~[], + stmts: stmts.to_owned(), + expr: expr, + id: ast::DUMMY_NODE_ID, + rules: ast::DefaultBlock, + span: span, + } + } + + fn mk_simple_path(ident: ast::Ident, span: Span) -> ast::Path { + ast::Path { + span: span, + global: false, + segments: ~[ + ast::PathSegment { + identifier: ident, + lifetime: None, + types: opt_vec::Empty, + } + ], + } + } // to: // @@ -182,10 +230,14 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, ~[iter_decl_stmt], Some(loop_expr)); - (ast::ExprBlock(block), span) + @ast::Expr { + id: ast::DUMMY_NODE_ID, + node: ast::ExprBlock(block), + span: span, + } } - _ => orig(e, span, fld) + _ => noop_fold_expr(e, fld) } } @@ -201,12 +253,10 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, pub fn expand_mod_items(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, module_: &ast::_mod, - fld: @ast_fold, - orig: @fn(&ast::_mod, @ast_fold) -> ast::_mod) - -> ast::_mod { - + fld: &MacroExpander) + -> ast::_mod { // Fold the contents first: - let module_ = orig(module_, fld); + let module_ = noop_fold_mod(module_, fld); // For each item, look through the attributes. If any of them are // decorated with "item decorators", then use that function to transform @@ -233,7 +283,10 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv, } }; - ast::_mod { items: new_items, ..module_ } + ast::_mod { + items: new_items, + ..module_ + } } // eval $e with a new exts frame: @@ -256,19 +309,20 @@ static special_block_name : &'static str = " block"; pub fn expand_item(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, it: @ast::item, - fld: @ast_fold, - orig: @fn(@ast::item, @ast_fold) -> Option<@ast::item>) - -> Option<@ast::item> { + fld: &MacroExpander) + -> Option<@ast::item> { match it.node { ast::item_mac(*) => expand_item_mac(extsbox, cx, it, fld), ast::item_mod(_) | ast::item_foreign_mod(_) => { cx.mod_push(it.ident); let macro_escape = contains_macro_escape(it.attrs); - let result = with_exts_frame!(extsbox,macro_escape,orig(it,fld)); + let result = with_exts_frame!(extsbox, + macro_escape, + noop_fold_item(it, fld)); cx.mod_pop(); result }, - _ => orig(it,fld) + _ => noop_fold_item(it, fld) } } @@ -280,11 +334,15 @@ pub fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. pub fn expand_item_mac(extsbox: @mut SyntaxEnv, - cx: @ExtCtxt, it: @ast::item, - fld: @ast_fold) - -> Option<@ast::item> { + cx: @ExtCtxt, + it: @ast::item, + fld: &MacroExpander) + -> Option<@ast::item> { let (pth, tts, ctxt) = match it.node { - item_mac(codemap::Spanned { node: mac_invoc_tt(ref pth, ref tts, ctxt), _}) => { + item_mac(codemap::Spanned { + node: mac_invoc_tt(ref pth, ref tts, ctxt), + _ + }) => { (pth, (*tts).clone(), ctxt) } _ => cx.span_bug(it.span, "invalid item macro invocation") @@ -314,7 +372,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, // mark before expansion: let marked_before = mark_tts(tts,fm); let marked_ctxt = new_mark(fm,ctxt); - expander(cx, it.span, marked_before, marked_ctxt) + expander.expand(cx, it.span, marked_before, marked_ctxt) } Some(@SE(IdentTT(expander, span))) => { if it.ident.name == parse::token::special_idents::invalid.name { @@ -332,7 +390,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, // mark before expansion: let marked_tts = mark_tts(tts,fm); let marked_ctxt = new_mark(fm,ctxt); - expander(cx, it.span, it.ident, marked_tts, marked_ctxt) + expander.expand(cx, it.span, it.ident, marked_tts, marked_ctxt) } _ => cx.span_fatal( it.span, fmt!("%s! is not legal in item position", extnamestr)) @@ -346,10 +404,10 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, MRExpr(_) => { cx.span_fatal(pth.span, fmt!("expr macro in item position: %s", extnamestr)) } - MRAny(_, item_maker, _) => { - item_maker() - .and_then(|i| mark_item(i,fm)) - .and_then(|i| fld.fold_item(i)) + MRAny(any_macro) => { + any_macro.make_item() + .and_then(|i| mark_item(i,fm)) + .and_then(|i| fld.fold_item(i)) } MRDef(ref mdef) => { // yikes... no idea how to apply the mark to this. I'm afraid @@ -382,15 +440,12 @@ fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) { // expand a stmt pub fn expand_stmt(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, - s: &Stmt_, - sp: Span, - fld: @ast_fold, - orig: @fn(&Stmt_, Span, @ast_fold) - -> (Option<Stmt_>, Span)) - -> (Option<Stmt_>, Span) { + s: &Stmt, + fld: &MacroExpander) + -> Option<@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 { + let (pth, tts, semi, ctxt) = match s.node { StmtMac(ref mac, semi) => { match mac.node { mac_invoc_tt(ref pth, ref tts, ctxt) => { @@ -398,24 +453,26 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } } } - _ => return expand_non_macro_stmt(*extsbox,s,sp,fld,orig) + _ => return expand_non_macro_stmt(*extsbox, s, fld) }; if (pth.segments.len() > 1u) { - cx.span_fatal( - pth.span, - fmt!("expected macro name without module \ - separators")); + cx.span_fatal(pth.span, + "expected macro name without module separators"); } let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); - let (fully_expanded, sp) = match (*extsbox).find(&extname.name) { - None => - cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", extnamestr)), + let fully_expanded: @ast::Stmt = match (*extsbox).find(&extname.name) { + None => { + cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", extnamestr)) + } Some(@SE(NormalTT(expandfun, exp_span))) => { cx.bt_push(ExpnInfo { - call_site: sp, - callee: NameAndSpan { name: extnamestr, span: exp_span } + call_site: s.span, + callee: NameAndSpan { + name: extnamestr, + span: exp_span, + } }); let fm = fresh_mark(); // mark before expansion: @@ -426,24 +483,32 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, // not the current mac.span. let mac_span = original_span(cx); - let expanded = match expandfun(cx, mac_span.call_site, - marked_tts, marked_ctxt) { - MRExpr(e) => - @codemap::Spanned { node: StmtExpr(e, ast::DUMMY_NODE_ID), - span: e.span}, - MRAny(_,_,stmt_mkr) => stmt_mkr(), + let expanded = match expandfun.expand(cx, + mac_span.call_site, + marked_tts, + marked_ctxt) { + MRExpr(e) => { + @codemap::Spanned { + node: StmtExpr(e, ast::DUMMY_NODE_ID), + span: e.span, + } + } + MRAny(any_macro) => any_macro.make_stmt(), _ => cx.span_fatal( pth.span, fmt!("non-stmt macro in stmt pos: %s", extnamestr)) }; let marked_after = mark_stmt(expanded,fm); - //keep going, outside-in + // Keep going, outside-in. let fully_expanded = match fld.fold_stmt(marked_after) { Some(stmt) => { let fully_expanded = &stmt.node; cx.bt_pop(); - (*fully_expanded).clone() + @Spanned { + span: stmt.span, + node: (*fully_expanded).clone(), + } } None => { cx.span_fatal(pth.span, @@ -451,7 +516,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } }; - (fully_expanded, sp) + fully_expanded } _ => { @@ -460,24 +525,28 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } }; - (match fully_expanded { - StmtExpr(e, stmt_id) if semi => Some(StmtSemi(e, stmt_id)), - _ => { Some(fully_expanded) } /* might already have a semi */ - }, sp) - + match fully_expanded.node { + StmtExpr(e, stmt_id) if semi => { + Some(@Spanned { + span: fully_expanded.span, + node: StmtSemi(e, stmt_id), + }) + } + _ => Some(fully_expanded), /* might already have a semi */ + } } // expand a non-macro stmt. this is essentially the fallthrough for // expand_stmt, above. -fn expand_non_macro_stmt (exts: SyntaxEnv, - s: &Stmt_, - sp: Span, - fld: @ast_fold, - orig: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span)) - -> (Option<Stmt_>,Span) { +fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander) + -> Option<@Stmt> { // is it a let? - match *s { - StmtDecl(@Spanned{node: DeclLocal(ref local), span: stmt_span}, node_id) => { + match s.node { + StmtDecl(@Spanned { + node: DeclLocal(ref local), + span: stmt_span + }, + node_id) => { let block_info = get_block_info(exts); let pending_renames = block_info.pending_renames; @@ -515,19 +584,24 @@ fn expand_non_macro_stmt (exts: SyntaxEnv, // also, don't forget to expand the init: let new_init_opt = init.map(|e| fld.fold_expr(*e)); let rewritten_local = - @Local{is_mutbl:is_mutbl, - ty:ty, - pat:rewritten_pat, - init:new_init_opt, - id:id, - span:span}; - (Some(StmtDecl(@Spanned{node:DeclLocal(rewritten_local), - span: stmt_span},node_id)), - sp) + @Local { + is_mutbl: is_mutbl, + ty: ty, + pat: rewritten_pat, + init: new_init_opt, + id: id, + span: span, + }; + Some(@Spanned { + node: StmtDecl(@Spanned { + node: DeclLocal(rewritten_local), + span: stmt_span + }, + node_id), + span: span + }) }, - _ => { - orig(s, sp, fld) - } + _ => noop_fold_stmt(s, fld), } } @@ -628,18 +702,18 @@ pub fn new_path_finder(paths: @mut ~[ast::Path]) -> @mut Visitor<()> { // expand a block. pushes a new exts_frame, then calls expand_block_elts pub fn expand_block(extsbox: @mut SyntaxEnv, - _cx: @ExtCtxt, + _: @ExtCtxt, blk: &Block, - fld: @ast_fold, - _orig: @fn(&Block, @ast_fold) -> Block) - -> Block { + fld: &MacroExpander) + -> Block { // see note below about treatment of exts table with_exts_frame!(extsbox,false, expand_block_elts(*extsbox, blk, fld)) } // expand the elements of a block. -pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: @ast_fold) -> Block { +pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: &MacroExpander) + -> Block { let block_info = get_block_info(exts); let pending_renames = block_info.pending_renames; let rename_fld = renames_to_fold(pending_renames); @@ -680,9 +754,47 @@ fn get_block_info(exts : SyntaxEnv) -> BlockInfo { } } +struct IdentRenamer { + renames: @mut ~[(ast::Ident,ast::Name)], +} + +impl ast_fold for IdentRenamer { + fn fold_ident(&self, id: ast::Ident) -> ast::Ident { + let new_ctxt = self.renames.iter().fold(id.ctxt, |ctxt, &(from, to)| { + new_rename(from, to, ctxt) + }); + ast::Ident { + name: id.name, + ctxt: new_ctxt, + } + } +} + +// given a mutable list of renames, return a tree-folder that applies those +// renames. +pub fn renames_to_fold(renames: @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold { + @IdentRenamer { + renames: renames, + } as @ast_fold +} + +// perform a bunch of renames +fn apply_pending_renames(folder : @ast_fold, stmt : ast::Stmt) -> @ast::Stmt { + match folder.fold_stmt(&stmt) { + Some(s) => s, + None => fail!(fmt!("renaming of stmt produced None")) + } +} + + + pub fn new_span(cx: @ExtCtxt, sp: Span) -> Span { /* this discards information in the case of macro-defining macros */ - return Span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()}; + Span { + lo: sp.lo, + hi: sp.hi, + expn_info: cx.backtrace(), + } } // FIXME (#2247): this is a moderately bad kludge to inject some macros into @@ -1025,10 +1137,28 @@ pub fn std_macros() -> @str { }"; } +struct Injector { + sm: @ast::item, +} + +impl ast_fold for Injector { + fn fold_mod(&self, module: &ast::_mod) -> ast::_mod { + // Just inject the standard macros at the start of the first module + // in the crate: that is, at the start of the crate file itself. + let items = vec::append(~[ self.sm ], module.items); + ast::_mod { + items: items, + ..(*module).clone() // FIXME #2543: Bad copy. + } + } +} + // add a bunch of macros as though they were placed at the head of the // program (ick). This should run before cfg stripping. pub fn inject_std_macros(parse_sess: @mut parse::ParseSess, - cfg: ast::CrateConfig, c: &Crate) -> @Crate { + cfg: ast::CrateConfig, + c: @Crate) + -> @Crate { let sm = match parse_item_from_source_str(@"<std-macros>", std_macros(), cfg.clone(), @@ -1038,48 +1168,80 @@ pub fn inject_std_macros(parse_sess: @mut parse::ParseSess, None => fail!("expected core macros to parse correctly") }; - let injecter = @AstFoldFns { - fold_mod: |modd, _| { - // just inject the std macros at the start of the first - // module in the crate (i.e the crate file itself.) - let items = vec::append(~[sm], modd.items); - ast::_mod { - items: items, - // FIXME #2543: Bad copy. - .. (*modd).clone() - } - }, - .. *default_ast_fold() - }; - @make_fold(injecter).fold_crate(c) + let injector = @Injector { + sm: sm, + } as @ast_fold; + @injector.fold_crate(c) +} + +struct NoOpFolder { + contents: (), +} + +impl ast_fold for NoOpFolder {} + +struct MacroExpander { + extsbox: @mut SyntaxEnv, + cx: @ExtCtxt, +} + +impl ast_fold for MacroExpander { + fn fold_expr(&self, expr: @ast::Expr) -> @ast::Expr { + expand_expr(self.extsbox, + self.cx, + expr, + self) + } + + fn fold_mod(&self, module: &ast::_mod) -> ast::_mod { + expand_mod_items(self.extsbox, + self.cx, + module, + self) + } + + fn fold_item(&self, item: @ast::item) -> Option<@ast::item> { + expand_item(self.extsbox, + self.cx, + item, + self) + } + + fn fold_stmt(&self, stmt: &ast::Stmt) -> Option<@ast::Stmt> { + expand_stmt(self.extsbox, + self.cx, + stmt, + self) + } + + fn fold_block(&self, block: &ast::Block) -> ast::Block { + expand_block(self.extsbox, + self.cx, + block, + self) + } + + fn new_span(&self, span: Span) -> Span { + new_span(self.cx, span) + } } pub fn expand_crate(parse_sess: @mut parse::ParseSess, - cfg: ast::CrateConfig, c: &Crate) -> @Crate { + cfg: ast::CrateConfig, + c: &Crate) -> @Crate { // adding *another* layer of indirection here so that the block // visitor can swap out one exts table for another for the duration // of the block. The cleaner alternative would be to thread the // exts table through the fold, but that would require updating // every method/element of AstFoldFns in fold.rs. - let extsbox = @mut syntax_expander_table(); - let afp = default_ast_fold(); + let extsbox = syntax_expander_table(); let cx = ExtCtxt::new(parse_sess, cfg.clone()); - let f_pre = @AstFoldFns { - fold_expr: |expr,span,recur| - expand_expr(extsbox, cx, expr, span, recur, afp.fold_expr), - fold_mod: |modd,recur| - expand_mod_items(extsbox, cx, modd, recur, afp.fold_mod), - fold_item: |item,recur| - expand_item(extsbox, cx, item, recur, afp.fold_item), - fold_stmt: |stmt,span,recur| - expand_stmt(extsbox, cx, stmt, span, recur, afp.fold_stmt), - fold_block: |blk,recur| - expand_block(extsbox, cx, blk, recur, afp.fold_block), - new_span: |a| new_span(cx, a), - .. *afp}; - let f = make_fold(f_pre); - - let ret = @f.fold_crate(c); + let expander = @MacroExpander { + extsbox: @mut extsbox, + cx: cx, + } as @ast_fold; + + let ret = @expander.fold_crate(c); parse_sess.span_diagnostic.handler().abort_if_errors(); return ret; } @@ -1145,53 +1307,56 @@ impl CtxtFn for Repainter { } } -// given a function from ctxts to ctxts, produce -// an ast_fold that applies that function to all ctxts: -pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @AstFoldFns { - let afp = default_ast_fold(); - let fi : @fn(ast::Ident, @ast_fold) -> ast::Ident = - |ast::Ident{name, ctxt}, _| { - ast::Ident{name:name,ctxt:cf.f(ctxt)} - }; - let fm : @fn(&ast::mac_, Span, @ast_fold) -> (ast::mac_,Span) = - |m, sp, fld| { - match *m { - mac_invoc_tt(ref path, ref tts, ctxt) => - (mac_invoc_tt(fld.fold_path(path), - fold_tts(*tts,fld), - cf.f(ctxt)), - sp) - } +pub struct ContextWrapper { + context_function: @CtxtFn, +} - }; - @AstFoldFns{ - fold_ident : fi, - fold_mac : fm, - .. *afp +impl ast_fold for ContextWrapper { + fn fold_ident(&self, id: ast::Ident) -> ast::Ident { + let ast::Ident { + name, + ctxt + } = id; + ast::Ident { + name: name, + ctxt: self.context_function.f(ctxt), + } + } + fn fold_mac(&self, m: &ast::mac) -> ast::mac { + let macro = match m.node { + mac_invoc_tt(ref path, ref tts, ctxt) => { + mac_invoc_tt(self.fold_path(path), + fold_tts(*tts, self), + self.context_function.f(ctxt)) + } + }; + Spanned { + node: macro, + span: m.span, + } } } - - -// given a mutable list of renames, return a tree-folder that applies those -// renames. -// FIXME #4536: currently pub to allow testing -pub fn renames_to_fold(renames : @mut ~[(ast::Ident,ast::Name)]) -> @AstFoldFns { - fun_to_ctxt_folder(@MultiRenamer{renames : renames}) +// given a function from ctxts to ctxts, produce +// an ast_fold that applies that function to all ctxts: +pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @ContextWrapper { + @ContextWrapper { + context_function: cf as @CtxtFn, + } } // just a convenience: -pub fn new_mark_folder(m : Mrk) -> @AstFoldFns { +pub fn new_mark_folder(m: Mrk) -> @ContextWrapper { fun_to_ctxt_folder(@Marker{mark:m}) } -pub fn new_rename_folder(from : ast::Ident, to : ast::Name) -> @AstFoldFns { +pub fn new_rename_folder(from: ast::Ident, to: ast::Name) -> @ContextWrapper { fun_to_ctxt_folder(@Renamer{from:from,to:to}) } // apply a given mark to the given token trees. Used prior to expansion of a macro. fn mark_tts(tts : &[token_tree], m : Mrk) -> ~[token_tree] { - fold_tts(tts,new_mark_folder(m) as @ast_fold) + fold_tts(tts,new_mark_folder(m)) } // apply a given mark to the given expr. Used following the expansion of a macro. @@ -1359,7 +1524,7 @@ mod test { let ident_str = @"x"; let tts = string_to_tts(ident_str); let fm = fresh_mark(); - let marked_once = fold::fold_tts(tts,new_mark_folder(fm) as @fold::ast_fold); + let marked_once = fold::fold_tts(tts,new_mark_folder(fm)); assert_eq!(marked_once.len(),1); let marked_once_ctxt = match marked_once[0] { diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 9adb02ecc98..d48fa03c0ef 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -38,7 +38,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) fn parse_fmt_err_(cx: @ExtCtxt, sp: Span, msg: &str) -> ! { cx.span_fatal(sp, msg); } - let parse_fmt_err: @fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s); + let parse_fmt_err: &fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s); let pieces = parse_fmt_string(fmt, parse_fmt_err); MRExpr(pieces_to_expr(cx, sp, pieces, args)) } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 74de8eaa09e..3fd394b3652 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -12,9 +12,9 @@ use ast::{Ident, matcher_, matcher, match_tok, match_nonterminal, match_seq}; use ast::{tt_delim}; use ast; use codemap::{Span, Spanned, dummy_sp}; -use ext::base::{ExtCtxt, MacResult, MRAny, MRDef, MacroDef, NormalTT}; +use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef}; +use ext::base::{NormalTT, SyntaxExpanderTTTrait}; use ext::base; -use ext::expand; use ext::tt::macro_parser::{error}; use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; use ext::tt::macro_parser::{parse, parse_or_else, success, failure}; @@ -24,6 +24,112 @@ use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_st use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt}; use print; +struct ParserAnyMacro { + parser: @Parser, +} + +impl AnyMacro for ParserAnyMacro { + fn make_expr(&self) -> @ast::Expr { + self.parser.parse_expr() + } + fn make_item(&self) -> Option<@ast::item> { + self.parser.parse_item(~[]) // no attrs + } + fn make_stmt(&self) -> @ast::Stmt { + self.parser.parse_stmt(~[]) // no attrs + } +} + +struct MacroRulesSyntaxExpanderTTFun { + name: Ident, + lhses: @~[@named_match], + rhses: @~[@named_match], +} + +impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun { + fn expand(&self, + cx: @ExtCtxt, + sp: Span, + arg: &[ast::token_tree], + _: ast::SyntaxContext) + -> MacResult { + generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses) + } +} + +// Given `lhses` and `rhses`, this is the new macro we create +fn generic_extension(cx: @ExtCtxt, + sp: Span, + name: Ident, + arg: &[ast::token_tree], + lhses: &[@named_match], + rhses: &[@named_match]) + -> MacResult { + if cx.trace_macros() { + printfln!("%s! { %s }", + cx.str_of(name), + print::pprust::tt_to_str( + &ast::tt_delim(@mut arg.to_owned()), + get_ident_interner())); + } + + // Which arm's failure should we report? (the one furthest along) + let mut best_fail_spot = dummy_sp(); + let mut best_fail_msg = ~"internal error: ran no matchers"; + + let s_d = cx.parse_sess().span_diagnostic; + + for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers + match *lhs { + @matched_nonterminal(nt_matchers(ref mtcs)) => { + // `none` is because we're not interpolating + let arg_rdr = new_tt_reader( + s_d, + None, + arg.to_owned() + ) as @mut reader; + match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) { + success(named_matches) => { + let rhs = match rhses[i] { + // okay, what's your transcriber? + @matched_nonterminal(nt_tt(@ref tt)) => { + match (*tt) { + // cut off delimiters; don't parse 'em + tt_delim(ref tts) => { + (*tts).slice(1u,(*tts).len()-1u).to_owned() + } + _ => cx.span_fatal( + sp, "macro rhs must be delimited") + } + }, + _ => cx.span_bug(sp, "bad thing in rhs") + }; + // rhs has holes ( `$id` and `$(...)` that need filled) + let trncbr = new_tt_reader(s_d, Some(named_matches), + rhs); + let p = @Parser(cx.parse_sess(), + cx.cfg(), + trncbr as @mut reader); + + // Let the context choose how to interpret the result. + // Weird, but useful for X-macros. + return MRAny(@ParserAnyMacro { + parser: p, + } as @AnyMacro) + } + failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { + best_fail_spot = sp; + best_fail_msg = (*msg).clone(); + }, + error(sp, ref msg) => cx.span_fatal(sp, (*msg)) + } + } + _ => cx.bug("non-matcher found in parsed lhses") + } + } + cx.span_fatal(best_fail_spot, best_fail_msg); +} + // this procedure performs the expansion of the // macro_rules! macro. It parses the RHS and adds // an extension to the current context. @@ -31,10 +137,8 @@ pub fn add_new_extension(cx: @ExtCtxt, sp: Span, name: Ident, arg: ~[ast::token_tree], - stx_ctxt: ast::SyntaxContext) - -> base::MacResult { - let arg = expand::mtwt_cancel_outer_mark(arg,stx_ctxt); - // Wrap a matcher_ in a spanned to produce a matcher. + _: ast::SyntaxContext) + -> base::MacResult { // these spans won't matter, anyways fn ms(m: matcher_) -> matcher { Spanned { @@ -82,11 +186,13 @@ pub fn add_new_extension(cx: @ExtCtxt, }; // Given `lhses` and `rhses`, this is the new macro we create - fn generic_extension(cx: @ExtCtxt, sp: Span, name: Ident, + fn generic_extension(cx: @ExtCtxt, + sp: Span, + name: Ident, arg: &[ast::token_tree], - lhses: &[@named_match], rhses: &[@named_match]) - -> MacResult { - + lhses: &[@named_match], + rhses: &[@named_match]) + -> MacResult { if cx.trace_macros() { printfln!("%s! { %s }", cx.str_of(name), @@ -135,9 +241,9 @@ pub fn add_new_extension(cx: @ExtCtxt, // Let the context choose how to interpret the result. // Weird, but useful for X-macros. - return MRAny(|| p.parse_expr(), - || p.parse_item(~[/* no attrs*/]), - || p.parse_stmt(~[/* no attrs*/])); + return MRAny(@ParserAnyMacro { + parser: p + } as @AnyMacro); } failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { best_fail_spot = sp; @@ -152,10 +258,13 @@ pub fn add_new_extension(cx: @ExtCtxt, cx.span_fatal(best_fail_spot, best_fail_msg); } - let exp: @fn(@ExtCtxt, Span, &[ast::token_tree], ctxt: ast::SyntaxContext) -> MacResult = - |cx, sp, arg, _ctxt| generic_extension(cx, sp, name, arg, *lhses, *rhses); + let exp = @MacroRulesSyntaxExpanderTTFun { + name: name, + lhses: lhses, + rhses: rhses, + } as @SyntaxExpanderTTTrait; - return MRDef(MacroDef{ + return MRDef(MacroDef { name: ident_to_str(&name), ext: NormalTT(exp, Some(sp)) }); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 5472c61a155..a25f267c458 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -14,227 +14,434 @@ use codemap::{Span, Spanned}; use parse::token; use opt_vec::OptVec; -// this file defines an ast_fold trait for objects that can perform -// a "fold" on Rust ASTs. It also contains a structure that implements -// that trait, and a "default_fold" whose fields contain closures -// that perform "default traversals", visiting all of the sub-elements -// and re-assembling the result. The "fun_to_ident_folder" in the -// test module provides a simple example of creating a very simple -// fold that only looks at identifiers. - +// We may eventually want to be able to fold over type parameters, too. pub trait ast_fold { - fn fold_crate(@self, &Crate) -> Crate; - fn fold_view_item(@self, &view_item) -> view_item; - fn fold_foreign_item(@self, @foreign_item) -> @foreign_item; - fn fold_item(@self, @item) -> Option<@item>; - fn fold_struct_field(@self, @struct_field) -> @struct_field; - fn fold_item_underscore(@self, &item_) -> item_; - fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod; - fn fold_method(@self, @method) -> @method; - fn fold_block(@self, &Block) -> Block; - fn fold_stmt(@self, &Stmt) -> Option<@Stmt>; - fn fold_arm(@self, &Arm) -> Arm; - fn fold_pat(@self, @Pat) -> @Pat; - fn fold_decl(@self, @Decl) -> Option<@Decl>; - fn fold_expr(@self, @Expr) -> @Expr; - fn fold_ty(@self, &Ty) -> Ty; - fn fold_mod(@self, &_mod) -> _mod; - fn fold_foreign_mod(@self, &foreign_mod) -> foreign_mod; - fn fold_variant(@self, &variant) -> variant; - fn fold_ident(@self, Ident) -> Ident; - fn fold_path(@self, &Path) -> Path; - fn fold_local(@self, @Local) -> @Local; - fn fold_mac(@self, &mac) -> mac; - fn map_exprs(@self, @fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr]; - fn new_id(@self, NodeId) -> NodeId; - fn new_span(@self, Span) -> Span; - - // New style, using default methods: - - fn fold_variant_arg(@self, va: &variant_arg) -> variant_arg { - variant_arg { - ty: self.fold_ty(&va.ty), - id: self.new_id(va.id) - } - } - - fn fold_spanned<T>(@self, s: &Spanned<T>, f: &fn(&T) -> T) -> Spanned<T> { - Spanned { - node: f(&s.node), - span: self.new_span(s.span) - } + fn fold_crate(&self, c: &Crate) -> Crate { + noop_fold_crate(c, self) } - fn fold_view_path(@self, vp: &view_path) -> view_path { - self.fold_spanned(vp, |v| self.fold_view_path_(v)) + fn fold_meta_items(&self, meta_items: &[@MetaItem]) -> ~[@MetaItem] { + meta_items.map(|x| fold_meta_item_(*x, self)) } - fn fold_view_paths(@self, vps: &[@view_path]) -> ~[@view_path] { - vps.map(|vp| @self.fold_view_path(*vp)) + fn fold_view_paths(&self, view_paths: &[@view_path]) -> ~[@view_path] { + view_paths.map(|view_path| { + let inner_view_path = match view_path.node { + view_path_simple(ref ident, ref path, node_id) => { + view_path_simple(ident.clone(), + self.fold_path(path), + self.new_id(node_id)) + } + view_path_glob(ref path, node_id) => { + view_path_glob(self.fold_path(path), self.new_id(node_id)) + } + view_path_list(ref path, ref path_list_idents, node_id) => { + view_path_list(self.fold_path(path), + path_list_idents.map(|path_list_ident| { + let id = self.new_id(path_list_ident.node + .id); + Spanned { + node: path_list_ident_ { + name: path_list_ident.node + .name + .clone(), + id: id, + }, + span: self.new_span( + path_list_ident.span) + } + }), + self.new_id(node_id)) + } + }; + @Spanned { + node: inner_view_path, + span: self.new_span(view_path.span), + } + }) } - fn fold_view_path_(@self, vp: &view_path_) -> view_path_ { - match *vp { - view_path_simple(ident, ref path, node_id) => { - view_path_simple(self.fold_ident(ident), - self.fold_path(path), - self.new_id(node_id)) - } - view_path_glob(ref path, node_id) => { - view_path_glob(self.fold_path(path), - self.new_id(node_id)) + fn fold_view_item(&self, vi: &view_item) -> view_item { + let inner_view_item = match vi.node { + view_item_extern_mod(ref ident, + string, + ref meta_items, + node_id) => { + view_item_extern_mod(ident.clone(), + string, + self.fold_meta_items(*meta_items), + self.new_id(node_id)) } - view_path_list(ref path, ref idents, node_id) => { - view_path_list(self.fold_path(path), - self.fold_path_list_idents(*idents), - self.new_id(node_id)) + view_item_use(ref view_paths) => { + view_item_use(self.fold_view_paths(*view_paths)) } + }; + view_item { + node: inner_view_item, + attrs: vi.attrs.map(|a| fold_attribute_(*a, self)), + vis: vi.vis, + span: self.new_span(vi.span), + } + } + + fn fold_foreign_item(&self, ni: @foreign_item) -> @foreign_item { + let fold_attribute = |x| fold_attribute_(x, self); + + @ast::foreign_item { + ident: self.fold_ident(ni.ident), + attrs: ni.attrs.map(|x| fold_attribute(*x)), + node: + match ni.node { + foreign_item_fn(ref fdec, ref generics) => { + foreign_item_fn( + ast::fn_decl { + inputs: fdec.inputs.map(|a| fold_arg_(a, + self)), + output: self.fold_ty(&fdec.output), + cf: fdec.cf, + }, + fold_generics(generics, self)) + } + foreign_item_static(ref t, m) => { + foreign_item_static(self.fold_ty(t), m) + } + }, + id: self.new_id(ni.id), + span: self.new_span(ni.span), + vis: ni.vis, } } - fn fold_path_list_idents(@self, idents: &[path_list_ident]) -> ~[path_list_ident] { - idents.map(|i| self.fold_path_list_ident(i)) + fn fold_item(&self, i: @item) -> Option<@item> { + noop_fold_item(i, self) } - fn fold_path_list_ident(@self, ident: &path_list_ident) -> path_list_ident { - self.fold_spanned(ident, |i| self.fold_path_list_ident_(i)) - } + fn fold_struct_field(&self, sf: @struct_field) -> @struct_field { + let fold_attribute = |x| fold_attribute_(x, self); - fn fold_path_list_ident_(@self, ident: &path_list_ident_) -> path_list_ident_ { - path_list_ident_ { - name: self.fold_ident(ident.name), - id: self.new_id(ident.id) + @Spanned { + node: ast::struct_field_ { + kind: sf.node.kind, + id: self.new_id(sf.node.id), + ty: self.fold_ty(&sf.node.ty), + attrs: sf.node.attrs.map(|e| fold_attribute(*e)) + }, + span: self.new_span(sf.span) } } - fn fold_arg(@self, a: &arg) -> arg { - arg { - is_mutbl: a.is_mutbl, - ty: self.fold_ty(&a.ty), - pat: self.fold_pat(a.pat), - id: self.new_id(a.id), + fn fold_item_underscore(&self, i: &item_) -> item_ { + noop_fold_item_underscore(i, self) + } + + fn fold_type_method(&self, m: &TypeMethod) -> TypeMethod { + noop_fold_type_method(m, self) + } + + fn fold_method(&self, m: @method) -> @method { + @ast::method { + ident: self.fold_ident(m.ident), + attrs: m.attrs.map(|a| fold_attribute_(*a, self)), + generics: fold_generics(&m.generics, self), + explicit_self: m.explicit_self, + purity: m.purity, + decl: fold_fn_decl(&m.decl, self), + body: self.fold_block(&m.body), + id: self.new_id(m.id), + span: self.new_span(m.span), + self_id: self.new_id(m.self_id), + vis: m.vis, } } - fn fold_trait_ref(@self, p: &trait_ref) -> trait_ref { - trait_ref { - path: self.fold_path(&p.path), - ref_id: self.new_id(p.ref_id), + fn fold_block(&self, b: &Block) -> Block { + noop_fold_block(b, self) + } + + fn fold_stmt(&self, s: &Stmt) -> Option<@Stmt> { + noop_fold_stmt(s, self) + } + + fn fold_arm(&self, a: &Arm) -> Arm { + Arm { + pats: a.pats.map(|x| self.fold_pat(*x)), + guard: a.guard.map_move(|x| self.fold_expr(x)), + body: self.fold_block(&a.body), } } - fn fold_ty_param_bound(@self, tpb: &TyParamBound) -> TyParamBound { - match *tpb { - TraitTyParamBound(ref ty) => { - TraitTyParamBound(self.fold_trait_ref(ty)) + fn fold_pat(&self, p: @Pat) -> @Pat { + let node = match p.node { + PatWild => PatWild, + PatIdent(binding_mode, ref pth, ref sub) => { + PatIdent(binding_mode, + self.fold_path(pth), + sub.map_move(|x| self.fold_pat(x))) + } + PatLit(e) => PatLit(self.fold_expr(e)), + PatEnum(ref pth, ref pats) => { + PatEnum(self.fold_path(pth), + pats.map(|pats| pats.map(|x| self.fold_pat(*x)))) } - RegionTyParamBound => { - RegionTyParamBound + PatStruct(ref pth, ref fields, etc) => { + let pth_ = self.fold_path(pth); + let fs = do fields.map |f| { + ast::FieldPat { + ident: f.ident, + pat: self.fold_pat(f.pat) + } + }; + PatStruct(pth_, fs, etc) } + PatTup(ref elts) => PatTup(elts.map(|x| self.fold_pat(*x))), + PatBox(inner) => PatBox(self.fold_pat(inner)), + PatUniq(inner) => PatUniq(self.fold_pat(inner)), + PatRegion(inner) => PatRegion(self.fold_pat(inner)), + PatRange(e1, e2) => { + PatRange(self.fold_expr(e1), self.fold_expr(e2)) + }, + PatVec(ref before, ref slice, ref after) => { + PatVec(before.map(|x| self.fold_pat(*x)), + slice.map_move(|x| self.fold_pat(x)), + after.map(|x| self.fold_pat(*x))) + } + }; + + @Pat { + id: self.new_id(p.id), + span: self.new_span(p.span), + node: node, } } - fn fold_ty_param(@self, tp: &TyParam) -> TyParam { - TyParam { - ident: self.fold_ident(tp.ident), - id: self.new_id(tp.id), - bounds: tp.bounds.map(|x| self.fold_ty_param_bound(x)) + fn fold_decl(&self, d: @Decl) -> Option<@Decl> { + let node = match d.node { + DeclLocal(ref l) => Some(DeclLocal(self.fold_local(*l))), + DeclItem(it) => { + match self.fold_item(it) { + Some(it_folded) => Some(DeclItem(it_folded)), + None => None, + } + } + }; + + node.map_move(|node| { + @Spanned { + node: node, + span: d.span, + } + }) + } + + fn fold_expr(&self, e: @Expr) -> @Expr { + noop_fold_expr(e, self) + } + + fn fold_ty(&self, t: &Ty) -> Ty { + let node = match t.node { + ty_nil | ty_bot | ty_infer => t.node.clone(), + ty_box(ref mt) => ty_box(fold_mt(mt, self)), + ty_uniq(ref mt) => ty_uniq(fold_mt(mt, self)), + ty_vec(ref mt) => ty_vec(fold_mt(mt, self)), + ty_ptr(ref mt) => ty_ptr(fold_mt(mt, self)), + ty_rptr(region, ref mt) => ty_rptr(region, fold_mt(mt, self)), + ty_closure(ref f) => { + ty_closure(@TyClosure { + sigil: f.sigil, + purity: f.purity, + region: f.region, + onceness: f.onceness, + bounds: fold_opt_bounds(&f.bounds, self), + decl: fold_fn_decl(&f.decl, self), + lifetimes: f.lifetimes.map(|l| fold_lifetime(l, self)), + }) + } + ty_bare_fn(ref f) => { + ty_bare_fn(@TyBareFn { + lifetimes: f.lifetimes.map(|l| fold_lifetime(l, self)), + purity: f.purity, + abis: f.abis, + decl: fold_fn_decl(&f.decl, self) + }) + } + ty_tup(ref tys) => ty_tup(tys.map(|ty| self.fold_ty(ty))), + ty_path(ref path, ref bounds, id) => { + ty_path(self.fold_path(path), + fold_opt_bounds(bounds, self), + self.new_id(id)) + } + ty_fixed_length_vec(ref mt, e) => { + ty_fixed_length_vec(fold_mt(mt, self), self.fold_expr(e)) + } + ty_mac(ref mac) => ty_mac(self.fold_mac(mac)), + ty_typeof(expr) => ty_typeof(self.fold_expr(expr)), + }; + Ty { + id: self.new_id(t.id), + span: self.new_span(t.span), + node: node, } } - fn fold_ty_params(@self, tps: &OptVec<TyParam>) -> OptVec<TyParam> { - tps.map(|tp| self.fold_ty_param(tp)) + fn fold_mod(&self, m: &_mod) -> _mod { + noop_fold_mod(m, self) } - fn fold_lifetime(@self, l: &Lifetime) -> Lifetime { - Lifetime { - id: self.new_id(l.id), - span: self.new_span(l.span), - ident: l.ident, // Folding this ident causes hygiene errors - ndm + fn fold_foreign_mod(&self, nm: &foreign_mod) -> foreign_mod { + ast::foreign_mod { + sort: nm.sort, + abis: nm.abis, + view_items: nm.view_items + .iter() + .map(|x| self.fold_view_item(x)) + .collect(), + items: nm.items + .iter() + .map(|x| self.fold_foreign_item(*x)) + .collect(), } } - fn fold_lifetimes(@self, lts: &OptVec<Lifetime>) -> OptVec<Lifetime> { - lts.map(|l| self.fold_lifetime(l)) + fn fold_variant(&self, v: &variant) -> variant { + let kind; + match v.node.kind { + tuple_variant_kind(ref variant_args) => { + kind = tuple_variant_kind(variant_args.map(|x| + fold_variant_arg_(x, self))) + } + struct_variant_kind(ref struct_def) => { + kind = struct_variant_kind(@ast::struct_def { + fields: struct_def.fields.iter() + .map(|f| self.fold_struct_field(*f)).collect(), + ctor_id: struct_def.ctor_id.map(|c| self.new_id(*c)) + }) + } + } + + let fold_attribute = |x| fold_attribute_(x, self); + let attrs = v.node.attrs.map(|x| fold_attribute(*x)); + + let de = match v.node.disr_expr { + Some(e) => Some(self.fold_expr(e)), + None => None + }; + let node = ast::variant_ { + name: v.node.name, + attrs: attrs, + kind: kind, + id: self.new_id(v.node.id), + disr_expr: de, + vis: v.node.vis, + }; + Spanned { + node: node, + span: self.new_span(v.span), + } } + fn fold_ident(&self, i: Ident) -> Ident { + i + } - fn fold_meta_item(@self, mi: &MetaItem) -> @MetaItem { - @self.fold_spanned(mi, |n| match *n { - MetaWord(id) => { - MetaWord(id) - } - MetaList(id, ref mis) => { - MetaList(id, self.fold_meta_items(*mis)) - } - MetaNameValue(id, s) => { - MetaNameValue(id, s) - } + fn fold_path(&self, p: &Path) -> Path { + ast::Path { + span: self.new_span(p.span), + global: p.global, + segments: p.segments.map(|segment| ast::PathSegment { + identifier: self.fold_ident(segment.identifier), + lifetime: segment.lifetime, + types: segment.types.map(|typ| self.fold_ty(typ)), }) + } } - fn fold_meta_items(@self, mis: &[@MetaItem]) -> ~[@MetaItem] { - mis.map(|&mi| self.fold_meta_item(mi)) + fn fold_local(&self, l: @Local) -> @Local { + @Local { + is_mutbl: l.is_mutbl, + ty: self.fold_ty(&l.ty), + pat: self.fold_pat(l.pat), + init: l.init.map_move(|e| self.fold_expr(e)), + id: self.new_id(l.id), + span: self.new_span(l.span), + } } - fn fold_attribute(@self, at: &Attribute) -> Attribute { + fn fold_mac(&self, macro: &mac) -> mac { Spanned { - span: self.new_span(at.span), - node: Attribute_ { - style: at.node.style, - value: self.fold_meta_item(at.node.value), - is_sugared_doc: at.node.is_sugared_doc - } + node: match macro.node { + mac_invoc_tt(ref p, ref tts, ctxt) => { + mac_invoc_tt(self.fold_path(p), + fold_tts(*tts, self), + ctxt) + } + }, + span: self.new_span(macro.span) } } - fn fold_attributes(@self, attrs: &[Attribute]) -> ~[Attribute] { - attrs.map(|x| self.fold_attribute(x)) + fn map_exprs(&self, f: &fn(@Expr) -> @Expr, es: &[@Expr]) -> ~[@Expr] { + es.map(|x| f(*x)) + } + + fn new_id(&self, i: NodeId) -> NodeId { + i + } + + fn new_span(&self, sp: Span) -> Span { + sp } } -// We may eventually want to be able to fold over type parameters, too - -pub struct AstFoldFns { - //unlike the others, item_ is non-trivial - fold_crate: @fn(&Crate, @ast_fold) -> Crate, - fold_view_item: @fn(&view_item_, @ast_fold) -> view_item_, - fold_foreign_item: @fn(@foreign_item, @ast_fold) -> @foreign_item, - fold_item: @fn(@item, @ast_fold) -> Option<@item>, - fold_struct_field: @fn(@struct_field, @ast_fold) -> @struct_field, - fold_item_underscore: @fn(&item_, @ast_fold) -> item_, - fold_type_method: @fn(&TypeMethod, @ast_fold) -> TypeMethod, - fold_method: @fn(@method, @ast_fold) -> @method, - fold_block: @fn(&Block, @ast_fold) -> Block, - fold_stmt: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span), - fold_arm: @fn(&Arm, @ast_fold) -> Arm, - fold_pat: @fn(&Pat_, Span, @ast_fold) -> (Pat_, Span), - fold_decl: @fn(&Decl_, Span, @ast_fold) -> (Option<Decl_>, Span), - fold_expr: @fn(&Expr_, Span, @ast_fold) -> (Expr_, Span), - fold_ty: @fn(&ty_, Span, @ast_fold) -> (ty_, Span), - fold_mod: @fn(&_mod, @ast_fold) -> _mod, - fold_foreign_mod: @fn(&foreign_mod, @ast_fold) -> foreign_mod, - fold_variant: @fn(&variant_, Span, @ast_fold) -> (variant_, Span), - fold_ident: @fn(Ident, @ast_fold) -> Ident, - fold_path: @fn(&Path, @ast_fold) -> Path, - fold_local: @fn(@Local, @ast_fold) -> @Local, - fold_mac: @fn(&mac_, Span, @ast_fold) -> (mac_, Span), - map_exprs: @fn(@fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr], - new_id: @fn(NodeId) -> NodeId, - new_span: @fn(Span) -> Span +/* some little folds that probably aren't useful to have in ast_fold itself*/ + +//used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive +fn fold_meta_item_<T:ast_fold>(mi: @MetaItem, fld: &T) -> @MetaItem { + @Spanned { + node: + match mi.node { + MetaWord(id) => MetaWord(id), + MetaList(id, ref mis) => { + let fold_meta_item = |x| fold_meta_item_(x, fld); + MetaList( + id, + mis.map(|e| fold_meta_item(*e)) + ) + } + MetaNameValue(id, s) => MetaNameValue(id, s) + }, + span: fld.new_span(mi.span) } } -pub type ast_fold_fns = @AstFoldFns; +//used in noop_fold_item and noop_fold_crate +fn fold_attribute_<T:ast_fold>(at: Attribute, fld: &T) -> Attribute { + Spanned { + span: fld.new_span(at.span), + node: ast::Attribute_ { + style: at.node.style, + value: fold_meta_item_(at.node.value, fld), + is_sugared_doc: at.node.is_sugared_doc + } + } +} -/* some little folds that probably aren't useful to have in ast_fold itself*/ +//used in noop_fold_foreign_item and noop_fold_fn_decl +fn fold_arg_<T:ast_fold>(a: &arg, fld: &T) -> arg { + ast::arg { + is_mutbl: a.is_mutbl, + ty: fld.fold_ty(&a.ty), + pat: fld.fold_pat(a.pat), + id: fld.new_id(a.id), + } +} -pub fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] { +// build a new vector of tts by appling the ast_fold's fold_ident to +// all of the identifiers in the token trees. +pub fn fold_tts<T:ast_fold>(tts: &[token_tree], fld: &T) -> ~[token_tree] { do tts.map |tt| { match *tt { tt_tok(span, ref tok) => tt_tok(span,maybe_fold_ident(tok,fld)), - tt_delim(ref tts) => - tt_delim(@mut fold_tts(**tts, fld)), + tt_delim(ref tts) => tt_delim(@mut fold_tts(**tts, fld)), tt_seq(span, ref pattern, ref sep, is_optional) => tt_seq(span, @mut fold_tts(**pattern, fld), @@ -247,33 +454,68 @@ pub fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] { } // apply ident folder if it's an ident, otherwise leave it alone -fn maybe_fold_ident(t : &token::Token, f: @ast_fold) -> token::Token { +fn maybe_fold_ident<T:ast_fold>(t: &token::Token, fld: &T) -> token::Token { match *t { - token::IDENT(id,followed_by_colons) => - token::IDENT(f.fold_ident(id),followed_by_colons), + token::IDENT(id, followed_by_colons) => { + token::IDENT(fld.fold_ident(id), followed_by_colons) + } _ => (*t).clone() } } -pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl { +pub fn fold_fn_decl<T:ast_fold>(decl: &ast::fn_decl, fld: &T) + -> ast::fn_decl { ast::fn_decl { - inputs: decl.inputs.map(|x| fld.fold_arg(x)), + inputs: decl.inputs.map(|x| fold_arg_(x, fld)), // bad copy output: fld.fold_ty(&decl.output), cf: decl.cf, } } -pub fn fold_generics(generics: &Generics, fld: @ast_fold) -> Generics { - Generics {ty_params: fld.fold_ty_params(&generics.ty_params), - lifetimes: fld.fold_lifetimes(&generics.lifetimes)} +fn fold_ty_param_bound<T:ast_fold>(tpb: &TyParamBound, fld: &T) + -> TyParamBound { + match *tpb { + TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)), + RegionTyParamBound => RegionTyParamBound + } } -pub fn noop_fold_crate(c: &Crate, fld: @ast_fold) -> Crate { - Crate { - module: fld.fold_mod(&c.module), - attrs: fld.fold_attributes(c.attrs), - config: fld.fold_meta_items(c.config), - span: fld.new_span(c.span), +pub fn fold_ty_param<T:ast_fold>(tp: &TyParam, fld: &T) -> TyParam { + TyParam { + ident: tp.ident, + id: fld.new_id(tp.id), + bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld)), + } +} + +pub fn fold_ty_params<T:ast_fold>(tps: &OptVec<TyParam>, fld: &T) + -> OptVec<TyParam> { + tps.map(|tp| fold_ty_param(tp, fld)) +} + +pub fn fold_lifetime<T:ast_fold>(l: &Lifetime, fld: &T) -> Lifetime { + Lifetime { + id: fld.new_id(l.id), + span: fld.new_span(l.span), + ident: l.ident + } +} + +pub fn fold_lifetimes<T:ast_fold>(lts: &OptVec<Lifetime>, fld: &T) + -> OptVec<Lifetime> { + lts.map(|l| fold_lifetime(l, fld)) +} + +pub fn fold_generics<T:ast_fold>(generics: &Generics, fld: &T) -> Generics { + Generics {ty_params: fold_ty_params(&generics.ty_params, fld), + lifetimes: fold_lifetimes(&generics.lifetimes, fld)} +} + +fn fold_struct_def<T:ast_fold>(struct_def: @ast::struct_def, fld: &T) + -> @ast::struct_def { + @ast::struct_def { + fields: struct_def.fields.map(|f| fold_struct_field(*f, fld)), + ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(*cid)), } } @@ -291,753 +533,333 @@ fn noop_fold_view_item(vi: &view_item_, fld: @ast_fold) -> view_item_ { } } -fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold) - -> @foreign_item { - @ast::foreign_item { - ident: fld.fold_ident(ni.ident), - attrs: fld.fold_attributes(ni.attrs), - node: - match ni.node { - foreign_item_fn(ref fdec, ref generics) => { - foreign_item_fn( - ast::fn_decl { - inputs: fdec.inputs.map(|a| fld.fold_arg(a)), - output: fld.fold_ty(&fdec.output), - cf: fdec.cf, - }, - fold_generics(generics, fld)) - } - foreign_item_static(ref t, m) => { - foreign_item_static(fld.fold_ty(t), m) - } - }, - id: fld.new_id(ni.id), - span: fld.new_span(ni.span), - vis: ni.vis, +fn fold_trait_ref<T:ast_fold>(p: &trait_ref, fld: &T) -> trait_ref { + ast::trait_ref { + path: fld.fold_path(&p.path), + ref_id: fld.new_id(p.ref_id), } } -pub fn noop_fold_item(i: @item, fld: @ast_fold) -> Option<@item> { - Some(@ast::item { ident: fld.fold_ident(i.ident), - attrs: fld.fold_attributes(i.attrs), - id: fld.new_id(i.id), - node: fld.fold_item_underscore(&i.node), - vis: i.vis, - span: fld.new_span(i.span) }) -} - -fn noop_fold_struct_field(sf: @struct_field, fld: @ast_fold) - -> @struct_field { +fn fold_struct_field<T:ast_fold>(f: @struct_field, fld: &T) -> @struct_field { @Spanned { node: ast::struct_field_ { - kind: sf.node.kind, - id: fld.new_id(sf.node.id), - ty: fld.fold_ty(&sf.node.ty), - attrs: fld.fold_attributes(sf.node.attrs), + kind: f.node.kind, + id: fld.new_id(f.node.id), + ty: fld.fold_ty(&f.node.ty), + attrs: f.node.attrs.map(|a| fold_attribute_(*a, fld)), }, - span: sf.span + span: fld.new_span(f.span), } } -pub fn noop_fold_type_method(m: &TypeMethod, fld: @ast_fold) -> TypeMethod { - TypeMethod { - ident: fld.fold_ident(m.ident), - attrs: fld.fold_attributes(m.attrs), - purity: m.purity, - decl: fold_fn_decl(&m.decl, fld), - generics: fold_generics(&m.generics, fld), - explicit_self: m.explicit_self, - id: fld.new_id(m.id), - span: fld.new_span(m.span), +fn fold_field_<T:ast_fold>(field: Field, folder: &T) -> Field { + ast::Field { + ident: folder.fold_ident(field.ident), + expr: folder.fold_expr(field.expr), + span: folder.new_span(field.span), } } -pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ { +fn fold_mt<T:ast_fold>(mt: &mt, folder: &T) -> mt { + mt { + ty: ~folder.fold_ty(mt.ty), + mutbl: mt.mutbl, + } +} + +fn fold_field<T:ast_fold>(f: TypeField, folder: &T) -> TypeField { + ast::TypeField { + ident: folder.fold_ident(f.ident), + mt: fold_mt(&f.mt, folder), + span: folder.new_span(f.span), + } +} + +fn fold_opt_bounds<T:ast_fold>(b: &Option<OptVec<TyParamBound>>, folder: &T) + -> Option<OptVec<TyParamBound>> { + do b.map |bounds| { + do bounds.map |bound| { + fold_ty_param_bound(bound, folder) + } + } +} + +fn fold_variant_arg_<T:ast_fold>(va: &variant_arg, folder: &T) + -> variant_arg { + ast::variant_arg { + ty: folder.fold_ty(&va.ty), + id: folder.new_id(va.id) + } +} + +pub fn noop_fold_block<T:ast_fold>(b: &Block, folder: &T) -> Block { + let view_items = b.view_items.map(|x| folder.fold_view_item(x)); + let mut stmts = ~[]; + for stmt in b.stmts.iter() { + match folder.fold_stmt(*stmt) { + None => {} + Some(stmt) => stmts.push(stmt) + } + } + ast::Block { + view_items: view_items, + stmts: stmts, + expr: b.expr.map(|x| folder.fold_expr(*x)), + id: folder.new_id(b.id), + rules: b.rules, + span: folder.new_span(b.span), + } +} + +pub fn noop_fold_item_underscore<T:ast_fold>(i: &item_, folder: &T) -> item_ { match *i { item_static(ref t, m, e) => { - item_static(fld.fold_ty(t), m, fld.fold_expr(e)) + item_static(folder.fold_ty(t), m, folder.fold_expr(e)) } item_fn(ref decl, purity, abi, ref generics, ref body) => { item_fn( - fold_fn_decl(decl, fld), + fold_fn_decl(decl, folder), purity, abi, - fold_generics(generics, fld), - fld.fold_block(body) + fold_generics(generics, folder), + folder.fold_block(body) ) } - item_mod(ref m) => { - item_mod(fld.fold_mod(m)) - } + item_mod(ref m) => item_mod(folder.fold_mod(m)), item_foreign_mod(ref nm) => { - item_foreign_mod(fld.fold_foreign_mod(nm)) + item_foreign_mod(folder.fold_foreign_mod(nm)) } item_ty(ref t, ref generics) => { - item_ty(fld.fold_ty(t), fold_generics(generics, fld)) + item_ty(folder.fold_ty(t), + fold_generics(generics, folder)) } item_enum(ref enum_definition, ref generics) => { item_enum( ast::enum_def { variants: do enum_definition.variants.map |x| { - fld.fold_variant(x) + folder.fold_variant(x) }, }, - fold_generics(generics, fld)) + fold_generics(generics, folder)) } item_struct(ref struct_def, ref generics) => { - let struct_def = fold_struct_def(*struct_def, fld); - item_struct(struct_def, fold_generics(generics, fld)) + let struct_def = fold_struct_def(*struct_def, folder); + item_struct(struct_def, fold_generics(generics, folder)) } item_impl(ref generics, ref ifce, ref ty, ref methods) => { - item_impl( - fold_generics(generics, fld), - ifce.map(|p| fld.fold_trait_ref(p)), - fld.fold_ty(ty), - methods.map(|x| fld.fold_method(*x)) + item_impl(fold_generics(generics, folder), + ifce.map(|p| fold_trait_ref(p, folder)), + folder.fold_ty(ty), + methods.map(|x| folder.fold_method(*x)) ) } item_trait(ref generics, ref traits, ref methods) => { let methods = do methods.map |method| { match *method { - required(ref m) => required(fld.fold_type_method(m)), - provided(method) => provided(fld.fold_method(method)) + required(ref m) => required(folder.fold_type_method(m)), + provided(method) => provided(folder.fold_method(method)) } }; - item_trait( - fold_generics(generics, fld), - traits.map(|p| fld.fold_trait_ref(p)), - methods - ) - } - item_mac(ref m) => { - item_mac(fld.fold_mac(m)) + item_trait(fold_generics(generics, folder), + traits.map(|p| fold_trait_ref(p, folder)), + methods) } + item_mac(ref m) => item_mac(folder.fold_mac(m)), } } -fn fold_struct_def(struct_def: @ast::struct_def, fld: @ast_fold) - -> @ast::struct_def { - @ast::struct_def { - fields: struct_def.fields.map(|f| fold_struct_field(*f, fld)), - ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(*cid)), - } -} - -fn fold_struct_field(f: @struct_field, fld: @ast_fold) -> @struct_field { - @Spanned { - node: ast::struct_field_ { - kind: f.node.kind, - id: fld.new_id(f.node.id), - ty: fld.fold_ty(&f.node.ty), - attrs: fld.fold_attributes(f.node.attrs), - }, - span: fld.new_span(f.span), - } -} - -fn noop_fold_method(m: @method, fld: @ast_fold) -> @method { - @ast::method { +pub fn noop_fold_type_method<T:ast_fold>(m: &TypeMethod, fld: &T) + -> TypeMethod { + TypeMethod { ident: fld.fold_ident(m.ident), - attrs: fld.fold_attributes(m.attrs), - generics: fold_generics(&m.generics, fld), - explicit_self: m.explicit_self, + attrs: m.attrs.map(|a| fold_attribute_(*a, fld)), purity: m.purity, decl: fold_fn_decl(&m.decl, fld), - body: fld.fold_block(&m.body), + generics: fold_generics(&m.generics, fld), + explicit_self: m.explicit_self, id: fld.new_id(m.id), span: fld.new_span(m.span), - self_id: fld.new_id(m.self_id), - vis: m.vis, - } -} - - -pub fn noop_fold_block(b: &Block, fld: @ast_fold) -> Block { - let view_items = b.view_items.map(|x| fld.fold_view_item(x)); - let mut stmts = ~[]; - for stmt in b.stmts.iter() { - match fld.fold_stmt(*stmt) { - None => {} - Some(stmt) => stmts.push(stmt) - } - } - ast::Block { - view_items: view_items, - stmts: stmts, - expr: b.expr.map(|x| fld.fold_expr(*x)), - id: fld.new_id(b.id), - rules: b.rules, - span: b.span, } } -fn noop_fold_stmt(s: &Stmt_, fld: @ast_fold) -> Option<Stmt_> { - match *s { - StmtDecl(d, nid) => { - match fld.fold_decl(d) { - Some(d) => Some(StmtDecl(d, fld.new_id(nid))), - None => None, - } - } - StmtExpr(e, nid) => { - Some(StmtExpr(fld.fold_expr(e), fld.new_id(nid))) - } - StmtSemi(e, nid) => { - Some(StmtSemi(fld.fold_expr(e), fld.new_id(nid))) - } - StmtMac(ref mac, semi) => Some(StmtMac(fld.fold_mac(mac), semi)) +pub fn noop_fold_mod<T:ast_fold>(m: &_mod, folder: &T) -> _mod { + ast::_mod { + view_items: m.view_items + .iter() + .map(|x| folder.fold_view_item(x)).collect(), + items: m.items.iter().filter_map(|x| folder.fold_item(*x)).collect(), } } -fn noop_fold_arm(a: &Arm, fld: @ast_fold) -> Arm { - Arm { - pats: a.pats.map(|x| fld.fold_pat(*x)), - guard: a.guard.map_move(|x| fld.fold_expr(x)), - body: fld.fold_block(&a.body), - } -} +pub fn noop_fold_crate<T:ast_fold>(c: &Crate, folder: &T) -> Crate { + let fold_meta_item = |x| fold_meta_item_(x, folder); + let fold_attribute = |x| fold_attribute_(x, folder); -pub fn noop_fold_pat(p: &Pat_, fld: @ast_fold) -> Pat_ { - match *p { - PatWild => PatWild, - PatIdent(binding_mode, ref pth, ref sub) => { - PatIdent( - binding_mode, - fld.fold_path(pth), - sub.map_move(|x| fld.fold_pat(x)) - ) - } - PatLit(e) => PatLit(fld.fold_expr(e)), - PatEnum(ref pth, ref pats) => { - PatEnum( - fld.fold_path(pth), - pats.map(|pats| pats.map(|x| fld.fold_pat(*x))) - ) - } - PatStruct(ref pth, ref fields, etc) => { - let pth_ = fld.fold_path(pth); - let fs = do fields.map |f| { - ast::FieldPat { - ident: f.ident, - pat: fld.fold_pat(f.pat) - } - }; - PatStruct(pth_, fs, etc) - } - PatTup(ref elts) => PatTup(elts.map(|x| fld.fold_pat(*x))), - PatBox(inner) => PatBox(fld.fold_pat(inner)), - PatUniq(inner) => PatUniq(fld.fold_pat(inner)), - PatRegion(inner) => PatRegion(fld.fold_pat(inner)), - PatRange(e1, e2) => { - PatRange(fld.fold_expr(e1), fld.fold_expr(e2)) - }, - PatVec(ref before, ref slice, ref after) => { - PatVec( - before.map(|x| fld.fold_pat(*x)), - slice.map_move(|x| fld.fold_pat(x)), - after.map(|x| fld.fold_pat(*x)) - ) - } + Crate { + module: folder.fold_mod(&c.module), + attrs: c.attrs.map(|x| fold_attribute(*x)), + config: c.config.map(|x| fold_meta_item(*x)), + span: folder.new_span(c.span), } } -fn noop_fold_decl(d: &Decl_, fld: @ast_fold) -> Option<Decl_> { - match *d { - DeclLocal(ref l) => Some(DeclLocal(fld.fold_local(*l))), - DeclItem(it) => { - match fld.fold_item(it) { - Some(it_folded) => Some(DeclItem(it_folded)), - None => None, - } - } - } -} +pub fn noop_fold_item<T:ast_fold>(i: @ast::item, folder: &T) + -> Option<@ast::item> { + let fold_attribute = |x| fold_attribute_(x, folder); -// lift a function in ast-thingy X fold -> ast-thingy to a function -// in (ast-thingy X span X fold) -> (ast-thingy X span). Basically, -// carries the span around. -// It seems strange to me that the call to new_fold doesn't happen -// here but instead in the impl down below.... probably just an -// accident? -pub fn wrap<T>(f: @fn(&T, @ast_fold) -> T) - -> @fn(&T, Span, @ast_fold) -> (T, Span) { - let result: @fn(&T, Span, @ast_fold) -> (T, Span) = |x, s, fld| { - (f(x, fld), s) - }; - result + Some(@ast::item { + ident: folder.fold_ident(i.ident), + attrs: i.attrs.map(|e| fold_attribute(*e)), + id: folder.new_id(i.id), + node: folder.fold_item_underscore(&i.node), + vis: i.vis, + span: folder.new_span(i.span) + }) } -pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ { - fn fold_field_(field: Field, fld: @ast_fold) -> Field { - ast::Field { - ident: fld.fold_ident(field.ident), - expr: fld.fold_expr(field.expr), - span: fld.new_span(field.span), - } - } - let fold_field = |x| fold_field_(x, fld); +pub fn noop_fold_expr<T:ast_fold>(e: @ast::Expr, folder: &T) -> @ast::Expr { + let fold_field = |x| fold_field_(x, folder); - match *e { + let node = match e.node { ExprVstore(e, v) => { - ExprVstore(fld.fold_expr(e), v) + ExprVstore(folder.fold_expr(e), v) } ExprVec(ref exprs, mutt) => { - ExprVec(fld.map_exprs(|x| fld.fold_expr(x), *exprs), mutt) + ExprVec(folder.map_exprs(|x| folder.fold_expr(x), *exprs), mutt) } ExprRepeat(expr, count, mutt) => { - ExprRepeat(fld.fold_expr(expr), fld.fold_expr(count), mutt) + ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count), mutt) } - ExprTup(ref elts) => ExprTup(elts.map(|x| fld.fold_expr(*x))), + ExprTup(ref elts) => ExprTup(elts.map(|x| folder.fold_expr(*x))), ExprCall(f, ref args, blk) => { - ExprCall( - fld.fold_expr(f), - fld.map_exprs(|x| fld.fold_expr(x), *args), - blk - ) + ExprCall(folder.fold_expr(f), + folder.map_exprs(|x| folder.fold_expr(x), *args), + blk) } ExprMethodCall(callee_id, f, i, ref tps, ref args, blk) => { ExprMethodCall( - fld.new_id(callee_id), - fld.fold_expr(f), - fld.fold_ident(i), - tps.map(|x| fld.fold_ty(x)), - fld.map_exprs(|x| fld.fold_expr(x), *args), + folder.new_id(callee_id), + folder.fold_expr(f), + folder.fold_ident(i), + tps.map(|x| folder.fold_ty(x)), + folder.map_exprs(|x| folder.fold_expr(x), *args), blk ) } ExprBinary(callee_id, binop, lhs, rhs) => { - ExprBinary( - fld.new_id(callee_id), - binop, - fld.fold_expr(lhs), - fld.fold_expr(rhs) - ) + ExprBinary(folder.new_id(callee_id), + binop, + folder.fold_expr(lhs), + folder.fold_expr(rhs)) } ExprUnary(callee_id, binop, ohs) => { - ExprUnary( - fld.new_id(callee_id), - binop, - fld.fold_expr(ohs) - ) + ExprUnary(folder.new_id(callee_id), binop, folder.fold_expr(ohs)) } - ExprDoBody(f) => ExprDoBody(fld.fold_expr(f)), - ExprLit(_) => (*e).clone(), + ExprDoBody(f) => ExprDoBody(folder.fold_expr(f)), + ExprLit(_) => e.node.clone(), ExprCast(expr, ref ty) => { - ExprCast(fld.fold_expr(expr), fld.fold_ty(ty)) + ExprCast(folder.fold_expr(expr), folder.fold_ty(ty)) } - ExprAddrOf(m, ohs) => ExprAddrOf(m, fld.fold_expr(ohs)), + ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)), ExprIf(cond, ref tr, fl) => { - ExprIf( - fld.fold_expr(cond), - fld.fold_block(tr), - fl.map_move(|x| fld.fold_expr(x)) - ) + ExprIf(folder.fold_expr(cond), + folder.fold_block(tr), + fl.map_move(|x| folder.fold_expr(x))) } ExprWhile(cond, ref body) => { - ExprWhile(fld.fold_expr(cond), fld.fold_block(body)) + ExprWhile(folder.fold_expr(cond), folder.fold_block(body)) } - ExprForLoop(pat, iter, ref body, opt_ident) => { - ExprForLoop(fld.fold_pat(pat), - fld.fold_expr(iter), - fld.fold_block(body), - opt_ident.map_move(|x| fld.fold_ident(x))) + ExprForLoop(pat, iter, ref body, ref maybe_ident) => { + ExprForLoop(folder.fold_pat(pat), + folder.fold_expr(iter), + folder.fold_block(body), + maybe_ident.map_move(|i| folder.fold_ident(i))) } ExprLoop(ref body, opt_ident) => { - ExprLoop( - fld.fold_block(body), - opt_ident.map_move(|x| fld.fold_ident(x)) - ) + ExprLoop(folder.fold_block(body), + opt_ident.map_move(|x| folder.fold_ident(x))) } ExprMatch(expr, ref arms) => { - ExprMatch( - fld.fold_expr(expr), - arms.map(|x| fld.fold_arm(x)) - ) + ExprMatch(folder.fold_expr(expr), + arms.map(|x| folder.fold_arm(x))) } ExprFnBlock(ref decl, ref body) => { ExprFnBlock( - fold_fn_decl(decl, fld), - fld.fold_block(body) + fold_fn_decl(decl, folder), + folder.fold_block(body) ) } - ExprBlock(ref blk) => ExprBlock(fld.fold_block(blk)), + ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk)), ExprAssign(el, er) => { - ExprAssign(fld.fold_expr(el), fld.fold_expr(er)) + ExprAssign(folder.fold_expr(el), folder.fold_expr(er)) } ExprAssignOp(callee_id, op, el, er) => { - ExprAssignOp( - fld.new_id(callee_id), - op, - fld.fold_expr(el), - fld.fold_expr(er) - ) + ExprAssignOp(folder.new_id(callee_id), + op, + folder.fold_expr(el), + folder.fold_expr(er)) } ExprField(el, id, ref tys) => { - ExprField( - fld.fold_expr(el), fld.fold_ident(id), - tys.map(|x| fld.fold_ty(x)) - ) + ExprField(folder.fold_expr(el), folder.fold_ident(id), + tys.map(|x| folder.fold_ty(x))) } ExprIndex(callee_id, el, er) => { - ExprIndex( - fld.new_id(callee_id), - fld.fold_expr(el), - fld.fold_expr(er) - ) + ExprIndex(folder.new_id(callee_id), + folder.fold_expr(el), + folder.fold_expr(er)) } - ExprPath(ref pth) => ExprPath(fld.fold_path(pth)), + ExprPath(ref pth) => ExprPath(folder.fold_path(pth)), ExprSelf => ExprSelf, - ExprBreak(ref opt_ident) => { - // FIXME #6993: add fold_name to fold.... then cut out the - // bogus Name->Ident->Name conversion. - ExprBreak(opt_ident.map_move(|x| { - // FIXME #9129: Assigning the new ident to a temporary to work around codegen bug - let newx = Ident::new(x); - fld.fold_ident(newx).name - })) - } - ExprAgain(ref opt_ident) => { - // FIXME #6993: add fold_name to fold.... - ExprAgain(opt_ident.map_move(|x| { - // FIXME #9129: Assigning the new ident to a temporary to work around codegen bug - let newx = Ident::new(x); - fld.fold_ident(newx).name - })) - } + ExprLogLevel => ExprLogLevel, + ExprBreak(opt_ident) => ExprBreak(opt_ident), + ExprAgain(opt_ident) => ExprAgain(opt_ident), ExprRet(ref e) => { - ExprRet(e.map_move(|x| fld.fold_expr(x))) + ExprRet(e.map_move(|x| folder.fold_expr(x))) } - ExprLogLevel => ExprLogLevel, ExprInlineAsm(ref a) => { ExprInlineAsm(inline_asm { - inputs: a.inputs.map(|&(c, input)| (c, fld.fold_expr(input))), - outputs: a.outputs.map(|&(c, out)| (c, fld.fold_expr(out))), + inputs: a.inputs.map(|&(c, input)| (c, folder.fold_expr(input))), + outputs: a.outputs.map(|&(c, out)| (c, folder.fold_expr(out))), .. (*a).clone() }) } - ExprMac(ref mac) => ExprMac(fld.fold_mac(mac)), + ExprMac(ref mac) => ExprMac(folder.fold_mac(mac)), ExprStruct(ref path, ref fields, maybe_expr) => { - ExprStruct( - fld.fold_path(path), - fields.map(|x| fold_field(*x)), - maybe_expr.map_move(|x| fld.fold_expr(x)) - ) + ExprStruct(folder.fold_path(path), + fields.map(|x| fold_field(*x)), + maybe_expr.map_move(|x| folder.fold_expr(x))) }, - ExprParen(ex) => ExprParen(fld.fold_expr(ex)) - } -} - -pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ { - fn fold_mt(mt: &mt, fld: @ast_fold) -> mt { - mt { - ty: ~fld.fold_ty(mt.ty), - mutbl: mt.mutbl, - } - } - fn fold_field(f: TypeField, fld: @ast_fold) -> TypeField { - ast::TypeField { - ident: fld.fold_ident(f.ident), - mt: fold_mt(&f.mt, fld), - span: fld.new_span(f.span), - } - } - fn fold_opt_bounds(b: &Option<OptVec<TyParamBound>>, fld: @ast_fold) - -> Option<OptVec<TyParamBound>> { - do b.map |bounds| { - do bounds.map |bound| { fld.fold_ty_param_bound(bound) } - } - } - match *t { - ty_nil | ty_bot | ty_infer => (*t).clone(), - ty_box(ref mt) => ty_box(fold_mt(mt, fld)), - ty_uniq(ref mt) => ty_uniq(fold_mt(mt, fld)), - ty_vec(ref mt) => ty_vec(fold_mt(mt, fld)), - ty_ptr(ref mt) => ty_ptr(fold_mt(mt, fld)), - ty_rptr(region, ref mt) => ty_rptr(region, fold_mt(mt, fld)), - ty_closure(ref f) => { - ty_closure(@TyClosure { - sigil: f.sigil, - purity: f.purity, - region: f.region, - onceness: f.onceness, - bounds: fold_opt_bounds(&f.bounds, fld), - decl: fold_fn_decl(&f.decl, fld), - lifetimes: fld.fold_lifetimes(&f.lifetimes) - }) - } - ty_bare_fn(ref f) => { - ty_bare_fn(@TyBareFn { - lifetimes: fld.fold_lifetimes(&f.lifetimes), - purity: f.purity, - abis: f.abis, - decl: fold_fn_decl(&f.decl, fld) - }) - } - ty_tup(ref tys) => ty_tup(tys.map(|ty| fld.fold_ty(ty))), - ty_path(ref path, ref bounds, id) => - ty_path(fld.fold_path(path), fold_opt_bounds(bounds, fld), fld.new_id(id)), - ty_fixed_length_vec(ref mt, e) => { - ty_fixed_length_vec( - fold_mt(mt, fld), - fld.fold_expr(e) - ) - } - ty_typeof(e) => ty_typeof(fld.fold_expr(e)), - ty_mac(ref mac) => ty_mac(fld.fold_mac(mac)) - } -} - -// ...nor do modules -pub fn noop_fold_mod(m: &_mod, fld: @ast_fold) -> _mod { - ast::_mod { - view_items: m.view_items.iter().map(|x| fld.fold_view_item(x)).collect(), - items: m.items.iter().filter_map(|x| fld.fold_item(*x)).collect(), - } -} - -fn noop_fold_foreign_mod(nm: &foreign_mod, fld: @ast_fold) -> foreign_mod { - ast::foreign_mod { - sort: nm.sort, - abis: nm.abis, - view_items: nm.view_items.iter().map(|x| fld.fold_view_item(x)).collect(), - items: nm.items.iter().map(|x| fld.fold_foreign_item(*x)).collect(), - } -} - -fn noop_fold_variant(v: &variant_, fld: @ast_fold) -> variant_ { - let kind = match v.kind { - tuple_variant_kind(ref variant_args) => { - tuple_variant_kind(variant_args.map(|x| fld.fold_variant_arg(x))) - } - struct_variant_kind(ref struct_def) => { - struct_variant_kind(@ast::struct_def { - fields: struct_def.fields.iter() - .map(|f| fld.fold_struct_field(*f)).collect(), - ctor_id: struct_def.ctor_id.map(|c| fld.new_id(*c)) - }) - } - }; - - let attrs = fld.fold_attributes(v.attrs); - - let de = match v.disr_expr { - Some(e) => Some(fld.fold_expr(e)), - None => None + ExprParen(ex) => ExprParen(folder.fold_expr(ex)) }; - ast::variant_ { - name: v.name, - attrs: attrs, - kind: kind, - id: fld.new_id(v.id), - disr_expr: de, - vis: v.vis, - } -} - -fn noop_fold_ident(i: Ident, _fld: @ast_fold) -> Ident { - i -} -fn noop_fold_path(p: &Path, fld: @ast_fold) -> Path { - ast::Path { - span: fld.new_span(p.span), - global: p.global, - segments: p.segments.map(|segment| ast::PathSegment { - identifier: fld.fold_ident(segment.identifier), - lifetime: segment.lifetime, - types: segment.types.map(|typ| fld.fold_ty(typ)), - }) + @Expr { + id: folder.new_id(e.id), + node: node, + span: folder.new_span(e.span), } } -fn noop_fold_local(l: @Local, fld: @ast_fold) -> @Local { - @Local { - is_mutbl: l.is_mutbl, - ty: fld.fold_ty(&l.ty), - pat: fld.fold_pat(l.pat), - init: l.init.map_move(|e| fld.fold_expr(e)), - id: fld.new_id(l.id), - span: fld.new_span(l.span), - } -} - -// the default macro traversal. visit the path -// using fold_path, and the tts using fold_tts, -// and the span using new_span -fn noop_fold_mac(m: &mac_, fld: @ast_fold) -> mac_ { - match *m { - mac_invoc_tt(ref p,ref tts,ctxt) => - mac_invoc_tt(fld.fold_path(p), - fold_tts(*tts,fld), - ctxt) - } -} - - -/* temporarily eta-expand because of a compiler bug with using `fn<T>` as a - value */ -fn noop_map_exprs(f: @fn(@Expr) -> @Expr, es: &[@Expr]) -> ~[@Expr] { - es.map(|x| f(*x)) -} - -fn noop_id(i: NodeId) -> NodeId { return i; } - -fn noop_span(sp: Span) -> Span { return sp; } - -pub fn default_ast_fold() -> ast_fold_fns { - @AstFoldFns { - fold_crate: noop_fold_crate, - fold_view_item: noop_fold_view_item, - fold_foreign_item: noop_fold_foreign_item, - fold_item: noop_fold_item, - fold_struct_field: noop_fold_struct_field, - fold_item_underscore: noop_fold_item_underscore, - fold_type_method: noop_fold_type_method, - fold_method: noop_fold_method, - fold_block: noop_fold_block, - fold_stmt: |x, s, fld| (noop_fold_stmt(x, fld), s), - fold_arm: noop_fold_arm, - fold_pat: wrap(noop_fold_pat), - fold_decl: |x, s, fld| (noop_fold_decl(x, fld), s), - fold_expr: wrap(noop_fold_expr), - fold_ty: wrap(noop_fold_ty), - fold_mod: noop_fold_mod, - fold_foreign_mod: noop_fold_foreign_mod, - fold_variant: wrap(noop_fold_variant), - fold_ident: noop_fold_ident, - fold_path: noop_fold_path, - fold_local: noop_fold_local, - fold_mac: wrap(noop_fold_mac), - map_exprs: noop_map_exprs, - new_id: noop_id, - new_span: noop_span, - } -} - -impl ast_fold for AstFoldFns { - /* naturally, a macro to write these would be nice */ - fn fold_crate(@self, c: &Crate) -> Crate { - (self.fold_crate)(c, self as @ast_fold) - } - fn fold_view_item(@self, x: &view_item) -> view_item { - ast::view_item { - node: (self.fold_view_item)(&x.node, self as @ast_fold), - attrs: self.fold_attributes(x.attrs), - vis: x.vis, - span: (self.new_span)(x.span), - } - } - fn fold_foreign_item(@self, x: @foreign_item) -> @foreign_item { - (self.fold_foreign_item)(x, self as @ast_fold) - } - fn fold_item(@self, i: @item) -> Option<@item> { - (self.fold_item)(i, self as @ast_fold) - } - fn fold_struct_field(@self, sf: @struct_field) -> @struct_field { - @Spanned { - node: ast::struct_field_ { - kind: sf.node.kind, - id: (self.new_id)(sf.node.id), - ty: self.fold_ty(&sf.node.ty), - attrs: self.fold_attributes(sf.node.attrs), - }, - span: (self.new_span)(sf.span), - } - } - fn fold_item_underscore(@self, i: &item_) -> item_ { - (self.fold_item_underscore)(i, self as @ast_fold) - } - fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod { - (self.fold_type_method)(m, self as @ast_fold) - } - fn fold_method(@self, x: @method) -> @method { - (self.fold_method)(x, self as @ast_fold) - } - fn fold_block(@self, x: &Block) -> Block { - (self.fold_block)(x, self as @ast_fold) - } - fn fold_stmt(@self, x: &Stmt) -> Option<@Stmt> { - let (n_opt, s) = (self.fold_stmt)(&x.node, x.span, self as @ast_fold); - match n_opt { - Some(n) => Some(@Spanned { node: n, span: (self.new_span)(s) }), - None => None, - } - } - fn fold_arm(@self, x: &Arm) -> Arm { - (self.fold_arm)(x, self as @ast_fold) - } - fn fold_pat(@self, x: @Pat) -> @Pat { - let (n, s) = (self.fold_pat)(&x.node, x.span, self as @ast_fold); - @Pat { - id: (self.new_id)(x.id), - node: n, - span: (self.new_span)(s), - } - } - fn fold_decl(@self, x: @Decl) -> Option<@Decl> { - let (n_opt, s) = (self.fold_decl)(&x.node, x.span, self as @ast_fold); - match n_opt { - Some(n) => Some(@Spanned { node: n, span: (self.new_span)(s) }), - None => None, +pub fn noop_fold_stmt<T:ast_fold>(s: &Stmt, folder: &T) -> Option<@Stmt> { + let node = match s.node { + StmtDecl(d, nid) => { + match folder.fold_decl(d) { + Some(d) => Some(StmtDecl(d, folder.new_id(nid))), + None => None, + } } - } - fn fold_expr(@self, x: @Expr) -> @Expr { - let (n, s) = (self.fold_expr)(&x.node, x.span, self as @ast_fold); - @Expr { - id: (self.new_id)(x.id), - node: n, - span: (self.new_span)(s), + StmtExpr(e, nid) => { + Some(StmtExpr(folder.fold_expr(e), folder.new_id(nid))) } - } - fn fold_ty(@self, x: &Ty) -> Ty { - let (n, s) = (self.fold_ty)(&x.node, x.span, self as @ast_fold); - Ty { - id: (self.new_id)(x.id), - node: n, - span: (self.new_span)(s), + StmtSemi(e, nid) => { + Some(StmtSemi(folder.fold_expr(e), folder.new_id(nid))) } - } - fn fold_mod(@self, x: &_mod) -> _mod { - (self.fold_mod)(x, self as @ast_fold) - } - fn fold_foreign_mod(@self, x: &foreign_mod) -> foreign_mod { - (self.fold_foreign_mod)(x, self as @ast_fold) - } - fn fold_variant(@self, x: &variant) -> variant { - let (n, s) = (self.fold_variant)(&x.node, x.span, self as @ast_fold); - Spanned { node: n, span: (self.new_span)(s) } - } - fn fold_ident(@self, x: Ident) -> Ident { - (self.fold_ident)(x, self as @ast_fold) - } - fn fold_path(@self, x: &Path) -> Path { - (self.fold_path)(x, self as @ast_fold) - } - fn fold_local(@self, x: @Local) -> @Local { - (self.fold_local)(x, self as @ast_fold) - } - fn fold_mac(@self, x: &mac) -> mac { - let (n, s) = (self.fold_mac)(&x.node, x.span, self as @ast_fold); - Spanned { node: n, span: (self.new_span)(s) } - } - fn map_exprs(@self, - f: @fn(@Expr) -> @Expr, - e: &[@Expr]) - -> ~[@Expr] { - (self.map_exprs)(f, e) - } - fn new_id(@self, node_id: ast::NodeId) -> NodeId { - (self.new_id)(node_id) - } - fn new_span(@self, span: Span) -> Span { - (self.new_span)(span) - } -} + StmtMac(ref mac, semi) => Some(StmtMac(folder.fold_mac(mac), semi)) + }; -// brson agrees with me that this function's existence is probably -// not a good or useful thing. -pub fn make_fold(afp: ast_fold_fns) -> @ast_fold { - afp as @ast_fold + node.map_move(|node| @Spanned { + node: node, + span: folder.new_span(s.span), + }) } #[cfg(test)] @@ -1048,27 +870,18 @@ mod test { use print::pprust; use super::*; - // taken from expand - // given a function from idents to idents, produce - // an ast_fold that applies that function: - pub fn fun_to_ident_folder(f: @fn(ast::Ident)->ast::Ident) -> @ast_fold{ - let afp = default_ast_fold(); - let f_pre = @AstFoldFns{ - fold_ident : |id, _| f(id), - .. *afp - }; - make_fold(f_pre) - } - // this version doesn't care about getting comments or docstrings in. fn fake_print_crate(s: @pprust::ps, crate: &ast::Crate) { pprust::print_mod(s, &crate.module, crate.attrs); } // change every identifier to "zz" - pub fn to_zz() -> @fn(ast::Ident)->ast::Ident { - let zz_id = token::str_to_ident("zz"); - |_id| {zz_id} + struct ToZzIdentFolder; + + impl ast_fold for ToZzIdentFolder { + fn fold_ident(&self, _: ast::Ident) -> ast::Ident { + token::str_to_ident("zz") + } } // maybe add to expand.rs... @@ -1088,7 +901,7 @@ mod test { // make sure idents get transformed everywhere #[test] fn ident_transformation () { - let zz_fold = fun_to_ident_folder(to_zz()); + let zz_fold = ToZzIdentFolder; let ast = string_to_crate(@"#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}"); assert_pred!(matches_codepattern, "matches_codepattern", @@ -1099,7 +912,7 @@ mod test { // even inside macro defs.... #[test] fn ident_transformation_in_defs () { - let zz_fold = fun_to_ident_folder(to_zz()); + let zz_fold = ToZzIdentFolder; let ast = string_to_crate(@"macro_rules! a {(b $c:expr $(d $e:token)f+ => (g $(d $d $e)+))} "); assert_pred!(matches_codepattern, @@ -1108,15 +921,5 @@ mod test { token::get_ident_interner()), ~"zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))"); } - - // and in cast expressions... this appears to be an existing bug. - #[test] fn ident_transformation_in_types () { - let zz_fold = fun_to_ident_folder(to_zz()); - let ast = string_to_crate(@"fn a() {let z = 13 as int;}"); - assert_pred!(matches_codepattern, - "matches_codepattern", - pprust::to_str(&zz_fold.fold_crate(ast),fake_print_crate, - token::get_ident_interner()), - ~"fn zz(){let zz=13 as zz;}"); - } } + diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 9645dab4e8b..91ef55c78f6 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -45,7 +45,7 @@ pub struct ParseSess { included_mod_stack: ~[Path], } -pub fn new_parse_sess(demitter: Option<Emitter>) -> @mut ParseSess { +pub fn new_parse_sess(demitter: Option<@Emitter>) -> @mut ParseSess { let cm = @CodeMap::new(); @mut ParseSess { cm: cm, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b5868cbc63d..867e4fe416b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -37,16 +37,26 @@ pub enum ann_node<'self> { node_expr(@ps, &'self ast::Expr), node_pat(@ps, &'self ast::Pat), } -pub struct pp_ann { - pre: @fn(ann_node), - post: @fn(ann_node) + +pub trait pp_ann { + fn pre(&self, _node: ann_node) {} + fn post(&self, _node: ann_node) {} +} + +pub struct no_ann { + contents: (), } -pub fn no_ann() -> pp_ann { - fn ignore(_node: ann_node) { } - return pp_ann {pre: ignore, post: ignore}; +impl no_ann { + pub fn new() -> no_ann { + no_ann { + contents: (), + } + } } +impl pp_ann for no_ann {} + pub struct CurrentCommentAndLiteral { cur_cmnt: uint, cur_lit: uint, @@ -60,7 +70,7 @@ pub struct ps { literals: Option<~[comments::lit]>, cur_cmnt_and_lit: @mut CurrentCommentAndLiteral, boxes: @mut ~[pp::breaks], - ann: pp_ann + ann: @pp_ann } pub fn ibox(s: @ps, u: uint) { @@ -74,12 +84,13 @@ pub fn end(s: @ps) { } pub fn rust_printer(writer: @io::Writer, intr: @ident_interner) -> @ps { - return rust_printer_annotated(writer, intr, no_ann()); + return rust_printer_annotated(writer, intr, @no_ann::new() as @pp_ann); } pub fn rust_printer_annotated(writer: @io::Writer, intr: @ident_interner, - ann: pp_ann) -> @ps { + ann: @pp_ann) + -> @ps { return @ps { s: pp::mk_printer(writer, default_columns), cm: None::<@CodeMap>, @@ -109,7 +120,7 @@ pub fn print_crate(cm: @CodeMap, filename: @str, input: @io::Reader, out: @io::Writer, - ann: pp_ann, + ann: @pp_ann, is_expanded: bool) { let (cmnts, lits) = comments::gather_comments_and_literals( span_diagnostic, @@ -484,7 +495,7 @@ pub fn print_item(s: @ps, item: &ast::item) { maybe_print_comment(s, item.span.lo); print_outer_attributes(s, item.attrs); let ann_node = node_item(s, item); - (s.ann.pre)(ann_node); + s.ann.pre(ann_node); match item.node { ast::item_static(ref ty, m, expr) => { head(s, visibility_qualified(item.vis, "static")); @@ -635,7 +646,7 @@ pub fn print_item(s: @ps, item: &ast::item) { end(s); } } - (s.ann.post)(ann_node); + s.ann.post(ann_node); } fn print_trait_ref(s: @ps, t: &ast::trait_ref) { @@ -958,7 +969,7 @@ pub fn print_possibly_embedded_block_(s: @ps, } maybe_print_comment(s, blk.span.lo); let ann_node = node_block(s, blk); - (s.ann.pre)(ann_node); + s.ann.pre(ann_node); match embedded { block_block_fn => end(s), block_normal => bopen(s) @@ -979,7 +990,7 @@ pub fn print_possibly_embedded_block_(s: @ps, _ => () } bclose_maybe_open(s, blk.span, indented, close_box); - (s.ann.post)(ann_node); + s.ann.post(ann_node); } pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block, @@ -1121,7 +1132,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) { maybe_print_comment(s, expr.span.lo); ibox(s, indent_unit); let ann_node = node_expr(s, expr); - (s.ann.pre)(ann_node); + s.ann.pre(ann_node); match expr.node { ast::ExprVstore(e, v) => { print_expr_vstore(s, v); @@ -1456,7 +1467,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) { pclose(s); } } - (s.ann.post)(ann_node); + s.ann.post(ann_node); end(s); } @@ -1578,7 +1589,7 @@ pub fn print_bounded_path(s: @ps, path: &ast::Path, pub fn print_pat(s: @ps, pat: &ast::Pat) { maybe_print_comment(s, pat.span.lo); let ann_node = node_pat(s, pat); - (s.ann.pre)(ann_node); + s.ann.pre(ann_node); /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.node { @@ -1678,7 +1689,7 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) { word(s.s, "]"); } } - (s.ann.post)(ann_node); + s.ann.post(ann_node); } pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_interner) -> ~str { @@ -2254,17 +2265,6 @@ pub fn print_fn_header_info(s: @ps, print_opt_sigil(s, opt_sigil); } -pub fn opt_sigil_to_str(opt_p: Option<ast::Sigil>) -> &'static str { - match opt_p { - None => "fn", - Some(p) => match p { - ast::BorrowedSigil => "fn&", - ast::OwnedSigil => "fn~", - ast::ManagedSigil => "fn@" - } - } -} - pub fn purity_to_str(p: ast::purity) -> &'static str { match p { ast::impure_fn => "impure", |
